For all currently supported modules, i.e. stages and assemblers,
convert the STAGE_DESC and STAGE_INFO into a proper doc-string.
Rename the STAGE_OPTS into SCHEMA.
Refactor meta.ModuleInfo loading accordingly.
The script to be used for the conversion is:
--- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< ---
import os
import sys
import osbuild
import osbuild.meta
from osbuild.meta import ModuleInfo
def find_line(lines, start):
for i, l in enumerate(lines):
if l.startswith(start):
return i
return None
def del_block(lines, prefix):
start = find_line(lines, prefix)
end = find_line(lines[start:], '"""')
print(start, end)
del lines[start:start+end+1]
def main():
index = osbuild.meta.Index(os.curdir)
modules = []
for klass in ("Stage", "Assembler"):
mods = index.list_modules_for_class(klass)
modules += [(klass, module) for module in mods]
for m in modules:
print(m)
klass, name = m
info = ModuleInfo.load(os.curdir, klass, name)
module_path = ModuleInfo.module_class_to_directory(klass)
path = os.path.join(os.curdir, module_path, name)
with open(path, "r") as f:
data = list(f.readlines())
i = find_line(data, "STAGE_DESC")
print(i)
del data[i]
del_block(data, "STAGE_INFO")
i = find_line(data, "STAGE_OPTS")
data[i] = 'SCHEMA = """\n'
docstr = '"""\n' + info.desc + "\n" + info.info + '"""\n'
doclst = docstr.split("\n")
doclst = [l + "\n" for l in doclst]
data = [data[0]] + doclst + data[1:]
with open(path, "w") as f:
f.writelines(data)
if __name__ == "__main__":
main()
170 lines
4.4 KiB
Python
Executable file
170 lines
4.4 KiB
Python
Executable file
#!/usr/bin/python3
|
|
"""
|
|
Assemble a file system tree into a ostree commit
|
|
|
|
Takes a file system tree that is already conforming to the ostree
|
|
system layout[1] and commits it to an archive repository.
|
|
|
|
The repository is located at the `/repo` directory and additional
|
|
metadata is stored in `/compose.json` which contains the commit
|
|
compose information.
|
|
|
|
Alternatively, if the `tar` option is supplied, the repository and
|
|
the `compose.json` will be archived in a file named via the
|
|
`tar.filename` option. This supports auto-compression via the file
|
|
extension (see the tar man page). Requires the `tar` command to be
|
|
in the build root.
|
|
|
|
[1] https://ostree.readthedocs.io/en/stable/manual/adapting-existing/
|
|
"""
|
|
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
from osbuild.util import ostree
|
|
|
|
|
|
SCHEMA = """
|
|
"additionalProperties": false,
|
|
"required": ["ref"],
|
|
"properties": {
|
|
"ref": {
|
|
"description": "OStree ref to create for the commit",
|
|
"type": "string",
|
|
"default": ""
|
|
},
|
|
"tmp-is-dir": {
|
|
"description": "Create a regular directory for /tmp",
|
|
"type": "boolean",
|
|
"default": true
|
|
},
|
|
"parent": {
|
|
"description": "commit id of the parent commit",
|
|
"type": "string"
|
|
},
|
|
"tar": {
|
|
"description": "Emit a tarball as the result",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["filename"],
|
|
"properties": {
|
|
"filename": {
|
|
"description": "File-name of the tarball to create. Compression is determined by the extension.",
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
|
|
TOPLEVEL_DIRS = ["dev", "proc", "run", "sys", "sysroot", "var"]
|
|
TOPLEVEL_LINKS = {
|
|
"home": "var/home",
|
|
"media": "run/media",
|
|
"mnt": "var/mnt",
|
|
"opt": "var/opt",
|
|
"ostree": "sysroot/ostree",
|
|
"root": "var/roothome",
|
|
"srv": "var/srv",
|
|
}
|
|
|
|
|
|
def copy(name, source, dest):
|
|
subprocess.run(["cp", "--reflink=auto", "-a",
|
|
os.path.join(source, name),
|
|
os.path.join(dest, name)],
|
|
check=True)
|
|
|
|
|
|
def init_rootfs(root, tmp_is_dir):
|
|
"""Initialize a pristine root file-system"""
|
|
|
|
fd = os.open(root, os.O_DIRECTORY)
|
|
|
|
os.fchmod(fd, 0o755)
|
|
|
|
for d in TOPLEVEL_DIRS:
|
|
os.mkdir(d, mode=0o755, dir_fd=fd)
|
|
os.chmod(d, mode=0o755, dir_fd=fd)
|
|
|
|
for l, t in TOPLEVEL_LINKS.items():
|
|
# <dir_fd>/l -> t
|
|
os.symlink(t, l, dir_fd=fd)
|
|
|
|
if tmp_is_dir:
|
|
os.mkdir("tmp", mode=0o1777, dir_fd=fd)
|
|
os.chmod("tmp", mode=0o1777, dir_fd=fd)
|
|
else:
|
|
os.symlink("tmp", "sysroot/tmp", dir_fd=fd)
|
|
|
|
|
|
def main(tree, output_dir, options):
|
|
ref = options["ref"]
|
|
tmp_is_dir = options.get("tmp-is-dir", True)
|
|
parent = options.get("parent", None)
|
|
tar = options.get("tar", None)
|
|
|
|
with tempfile.TemporaryDirectory(dir=output_dir) as root:
|
|
print("Initializing root filesystem", file=sys.stderr)
|
|
init_rootfs(root, tmp_is_dir)
|
|
|
|
print("Copying data", file=sys.stderr)
|
|
copy("usr", tree, root)
|
|
copy("boot", tree, root)
|
|
copy("var", tree, root)
|
|
|
|
for name in ["bin", "lib", "lib32", "lib64", "sbin"]:
|
|
if os.path.lexists(f"{tree}/{name}"):
|
|
copy(name, tree, root)
|
|
|
|
repo = os.path.join(output_dir, "repo")
|
|
|
|
subprocess.run(["ostree",
|
|
"init",
|
|
"--mode=archive",
|
|
f"--repo={repo}"],
|
|
stdout=sys.stderr,
|
|
check=True)
|
|
|
|
treefile = ostree.Treefile()
|
|
treefile["ref"] = ref
|
|
|
|
argv = ["rpm-ostree", "compose", "commit"]
|
|
argv += [f"--repo={repo}"]
|
|
|
|
if parent:
|
|
argv += [f"--parent={parent}"]
|
|
|
|
argv += [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)
|
|
|
|
if tar:
|
|
filename = tar["filename"]
|
|
command = [
|
|
"tar",
|
|
"--remove-files",
|
|
"--auto-compress",
|
|
"-cf", os.path.join(output_dir, filename),
|
|
"-C", output_dir,
|
|
"repo", "compose.json"
|
|
]
|
|
subprocess.run(command,
|
|
stdout=sys.stderr,
|
|
check=True)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
args = json.load(sys.stdin)
|
|
r = main(args["tree"], args["output_dir"], args["options"])
|
|
sys.exit(r)
|