Skip to content

Commit

Permalink
handle colon and empty on the right side (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Aug 6, 2022
1 parent 966a9e9 commit 7afebb7
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 69 deletions.
9 changes: 8 additions & 1 deletion git-refspec/src/parse.rs
Expand Up @@ -4,6 +4,8 @@ pub enum Error {
Empty,
#[error("Negative refspecs cannot have destinations as they exclude sources")]
NegativeWithDestination,
#[error("Cannot push into an empty destination")]
PushToEmpty,
}

pub(crate) mod function {
Expand Down Expand Up @@ -33,14 +35,19 @@ pub(crate) mod function {
if mode == Mode::Negative {
return Err(Error::NegativeWithDestination);
}

let src = (!src.is_empty()).then(|| src.as_bstr());
let dst = (!dst.is_empty()).then(|| dst.as_bstr());
match (src, dst) {
(None, None) => (None, None), // match all
(None, None) => (None, None),
(None, Some(dst)) => match operation {
Operation::Push => (None, Some(dst)),
Operation::Fetch => (Some("HEAD".into()), Some(dst)),
},
(Some(src), None) => match operation {
Operation::Push => return Err(Error::PushToEmpty),
Operation::Fetch => (Some(src), None),
},
_ => todo!("src or dst handling"),
}
}
Expand Down
1 change: 1 addition & 0 deletions git-refspec/src/spec.rs
Expand Up @@ -15,6 +15,7 @@ impl RefSpecRef<'_> {
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 {
src,
Expand Down
155 changes: 87 additions & 68 deletions git-refspec/tests/parse/mod.rs
Expand Up @@ -74,78 +74,97 @@ mod invalid {
}
}

mod fetch {
use crate::parse::{assert_parse, b};
use git_refspec::{Fetch, Instruction};

#[test]
fn empty_lhs_colon_rhs_fetches_head_to_destination() {
assert_parse(
":a",
Instruction::Fetch(Fetch::AndUpdateSingle {
src: b("HEAD"),
dst: b("a"),
allow_non_fast_forward: false,
}),
);

assert_parse(
"+:a",
Instruction::Fetch(Fetch::AndUpdateSingle {
src: b("HEAD"),
dst: b("a"),
allow_non_fast_forward: true,
}),
);
}
#[test]
fn push_to_empty() {
assert!(matches!(
try_parse("HEAD:", Operation::Push).unwrap_err(),
Error::PushToEmpty
));
}
}

#[test]
fn colon_alone_is_for_fetching_into_fetchhead() {
assert_parse(
":",
Instruction::Fetch(Fetch::AllMatchingBranches {
allow_non_fast_forward: false,
}),
);
assert_parse(
"+:",
Instruction::Fetch(Fetch::AllMatchingBranches {
allow_non_fast_forward: true,
}),
);
}
mod fetch {
use crate::parse::{assert_parse, b};
use git_refspec::{Fetch, Instruction, Mode};

#[test]
fn lhs_colon_empty_fetches_only() {
assert_parse("src:", Instruction::Fetch(Fetch::Only { src: b("src") }));
let spec = assert_parse("+src:", Instruction::Fetch(Fetch::Only { src: b("src") }));
assert_eq!(
spec.mode(),
Mode::Force,
"force is set, even though it has no effect in the actual instruction"
);
}

mod push {
use crate::parse::{assert_parse, b};
use git_refspec::{Instruction, Mode, Push};

#[test]
fn colon_alone_is_for_pushing_matching_refs() {
assert_parse(
":",
Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: false,
}),
);
assert_parse(
"+:",
Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: true,
}),
);
}
#[test]
fn empty_lhs_colon_rhs_fetches_head_to_destination() {
assert_parse(
":a",
Instruction::Fetch(Fetch::AndUpdateSingle {
src: b("HEAD"),
dst: b("a"),
allow_non_fast_forward: false,
}),
);

#[test]
fn delete() {
assert_parse(":a", Instruction::Push(Push::Delete { ref_or_pattern: b("a") }));
let spec = assert_parse("+:a", Instruction::Push(Push::Delete { ref_or_pattern: b("a") }));
assert_eq!(
spec.mode(),
Mode::Force,
"force is set, even though it has no effect in the actual instruction"
);
}
assert_parse(
"+:a",
Instruction::Fetch(Fetch::AndUpdateSingle {
src: b("HEAD"),
dst: b("a"),
allow_non_fast_forward: true,
}),
);
}

#[test]
fn colon_alone_is_for_fetching_into_fetchhead() {
assert_parse(
":",
Instruction::Fetch(Fetch::AllMatchingBranches {
allow_non_fast_forward: false,
}),
);
assert_parse(
"+:",
Instruction::Fetch(Fetch::AllMatchingBranches {
allow_non_fast_forward: true,
}),
);
}
}

mod push {
use crate::parse::{assert_parse, b};
use git_refspec::{Instruction, Mode, Push};

#[test]
fn colon_alone_is_for_pushing_matching_refs() {
assert_parse(
":",
Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: false,
}),
);
assert_parse(
"+:",
Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: true,
}),
);
}

#[test]
fn delete() {
assert_parse(":a", Instruction::Push(Push::Delete { ref_or_pattern: b("a") }));
let spec = assert_parse("+:a", Instruction::Push(Push::Delete { ref_or_pattern: b("a") }));
assert_eq!(
spec.mode(),
Mode::Force,
"force is set, even though it has no effect in the actual instruction"
);
}
}

Expand Down

0 comments on commit 7afebb7

Please sign in to comment.