use std::path::PathBuf;
use crate::remote::fetch;
mod error {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
FindReference(#[from] crate::reference::find::Error),
#[error("A remote reference had a name that wasn't considered valid. Corrupt remote repo or insufficient checks on remote?")]
InvalidRefName(#[from] gix_validate::reference::name::Error),
#[error("Failed to update references to their new position to match their remote locations")]
EditReferences(#[from] crate::reference::edit::Error),
#[error("Failed to read or iterate worktree dir")]
WorktreeListing(#[from] std::io::Error),
#[error("Could not open worktree repository")]
OpenWorktreeRepo(#[from] crate::open::Error),
#[error("Could not find local commit for fast-forward ancestor check")]
FindCommit(#[from] crate::object::find::existing::Error),
#[error("Could not peel symbolic local reference to its ID")]
PeelToId(#[from] crate::reference::peel::Error),
#[error("Failed to follow a symbolic reference to assure worktree isn't affected")]
FollowSymref(#[from] gix_ref::file::find::existing::Error),
#[error(transparent)]
FindObject(#[from] crate::object::find::Error),
}
}
pub use error::Error;
#[derive(Debug, Clone)]
pub struct Outcome {
pub edits: Vec<gix_ref::transaction::RefEdit>,
pub updates: Vec<super::Update>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Mode {
NoChangeNeeded,
FastForward,
Forced,
New,
ImplicitTagNotSentByRemote,
RejectedSourceObjectNotFound {
id: gix_hash::ObjectId,
},
RejectedTagUpdate,
RejectedNonFastForward,
RejectedToReplaceWithUnborn,
RejectedCurrentlyCheckedOut {
worktree_dirs: Vec<PathBuf>,
},
}
impl std::fmt::Display for Mode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Mode::NoChangeNeeded => "up-to-date",
Mode::FastForward => "fast-forward",
Mode::Forced => "forced-update",
Mode::New => "new",
Mode::ImplicitTagNotSentByRemote => "unrelated tag on remote",
Mode::RejectedSourceObjectNotFound { id } => return write!(f, "rejected ({id} not found)"),
Mode::RejectedTagUpdate => "rejected (would overwrite existing tag)",
Mode::RejectedNonFastForward => "rejected (non-fast-forward)",
Mode::RejectedToReplaceWithUnborn => "rejected (refusing to overwrite existing with unborn ref)",
Mode::RejectedCurrentlyCheckedOut { worktree_dirs } => {
return write!(
f,
"rejected (cannot write into checked-out branch at \"{}\")",
worktree_dirs
.iter()
.filter_map(|d| d.to_str())
.collect::<Vec<_>>()
.join(", ")
)
}
}
.fmt(f)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum TypeChange {
DirectToSymbolic,
SymbolicToDirect,
}
impl Outcome {
pub fn iter_mapping_updates<'a, 'b>(
&self,
mappings: &'a [fetch::refmap::Mapping],
refspecs: &'b [gix_refspec::RefSpec],
extra_refspecs: &'b [gix_refspec::RefSpec],
) -> impl Iterator<
Item = (
&super::Update,
&'a fetch::refmap::Mapping,
Option<&'b gix_refspec::RefSpec>,
Option<&gix_ref::transaction::RefEdit>,
),
> {
self.updates.iter().zip(mappings.iter()).map(move |(update, mapping)| {
(
update,
mapping,
mapping.spec_index.get(refspecs, extra_refspecs),
update.edit_index.and_then(|idx| self.edits.get(idx)),
)
})
}
}