From 478b65fd8d6b39c3ed68bcdf3da26b763f5f2ef3 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Wed, 25 May 2022 18:20:00 +0800 Subject: [PATCH] basic range parsing (#427) Benefit of this is that the basic structure of the parser is setup early. --- git-revision/src/spec.rs | 32 ++++++++++++++++++++++++++++---- git-revision/tests/spec/mod.rs | 14 ++++++++++++++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/git-revision/src/spec.rs b/git-revision/src/spec.rs index a7e34af495..ceccfceb1d 100644 --- a/git-revision/src/spec.rs +++ b/git-revision/src/spec.rs @@ -50,6 +50,7 @@ pub mod parse { } pub(crate) mod function { + use crate::spec; use crate::spec::parse::{Delegate, Error}; use bstr::{BStr, ByteSlice}; @@ -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))) } } } diff --git a/git-revision/tests/spec/mod.rs b/git-revision/tests/spec/mod.rs index cf130ff8c9..f99fa1c1fb 100644 --- a/git-revision/tests/spec/mod.rs +++ b/git-revision/tests/spec/mod.rs @@ -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("@");