Skip to content

Commit

Permalink
negative must not be empty (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Aug 7, 2022
1 parent 32d98e9 commit 79e0eaf
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 60 deletions.
12 changes: 9 additions & 3 deletions 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("Negative specs must not be empty")]
NegativeEmpty,
#[error("Cannot push into an empty destination")]
PushToEmpty,
#[error("glob patterns may only involved a single '*' character, found {pattern:?}")]
Expand Down Expand Up @@ -52,12 +54,12 @@ pub(crate) mod function {

let (mut src, dst) = match spec.find_byte(b':') {
Some(pos) => {
let (src, dst) = spec.split_at(pos);
let dst = &dst[1..];
if mode == Mode::Negative {
return Err(Error::NegativeWithDestination);
}

let (src, dst) = spec.split_at(pos);
let dst = &dst[1..];
let src = (!src.is_empty()).then(|| src.as_bstr());
let dst = (!dst.is_empty()).then(|| dst.as_bstr());
match (src, dst) {
Expand All @@ -78,14 +80,18 @@ pub(crate) mod function {
}
None => {
let src = (!spec.is_empty()).then(|| spec);
if Operation::Fetch == operation && src.is_none() {
if Operation::Fetch == operation && mode != Mode::Negative && src.is_none() {
return Ok(fetch_head_only(mode));
} else {
(src, None)
}
}
};

if mode == Mode::Negative && src.is_none() {
return Err(Error::NegativeEmpty);
}

if let Some(spec) = src.as_mut() {
if *spec == "@" {
*spec = "HEAD".into();
Expand Down
Git LFS file not shown
2 changes: 2 additions & 0 deletions git-refspec/tests/fixtures/make_baseline.sh
Expand Up @@ -30,6 +30,8 @@ baseline fetch '^a:'
baseline fetch '^a:b'
baseline fetch '^:'
baseline fetch '^:b'
baseline fetch '^'
baseline push '^'

baseline fetch '^refs/heads/qa/*/*'
baseline push '^refs/heads/qa/*/*'
Expand Down
59 changes: 59 additions & 0 deletions git-refspec/tests/parse/invalid.rs
@@ -0,0 +1,59 @@
use crate::parse::try_parse;
use git_refspec::{parse::Error, Operation};

#[test]
fn empty() {
assert!(matches!(try_parse("", Operation::Push).unwrap_err(), Error::Empty));
}

#[test]
fn negative_must_not_be_empty() {
for op in [Operation::Fetch, Operation::Push] {
assert!(matches!(try_parse("^", op).unwrap_err(), Error::NegativeEmpty));
}
}

#[test]
fn negative_with_destination() {
for op in [Operation::Fetch, Operation::Push] {
for spec in ["^a:b", "^a:", "^:", "^:b"] {
assert!(matches!(
try_parse(spec, op).unwrap_err(),
Error::NegativeWithDestination
));
}
}
}

#[test]
fn complex_patterns_with_more_than_one_asterisk() {
for op in [Operation::Fetch, Operation::Push] {
for spec in ["^*/*", "a/*/c/*", "a**:**b", "+:**/"] {
assert!(matches!(
try_parse(spec, op).unwrap_err(),
Error::PatternUnsupported { .. }
));
}
}
}

#[test]
fn both_sides_need_pattern_if_one_uses_it() {
for op in [Operation::Fetch, Operation::Push] {
for spec in ["refs/*/a", ":a/*", "+:a/*", "a*:b/c", "a:b/*"] {
assert!(
matches!(try_parse(spec, op).unwrap_err(), Error::PatternUnbalanced),
"{}",
spec
);
}
}
}

#[test]
fn push_to_empty() {
assert!(matches!(
try_parse("HEAD:", Operation::Push).unwrap_err(),
Error::PushToEmpty
));
}
56 changes: 1 addition & 55 deletions git-refspec/tests/parse/mod.rs
Expand Up @@ -56,62 +56,8 @@ fn baseline() {
}
}

mod invalid {
use crate::parse::try_parse;
use git_refspec::{parse::Error, Operation};

#[test]
fn empty() {
assert!(matches!(try_parse("", Operation::Push).unwrap_err(), Error::Empty));
}

#[test]
fn negative_with_destination() {
for op in [Operation::Fetch, Operation::Push] {
for spec in ["^a:b", "^a:", "^:", "^:b"] {
assert!(matches!(
try_parse(spec, op).unwrap_err(),
Error::NegativeWithDestination
));
}
}
}

#[test]
fn complex_patterns_with_more_than_one_asterisk() {
for op in [Operation::Fetch, Operation::Push] {
for spec in ["^*/*", "a/*/c/*", "a**:**b", "+:**/"] {
assert!(matches!(
try_parse(spec, op).unwrap_err(),
Error::PatternUnsupported { .. }
));
}
}
}

#[test]
fn both_sides_need_pattern_if_one_uses_it() {
for op in [Operation::Fetch, Operation::Push] {
for spec in ["refs/*/a", ":a/*", "+:a/*", "a*:b/c", "a:b/*"] {
assert!(
matches!(try_parse(spec, op).unwrap_err(), Error::PatternUnbalanced),
"{}",
spec
);
}
}
}

#[test]
fn push_to_empty() {
assert!(matches!(
try_parse("HEAD:", Operation::Push).unwrap_err(),
Error::PushToEmpty
));
}
}

mod fetch;
mod invalid;
mod push;

mod util {
Expand Down

0 comments on commit 79e0eaf

Please sign in to comment.