2 use std
::convert
::TryInto
;
4 use gix_hash
::ObjectId
;
5 use gix_ref
::FullNameRef
;
8 ext
::{ObjectIdExt, ReferenceExt}
,
12 /// Represents the kind of `HEAD` reference.
15 /// The existing reference the symbolic HEAD points to.
17 /// This is the common case.
18 Symbolic(gix_ref
::Reference
),
19 /// The yet-to-be-created reference the symbolic HEAD refers to.
21 /// This is the case in a newly initialized repository.
22 Unborn(gix_ref
::FullName
),
23 /// The head points to an object directly, not to a symbolic reference.
25 /// This state is less common and can occur when checking out commits directly.
27 /// The object to which the head points to
29 /// Possibly the final destination of `target` after following the object chain from tag objects to commits.
30 peeled
: Option
<ObjectId
>,
35 /// Attach this instance to a `repo` to produce a [`Head`].
36 pub fn attach(self, repo
: &crate::Repository
) -> Head
<'_
> {
37 Head { kind: self, repo }
42 impl<'repo
> Head
<'repo
> {
43 /// Returns the name of this references, always `HEAD`.
44 pub fn name(&self) -> &'
static FullNameRef
{
45 // TODO: use a statically checked version of this when available.
46 "HEAD".try_into().expect("HEAD is valid")
49 /// Returns the full reference name of this head if it is not detached, or `None` otherwise.
50 pub fn referent_name(&self) -> Option
<&FullNameRef
> {
51 Some(match &self.kind
{
52 Kind
::Symbolic(r
) => r
.name
.as_ref(),
53 Kind
::Unborn(name
) => name
.as_ref(),
54 Kind
::Detached { .. }
=> return None
,
58 /// Returns true if this instance is detached, and points to an object directly.
59 pub fn is_detached(&self) -> bool
{
60 matches
!(self.kind
, Kind
::Detached { .. }
)
63 /// Returns true if this instance is not yet born, hence it points to a ref that doesn't exist yet.
65 /// This is the case in a newly initialized repository.
66 pub fn is_unborn(&self) -> bool
{
67 matches
!(self.kind
, Kind
::Unborn(_
))
71 /// Returns the id the head points to, which isn't possible on unborn heads.
72 pub fn id(&self) -> Option
<crate::Id
<'repo
>> {
74 Kind
::Symbolic(r
) => r
.target
.try_id().map(|oid
| oid
.to_owned().attach(self.repo
)),
75 Kind
::Detached { peeled, target }
=> {
76 (*peeled
).unwrap_or_else(|| target
.to_owned()).attach(self.repo
).into()
78 Kind
::Unborn(_
) => None
,
82 /// Try to transform this instance into the symbolic reference that it points to, or return `None` if head is detached or unborn.
83 pub fn try_into_referent(self) -> Option
<crate::Reference
<'repo
>> {
85 Kind
::Symbolic(r
) => r
.attach(self.repo
).into(),
93 use crate::{remote, Remote}
;
96 impl<'repo
> Head
<'repo
> {
97 /// Return the remote with which the currently checked our reference can be handled as configured by `branch.<name>.remote|pushRemote`
98 /// or fall back to the non-branch specific remote configuration. `None` is returned if the head is detached or unborn, so there is
99 /// no branch specific remote.
101 /// This is equivalent to calling [`Reference::remote(…)`][crate::Reference::remote()] and
102 /// [`Repository::remote_default_name()`][crate::Repository::remote_default_name()] in order.
104 /// Combine it with [`Repository::find_default_remote()`][crate::Repository::find_default_remote()] as fallback to
105 /// handle detached heads, i.e. obtain a remote even in case of detached heads,
106 /// or call [`Repository::find_fetch_remote(…)`](crate::Repository::find_fetch_remote()) for the highest-level way of finding
107 /// the right remote, just like `git fetch` does.
110 direction
: remote
::Direction
,
111 ) -> Option
<Result
<Remote
<'repo
>, remote
::find
::existing
::Error
>> {
112 let repo
= self.repo
;
113 self.try_into_referent()?
115 .or_else(|| repo
.find_default_remote(direction
))