summaryrefslogtreecommitdiff
path: root/buildstream/_frontend/cli.py
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-12 16:32:41 +0000
commitba08a0cdb6b9f7b1a09821c88cde510056c51ec6 (patch)
tree2894794fc6a878a13a22c8389a74e4f4d80e59e3 /buildstream/_frontend/cli.py
parentb3dceb16cc56bd8d1c43a7d14e2c0e98d39769c4 (diff)
downloadbuildstream-ba08a0cdb6b9f7b1a09821c88cde510056c51ec6.tar.gz
cli: Add artifact log command
Diffstat (limited to 'buildstream/_frontend/cli.py')
-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 67958385c..84133f608 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
@@ -976,3 +978,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)