diff --git a/lib/src/repo.rs b/lib/src/repo.rs index d2c44254e..34859584f 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -352,23 +352,12 @@ impl ReadonlyRepo { Transaction::new(mut_repo, description) } - pub fn reload(&mut self) { - let repo_loader = self.loader(); - let operation = self - .op_heads_store - .get_single_op_head(&repo_loader) - .unwrap(); - self.op_id = operation.id().clone(); - self.view = ReadonlyView::new(operation.view().take_store_view()); - self.index.lock().unwrap().take(); - self.evolution.lock().unwrap().take(); + pub fn reload(&self) -> Result, RepoLoadError> { + self.loader().load_at_head() } - pub fn reload_at(&mut self, operation: &Operation) { - self.op_id = operation.id().clone(); - self.view = ReadonlyView::new(operation.view().take_store_view()); - self.index.lock().unwrap().take(); - self.evolution.lock().unwrap().take(); + pub fn reload_at(&self, operation: &Operation) -> Result, RepoLoadError> { + self.loader().load_at(operation) } } diff --git a/lib/src/working_copy.rs b/lib/src/working_copy.rs index ea2b988eb..82a1a35ed 100644 --- a/lib/src/working_copy.rs +++ b/lib/src/working_copy.rs @@ -718,7 +718,11 @@ impl WorkingCopy { Ok(stats) } - pub fn commit(&self, settings: &UserSettings, repo: &mut ReadonlyRepo) -> Commit { + pub fn commit( + &self, + settings: &UserSettings, + mut repo: Arc, + ) -> (Arc, Commit) { let lock_path = self.state_path.join("working_copy.lock"); let _lock = FileLock::lock(lock_path); @@ -735,7 +739,7 @@ impl WorkingCopy { // Reload the repo so the new commit is visible in the index and view // TODO: This is not enough. The new commit is not necessarily still in the // view when we reload. - repo.reload(); + repo = repo.reload().unwrap(); } _ => {} } @@ -750,12 +754,13 @@ impl WorkingCopy { .write_to_repo(mut_repo); mut_repo.set_checkout(commit.id().clone()); let operation = tx.commit(); - repo.reload_at(&operation); + repo = repo.reload_at(&operation).unwrap(); self.commit_id.replace(Some(commit.id().clone())); self.commit.replace(Some(commit)); self.save(); } - self.commit.borrow().as_ref().unwrap().clone() + let commit = self.commit.borrow().as_ref().unwrap().clone(); + (repo, commit) } } diff --git a/lib/tests/test_bad_locking.rs b/lib/tests/test_bad_locking.rs index 1f483553e..833c3c4f1 100644 --- a/lib/tests/test_bad_locking.rs +++ b/lib/tests/test_bad_locking.rs @@ -13,7 +13,6 @@ // limitations under the License. use std::path::Path; -use std::sync::Arc; use jujube_lib::repo::ReadonlyRepo; use jujube_lib::testutils; @@ -141,12 +140,12 @@ fn test_bad_locking_interrupted(use_git: bool) { // that's a descendant of the other is resolved without creating a new // operation. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let initial = testutils::create_random_commit(&settings, &repo) .set_parents(vec![repo.store().root_commit_id().clone()]) .write_to_new_transaction(&repo, "test"); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); // Simulate a crash that resulted in the old op-head left in place. We simulate // it somewhat hackily by copying the .jj/op_heads/ directory before the diff --git a/lib/tests/test_commit_builder.rs b/lib/tests/test_commit_builder.rs index 7694c86dc..f6afbc301 100644 --- a/lib/tests/test_commit_builder.rs +++ b/lib/tests/test_commit_builder.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::Arc; - use jujube_lib::commit_builder::CommitBuilder; use jujube_lib::repo_path::FileRepoPath; use jujube_lib::settings::UserSettings; @@ -64,7 +62,7 @@ fn test_initial(use_git: bool) { #[test_case(true ; "git store")] fn test_rewrite(use_git: bool) { let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let store = repo.store().clone(); let root_file_path = FileRepoPath::from("file"); @@ -81,7 +79,7 @@ fn test_rewrite(use_git: bool) { CommitBuilder::for_new_commit(&settings, &store, initial_tree.id().clone()) .set_parents(vec![store.root_commit_id().clone()]) .write_to_new_transaction(&repo, "test"); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let rewritten_tree = testutils::create_tree( &repo, diff --git a/lib/tests/test_commit_concurrent.rs b/lib/tests/test_commit_concurrent.rs index e90c590f6..e68f5ada8 100644 --- a/lib/tests/test_commit_concurrent.rs +++ b/lib/tests/test_commit_concurrent.rs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::Arc; use std::thread; use jujube_lib::repo::ReadonlyRepo; @@ -44,7 +43,7 @@ fn test_commit_parallel(use_git: bool) { // transactions from it. It then reloads the repo. That should merge all the // operations and all commits should be visible. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut threads = vec![]; for _ in 0..100 { @@ -59,7 +58,7 @@ fn test_commit_parallel(use_git: bool) { for thread in threads { thread.join().ok().unwrap(); } - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); // One commit per thread plus the commit from the initial checkout on top of the // root commit assert_eq!(repo.view().heads().len(), 101); diff --git a/lib/tests/test_git.rs b/lib/tests/test_git.rs index 581942cda..20a5ebe3e 100644 --- a/lib/tests/test_git.rs +++ b/lib/tests/test_git.rs @@ -126,7 +126,7 @@ fn test_import_refs_reimport() { delete_git_ref(&git_repo, "refs/heads/feature2"); let commit5 = empty_git_commit(&git_repo, "refs/heads/feature2", &[&commit2]); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); jujube_lib::git::import_refs(mut_repo, &git_repo).unwrap_or_default(); @@ -203,7 +203,7 @@ fn test_import_refs_merge() { let mut tx = repo.start_transaction("initial import"); jujube_lib::git::import_refs(tx.mut_repo(), &git_repo).unwrap_or_default(); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); // One of the concurrent operations: git_ref(&git_repo, "refs/heads/sideways-unchanged", commit4.id()); @@ -230,7 +230,7 @@ fn test_import_refs_merge() { tx2.commit(); // Reload the repo, causing the operations to be merged. - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); let view = repo.view(); let git_refs = view.git_refs(); @@ -367,11 +367,11 @@ fn set_up_push_repos(settings: &UserSettings, temp_dir: &TempDir) -> PushTestSet let initial_commit_id = commit_id(&initial_git_commit); git2::Repository::clone(&source_repo_dir.to_str().unwrap(), &clone_repo_dir).unwrap(); std::fs::create_dir(&jj_repo_dir).unwrap(); - let mut jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir); + let jj_repo = ReadonlyRepo::init_external_git(&settings, jj_repo_dir, clone_repo_dir); let new_commit = testutils::create_random_commit(&settings, &jj_repo) .set_parents(vec![initial_commit_id]) .write_to_new_transaction(&jj_repo, "test"); - Arc::get_mut(&mut jj_repo).unwrap().reload(); + let jj_repo = jj_repo.reload().unwrap(); PushTestSetup { source_repo_dir, jj_repo, @@ -414,7 +414,7 @@ fn test_push_commit_not_fast_forward() { let mut setup = set_up_push_repos(&settings, &temp_dir); let new_commit = testutils::create_random_commit(&settings, &setup.jj_repo) .write_to_new_transaction(&setup.jj_repo, "test"); - Arc::get_mut(&mut setup.jj_repo).unwrap().reload(); + setup.jj_repo = setup.jj_repo.reload().unwrap(); let result = git::push_commit( &setup.jj_repo.store().git_repo().unwrap(), &new_commit, diff --git a/lib/tests/test_index.rs b/lib/tests/test_index.rs index 1a73d06dc..6d87eff2e 100644 --- a/lib/tests/test_index.rs +++ b/lib/tests/test_index.rs @@ -93,7 +93,7 @@ fn test_index_commits_standard_cases(use_git: bool) { let commit_g = child_commit(&settings, &repo, &commit_f).write_to_repo(tx.mut_repo()); let commit_h = child_commit(&settings, &repo, &commit_e).write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); let index = repo.index(); // There should be the root commit and the working copy commit, plus @@ -165,7 +165,7 @@ fn test_index_commits_criss_cross(use_git: bool) { right_commits.push(new_right); } tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); let index = repo.index(); // There should the root commit and the working copy commit, plus 2 for each @@ -263,12 +263,12 @@ fn test_index_commits_previous_operations(use_git: bool) { let commit_b = child_commit(&settings, &repo, &commit_a).write_to_repo(tx.mut_repo()); let commit_c = child_commit(&settings, &repo, &commit_b).write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); tx.mut_repo().remove_head(&commit_c); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); // Delete index from disk let index_operations_dir = repo @@ -314,7 +314,7 @@ fn test_index_commits_incremental(use_git: bool) { let root_commit = repo.store().root_commit(); let commit_a = child_commit(&settings, &repo, &root_commit).write_to_new_transaction(&repo, "test"); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); let index = repo.index(); // There should be the root commit and the working copy commit, plus @@ -361,7 +361,7 @@ fn test_index_commits_incremental_empty_transaction(use_git: bool) { let root_commit = repo.store().root_commit(); let commit_a = child_commit(&settings, &repo, &root_commit).write_to_new_transaction(&repo, "test"); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); let index = repo.index(); // There should be the root commit and the working copy commit, plus @@ -405,7 +405,7 @@ fn test_index_commits_incremental_already_indexed(use_git: bool) { let root_commit = repo.store().root_commit(); let commit_a = child_commit(&settings, &repo, &root_commit).write_to_new_transaction(&repo, "test"); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); assert!(repo.index().has_id(commit_a.id())); assert_eq!(repo.index().num_commits(), 2 + 1); @@ -416,13 +416,18 @@ fn test_index_commits_incremental_already_indexed(use_git: bool) { tx.discard(); } -fn create_n_commits(settings: &UserSettings, repo: &mut Arc, num_commits: i32) { +#[must_use] +fn create_n_commits( + settings: &UserSettings, + repo: &Arc, + num_commits: i32, +) -> Arc { let mut tx = repo.start_transaction("test"); for _ in 0..num_commits { create_random_commit(settings, repo).write_to_repo(tx.mut_repo()); } tx.commit(); - Arc::get_mut(repo).unwrap().reload(); + repo.reload().unwrap() } fn commits_by_level(repo: &ReadonlyRepo) -> Vec { @@ -440,44 +445,44 @@ fn test_index_commits_incremental_squashed(use_git: bool) { let settings = testutils::user_settings(); let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); - create_n_commits(&settings, &mut repo, 1); + repo = create_n_commits(&settings, &repo, 1); assert_eq!(commits_by_level(&repo), vec![2, 1]); - create_n_commits(&settings, &mut repo, 1); + repo = create_n_commits(&settings, &repo, 1); assert_eq!(commits_by_level(&repo), vec![4]); let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); - create_n_commits(&settings, &mut repo, 2); + repo = create_n_commits(&settings, &repo, 2); assert_eq!(commits_by_level(&repo), vec![4]); let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); - create_n_commits(&settings, &mut repo, 100); + repo = create_n_commits(&settings, &repo, 100); assert_eq!(commits_by_level(&repo), vec![102]); let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); - create_n_commits(&settings, &mut repo, 2); - create_n_commits(&settings, &mut repo, 4); - create_n_commits(&settings, &mut repo, 8); - create_n_commits(&settings, &mut repo, 16); - create_n_commits(&settings, &mut repo, 32); + repo = create_n_commits(&settings, &repo, 2); + repo = create_n_commits(&settings, &repo, 4); + repo = create_n_commits(&settings, &repo, 8); + repo = create_n_commits(&settings, &repo, 16); + repo = create_n_commits(&settings, &repo, 32); assert_eq!(commits_by_level(&repo), vec![64]); let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); - create_n_commits(&settings, &mut repo, 32); - create_n_commits(&settings, &mut repo, 16); - create_n_commits(&settings, &mut repo, 8); - create_n_commits(&settings, &mut repo, 4); - create_n_commits(&settings, &mut repo, 2); + repo = create_n_commits(&settings, &repo, 32); + repo = create_n_commits(&settings, &repo, 16); + repo = create_n_commits(&settings, &repo, 8); + repo = create_n_commits(&settings, &repo, 4); + repo = create_n_commits(&settings, &repo, 2); assert_eq!(commits_by_level(&repo), vec![34, 16, 8, 4, 2]); let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); - create_n_commits(&settings, &mut repo, 10); - create_n_commits(&settings, &mut repo, 10); - create_n_commits(&settings, &mut repo, 10); - create_n_commits(&settings, &mut repo, 10); - create_n_commits(&settings, &mut repo, 10); - create_n_commits(&settings, &mut repo, 10); - create_n_commits(&settings, &mut repo, 10); - create_n_commits(&settings, &mut repo, 10); - create_n_commits(&settings, &mut repo, 10); + repo = create_n_commits(&settings, &repo, 10); + repo = create_n_commits(&settings, &repo, 10); + repo = create_n_commits(&settings, &repo, 10); + repo = create_n_commits(&settings, &repo, 10); + repo = create_n_commits(&settings, &repo, 10); + repo = create_n_commits(&settings, &repo, 10); + repo = create_n_commits(&settings, &repo, 10); + repo = create_n_commits(&settings, &repo, 10); + repo = create_n_commits(&settings, &repo, 10); assert_eq!(commits_by_level(&repo), vec![72, 20]); } diff --git a/lib/tests/test_load_repo.rs b/lib/tests/test_load_repo.rs index 74a9e0ced..043acc6c5 100644 --- a/lib/tests/test_load_repo.rs +++ b/lib/tests/test_load_repo.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::Arc; - use jujube_lib::repo::{ReadonlyRepo, RepoLoadError, RepoLoader}; use jujube_lib::testutils; use test_case::test_case; @@ -37,7 +35,7 @@ fn test_load_at_operation(use_git: bool) { let mut tx = repo.start_transaction("add commit"); let commit = testutils::create_random_commit(&settings, &repo).write_to_repo(tx.mut_repo()); let op = tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("remove commit"); tx.mut_repo().remove_head(&commit); diff --git a/lib/tests/test_mut_repo.rs b/lib/tests/test_mut_repo.rs index 855dad948..c19d30220 100644 --- a/lib/tests/test_mut_repo.rs +++ b/lib/tests/test_mut_repo.rs @@ -29,20 +29,20 @@ use test_case::test_case; fn test_checkout_open(use_git: bool) { // Test that MutableRepo::check_out() uses the requested commit if it's open let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let requested_checkout = testutils::create_random_commit(&settings, &repo) .set_open(true) .write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let actual_checkout = tx.mut_repo().check_out(&settings, &requested_checkout); assert_eq!(actual_checkout.id(), requested_checkout.id()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert_eq!(repo.view().checkout(), actual_checkout.id()); } @@ -52,14 +52,14 @@ fn test_checkout_closed(use_git: bool) { // Test that MutableRepo::check_out() creates a child if the requested commit is // closed let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let requested_checkout = testutils::create_random_commit(&settings, &repo) .set_open(false) .write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let actual_checkout = tx.mut_repo().check_out(&settings, &requested_checkout); @@ -67,7 +67,7 @@ fn test_checkout_closed(use_git: bool) { assert_eq!(actual_checkout.parents().len(), 1); assert_eq!(actual_checkout.parents()[0].id(), requested_checkout.id()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert_eq!(repo.view().checkout(), actual_checkout.id()); } @@ -77,7 +77,7 @@ fn test_checkout_open_with_conflict(use_git: bool) { // Test that MutableRepo::check_out() creates a child if the requested // commit is open and has conflicts let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let store = repo.store(); let file_path = FileRepoPath::from("file"); @@ -93,7 +93,7 @@ fn test_checkout_open_with_conflict(use_git: bool) { .set_open(true) .write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let actual_checkout = tx.mut_repo().check_out(&settings, &requested_checkout); @@ -108,7 +108,7 @@ fn test_checkout_open_with_conflict(use_git: bool) { assert_eq!(actual_checkout.parents().len(), 1); assert_eq!(actual_checkout.parents()[0].id(), requested_checkout.id()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert_eq!(repo.view().checkout(), actual_checkout.id()); } @@ -118,7 +118,7 @@ fn test_checkout_closed_with_conflict(use_git: bool) { // Test that MutableRepo::check_out() creates a child if the requested commit is // closed and has conflicts let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let store = repo.store(); let file_path = FileRepoPath::from("file"); @@ -134,7 +134,7 @@ fn test_checkout_closed_with_conflict(use_git: bool) { .set_open(false) .write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let actual_checkout = tx.mut_repo().check_out(&settings, &requested_checkout); @@ -149,7 +149,7 @@ fn test_checkout_closed_with_conflict(use_git: bool) { assert_eq!(actual_checkout.parents().len(), 1); assert_eq!(actual_checkout.parents()[0].id(), requested_checkout.id()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert_eq!(repo.view().checkout(), actual_checkout.id()); } @@ -188,7 +188,7 @@ fn test_checkout_previous_not_empty(use_git: bool) { // Test that MutableRepo::check_out() does not usually prune the previous // commit. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -197,7 +197,7 @@ fn test_checkout_previous_not_empty(use_git: bool) { .write_to_repo(mut_repo); mut_repo.check_out(&settings, &old_checkout); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -215,7 +215,7 @@ fn test_checkout_previous_empty(use_git: bool) { // Test that MutableRepo::check_out() prunes the previous commit if it was // empty. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -228,7 +228,7 @@ fn test_checkout_previous_empty(use_git: bool) { .write_to_repo(mut_repo); mut_repo.check_out(&settings, &old_checkout); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -246,7 +246,7 @@ fn test_checkout_previous_empty_and_obsolete(use_git: bool) { // Test that MutableRepo::check_out() does not unnecessarily prune the previous // commit if it was empty but already obsolete. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -261,7 +261,7 @@ fn test_checkout_previous_empty_and_obsolete(use_git: bool) { .write_to_repo(mut_repo); mut_repo.check_out(&settings, &old_checkout); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -281,7 +281,7 @@ fn test_checkout_previous_empty_and_pruned(use_git: bool) { // Test that MutableRepo::check_out() does not unnecessarily prune the previous // commit if it was empty but already obsolete. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -291,7 +291,7 @@ fn test_checkout_previous_empty_and_pruned(use_git: bool) { .write_to_repo(mut_repo); mut_repo.check_out(&settings, &old_checkout); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -312,7 +312,7 @@ fn test_add_head_success(use_git: bool) { // Test that MutableRepo::add_head() adds the head, and that it's still there // after commit. It should also be indexed. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); // Create a commit outside of the repo by using a temporary transaction. Then // add that as a head. @@ -332,7 +332,7 @@ fn test_add_head_success(use_git: bool) { assert!(mut_repo.view().heads().contains(new_commit.id())); assert!(mut_repo.index().has_id(new_commit.id())); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert!(repo.view().heads().contains(new_commit.id())); assert!(repo.index().has_id(new_commit.id())); let index_stats = repo.index().stats(); @@ -347,7 +347,7 @@ fn test_add_head_ancestor(use_git: bool) { // Test that MutableRepo::add_head() does not add a head if it's an ancestor of // an existing head. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(tx.mut_repo()); @@ -358,7 +358,7 @@ fn test_add_head_ancestor(use_git: bool) { .set_parents(vec![commit2.id().clone()]) .write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let index_stats = repo.index().stats(); assert_eq!(index_stats.num_heads, 2); @@ -381,12 +381,12 @@ fn test_add_head_not_immediate_child(use_git: bool) { // Test that MutableRepo::add_head() can be used for adding a head that is not // an immediate child of a current head. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let initial = testutils::create_random_commit(&settings, &repo).write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); // Create some commit outside of the repo by using a temporary transaction. Then // add one of them as a head. @@ -432,7 +432,7 @@ fn test_remove_head(use_git: bool) { // for commits no longer visible in that case so we don't have to reindex e.g. // when the user does `jj op undo`. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(tx.mut_repo()); @@ -443,7 +443,7 @@ fn test_remove_head(use_git: bool) { .set_parents(vec![commit2.id().clone()]) .write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -458,7 +458,7 @@ fn test_remove_head(use_git: bool) { assert!(mut_repo.index().has_id(commit3.id())); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let heads = repo.view().heads().clone(); assert!(!heads.contains(commit3.id())); assert!(!heads.contains(commit2.id())); @@ -474,7 +474,7 @@ fn test_remove_head_ancestor_git_ref(use_git: bool) { // Test that MutableRepo::remove_head() does not leave the view with a git ref // pointing to a commit that's not reachable by any head. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -487,7 +487,7 @@ fn test_remove_head_ancestor_git_ref(use_git: bool) { .write_to_repo(mut_repo); mut_repo.insert_git_ref("refs/heads/main".to_string(), commit1.id().clone()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -500,7 +500,7 @@ fn test_remove_head_ancestor_git_ref(use_git: bool) { assert!(heads.contains(commit1.id())); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let heads = repo.view().heads().clone(); assert!(!heads.contains(commit3.id())); assert!(!heads.contains(commit2.id())); @@ -513,12 +513,12 @@ fn test_add_public_head(use_git: bool) { // Test that MutableRepo::add_public_head() adds the head, and that it's still // there after commit. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(tx.mut_repo()); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -526,7 +526,7 @@ fn test_add_public_head(use_git: bool) { mut_repo.add_public_head(&commit1); assert!(mut_repo.view().public_heads().contains(commit1.id())); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert!(repo.view().public_heads().contains(commit1.id())); } @@ -536,7 +536,7 @@ fn test_add_public_head_ancestor(use_git: bool) { // Test that MutableRepo::add_public_head() does not add a public head if it's // an ancestor of an existing public head. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -546,7 +546,7 @@ fn test_add_public_head_ancestor(use_git: bool) { .write_to_repo(mut_repo); mut_repo.add_public_head(&commit2); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -554,7 +554,7 @@ fn test_add_public_head_ancestor(use_git: bool) { mut_repo.add_public_head(&commit1); assert!(!mut_repo.view().public_heads().contains(commit1.id())); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert!(!repo.view().public_heads().contains(commit1.id())); } @@ -564,14 +564,14 @@ fn test_remove_public_head(use_git: bool) { // Test that MutableRepo::remove_public_head() removes the head, and that it's // still removed after commit. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); let commit1 = testutils::create_random_commit(&settings, &repo).write_to_repo(mut_repo); mut_repo.add_public_head(&commit1); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx = repo.start_transaction("test"); let mut_repo = tx.mut_repo(); @@ -579,6 +579,6 @@ fn test_remove_public_head(use_git: bool) { mut_repo.remove_public_head(&commit1); assert!(!mut_repo.view().public_heads().contains(commit1.id())); tx.commit(); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert!(!repo.view().public_heads().contains(commit1.id())); } diff --git a/lib/tests/test_operations.rs b/lib/tests/test_operations.rs index 57aad888e..934d7fb15 100644 --- a/lib/tests/test_operations.rs +++ b/lib/tests/test_operations.rs @@ -13,7 +13,6 @@ // limitations under the License. use std::path::Path; -use std::sync::Arc; use jujube_lib::commit_builder::CommitBuilder; use jujube_lib::repo::RepoRef; @@ -55,7 +54,7 @@ fn test_consecutive_operations(use_git: bool) { // Test that consecutive operations result in a single op-head on disk after // each operation let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let op_heads_dir = repo.repo_path().join("op_heads"); let op_id0 = repo.op_id().clone(); @@ -67,7 +66,7 @@ fn test_consecutive_operations(use_git: bool) { assert_ne!(op_id1, op_id0); assert_eq!(list_dir(&op_heads_dir), vec![op_id1.hex()]); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx2 = repo.start_transaction("transaction 2"); testutils::create_random_commit(&settings, &repo).write_to_repo(tx2.mut_repo()); let op_id2 = tx2.commit().id().clone(); @@ -77,7 +76,7 @@ fn test_consecutive_operations(use_git: bool) { // Reloading the repo makes no difference (there are no conflicting operations // to resolve). - Arc::get_mut(&mut repo).unwrap().reload(); + let _repo = repo.reload().unwrap(); assert_eq!(list_dir(&op_heads_dir), vec![op_id2.hex()]); } @@ -87,7 +86,7 @@ fn test_concurrent_operations(use_git: bool) { // Test that consecutive operations result in multiple op-heads on disk until // the repo has been reloaded (which currently happens right away). let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let op_heads_dir = repo.repo_path().join("op_heads"); let op_id0 = repo.op_id().clone(); @@ -113,7 +112,7 @@ fn test_concurrent_operations(use_git: bool) { assert_eq!(actual_heads_on_disk, expected_heads_on_disk); // Reloading the repo causes the operations to be merged - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let merged_op_id = repo.op_id().clone(); assert_ne!(merged_op_id, op_id0); assert_ne!(merged_op_id, op_id1); @@ -131,13 +130,13 @@ fn assert_heads(repo: RepoRef, expected: Vec<&CommitId>) { fn test_isolation(use_git: bool) { // Test that two concurrent transactions don't see each other's changes. let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let wc_id = repo.working_copy_locked().current_commit_id(); let initial = testutils::create_random_commit(&settings, &repo) .set_parents(vec![repo.store().root_commit_id().clone()]) .write_to_new_transaction(&repo, "test"); - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); let mut tx1 = repo.start_transaction("transaction 1"); let mut_repo1 = tx1.mut_repo(); @@ -185,7 +184,7 @@ fn test_isolation(use_git: bool) { tx2.commit(); assert_heads(repo.as_repo_ref(), vec![&wc_id, initial.id()]); // After reload, the base repo sees both rewrites. - Arc::get_mut(&mut repo).unwrap().reload(); + let repo = repo.reload().unwrap(); assert_heads( repo.as_repo_ref(), vec![&wc_id, initial.id(), rewrite1.id(), rewrite2.id()], diff --git a/lib/tests/test_working_copy.rs b/lib/tests/test_working_copy.rs index f5ba1a4b5..fdec1e5f3 100644 --- a/lib/tests/test_working_copy.rs +++ b/lib/tests/test_working_copy.rs @@ -16,7 +16,6 @@ use std::fs::OpenOptions; use std::io::Write; #[cfg(unix)] use std::os::unix::fs::PermissionsExt; -use std::sync::Arc; use jujube_lib::commit_builder::CommitBuilder; use jujube_lib::repo::ReadonlyRepo; @@ -31,13 +30,13 @@ use test_case::test_case; #[test_case(true ; "git store")] fn test_root(use_git: bool) { let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let owned_wc = repo.working_copy().clone(); let wc = owned_wc.lock().unwrap(); assert_eq!(&wc.current_commit_id(), repo.view().checkout()); assert_ne!(&wc.current_commit_id(), repo.store().root_commit_id()); - let wc_commit = wc.commit(&settings, Arc::get_mut(&mut repo).unwrap()); + let (repo, wc_commit) = wc.commit(&settings, repo); assert_eq!(wc_commit.id(), repo.view().checkout()); assert_eq!(wc_commit.tree().id(), repo.store().empty_tree_id()); assert_eq!(wc_commit.store_commit().parents, vec![]); @@ -175,11 +174,12 @@ fn test_checkout_file_transitions(use_git: bool) { let owned_wc = repo.working_copy().clone(); let wc = owned_wc.lock().unwrap(); wc.check_out(left_commit).unwrap(); - wc.commit(&settings, Arc::get_mut(&mut repo).unwrap()); + repo = wc.commit(&settings, repo).0; wc.check_out(right_commit.clone()).unwrap(); // Check that the working copy is clean. - let after_commit = wc.commit(&settings, Arc::get_mut(&mut repo).unwrap()); + let (reloaded_repo, after_commit) = wc.commit(&settings, repo); + repo = reloaded_repo; let diff_summary = right_commit.tree().diff_summary(&after_commit.tree()); assert_eq!(diff_summary.modified, vec![]); assert_eq!(diff_summary.added, vec![]); @@ -262,7 +262,8 @@ fn test_commit_racy_timestamps(use_git: bool) { file.write_all(format!("contents {}", i).as_bytes()) .unwrap(); } - let commit = wc.commit(&settings, Arc::get_mut(&mut repo).unwrap()); + let (reloaded_repo, commit) = wc.commit(&settings, repo); + repo = reloaded_repo; let new_tree_id = commit.tree().id().clone(); assert_ne!(new_tree_id, previous_tree_id); previous_tree_id = new_tree_id; @@ -276,7 +277,7 @@ fn test_gitignores(use_git: bool) { let _home_dir = testutils::new_user_home(); let settings = testutils::user_settings(); - let (_temp_dir, mut repo) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo) = testutils::init_repo(&settings, use_git); let gitignore_path = FileRepoPath::from(".gitignore"); let added_path = FileRepoPath::from("added"); @@ -293,10 +294,7 @@ fn test_gitignores(use_git: bool) { testutils::write_working_copy_file(&repo, &subdir_modified_path, "1"); let wc = repo.working_copy().clone(); - let commit1 = wc - .lock() - .unwrap() - .commit(&settings, Arc::get_mut(&mut repo).unwrap()); + let (repo, commit1) = wc.lock().unwrap().commit(&settings, repo); let files1: Vec<_> = commit1 .tree() .entries() @@ -325,10 +323,7 @@ fn test_gitignores(use_git: bool) { testutils::write_working_copy_file(&repo, &subdir_ignored_path, "2"); let wc = repo.working_copy().clone(); - let commit2 = wc - .lock() - .unwrap() - .commit(&settings, Arc::get_mut(&mut repo).unwrap()); + let (_repo, commit2) = wc.lock().unwrap().commit(&settings, repo); let files2: Vec<_> = commit2 .tree() .entries() diff --git a/lib/tests/test_working_copy_concurrent.rs b/lib/tests/test_working_copy_concurrent.rs index 7450f84d8..9d3317393 100644 --- a/lib/tests/test_working_copy_concurrent.rs +++ b/lib/tests/test_working_copy_concurrent.rs @@ -13,7 +13,6 @@ // limitations under the License. use std::collections::HashSet; -use std::sync::Arc; use std::thread; use jujube_lib::commit_builder::CommitBuilder; @@ -74,25 +73,25 @@ fn test_concurrent_commit(use_git: bool) { // instead of divergence. let _home_dir = testutils::new_user_home(); let settings = testutils::user_settings(); - let (_temp_dir, mut repo1) = testutils::init_repo(&settings, use_git); + let (_temp_dir, repo1) = testutils::init_repo(&settings, use_git); let owned_wc1 = repo1.working_copy().clone(); let wc1 = owned_wc1.lock().unwrap(); let commit1 = wc1.current_commit(); // Commit from another process (simulated by another repo instance) - let mut repo2 = ReadonlyRepo::load(&settings, repo1.working_copy_path().clone()).unwrap(); + let repo2 = ReadonlyRepo::load(&settings, repo1.working_copy_path().clone()).unwrap(); testutils::write_working_copy_file(&repo2, &FileRepoPath::from("file2"), "contents2"); let owned_wc2 = repo2.working_copy().clone(); let wc2 = owned_wc2.lock().unwrap(); - let commit2 = wc2.commit(&settings, Arc::get_mut(&mut repo2).unwrap()); + let commit2 = wc2.commit(&settings, repo2).1; assert_eq!(commit2.predecessors(), vec![commit1]); // Creating another commit (via the first repo instance) should result in a // successor of the commit created from the other process. testutils::write_working_copy_file(&repo1, &FileRepoPath::from("file3"), "contents3"); - let commit3 = wc1.commit(&settings, Arc::get_mut(&mut repo1).unwrap()); + let commit3 = wc1.commit(&settings, repo1).1; assert_eq!(commit3.predecessors(), vec![commit2]); } @@ -133,7 +132,7 @@ fn test_checkout_parallel(use_git: bool) { let settings = settings.clone(); let working_copy_path = repo.working_copy_path().clone(); let handle = thread::spawn(move || { - let mut repo = ReadonlyRepo::load(&settings, working_copy_path).unwrap(); + let repo = ReadonlyRepo::load(&settings, working_copy_path).unwrap(); let owned_wc = repo.working_copy().clone(); let wc = owned_wc.lock().unwrap(); let commit = repo.store().get_commit(&commit_id).unwrap(); @@ -145,7 +144,7 @@ fn test_checkout_parallel(use_git: bool) { // different commit than the one we just checked out, but since // commit() should take the same lock as check_out(), commit() // should never produce a different tree (resulting in a different commit). - let commit_after = wc.commit(&settings, Arc::get_mut(&mut repo).unwrap()); + let commit_after = wc.commit(&settings, repo).1; assert!(commit_ids_set.contains(commit_after.id())); }); threads.push(handle); diff --git a/src/commands.rs b/src/commands.rs index f5e81b036..1de454253 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -114,34 +114,35 @@ fn get_repo(ui: &Ui, matches: &ArgMatches) -> Result, CommandE fn resolve_revision_arg( ui: &Ui, - repo: &mut ReadonlyRepo, + repo: Arc, matches: &ArgMatches, -) -> Result { +) -> Result<(Arc, Commit), CommandError> { resolve_single_rev(ui, repo, matches.value_of("revision").unwrap()) } fn resolve_single_rev( ui: &Ui, - repo: &mut ReadonlyRepo, + mut repo: Arc, revision_str: &str, -) -> Result { +) -> Result<(Arc, Commit), CommandError> { // If we're looking up the working copy commit ("@"), make sure that it is up to // date (the lib crate only looks at the checkout in the view). if revision_str == "@" { let owned_wc = repo.working_copy().clone(); // TODO: Avoid committing every time this function is called. - owned_wc.lock().unwrap().commit(ui.settings(), repo); + let (reloaded_repo, _) = owned_wc.lock().unwrap().commit(ui.settings(), repo.clone()); + repo = reloaded_repo; } if revision_str == "@^" { let commit = repo.store().get_commit(repo.view().checkout()).unwrap(); assert!(commit.is_open()); let parents = commit.parents(); - Ok(parents[0].clone()) + Ok((repo, parents[0].clone())) } else if revision_str.starts_with("desc(") && revision_str.ends_with(')') { let needle = revision_str[5..revision_str.len() - 1].to_string(); let mut matches = vec![]; - let head_ids = skip_uninteresting_heads(repo, &repo.view().heads()); + let head_ids = skip_uninteresting_heads(repo.as_ref(), &repo.view().heads()); let heads: Vec<_> = head_ids .iter() .map(|id| repo.store().get_commit(&id).unwrap()) @@ -151,11 +152,15 @@ fn resolve_single_rev( matches.push(commit); } } - matches - .pop() - .ok_or_else(|| CommandError::UserError(String::from("No matching commit"))) + match matches.pop() { + None => Err(CommandError::UserError(String::from("No matching commit"))), + Some(commit) => Ok((repo, commit)), + } } else { - Ok(revset::resolve_symbol(repo.as_repo_ref(), revision_str)?) + Ok(( + repo.clone(), + revset::resolve_symbol(repo.as_repo_ref(), revision_str)?, + )) } } @@ -218,10 +223,10 @@ fn resolve_single_op_from_store( fn update_working_copy( ui: &mut Ui, - repo: &mut ReadonlyRepo, + repo: &Arc, wc: &WorkingCopy, ) -> Result, CommandError> { - repo.reload(); + let repo = repo.reload()?; let old_commit = wc.current_commit(); let new_commit = repo.store().get_commit(repo.view().checkout()).unwrap(); if old_commit == new_commit { @@ -627,16 +632,15 @@ fn cmd_checkout( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let new_commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, new_commit) = resolve_revision_arg(ui, repo, sub_matches)?; let wc = owned_wc.lock().unwrap(); - wc.commit(ui.settings(), mut_repo); + let (repo, _) = wc.commit(ui.settings(), repo); let mut tx = repo.start_transaction(&format!("check out commit {}", new_commit.id().hex())); tx.mut_repo().check_out(ui.settings(), &new_commit); tx.commit(); - let stats = update_working_copy(ui, Arc::get_mut(&mut repo).unwrap(), &wc)?; + let stats = update_working_copy(ui, &repo, &wc)?; match stats { None => ui.write("already on that commit\n")?, Some(stats) => writeln!( @@ -653,9 +657,8 @@ fn cmd_files( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let repo = get_repo(ui, &matches)?; + let (_repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; for (name, _value) in commit.tree().entries() { writeln!(ui, "{}", name.to_internal_string())?; } @@ -760,20 +763,20 @@ fn cmd_diff( ))); } let mut repo = get_repo(ui, &matches)?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); let from_tree; let to_tree; if sub_matches.is_present("from") || sub_matches.is_present("to") { - from_tree = - resolve_single_rev(ui, mut_repo, sub_matches.value_of("from").unwrap_or("@"))?.tree(); - to_tree = - resolve_single_rev(ui, mut_repo, sub_matches.value_of("to").unwrap_or("@"))?.tree(); + let (reoaded_repo, from) = + resolve_single_rev(ui, repo, sub_matches.value_of("from").unwrap_or("@"))?; + from_tree = from.tree(); + let (reloaded_repo, to) = + resolve_single_rev(ui, reoaded_repo, sub_matches.value_of("to").unwrap_or("@"))?; + repo = reloaded_repo; + to_tree = to.tree(); } else { - let commit = resolve_single_rev( - ui, - mut_repo, - sub_matches.value_of("revision").unwrap_or("@"), - )?; + let (reloaded_repo, commit) = + resolve_single_rev(ui, repo, sub_matches.value_of("revision").unwrap_or("@"))?; + repo = reloaded_repo; let parents = commit.parents(); from_tree = merge_commit_trees(repo.as_repo_ref(), &parents); to_tree = commit.tree() @@ -939,11 +942,10 @@ fn cmd_status( matches: &ArgMatches, _sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); let wc = owned_wc.lock().unwrap(); - let commit = wc.commit(ui.settings(), mut_repo); + let (repo, commit) = wc.commit(ui.settings(), repo); ui.write("Working copy : ")?; ui.write_commit_summary(repo.as_repo_ref(), &commit)?; ui.write("\n")?; @@ -1038,12 +1040,13 @@ fn cmd_log( ) -> Result<(), CommandError> { let mut repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); let use_graph = !sub_matches.is_present("no-graph"); if use_graph { - // Commit so the latest working copy is reflected in the visible heads - owned_wc.lock().unwrap().commit(ui.settings(), mut_repo); + // Commit so the latest working copy is reflected in the view's checkout and + // visible heads + let (reloaded_repo, _wc_commit) = owned_wc.lock().unwrap().commit(ui.settings(), repo); + repo = reloaded_repo; } let template_string = match sub_matches.value_of("template") { @@ -1107,11 +1110,10 @@ fn cmd_obslog( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let use_graph = !sub_matches.is_present("no-graph"); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let start_commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, start_commit) = resolve_revision_arg(ui, repo, sub_matches)?; let template_string = match sub_matches.value_of("template") { Some(value) => value.to_string(), @@ -1204,10 +1206,9 @@ fn cmd_describe( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; let description; if sub_matches.is_present("stdin") { let mut buffer = String::new(); @@ -1224,11 +1225,7 @@ fn cmd_describe( .write_to_repo(tx.mut_repo()); update_checkout_after_rewrite(ui, tx.mut_repo())?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1237,21 +1234,16 @@ fn cmd_open( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; let mut tx = repo.start_transaction(&format!("open commit {}", commit.id().hex())); CommitBuilder::for_rewrite_from(ui.settings(), repo.store(), &commit) .set_open(true) .write_to_repo(tx.mut_repo()); update_checkout_after_rewrite(ui, tx.mut_repo())?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1260,10 +1252,9 @@ fn cmd_close( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; let mut commit_builder = CommitBuilder::for_rewrite_from(ui.settings(), repo.store(), &commit).set_open(false); let description; @@ -1279,11 +1270,7 @@ fn cmd_close( commit_builder.write_to_repo(tx.mut_repo()); update_checkout_after_rewrite(ui, tx.mut_repo())?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1292,9 +1279,8 @@ fn cmd_duplicate( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let predecessor = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let repo = get_repo(ui, &matches)?; + let (repo, predecessor) = resolve_revision_arg(ui, repo, sub_matches)?; let mut tx = repo.start_transaction(&format!("duplicate commit {}", predecessor.id().hex())); let mut_repo = tx.mut_repo(); let new_commit = CommitBuilder::for_rewrite_from(ui.settings(), repo.store(), &predecessor) @@ -1312,10 +1298,9 @@ fn cmd_prune( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let predecessor = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, predecessor) = resolve_revision_arg(ui, repo, sub_matches)?; if predecessor.id() == repo.store().root_commit_id() { return Err(CommandError::UserError(String::from( "Cannot prune the root commit", @@ -1327,11 +1312,7 @@ fn cmd_prune( .write_to_repo(tx.mut_repo()); update_checkout_after_rewrite(ui, tx.mut_repo())?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1340,10 +1321,9 @@ fn cmd_new( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let parent = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, parent) = resolve_revision_arg(ui, repo, sub_matches)?; let commit_builder = CommitBuilder::for_open_commit( ui.settings(), repo.store(), @@ -1357,11 +1337,7 @@ fn cmd_new( mut_repo.check_out(ui.settings(), &new_commit); } tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1370,10 +1346,9 @@ fn cmd_squash( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; let parents = commit.parents(); if parents.len() != 1 { return Err(CommandError::UserError(String::from( @@ -1411,11 +1386,7 @@ fn cmd_squash( .write_to_repo(mut_repo); update_checkout_after_rewrite(ui, mut_repo)?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1424,10 +1395,9 @@ fn cmd_unsquash( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; let parents = commit.parents(); if parents.len() != 1 { return Err(CommandError::UserError(String::from( @@ -1466,11 +1436,7 @@ fn cmd_unsquash( .write_to_repo(mut_repo); update_checkout_after_rewrite(ui, mut_repo)?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1479,9 +1445,8 @@ fn cmd_discard( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let repo = get_repo(ui, &matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; let mut tx = repo.start_transaction(&format!("discard commit {}", commit.id().hex())); let mut_repo = tx.mut_repo(); mut_repo.remove_head(&commit); @@ -1499,12 +1464,12 @@ fn cmd_restore( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let source_commit = resolve_single_rev(ui, mut_repo, sub_matches.value_of("source").unwrap())?; - let destination_commit = - resolve_single_rev(ui, mut_repo, sub_matches.value_of("destination").unwrap())?; + let (repo, source_commit) = + resolve_single_rev(ui, repo, sub_matches.value_of("source").unwrap())?; + let (repo, destination_commit) = + resolve_single_rev(ui, repo, sub_matches.value_of("destination").unwrap())?; let tree_id; if sub_matches.is_present("interactive") { if sub_matches.is_present("paths") { @@ -1550,11 +1515,7 @@ fn cmd_restore( ui.write("\n")?; update_checkout_after_rewrite(ui, mut_repo)?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; } Ok(()) } @@ -1564,10 +1525,9 @@ fn cmd_edit( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; let base_tree = merge_commit_trees(repo.as_repo_ref(), &commit.parents()); let tree_id = crate::diff_edit::edit_diff(&base_tree, &commit.tree())?; if &tree_id == commit.tree().id() { @@ -1583,11 +1543,7 @@ fn cmd_edit( ui.write("\n")?; update_checkout_after_rewrite(ui, mut_repo)?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; } Ok(()) } @@ -1597,10 +1553,9 @@ fn cmd_split( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, sub_matches)?; let base_tree = merge_commit_trees(repo.as_repo_ref(), &commit.parents()); let tree_id = crate::diff_edit::edit_diff(&base_tree, &commit.tree())?; if &tree_id == commit.tree().id() { @@ -1629,11 +1584,7 @@ fn cmd_split( ui.write("\n")?; update_checkout_after_rewrite(ui, mut_repo)?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; } Ok(()) } @@ -1645,7 +1596,6 @@ fn cmd_merge( ) -> Result<(), CommandError> { let mut repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); let revision_args = sub_matches.values_of("revisions").unwrap(); if revision_args.len() < 2 { return Err(CommandError::UserError(String::from( @@ -1655,7 +1605,8 @@ fn cmd_merge( let mut commits = vec![]; let mut parent_ids = vec![]; for revision_arg in revision_args { - let commit = resolve_single_rev(ui, mut_repo, revision_arg)?; + let (reloaded_repo, commit) = resolve_single_rev(ui, repo, revision_arg)?; + repo = reloaded_repo; parent_ids.push(commit.id().clone()); commits.push(commit); } @@ -1674,11 +1625,7 @@ fn cmd_merge( .write_to_repo(tx.mut_repo()); update_checkout_after_rewrite(ui, tx.mut_repo())?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1688,23 +1635,20 @@ fn cmd_rebase( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit_to_rebase = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (mut repo, commit_to_rebase) = resolve_revision_arg(ui, repo, sub_matches)?; let mut parents = vec![]; for revision_str in sub_matches.values_of("destination").unwrap() { - parents.push(resolve_single_rev(ui, mut_repo, revision_str)?); + let (reloaded_repo, destination) = resolve_single_rev(ui, repo, revision_str)?; + repo = reloaded_repo; + parents.push(destination); } let mut tx = repo.start_transaction(&format!("rebase commit {}", commit_to_rebase.id().hex())); rebase_commit(ui.settings(), tx.mut_repo(), &commit_to_rebase, &parents); update_checkout_after_rewrite(ui, tx.mut_repo())?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1714,13 +1658,14 @@ fn cmd_backout( matches: &ArgMatches, sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit_to_back_out = resolve_revision_arg(ui, mut_repo, sub_matches)?; + let (mut repo, commit_to_back_out) = resolve_revision_arg(ui, repo, sub_matches)?; let mut parents = vec![]; for revision_str in sub_matches.values_of("destination").unwrap() { - parents.push(resolve_single_rev(ui, mut_repo, revision_str)?); + let (reloaded_repo, destination) = resolve_single_rev(ui, repo, revision_str)?; + repo = reloaded_repo; + parents.push(destination); } let mut tx = repo.start_transaction(&format!( "back out commit {}", @@ -1729,11 +1674,7 @@ fn cmd_backout( back_out_commit(ui.settings(), tx.mut_repo(), &commit_to_back_out, &parents); update_checkout_after_rewrite(ui, tx.mut_repo())?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1743,7 +1684,7 @@ fn cmd_evolve<'s>( matches: &ArgMatches, _sub_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); struct Listener<'a, 's> { @@ -1834,11 +1775,7 @@ fn cmd_evolve<'s>( evolve(&user_settings, tx.mut_repo(), &mut listener); update_checkout_after_rewrite(ui, tx.mut_repo())?; tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -1849,9 +1786,8 @@ fn cmd_debug( sub_matches: &ArgMatches, ) -> Result<(), CommandError> { if let Some(resolve_matches) = sub_matches.subcommand_matches("resolverev") { - let mut repo = get_repo(ui, &matches)?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, resolve_matches)?; + let repo = get_repo(ui, &matches)?; + let (_repo, commit) = resolve_revision_arg(ui, repo, resolve_matches)?; writeln!(ui, "{}", commit.id().hex())?; } else if let Some(_wc_matches) = sub_matches.subcommand_matches("workingcopy") { let repo = get_repo(ui, &matches)?; @@ -1866,12 +1802,12 @@ fn cmd_debug( )?; } } else if let Some(_wc_matches) = sub_matches.subcommand_matches("writeworkingcopy") { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); let wc = owned_wc.lock().unwrap(); - let mut_repo = Arc::get_mut(&mut repo).unwrap(); let old_commit_id = wc.current_commit_id(); - let new_commit_id = wc.commit(ui.settings(), mut_repo).id().clone(); + let (_repo, new_commit) = wc.commit(ui.settings(), repo); + let new_commit_id = new_commit.id().clone(); writeln!(ui, "old commit {:?}", old_commit_id)?; writeln!(ui, "new commit {:?}", new_commit_id)?; } else if let Some(template_matches) = sub_matches.subcommand_matches("template") { @@ -1933,37 +1869,31 @@ fn cmd_bench( sub_matches: &ArgMatches, ) -> Result<(), CommandError> { if let Some(command_matches) = sub_matches.subcommand_matches("commonancestors") { - let mut repo = get_repo(ui, &matches)?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit1 = - resolve_single_rev(ui, mut_repo, command_matches.value_of("revision1").unwrap())?; - let commit2 = - resolve_single_rev(ui, mut_repo, command_matches.value_of("revision2").unwrap())?; + let repo = get_repo(ui, &matches)?; + let (repo, commit1) = + resolve_single_rev(ui, repo, command_matches.value_of("revision1").unwrap())?; + let (repo, commit2) = + resolve_single_rev(ui, repo, command_matches.value_of("revision2").unwrap())?; let routine = || { repo.index() .common_ancestors(&[commit1.id().clone()], &[commit2.id().clone()]) }; run_bench(ui, "commonancestors", routine)?; } else if let Some(command_matches) = sub_matches.subcommand_matches("isancestor") { - let mut repo = get_repo(ui, &matches)?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let ancestor_commit = - resolve_single_rev(ui, mut_repo, command_matches.value_of("ancestor").unwrap())?; - let descendant_commit = resolve_single_rev( - ui, - mut_repo, - command_matches.value_of("descendant").unwrap(), - )?; + let repo = get_repo(ui, &matches)?; + let (repo, ancestor_commit) = + resolve_single_rev(ui, repo, command_matches.value_of("ancestor").unwrap())?; + let (repo, descendant_commit) = + resolve_single_rev(ui, repo, command_matches.value_of("descendant").unwrap())?; let index = repo.index(); let routine = || index.is_ancestor(ancestor_commit.id(), descendant_commit.id()); run_bench(ui, "isancestor", routine)?; } else if let Some(command_matches) = sub_matches.subcommand_matches("walkrevs") { - let mut repo = get_repo(ui, &matches)?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let unwanted_commit = - resolve_single_rev(ui, mut_repo, command_matches.value_of("unwanted").unwrap())?; - let wanted_commit = - resolve_single_rev(ui, mut_repo, command_matches.value_of("wanted").unwrap())?; + let repo = get_repo(ui, &matches)?; + let (repo, unwanted_commit) = + resolve_single_rev(ui, repo, command_matches.value_of("unwanted").unwrap())?; + let (repo, wanted_commit) = + resolve_single_rev(ui, repo, command_matches.value_of("wanted").unwrap())?; let index = repo.index(); let routine = || { index @@ -2075,7 +2005,7 @@ fn cmd_op_undo( _op_matches: &ArgMatches, _cmd_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); let bad_op = resolve_single_op(&repo, _cmd_matches.value_of("operation").unwrap())?; let parent_ops = bad_op.parents(); @@ -2095,11 +2025,7 @@ fn cmd_op_undo( let parent_repo = repo.loader().load_at(&parent_ops[0])?; tx.mut_repo().merge(&bad_repo, &parent_repo); tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -2109,17 +2035,13 @@ fn cmd_op_restore( _op_matches: &ArgMatches, _cmd_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let owned_wc = repo.working_copy().clone(); let target_op = resolve_single_op(&repo, _cmd_matches.value_of("operation").unwrap())?; let mut tx = repo.start_transaction(&format!("restore to operation {}", target_op.id().hex())); tx.mut_repo().set_view(target_op.view().take_store_view()); tx.commit(); - update_working_copy( - ui, - Arc::get_mut(&mut repo).unwrap(), - &owned_wc.lock().unwrap(), - )?; + update_working_copy(ui, &repo, &owned_wc.lock().unwrap())?; Ok(()) } @@ -2210,10 +2132,9 @@ fn cmd_git_push( _git_matches: &ArgMatches, cmd_matches: &ArgMatches, ) -> Result<(), CommandError> { - let mut repo = get_repo(ui, &matches)?; + let repo = get_repo(ui, &matches)?; let git_repo = get_git_repo(repo.store())?; - let mut_repo = Arc::get_mut(&mut repo).unwrap(); - let commit = resolve_revision_arg(ui, mut_repo, cmd_matches)?; + let (repo, commit) = resolve_revision_arg(ui, repo, cmd_matches)?; let remote_name = cmd_matches.value_of("remote").unwrap(); let branch_name = cmd_matches.value_of("branch").unwrap(); git::push_commit(&git_repo, &commit, remote_name, branch_name)