// Copyright 2020 The Jujutsu Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at//// https://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License. use std::collections::BTreeMap;use std::time::Duration; use itertools::Itertools as _;use jj_lib::op_store::LocalRemoteRefTarget;use jj_lib::op_store::RefTarget;use jj_lib::op_store::RemoteRef;use jj_lib::op_store::RemoteRefState;use jj_lib::ref_name::RefName;use jj_lib::ref_name::RemoteName;use jj_lib::ref_name::RemoteRefSymbol;use jj_lib::ref_name::WorkspaceName;use jj_lib::ref_name::WorkspaceNameBuf;use jj_lib::repo::Repo as _;use maplit::btreemap;use maplit::hashset;use pollster::FutureExt as _;use test_case::test_case;use testutils::CommitBuilderExt as _;use testutils::TestRepo;use testutils::TestResult;use testutils::commit_transactions;use testutils::create_random_commit;use testutils::write_random_commit;use testutils::write_random_commit_with_parents;use testutils::write_random_commit_with_parents_and_description; fn remote_symbol<'a, N, M>(name: &'a N, remote: &'a M) -> RemoteRefSymbol<'a>where N: AsRef<RefName> + ?Sized, M: AsRef<RemoteName> + ?Sized,{ RemoteRefSymbol { name: name.as_ref(), remote: remote.as_ref(), }} #[test]fn test_heads_empty() { let test_repo = TestRepo::init(); let repo = &test_repo.repo; assert_eq!( *repo.view().heads(), hashset! {repo.store().root_commit_id().clone()} );} #[test]fn test_heads_fork() -> TestResult { let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let initial = write_random_commit(tx.repo_mut()); let child1 = write_random_commit_with_parents(tx.repo_mut(), &[&initial]); let child2 = write_random_commit_with_parents(tx.repo_mut(), &[&initial]); let repo = tx.commit("test").block_on()?; assert_eq!( *repo.view().heads(), hashset! { child1.id().clone(), child2.id().clone(), } ); Ok(())} #[test]fn test_heads_merge() -> TestResult { let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let initial = write_random_commit(tx.repo_mut()); let child1 = write_random_commit_with_parents(tx.repo_mut(), &[&initial]); let child2 = write_random_commit_with_parents(tx.repo_mut(), &[&initial]); let merge = write_random_commit_with_parents(tx.repo_mut(), &[&child1, &child2]); let repo = tx.commit("test").block_on()?; assert_eq!(*repo.view().heads(), hashset! {merge.id().clone()}); Ok(())} #[test]fn test_merge_views_heads() -> TestResult { // Tests merging of the view's heads (by performing divergent operations). let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let head_unchanged = write_random_commit(mut_repo); let head_remove_tx1 = write_random_commit(mut_repo); let head_remove_tx2 = write_random_commit(mut_repo); let repo = tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); tx1.repo_mut().remove_head(head_remove_tx1.id()); let head_add_tx1 = write_random_commit(tx1.repo_mut()); let mut tx2 = repo.start_transaction(); tx2.repo_mut().remove_head(head_remove_tx2.id()); let head_add_tx2 = write_random_commit(tx2.repo_mut()); let repo = commit_transactions(vec![tx1, tx2]); let expected_heads = hashset! { head_unchanged.id().clone(), head_add_tx1.id().clone(), head_add_tx2.id().clone(), }; assert_eq!(repo.view().heads(), &expected_heads); Ok(())} #[test]fn test_merge_views_checkout() -> TestResult { // Tests merging of the view's checkout (by performing divergent operations). let test_repo = TestRepo::init(); let repo = &test_repo.repo; // Workspace 1 gets updated in both transactions. // Workspace 2 gets updated only in tx1. // Workspace 3 gets updated only in tx2. // Workspace 4 gets deleted in tx1 and modified in tx2. // Workspace 5 gets deleted in tx2 and modified in tx1. // Workspace 6 gets added in tx1. // Workspace 7 gets added in tx2. let mut initial_tx = repo.start_transaction(); let commit1 = write_random_commit(initial_tx.repo_mut()); let commit2 = write_random_commit(initial_tx.repo_mut()); let commit3 = write_random_commit(initial_tx.repo_mut()); let ws1_name = WorkspaceNameBuf::from("ws1"); let ws2_name = WorkspaceNameBuf::from("ws2"); let ws3_name = WorkspaceNameBuf::from("ws3"); let ws4_name = WorkspaceNameBuf::from("ws4"); let ws5_name = WorkspaceNameBuf::from("ws5"); let ws6_name = WorkspaceNameBuf::from("ws6"); let ws7_name = WorkspaceNameBuf::from("ws7"); initial_tx .repo_mut() .set_wc_commit(ws1_name.clone(), commit1.id().clone())?; initial_tx .repo_mut() .set_wc_commit(ws2_name.clone(), commit1.id().clone())?; initial_tx .repo_mut() .set_wc_commit(ws3_name.clone(), commit1.id().clone())?; initial_tx .repo_mut() .set_wc_commit(ws4_name.clone(), commit1.id().clone())?; initial_tx .repo_mut() .set_wc_commit(ws5_name.clone(), commit1.id().clone())?; let repo = initial_tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); tx1.repo_mut() .set_wc_commit(ws1_name.clone(), commit2.id().clone())?; tx1.repo_mut() .set_wc_commit(ws2_name.clone(), commit2.id().clone())?; tx1.repo_mut().remove_wc_commit(&ws4_name).block_on()?; tx1.repo_mut() .set_wc_commit(ws5_name.clone(), commit2.id().clone())?; tx1.repo_mut() .set_wc_commit(ws6_name.clone(), commit2.id().clone())?; let mut tx2 = repo.start_transaction(); tx2.repo_mut() .set_wc_commit(ws1_name.clone(), commit3.id().clone())?; tx2.repo_mut() .set_wc_commit(ws3_name.clone(), commit3.id().clone())?; tx2.repo_mut() .set_wc_commit(ws4_name.clone(), commit3.id().clone())?; tx2.repo_mut().remove_wc_commit(&ws5_name).block_on()?; tx2.repo_mut() .set_wc_commit(ws7_name.clone(), commit3.id().clone())?; let repo = commit_transactions(vec![tx1, tx2]); // We currently arbitrarily pick the first transaction's working-copy commit // (first by transaction end time). assert_eq!(repo.view().get_wc_commit_id(&ws1_name), Some(commit2.id())); assert_eq!(repo.view().get_wc_commit_id(&ws2_name), Some(commit2.id())); assert_eq!(repo.view().get_wc_commit_id(&ws3_name), Some(commit3.id())); assert_eq!(repo.view().get_wc_commit_id(&ws4_name), None); assert_eq!(repo.view().get_wc_commit_id(&ws5_name), None); assert_eq!(repo.view().get_wc_commit_id(&ws6_name), Some(commit2.id())); assert_eq!(repo.view().get_wc_commit_id(&ws7_name), Some(commit3.id())); Ok(())} #[test]fn test_merge_views_bookmarks() -> TestResult { // Tests merging of bookmarks (by performing concurrent operations). See // test_refs.rs for tests of merging of individual ref targets. let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let main_bookmark_local_tx0 = write_random_commit(mut_repo); let main_bookmark_origin_tx0 = write_random_commit(mut_repo); let main_bookmark_alternate_tx0 = write_random_commit(mut_repo); let main_bookmark_origin_tx0_remote_ref = RemoteRef { target: RefTarget::normal(main_bookmark_origin_tx0.id().clone()), state: RemoteRefState::New, }; let main_bookmark_alternate_tx0_remote_ref = RemoteRef { target: RefTarget::normal(main_bookmark_alternate_tx0.id().clone()), state: RemoteRefState::Tracked, }; mut_repo.set_local_bookmark_target( "main".as_ref(), RefTarget::normal(main_bookmark_local_tx0.id().clone()), ); mut_repo.set_remote_bookmark( remote_symbol("main", "origin"), main_bookmark_origin_tx0_remote_ref, ); mut_repo.set_remote_bookmark( remote_symbol("main", "alternate"), main_bookmark_alternate_tx0_remote_ref.clone(), ); let feature_bookmark_local_tx0 = write_random_commit(mut_repo); mut_repo.set_local_bookmark_target( "feature".as_ref(), RefTarget::normal(feature_bookmark_local_tx0.id().clone()), ); let repo = tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); let main_bookmark_local_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_local_bookmark_target( "main".as_ref(), RefTarget::normal(main_bookmark_local_tx1.id().clone()), ); let feature_bookmark_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_local_bookmark_target( "feature".as_ref(), RefTarget::normal(feature_bookmark_tx1.id().clone()), ); let mut tx2 = repo.start_transaction(); let main_bookmark_local_tx2 = write_random_commit(tx2.repo_mut()); let main_bookmark_origin_tx2 = write_random_commit(tx2.repo_mut()); let main_bookmark_origin_tx2_remote_ref = RemoteRef { target: RefTarget::normal(main_bookmark_origin_tx2.id().clone()), state: RemoteRefState::Tracked, }; tx2.repo_mut().set_local_bookmark_target( "main".as_ref(), RefTarget::normal(main_bookmark_local_tx2.id().clone()), ); tx2.repo_mut().set_remote_bookmark( remote_symbol("main", "origin"), main_bookmark_origin_tx2_remote_ref.clone(), ); let repo = commit_transactions(vec![tx1, tx2]); let expected_main_bookmark = LocalRemoteRefTarget { local_target: &RefTarget::from_legacy_form( [main_bookmark_local_tx0.id().clone()], [ main_bookmark_local_tx1.id().clone(), main_bookmark_local_tx2.id().clone(), ], ), remote_refs: vec![ ( "alternate".as_ref(), &main_bookmark_alternate_tx0_remote_ref, ), // tx1: unchanged, tx2: new -> tracking ("origin".as_ref(), &main_bookmark_origin_tx2_remote_ref), ], }; let expected_feature_bookmark = LocalRemoteRefTarget { local_target: &RefTarget::normal(feature_bookmark_tx1.id().clone()), remote_refs: vec![], }; assert_eq!( repo.view().bookmarks().collect::<BTreeMap<_, _>>(), btreemap! { "main".as_ref() => expected_main_bookmark, "feature".as_ref() => expected_feature_bookmark, } ); Ok(())} #[test]fn test_merge_views_tags() -> TestResult { // Tests merging of tags (by performing divergent operations). See // test_refs.rs for tests of merging of individual ref targets. let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let v1_tx0 = write_random_commit(mut_repo); mut_repo.set_local_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx0.id().clone())); let v2_tx0 = write_random_commit(mut_repo); mut_repo.set_local_tag_target("v2.0".as_ref(), RefTarget::normal(v2_tx0.id().clone())); let repo = tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); let v1_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut() .set_local_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx1.id().clone())); let v2_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut() .set_local_tag_target("v2.0".as_ref(), RefTarget::normal(v2_tx1.id().clone())); let mut tx2 = repo.start_transaction(); let v1_tx2 = write_random_commit(tx2.repo_mut()); tx2.repo_mut() .set_local_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx2.id().clone())); let repo = commit_transactions(vec![tx1, tx2]); let expected_v1 = RefTarget::from_legacy_form( [v1_tx0.id().clone()], [v1_tx1.id().clone(), v1_tx2.id().clone()], ); let expected_v2 = RefTarget::normal(v2_tx1.id().clone()); assert_eq!( repo.view().local_tags().collect_vec(), vec![ ("v1.0".as_ref(), &expected_v1), ("v2.0".as_ref(), &expected_v2), ] ); Ok(())} #[test]fn test_merge_views_remote_tags() -> TestResult { // Tests merging of remote tags (by performing divergent operations). See // test_refs.rs for tests of merging of individual ref targets. let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let v1_origin_tx0 = write_random_commit(mut_repo); mut_repo.set_remote_tag( remote_symbol("v1.0", "origin"), RemoteRef { target: RefTarget::normal(v1_origin_tx0.id().clone()), state: RemoteRefState::New, }, ); let v1_upstream_tx0 = write_random_commit(mut_repo); mut_repo.set_remote_tag( remote_symbol("v1.0", "upstream"), RemoteRef { target: RefTarget::normal(v1_upstream_tx0.id().clone()), state: RemoteRefState::Tracked, }, ); let v2_upstream_tx0 = write_random_commit(mut_repo); mut_repo.set_remote_tag( remote_symbol("v2.0", "upstream"), RemoteRef { target: RefTarget::normal(v2_upstream_tx0.id().clone()), state: RemoteRefState::Tracked, }, ); let repo = tx.commit("test").block_on()?; // v1.0@origin: tx0 (new) -> tx1 (new) // v2.0@upstream: tx0 (tracked) -> tx1 (tracked) let mut tx1 = repo.start_transaction(); let v1_origin_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_remote_tag( remote_symbol("v1.0", "origin"), RemoteRef { target: RefTarget::normal(v1_origin_tx1.id().clone()), state: RemoteRefState::New, }, ); let v2_upstream_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_remote_tag( remote_symbol("v2.0", "upstream"), RemoteRef { target: RefTarget::normal(v2_upstream_tx1.id().clone()), state: RemoteRefState::Tracked, }, ); // v1.0@origin: tx0 (new) -> tx2 (tracked) // v1.0@upstream: tx0 (tracked) -> tx2 (new) let mut tx2 = repo.start_transaction(); let v1_origin_tx2 = write_random_commit(tx2.repo_mut()); tx2.repo_mut().set_remote_tag( remote_symbol("v1.0", "origin"), RemoteRef { target: RefTarget::normal(v1_origin_tx2.id().clone()), state: RemoteRefState::Tracked, }, ); let v1_upstream_tx2 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_remote_tag( remote_symbol("v1.0", "upstream"), RemoteRef { target: RefTarget::normal(v1_upstream_tx2.id().clone()), state: RemoteRefState::New, }, ); let repo = commit_transactions(vec![tx1, tx2]); let expected_v1_origin = RemoteRef { target: RefTarget::from_legacy_form( [v1_origin_tx0.id().clone()], [v1_origin_tx1.id().clone(), v1_origin_tx2.id().clone()], ), state: RemoteRefState::Tracked, }; let expected_v1_upstream = RemoteRef { target: RefTarget::normal(v1_upstream_tx2.id().clone()), state: RemoteRefState::New, }; let expected_v2_upstream = RemoteRef { target: RefTarget::normal(v2_upstream_tx1.id().clone()), state: RemoteRefState::Tracked, }; assert_eq!( repo.view().all_remote_tags().collect_vec(), vec![ (remote_symbol("v1.0", "origin"), &expected_v1_origin), (remote_symbol("v1.0", "upstream"), &expected_v1_upstream), (remote_symbol("v2.0", "upstream"), &expected_v2_upstream), ] ); Ok(())} #[test]fn test_merge_views_git_refs() -> TestResult { // Tests merging of git refs (by performing divergent operations). See // test_refs.rs for tests of merging of individual ref targets. let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let main_bookmark_tx0 = write_random_commit(mut_repo); mut_repo.set_git_ref_target( "refs/heads/main".as_ref(), RefTarget::normal(main_bookmark_tx0.id().clone()), ); let feature_bookmark_tx0 = write_random_commit(mut_repo); mut_repo.set_git_ref_target( "refs/heads/feature".as_ref(), RefTarget::normal(feature_bookmark_tx0.id().clone()), ); let repo = tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); let main_bookmark_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_git_ref_target( "refs/heads/main".as_ref(), RefTarget::normal(main_bookmark_tx1.id().clone()), ); let feature_bookmark_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_git_ref_target( "refs/heads/feature".as_ref(), RefTarget::normal(feature_bookmark_tx1.id().clone()), ); let mut tx2 = repo.start_transaction(); let main_bookmark_tx2 = write_random_commit(tx2.repo_mut()); tx2.repo_mut().set_git_ref_target( "refs/heads/main".as_ref(), RefTarget::normal(main_bookmark_tx2.id().clone()), ); let repo = commit_transactions(vec![tx1, tx2]); let expected_main_bookmark = RefTarget::from_legacy_form( [main_bookmark_tx0.id().clone()], [ main_bookmark_tx1.id().clone(), main_bookmark_tx2.id().clone(),Lines 1–500 of 1007. Load more
// Copyright 2020 The Jujutsu Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::collections::BTreeMap; use std::time::Duration; use itertools::Itertools as _; use jj_lib::op_store::LocalRemoteRefTarget; use jj_lib::op_store::RefTarget; use jj_lib::op_store::RemoteRef; use jj_lib::op_store::RemoteRefState; use jj_lib::ref_name::RefName; use jj_lib::ref_name::RemoteName; use jj_lib::ref_name::RemoteRefSymbol; use jj_lib::ref_name::WorkspaceName; use jj_lib::ref_name::WorkspaceNameBuf; use jj_lib::repo::Repo as _; use maplit::btreemap; use maplit::hashset; use pollster::FutureExt as _; use test_case::test_case; use testutils::CommitBuilderExt as _; use testutils::TestRepo; use testutils::TestResult; use testutils::commit_transactions; use testutils::create_random_commit; use testutils::write_random_commit; use testutils::write_random_commit_with_parents; use testutils::write_random_commit_with_parents_and_description; fn remote_symbol<'a, N, M>(name: &'a N, remote: &'a M) -> RemoteRefSymbol<'a> where N: AsRef<RefName> + ?Sized, M: AsRef<RemoteName> + ?Sized, { RemoteRefSymbol { name: name.as_ref(), remote: remote.as_ref(), } } #[test] fn test_heads_empty() { let test_repo = TestRepo::init(); let repo = &test_repo.repo; assert_eq!( *repo.view().heads(), hashset! {repo.store().root_commit_id().clone()} ); } #[test] fn test_heads_fork() -> TestResult { let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let initial = write_random_commit(tx.repo_mut()); let child1 = write_random_commit_with_parents(tx.repo_mut(), &[&initial]); let child2 = write_random_commit_with_parents(tx.repo_mut(), &[&initial]); let repo = tx.commit("test").block_on()?; assert_eq!( *repo.view().heads(), hashset! { child1.id().clone(), child2.id().clone(), } ); Ok(()) } #[test] fn test_heads_merge() -> TestResult { let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let initial = write_random_commit(tx.repo_mut()); let child1 = write_random_commit_with_parents(tx.repo_mut(), &[&initial]); let child2 = write_random_commit_with_parents(tx.repo_mut(), &[&initial]); let merge = write_random_commit_with_parents(tx.repo_mut(), &[&child1, &child2]); let repo = tx.commit("test").block_on()?; assert_eq!(*repo.view().heads(), hashset! {merge.id().clone()}); Ok(()) } #[test] fn test_merge_views_heads() -> TestResult { // Tests merging of the view's heads (by performing divergent operations). let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let head_unchanged = write_random_commit(mut_repo); let head_remove_tx1 = write_random_commit(mut_repo); let head_remove_tx2 = write_random_commit(mut_repo); let repo = tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); tx1.repo_mut().remove_head(head_remove_tx1.id()); let head_add_tx1 = write_random_commit(tx1.repo_mut()); let mut tx2 = repo.start_transaction(); tx2.repo_mut().remove_head(head_remove_tx2.id()); let head_add_tx2 = write_random_commit(tx2.repo_mut()); let repo = commit_transactions(vec![tx1, tx2]); let expected_heads = hashset! { head_unchanged.id().clone(), head_add_tx1.id().clone(), head_add_tx2.id().clone(), }; assert_eq!(repo.view().heads(), &expected_heads); Ok(()) } #[test] fn test_merge_views_checkout() -> TestResult { // Tests merging of the view's checkout (by performing divergent operations). let test_repo = TestRepo::init(); let repo = &test_repo.repo; // Workspace 1 gets updated in both transactions. // Workspace 2 gets updated only in tx1. // Workspace 3 gets updated only in tx2. // Workspace 4 gets deleted in tx1 and modified in tx2. // Workspace 5 gets deleted in tx2 and modified in tx1. // Workspace 6 gets added in tx1. // Workspace 7 gets added in tx2. let mut initial_tx = repo.start_transaction(); let commit1 = write_random_commit(initial_tx.repo_mut()); let commit2 = write_random_commit(initial_tx.repo_mut()); let commit3 = write_random_commit(initial_tx.repo_mut()); let ws1_name = WorkspaceNameBuf::from("ws1"); let ws2_name = WorkspaceNameBuf::from("ws2"); let ws3_name = WorkspaceNameBuf::from("ws3"); let ws4_name = WorkspaceNameBuf::from("ws4"); let ws5_name = WorkspaceNameBuf::from("ws5"); let ws6_name = WorkspaceNameBuf::from("ws6"); let ws7_name = WorkspaceNameBuf::from("ws7"); initial_tx .repo_mut() .set_wc_commit(ws1_name.clone(), commit1.id().clone())?; initial_tx .repo_mut() .set_wc_commit(ws2_name.clone(), commit1.id().clone())?; initial_tx .repo_mut() .set_wc_commit(ws3_name.clone(), commit1.id().clone())?; initial_tx .repo_mut() .set_wc_commit(ws4_name.clone(), commit1.id().clone())?; initial_tx .repo_mut() .set_wc_commit(ws5_name.clone(), commit1.id().clone())?; let repo = initial_tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); tx1.repo_mut() .set_wc_commit(ws1_name.clone(), commit2.id().clone())?; tx1.repo_mut() .set_wc_commit(ws2_name.clone(), commit2.id().clone())?; tx1.repo_mut().remove_wc_commit(&ws4_name).block_on()?; tx1.repo_mut() .set_wc_commit(ws5_name.clone(), commit2.id().clone())?; tx1.repo_mut() .set_wc_commit(ws6_name.clone(), commit2.id().clone())?; let mut tx2 = repo.start_transaction(); tx2.repo_mut() .set_wc_commit(ws1_name.clone(), commit3.id().clone())?; tx2.repo_mut() .set_wc_commit(ws3_name.clone(), commit3.id().clone())?; tx2.repo_mut() .set_wc_commit(ws4_name.clone(), commit3.id().clone())?; tx2.repo_mut().remove_wc_commit(&ws5_name).block_on()?; tx2.repo_mut() .set_wc_commit(ws7_name.clone(), commit3.id().clone())?; let repo = commit_transactions(vec![tx1, tx2]); // We currently arbitrarily pick the first transaction's working-copy commit // (first by transaction end time). assert_eq!(repo.view().get_wc_commit_id(&ws1_name), Some(commit2.id())); assert_eq!(repo.view().get_wc_commit_id(&ws2_name), Some(commit2.id())); assert_eq!(repo.view().get_wc_commit_id(&ws3_name), Some(commit3.id())); assert_eq!(repo.view().get_wc_commit_id(&ws4_name), None); assert_eq!(repo.view().get_wc_commit_id(&ws5_name), None); assert_eq!(repo.view().get_wc_commit_id(&ws6_name), Some(commit2.id())); assert_eq!(repo.view().get_wc_commit_id(&ws7_name), Some(commit3.id())); Ok(()) } #[test] fn test_merge_views_bookmarks() -> TestResult { // Tests merging of bookmarks (by performing concurrent operations). See // test_refs.rs for tests of merging of individual ref targets. let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let main_bookmark_local_tx0 = write_random_commit(mut_repo); let main_bookmark_origin_tx0 = write_random_commit(mut_repo); let main_bookmark_alternate_tx0 = write_random_commit(mut_repo); let main_bookmark_origin_tx0_remote_ref = RemoteRef { target: RefTarget::normal(main_bookmark_origin_tx0.id().clone()), state: RemoteRefState::New, }; let main_bookmark_alternate_tx0_remote_ref = RemoteRef { target: RefTarget::normal(main_bookmark_alternate_tx0.id().clone()), state: RemoteRefState::Tracked, }; mut_repo.set_local_bookmark_target( "main".as_ref(), RefTarget::normal(main_bookmark_local_tx0.id().clone()), ); mut_repo.set_remote_bookmark( remote_symbol("main", "origin"), main_bookmark_origin_tx0_remote_ref, ); mut_repo.set_remote_bookmark( remote_symbol("main", "alternate"), main_bookmark_alternate_tx0_remote_ref.clone(), ); let feature_bookmark_local_tx0 = write_random_commit(mut_repo); mut_repo.set_local_bookmark_target( "feature".as_ref(), RefTarget::normal(feature_bookmark_local_tx0.id().clone()), ); let repo = tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); let main_bookmark_local_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_local_bookmark_target( "main".as_ref(), RefTarget::normal(main_bookmark_local_tx1.id().clone()), ); let feature_bookmark_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_local_bookmark_target( "feature".as_ref(), RefTarget::normal(feature_bookmark_tx1.id().clone()), ); let mut tx2 = repo.start_transaction(); let main_bookmark_local_tx2 = write_random_commit(tx2.repo_mut()); let main_bookmark_origin_tx2 = write_random_commit(tx2.repo_mut()); let main_bookmark_origin_tx2_remote_ref = RemoteRef { target: RefTarget::normal(main_bookmark_origin_tx2.id().clone()), state: RemoteRefState::Tracked, }; tx2.repo_mut().set_local_bookmark_target( "main".as_ref(), RefTarget::normal(main_bookmark_local_tx2.id().clone()), ); tx2.repo_mut().set_remote_bookmark( remote_symbol("main", "origin"), main_bookmark_origin_tx2_remote_ref.clone(), ); let repo = commit_transactions(vec![tx1, tx2]); let expected_main_bookmark = LocalRemoteRefTarget { local_target: &RefTarget::from_legacy_form( [main_bookmark_local_tx0.id().clone()], [ main_bookmark_local_tx1.id().clone(), main_bookmark_local_tx2.id().clone(), ], ), remote_refs: vec![ ( "alternate".as_ref(), &main_bookmark_alternate_tx0_remote_ref, ), // tx1: unchanged, tx2: new -> tracking ("origin".as_ref(), &main_bookmark_origin_tx2_remote_ref), ], }; let expected_feature_bookmark = LocalRemoteRefTarget { local_target: &RefTarget::normal(feature_bookmark_tx1.id().clone()), remote_refs: vec![], }; assert_eq!( repo.view().bookmarks().collect::<BTreeMap<_, _>>(), btreemap! { "main".as_ref() => expected_main_bookmark, "feature".as_ref() => expected_feature_bookmark, } ); Ok(()) } #[test] fn test_merge_views_tags() -> TestResult { // Tests merging of tags (by performing divergent operations). See // test_refs.rs for tests of merging of individual ref targets. let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let v1_tx0 = write_random_commit(mut_repo); mut_repo.set_local_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx0.id().clone())); let v2_tx0 = write_random_commit(mut_repo); mut_repo.set_local_tag_target("v2.0".as_ref(), RefTarget::normal(v2_tx0.id().clone())); let repo = tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); let v1_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut() .set_local_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx1.id().clone())); let v2_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut() .set_local_tag_target("v2.0".as_ref(), RefTarget::normal(v2_tx1.id().clone())); let mut tx2 = repo.start_transaction(); let v1_tx2 = write_random_commit(tx2.repo_mut()); tx2.repo_mut() .set_local_tag_target("v1.0".as_ref(), RefTarget::normal(v1_tx2.id().clone())); let repo = commit_transactions(vec![tx1, tx2]); let expected_v1 = RefTarget::from_legacy_form( [v1_tx0.id().clone()], [v1_tx1.id().clone(), v1_tx2.id().clone()], ); let expected_v2 = RefTarget::normal(v2_tx1.id().clone()); assert_eq!( repo.view().local_tags().collect_vec(), vec![ ("v1.0".as_ref(), &expected_v1), ("v2.0".as_ref(), &expected_v2), ] ); Ok(()) } #[test] fn test_merge_views_remote_tags() -> TestResult { // Tests merging of remote tags (by performing divergent operations). See // test_refs.rs for tests of merging of individual ref targets. let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let v1_origin_tx0 = write_random_commit(mut_repo); mut_repo.set_remote_tag( remote_symbol("v1.0", "origin"), RemoteRef { target: RefTarget::normal(v1_origin_tx0.id().clone()), state: RemoteRefState::New, }, ); let v1_upstream_tx0 = write_random_commit(mut_repo); mut_repo.set_remote_tag( remote_symbol("v1.0", "upstream"), RemoteRef { target: RefTarget::normal(v1_upstream_tx0.id().clone()), state: RemoteRefState::Tracked, }, ); let v2_upstream_tx0 = write_random_commit(mut_repo); mut_repo.set_remote_tag( remote_symbol("v2.0", "upstream"), RemoteRef { target: RefTarget::normal(v2_upstream_tx0.id().clone()), state: RemoteRefState::Tracked, }, ); let repo = tx.commit("test").block_on()?; // v1.0@origin: tx0 (new) -> tx1 (new) // v2.0@upstream: tx0 (tracked) -> tx1 (tracked) let mut tx1 = repo.start_transaction(); let v1_origin_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_remote_tag( remote_symbol("v1.0", "origin"), RemoteRef { target: RefTarget::normal(v1_origin_tx1.id().clone()), state: RemoteRefState::New, }, ); let v2_upstream_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_remote_tag( remote_symbol("v2.0", "upstream"), RemoteRef { target: RefTarget::normal(v2_upstream_tx1.id().clone()), state: RemoteRefState::Tracked, }, ); // v1.0@origin: tx0 (new) -> tx2 (tracked) // v1.0@upstream: tx0 (tracked) -> tx2 (new) let mut tx2 = repo.start_transaction(); let v1_origin_tx2 = write_random_commit(tx2.repo_mut()); tx2.repo_mut().set_remote_tag( remote_symbol("v1.0", "origin"), RemoteRef { target: RefTarget::normal(v1_origin_tx2.id().clone()), state: RemoteRefState::Tracked, }, ); let v1_upstream_tx2 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_remote_tag( remote_symbol("v1.0", "upstream"), RemoteRef { target: RefTarget::normal(v1_upstream_tx2.id().clone()), state: RemoteRefState::New, }, ); let repo = commit_transactions(vec![tx1, tx2]); let expected_v1_origin = RemoteRef { target: RefTarget::from_legacy_form( [v1_origin_tx0.id().clone()], [v1_origin_tx1.id().clone(), v1_origin_tx2.id().clone()], ), state: RemoteRefState::Tracked, }; let expected_v1_upstream = RemoteRef { target: RefTarget::normal(v1_upstream_tx2.id().clone()), state: RemoteRefState::New, }; let expected_v2_upstream = RemoteRef { target: RefTarget::normal(v2_upstream_tx1.id().clone()), state: RemoteRefState::Tracked, }; assert_eq!( repo.view().all_remote_tags().collect_vec(), vec![ (remote_symbol("v1.0", "origin"), &expected_v1_origin), (remote_symbol("v1.0", "upstream"), &expected_v1_upstream), (remote_symbol("v2.0", "upstream"), &expected_v2_upstream), ] ); Ok(()) } #[test] fn test_merge_views_git_refs() -> TestResult { // Tests merging of git refs (by performing divergent operations). See // test_refs.rs for tests of merging of individual ref targets. let test_repo = TestRepo::init(); let repo = &test_repo.repo; let mut tx = repo.start_transaction(); let mut_repo = tx.repo_mut(); let main_bookmark_tx0 = write_random_commit(mut_repo); mut_repo.set_git_ref_target( "refs/heads/main".as_ref(), RefTarget::normal(main_bookmark_tx0.id().clone()), ); let feature_bookmark_tx0 = write_random_commit(mut_repo); mut_repo.set_git_ref_target( "refs/heads/feature".as_ref(), RefTarget::normal(feature_bookmark_tx0.id().clone()), ); let repo = tx.commit("test").block_on()?; let mut tx1 = repo.start_transaction(); let main_bookmark_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_git_ref_target( "refs/heads/main".as_ref(), RefTarget::normal(main_bookmark_tx1.id().clone()), ); let feature_bookmark_tx1 = write_random_commit(tx1.repo_mut()); tx1.repo_mut().set_git_ref_target( "refs/heads/feature".as_ref(), RefTarget::normal(feature_bookmark_tx1.id().clone()), ); let mut tx2 = repo.start_transaction(); let main_bookmark_tx2 = write_random_commit(tx2.repo_mut()); tx2.repo_mut().set_git_ref_target( "refs/heads/main".as_ref(), RefTarget::normal(main_bookmark_tx2.id().clone()), ); let repo = commit_transactions(vec![tx1, tx2]); let expected_main_bookmark = RefTarget::from_legacy_form( [main_bookmark_tx0.id().clone()], [ main_bookmark_tx1.id().clone(), main_bookmark_tx2.id().clone(),