summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Maw <jonathan.maw@codethink.co.uk>2018-11-08 18:16:20 +0000
committerJonathan Maw <jonathan.maw@codethink.co.uk>2018-12-11 12:56:32 +0000
commitf145a3e4c66017ab5b2de492c4d6de538d4ec224 (patch)
treee4e86bfd63f68eb8006a3eb4ec2b337558cb55d7
parent921f2bcbd6bc050c77a6099d9b90705953f93622 (diff)
downloadbuildstream-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.py7
-rw-r--r--buildstream/_frontend/cli.py10
-rw-r--r--buildstream/_stream.py14
-rw-r--r--buildstream/data/userconfig.yaml8
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.
#