Skip to content

Commit d9e551b

Browse files
committed
feat: Add Reference::follow() as a way to peel symbolic refs step by step.
1 parent 5f6cf22 commit d9e551b

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

gix/src/reference/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl<'repo> Reference<'repo> {
6262
}
6363
}
6464

65+
/// Peeling
6566
impl<'repo> Reference<'repo> {
6667
/// Follow all symbolic targets this reference might point to and peel the underlying object
6768
/// to the end of the chain, and return it.
@@ -81,6 +82,18 @@ impl<'repo> Reference<'repo> {
8182
pub fn into_fully_peeled_id(mut self) -> Result<Id<'repo>, peel::Error> {
8283
self.peel_to_id_in_place()
8384
}
85+
86+
/// Follow this symbolic reference one level and return the ref it refers to.
87+
///
88+
/// Returns `None` if this is not a symbolic reference, hence the leaf of the chain.
89+
pub fn follow(&self) -> Option<Result<Reference<'repo>, gix_ref::file::find::existing::Error>> {
90+
self.inner.follow(&self.repo.refs).map(|res| {
91+
res.map(|r| Reference {
92+
inner: r,
93+
repo: self.repo,
94+
})
95+
})
96+
}
8497
}
8598

8699
mod edits;

gix/tests/reference/mod.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ mod find {
2323
use std::convert::TryInto;
2424

2525
use gix_ref as refs;
26-
use gix_ref::FullNameRef;
26+
use gix_ref::{FullName, FullNameRef, Target};
2727

2828
use crate::util::hex_to_id;
2929

@@ -64,6 +64,25 @@ mod find {
6464
assert_eq!(symbolic_ref.into_fully_peeled_id()?, the_commit, "idempotency");
6565
Ok(())
6666
}
67+
68+
#[test]
69+
fn and_follow() -> crate::Result {
70+
let repo = repo()?;
71+
let mut symbolic_ref = repo.find_reference("multi-link-target1")?;
72+
let first_hop = Target::Symbolic(FullName::try_from("refs/tags/multi-link-target2").expect("valid"));
73+
assert_eq!(symbolic_ref.target(), first_hop.to_ref());
74+
75+
let second_hop = Target::Symbolic(FullName::try_from("refs/remotes/origin/multi-link-target3").expect("valid"));
76+
symbolic_ref = symbolic_ref.follow().expect("another hop")?;
77+
assert_eq!(symbolic_ref.target(), second_hop.to_ref());
78+
79+
let last_hop = Target::Peeled(hex_to_id("134385f6d781b7e97062102c6a483440bfda2a03"));
80+
symbolic_ref = symbolic_ref.follow().expect("another hop")?;
81+
assert_eq!(symbolic_ref.target(), last_hop.to_ref());
82+
83+
assert!(symbolic_ref.follow().is_none(), "direct references can't be followed");
84+
Ok(())
85+
}
6786
}
6887

6988
#[test]

0 commit comments

Comments
 (0)