pipeline: drop output_id and pull in output-directory

Now that no caller requires the "output_id" anymore, drop it from our
results-dictionary. Instead, pass the output-directory through and copy
outputs where we produce / fetch them.

This still uses `objectstore.resolve_ref()`, since we do not have the
outputs pinned at the places where we want to copy. This needs a little
bit more rework, but we might just delay that until we have the cache
rework landed.

This already simplifies the output-directory path and drops the slight
hack which checked very late for produced outputs.

Note that we must be careful not to copy things too early, because we
do not want remnants in the output-directory if we return failure.
Hence, keep the copy-operation close to the commit-operation on the
store.
This commit is contained in:
David Rheinsberg 2020-05-22 11:10:32 +02:00
parent 18b16acd3f
commit 43ddcf895d
2 changed files with 23 additions and 12 deletions

View file

@ -195,6 +195,20 @@ class Object:
def __exit__(self, exc_type, exc_val, exc_tb):
self.cleanup()
def export(self, to_directory):
"""Copy object into an external directory"""
with self.read() as from_directory:
subprocess.run(
[
"cp",
"--reflink=auto",
"-a",
f"{from_directory}/.",
to_directory,
],
check=True,
)
class HostTree:
"""Read-only access to the host file system

View file

@ -285,7 +285,7 @@ class Pipeline:
results["tree_id"] = self.tree_id
return results, build_tree, tree
def assemble(self, object_store, build_tree, tree, interactive, libdir):
def assemble(self, object_store, build_tree, tree, interactive, libdir, output_directory=None):
results = {"success": True}
if not self.assembler:
@ -312,9 +312,10 @@ class Pipeline:
return results
object_store.commit(output, self.output_id)
if output_directory:
output.export(output_directory)
output.cleanup()
results["output_id"] = self.output_id
return results
def run(self, store, interactive=False, libdir=None, secrets=None, output_directory=None):
@ -328,10 +329,10 @@ class Pipeline:
# missing, since it is not a mandatory part of the result and would
# usually be needless overhead.
if object_store.contains(self.output_id):
results = {"output_id": self.output_id,
"success": True}
if object_store.contains(self.tree_id):
results["tree_id"] = self.tree_id
results = {"success": True}
if output_directory:
with object_store.new(base_id=self.output_id) as output:
output.export(output_directory)
else:
results, build_tree, tree = self.build_stages(object_store,
interactive,
@ -345,15 +346,11 @@ class Pipeline:
build_tree,
tree,
interactive,
libdir)
libdir,
output_directory)
results.update(r) # This will also update 'success'
if results["success"] and output_directory and "output_id" in results:
output_source = object_store.resolve_ref(results["output_id"])
if output_source is not None:
subprocess.run(["cp", "--reflink=auto", "-a", f"{output_source}/.", output_directory], check=True)
return results