mirror of
https://github.com/systemd/systemd.git
synced 2026-06-24 08:47:49 +00:00
185 lines
5.2 KiB
Python
Executable File
185 lines
5.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
"""
|
|
Check out pkg/{distribution}.
|
|
With -u, fetch commits, 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,
|
|
)
|
|
p.add_argument(
|
|
'--update',
|
|
'-u',
|
|
action='store_true',
|
|
default=False,
|
|
)
|
|
p.add_argument('--profile')
|
|
return p.parse_args()
|
|
|
|
|
|
def read_config(distro: str):
|
|
cmd = ['mkosi', '--json', '-d', distro, '-f', 'summary']
|
|
if args.profile:
|
|
cmd += ['--profile', args.profile]
|
|
print(f'+ {shlex.join(cmd)}')
|
|
text = subprocess.check_output(cmd, text=True)
|
|
|
|
data = json.loads(text)
|
|
images = {image['Image']: image for image in data['Images']}
|
|
return images['build']
|
|
|
|
|
|
def commit_file(distro: str, files: list[Path], commit: str, changes: str):
|
|
message = '\n'.join((f'mkosi: update {distro} commit reference to {commit}', '', changes))
|
|
|
|
cmd = ['git', 'commit', '-m', message, *(str(file) for file in files)]
|
|
print(f'+ {shlex.join(cmd)}')
|
|
subprocess.check_call(cmd)
|
|
|
|
|
|
def checkout_distro(args, distro: str, config: dict):
|
|
url = config['Environment']['GIT_URL']
|
|
branch = config['Environment']['GIT_BRANCH']
|
|
subdir = config['Environment'].get('GIT_SUBDIR')
|
|
pkg_subdir = config['Environment']['PKG_SUBDIR']
|
|
|
|
dest = Path(f'pkg/{pkg_subdir}')
|
|
if dest.exists():
|
|
print(f'{dest} already exists.')
|
|
return
|
|
|
|
# Do not checkout the full sources if the package is in a subdirectory,
|
|
# a sparse checkout will be done after
|
|
sparse = ['--no-checkout', '--filter=blob:none'] if subdir is not None else []
|
|
|
|
# Only debian uses source-git for now…
|
|
reference = ['--reference-if-able=.'] if distro == 'debian' else []
|
|
|
|
cmd = [
|
|
'git',
|
|
'clone',
|
|
url,
|
|
f'--branch={branch}',
|
|
*sparse,
|
|
dest.as_posix(),
|
|
*reference,
|
|
]
|
|
print(f'+ {shlex.join(cmd)}')
|
|
subprocess.check_call(cmd)
|
|
|
|
# Sparse checkout if the package is in a subdirectory
|
|
if subdir is not None:
|
|
cmd = ['git', '-C', f'pkg/{pkg_subdir}', 'sparse-checkout', 'set', '--no-cone', f'{subdir}']
|
|
print(f'+ {shlex.join(cmd)}')
|
|
subprocess.check_call(cmd)
|
|
|
|
cmd = ['git', '-C', f'pkg/{pkg_subdir}', 'checkout', 'HEAD']
|
|
print(f'+ {shlex.join(cmd)}')
|
|
subprocess.check_call(cmd)
|
|
|
|
args.fetch = False # no need to fetch if we just cloned
|
|
|
|
|
|
def update_distro(args, distro: str, config: dict):
|
|
branch = config['Environment']['GIT_BRANCH']
|
|
subdir = config['Environment'].get('GIT_SUBDIR')
|
|
old_commit = config['Environment']['GIT_COMMIT']
|
|
pkg_subdir = config['Environment']['PKG_SUBDIR']
|
|
|
|
if args.fetch:
|
|
cmd = [
|
|
'git',
|
|
'-C', f'pkg/{pkg_subdir}',
|
|
'fetch',
|
|
'origin',
|
|
'-v',
|
|
f'{branch}:remotes/origin/{branch}',
|
|
] # fmt: skip
|
|
print(f'+ {shlex.join(cmd)}')
|
|
subprocess.check_call(cmd)
|
|
|
|
cmd = ['git', '-C', f'pkg/{pkg_subdir}', 'switch', branch]
|
|
print(f'+ {shlex.join(cmd)}')
|
|
subprocess.check_call(cmd)
|
|
|
|
cmd = ['git', '-C', f'pkg/{pkg_subdir}', 'log', '-n1', '--format=%H', f'refs/remotes/origin/{branch}']
|
|
if subdir is not None:
|
|
cmd += [f'{subdir}']
|
|
print(f'+ {shlex.join(cmd)}')
|
|
new_commit = subprocess.check_output(cmd, text=True).strip()
|
|
|
|
if old_commit == new_commit:
|
|
print(f'{pkg_subdir}: commit {new_commit!s} is still fresh')
|
|
return
|
|
|
|
cmd = [
|
|
'git',
|
|
'-C', f'pkg/{pkg_subdir}',
|
|
'log',
|
|
'--graph',
|
|
'--no-merges',
|
|
'--pretty=oneline',
|
|
'--no-decorate',
|
|
'--abbrev-commit',
|
|
'--abbrev=10',
|
|
f'{old_commit}..{new_commit}',
|
|
] # fmt: skip
|
|
if subdir is not None:
|
|
cmd += [f'{subdir}']
|
|
print(f'+ {shlex.join(cmd)}')
|
|
changes = subprocess.check_output(cmd, text=True).strip()
|
|
|
|
conf_dir = Path('mkosi/mkosi.pkgenv/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)
|
|
tocommit = [file]
|
|
|
|
if distro == 'fedora':
|
|
packit = Path('.packit.yml')
|
|
s = packit.read_text()
|
|
assert old_commit in s
|
|
new = s.replace(old_commit, new_commit)
|
|
packit.write_text(new)
|
|
tocommit += [packit]
|
|
|
|
commit_file(distro, tocommit, 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:
|
|
config = read_config(distro)
|
|
checkout_distro(args, distro, config)
|
|
if args.update:
|
|
update_distro(args, distro, config)
|