//!use std::convert::TryInto;use git_hash::ObjectId;use git_ref::FullNameRef;use crate::{ ext::{ObjectIdExt, ReferenceExt}, Head,};/// Represents the kind of `HEAD` reference.#[derive(Clone)]pub enum Kind { /// The existing reference the symbolic HEAD points to. /// /// This is the common case. Symbolic(git_ref::Reference), /// The yet-to-be-created reference the symbolic HEAD refers to. /// /// This is the case in a newly initialized repository. Unborn(git_ref::FullName), /// The head points to an object directly, not to a symbolic reference. /// /// This state is less common and can occur when checking out commits directly. Detached { /// The object to which the head points to target: ObjectId, /// Possibly the final destination of `target` after following the object chain from tag objects to commits. peeled: Option<ObjectId>, },}impl Kind { /// Attach this instance to a `repo` to produce a [`Head`]. pub fn attach(self, repo: &crate::Repository) -> Head<'_> { Head { kind: self, repo } }}/// Accessimpl<'repo> Head<'repo> { /// Returns the name of this references, always `HEAD`. pub fn name(&self) -> &'static FullNameRef { // TODO: use a statically checked version of this when available. "HEAD".try_into().expect("HEAD is valid") } /// Returns the full reference name of this head if it is not detached, or `None` otherwise. pub fn referent_name(&self) -> Option<&FullNameRef> { Some(match &self.kind { Kind::Symbolic(r) => r.name.as_ref(), Kind::Unborn(name) => name.as_ref(), Kind::Detached { .. } => return None, }) } /// Returns true if this instance is detached, and points to an object directly. pub fn is_detached(&self) -> bool { matches!(self.kind, Kind::Detached { .. }) } // TODO: tests /// Returns the id the head points to, which isn't possible on unborn heads. pub fn id(&self) -> Option<crate::Id<'repo>> { match &self.kind { Kind::Symbolic(r) => r.target.try_id().map(|oid| oid.to_owned().attach(self.repo)), Kind::Detached { peeled, target } => { (*peeled).unwrap_or_else(|| target.to_owned()).attach(self.repo).into() } Kind::Unborn(_) => None, } } /// Try to transform this instance into the symbolic reference that it points to, or return `None` if head is detached or unborn. pub fn try_into_referent(self) -> Option<crate::Reference<'repo>> { match self.kind { Kind::Symbolic(r) => r.attach(self.repo).into(), _ => None, } }}mod remote { use super::Head; use crate::{remote, Remote}; /// Remote impl<'repo> Head<'repo> { /// Return the remote with which the currently checked our reference can be handled as configured by `branch.<name>.remote|pushRemote` /// or fall back to the non-branch specific remote configuration. /// /// This is equivalent to calling [`Reference::remote(…)`][crate::Reference::remote()] and /// [`Repository::remote_default_name()`][crate::Repository::remote_default_name()] in order. pub fn into_remote( self, direction: remote::Direction, ) -> Option<Result<Remote<'repo>, remote::find::existing::Error>> { let repo = self.repo; self.try_into_referent()?.remote(direction).or_else(|| { repo.remote_default_name(direction) .map(|name| repo.find_remote(name.as_ref())) }) } }}///pub mod log;///pub mod peel;
//!
use std::convert::TryInto;
use git_hash::ObjectId;
use git_ref::FullNameRef;
use crate::{
ext::{ObjectIdExt, ReferenceExt},
Head,
};
/// Represents the kind of `HEAD` reference.
#[derive(Clone)]
pub enum Kind {
/// The existing reference the symbolic HEAD points to.
///
/// This is the common case.
Symbolic(git_ref::Reference),
/// The yet-to-be-created reference the symbolic HEAD refers to.
///
/// This is the case in a newly initialized repository.
Unborn(git_ref::FullName),
/// The head points to an object directly, not to a symbolic reference.
///
/// This state is less common and can occur when checking out commits directly.
Detached {
/// The object to which the head points to
target: ObjectId,
/// Possibly the final destination of `target` after following the object chain from tag objects to commits.
peeled: Option<ObjectId>,
},
}
impl Kind {
/// Attach this instance to a `repo` to produce a [`Head`].
pub fn attach(self, repo: &crate::Repository) -> Head<'_> {
Head { kind: self, repo }
}
}
/// Access
impl<'repo> Head<'repo> {
/// Returns the name of this references, always `HEAD`.
pub fn name(&self) -> &'static FullNameRef {
// TODO: use a statically checked version of this when available.
"HEAD".try_into().expect("HEAD is valid")
}
/// Returns the full reference name of this head if it is not detached, or `None` otherwise.
pub fn referent_name(&self) -> Option<&FullNameRef> {
Some(match &self.kind {
Kind::Symbolic(r) => r.name.as_ref(),
Kind::Unborn(name) => name.as_ref(),
Kind::Detached { .. } => return None,
})
}
/// Returns true if this instance is detached, and points to an object directly.
pub fn is_detached(&self) -> bool {
matches!(self.kind, Kind::Detached { .. })
}
// TODO: tests
/// Returns the id the head points to, which isn't possible on unborn heads.
pub fn id(&self) -> Option<crate::Id<'repo>> {
match &self.kind {
Kind::Symbolic(r) => r.target.try_id().map(|oid| oid.to_owned().attach(self.repo)),
Kind::Detached { peeled, target } => {
(*peeled).unwrap_or_else(|| target.to_owned()).attach(self.repo).into()
}
Kind::Unborn(_) => None,
}
}
/// Try to transform this instance into the symbolic reference that it points to, or return `None` if head is detached or unborn.
pub fn try_into_referent(self) -> Option<crate::Reference<'repo>> {
match self.kind {
Kind::Symbolic(r) => r.attach(self.repo).into(),
_ => None,
}
}
}
mod remote {
use super::Head;
use crate::{remote, Remote};
/// Remote
impl<'repo> Head<'repo> {
/// Return the remote with which the currently checked our reference can be handled as configured by `branch.<name>.remote|pushRemote`
/// or fall back to the non-branch specific remote configuration.
///
/// This is equivalent to calling [`Reference::remote(…)`][crate::Reference::remote()] and
/// [`Repository::remote_default_name()`][crate::Repository::remote_default_name()] in order.
pub fn into_remote(
self,
direction: remote::Direction,
) -> Option<Result<Remote<'repo>, remote::find::existing::Error>> {
let repo = self.repo;
self.try_into_referent()?.remote(direction).or_else(|| {
repo.remote_default_name(direction)
.map(|name| repo.find_remote(name.as_ref()))
})
}
}
}
///
pub mod log;
///
pub mod peel;