255 lines · 7.2 KB · Rust
RawDownload
// Copyright 2023 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 itertools::Itertools;use jj_lib::backend::{CommitId, MillisSinceEpoch, Signature, Timestamp};use jj_lib::id_prefix::IdPrefixContext;use jj_lib::object_id::PrefixResolution::{AmbiguousMatch, NoMatch, SingleMatch};use jj_lib::object_id::{HexPrefix, ObjectId};use jj_lib::repo::Repo;use jj_lib::revset::RevsetExpression;use testutils::{TestRepo, TestRepoBackend}; #[test]fn test_id_prefix() {    let settings = testutils::user_settings();    let test_repo = TestRepo::init_with_backend(TestRepoBackend::Git);    let repo = &test_repo.repo;    let root_commit_id = repo.store().root_commit_id();    let root_change_id = repo.store().root_change_id();     let mut tx = repo.start_transaction(&settings);    let mut create_commit = |parent_id: &CommitId| {        let signature = Signature {            name: "Some One".to_string(),            email: "some.one@example.com".to_string(),            timestamp: Timestamp {                timestamp: MillisSinceEpoch(0),                tz_offset: 0,            },        };        tx.mut_repo()            .new_commit(                &settings,                vec![parent_id.clone()],                repo.store().empty_merged_tree_id(),            )            .set_author(signature.clone())            .set_committer(signature)            .write()            .unwrap()    };    let mut commits = vec![create_commit(root_commit_id)];    for _ in 0..25 {        commits.push(create_commit(commits.last().unwrap().id()));    }    let repo = tx.commit("test");     // Print the commit IDs and change IDs for reference    let commit_prefixes = commits        .iter()        .enumerate()        .map(|(i, commit)| format!("{} {}", &commit.id().hex()[..3], i))        .sorted()        .join("\n");    insta::assert_snapshot!(commit_prefixes, @r###"    11a 5    214 24    2a6 2    33e 14    3be 16    3ea 18    593 20    5d3 1    5f6 13    676 3    7b6 25    7da 9    81c 10    87e 12    997 21    9f7 22    a0e 4    a55 19    ac4 23    c18 17    ce9 0    d42 6    d9d 8    eec 15    efe 7    fa3 11    "###);    let change_prefixes = commits        .iter()        .enumerate()        .map(|(i, commit)| format!("{} {}", &commit.change_id().hex()[..3], i))        .sorted()        .join("\n");    insta::assert_snapshot!(change_prefixes, @r###"    026 9    030 13    1b5 6    26b 3    26c 8    271 10    439 2    44a 17    4e9 16    5b2 23    6c2 19    781 0    79f 14    7d5 24    86b 20    871 7    896 5    9e4 18    a2c 1    a63 22    b19 11    b93 4    bf5 21    c24 15    d64 12    fee 25    "###);     let prefix = |x| HexPrefix::new(x).unwrap();     // Without a disambiguation revset    // ---------------------------------------------------------------------------------------------    let c = IdPrefixContext::default();    assert_eq!(        c.shortest_commit_prefix_len(repo.as_ref(), commits[2].id()),        2    );    assert_eq!(        c.shortest_commit_prefix_len(repo.as_ref(), commits[5].id()),        1    );    assert_eq!(        c.resolve_commit_prefix(repo.as_ref(), &prefix("2")),        AmbiguousMatch    );    assert_eq!(        c.resolve_commit_prefix(repo.as_ref(), &prefix("2a")),        SingleMatch(commits[2].id().clone())    );    assert_eq!(        c.resolve_commit_prefix(repo.as_ref(), &prefix("20")),        NoMatch    );    assert_eq!(        c.resolve_commit_prefix(repo.as_ref(), &prefix("2a0")),        NoMatch    );    assert_eq!(        c.shortest_change_prefix_len(repo.as_ref(), commits[0].change_id()),        2    );    assert_eq!(        c.shortest_change_prefix_len(repo.as_ref(), commits[6].change_id()),        1    );    assert_eq!(        c.resolve_change_prefix(repo.as_ref(), &prefix("7")),        AmbiguousMatch    );    assert_eq!(        c.resolve_change_prefix(repo.as_ref(), &prefix("78")),        SingleMatch(vec![commits[0].id().clone()])    );    assert_eq!(        c.resolve_change_prefix(repo.as_ref(), &prefix("70")),        NoMatch    );    assert_eq!(        c.resolve_change_prefix(repo.as_ref(), &prefix("780")),        NoMatch    );     // Disambiguate within a revset    // ---------------------------------------------------------------------------------------------    let expression =        RevsetExpression::commits(vec![commits[0].id().clone(), commits[2].id().clone()]);    let c = c.disambiguate_within(expression);    // The prefix is now shorter    assert_eq!(        c.shortest_commit_prefix_len(repo.as_ref(), commits[2].id()),        1    );    // Shorter prefix within the set can be used    assert_eq!(        c.resolve_commit_prefix(repo.as_ref(), &prefix("2")),        SingleMatch(commits[2].id().clone())    );    // Can still resolve commits outside the set    assert_eq!(        c.resolve_commit_prefix(repo.as_ref(), &prefix("21")),        SingleMatch(commits[24].id().clone())    );    assert_eq!(        c.shortest_change_prefix_len(repo.as_ref(), commits[0].change_id()),        1    );    assert_eq!(        c.resolve_change_prefix(repo.as_ref(), &prefix("7")),        SingleMatch(vec![commits[0].id().clone()])    );     // Single commit in revset. Length 0 is unambiguous, but we pretend 1 digit is    // needed.    // ---------------------------------------------------------------------------------------------    let expression = RevsetExpression::commit(root_commit_id.clone());    let c = c.disambiguate_within(expression);    assert_eq!(        c.shortest_commit_prefix_len(repo.as_ref(), root_commit_id),        1    );    assert_eq!(        c.resolve_commit_prefix(repo.as_ref(), &prefix("")),        AmbiguousMatch    );    assert_eq!(        c.resolve_commit_prefix(repo.as_ref(), &prefix("0")),        SingleMatch(root_commit_id.clone())    );    assert_eq!(        c.shortest_change_prefix_len(repo.as_ref(), root_change_id),        1    );    assert_eq!(        c.resolve_change_prefix(repo.as_ref(), &prefix("")),        AmbiguousMatch    );    assert_eq!(        c.resolve_change_prefix(repo.as_ref(), &prefix("0")),        SingleMatch(vec![root_commit_id.clone()])    );     // Disambiguate within revset that fails to evaluate    // ---------------------------------------------------------------------------------------------    // TODO: Should be an error    let expression = RevsetExpression::symbol("nonexistent".to_string());    let context = c.disambiguate_within(expression);    assert_eq!(        context.shortest_commit_prefix_len(repo.as_ref(), commits[2].id()),        2    );    assert_eq!(        context.resolve_commit_prefix(repo.as_ref(), &prefix("2")),        AmbiguousMatch    );}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t