diff options
Diffstat (limited to 'bin/common/srtool_patcher.py')
-rwxr-xr-x | bin/common/srtool_patcher.py | 190 |
1 files changed, 154 insertions, 36 deletions
diff --git a/bin/common/srtool_patcher.py b/bin/common/srtool_patcher.py index ccf93060..bda941fc 100755 --- a/bin/common/srtool_patcher.py +++ b/bin/common/srtool_patcher.py @@ -59,12 +59,17 @@ import json # Setup: verbose = False +INPLACE_TAG = 'INPLACE' +DISABLE_TAG = 'DISABLE' ################################# # extract_custom_patch # +# Extract a clean version of the file without the the custom sections, +# and generate a patch file of those sections +# -def extract_custom_patch(custom_file,clean_file,patch_file,label,patcher_dir): +def extract_custom_patch(custom_file,clean_file,patch_file,label,patcher_dir,options): tag_begin = "%s_EXTENSION_BEGIN" % label tag_end = "%s_EXTENSION_END" % label ret = 0 @@ -108,18 +113,32 @@ def extract_custom_patch(custom_file,clean_file,patch_file,label,patcher_dir): # Did we end cleanly? if state != "find": print("ERROR: START not STOPPED (%s)" % state) - os.system("diff -u %s %s > %s" % (clean_file,custom_file,patch_file)) - print("Custom File: %s" % (custom_file)) - print("Clean File: %s" % (clean_file)) - print("Patch File: %s" % (patch_file)) + if INPLACE_TAG in options: + cmd = "git diff %s > %s" % (custom_file,patch_file) + print(cmd) + os.system(cmd) + print("In-place File: %s" % (clean_file)) + else: + os.system("diff -u %s %s > %s" % (clean_file,custom_file,patch_file)) + print("Custom File: %s" % (custom_file)) + print("Clean File: %s" % (clean_file)) + print("Patch File: %s" % (patch_file)) return(ret,clean_file,patch_file) ################################# # merge_original # +# Merge any changes in the original upstream file into the +# custom file and reapply the custom patches, so that general upstream +# changes be be included in the local custom file +# + +def merge_original(custom_file,original_file,patch_file,label,patcher_dir,options): + # Skip if in-place + if INPLACE_TAG in options: + return 0 -def merge_original(custom_file,original_file,patch_file,label,patcher_dir): - ret,clean_file,patch_file = extract_custom_patch(custom_file,'',patch_file,label,patcher_dir) + ret,clean_file,patch_file = extract_custom_patch(custom_file,'',patch_file,label,patcher_dir,options) custom_saved = os.path.join(os.path.dirname(patch_file),os.path.basename(custom_file) + '.saved') if 0 == ret: print("* Preserving custom file as '%s'" % custom_saved) @@ -143,9 +162,16 @@ def merge_original(custom_file,original_file,patch_file,label,patcher_dir): ################################# # merge_custom # +# Merge any changes in the normal non-custom sections of the custom file back into +# original file, so that general fixes can be shared upstream +# + +def merge_custom(custom_file,original_file,patch_file,label,patcher_dir,options): + # Skip if in-place + if INPLACE_TAG in options: + return 0 -def merge_custom(custom_file,original_file,patch_file,label,patcher_dir): - ret,clean_file,patch_file = extract_custom_patch(custom_file,'',patch_file,label,patcher_dir) + ret,clean_file,patch_file = extract_custom_patch(custom_file,'',patch_file,label,patcher_dir,options) if 0 == ret: print("== Copying clean version of custom file to '%s' ===" % original_file) cmd = "cp -f %s %s" % (clean_file, original_file) @@ -156,14 +182,102 @@ def merge_custom(custom_file,original_file,patch_file,label,patcher_dir): ################################# # diff_original # +# Show how the general sections of the custom file compare to the +# original file, so that the user can (a) see might be shared upstream, +# and/or (b) insure the custom sections are correct and complete +# -def diff_original(custom_file,original_file,patch_file,label,patcher_dir): - ret,clean_file,patch_file = extract_custom_patch(custom_file,'',patch_file,label,patcher_dir) +def diff_original(custom_file,original_file,patch_file,label,patcher_dir,options): + # Skip if in-place + if INPLACE_TAG in options: + return 0 + + ret,clean_file,patch_file = extract_custom_patch(custom_file,'',patch_file,label,patcher_dir,options) if 0 == ret: print("== DIFF from '%s' to clean version of custom file ===" % original_file) os.system("diff -u %s %s" % (original_file,clean_file)) return(ret) + +################################# +# clean_inplace +# +# Stash the customized general file and replace it with a clean version +# without the custom sections, so that general fixes can be shared upstream +# + +def clean_inplace(custom_file,original_file,patch_file,label,patcher_dir,options): + print("FOO1:%s,%s" % (INPLACE_TAG,options)) + # Skip if not in-place + if not INPLACE_TAG in options: + return 0 + + print("FOO2") + # Only continue if 'original' file has custom patches, in case this + # command is run multiple times by accident + cmd = "grep %s %s" % (label,original_file) + ret = os.system(cmd) + if 0 != ret: + print("ERROR:SKIP: original file '%s' does not have custom tags '%s'" % (original_file,label)) + return ret + + print("* Backup customized in-place file") + try: + os.makedirs(os.path.dirname(custom_file)) + except: + pass + cmd = "cp --force %s %s" % (original_file,custom_file) + print(cmd) + os.system(cmd) + + print("* Extract patch file (via 'git diff')") + clean_file = custom_file + '.clean' + patch_file = custom_file + '.patch' + ret,clean_file,patch_file = extract_custom_patch(original_file,clean_file,patch_file,label,'',options) + if 0 != ret: + return(ret) + + print("* Copy cleaned version back to in-place location") + cmd = "cp --force %s %s" % (clean_file,original_file) + print(cmd) + ret = os.system(cmd) + return(ret) + +################################# +# patch_inplace +# +# Re-apply the custom patches on top of the general file, so that general fixes can be adopted +# from upstream together with the customized patches applied on top +# + +def patch_inplace(custom_file,original_file,patch_file,label,patcher_dir,options): + # Skip if not in-place + if not INPLACE_TAG in options: + return 0 + + ret = 0 + patch_file = custom_file + '.patch' + if not os.path.isfile(patch_file): + # No patch file found, do a simple copy-over of custom file + if not os.path.isfile(custom_file): + print("ERROR:SKIP: neither the patch file '%s' nor the custom file '%s' can be found" % (patch_file,custom_file)) + return 1 + print("* No patch file found, copying custom file over in-place file") + cmd = "cp -f %s %s" % (custom_file,original_file) + print(cmd) + ret = os.system(cmd) + else: + print("* Patching the in-place file with custom patch") + cmd = "patch %s %s" % (original_file,patch_file) + print(cmd) + ret = os.system(cmd) + if 0 != ret: + print("* ERROR: Merge failed, restoring previous custom file") + cmd = "cp %s %s" % (custom_saved,custom_file) + print(cmd) + os.system(cmd) + return(ret) + ################################# # load_json_list # @@ -182,7 +296,7 @@ def load_json_list(json_file): patcher_dir = dct['patcher_dir'] if 'patch_set' in dct: for patch in dct['patch_set']: - if 'DISABLE' in patch['options']: + if DISABLE_TAG in patch['options']: continue file_list.append([patch['custom'],patch['original'],patch['patch'],patch['options']]) return file_list,patcher_dir,label @@ -197,13 +311,17 @@ def main(argv): # setup parser = argparse.ArgumentParser(description='srtool_sanity_test.py: SRTool common sanity tests') - parser.add_argument('--merge-original', '-O', action='store_const', const='merge_original', dest='command', help='Copy the (updated) original file, merge the custom patches') - parser.add_argument('--merge-custom', '-C', action='store_const', const='merge_custom', dest='command', help='Copy the (updated) file to the original, without custom patches') + parser.add_argument('--merge-original', '-o', action='store_const', const='merge_original', dest='command', help='Copy the (updated) original file, merge the custom patches') + parser.add_argument('--merge-custom', '-c', action='store_const', const='merge_custom', dest='command', help='Copy the (updated) file to the original, without custom patches') - parser.add_argument('--custom', '-c', help='Custom file') - parser.add_argument('--original', '-o', help='Original file') - parser.add_argument('--label', '-l', help='Custom label tag (default="CUSTOM")') - parser.add_argument('--json', '-j', help='Use JSON file for file list') + parser.add_argument('--clean-inplace', '-i', action='store_const', const='clean_inplace', dest='command', help='Stash the customized file, leaving the clean mainline version inline') + parser.add_argument('--patch-inplace', '-I', action='store_const', const='patch_inplace', dest='command', help='Restore the customized file in place of the mainline version inline') + + parser.add_argument('--json', '-J', help='Use JSON file for file list') + parser.add_argument('--custom', '-C', help='Custom file') + parser.add_argument('--original', '-O', help='Original file') + parser.add_argument('--label', '-L', help='Custom label tag (default="CUSTOM")') + parser.add_argument('--options', '-P', help='Options, for example "INPLACE", "DISABLE"') parser.add_argument('--extract-custom-patch', '-e', action='store_const', const='extract_custom_patch', dest='command', help='Extract a patch of the custom content') parser.add_argument('--patch', '-p', help='Patch file') @@ -224,40 +342,40 @@ def main(argv): validate_file(args.json,"JSON") file_list,patcher_dir,label = load_json_list(args.json) else: - custom_file = '' - if args.custom: - custom_file = args.custom - original_file = '' - if args.original: - original_file = args.original - patch_file = '' - if args.patch: - patch_file = args.patch - options = '' + original_file = args.original if args.original else '' + custom_file = args.custom if args.custom else '' + patch_file = args.patch if args.patch else '' + label = args.label if args.label else 'CUSTOM' + options = args.options if args.options else '' file_list.append([custom_file,original_file,patch_file,options]) - label = 'CUSTOM' - if args.label: - label = args.label patcher_dir = os.path.join(os.path.dirname(custom_file),'patcher') ret = 0 for custom_file,original_file,patch_file,options in file_list: - #print("PATCH_FILE:%s,%s,%s,%s,%s" % (custom_file,original_file,patch_file,options,patcher_dir)) + #print("PATCH_FILE:%s,%s,%s,%s,%s,%s" % (custom_file,original_file,patch_file,options,patcher_dir,options)) if 'merge_original' == args.command: validate_file(custom_file,'Custom') validate_file(original_file,'Original') - ret = merge_original(custom_file,original_file,patch_file,label,patcher_dir) + ret = merge_original(custom_file,original_file,patch_file,label,patcher_dir,options) elif 'merge_custom' == args.command: validate_file(custom_file,'Custom') validate_file(original_file,'Original') - ret = merge_custom(custom_file,original_file,patch_file,label,patcher_dir) + ret = merge_custom(custom_file,original_file,patch_file,label,patcher_dir,options) + elif 'clean_inplace' == args.command: + validate_file(custom_file,'Custom') + validate_file(original_file,'Original') + ret = clean_inplace(custom_file,original_file,patch_file,label,patcher_dir,options) + elif 'patch_inplace' == args.command: + validate_file(custom_file,'Custom') + validate_file(original_file,'Original') + ret = patch_inplace(custom_file,original_file,patch_file,label,patcher_dir,options) elif 'extract_custom_patch' == args.command: validate_file(custom_file,'Custom') - ret,clean_file,patch_file = extract_custom_patch(custom_file,'',patch_file,label,patcher_dir) + ret,clean_file,patch_file = extract_custom_patch(custom_file,'',patch_file,label,patcher_dir,options) elif 'diff_original' == args.command: validate_file(custom_file,'Custom') validate_file(original_file,'Original') - ret = diff_original(custom_file,original_file,patch_file,label,patcher_dir) + ret = diff_original(custom_file,original_file,patch_file,label,patcher_dir,options) else: print("Command not found '%s'" % args.command) ret = 1 |