summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Maat <tm@tlater.net>2020-01-08 18:24:14 +0000
committerTristan Maat <tm@tlater.net>2020-01-08 18:24:14 +0000
commit5960a90e03b1e5115f6e5912b126529846e589f5 (patch)
treed3f08b0b1ec959d17da2ad30ab53f9e3ab65175f
parent2855243b80e6b549e338f438b89a6867cfd7ff45 (diff)
parent0ae6205598e49e44e45d6f943a0bba9825ce51c2 (diff)
downloadbuildstream-5960a90e03b1e5115f6e5912b126529846e589f5.tar.gz
Merge branch 'tlater/pipeline-enums' into 'master'
Make PipelineSelection a proper enum type Closes #1135 See merge request BuildStream/buildstream!1787
-rw-r--r--src/buildstream/_context.py7
-rw-r--r--src/buildstream/_frontend/cli.py109
-rw-r--r--src/buildstream/_pipeline.py65
-rw-r--r--src/buildstream/_stream.py71
-rw-r--r--src/buildstream/types.py30
5 files changed, 162 insertions, 120 deletions
diff --git a/src/buildstream/_context.py b/src/buildstream/_context.py
index 47001440a..9642edd49 100644
--- a/src/buildstream/_context.py
+++ b/src/buildstream/_context.py
@@ -29,7 +29,7 @@ from ._platform import Platform
from ._artifactcache import ArtifactCache
from ._sourcecache import SourceCache
from ._cas import CASCache, CASLogLevel
-from .types import _CacheBuildTrees, _SchedulerErrorAction
+from .types import _CacheBuildTrees, _PipelineSelection, _SchedulerErrorAction
from ._workspaces import Workspaces, WorkspaceProjectCache
from .node import Node
from .sandbox import SandboxRemote
@@ -361,13 +361,14 @@ class Context:
build.validate_keys(["max-jobs", "dependencies"])
self.build_max_jobs = build.get_int("max-jobs")
- self.build_dependencies = build.get_str("dependencies")
- if self.build_dependencies not in ["plan", "all"]:
+ dependencies = build.get_str("dependencies")
+ if dependencies not in ["plan", "all"]:
provenance = build.get_scalar("dependencies").get_provenance()
raise LoadError(
"{}: Invalid value for 'dependencies'. Choose 'plan' or 'all'.".format(provenance),
LoadErrorReason.INVALID_DATA,
)
+ self.build_dependencies = _PipelineSelection(dependencies)
# Load per-projects overrides
self._project_overrides = defaults.get_mapping("projects", default={})
diff --git a/src/buildstream/_frontend/cli.py b/src/buildstream/_frontend/cli.py
index 051f5d7f7..365f5c421 100644
--- a/src/buildstream/_frontend/cli.py
+++ b/src/buildstream/_frontend/cli.py
@@ -9,7 +9,7 @@ from .. import _yaml
from .._exceptions import BstError, LoadError, AppError
from .._versions import BST_FORMAT_VERSION
from .complete import main_bashcomplete, complete_path, CompleteUnhandled
-from ..types import _CacheBuildTrees, _SchedulerErrorAction
+from ..types import _CacheBuildTrees, _SchedulerErrorAction, _PipelineSelection
from ..utils import _get_compression, UtilError
@@ -19,11 +19,22 @@ from ..utils import _get_compression, UtilError
class FastEnumType(click.Choice):
- def __init__(self, enum):
+ def __init__(self, enum, options=None):
self._enum = enum
- super().__init__(enum.values())
+
+ if options is None:
+ options = enum.values()
+ else:
+ options = [option.value for option in options]
+
+ super().__init__(options)
def convert(self, value, param, ctx):
+ # This allows specifying default values as instances of the
+ # enum
+ if isinstance(value, self._enum):
+ value = value.value
+
return self._enum(super().convert(value, param, ctx))
@@ -438,7 +449,13 @@ def init(app, project_name, format_version, element_path, force, target_director
# Build Command #
##################################################################
@cli.command(short_help="Build elements in a pipeline")
-@click.option("--deps", "-d", default=None, type=click.Choice(["plan", "all"]), help="The dependencies to build")
+@click.option(
+ "--deps",
+ "-d",
+ default=None,
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.PLAN, _PipelineSelection.ALL]),
+ help="The dependencies to build",
+)
@click.option(
"--remote", "-r", default=None, help="The URL of the remote cache (defaults to the first configured cache)"
)
@@ -484,9 +501,18 @@ def build(app, elements, deps, remote):
@click.option(
"--deps",
"-d",
- default="all",
+ default=_PipelineSelection.ALL,
show_default=True,
- type=click.Choice(["none", "plan", "run", "build", "all"]),
+ type=FastEnumType(
+ _PipelineSelection,
+ [
+ _PipelineSelection.NONE,
+ _PipelineSelection.PLAN,
+ _PipelineSelection.RUN,
+ _PipelineSelection.BUILD,
+ _PipelineSelection.ALL,
+ ],
+ ),
help="The dependencies to show",
)
@click.option(
@@ -641,12 +667,11 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, pull_, c
"""
from ..element import Scope
from .._project import HostMount
- from .._pipeline import PipelineSelection
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
+ selection = _PipelineSelection.ALL if pull_ else _PipelineSelection.NONE
use_buildtree = None
with app.initialized():
@@ -750,9 +775,9 @@ def source():
@click.option(
"--deps",
"-d",
- default="plan",
+ default=_PipelineSelection.PLAN,
show_default=True,
- type=click.Choice(["none", "plan", "all"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.NONE, _PipelineSelection.PLAN, _PipelineSelection.ALL]),
help="The dependencies to fetch",
)
@click.option(
@@ -803,9 +828,9 @@ def source_fetch(app, elements, deps, except_, remote):
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["none", "all"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.NONE, _PipelineSelection.ALL]),
help="The dependencies to track",
)
@click.option("--cross-junctions", "-J", is_flag=True, help="Allow crossing junction boundaries")
@@ -839,8 +864,8 @@ def source_track(app, elements, deps, except_, cross_junctions):
# Substitute 'none' for 'redirect' so that element redirections
# will be done
- if deps == "none":
- deps = "redirect"
+ if deps == _PipelineSelection.NONE:
+ deps = _PipelineSelection.REDIRECT
app.stream.track(elements, selection=deps, except_targets=except_, cross_junctions=cross_junctions)
@@ -855,9 +880,12 @@ def source_track(app, elements, deps, except_, cross_junctions):
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["build", "none", "run", "all"]),
+ type=FastEnumType(
+ _PipelineSelection,
+ [_PipelineSelection.BUILD, _PipelineSelection.NONE, _PipelineSelection.RUN, _PipelineSelection.ALL],
+ ),
help="The dependencies whose sources to checkout",
)
@click.option(
@@ -1097,9 +1125,12 @@ def artifact():
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["build", "run", "all", "none"]),
+ type=FastEnumType(
+ _PipelineSelection,
+ [_PipelineSelection.BUILD, _PipelineSelection.RUN, _PipelineSelection.ALL, _PipelineSelection.NONE],
+ ),
help="The dependencies we also want to show",
)
@click.argument("artifacts", type=click.Path(), nargs=-1)
@@ -1120,9 +1151,12 @@ def artifact_show(app, deps, artifacts):
@click.option(
"--deps",
"-d",
- default="run",
+ default=_PipelineSelection.RUN,
show_default=True,
- type=click.Choice(["run", "build", "none", "all"]),
+ type=FastEnumType(
+ _PipelineSelection,
+ [_PipelineSelection.RUN, _PipelineSelection.BUILD, _PipelineSelection.NONE, _PipelineSelection.ALL],
+ ),
help="The dependencies to checkout",
)
@click.option("--integrate/--no-integrate", default=None, is_flag=True, help="Whether to run integration commands")
@@ -1216,9 +1250,9 @@ def artifact_checkout(app, force, deps, integrate, hardlinks, tar, compression,
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["none", "all"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.NONE, _PipelineSelection.ALL]),
help="The dependency artifacts to pull",
)
@click.option(
@@ -1265,9 +1299,9 @@ def artifact_pull(app, artifacts, deps, remote):
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["none", "all"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.NONE, _PipelineSelection.ALL]),
help="The dependencies to push",
)
@click.option(
@@ -1389,9 +1423,12 @@ def artifact_list_contents(app, artifacts, long_):
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["none", "run", "build", "all"]),
+ type=FastEnumType(
+ _PipelineSelection,
+ [_PipelineSelection.NONE, _PipelineSelection.RUN, _PipelineSelection.BUILD, _PipelineSelection.ALL],
+ ),
help="The dependencies to delete",
)
@click.argument("artifacts", type=click.Path(), nargs=-1)
@@ -1425,9 +1462,9 @@ def artifact_delete(app, artifacts, deps):
@click.option(
"--deps",
"-d",
- default="plan",
+ default=_PipelineSelection.PLAN,
show_default=True,
- type=click.Choice(["none", "plan", "all"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.NONE, _PipelineSelection.PLAN, _PipelineSelection.ALL]),
help="The dependencies to fetch",
)
@click.argument("elements", nargs=-1, type=click.Path(readable=False))
@@ -1451,9 +1488,9 @@ def fetch(app, elements, deps, except_):
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["none", "all"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.NONE, _PipelineSelection.ALL]),
help="The dependencies to track",
)
@click.option("--cross-junctions", "-J", is_flag=True, help="Allow crossing junction boundaries")
@@ -1472,9 +1509,9 @@ def track(app, elements, deps, except_, cross_junctions):
@click.option(
"--deps",
"-d",
- default="run",
+ default=_PipelineSelection.RUN,
show_default=True,
- type=click.Choice(["run", "build", "none"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.RUN, _PipelineSelection.BUILD, _PipelineSelection.NONE]),
help="The dependencies to checkout",
)
@click.option("--integrate/--no-integrate", default=True, help="Run integration commands (default is to run commands)")
@@ -1505,9 +1542,9 @@ def checkout(app, element, location, force, deps, integrate, hardlinks, tar):
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["none", "all"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.NONE, _PipelineSelection.ALL]),
help="The dependency artifacts to pull",
)
@click.option("--remote", "-r", help="The URL of the remote cache (defaults to the first configured cache)")
@@ -1525,9 +1562,9 @@ def pull(app, elements, deps, remote):
@click.option(
"--deps",
"-d",
- default="none",
+ default=_PipelineSelection.NONE,
show_default=True,
- type=click.Choice(["none", "all"]),
+ type=FastEnumType(_PipelineSelection, [_PipelineSelection.NONE, _PipelineSelection.ALL]),
help="The dependencies to push",
)
@click.option(
diff --git a/src/buildstream/_pipeline.py b/src/buildstream/_pipeline.py
index aee0c55da..353a9c3a0 100644
--- a/src/buildstream/_pipeline.py
+++ b/src/buildstream/_pipeline.py
@@ -31,36 +31,7 @@ from ._message import Message, MessageType
from ._profile import Topics, PROFILER
from . import Scope, Consistency
from ._project import ProjectRefStorage
-
-
-# PipelineSelection()
-#
-# Defines the kind of pipeline selection to make when the pipeline
-# is provided a list of targets, for whichever purpose.
-#
-# These values correspond to the CLI `--deps` arguments for convenience.
-#
-class PipelineSelection:
-
- # Select only the target elements in the associated targets
- NONE = "none"
-
- # As NONE, but redirect elements that are capable of it
- REDIRECT = "redirect"
-
- # Select elements which must be built for the associated targets to be built
- PLAN = "plan"
-
- # All dependencies of all targets, including the targets
- ALL = "all"
-
- # All direct build dependencies and their recursive runtime dependencies,
- # excluding the targets
- BUILD = "build"
-
- # All direct runtime dependencies and their recursive runtime dependencies,
- # including the targets
- RUN = "run"
+from .types import _PipelineSelection
# Pipeline()
@@ -219,18 +190,14 @@ class Pipeline:
#
# Args:
# targets (list of Element): The target Elements
- # mode (PipelineSelection): The PipelineSelection mode
+ # mode (_PipelineSelection): The PipelineSelection mode
#
# Various commands define a --deps option to specify what elements to
# use in the result, this function reports a list that is appropriate for
# the selected option.
#
def get_selection(self, targets, mode, *, silent=True):
-
- elements = None
- if mode == PipelineSelection.NONE:
- elements = targets
- elif mode == PipelineSelection.REDIRECT:
+ def redirect_and_log():
# Redirect and log if permitted
elements = []
for t in targets:
@@ -239,19 +206,21 @@ class Pipeline:
self._message(MessageType.INFO, "Element '{}' redirected to '{}'".format(t.name, new_elm.name))
if new_elm not in elements:
elements.append(new_elm)
- elif mode == PipelineSelection.PLAN:
- elements = self.plan(targets)
- else:
- if mode == PipelineSelection.ALL:
- scope = Scope.ALL
- elif mode == PipelineSelection.BUILD:
- scope = Scope.BUILD
- elif mode == PipelineSelection.RUN:
- scope = Scope.RUN
-
- elements = list(self.dependencies(targets, scope))
+ return elements
- return elements
+ # Work around python not having a switch statement; this is
+ # much clearer than the if/elif/else block we used to have.
+ #
+ # Note that the lambda is necessary so that we don't evaluate
+ # all possible values at run time; that would be slow.
+ return {
+ _PipelineSelection.NONE: lambda: targets,
+ _PipelineSelection.REDIRECT: redirect_and_log,
+ _PipelineSelection.PLAN: lambda: self.plan(targets),
+ _PipelineSelection.ALL: lambda: list(self.dependencies(targets, Scope.ALL)),
+ _PipelineSelection.BUILD: lambda: list(self.dependencies(targets, Scope.BUILD)),
+ _PipelineSelection.RUN: lambda: list(self.dependencies(targets, Scope.RUN)),
+ }[mode]()
# except_elements():
#
diff --git a/src/buildstream/_stream.py b/src/buildstream/_stream.py
index c2945a2f6..db9794c45 100644
--- a/src/buildstream/_stream.py
+++ b/src/buildstream/_stream.py
@@ -48,10 +48,10 @@ from ._scheduler import (
JobStatus,
)
from .element import Element
-from ._pipeline import Pipeline, PipelineSelection
+from ._pipeline import Pipeline
from ._profile import Topics, PROFILER
from ._state import State
-from .types import _KeyStrength, _SchedulerErrorAction
+from .types import _KeyStrength, _PipelineSelection, _SchedulerErrorAction
from .plugin import Plugin
from . import utils, _yaml, _site
from . import Scope
@@ -143,7 +143,7 @@ class Stream:
#
# Args:
# targets (list of str): Targets to pull
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# except_targets (list of str): Specified targets to except from fetching
# use_artifact_config (bool): If artifact remote configs should be loaded
#
@@ -153,7 +153,7 @@ class Stream:
self,
targets,
*,
- selection=PipelineSelection.NONE,
+ selection=_PipelineSelection.NONE,
except_targets=(),
use_artifact_config=False,
load_refs=False
@@ -267,14 +267,14 @@ class Stream:
#
# Args:
# targets (list of str): Targets to build
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# ignore_junction_targets (bool): Whether junction targets should be filtered out
# remote (str): The URL of a specific remote server to push to, or None
#
# If `remote` specified as None, then regular configuration will be used
# to determine where to push artifacts to.
#
- def build(self, targets, *, selection=PipelineSelection.PLAN, ignore_junction_targets=False, remote=None):
+ def build(self, targets, *, selection=_PipelineSelection.PLAN, ignore_junction_targets=False, remote=None):
use_config = True
if remote:
@@ -300,7 +300,7 @@ class Stream:
# fetch blobs of targets if options set
if self._context.pull_artifact_files:
- scope = Scope.ALL if selection == PipelineSelection.ALL else Scope.RUN
+ scope = Scope.ALL if selection == _PipelineSelection.ALL else Scope.RUN
for element in self.targets:
element._set_artifact_files_required(scope=scope)
@@ -331,11 +331,11 @@ class Stream:
#
# Args:
# targets (list of str): Targets to fetch
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# except_targets (list of str): Specified targets to except from fetching
# remote (str|None): The URL of a specific remote server to pull from.
#
- def fetch(self, targets, *, selection=PipelineSelection.PLAN, except_targets=None, remote=None):
+ def fetch(self, targets, *, selection=_PipelineSelection.PLAN, except_targets=None, remote=None):
use_source_config = True
if remote:
@@ -358,14 +358,14 @@ class Stream:
#
# Args:
# targets (list of str): Targets to track
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# except_targets (list of str): Specified targets to except from tracking
# cross_junctions (bool): Whether tracking should cross junction boundaries
#
# If no error is encountered while tracking, then the project files
# are rewritten inline.
#
- def track(self, targets, *, selection=PipelineSelection.REDIRECT, except_targets=None, cross_junctions=False):
+ def track(self, targets, *, selection=_PipelineSelection.REDIRECT, except_targets=None, cross_junctions=False):
elements = self._load_tracking(
targets, selection=selection, except_targets=except_targets, cross_junctions=cross_junctions
@@ -389,14 +389,14 @@ class Stream:
#
# Args:
# targets (list of str): Targets to pull
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# ignore_junction_targets (bool): Whether junction targets should be filtered out
# remote (str): The URL of a specific remote server to pull from, or None
#
# If `remote` specified as None, then regular configuration will be used
# to determine where to pull artifacts from.
#
- def pull(self, targets, *, selection=PipelineSelection.NONE, ignore_junction_targets=False, remote=None):
+ def pull(self, targets, *, selection=_PipelineSelection.NONE, ignore_junction_targets=False, remote=None):
use_config = True
if remote:
@@ -426,7 +426,7 @@ class Stream:
#
# Args:
# targets (list of str): Targets to push
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# ignore_junction_targets (bool): Whether junction targets should be filtered out
# remote (str): The URL of a specific remote server to push to, or None
#
@@ -437,7 +437,7 @@ class Stream:
# a pull queue will be created if user context and available remotes allow for
# attempting to fetch them.
#
- def push(self, targets, *, selection=PipelineSelection.NONE, ignore_junction_targets=False, remote=None):
+ def push(self, targets, *, selection=_PipelineSelection.NONE, ignore_junction_targets=False, remote=None):
use_config = True
if remote:
@@ -509,7 +509,7 @@ class Stream:
# target (str): Target to checkout
# location (str): Location to checkout the artifact to
# force (bool): Whether files can be overwritten if necessary
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# integrate (bool): Whether to run integration commands
# hardlinks (bool): Whether checking out files hardlinked to
# their artifacts is acceptable
@@ -527,7 +527,7 @@ class Stream:
*,
location=None,
force=False,
- selection=PipelineSelection.RUN,
+ selection=_PipelineSelection.RUN,
integrate=True,
hardlinks=False,
compression="",
@@ -554,7 +554,12 @@ class Stream:
self._run()
try:
- scope = {"run": Scope.RUN, "build": Scope.BUILD, "none": Scope.NONE, "all": Scope.ALL}
+ scope = {
+ _PipelineSelection.RUN: Scope.RUN,
+ _PipelineSelection.BUILD: Scope.BUILD,
+ _PipelineSelection.NONE: Scope.NONE,
+ _PipelineSelection.ALL: Scope.ALL,
+ }
with target._prepare_sandbox(scope=scope[selection], directory=None, integrate=integrate) as sandbox:
# Copy or move the sandbox to the target directory
virdir = sandbox.get_virtual_directory()
@@ -612,7 +617,7 @@ class Stream:
# Args:
# targets (str): Targets to show the cached state of
#
- def artifact_show(self, targets, *, selection=PipelineSelection.NONE):
+ def artifact_show(self, targets, *, selection=_PipelineSelection.NONE):
# Obtain list of Element and/or ArtifactElement objects
target_objects = self.load_selection(targets, selection=selection, use_artifact_config=True, load_refs=True)
@@ -639,7 +644,7 @@ class Stream:
#
def artifact_log(self, targets):
# Return list of Element and/or ArtifactElement objects
- target_objects = self.load_selection(targets, selection=PipelineSelection.NONE, load_refs=True)
+ target_objects = self.load_selection(targets, selection=_PipelineSelection.NONE, load_refs=True)
artifact_logs = {}
for obj in target_objects:
@@ -667,7 +672,7 @@ class Stream:
#
def artifact_list_contents(self, targets):
# Return list of Element and/or ArtifactElement objects
- target_objects = self.load_selection(targets, selection=PipelineSelection.NONE, load_refs=True)
+ target_objects = self.load_selection(targets, selection=_PipelineSelection.NONE, load_refs=True)
elements_to_files = {}
for obj in target_objects:
@@ -689,7 +694,7 @@ class Stream:
# Args:
# targets (str): Targets to remove
#
- def artifact_delete(self, targets, *, selection=PipelineSelection.NONE):
+ def artifact_delete(self, targets, *, selection=_PipelineSelection.NONE):
# Return list of Element and/or ArtifactElement objects
target_objects = self.load_selection(targets, selection=selection, load_refs=True)
@@ -773,7 +778,7 @@ class Stream:
def workspace_open(self, targets, *, no_checkout, force, custom_dir):
# This function is a little funny but it is trying to be as atomic as possible.
- elements = self._load(targets, selection=PipelineSelection.REDIRECT)
+ elements = self._load(targets, selection=_PipelineSelection.REDIRECT)
workspaces = self._context.get_workspaces()
@@ -910,7 +915,7 @@ class Stream:
#
def workspace_reset(self, targets, *, soft):
- elements = self._load(targets, selection=PipelineSelection.REDIRECT)
+ elements = self._load(targets, selection=_PipelineSelection.REDIRECT)
nonexisting = []
for element in elements:
@@ -1013,7 +1018,7 @@ class Stream:
else:
output_elements.add(e)
if load_elements:
- loaded_elements = self._load(load_elements, selection=PipelineSelection.REDIRECT)
+ loaded_elements = self._load(load_elements, selection=_PipelineSelection.REDIRECT)
for e in loaded_elements:
output_elements.add(e.name)
@@ -1183,16 +1188,16 @@ class Stream:
#
# Args:
# targets (list of str): Targets to load
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# except_targets (list of str): Specified targets to except
# cross_junctions (bool): Whether tracking should cross junction boundaries
#
# Returns:
# (list of Element): The tracking element selection
#
- def _load_tracking(self, targets, *, selection=PipelineSelection.NONE, except_targets=(), cross_junctions=False):
+ def _load_tracking(self, targets, *, selection=_PipelineSelection.NONE, except_targets=(), cross_junctions=False):
# We never want to use a PLAN selection when tracking elements
- assert selection != PipelineSelection.PLAN
+ assert selection != _PipelineSelection.PLAN
elements, except_elements, artifacts = self.__load_elements_from_targets(
targets, except_targets, rewritable=True
@@ -1234,7 +1239,7 @@ class Stream:
#
# Args:
# targets (list of str): Main targets to load
- # selection (PipelineSelection): The selection mode for the specified targets
+ # selection (_PipelineSelection): The selection mode for the specified targets
# except_targets (list of str): Specified targets to except from fetching
# ignore_junction_targets (bool): Whether junction targets should be filtered out
# use_artifact_config (bool): Whether to initialize artifacts with the config
@@ -1249,7 +1254,7 @@ class Stream:
self,
targets,
*,
- selection=PipelineSelection.NONE,
+ selection=_PipelineSelection.NONE,
except_targets=(),
ignore_junction_targets=False,
use_artifact_config=False,
@@ -1267,8 +1272,8 @@ class Stream:
if not load_refs:
detail = "\n".join(artifact.get_artifact_name() for artifact in artifacts)
raise ArtifactElementError("Cannot perform this operation with artifact refs:", detail=detail)
- if selection in (PipelineSelection.ALL, PipelineSelection.RUN):
- raise StreamError("Error: '--deps {}' is not supported for artifact refs".format(selection))
+ if selection in (_PipelineSelection.ALL, _PipelineSelection.RUN):
+ raise StreamError("Error: '--deps {}' is not supported for artifact refs".format(selection.value))
if ignore_junction_targets:
elements = [e for e in elements if e.get_kind() != "junction"]
@@ -1285,7 +1290,7 @@ class Stream:
selected = self._pipeline.get_selection(self.targets, selection, silent=False)
selected = self._pipeline.except_elements(self.targets, selected, except_elements)
- if selection == PipelineSelection.PLAN and dynamic_plan:
+ if selection == _PipelineSelection.PLAN and dynamic_plan:
# We use a dynamic build plan, only request artifacts of top-level targets,
# others are requested dynamically as needed.
# This avoids pulling, fetching, or building unneeded build-only dependencies.
diff --git a/src/buildstream/types.py b/src/buildstream/types.py
index 180044dbd..0e596bddb 100644
--- a/src/buildstream/types.py
+++ b/src/buildstream/types.py
@@ -230,6 +230,36 @@ class _CacheBuildTrees(FastEnum):
NEVER = "never"
+# _PipelineSelection()
+#
+# Defines the kind of pipeline selection to make when the pipeline
+# is provided a list of targets, for whichever purpose.
+#
+# These values correspond to the CLI `--deps` arguments for convenience.
+#
+class _PipelineSelection(FastEnum):
+
+ # Select only the target elements in the associated targets
+ NONE = "none"
+
+ # As NONE, but redirect elements that are capable of it
+ REDIRECT = "redirect"
+
+ # Select elements which must be built for the associated targets to be built
+ PLAN = "plan"
+
+ # All dependencies of all targets, including the targets
+ ALL = "all"
+
+ # All direct build dependencies and their recursive runtime dependencies,
+ # excluding the targets
+ BUILD = "build"
+
+ # All direct runtime dependencies and their recursive runtime dependencies,
+ # including the targets
+ RUN = "run"
+
+
########################################
# Type aliases #
########################################