Skip to content

Commit

Permalink
basic range parsing (#427)
Browse files Browse the repository at this point in the history
Benefit of this is that the basic structure of the parser is setup
early.
  • Loading branch information
Byron committed May 25, 2022
1 parent 05445ec commit 03fc923
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 4 deletions.
32 changes: 28 additions & 4 deletions git-revision/src/spec.rs
Expand Up @@ -50,6 +50,7 @@ pub mod parse {
}

pub(crate) mod function {
use crate::spec;
use crate::spec::parse::{Delegate, Error};
use bstr::{BStr, ByteSlice};

Expand All @@ -58,17 +59,40 @@ pub mod parse {
(b, i[1..].as_bstr()).into()
}

pub fn revision<'a>(mut input: &'a BStr, delegate: &mut impl Delegate) -> Result<&'a BStr, Error> {
if let Some(rest) = input.strip_prefix(b"@").or_else(|| input.strip_prefix(b"HEAD")) {
delegate.resolve_ref("HEAD".into()).ok_or(Error::Delegate)?;
input = rest.as_bstr();
}
Ok(input)
}

pub fn parse(mut input: &BStr, delegate: &mut impl Delegate) -> Result<(), Error> {
if let Some(b'^') = input.get(0) {
input = next(input).1;
delegate.kind(crate::spec::Kind::Range);
delegate.kind(spec::Kind::Range);
}

if input == "@" || input == "HEAD" {
return delegate.resolve_ref("HEAD".into()).ok_or(Error::Delegate);
input = revision(input, delegate)?;
if let Some((rest, kind)) = try_range(input) {
// TODO: protect against double-kind calls, invalid for git
delegate.kind(kind);
input = rest.as_bstr();
}

todo!("")
assert!(
input.is_empty(),
"BUG: we must parse all of our input or fail gracefully: {:?}",
input
);
Ok(())
}

fn try_range(input: &BStr) -> Option<(&[u8], spec::Kind)> {
input
.strip_prefix(b"...")
.map(|rest| (rest, spec::Kind::MergeBase))
.or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::Range)))
}
}
}
Expand Down
14 changes: 14 additions & 0 deletions git-revision/tests/spec/mod.rs
Expand Up @@ -71,6 +71,20 @@ mod parse {
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
}

#[test]
fn trailing_dot_dot_is_range() {
let rec = parse("HEAD..");
assert_eq!(rec.kind.unwrap(), spec::Kind::Range);
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
}

#[test]
fn trailing_dot_dot_dot_is_merge_base() {
let rec = parse("HEAD...");
assert_eq!(rec.kind.unwrap(), spec::Kind::MergeBase);
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
}

#[test]
fn at_by_iteself_is_shortcut_for_head() {
let rec = parse("@");
Expand Down

0 comments on commit 03fc923

Please sign in to comment.