Skip to content

Commit a1680b4

Browse files
committed
fix: Commit::describe() now returns annnotated tags before lighweight ones and prefers more recent ones as well (#389)
Fixes #389
1 parent 0d9f6c6 commit a1680b4

File tree

4 files changed

+33
-22
lines changed

4 files changed

+33
-22
lines changed

git-repository/src/commit.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,37 @@ pub mod describe {
7171
repo: &Repository,
7272
) -> Result<git_revision::hash_hasher::HashedMap<ObjectId, Cow<'static, BStr>>, Error> {
7373
let platform = repo.references()?;
74-
let into_tuple =
75-
|r: crate::Reference<'_>| (r.inner.target.into_id(), Cow::from(r.inner.name.shorten().to_owned()));
7674

7775
Ok(match self {
78-
SelectRef::AllTags => platform
79-
.tags()?
80-
.peeled()
76+
SelectRef::AllTags | SelectRef::AllRefs => {
77+
let mut refs: Vec<_> = match self {
78+
SelectRef::AllRefs => platform.all()?,
79+
SelectRef::AllTags => platform.tags()?,
80+
_ => unreachable!(),
81+
}
8182
.filter_map(Result::ok)
82-
.map(into_tuple)
83-
.collect(),
84-
SelectRef::AllRefs => platform
85-
.all()?
86-
.peeled()
87-
.filter_map(Result::ok)
88-
.map(into_tuple)
89-
.collect(),
83+
.filter_map(|mut r: crate::Reference<'_>| {
84+
let target_id = r.target().try_id().map(ToOwned::to_owned);
85+
let peeled_id = r.peel_to_id_in_place().ok()?;
86+
let (prio, tag_time) = match target_id {
87+
Some(target_id) if peeled_id != *target_id => {
88+
let tag = repo.find_object(target_id).ok()?.try_into_tag().ok()?;
89+
(1, tag.tagger().ok()??.time.seconds_since_unix_epoch)
90+
}
91+
_ => (0, 0),
92+
};
93+
(
94+
peeled_id.inner,
95+
prio,
96+
tag_time,
97+
Cow::from(r.inner.name.shorten().to_owned()),
98+
)
99+
.into()
100+
})
101+
.collect();
102+
refs.sort_by(|a, b| a.2.cmp(&b.2).then_with(|| a.1.cmp(&b.1))); // by time ascending, then by priority. Older entries overwrite newer ones.
103+
refs.into_iter().map(|(a, _, _, b)| (a, b)).collect()
104+
}
90105
SelectRef::AnnotatedTags => {
91106
let mut peeled_commits_and_tag_date: Vec<_> = platform
92107
.tags()?
@@ -104,9 +119,7 @@ pub mod describe {
104119
Some((commit_id, tag_time, r.name().shorten().to_owned().into()))
105120
})
106121
.collect();
107-
// TODO: this kind of sorting would also have to apply to the AllRefs/AlLTags cases, where annotated tags are preferred
108-
// and sorted accordingly.
109-
peeled_commits_and_tag_date.sort_by(|a, b| a.1.cmp(&b.1).reverse()); // by time, ascending, causing older names to overwrite newer ones.
122+
peeled_commits_and_tag_date.sort_by(|a, b| a.1.cmp(&b.1)); // by time, ascending, causing older names to overwrite newer ones.
110123
peeled_commits_and_tag_date
111124
.into_iter()
112125
.map(|(a, _, c)| (a, c))

git-repository/tests/commit/mod.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@ mod describe {
33
use git_repository::commit::describe::SelectRef::{AllRefs, AllTags, AnnotatedTags};
44

55
#[test]
6-
#[ignore]
76
fn tags_are_sorted_by_date_and_lexigraphically() {
87
let repo = named_repo("make_commit_describe_multiple_tags.sh").unwrap();
98
let mut describe = repo.head_commit().unwrap().describe();
109
for filter in &[AnnotatedTags, AllTags, AllRefs] {
1110
describe = describe.names(*filter);
12-
assert_eq!(describe.format().unwrap().to_string(), "v1", "{:?}", filter);
11+
assert_eq!(describe.format().unwrap().to_string(), "v2", "{:?}", filter);
1312
}
14-
let mut describe = describe.names(AllRefs);
15-
assert_eq!(describe.format().unwrap().to_string(), "v1");
1613
}
1714
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:28fb09e31eca8d5c43d5b93918691ef3cc9007d97edb73ef803e505353f3ed46
3-
size 10396
2+
oid sha256:22fd60100187fc3f4180b31d3ae1d8c5506a65c3ee059b4bbc3a40009fb23f60
3+
size 10408

git-repository/tests/fixtures/make_commit_describe_multiple_tags.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ git commit --allow-empty -q -m c2
77

88
git tag v0 -m "tag object 0" "HEAD~1"
99
git tag v1 -m "tag object 1"
10+
git tag v1.5
1011
GIT_COMMITTER_DATE="2022-01-02 00:00:00 +0000" git tag v2 -m "tag object 2"

0 commit comments

Comments
 (0)