summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2018-11-01 15:24:32 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2018-12-04 16:58:42 +0000
commit84c8644d70b886eda2f2b6d1e09c91c8189f3906 (patch)
treec8a810f04babcd5bad5ea70805274a61c67a9e72
parent779e0d6a2e6ec0acb388646b7317737c4be2bdf9 (diff)
downloadbuildstream-84c8644d70b886eda2f2b6d1e09c91c8189f3906.tar.gz
cli: Add artifact log command
-rw-r--r--buildstream/_frontend/cli.py59
1 files changed, 59 insertions, 0 deletions
diff --git a/buildstream/_frontend/cli.py b/buildstream/_frontend/cli.py
index fcafb7757..0de1bd48b 100644
--- a/buildstream/_frontend/cli.py
+++ b/buildstream/_frontend/cli.py
@@ -1,6 +1,8 @@
import os
import sys
+from contextlib import ExitStack
from fnmatch import fnmatch
+from tempfile import TemporaryDirectory
import click
from .. import _yaml
@@ -927,3 +929,60 @@ def _classify_artifacts(names, cas, project_directory):
def artifact():
"""Manipulate cached artifacts"""
pass
+
+
+################################################################
+# Artifact Log Command #
+################################################################
+@artifact.command(name='log', short_help="Show logs of an artifact")
+@click.argument('artifacts', type=click.Path(), nargs=-1)
+@click.pass_obj
+def artifact_log(app, artifacts):
+ """Show logs of all artifacts"""
+ from .._exceptions import CASError
+ from .._message import MessageType
+ from .._pipeline import PipelineSelection
+ from ..storage._casbaseddirectory import CasBasedDirectory
+
+ with ExitStack() as stack:
+ stack.enter_context(app.initialized())
+ cache = app.context.artifactcache
+
+ elements, artifacts = _classify_artifacts(artifacts, cache.cas,
+ app.project.directory)
+
+ vdirs = []
+ extractdirs = []
+ if artifacts:
+ for ref in artifacts:
+ try:
+ cache_id = cache.cas.resolve_ref(ref, update_mtime=True)
+ vdir = CasBasedDirectory(cache.cas, cache_id)
+ vdirs.append(vdir)
+ except CASError as e:
+ app._message(MessageType.WARN, "Artifact {} is not cached".format(ref), detail=str(e))
+ continue
+ if elements:
+ elements = app.stream.load_selection(elements, selection=PipelineSelection.NONE)
+ for element in elements:
+ if not element._cached():
+ app._message(MessageType.WARN, "Element {} is not cached".format(element))
+ continue
+ ref = cache.get_artifact_fullname(element, element._get_cache_key())
+ cache_id = cache.cas.resolve_ref(ref, update_mtime=True)
+ vdir = CasBasedDirectory(cache.cas, cache_id)
+ vdirs.append(vdir)
+
+ for vdir in vdirs:
+ # NOTE: If reading the logs feels unresponsive, here would be a good place to provide progress information.
+ logsdir = vdir.descend(["logs"])
+ td = stack.enter_context(TemporaryDirectory())
+ logsdir.export_files(td, can_link=True)
+ extractdirs.append(td)
+
+ for extractdir in extractdirs:
+ for log in (os.path.join(extractdir, log) for log in os.listdir(extractdir)):
+ # NOTE: Should click gain the ability to pass files to the pager this can be optimised.
+ with open(log) as f:
+ data = f.read()
+ click.echo_via_pager(data)