Skip to content

Commit

Permalink
assure ref-specs handle equality, ordering and hashing according to t…
Browse files Browse the repository at this point in the history
…heir instruction (#450)

That way, it's possible to treat dissimilar yet effectively equal specs
like they are equal.
  • Loading branch information
Byron committed Aug 9, 2022
1 parent 4347a96 commit b4bf7d0
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 7 deletions.
4 changes: 2 additions & 2 deletions git-refspec/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ impl Instruction<'_> {

/// Note that all sources can either be a ref-name, partial or full, or a rev-spec, unless specified otherwise, on the local side.
/// Destinations can only be a partial or full ref names on the remote side.
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum Push<'a> {
/// Push all local branches to the matching destination on the remote, which has to exist to be updated.
AllMatchingBranches {
Expand All @@ -39,7 +39,7 @@ pub enum Push<'a> {
/// Any source can either be a ref name (full or partial) or a fully spelled out hex-sha for an object, on the remote side.
///
/// Destinations can only be a partial or full ref-names on the local side.
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum Fetch<'a> {
/// Fetch a ref or refs and write the result into the `FETCH_HEAD` without updating local branches.
Only {
Expand Down
4 changes: 2 additions & 2 deletions git-refspec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use parse::function::parse;
pub mod instruction;

/// A refspec with references to the memory it was parsed from.
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[derive(Ord, Eq, Copy, Clone, Debug)]
pub struct RefSpecRef<'a> {
mode: types::Mode,
op: parse::Operation,
Expand All @@ -19,7 +19,7 @@ pub struct RefSpecRef<'a> {
}

/// An owned refspec.
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
#[derive(Ord, Eq, Clone, Debug)]
pub struct RefSpec {
mode: types::Mode,
op: parse::Operation,
Expand Down
2 changes: 1 addition & 1 deletion git-refspec/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub enum Error {
}

/// Define how the parsed refspec should be used.
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum Operation {
/// The `src` side is local and the `dst` side is remote.
Push,
Expand Down
38 changes: 38 additions & 0 deletions git-refspec/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,50 @@ impl RefSpec {

mod impls {
use crate::{RefSpec, RefSpecRef};
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};

impl From<RefSpecRef<'_>> for RefSpec {
fn from(v: RefSpecRef<'_>) -> Self {
v.to_owned()
}
}

impl Hash for RefSpec {
fn hash<H: Hasher>(&self, state: &mut H) {
self.to_ref().hash(state)
}
}

impl Hash for RefSpecRef<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.instruction().hash(state)
}
}

impl PartialEq for RefSpec {
fn eq(&self, other: &Self) -> bool {
self.to_ref().eq(&other.to_ref())
}
}

impl PartialEq for RefSpecRef<'_> {
fn eq(&self, other: &Self) -> bool {
self.instruction().eq(&other.instruction())
}
}

impl PartialOrd for RefSpecRef<'_> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.instruction().partial_cmp(&other.instruction())
}
}

impl PartialOrd for RefSpec {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.to_ref().partial_cmp(&other.to_ref())
}
}
}

/// Access
Expand Down
4 changes: 2 additions & 2 deletions git-refspec/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::instruction;

/// The way to interpret a refspec.
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub(crate) enum Mode {
/// Apply standard rules for refspecs which are including refs with specific rules related to allowing fast forwards of destinations.
Normal,
Expand All @@ -12,7 +12,7 @@ pub(crate) enum Mode {
}

/// Tells what to do and is derived from a [`RefSpec`][crate::RefSpecRef].
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum Instruction<'a> {
/// An instruction for pushing.
Push(instruction::Push<'a>),
Expand Down
27 changes: 27 additions & 0 deletions git-refspec/tests/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use git_refspec::parse::Operation;
use git_refspec::RefSpec;
use std::collections::{BTreeSet, HashSet};
use std::iter::FromIterator;

fn pair() -> Vec<RefSpec> {
let lhs = git_refspec::parse("refs/heads/foo".into(), Operation::Push).unwrap();
let rhs = git_refspec::parse("refs/heads/foo:refs/heads/foo".into(), Operation::Push).unwrap();
vec![lhs.to_owned(), rhs.to_owned()]
}

#[test]
fn cmp() {
assert_eq!(BTreeSet::from_iter(pair()).len(), 1)
}

#[test]
fn hash() {
let set: HashSet<_> = pair().into_iter().collect();
assert_eq!(set.len(), 1)
}

#[test]
fn eq() {
let specs = pair();
assert_eq!(&specs[0], &specs[1]);
}
1 change: 1 addition & 0 deletions git-refspec/tests/refspec.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
mod impls;
mod parse;

0 comments on commit b4bf7d0

Please sign in to comment.