diff --git a/src/buildstream/_frontend/cli.py b/src/buildstream/_frontend/cli.py index e9e6ddfb9..ff921d9ef 100644 --- a/src/buildstream/_frontend/cli.py +++ b/src/buildstream/_frontend/cli.py @@ -1211,15 +1211,22 @@ def workspace_close(app, remove_dir, all_, elements): is_flag=True, help="Mark workspace to re-execute configuration steps (if any) on next build. Does not alter workspace contents.", ) -@click.option("--all", "-a", "all_", is_flag=True, help="Reset all open workspaces") +@click.option("--all", "-a", "all_", is_flag=True, help="Reset all open workspaces. Cannot be combined with ELEMENTS.") @click.argument("elements", nargs=-1, type=click.Path(readable=False)) @click.pass_obj def workspace_reset(app, soft, all_, elements): - """Reset a workspace to its original state""" + """Reset a workspace to its original state. + + Specify either one or more ELEMENTS, or use ``--all`` to target all + workspaces at once. These options are mutually exclusive. + """ # Check that the workspaces in question exist with app.initialized(): + if all_ and elements: + raise AppError("Specify either --all or elements, not both") + if not (all_ or elements): element = app.stream.get_default_target() if element: diff --git a/tests/frontend/workspace.py b/tests/frontend/workspace.py index e243dec54..e244c6005 100644 --- a/tests/frontend/workspace.py +++ b/tests/frontend/workspace.py @@ -634,6 +634,41 @@ def test_reset_all(cli, tmpdir, datafiles): assert not os.path.exists(os.path.join(workspace_beta, "etc", "pony.conf")) +@pytest.mark.datafiles(DATA_DIR) +@pytest.mark.parametrize( + "element_arg", + [ + "element_name", # actual element + "\u2013-soft", # en-dash soft (copy-pasted from docs) + ], + ids=["real-element", "en-dash-soft"], +) +def test_reset_all_with_elements_error(cli, tmpdir, datafiles, element_arg): + # Open a workspace + tmpdir_alpha = os.path.join(str(tmpdir), "alpha") + element_name, project, workspace = open_workspace(cli, tmpdir_alpha, datafiles, "tar", suffix="-alpha") + + # Modify workspace + shutil.rmtree(os.path.join(workspace, "usr", "bin")) + os.makedirs(os.path.join(workspace, "etc")) + with open(os.path.join(workspace, "etc", "pony.conf"), "w", encoding="utf-8") as f: + f.write("PONY='pink'") + + # Resolve the argument: if it's the literal "element_name", use the real one + if element_arg == "element_name": + args = ["workspace", "reset", "--all", element_name] + else: + args = ["workspace", "reset", element_arg, "--all"] + + # Reset with --all and elements should fail + result = cli.run(project=project, args=args) + result.assert_main_error(ErrorDomain.APP, None) + + # Verify workspace content was NOT modified + assert not os.path.exists(os.path.join(workspace, "usr", "bin", "hello")) + assert os.path.exists(os.path.join(workspace, "etc", "pony.conf")) + + @pytest.mark.datafiles(DATA_DIR) def test_list(cli, tmpdir, datafiles): element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, "tar")