本文主要是介绍repo的patch转换成git am能打的patch,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
安卓sdk项目小的几十G,大的上百G,有的人会把sdk分成许多个小的git然后统一用repo来管理,还有的人会选择把sdk放在一个git中管理. 那么repo中修改后生成的patch是无法直接给git用的,因为路径不一样,patch内容也不相符
比如repo中device子目录是一个git,那么它生成的patch放到另一个git项目中只能cd到device路径,然后再用patch指令打,无法用git am xx.patch来打. 两边同步代码会很麻烦.
需要用脚本进行一个转换.
repo生成manifest快照
repo比如要生成0801到0805之间的修改的patch
8月1号用如下指令生成快照
./repo sync
./repo manifest -r -o manifest_0801.xml
中间做过修改.
8月5号再生成快照
./repo sync
./repo manifest -r -o manifest_0805.xml
得有两个快照, 才能生成这两个快照之间的diff提交.
生成快照后,接下来用脚本来生成两个快照间的修改的patch
生成repo快照间的提交的patch并转换成git am的patch
# 作者帅得不敢出门
# -*- coding: utf-8 -*-import sys
import os
import re
import subprocessdef do_popen(cmd):#popenprocess = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)stdout, stderr = process.communicate()return stdout.decode('utf-8')def auto_detect_manifests():"""遍历repo项目根目录,找到两个快照,快照以.xml结尾"""manifests = []for item in os.listdir('./'):if item.startswith('manifest') and item.endswith('.xml'):manifests.append(item)if len(manifests) != 2:print('Error:the number of manifest_xx.xml files are not equal to 2, abort!')sys.exit(1)manifests.sort()print(manifests)return manifestsdef get_diffmanifests():"""查看两个repo快照间的差异, 得到类似如下changed projects :bootable/bootloader/lk changed from e5f360f35a6d3848475ba4920f40c1609b1348b0 to ca0100b2da6ca7831348cb5fcfe8d23c529e8a57[+] ca0100b2 edit 1device/sprd/sepolicy changed from f15d0189283f767bd315f0900a59256323c071c2 to 64c586a362cb19a290280e79b2e20e8aab7d94cc[+] 64c586a hellokernel/msm-3.18 changed from f36f37a42a94fe78d5d7cbe2e8a4ab6477de74ab to 6b372c76fc0874d19822d978ad557a4aeec0ebee[+] 6b372c76fc08 word"""manifests = auto_detect_manifests()cmd = './repo diffmanifests ' + manifests[0] + ' ' + manifests[1]print(cmd)return do_popen(cmd)def get_diff_git_log():"""得到两个repo快照间的git修改的log[{'path': 'bootable/bootloader/lk', 'from': 'e5f360f35a6d3848475ba4920f40c1609b1348b0', 'to': 'ca0100b2da6ca7831348cb5fcfe8d23c529e8a57'}, {'path': 'device/sprd/sepolicy', 'from': 'f15d0189283f767bd315f0900a59256323c071c2', 'to': '64c586a362cb19a290280e79b2e20e8aab7d94cc'}, {'path': 'kernel/msm-3.18', 'from': 'f36f37a42a94fe78d5d7cbe2e8a4ab6477de74ab', 'to': '6b372c76fc0874d19822d978ad557a4aeec0ebee'}]"""data = get_diffmanifests()print(data)# 只保留\t开头的有效行line = [ x for x in data.split('\n') if x.startswith('\t')]ret = []for i in range(len(line)):if i % 2 == 0:#print(line[i])log = line[i].split()ret.append({'path':log[0], 'from':log[3], 'to':log[5]})#print(ret)return retdef get_format_patch(log, outdir):try:do_popen('rm ./*.patch ')except Exception as e:print('')# 生成从from开始的提交的git patch,生成的git是在子目录中生成的,所以需要在patch内容中的文件路径添加父目录do_popen('git format-patch ' + log['from'])for file in os.listdir('./'):if file.endswith('.patch'):print(file)with open(file, 'r') as fp:new_lines = []lines = fp.readlines()fp.close()for line in lines:#查找文件路径,并在前面拼接上目录, 把repo补丁转换成可以直接在git上打的patchif line.startswith('diff --git') or line.startswith('--- ') or line.startswith('+++ '):#print(line)new_line = re.sub(' a/', ' a/' + log['path'] + '/', line)new_line = re.sub(' b/', ' b/' + log['path'] + '/', new_line)#print(new_line)new_lines.append(new_line)else:new_lines.append(line)patch_name = os.path.join(outdir, file)with open(patch_name, 'w') as new_fp:print(patch_name)new_fp.writelines(new_lines)new_fp.close()try:do_popen('rm ./*.patch ')except Exception as e:print('')if __name__ == '__main__':"""通过repo获取到两个时间段的提交git log, 再通过git log获取patch"""# 生成的patch放在当前目录的patchs中patch_dir = os.path.join(os.getcwd(), 'patchs')if not os.path.exists(patch_dir):os.mkdir(patch_dir)else:try:# 先删除旧的patchdo_popen('rm ' + patch_dir + './*.patch ')except Exception as e:print('')#得到两个repo快照间的git修改的loglogs = get_diff_git_log()for log in logs:# 遍历git log进入到实际的子git目录中生成patchold_dir = os.getcwd()os.chdir(log['path'])print(log['path'])# 把所有的子git中的修改制作成patch放到patchs目录下get_format_patch(log, patch_dir)os.chdir(old_dir)
作者:帅得不敢出门 csdn原创谢绝转载
这篇关于repo的patch转换成git am能打的patch的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!