Skip to content

Commit

Permalink
basic validation and detection of patterns (#450)
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Aug 6, 2022
1 parent 7afebb7 commit e4227d6
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
26 changes: 24 additions & 2 deletions git-refspec/src/parse.rs
Expand Up @@ -6,6 +6,10 @@ pub enum Error {
NegativeWithDestination,
#[error("Cannot push into an empty destination")]
PushToEmpty,
#[error("glob patterns may only involved a single '*' character, found {pattern:?}")]
PatternUnsupported { pattern: bstr::BString },
#[error("Both sides of the specification need a pattern, like 'a/*:b/*'")]
PatternUnbalanced,
}

pub(crate) mod function {
Expand Down Expand Up @@ -48,17 +52,35 @@ pub(crate) mod function {
Operation::Push => return Err(Error::PushToEmpty),
Operation::Fetch => (Some(src), None),
},
_ => todo!("src or dst handling"),
(Some(src), Some(dst)) => (Some(src), Some(dst)),
}
}
None => todo!("no colon"),
None => (Some(spec), None),
};

let (src, src_had_pattern) = validated(src)?;
let (dst, dst_had_pattern) = validated(dst)?;
if src_had_pattern != dst_had_pattern {
return Err(Error::PatternUnbalanced);
}
Ok(RefSpecRef {
op: operation,
mode,
src,
dst,
})
}

fn validated(spec: Option<&BStr>) -> Result<(Option<&BStr>, bool), Error> {
match spec {
Some(spec) => {
let glob_count = spec.iter().filter(|b| **b == b'*').take(2).count();
if glob_count == 2 {
return Err(Error::PatternUnsupported { pattern: spec.into() });
}
Ok((Some(spec), glob_count == 1))
}
None => Ok((None, false)),
}
}
}
24 changes: 23 additions & 1 deletion git-refspec/tests/parse/mod.rs
Expand Up @@ -15,6 +15,7 @@ fn baseline() {
while let Some(kind_spec) = lines.next() {
count += 1;
let (kind, spec) = kind_spec.split_at(kind_spec.find_byte(b' ').expect("space between kind and spec"));
let spec = &spec[1..];
let err_code: usize = lines
.next()
.expect("err code")
Expand All @@ -32,7 +33,7 @@ fn baseline() {
Ok(res) => match (res.is_ok(), err_code == 0) {
(true, true) | (false, false) => {}
_ => {
eprintln!("{res:?} {err_code}");
eprintln!("{res:?} {err_code} {} {:?}", kind.as_bstr(), spec.as_bstr());
mismatch += 1;
}
},
Expand Down Expand Up @@ -74,6 +75,27 @@ mod invalid {
}
}

#[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 ["/*/a", ":a/*", "+:a/*", "a*:b/c", "a:b/*"] {
assert!(matches!(try_parse(spec, op).unwrap_err(), Error::PatternUnbalanced));
}
}
}

#[test]
fn push_to_empty() {
assert!(matches!(
Expand Down

0 comments on commit e4227d6

Please sign in to comment.