Browse Source

build: check patches on update (#23103)

Shelley Vohr 4 years ago
parent
commit
9d960e29eb
4 changed files with 56 additions and 15 deletions
  1. 2 1
      package.json
  2. 18 0
      script/check-patch-diff.js
  3. 7 3
      script/export_all_patches.py
  4. 29 11
      script/lib/git.py

+ 2 - 1
package.json

@@ -134,7 +134,8 @@
       "git add filenames.auto.gni"
     ],
     "{*.patch,.patches}": [
-      "node script/lint.js --patches --only --"
+      "node script/lint.js --patches --only --",
+      "node script/check-patch-diff.js"
     ],
     "DEPS": [
       "node script/gen-hunspell-filenames.js"

+ 18 - 0
script/check-patch-diff.js

@@ -0,0 +1,18 @@
+const { spawnSync } = require('child_process');
+const path = require('path');
+const { inspect } = require('util');
+
+const srcPath = path.resolve(__dirname, '..', '..', '..');
+const patchExportFnPath = path.resolve(__dirname, 'export_all_patches.py');
+const configPath = path.resolve(__dirname, '..', 'patches', 'config.json');
+
+// Re-export all the patches to check if there were changes.
+const proc = spawnSync('python', [patchExportFnPath, configPath, '--dry-run'], {
+  cwd: srcPath
+});
+
+// Fail if patch exporting returned 1, e.g dry run failed.
+if (proc.status === 1) {
+  console.log(proc.stderr.toString('utf8'));
+  process.exit(1);
+}

+ 7 - 3
script/export_all_patches.py

@@ -8,9 +8,9 @@ import sys
 from lib import git
 
 
-def export_patches(dirs):
+def export_patches(dirs, dry_run):
   for patch_dir, repo in dirs.iteritems():
-    git.export_patches(repo=repo, out_dir=patch_dir)
+    git.export_patches(repo=repo, out_dir=patch_dir, dry_run=dry_run)
 
 
 def parse_args():
@@ -18,13 +18,17 @@ def parse_args():
   parser.add_argument('config', nargs='+',
                       type=argparse.FileType('r'),
                       help='patches\' config(s) in the JSON format')
+  parser.add_argument("-d", "--dry-run",
+    help="Checks whether the exported patches need to be updated.",
+    default=False, action='store_true')
   return parser.parse_args()
 
 
 def main():
   configs = parse_args().config
+  dry_run = parse_args().dry_run
   for config_json in configs:
-    export_patches(json.load(config_json))
+    export_patches(json.load(config_json), dry_run)
 
 
 if __name__ == '__main__':

+ 29 - 11
script/lib/git.py

@@ -260,7 +260,7 @@ def remove_patch_filename(patch):
     force_keep_next_line = l.startswith('Subject: ')
 
 
-def export_patches(repo, out_dir, patch_range=None):
+def export_patches(repo, out_dir, patch_range=None, dry_run=False):
   if patch_range is None:
     patch_range, num_patches = guess_base_commit(repo)
     sys.stderr.write("Exporting {} patches since {}\n".format(num_patches, patch_range))
@@ -272,15 +272,33 @@ def export_patches(repo, out_dir, patch_range=None):
   except OSError:
     pass
 
-  # remove old patches, so that deleted commits are correctly reflected in the
-  # patch files (as a removed file)
-  for p in os.listdir(out_dir):
-    if p.endswith('.patch'):
-      os.remove(os.path.join(out_dir, p))
-
-  with open(os.path.join(out_dir, '.patches'), 'w') as pl:
+  if dry_run:
+    # If we're doing a dry run, iterate through each patch and see if the newly
+    # exported patch differs from what exists. Report number of mismatched patches
+    # and fail if there's more than one.
+    patch_count = 0
     for patch in patches:
       filename = get_file_name(patch)
-      with open(os.path.join(out_dir, filename), 'w') as f:
-        f.write('\n'.join(remove_patch_filename(patch)).rstrip('\n') + '\n')
-      pl.write(filename + '\n')
+      filepath = os.path.join(out_dir, filename)
+      existing_patch = open(filepath, 'r').read()
+      formatted_patch = '\n'.join(remove_patch_filename(patch)).rstrip('\n') + '\n'
+      if formatted_patch != existing_patch:
+        patch_count += 1
+    if patch_count > 0:
+      sys.stderr.write("Patches not up to date: {} patches need update\n".format(patch_count))
+      exit(1)
+  else:
+    # Remove old patches so that deleted commits are correctly reflected in the
+    # patch files (as a removed file)
+    for p in os.listdir(out_dir):
+      if p.endswith('.patch'):
+        os.remove(os.path.join(out_dir, p))
+    with open(os.path.join(out_dir, '.patches'), 'w') as pl:
+      for patch in patches:
+        filename = get_file_name(patch)
+        file_path = os.path.join(out_dir, filename)
+        formatted_patch = '\n'.join(remove_patch_filename(patch)).rstrip('\n') + '\n'
+        with open(file_path, 'w') as f:
+          f.write(formatted_patch)
+        pl.write(filename + '\n')
+