debian-forge/sources/org.osbuild.ostree
Christian Kellner a05a8aaed6 sources/ostree: remove export functionality
Since the `sources.SourcesServer` has been removed, nothing is
using the export functionality anymore. Inputs are now used to
make content in the store available to stages. Remove all the
export logic from org.osbuild.ostree.
2021-04-29 12:58:01 +02:00

138 lines
3.5 KiB
Python
Executable file

#!/usr/bin/python3
"""Fetch OSTree commits from an repository
Uses ostree to pull specific commits from (remote) repositories
at the provided `url`. Can verify the commit, if one or more
gpg keys are provided via `gpgkeys`.
"""
import json
import os
import sys
import subprocess
import uuid
from typing import Dict
SCHEMA = """
"additionalProperties": false,
"definitions": {
"item": {
"description": "The commits to fetch indexed their checksum",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"[0-9a-f]{5,64}": {
"type": "object",
"additionalProperties": false,
"required": ["remote"],
"properties": {
"remote": {
"type": "object",
"additionalProperties": false,
"required": ["url"],
"properties": {
"url": {
"type": "string",
"description": "URL of the repository."
},
"gpgkeys": {
"type": "array",
"items": {
"type": "string",
"description": "GPG keys to verify the commits"
}
}
}
}
}
}
}
}
},
"properties": {
"items": {"$ref": "#/definitions/item"},
"commits": {"$ref": "#/definitions/item"}
},
"oneOf": [{
"required": ["items"]
}, {
"required": ["commits"]
}]
"""
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf-8",
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
input=_input,
check=True)
def download(items, cache):
# 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)
for commit, item in items.items():
remote = item["remote"]
url = remote["url"]
gpg = remote.get("gpgkeys", [])
uid = str(uuid.uuid4())
verify_args = []
if not gpg:
verify_args = ["--no-gpg-verify"]
ostree("remote", "add",
uid, url,
*verify_args,
repo=repo_cache)
for key in gpg:
ostree("remote", "gpg-import", "--stdin", uid,
repo=repo_cache, _input=key)
# Transfer the commit: remote → cache
print(f"pulling {commit}", file=sys.stderr)
ostree("pull", uid, commit, repo=repo_cache)
# Remove the temporary remotes again
ostree("remote", "delete", uid,
repo=repo_cache)
def main(items: Dict, cache: str):
cache = os.path.join(cache, "org.osbuild.ostree")
if not items:
json.dump({}, sys.stdout)
return 0
os.makedirs(cache, exist_ok=True)
try:
download(items, cache)
except subprocess.CalledProcessError as e:
output = e.output.strip()
json.dump({"error": output}, sys.stdout)
return 1
json.dump({}, sys.stdout)
return 0
if __name__ == '__main__':
source_args = json.load(sys.stdin)
r = main(source_args["items"], source_args["cache"])
sys.exit(r)