forked from mirrors/jj
workspace: workspace forget
multiple names at once
Summary: This allows `workspace forget` to forget multiple workspaces in a single action; it now behaves more consistently with other verbs like `abandon` which can take multiple revisions at one time. There's some hoop-jumping involved to ensure the oplog transaction description looks nice, but as they say: small conveniences cost a lot. Signed-off-by: Austin Seipp <aseipp@pobox.com> Change-Id: Id91da269f87b145010c870b7dc043748
This commit is contained in:
parent
ec1015943a
commit
220292ad84
3 changed files with 94 additions and 18 deletions
|
@ -28,6 +28,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
* `jj workspace add` now takes a `--revision` argument.
|
||||
|
||||
* `jj workspace forget` can now forget multiple workspaces at once.
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
* Updating the working copy to a commit where a file that's currently ignored
|
||||
|
|
|
@ -1063,8 +1063,9 @@ struct WorkspaceAddArgs {
|
|||
/// before or after running this command.
|
||||
#[derive(clap::Args, Clone, Debug)]
|
||||
struct WorkspaceForgetArgs {
|
||||
/// Name of the workspace to forget (the current workspace by default)
|
||||
workspace: Option<String>,
|
||||
/// Names of the workspaces to forget. By default, forgets only the current
|
||||
/// workspace.
|
||||
workspaces: Vec<String>,
|
||||
}
|
||||
|
||||
/// List workspaces
|
||||
|
@ -3812,24 +3813,47 @@ fn cmd_workspace_forget(
|
|||
args: &WorkspaceForgetArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let mut workspace_command = command.workspace_helper(ui)?;
|
||||
let len = args.workspaces.len();
|
||||
|
||||
let workspace_id = if let Some(workspace_str) = &args.workspace {
|
||||
WorkspaceId::new(workspace_str.to_string())
|
||||
} else {
|
||||
workspace_command.workspace_id().to_owned()
|
||||
let mut wss = Vec::new();
|
||||
let description = match len {
|
||||
// NOTE (aseipp): if there's only 1-or-0 arguments, shortcut. this is
|
||||
// mostly so the oplog description can look good: it removes the need,
|
||||
// in the case of more-than-1 argument, to handle pluralization of the
|
||||
// nouns in the description
|
||||
0 | 1 => {
|
||||
let ws = match len == 0 {
|
||||
true => workspace_command.workspace_id().to_owned(),
|
||||
false => WorkspaceId::new(args.workspaces[0].to_string()),
|
||||
};
|
||||
wss.push(ws.clone());
|
||||
format!("forget workspace {}", ws.as_str())
|
||||
}
|
||||
_ => {
|
||||
args.workspaces
|
||||
.iter()
|
||||
.map(|ws| WorkspaceId::new(ws.to_string()))
|
||||
.for_each(|ws| wss.push(ws));
|
||||
|
||||
format!("forget workspaces {}", args.workspaces.join(", "))
|
||||
}
|
||||
};
|
||||
if workspace_command
|
||||
.repo()
|
||||
.view()
|
||||
.get_wc_commit_id(&workspace_id)
|
||||
.is_none()
|
||||
{
|
||||
return Err(user_error("No such workspace"));
|
||||
|
||||
for ws in &wss {
|
||||
if workspace_command
|
||||
.repo()
|
||||
.view()
|
||||
.get_wc_commit_id(ws)
|
||||
.is_none()
|
||||
{
|
||||
return Err(user_error(format!("No such workspace: {}", ws.as_str())));
|
||||
}
|
||||
}
|
||||
|
||||
let mut tx =
|
||||
workspace_command.start_transaction(&format!("forget workspace {}", workspace_id.as_str()));
|
||||
tx.mut_repo().remove_wc_commit(&workspace_id);
|
||||
// bundle every workspace forget into a single transaction, so that e.g.
|
||||
// undo correctly restores all of them at once.
|
||||
let mut tx = workspace_command.start_transaction(&description);
|
||||
wss.iter().for_each(|ws| tx.mut_repo().remove_wc_commit(ws));
|
||||
tx.finish(ui)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -400,8 +400,11 @@ fn test_workspaces_forget() {
|
|||
Error: Workspace already exists
|
||||
"###);
|
||||
|
||||
// Forget the secondary workspace
|
||||
let (stdout, stderr) = test_env.jj_cmd_ok(&main_path, &["workspace", "forget", "secondary"]);
|
||||
// Add a third workspace...
|
||||
test_env.jj_cmd_ok(&main_path, &["workspace", "add", "../third"]);
|
||||
// ... and then forget it, and the secondary workspace too
|
||||
let (stdout, stderr) =
|
||||
test_env.jj_cmd_ok(&main_path, &["workspace", "forget", "secondary", "third"]);
|
||||
insta::assert_snapshot!(stdout, @"");
|
||||
insta::assert_snapshot!(stderr, @"");
|
||||
// No workspaces left
|
||||
|
@ -409,6 +412,53 @@ fn test_workspaces_forget() {
|
|||
insta::assert_snapshot!(stdout, @"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_workspaces_forget_multi_transaction() {
|
||||
let test_env = TestEnvironment::default();
|
||||
test_env.jj_cmd_ok(test_env.env_root(), &["init", "--git", "main"]);
|
||||
let main_path = test_env.env_root().join("main");
|
||||
|
||||
std::fs::write(main_path.join("file"), "contents").unwrap();
|
||||
test_env.jj_cmd_ok(&main_path, &["new"]);
|
||||
|
||||
test_env.jj_cmd_ok(&main_path, &["workspace", "add", "../second"]);
|
||||
test_env.jj_cmd_ok(&main_path, &["workspace", "add", "../third"]);
|
||||
|
||||
// there should be three workspaces
|
||||
let stdout = test_env.jj_cmd_success(&main_path, &["workspace", "list"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
default: rlvkpnrz e949be04 (empty) (no description set)
|
||||
second: pmmvwywv feda1c4e (empty) (no description set)
|
||||
third: rzvqmyuk 485853ed (empty) (no description set)
|
||||
"###);
|
||||
|
||||
// delete two at once, in a single tx
|
||||
test_env.jj_cmd_ok(&main_path, &["workspace", "forget", "second", "third"]);
|
||||
let stdout = test_env.jj_cmd_success(&main_path, &["workspace", "list"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
default: rlvkpnrz e949be04 (empty) (no description set)
|
||||
"###);
|
||||
|
||||
// the op log should have multiple workspaces forgotten in a single tx
|
||||
let stdout = test_env.jj_cmd_success(&main_path, &["op", "log", "--limit", "1"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
@ e18f223ba3d3 test-username@host.example.com 2001-02-03 04:05:12.000 +07:00 - 2001-02-03 04:05:12.000 +07:00
|
||||
│ forget workspaces second, third
|
||||
│ args: jj workspace forget second third
|
||||
"###);
|
||||
|
||||
// now, undo, and that should restore both workspaces
|
||||
test_env.jj_cmd_ok(&main_path, &["op", "undo"]);
|
||||
|
||||
// finally, there should be three workspaces at the end
|
||||
let stdout = test_env.jj_cmd_success(&main_path, &["workspace", "list"]);
|
||||
insta::assert_snapshot!(stdout, @r###"
|
||||
default: rlvkpnrz e949be04 (empty) (no description set)
|
||||
second: pmmvwywv feda1c4e (empty) (no description set)
|
||||
third: rzvqmyuk 485853ed (empty) (no description set)
|
||||
"###);
|
||||
}
|
||||
|
||||
/// Test context of commit summary template
|
||||
#[test]
|
||||
fn test_list_workspaces_template() {
|
||||
|
|
Loading…
Reference in a new issue