summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaoul Hidalgo Charman <raoul.hidalgocharman@codethink.co.uk>2019-06-13 11:50:39 +0100
committerRaoul Hidalgo Charman <raoul.hidalgocharman@codethink.co.uk>2019-06-24 11:42:55 +0100
commit86330faf4f0ababde265f1ac3e86733d1908ed44 (patch)
tree327c9a04ca618d555ec963f5692c3895b1b15bcf
parentc69a6ee7a464bc651567e67217c8c093cc956f88 (diff)
downloadbuildstream-86330faf4f0ababde265f1ac3e86733d1908ed44.tar.gz
_stream/cli: Add pull option to shell
This will fetch artifacts if they're not local or are incomplete. Part of #1044
-rw-r--r--src/buildstream/_frontend/cli.py27
-rw-r--r--src/buildstream/_stream.py18
2 files changed, 30 insertions, 15 deletions
diff --git a/src/buildstream/_frontend/cli.py b/src/buildstream/_frontend/cli.py
index b353ced93..53adb188c 100644
--- a/src/buildstream/_frontend/cli.py
+++ b/src/buildstream/_frontend/cli.py
@@ -501,11 +501,13 @@ def show(app, elements, deps, except_, order, format_):
@click.option('--use-buildtree', '-t', 'cli_buildtree', type=click.Choice(['ask', 'try', 'always', 'never']),
default='ask',
help='Defaults to ask but if set to always the function will fail if a build tree is not available')
+@click.option('--pull', 'pull_', is_flag=True, default=False,
+ help='Attempt to pull missing or incomplete artifacts')
@click.argument('element', required=False,
type=click.Path(readable=False))
@click.argument('command', type=click.STRING, nargs=-1)
@click.pass_obj
-def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command):
+def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, pull_, command):
"""Run a command in the target element's sandbox environment
When this command is executed from a workspace directory, the default
@@ -535,11 +537,10 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command)
from .._project import HostMount
from .._pipeline import PipelineSelection
- if build_:
- scope = Scope.BUILD
- else:
- scope = Scope.RUN
+ scope = Scope.BUILD if build_ else Scope.RUN
+ # We may need to fetch dependency artifacts if we're pulling the artifact
+ selection = PipelineSelection.ALL if pull_ else PipelineSelection.NONE
use_buildtree = None
with app.initialized():
@@ -548,9 +549,14 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command)
if not element:
raise AppError('Missing argument "ELEMENT".')
- dependencies = app.stream.load_selection((element,), selection=PipelineSelection.NONE,
- use_artifact_config=True)
- element = dependencies[0]
+ elements = app.stream.load_selection((element,), selection=selection,
+ use_artifact_config=True)
+
+ # last one will be the element we want to stage, previous ones are
+ # elements to try and pull
+ element = elements[-1]
+ pull_dependencies = elements[:-1] if pull_ else None
+
prompt = app.shell_prompt(element)
mounts = [
HostMount(path, host_path)
@@ -561,7 +567,7 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command)
buildtree_exists = element._buildtree_exists()
if cli_buildtree in ("always", "try"):
- if buildtree_exists:
+ if buildtree_exists or pull_:
use_buildtree = cli_buildtree
if not cached and use_buildtree == "always":
click.echo("WARNING: buildtree is not cached locally, will attempt to pull from available remotes",
@@ -601,7 +607,8 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command)
mounts=mounts,
isolate=isolate,
command=command,
- usebuildtree=use_buildtree)
+ usebuildtree=use_buildtree,
+ pull_dependencies=pull_dependencies)
except BstError as e:
raise AppError("Error launching shell: {}".format(e), detail=e.detail) from e
diff --git a/src/buildstream/_stream.py b/src/buildstream/_stream.py
index 6f6d30f17..8097f451d 100644
--- a/src/buildstream/_stream.py
+++ b/src/buildstream/_stream.py
@@ -140,6 +140,7 @@ class Stream():
# isolate (bool): Whether to isolate the environment like we do in builds
# command (list): An argv to launch in the sandbox, or None
# usebuildtree (str): Whether to use a buildtree as the source, given cli option
+ # pull_dependencies ([Element]|None): Elements to attempt to pull
#
# Returns:
# (int): The exit code of the launched shell
@@ -149,20 +150,27 @@ class Stream():
mounts=None,
isolate=False,
command=None,
- usebuildtree=None):
+ usebuildtree=None,
+ pull_dependencies=None):
# Assert we have everything we need built, unless the directory is specified
# in which case we just blindly trust the directory, using the element
# definitions to control the execution environment only.
if directory is None:
missing_deps = [
- dep._get_full_name()
- for dep in self._pipeline.dependencies([element], scope)
+ dep for dep in self._pipeline.dependencies([element], scope)
if not dep._cached()
]
if missing_deps:
- raise StreamError("Elements need to be built or downloaded before staging a shell environment",
- detail="\n".join(missing_deps))
+ if not pull_dependencies:
+ raise StreamError(
+ "Elements need to be built or downloaded before staging a shell environment",
+ detail="\n"
+ .join(list(map(lambda x: x._get_full_name(), missing_deps))))
+ self._message(MessageType.INFO, "Attempting to fetch missing or incomplete artifacts")
+ self._add_queue(PullQueue(self._scheduler))
+ self._enqueue_plan([element] + missing_deps)
+ self._run()
buildtree = False
# Check if we require a pull queue attempt, with given artifact state and context