diff options
author | Jürg Billeter <j@bitron.ch> | 2019-01-21 13:58:55 +0100 |
---|---|---|
committer | Jürg Billeter <j@bitron.ch> | 2019-01-24 14:37:28 +0100 |
commit | ab72d384a0b79b55543e1e7facd00f4778bbc780 (patch) | |
tree | c930e804572f646c13bd94d7aa926848930e355c | |
parent | 3850274b423fff404ed3acaf1a21f271b07c6a08 (diff) | |
download | buildstream-ab72d384a0b79b55543e1e7facd00f4778bbc780.tar.gz |
_project.py: Add get_default_target() and get_default_targets() methods
_frontend/cli.py: Use new methods.
Based on patches by Phillip Smyth.
-rw-r--r-- | buildstream/_context.py | 16 | ||||
-rw-r--r-- | buildstream/_frontend/cli.py | 93 | ||||
-rw-r--r-- | buildstream/_project.py | 47 |
3 files changed, 115 insertions, 41 deletions
diff --git a/buildstream/_context.py b/buildstream/_context.py index 8b9f47bd6..f14f6b746 100644 --- a/buildstream/_context.py +++ b/buildstream/_context.py @@ -32,7 +32,7 @@ from ._message import Message, MessageType from ._profile import Topics, profile_start, profile_end from ._artifactcache import ArtifactCache from ._cas import CASCache -from ._workspaces import Workspaces, WorkspaceProjectCache, WORKSPACE_PROJECT_FILE +from ._workspaces import Workspaces, WorkspaceProjectCache from .plugin import _plugin_lookup from .sandbox import SandboxRemote @@ -657,20 +657,6 @@ class Context(): self._cascache = CASCache(self.artifactdir) return self._cascache - # guess_element() - # - # Attempts to interpret which element the user intended to run commands on - # - # Returns: - # (str) The name of the element, or None if no element can be guessed - def guess_element(self): - workspace_project_dir, _ = utils._search_upward_for_files(self._directory, [WORKSPACE_PROJECT_FILE]) - if workspace_project_dir: - workspace_project = self._workspace_project_cache.get(workspace_project_dir) - return workspace_project.get_default_element() - else: - return None - # _node_get_option_str() # diff --git a/buildstream/_frontend/cli.py b/buildstream/_frontend/cli.py index 36711e7fb..43b827f18 100644 --- a/buildstream/_frontend/cli.py +++ b/buildstream/_frontend/cli.py @@ -342,7 +342,15 @@ def init(app, project_name, format_version, element_path, force): type=click.Path(readable=False)) @click.pass_obj def build(app, elements, all_, track_, track_save, track_all, track_except, track_cross_junctions): - """Build elements in a pipeline""" + """Build elements in a pipeline + + Specifying no elements will result in building the default targets + of the project. If no default targets are configured, all project + elements will be built. + + When this command is executed from a workspace directory, the default + is to build the workspace element. + """ if (track_except or track_cross_junctions) and not (track_ or track_all): click.echo("ERROR: The --track-except and --track-cross-junctions options " @@ -354,9 +362,7 @@ def build(app, elements, all_, track_, track_save, track_all, track_except, trac with app.initialized(session_name="Build"): if not elements: - guessed_target = app.context.guess_element() - if guessed_target: - elements = (guessed_target,) + elements = app.project.get_default_targets() if track_all: track_ = elements @@ -390,6 +396,13 @@ def build(app, elements, all_, track_, track_save, track_all, track_except, trac def show(app, elements, deps, except_, order, format_): """Show elements in the pipeline + Specifying no elements will result in showing the default targets + of the project. If no default targets are configured, all project + elements will be shown. + + When this command is executed from a workspace directory, the default + is to show the workspace element. + By default this will show all of the dependencies of the specified target element. @@ -436,9 +449,7 @@ def show(app, elements, deps, except_, order, format_): """ with app.initialized(): if not elements: - guessed_target = app.context.guess_element() - if guessed_target: - elements = (guessed_target,) + elements = app.project.get_default_targets() dependencies = app.stream.load_selection(elements, selection=deps, @@ -478,6 +489,9 @@ def show(app, elements, deps, except_, order, format_): def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command): """Run a command in the target element's sandbox environment + When this command is executed from a workspace directory, the default + is to shell into the workspace element. + This will stage a temporary sysroot for running the target element, assuming it has already been built and all required artifacts are in the local cache. @@ -511,7 +525,7 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command) with app.initialized(): if not element: - element = app.context.guess_element() + element = app.project.get_default_target() if not element: raise AppError('Missing argument "ELEMENT".') @@ -581,6 +595,13 @@ def source(): def source_fetch(app, elements, deps, track_, except_, track_cross_junctions): """Fetch sources required to build the pipeline + Specifying no elements will result in fetching the default targets + of the project. If no default targets are configured, all project + elements will be fetched. + + When this command is executed from a workspace directory, the default + is to fetch the workspace element. + By default this will only try to fetch sources which are required for the build plan of the specified target element, omitting sources for any elements which are already built @@ -606,9 +627,7 @@ def source_fetch(app, elements, deps, track_, except_, track_cross_junctions): with app.initialized(session_name="Fetch"): if not elements: - guessed_target = app.context.guess_element() - if guessed_target: - elements = (guessed_target,) + elements = app.project.get_default_targets() app.stream.fetch(elements, selection=deps, @@ -636,6 +655,15 @@ def source_track(app, elements, deps, except_, cross_junctions): """Consults the specified tracking branches for new versions available to build and updates the project with any newly available references. + Specifying no elements will result in tracking the default targets + of the project. If no default targets are configured, all project + elements will be tracked. + + When this command is executed from a workspace directory, the default + is to track the workspace element. + + If no default is declared, all elements in the project will be tracked + By default this will track just the specified element, but you can also update a whole tree of dependencies in one go. @@ -647,9 +675,7 @@ def source_track(app, elements, deps, except_, cross_junctions): """ with app.initialized(session_name="Track"): if not elements: - guessed_target = app.context.guess_element() - if guessed_target: - elements = (guessed_target,) + elements = app.project.get_default_targets() # Substitute 'none' for 'redirect' so that element redirections # will be done @@ -685,6 +711,9 @@ def source_track(app, elements, deps, except_, cross_junctions): def source_checkout(app, element, location, force, deps, fetch_, except_, tar, build_scripts): """Checkout sources of an element to the specified location + + When this command is executed from a workspace directory, the default + is to checkout the sources of the workspace element. """ if not element and not location: click.echo("ERROR: LOCATION is not specified", err=True) @@ -697,7 +726,7 @@ def source_checkout(app, element, location, force, deps, fetch_, except_, with app.initialized(): if not element: - element = app.context.guess_element() + element = app.project.get_default_target() if not element: raise AppError('Missing argument "ELEMENT".') @@ -763,7 +792,7 @@ def workspace_close(app, remove_dir, all_, elements): if not (all_ or elements): # NOTE: I may need to revisit this when implementing multiple projects # opening one workspace. - element = app.context.guess_element() + element = app.project.get_default_target() if element: elements = (element,) else: @@ -824,7 +853,7 @@ def workspace_reset(app, soft, track_, all_, elements): with app.initialized(): if not (all_ or elements): - element = app.context.guess_element() + element = app.project.get_default_target() if element: elements = (element,) else: @@ -921,7 +950,11 @@ def artifact(): type=click.Path(readable=False)) @click.pass_obj def artifact_checkout(app, force, deps, integrate, hardlinks, tar, directory, element): - """Checkout contents of an artifact""" + """Checkout contents of an artifact + + When this command is executed from a workspace directory, the default + is to checkout the artifact of the workspace element. + """ from ..element import Scope if hardlinks and tar is not None: @@ -952,7 +985,7 @@ def artifact_checkout(app, force, deps, integrate, hardlinks, tar, directory, el with app.initialized(): if not element: - element = app.context.guess_element() + element = app.project.get_default_target() if not element: raise AppError('Missing argument "ELEMENT".') @@ -980,6 +1013,13 @@ def artifact_checkout(app, force, deps, integrate, hardlinks, tar, directory, el def artifact_pull(app, elements, deps, remote): """Pull a built artifact from the configured remote artifact cache. + Specifying no elements will result in pulling the default targets + of the project. If no default targets are configured, all project + elements will be pulled. + + When this command is executed from a workspace directory, the default + is to pull the workspace element. + By default the artifact will be pulled one of the configured caches if possible, following the usual priority order. If the `--remote` flag is given, only the specified cache will be queried. @@ -993,9 +1033,7 @@ def artifact_pull(app, elements, deps, remote): with app.initialized(session_name="Pull"): if not elements: - guessed_target = app.context.guess_element() - if guessed_target: - elements = (guessed_target,) + elements = app.project.get_default_targets() app.stream.pull(elements, selection=deps, remote=remote) @@ -1015,6 +1053,13 @@ def artifact_pull(app, elements, deps, remote): def artifact_push(app, elements, deps, remote): """Push a built artifact to a remote artifact cache. + Specifying no elements will result in pushing the default targets + of the project. If no default targets are configured, all project + elements will be pushed. + + When this command is executed from a workspace directory, the default + is to push the workspace element. + The default destination is the highest priority configured cache. You can override this by passing a different cache URL with the `--remote` flag. @@ -1030,9 +1075,7 @@ def artifact_push(app, elements, deps, remote): """ with app.initialized(session_name="Push"): if not elements: - guessed_target = app.context.guess_element() - if guessed_target: - elements = (guessed_target,) + elements = app.project.get_default_targets() app.stream.push(elements, selection=deps, remote=remote) diff --git a/buildstream/_project.py b/buildstream/_project.py index 1492fde77..3ec141d58 100644 --- a/buildstream/_project.py +++ b/buildstream/_project.py @@ -104,6 +104,9 @@ class Project(): # Absolute path to where elements are loaded from within the project self.element_path = None + # Default target elements + self._default_targets = None + # ProjectRefs for the main refs and also for junctions self.refs = ProjectRefs(self.directory, 'project.refs') self.junction_refs = ProjectRefs(self.directory, 'junction.refs') @@ -228,7 +231,7 @@ class Project(): 'element-path', 'variables', 'environment', 'environment-nocache', 'split-rules', 'elements', 'plugins', - 'aliases', 'name', + 'aliases', 'name', 'defaults', 'artifacts', 'options', 'fail-on-overlap', 'shell', 'fatal-warnings', 'ref-storage', 'sandbox', 'mirrors', 'remote-execution', @@ -391,6 +394,44 @@ class Project(): # Reset the element loader state Element._reset_load_state() + # get_default_target() + # + # Attempts to interpret which element the user intended to run a command on. + # This is for commands that only accept a single target element and thus, + # this only uses the workspace element (if invoked from workspace directory) + # and does not use the project default targets. + # + def get_default_target(self): + return self._invoked_from_workspace_element + + # get_default_targets() + # + # Attempts to interpret which elements the user intended to run a command on. + # This is for commands that accept multiple target elements. + # + def get_default_targets(self): + + # If _invoked_from_workspace_element has a value, + # a workspace element was found before a project config + # Therefore the workspace does not contain a project + if self._invoked_from_workspace_element: + return (self._invoked_from_workspace_element,) + + # Default targets from project configuration + if self._default_targets: + return tuple(self._default_targets) + + # If default targets are not configured, default to all project elements + default_targets = [] + for root, _, files in os.walk(self.element_path): + for file in files: + if file.endswith(".bst"): + rel_dir = os.path.relpath(root, self.element_path) + rel_file = os.path.join(rel_dir, file).lstrip("./") + default_targets.append(rel_file) + + return tuple(default_targets) + # _load(): # # Loads the project configuration file in the project @@ -456,6 +497,10 @@ class Project(): self.config.options = OptionPool(self.element_path) self.first_pass_config.options = OptionPool(self.element_path) + defaults = _yaml.node_get(pre_config_node, Mapping, 'defaults') + _yaml.node_validate(defaults, ['targets']) + self._default_targets = _yaml.node_get(defaults, list, "targets") + # Fatal warnings self._fatal_warnings = _yaml.node_get(pre_config_node, list, 'fatal-warnings', default_value=[]) |