Skip to content

Commit 478b65f

Browse files
committed
basic range parsing (#427)
Benefit of this is that the basic structure of the parser is setup early.
1 parent 67dc72a commit 478b65f

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

Diff for: git-revision/src/spec.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub mod parse {
5050
}
5151

5252
pub(crate) mod function {
53+
use crate::spec;
5354
use crate::spec::parse::{Delegate, Error};
5455
use bstr::{BStr, ByteSlice};
5556

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

62+
pub fn revision<'a>(mut input: &'a BStr, delegate: &mut impl Delegate) -> Result<&'a BStr, Error> {
63+
if let Some(rest) = input.strip_prefix(b"@").or_else(|| input.strip_prefix(b"HEAD")) {
64+
delegate.resolve_ref("HEAD".into()).ok_or(Error::Delegate)?;
65+
input = rest.as_bstr();
66+
}
67+
Ok(input)
68+
}
69+
6170
pub fn parse(mut input: &BStr, delegate: &mut impl Delegate) -> Result<(), Error> {
6271
if let Some(b'^') = input.get(0) {
6372
input = next(input).1;
64-
delegate.kind(crate::spec::Kind::Range);
73+
delegate.kind(spec::Kind::Range);
6574
}
6675

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

71-
todo!("")
83+
assert!(
84+
input.is_empty(),
85+
"BUG: we must parse all of our input or fail gracefully: {:?}",
86+
input
87+
);
88+
Ok(())
89+
}
90+
91+
fn try_range(input: &BStr) -> Option<(&[u8], spec::Kind)> {
92+
input
93+
.strip_prefix(b"...")
94+
.map(|rest| (rest, spec::Kind::MergeBase))
95+
.or_else(|| input.strip_prefix(b"..").map(|rest| (rest, spec::Kind::Range)))
7296
}
7397
}
7498
}

Diff for: git-revision/tests/spec/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ mod parse {
7171
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
7272
}
7373

74+
#[test]
75+
fn trailing_dot_dot_is_range() {
76+
let rec = parse("HEAD..");
77+
assert_eq!(rec.kind.unwrap(), spec::Kind::Range);
78+
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
79+
}
80+
81+
#[test]
82+
fn trailing_dot_dot_dot_is_merge_base() {
83+
let rec = parse("HEAD...");
84+
assert_eq!(rec.kind.unwrap(), spec::Kind::MergeBase);
85+
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
86+
}
87+
7488
#[test]
7589
fn at_by_iteself_is_shortcut_for_head() {
7690
let rec = parse("@");

0 commit comments

Comments
 (0)