tools/update-distro-hash: add a helper script to sync submodule
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 4 Jun 2024 13:10:15 +0000 (15:10 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 6 Jun 2024 08:02:23 +0000 (10:02 +0200)
tools/update-distro-hash.py [new file with mode: 0755]

diff --git a/tools/update-distro-hash.py b/tools/update-distro-hash.py
new file mode 100755 (executable)
index 0000000..16ed2e7
--- /dev/null
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+"""
+Fetch commits for pkg/{distribution} and, if changed, commit the latest hash.
+"""
+
+import argparse
+import json
+import shlex
+import subprocess
+from pathlib import Path
+
+def parse_args():
+    p = argparse.ArgumentParser(
+        description=__doc__,
+    )
+    p.add_argument(
+        'distribution',
+        nargs='+',
+    )
+    p.add_argument(
+        '--no-fetch',
+        dest='fetch',
+        action='store_false',
+        default=True,
+    )
+    return p.parse_args()
+
+def read_config(distro: str):
+    cmd = ['mkosi', '--json', '-d', distro, 'summary']
+    print(f"+ {shlex.join(cmd)}")
+    text = subprocess.check_output(cmd, text=True)
+
+    data = json.loads(text)
+    return data['Images'][-1]
+
+def commit_file(distro: str, file: Path, commit: str, changes: str):
+    message = '\n'.join((
+        f'mkosi: update {distro} commit reference',
+        '',
+        changes))
+
+    cmd = ['git', 'commit', '-m', message, str(file)]
+    print(f"+ {shlex.join(cmd)}")
+    subprocess.check_call(cmd)
+
+def update_distro(args, distro: str):
+    cmd = ['git', '-C', f'pkg/{distro}', 'fetch']
+    print(f"+ {shlex.join(cmd)}")
+    subprocess.check_call(cmd)
+
+    config = read_config(distro)
+
+    branch = config['Environment']['GIT_BRANCH']
+    old_commit = config['Environment']['GIT_COMMIT']
+
+    cmd = ['git', '-C', f'pkg/{distro}', 'rev-parse', f'refs/remotes/origin/{branch}']
+    print(f"+ {shlex.join(cmd)}")
+    new_commit = subprocess.check_output(cmd, text=True).strip()
+
+    if old_commit == new_commit:
+        print(f'{distro}: commit {new_commit!s} is still fresh')
+        return
+
+    cmd = ['git', '-C', f'pkg/{distro}', 'log', '--graph',
+           '--pretty=oneline', '--no-decorate', '--abbrev-commit', '--abbrev=10',
+           f'{old_commit}..{new_commit}']
+    print(f"+ {shlex.join(cmd)}")
+    changes = subprocess.check_output(cmd, text=True).strip()
+
+    conf_dir = Path('mkosi.images/system/mkosi.conf.d')
+    files = conf_dir.glob('*/*.conf')
+    for file in files:
+        s = file.read_text()
+        if old_commit in s:
+            print(f'{distro}: {file}: found old hash, updating…')
+            new = s.replace(old_commit, new_commit)
+            assert new != s
+            file.write_text(new)
+            commit_file(distro, file, new_commit, changes)
+            break
+    else:
+        raise ValueError(f'{distro}: hash {new_commit} not found under {conf_dir}')
+
+if __name__ == '__main__':
+    args = parse_args()
+    for distro in args.distribution:
+        update_distro(args, distro)