use gix_ref::{Category, FullName};
use crate::{
Reference,
bstr::{BStr, ByteSlice},
remote,
repository::{branch_remote_ref_name, branch_remote_tracking_ref_name},
};
impl<'repo> Reference<'repo> {
pub fn remote_name(&self, direction: remote::Direction) -> Option<remote::Name<'_>> {
let (category, shortname) = self.name().category_and_short_name()?;
match category {
Category::RemoteBranch => {
let mut remotes = None;
remote_name_from_tracking_branch(shortname, |candidate| {
remotes
.get_or_insert_with(|| self.repo.remote_names())
.contains(candidate)
})
.and_then(|name| name.to_str().ok())
.map(|name| remote::Name::Symbol(name.into()))
}
Category::LocalBranch => self.repo.branch_remote_name(shortname, direction),
_ => None,
}
}
pub fn remote(
&self,
direction: remote::Direction,
) -> Option<Result<crate::Remote<'repo>, remote::find::existing::Error>> {
self.repo.branch_remote(self.name().shorten(), direction)
}
#[doc(alias = "upstream", alias = "git2")]
pub fn remote_ref_name(
&self,
direction: remote::Direction,
) -> Option<Result<FullName, branch_remote_ref_name::Error>> {
self.repo.branch_remote_ref_name(self.name(), direction)
}
#[doc(alias = "upstream", alias = "git2")]
pub fn remote_tracking_ref_name(
&self,
direction: remote::Direction,
) -> Option<Result<FullName, branch_remote_tracking_ref_name::Error>> {
self.repo.branch_remote_tracking_ref_name(self.name(), direction)
}
}
pub(crate) fn remote_name_from_tracking_branch(
shortname: &BStr,
mut is_configured_remote: impl FnMut(&BStr) -> bool,
) -> Option<&BStr> {
if shortname.find_iter("/").take(2).count() == 1 {
let slash_pos = shortname.find_byte(b'/').expect("it was just found");
return Some(shortname[..slash_pos].as_bstr());
}
shortname
.rfind_iter("/")
.map(|slash_pos| shortname[..slash_pos].as_bstr())
.find(|candidate| is_configured_remote(candidate))
}