fix(git): peel les tags annotés vers leur commit cible dans log_graph — #218
This commit is contained in:
@ -207,8 +207,9 @@ impl GitPort for Git2Repository {
|
|||||||
let mut ref_map: HashMap<git2::Oid, Vec<String>> = HashMap::new();
|
let mut ref_map: HashMap<git2::Oid, Vec<String>> = HashMap::new();
|
||||||
if let Ok(references) = repo.references() {
|
if let Ok(references) = repo.references() {
|
||||||
for reference in references.flatten() {
|
for reference in references.flatten() {
|
||||||
// Only handle symbolic and direct refs; skip errors.
|
// Only handle refs that resolve to commits; annotated tags point at
|
||||||
let target_oid = reference.resolve().ok().and_then(|r| r.target());
|
// tag objects, so `target()` alone would never match revwalk commits.
|
||||||
|
let target_oid = reference_commit_oid(&reference);
|
||||||
if let Some(oid) = target_oid {
|
if let Some(oid) = target_oid {
|
||||||
let label = match reference.shorthand() {
|
let label = match reference.shorthand() {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
@ -269,3 +270,16 @@ impl GitPort for Git2Repository {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reference_commit_oid(reference: &git2::Reference<'_>) -> Option<git2::Oid> {
|
||||||
|
reference
|
||||||
|
.peel(git2::ObjectType::Commit)
|
||||||
|
.ok()
|
||||||
|
.map(|object| object.id())
|
||||||
|
.or_else(|| {
|
||||||
|
reference
|
||||||
|
.resolve()
|
||||||
|
.ok()
|
||||||
|
.and_then(|resolved| resolved.target())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -111,3 +111,45 @@ async fn unstage_after_first_commit_resets_index() {
|
|||||||
let a = st.iter().find(|s| s.path == "a.txt").unwrap();
|
let a = st.iter().find(|s| s.path == "a.txt").unwrap();
|
||||||
assert!(!a.staged, "unstaged change is no longer in the index");
|
assert!(!a.staged, "unstaged change is no longer in the index");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn git_graph_labels_annotated_tags_on_their_target_commit() {
|
||||||
|
let tmp = TempDir::new();
|
||||||
|
let root = tmp.root();
|
||||||
|
let git = Git2Repository::new();
|
||||||
|
git.init(&root).await.unwrap();
|
||||||
|
|
||||||
|
tmp.write("a.txt", "v1");
|
||||||
|
git.stage(&root, "a.txt").await.unwrap();
|
||||||
|
let tagged = git.commit(&root, "tagged commit").await.unwrap();
|
||||||
|
|
||||||
|
tmp.write("a.txt", "v2");
|
||||||
|
git.stage(&root, "a.txt").await.unwrap();
|
||||||
|
git.commit(&root, "head commit").await.unwrap();
|
||||||
|
|
||||||
|
let repo = git2::Repository::open(root.as_str()).unwrap();
|
||||||
|
let target = repo
|
||||||
|
.find_object(
|
||||||
|
git2::Oid::from_str(&tagged.hash).unwrap(),
|
||||||
|
Some(git2::ObjectType::Commit),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let sig = repo
|
||||||
|
.signature()
|
||||||
|
.or_else(|_| git2::Signature::now("IdeA", "idea@localhost"))
|
||||||
|
.unwrap();
|
||||||
|
repo.tag("v0.13.0", &target, &sig, "release v0.13.0", false)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let graph = git.log_graph(&root, 10).await.unwrap();
|
||||||
|
let commit = graph
|
||||||
|
.iter()
|
||||||
|
.find(|commit| commit.hash == tagged.hash)
|
||||||
|
.expect("tagged ancestor commit is included in graph");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
commit.refs.iter().any(|r| r == "tag: v0.13.0"),
|
||||||
|
"annotated tag must be attached to target commit refs, got {:?}",
|
||||||
|
commit.refs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user