707 lines · 24.9 KB · Rust
RawDownload
// 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 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::WorkspaceNameBuf;use jj_lib::repo::Repo as _;use maplit::btreemap;use maplit::hashset;use test_case::test_case;use testutils::TestRepo;use testutils::commit_transactions;use testutils::create_random_commit;use testutils::write_random_commit;use testutils::write_random_commit_with_parents; 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() {    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").unwrap();     assert_eq!(        *repo.view().heads(),        hashset! {            child1.id().clone(),            child2.id().clone(),        }    );} #[test]fn test_heads_merge() {    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").unwrap();     assert_eq!(*repo.view().heads(), hashset! {merge.id().clone()});} #[test]fn test_merge_views_heads() {    // 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").unwrap();     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);} #[test]fn test_merge_views_checkout() {    // 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())        .unwrap();    initial_tx        .repo_mut()        .set_wc_commit(ws2_name.clone(), commit1.id().clone())        .unwrap();    initial_tx        .repo_mut()        .set_wc_commit(ws3_name.clone(), commit1.id().clone())        .unwrap();    initial_tx        .repo_mut()        .set_wc_commit(ws4_name.clone(), commit1.id().clone())        .unwrap();    initial_tx        .repo_mut()        .set_wc_commit(ws5_name.clone(), commit1.id().clone())        .unwrap();    let repo = initial_tx.commit("test").unwrap();     let mut tx1 = repo.start_transaction();    tx1.repo_mut()        .set_wc_commit(ws1_name.clone(), commit2.id().clone())        .unwrap();    tx1.repo_mut()        .set_wc_commit(ws2_name.clone(), commit2.id().clone())        .unwrap();    tx1.repo_mut().remove_wc_commit(&ws4_name).unwrap();    tx1.repo_mut()        .set_wc_commit(ws5_name.clone(), commit2.id().clone())        .unwrap();    tx1.repo_mut()        .set_wc_commit(ws6_name.clone(), commit2.id().clone())        .unwrap();     let mut tx2 = repo.start_transaction();    tx2.repo_mut()        .set_wc_commit(ws1_name.clone(), commit3.id().clone())        .unwrap();    tx2.repo_mut()        .set_wc_commit(ws3_name.clone(), commit3.id().clone())        .unwrap();    tx2.repo_mut()        .set_wc_commit(ws4_name.clone(), commit3.id().clone())        .unwrap();    tx2.repo_mut().remove_wc_commit(&ws5_name).unwrap();    tx2.repo_mut()        .set_wc_commit(ws7_name.clone(), commit3.id().clone())        .unwrap();     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()));} #[test]fn test_merge_views_bookmarks() {    // 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").unwrap();     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,        }    );} #[test]fn test_merge_views_tags() {    // 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").unwrap();     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),        ]    );} #[test]fn test_merge_views_remote_tags() {    // 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").unwrap();     // 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),        ]    );} #[test]fn test_merge_views_git_refs() {    // 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").unwrap();     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 707.