Make sure access to the shared ostree metadata is locked properly. This is the default since 2018.5, but lets be explicit here. This also makes sure that the option exists and the local version supports locked and protected access. It is unclear whether the `ostree init` honors that as well. It really should, and if it doesn't we can always report it upstream.
89 lines
2.5 KiB
Python
Executable file
89 lines
2.5 KiB
Python
Executable file
#!/usr/bin/python3
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
import uuid
|
|
|
|
|
|
def ostree(*args, _input=None, **kwargs):
|
|
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
|
|
print(f"ostree " + " ".join(args), file=sys.stderr)
|
|
subprocess.run(["ostree"] + args,
|
|
encoding="utf-8",
|
|
stdout=sys.stderr,
|
|
input=_input,
|
|
check=True)
|
|
|
|
|
|
def main(options, checksums, cache, output):
|
|
commits = options["commits"]
|
|
|
|
os.makedirs(output, exist_ok=True)
|
|
os.makedirs(cache, exist_ok=True)
|
|
|
|
# Prepare the cache and the output repo
|
|
repo_cache = os.path.join(cache, "repo")
|
|
ostree("init", mode="archive", repo=repo_cache)
|
|
|
|
# Make sure the cache repository uses locks to protect the metadata during
|
|
# shared access. This is the default since `2018.5`, but lets document this
|
|
# explicitly here.
|
|
ostree("config", "set", "repo.locking", "true", repo=repo_cache)
|
|
|
|
repo_out = os.path.join(output, "repo")
|
|
ostree("init", mode="archive", repo=repo_out)
|
|
|
|
for commit in checksums:
|
|
remote = commits[commit]["remote"]
|
|
url = remote["url"]
|
|
gpg = remote.get("gpgkeys", [])
|
|
uid = str(uuid.uuid4())
|
|
|
|
ostree("remote", "add",
|
|
"--no-gpg-verify",
|
|
uid, url,
|
|
repo=repo_cache)
|
|
|
|
# this temporary remote is needed to verify
|
|
# the commit signatures via gpg below
|
|
ostree("remote", "add",
|
|
uid, repo_cache,
|
|
repo=repo_out)
|
|
|
|
for key in gpg:
|
|
ostree("remote", "gpg-import", "--stdin", uid,
|
|
repo=repo_out, _input=key)
|
|
|
|
# Transfer the commit: remote → cache
|
|
print(f"pulling {commit}", file=sys.stderr)
|
|
ostree("pull", uid, commit, repo=repo_cache)
|
|
|
|
# Transfer the commit: cache → output
|
|
verify_args = []
|
|
if gpg:
|
|
verify_args = ["--gpg-verify", "--remote", uid]
|
|
|
|
ostree("pull-local", repo_cache, commit,
|
|
*verify_args,
|
|
repo=repo_out)
|
|
|
|
# Remove the temporary remotes again
|
|
ostree("remote", "delete", uid,
|
|
repo=repo_cache)
|
|
|
|
ostree("remote", "delete", uid,
|
|
repo=repo_out)
|
|
|
|
json.dump({}, sys.stdout)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
source_args = json.load(sys.stdin)
|
|
r = main(source_args["options"],
|
|
source_args["checksums"],
|
|
source_args["cache"],
|
|
source_args["output"])
|
|
sys.exit(r)
|