Skip to content

Commit

Permalink
tests for handling exclusions (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Aug 6, 2022
1 parent c99f575 commit c4499ce
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 40 deletions.
2 changes: 1 addition & 1 deletion git-refspec/src/parse.rs
Expand Up @@ -73,7 +73,7 @@ pub(crate) mod function {

let (src, src_had_pattern) = validated(src)?;
let (dst, dst_had_pattern) = validated(dst)?;
if src_had_pattern != dst_had_pattern {
if mode != Mode::Negative && src_had_pattern != dst_had_pattern {
return Err(Error::PatternUnbalanced);
}
Ok(RefSpecRef {
Expand Down
84 changes: 48 additions & 36 deletions git-refspec/src/spec.rs
Expand Up @@ -14,48 +14,60 @@ impl RefSpecRef<'_> {
fn has_pattern(item: &BStr) -> bool {
item.contains(&b'*')
}
match (self.op, self.mode, self.src, self.dst) {
(Operation::Fetch, Mode::Normal | Mode::Force, Some(src), None) => Instruction::Fetch(Fetch::Only { src }),
(Operation::Fetch, Mode::Normal | Mode::Force, Some(src), Some(dst)) => {
Instruction::Fetch(Fetch::AndUpdateSingle {
match self.op {
Operation::Fetch => match (self.mode, self.src, self.dst) {
(Mode::Normal | Mode::Force, Some(src), None) => Instruction::Fetch(Fetch::Only { src }),
(Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Fetch(Fetch::AndUpdateSingle {
src,
dst,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
})
}
(Operation::Push, Mode::Normal | Mode::Force, Some(src), None) => Instruction::Push(Push::Single {
src,
dst: src,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
}),
(Operation::Push, Mode::Normal | Mode::Force, None, Some(dst)) => {
Instruction::Push(Push::Delete { ref_or_pattern: dst })
}
(Operation::Push, Mode::Normal | Mode::Force, None, None) => Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: matches!(self.mode, Mode::Force),
}),
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dst)) if has_pattern(src) => {
Instruction::Push(Push::MultipleWithGlob {
}),
(Mode::Negative, Some(src), None) if has_pattern(src) => {
Instruction::Fetch(Fetch::ExcludeMultipleWithGlob { src })
}
(Mode::Negative, Some(src), None) => Instruction::Fetch(Fetch::ExcludeSingle { src }),
(mode, src, dest) => {
unreachable!(
"BUG: fetch instructions with {:?} {:?} {:?} are not possible",
mode, src, dest
)
}
},
Operation::Push => match (self.mode, self.src, self.dst) {
(Mode::Normal | Mode::Force, Some(src), None) => Instruction::Push(Push::Single {
src,
dst: src,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
}),
(Mode::Normal | Mode::Force, None, Some(dst)) => {
Instruction::Push(Push::Delete { ref_or_pattern: dst })
}
(Mode::Normal | Mode::Force, None, None) => Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: matches!(self.mode, Mode::Force),
}),
(Mode::Normal | Mode::Force, Some(src), Some(dst)) if has_pattern(src) => {
Instruction::Push(Push::MultipleWithGlob {
src,
dst,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
})
}
(Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Push(Push::Single {
src,
dst,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
})
}
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Push(Push::Single {
src,
dst,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
}),
(Operation::Push, Mode::Negative, Some(src), None) if has_pattern(src) => {
Instruction::Push(Push::ExcludeMultipleWithGlob { src })
}
(Operation::Push, Mode::Negative, Some(src), None) => Instruction::Push(Push::ExcludeSingle { src }),
(op, mode, src, dest) => {
unreachable!(
"BUG: instructions with {:?} {:?} {:?} {:?} are not possible",
op, mode, src, dest
)
}
}),
(Mode::Negative, Some(src), None) if has_pattern(src) => {
Instruction::Push(Push::ExcludeMultipleWithGlob { src })
}
(Mode::Negative, Some(src), None) => Instruction::Push(Push::ExcludeSingle { src }),
(mode, src, dest) => {
unreachable!(
"BUG: push instructions with {:?} {:?} {:?} are not possible",
mode, src, dest
)
}
},
}
}
}
Expand Down
10 changes: 7 additions & 3 deletions git-refspec/src/types.rs
Expand Up @@ -26,6 +26,7 @@ pub enum Instruction<'a> {
Fetch(Fetch<'a>),
}

/// Note that all sources can either be a ref-name, partial or full, or a rev-spec. Destinations can only be a partial or full ref name.
#[derive(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.
Expand Down Expand Up @@ -59,7 +60,7 @@ pub enum Push<'a> {
},
/// Push a multiple refs to matching destination refs, with exactly a single glob on both sides.
MultipleWithGlob {
/// The source ref to match against all refs for pushing.
/// The source ref to match against all refs for pushing, as pattern with a single `*`.
src: &'a BStr,
/// The ref to update with object obtained from `src`, filling in the `*` with the portion that matched in `src`.
dst: &'a BStr,
Expand All @@ -68,10 +69,13 @@ pub enum Push<'a> {
},
}

/// Note that any source can either be a ref name (full or partial) or a fully spelled out hex-sha for an object.
///
/// Destinations can only be a partial or full ref-name.
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
pub enum Fetch<'a> {
Only {
/// The ref name to fetch on the remote side, without updating the local side.
/// The ref name to fetch on the remote side, without updating the local side. This will write the result into `FETCH_HEAD`.
src: &'a BStr,
},
/// Exclude a single ref.
Expand All @@ -94,7 +98,7 @@ pub enum Fetch<'a> {
},
/// Similar to `FetchAndUpdate`, but src and destination contain a single glob to fetch and update multiple refs.
AndUpdateMultipleWithGlob {
/// The ref glob to match against all refs on the remote side for fetching.
/// The ref glob to match against all refs on the remote side for fetching, as pattern with a single `*`.
src: &'a BStr,
/// The local destination to update with what was fetched by replacing the single `*` with the matching portion from `src`.
dst: &'a BStr,
Expand Down
23 changes: 23 additions & 0 deletions git-refspec/tests/parse/mod.rs
Expand Up @@ -108,6 +108,19 @@ mod fetch {
use crate::parse::{assert_parse, b};
use git_refspec::{Fetch, Instruction, Mode};

#[test]
fn exclude_single() {
assert_parse("^a", Instruction::Fetch(Fetch::ExcludeSingle { src: b("a") }));
}

#[test]
fn exclude_multiple() {
assert_parse(
"^a*",
Instruction::Fetch(Fetch::ExcludeMultipleWithGlob { src: b("a*") }),
);
}

#[test]
fn lhs_colon_empty_fetches_only() {
assert_parse("src:", Instruction::Fetch(Fetch::Only { src: b("src") }));
Expand Down Expand Up @@ -157,6 +170,16 @@ mod push {
use crate::parse::{assert_parse, b};
use git_refspec::{Instruction, Mode, Push};

#[test]
fn exclude_single() {
assert_parse("^a", Instruction::Push(Push::ExcludeSingle { src: b("a") }));
}

#[test]
fn exclude_multiple() {
assert_parse("^a*", Instruction::Push(Push::ExcludeMultipleWithGlob { src: b("a*") }));
}

#[test]
fn colon_alone_is_for_pushing_matching_refs() {
assert_parse(
Expand Down

0 comments on commit c4499ce

Please sign in to comment.