Blob Blame History Raw
#!/usr/bin/python3
"""
Assemble a file system tree into a ostree commit

Needs a file system tree that is already conforming to the ostree
system layout[1], specified via the `tree` input and commits it
to a repository. The repository must have been created at `/repo`.

Additional metadata is stored in `/compose.json` which contains
the commit compose information. This is also returned via the
metadata API to osbuild.

[1] https://ostree.readthedocs.io/en/stable/manual/adapting-existing/
"""


import json
import os
import subprocess
import sys
import tempfile

from osbuild import api
from osbuild.util import ostree


SCHEMA_2 = """
"options": {
  "additionalProperties": false,
  "required": ["ref"],
  "properties": {
    "ref": {
      "description": "OStree ref to create for the commit",
      "type": "string",
      "default": ""
    },
    "os_version": {
      "description": "Set the version of the OS as commit metadata",
      "type": "string"
    },
    "parent": {
      "description": "commit id of the parent commit",
      "type": "string"
    }
  }
},
"inputs": {
  "type": "object",
  "additionalProperties": false,
  "required": ["tree"],
  "properties": {
    "tree": {
      "type": "object",
      "additionalProperties": true
    }
  }
}
"""


def main(inputs, output_dir, options, meta):
    tree = inputs["tree"]["path"]

    ref = options["ref"]
    os_version = options.get("os_version", None)
    parent = options.get("parent", None)

    # rpm-ostree compose commit wants to consume the commit
    # so for now, we copy the whole tree and let it have its
    # way
    with tempfile.TemporaryDirectory(dir=output_dir) as root:
        subprocess.run(["cp", "--reflink=auto", "-a",
                        f"{tree}/.", root],
                       check=True)

        repo = os.path.join(output_dir, "repo")

        treefile = ostree.Treefile()
        treefile["ref"] = ref

        argv = ["rpm-ostree", "compose", "commit"]
        argv += [f"--repo={repo}"]

        if parent:
            argv += [f"--parent={parent}"]

        if os_version:
            argv += [
                f"--add-metadata-string=version={os_version}",
            ]

        argv += [
            f"--add-metadata-string=rpmostree.inputhash={meta['id']}",
            f"--write-composejson-to={output_dir}/compose.json"
        ]

        with treefile.as_tmp_file() as path:
            argv += [path, root]

            subprocess.run(argv,
                           stdout=sys.stderr,
                           check=True)

        with open(os.path.join(output_dir, "compose.json"), "r") as f:
            compose = json.load(f)

        api.metadata({"compose": compose})


if __name__ == '__main__':
    args = api.arguments()

    r = main(args["inputs"],
             args["tree"],
             args["options"],
             args["meta"])

    sys.exit(r)