Skip to content

Commit

Permalink
lib id_prefix: demo bug #2476 in a test
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyagr committed Jun 29, 2024
1 parent e21e5e6 commit a49a218
Showing 1 changed file with 137 additions and 1 deletion.
138 changes: 137 additions & 1 deletion lib/tests/test_id_prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.

use itertools::Itertools;
use jj_lib::backend::{CommitId, MillisSinceEpoch, Signature, Timestamp};
use jj_lib::backend::{ChangeId, 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};
Expand Down Expand Up @@ -253,3 +253,139 @@ fn test_id_prefix() {
AmbiguousMatch
);
}

#[test]
fn test_id_prefix_divergent() {
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 mut tx = repo.start_transaction(&settings);
let mut create_commit_with_change_id =
|parent_id: &CommitId, description: &str, change_id: Option<ChangeId>| {
let signature = Signature {
name: "Some One".to_string(),
email: "[email protected]".to_string(),
timestamp: Timestamp {
timestamp: MillisSinceEpoch(0),
tz_offset: 0,
},
};
let mut builder = tx
.mut_repo()
.new_commit(
&settings,
vec![parent_id.clone()],
repo.store().empty_merged_tree_id(),
)
.set_description(description)
.set_author(signature.clone())
.set_committer(signature);
if let Some(change_id) = change_id {
builder = builder.set_change_id(change_id);
}
builder.write().unwrap()
};

let first_commit = create_commit_with_change_id(root_commit_id, "first", None);
let first_change_id = first_commit.change_id();
let mut different_change_id_bytes = first_change_id.to_bytes();
// Change the second byte of the change id, which corresponds to the third and
// fourth letter.
different_change_id_bytes[1] = different_change_id_bytes[1].wrapping_add(128);
let different_change_id = ChangeId::from_bytes(&different_change_id_bytes);

let second_commit = create_commit_with_change_id(
first_commit.id(),
"second",
Some(different_change_id.clone()),
);
let third_commit_divergent_with_second =
create_commit_with_change_id(first_commit.id(), "third", Some(different_change_id));
let commits = [
first_commit.clone(),
second_commit.clone(),
third_commit_divergent_with_second.clone(),
];
let repo = tx.commit("test");

// Print the commit IDs and change IDs for reference
let change_prefixes = commits
.iter()
.enumerate()
.map(|(i, commit)| format!("{} {}", &commit.change_id().hex()[..4], i))
.sorted()
.join("\n");
insta::assert_snapshot!(change_prefixes, @r###"
7811 0
7891 1
7891 2
"###);
let commit_prefixes = commits
.iter()
.enumerate()
.map(|(i, commit)| format!("{} {}", &commit.id().hex()[..4], i))
.sorted()
.join("\n");
insta::assert_snapshot!(commit_prefixes, @r###"
2fbb 2
d48d 1
eafa 0
"###);

let prefix = |x| HexPrefix::new(x).unwrap();

// Without a disambiguation revset
// ---------------------------------------------------------------------------------------------
let c = IdPrefixContext::default();
assert_eq!(
c.shortest_change_prefix_len(repo.as_ref(), commits[0].change_id()),
3
);
assert_eq!(
c.shortest_change_prefix_len(repo.as_ref(), commits[1].change_id()),
3
);
assert_eq!(
c.shortest_change_prefix_len(repo.as_ref(), commits[2].change_id()),
3
);
assert_eq!(
c.resolve_change_prefix(repo.as_ref(), &prefix("7")),
AmbiguousMatch
);
assert_eq!(
c.resolve_change_prefix(repo.as_ref(), &prefix("781")),
SingleMatch(vec![first_commit.id().clone()])
);
assert_eq!(
c.resolve_change_prefix(repo.as_ref(), &prefix("789")),
SingleMatch(vec![
second_commit.id().clone(),
third_commit_divergent_with_second.id().clone()
])
);

// Now, disambiguate within the revset containing only the second commit
// ---------------------------------------------------------------------------------------------
let expression = RevsetExpression::commits(vec![second_commit.id().clone()]);
let c = c.disambiguate_within(expression);
// The prefix is now shorter
assert_eq!(
c.shortest_change_prefix_len(repo.as_ref(), second_commit.change_id()),
1
);
// We can still resolve commits outside the set
assert_eq!(
c.resolve_change_prefix(repo.as_ref(), &prefix("781")),
SingleMatch(vec![first_commit.id().clone()])
);
// Short prefix does not find the first commit (as intended).
// TODO(#2476): Looking up the divergent commits by their change id prefix only
// finds the id within the lookup set.
assert_eq!(
c.resolve_change_prefix(repo.as_ref(), &prefix("7")),
SingleMatch(vec![second_commit.id().clone()])
);
}

0 comments on commit a49a218

Please sign in to comment.