1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
use std::borrow::Cow;
use bstr::{BStr, BString};
use gix_hash::oid;
use crate::RefSpecRef;
/// A match group is able to match a list of ref specs in order while handling negation, conflicts and one to many mappings.
#[derive(Default, Debug, Clone)]
pub struct MatchGroup<'a> {
/// The specs that take part in item matching.
pub specs: Vec<RefSpecRef<'a>>,
}
/// The outcome of any matching operation of a [`MatchGroup`].
///
/// It's used to validate and process the contained [mappings][Mapping].
#[derive(Debug, Clone)]
pub struct Outcome<'spec, 'item> {
/// The match group that produced this outcome.
pub group: MatchGroup<'spec>,
/// The mappings derived from matching [items][Item].
pub mappings: Vec<Mapping<'item, 'spec>>,
}
/// An item to match, input to various matching operations.
#[derive(Debug, Copy, Clone)]
pub struct Item<'a> {
/// The full name of the references, like `refs/heads/main`
pub full_ref_name: &'a BStr,
/// The id that `full_ref_name` points to, which typically is a commit, but can also be a tag object (or anything else).
pub target: &'a oid,
/// The object an annotated tag is pointing to, if `target` is an annotated tag.
pub object: Option<&'a oid>,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
/// The source (or left-hand) side of a mapping, which references its name.
pub enum SourceRef<'a> {
/// A full reference name, which is expected to be valid.
///
/// Validity, however, is not enforced here.
FullName(&'a BStr),
/// The name of an object that is expected to exist on the remote side.
/// Note that it might not be advertised by the remote but part of the object graph,
/// and thus gets sent in the pack. The server is expected to fail unless the desired
/// object is present but at some time it is merely a request by the user.
ObjectId(gix_hash::ObjectId),
}
impl SourceRef<'_> {
/// Create a fully owned instance from this one.
pub fn to_owned(&self) -> Source {
match self {
SourceRef::ObjectId(id) => Source::ObjectId(*id),
SourceRef::FullName(name) => Source::FullName((*name).to_owned()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
/// The source (or left-hand) side of a mapping, which owns its name.
pub enum Source {
/// A full reference name, which is expected to be valid.
///
/// Validity, however, is not enforced here.
FullName(BString),
/// The name of an object that is expected to exist on the remote side.
/// Note that it might not be advertised by the remote but part of the object graph,
/// and thus gets sent in the pack. The server is expected to fail unless the desired
/// object is present but at some time it is merely a request by the user.
ObjectId(gix_hash::ObjectId),
}
impl std::fmt::Display for Source {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Source::FullName(name) => name.fmt(f),
Source::ObjectId(id) => id.fmt(f),
}
}
}
/// A mapping from a remote to a local refs for fetches or local to remote refs for pushes.
///
/// Mappings are like edges in a graph, initially without any constraints.
#[derive(Debug, Clone)]
pub struct Mapping<'a, 'b> {
/// The index into the initial `items` list that matched against a spec.
pub item_index: Option<usize>,
/// The name of the remote side for fetches or the local one for pushes that matched.
pub lhs: SourceRef<'a>,
/// The name of the local side for fetches or the remote one for pushes that corresponds to `lhs`, if available.
pub rhs: Option<Cow<'b, BStr>>,
/// The index of the matched ref-spec as seen from the match group.
pub spec_index: usize,
}
impl std::hash::Hash for Mapping<'_, '_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.lhs.hash(state);
self.rhs.hash(state);
}
}