stages: add org.osbuild.copy stage
Copies files obtained via a `source` to the tree. Multiple files or directories can be copied by specifying multiple entries in `paths`. If no paths are specified the whole contents of `source` is copied. The source and the target path for each individual path entry might optionally be specified via `from` and `to`, respectively; if no path is given for any of the two, the root `/` is assumed. Currently only an 'archive' 'source' is supported that in turn uses the existing 'org.osbuild.files' source to fetch an archive (tarball) and extracts it to a temporary directory.
This commit is contained in:
parent
73429035bc
commit
07c5fdb650
1 changed files with 138 additions and 0 deletions
138
stages/org.osbuild.copy
Executable file
138
stages/org.osbuild.copy
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
import osbuild.sources
|
||||
|
||||
|
||||
STAGE_DESC = "Copy files from a source to the tree"
|
||||
STAGE_INFO = """
|
||||
Copies files obtained via a `source` to the tree. Multiple files or
|
||||
directories can be copied by specifying multiple entries in `paths`.
|
||||
If no paths are specified the whole contents of `source` is copied.
|
||||
The source and the target path for each individual path entry might
|
||||
optionally be specified via `from` and `to`, respectively; if no
|
||||
path is given for any of the two, the root `/` is assumed.
|
||||
|
||||
Supported sources are currently:
|
||||
|
||||
o `archive`: Fetch an archive via the org.osbuild.files source and
|
||||
extract it to a temporary directory. Currently only tar archives
|
||||
are supported.
|
||||
|
||||
"""
|
||||
STAGE_OPTS = """
|
||||
"additionalProperties": false,
|
||||
"definitions": {
|
||||
"source-archive": {
|
||||
"description": "Fetch an via org.osbuild.files and extract it",
|
||||
"type": "object",
|
||||
"required": ["type", "checksum"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"description": "The type of the source, here 'archive'",
|
||||
"enum": ["archive"]
|
||||
},
|
||||
"checksum": {
|
||||
"type": "string",
|
||||
"description": "The checksum of the archive to fetch"
|
||||
},
|
||||
"strip-components": {
|
||||
"type": "number",
|
||||
"description": "Strip 'N' leading components from file names on extraction",
|
||||
"default": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"source": {
|
||||
"oneOf": [{ "$ref": "#/definitions/source-archive" }]
|
||||
},
|
||||
"paths": {
|
||||
"description": "Array of items to copy",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"from": {
|
||||
"type": "string",
|
||||
"description": "The source path",
|
||||
"default": "/"
|
||||
},
|
||||
"to": {
|
||||
"type": "string",
|
||||
"description": "The destination path",
|
||||
"default": "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def get_archive(options, srcdir, workdir):
|
||||
checksum = options["checksum"]
|
||||
strip = options.get("strip-components", 1)
|
||||
source_path = os.path.join(srcdir, "org.osbuild.files")
|
||||
|
||||
target = os.path.join(workdir, checksum)
|
||||
os.makedirs(target)
|
||||
|
||||
# actually fetch the archive
|
||||
res = osbuild.sources.get("org.osbuild.files", [checksum])
|
||||
|
||||
tar = [
|
||||
"tar",
|
||||
"--strip-components=" + str(strip),
|
||||
"-x",
|
||||
"-C", target,
|
||||
"-f", os.path.join(source_path, checksum)
|
||||
]
|
||||
|
||||
subprocess.run(tar, check=True)
|
||||
|
||||
return target, res
|
||||
|
||||
|
||||
def main(tree, srcdir, options, workdir):
|
||||
source_options = options["source"]
|
||||
source_type = source_options["type"]
|
||||
paths = options.get("paths", [{}])
|
||||
|
||||
if source_type == "archive":
|
||||
source = get_archive
|
||||
else:
|
||||
raise ValueError(f"Unsupported source: {source_type}")
|
||||
|
||||
# Fetch the requested data via the selected source
|
||||
source_path, _ = source(source_options, srcdir, workdir)
|
||||
|
||||
for path in paths:
|
||||
src = path.get("from", "/")
|
||||
dst = path.get("to", "/")
|
||||
|
||||
subprocess.run(["cp", "--reflink=auto", "-a",
|
||||
f"{source_path}{src}",
|
||||
f"{tree}{dst}"],
|
||||
check=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
stage_args = json.load(sys.stdin)
|
||||
|
||||
with tempfile.TemporaryDirectory() as _workdir:
|
||||
r = main(stage_args["tree"],
|
||||
stage_args["sources"],
|
||||
stage_args["options"],
|
||||
_workdir)
|
||||
|
||||
sys.exit(r)
|
||||
Loading…
Add table
Add a link
Reference in a new issue