Skip to content

Commit

Permalink
refactor(revspec): use git describe for finding latest tag
Browse files Browse the repository at this point in the history
Rather than implementing a tag walk ourselves, leverage `git describe`.

Tested: Ran `cargo nextest run` to ensure all local tests passed.

    Summary [   0.496s] 226 tests run: 226 passed, 0 skipped

Signed-off-by: Luke Hsiao <luke.hsiao@numbersstation.ai>
  • Loading branch information
lukehsiao authored and oknozor committed Aug 1, 2023
1 parent 36d1ea5 commit 9a49999
Showing 1 changed file with 7 additions and 41 deletions.
48 changes: 7 additions & 41 deletions src/git/revspec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt;
use std::fmt::Formatter;
use std::str::FromStr;

use git2::{Commit, ErrorCode, Oid};
use git2::{Commit, DescribeFormatOptions, DescribeOptions, ErrorCode, Oid};

use crate::conventional::changelog::release::Release;
use crate::git::error::Git2Error;
Expand Down Expand Up @@ -347,46 +347,12 @@ impl Repository {
fn get_latest_tag_starting_from(&self, starting_point: Oid) -> Result<Tag, Git2Error> {
let starting_point = self.0.find_commit(starting_point)?;
let starting_point = starting_point.parent(0)?;
let first_commit = self.get_first_commit()?;
let mut revwalk = self.0.revwalk()?;
let range = format!("{}..{}", first_commit, starting_point.id());

revwalk.push_range(&range)?;
let mut range = vec![];
for oid in revwalk {
range.push(oid?);
}

let mut tags = vec![];
self.0
.tag_foreach(|mut oid, name| {
let name = String::from_utf8_lossy(name);
let name = name.as_ref().strip_prefix("refs/tags/").unwrap();

// If this is an annotated tag, find the first parent commit
if self.0.revparse_single(name).unwrap().as_commit().is_none() {
if let Some(commit) = self
.0
.revparse_single([name, "^{}"].concat().as_str())
.unwrap()
.as_commit()
{
oid = commit.id();
}
};

if range.contains(&oid) {
if let Ok(tag) = Tag::from_str(name, Some(oid)) {
tags.push(tag);
};
};
true
})
.expect("Unable to walk tags");

let latest_tag: Option<Tag> = tags.into_iter().max();

latest_tag.ok_or(Git2Error::NoTagFound)
let describe = starting_point
.as_object()
.describe(DescribeOptions::new().describe_tags())?;
let tag_name = describe.format(Some(DescribeFormatOptions::new().abbreviated_size(0)))?;
let tag_oid = self.0.refname_to_id(&format!("refs/tags/{tag_name}")).ok();
Tag::from_str(&tag_name, tag_oid).map_err(|_| Git2Error::NoTagFound)
}
}

Expand Down

0 comments on commit 9a49999

Please sign in to comment.