Skip to content

Commit caaf5da

Browse files
committed
prepare range parsing (#427)
1 parent 11bf081 commit caaf5da

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

git-revision/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ serde1 = [ "serde", "git-hash/serde1", "git-object/serde1" ]
1919
[dependencies]
2020
git-hash = { version = "^0.9.4", path = "../git-hash" }
2121
git-object = { version = "^0.19.0", path = "../git-object" }
22+
2223
hash_hasher = "2.0.3"
2324
thiserror = "1.0.26"
2425
serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }

git-revision/src/spec.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
/// How to interpret a revision specification, or `revspec`.
2+
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
3+
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
4+
pub enum Kind {
5+
/// A single revision specification, pointing at one reference.
6+
Single,
7+
/// Two revision specifications `a` and `b` where we want all commits from `b` that are not also in `a`.
8+
Range,
9+
/// Everything in `a` and `b` but no commit from any of their merge bases.
10+
MergeBase,
11+
}
12+
13+
impl Default for Kind {
14+
fn default() -> Self {
15+
Kind::Single
16+
}
17+
}
18+
119
pub mod parse {
220
#![allow(missing_docs)]
321
use git_object::bstr::BStr;
@@ -8,12 +26,25 @@ pub mod parse {
826
Delegate,
927
}
1028

29+
/// A delegate to be informed about parse events, with methods split into three categories.
30+
///
31+
/// - **Revisions** - which revision to use as starting point for…
32+
/// - **Navigation** - where to go once from the initial revision.
33+
/// - **range** - to learn if the specification is for a single or multiple references.
1134
pub trait Delegate {
1235
fn resolve_ref(&mut self, input: &BStr) -> Option<()>;
1336
fn find_by_prefix(&mut self, input: &BStr) -> Option<()>;
1437

1538
fn nth_ancestor(&mut self, n: usize) -> Option<()>;
1639
fn nth_parent(&mut self, n: usize) -> Option<()>;
40+
41+
/// Set the kind of the specification, which happens only once if it happens at all.
42+
/// In case this method isn't called, assume `Single`.
43+
///
44+
/// Note that ranges don't necessarily assure that a second specification will be parsed.
45+
/// If `^rev` is given, this method is called with [`spec::Kind::Range`][crate::spec::Kind::Range]
46+
/// and no second specification is provided.
47+
fn kind(&mut self, kind: crate::spec::Kind);
1748
}
1849

1950
pub(crate) mod function {

git-revision/tests/spec/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
mod parse {
22
use git_object::bstr::{BStr, BString};
33
use git_revision::spec;
4+
45
#[derive(Default, Debug)]
56
struct Recorder {
67
resolve_ref_input: Option<BString>,
8+
kind: Option<spec::Kind>,
79
}
810
impl spec::parse::Delegate for Recorder {
911
fn resolve_ref(&mut self, input: &BStr) -> Option<()> {
@@ -27,6 +29,10 @@ mod parse {
2729
fn nth_parent(&mut self, _n: usize) -> Option<()> {
2830
todo!()
2931
}
32+
33+
fn kind(&mut self, kind: spec::Kind) {
34+
self.kind = Some(kind);
35+
}
3036
}
3137

3238
fn parse(spec: &str) -> Recorder {
@@ -35,15 +41,25 @@ mod parse {
3541
rec
3642
}
3743

44+
#[test]
45+
#[ignore]
46+
fn leading_caret_is_range_kind() {
47+
let rec = parse("^HEAD");
48+
assert_eq!(rec.kind.unwrap(), spec::Kind::Range);
49+
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
50+
}
51+
3852
#[test]
3953
fn at_by_iteself_is_shortcut_for_head() {
4054
let rec = parse("@");
55+
assert!(rec.kind.is_none());
4156
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
4257
}
4358

4459
#[test]
4560
fn refname_head() {
4661
let rec = parse("HEAD");
62+
assert!(rec.kind.is_none());
4763
assert_eq!(rec.resolve_ref_input.unwrap(), "HEAD");
4864
}
4965
}

0 commit comments

Comments
 (0)