From e4f6dadfad7ecb0b9a832e1626f3a87073d8f66a Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Tue, 24 Jan 2023 12:46:59 +0100 Subject: [PATCH] workspace: add a root subcommand to print the workspace root path --- CHANGELOG.md | 2 ++ docs/working-copy.md | 3 ++- src/commands/mod.rs | 26 ++++++++++++++++++++++++++ tests/test_workspaces.rs | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 321aac55a..ce9a12bc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 by a "␛" character. That prevents them from interfering with the ANSI escapes jj itself writes. +* `jj workspace root` prints the root path of the current workspace. + ### Fixed bugs * When sharing the working copy with a Git repo, we used to forget to export diff --git a/docs/working-copy.md b/docs/working-copy.md index 103d84f9a..d7e412ffc 100644 --- a/docs/working-copy.md +++ b/docs/working-copy.md @@ -70,7 +70,8 @@ directory together is called a "workspace". Each workspace can have a different commit checked out. Having multiple workspaces can be useful for running long-running tests in a one -while you continue developing in another, for example. +while you continue developing in another, for example. If needed, +`jj workspace root` prints the root path of the current workspace. When you're done using a workspace, use `jj workspace forget` to make the repo forget about it. The files can be deleted from disk separately (either before or diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 015c4d5d9..f0405f9b1 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -743,6 +743,7 @@ enum WorkspaceCommands { Add(WorkspaceAddArgs), Forget(WorkspaceForgetArgs), List(WorkspaceListArgs), + Root(WorkspaceRootArgs), UpdateStale(WorkspaceUpdateStaleArgs), } @@ -773,6 +774,10 @@ struct WorkspaceForgetArgs { #[derive(clap::Args, Clone, Debug)] struct WorkspaceListArgs {} +/// Show the current workspace root directory +#[derive(clap::Args, Clone, Debug)] +struct WorkspaceRootArgs {} + /// Update a workspace that has become stale /// /// For information about stale working copies, see @@ -3013,6 +3018,9 @@ fn cmd_workspace( WorkspaceCommands::List(command_matches) => { cmd_workspace_list(ui, command, command_matches) } + WorkspaceCommands::Root(command_matches) => { + cmd_workspace_root(ui, command, command_matches) + } WorkspaceCommands::UpdateStale(command_matches) => { cmd_workspace_update_stale(ui, command, command_matches) } @@ -3142,6 +3150,24 @@ fn cmd_workspace_list( Ok(()) } +fn cmd_workspace_root( + ui: &mut Ui, + command: &CommandHelper, + _args: &WorkspaceRootArgs, +) -> Result<(), CommandError> { + let workspace_command = command.workspace_helper(ui)?; + let root = + workspace_command + .workspace_root() + .to_str() + .ok_or_else(|| CommandError::UserError { + message: String::from("The workspace root is not valid UTF-8"), + hint: None, + })?; + writeln!(ui, "{root}")?; + Ok(()) +} + fn cmd_workspace_update_stale( ui: &mut Ui, command: &CommandHelper, diff --git a/tests/test_workspaces.rs b/tests/test_workspaces.rs index c42cf6994..97994b59a 100644 --- a/tests/test_workspaces.rs +++ b/tests/test_workspaces.rs @@ -244,6 +244,41 @@ fn test_list_workspaces_template() { "###); } +/// Test getting the workspace root from primary and secondary workspaces +#[test] +fn test_workspaces_root() { + let test_env = TestEnvironment::default(); + test_env.jj_cmd_success(test_env.env_root(), &["init", "--git", "main"]); + let main_path = test_env.env_root().join("main"); + let secondary_path = test_env.env_root().join("secondary"); + + let stdout = test_env.jj_cmd_success(&main_path, &["workspace", "root"]); + insta::assert_snapshot!(stdout, @r###" + $TEST_ENV/main + "###); + let main_subdir_path = main_path.join("subdir"); + std::fs::create_dir(&main_subdir_path).unwrap(); + let stdout = test_env.jj_cmd_success(&main_subdir_path, &["workspace", "root"]); + insta::assert_snapshot!(stdout, @r###" + $TEST_ENV/main + "###); + + test_env.jj_cmd_success( + &main_path, + &["workspace", "add", "--name", "secondary", "../secondary"], + ); + let stdout = test_env.jj_cmd_success(&secondary_path, &["workspace", "root"]); + insta::assert_snapshot!(stdout, @r###" + $TEST_ENV/secondary + "###); + let secondary_subdir_path = secondary_path.join("subdir"); + std::fs::create_dir(&secondary_subdir_path).unwrap(); + let stdout = test_env.jj_cmd_success(&secondary_subdir_path, &["workspace", "root"]); + insta::assert_snapshot!(stdout, @r###" + $TEST_ENV/secondary + "###); +} + fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String { test_env.jj_cmd_success( cwd,