diff --git a/src/buildstream/_frontend/cli.py b/src/buildstream/_frontend/cli.py index e9e6ddfb9..02ea0272f 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 -a 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..25384330c 100644 --- a/tests/frontend/workspace.py +++ b/tests/frontend/workspace.py @@ -634,6 +634,49 @@ 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) +def test_reset_all_with_elements_error(cli, tmpdir, datafiles): + # 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'") + + # Reset with --all and elements should fail + result = cli.run(project=project, args=["workspace", "reset", "--all", element_name]) + 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_reset_en_dash_soft_all_error(cli, tmpdir, datafiles): + # 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'") + + # Reset with en-dash-soft (copy-pasted from docs) should be treated as element + # and combined with --all should error + result = cli.run(project=project, args=["workspace", "reset", "\u2013-soft", "--all"]) + 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")