diff options
author | Jonathan Maw <jonathan.maw@codethink.co.uk> | 2018-11-08 18:16:20 +0000 |
---|---|---|
committer | Jonathan Maw <jonathan.maw@codethink.co.uk> | 2018-12-11 12:56:32 +0000 |
commit | f145a3e4c66017ab5b2de492c4d6de538d4ec224 (patch) | |
tree | e4e86bfd63f68eb8006a3eb4ec2b337558cb55d7 | |
parent | 921f2bcbd6bc050c77a6099d9b90705953f93622 (diff) | |
download | buildstream-f145a3e4c66017ab5b2de492c4d6de538d4ec224.tar.gz |
cli: Interactively warn if the user is trying to close the workspace they're using to load the project
This involves changes in:
* _stream.py:
* Add the helper Stream.workspace_is_required()
* userconfig.yaml:
* Add a default value for prompt.really-workspace-close-project-inaccessible
* _context.py:
* Load the prompt 'really-workspace-close-project-inaccessible' from
user config.
* cli.py:
* If buildstream is invoked interactively, prompt the user to confirm
that they want to close the workspace they're using to load this
project.
This is a part of #222
-rw-r--r-- | buildstream/_context.py | 7 | ||||
-rw-r--r-- | buildstream/_frontend/cli.py | 10 | ||||
-rw-r--r-- | buildstream/_stream.py | 14 | ||||
-rw-r--r-- | buildstream/data/userconfig.yaml | 8 |
4 files changed, 38 insertions, 1 deletions
diff --git a/buildstream/_context.py b/buildstream/_context.py index 55d0fd489..5211fe54d 100644 --- a/buildstream/_context.py +++ b/buildstream/_context.py @@ -122,6 +122,10 @@ class Context(): # remove a workspace directory. self.prompt_workspace_close_remove_dir = None + # Boolean, whether we double-check with the user that they meant to + # close the workspace when they're using it to access the project. + self.prompt_workspace_close_project_inaccessible = None + # Boolean, whether we double-check with the user that they meant to do # a hard reset of a workspace, potentially losing changes. self.prompt_workspace_reset_hard = None @@ -251,12 +255,15 @@ class Context(): defaults, Mapping, 'prompt') _yaml.node_validate(prompt, [ 'auto-init', 'really-workspace-close-remove-dir', + 'really-workspace-close-project-inaccessible', 'really-workspace-reset-hard', ]) self.prompt_auto_init = _node_get_option_str( prompt, 'auto-init', ['ask', 'no']) == 'ask' self.prompt_workspace_close_remove_dir = _node_get_option_str( prompt, 'really-workspace-close-remove-dir', ['ask', 'yes']) == 'ask' + self.prompt_workspace_close_project_inaccessible = _node_get_option_str( + prompt, 'really-workspace-close-project-inaccessible', ['ask', 'yes']) == 'ask' self.prompt_workspace_reset_hard = _node_get_option_str( prompt, 'really-workspace-reset-hard', ['ask', 'yes']) == 'ask' diff --git a/buildstream/_frontend/cli.py b/buildstream/_frontend/cli.py index b2ad1e8a4..e1fab38a0 100644 --- a/buildstream/_frontend/cli.py +++ b/buildstream/_frontend/cli.py @@ -763,11 +763,19 @@ def workspace_close(app, remove_dir, all_, elements): elements = app.stream.redirect_element_names(elements) - # Check that the workspaces in question exist + # Check that the workspaces in question exist, and that it's safe to + # remove them. nonexisting = [] for element_name in elements: if not app.stream.workspace_exists(element_name): nonexisting.append(element_name) + if (app.stream.workspace_is_required(element_name) and app.interactive and + app.context.prompt_workspace_close_project_inaccessible): + click.echo("Removing '{}' will prevent you from running " + "BuildStream commands from the current directory".format(element_name)) + if not click.confirm('Are you sure you want to close this workspace?'): + click.echo('Aborting', err=True) + sys.exit(-1) if nonexisting: raise AppError("Workspace does not exist", detail="\n".join(nonexisting)) diff --git a/buildstream/_stream.py b/buildstream/_stream.py index 3256003c8..6d4af1e79 100644 --- a/buildstream/_stream.py +++ b/buildstream/_stream.py @@ -696,6 +696,20 @@ class Stream(): return False + # workspace_is_required() + # + # Checks whether the workspace belonging to element_name is required to + # load the project + # + # Args: + # element_name (str): The element whose workspace may be required + # + # Returns: + # (bool): True if the workspace is required + def workspace_is_required(self, element_name): + invoked_elm = self._project.invoked_from_workspace_element() + return invoked_elm == element_name + # workspace_list # # Serializes the workspaces and dumps them in YAML to stdout. diff --git a/buildstream/data/userconfig.yaml b/buildstream/data/userconfig.yaml index e81961c53..4429d1f6d 100644 --- a/buildstream/data/userconfig.yaml +++ b/buildstream/data/userconfig.yaml @@ -128,6 +128,14 @@ prompt: # really-workspace-close-remove-dir: ask + # Whether to really proceed with 'bst workspace close' when doing so would + # stop them from running bst commands in this workspace. + # + # ask - Ask the user if they are sure. + # yes - Always close, without asking. + # + really-workspace-close-project-inaccessible: ask + # Whether to really proceed with 'bst workspace reset' doing a hard reset of # a workspace, potentially losing changes. # |