From 21d277b7dce840e835d5f559625e62d75ba77233 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Sat, 12 Feb 2022 16:41:51 -0800 Subject: [PATCH] cli: check for concurrent operation during `jj untrack` This patch addresses the TODO about a (tiny) race that could happen if `jj untrack` was run concurrently with another operation. --- src/commands.rs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 05042b3c9..81c505664 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1751,16 +1751,28 @@ fn cmd_untrack( args.values_of("paths"), )?; + let current_checkout_id = workspace_command + .repo + .view() + .get_checkout(&workspace_command.workspace_id()); + let current_checkout = if let Some(current_checkout_id) = current_checkout_id { + store.get_commit(current_checkout_id).unwrap() + } else { + return Err(CommandError::UserError( + "Nothing checked out in this workspace".to_string(), + )); + }; + let mut tx = workspace_command.start_transaction("untrack paths"); let mut locked_working_copy = workspace_command.working_copy_mut().start_mutation(); - // TODO: Error out if locked_working_copy.old_commit_id() doesn't match - // repo.view().checkout() - let old_commit = store - .get_commit(locked_working_copy.old_commit_id()) - .unwrap(); + if current_checkout.id() != locked_working_copy.old_commit_id() { + return Err(CommandError::UserError( + "Concurrent working copy operation. Try again.".to_string(), + )); + } // Create a new tree without the unwanted files - let mut tree_builder = store.tree_builder(old_commit.tree_id().clone()); - for (path, _value) in old_commit.tree().entries_matching(matcher.as_ref()) { + let mut tree_builder = store.tree_builder(current_checkout.tree_id().clone()); + for (path, _value) in current_checkout.tree().entries_matching(matcher.as_ref()) { tree_builder.remove(path); } let new_tree_id = tree_builder.write_tree(); @@ -1786,7 +1798,7 @@ fn cmd_untrack( locked_working_copy.reset(&new_tree)?; } } - let new_commit = CommitBuilder::for_rewrite_from(ui.settings(), &store, &old_commit) + let new_commit = CommitBuilder::for_rewrite_from(ui.settings(), &store, ¤t_checkout) .set_tree(new_tree_id) .write_to_repo(tx.mut_repo()); let num_rebased = tx.mut_repo().rebase_descendants(ui.settings());