diff --git a/tools/file_util.py b/tools/file_util.py index 12e12db09..edc382ba2 100644 --- a/tools/file_util.py +++ b/tools/file_util.py @@ -52,7 +52,7 @@ def backup_file(name): def copy_file(src, dst, quiet=True): """ Copy a file. """ try: - shutil.copy(src, dst) + shutil.copy2(src, dst) if not quiet: sys.stdout.write('Transferring ' + src + ' file.\n') except IOError, (errno, strerror): diff --git a/tools/patch_updater.py b/tools/patch_updater.py index 0f2efea79..e353ab40b 100644 --- a/tools/patch_updater.py +++ b/tools/patch_updater.py @@ -7,19 +7,27 @@ import os import re import sys from exec_util import exec_cmd +from file_util import copy_file, move_file, read_file, remove_file import git_util as git +backup_ext = '.cefbak' + def msg(message): """ Output a message. """ sys.stdout.write('--> ' + message + "\n") +def linebreak(): + """ Output a line break. """ + sys.stdout.write('-' * 80 + "\n") + + def warn(message): """ Output a warning. """ - sys.stdout.write('-' * 80 + "\n") + linebreak() sys.stdout.write('!!!! WARNING: ' + message + "\n") - sys.stdout.write('-' * 80 + "\n") + linebreak() def extract_paths(file): @@ -67,7 +75,7 @@ parser.add_option( action='store_true', dest='resave', default=False, - help='re-save existing patch files to pick up manual changes') + help='resave existing patch files to pick up manual changes') parser.add_option( '--reapply', action='store_true', @@ -80,6 +88,19 @@ parser.add_option( dest='revert', default=False, help='revert all changes from existing patch files') +parser.add_option( + '--backup', + action='store_true', + dest='backup', + default=False, + help='backup patched files. Used in combination with --revert.') +parser.add_option( + '--restore', + action='store_true', + dest='restore', + default=False, + help='restore backup of patched files that have not changed. If a backup has ' +\ + 'changed the patch file will be resaved. Used in combination with --reapply.') parser.add_option( '--patch', action='extend', @@ -113,6 +134,8 @@ scope = {} execfile(patch_cfg, scope) patches = scope["patches"] +failed_patches = {} + # Read each individual patch file. patches_dir = os.path.join(patch_dir, 'patches') for patch in patches: @@ -136,6 +159,9 @@ for patch in patches: # List of paths added by the patch file. added_paths = [] + # True if any backed up files have changed. + has_backup_changes = False + if not options.resave: if not options.reapply: # Revert any changes to existing files in the patch. @@ -143,6 +169,14 @@ for patch in patches: patch_path_abs = os.path.abspath(os.path.join(patch_root_abs, \ patch_path)) if os.path.exists(patch_path_abs): + if options.backup: + backup_path_abs = patch_path_abs + backup_ext + if not os.path.exists(backup_path_abs): + msg('Creating backup of %s' % patch_path_abs) + copy_file(patch_path_abs, backup_path_abs) + else: + msg('Skipping backup of %s' % patch_path_abs) + msg('Reverting changes to %s' % patch_path_abs) cmd = 'git checkout -- %s' % (patch_path_abs) result = exec_cmd(cmd, patch_root_abs) @@ -196,11 +230,34 @@ for patch in patches: raise Exception('Failed to apply patch file: %s' % result['err']) sys.stdout.write(result['out']) if result['out'].find('FAILED') != -1: + failed_lines = [] + for line in result['out'].split('\n'): + if line.find('FAILED') != -1: + failed_lines.append(line.strip()) warn('Failed to apply %s, fix manually and run with --resave' % \ patch['name']) + failed_patches[patch['name']] = failed_lines continue - if not options.revert and not options.reapply: + if options.restore: + # Restore from backup if a backup exists. + for patch_path in patch_paths: + patch_path_abs = os.path.abspath(os.path.join(patch_root_abs, \ + patch_path)) + backup_path_abs = patch_path_abs + backup_ext + if os.path.exists(backup_path_abs): + if read_file(patch_path_abs) == read_file(backup_path_abs): + msg('Restoring backup of %s' % patch_path_abs) + remove_file(patch_path_abs) + move_file(backup_path_abs, patch_path_abs) + else: + msg('Discarding backup of %s' % patch_path_abs) + remove_file(backup_path_abs) + has_backup_changes = True + else: + msg('No backup of %s' % patch_path_abs) + + if (not options.revert and not options.reapply) or has_backup_changes: msg('Saving changes to %s' % patch_file) if added_paths: # Inform git of the added paths so they appear in the patch file. @@ -228,3 +285,14 @@ for patch in patches: f.close() else: raise Exception('Patch file does not exist: %s' % patch_file) + +if len(failed_patches) > 0: + sys.stdout.write("\n") + linebreak() + sys.stdout.write("!!!! FAILED PATCHES, fix manually and run with --resave\n") + for name in sorted(failed_patches.keys()): + sys.stdout.write("%s:\n" % name) + for line in failed_patches[name]: + sys.stdout.write(" %s\n" % line) + linebreak() + sys.exit(1)