Skip to content

Commit aa8daf8

Browse files
committed
fix: Don't panic when rev-parsing ^^^ and similar (#1914)
1 parent 12cb847 commit aa8daf8

File tree

7 files changed

+30
-4
lines changed

7 files changed

+30
-4
lines changed

gix/src/revision/spec/parse/delegate/navigate.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ impl delegate::Navigate for Delegate<'_> {
2525

2626
let mut replacements = Replacements::default();
2727
let mut errors = Vec::new();
28-
let objs = self.objs[self.idx].as_mut()?;
28+
let objs = match self.objs[self.idx].as_mut() {
29+
Some(objs) => objs,
30+
None => {
31+
self.err.push(Error::TraversalWithoutStartObject);
32+
return None;
33+
}
34+
};
2935
let repo = self.repo;
3036

3137
for obj in objs.iter() {

gix/src/revision/spec/parse/error.rs

-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ impl Error {
105105
}
106106

107107
pub(crate) fn from_errors(errors: Vec<Self>) -> Self {
108-
assert!(!errors.is_empty());
109108
match errors.len() {
110109
0 => unreachable!(
111110
"BUG: cannot create something from nothing, must have recorded some errors to call from_errors()"

gix/src/revision/spec/parse/types.rs

+2
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ pub enum Error {
188188
},
189189
#[error(transparent)]
190190
Traverse(#[from] crate::revision::walk::iter::Error),
191+
#[error("Tried to navigate the commit-graph without providing an anchor first")]
192+
TraversalWithoutStartObject,
191193
#[error(transparent)]
192194
Walk(#[from] crate::revision::walk::Error),
193195
#[error("Spec does not contain a single object id")]
Binary file not shown.

gix/tests/fixtures/make_rev_spec_parse_repos.sh

+5
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ EOF
356356
baseline "@^{/!-B}" # negation from branch
357357
baseline ":file" # index lookup, default stage 0
358358
baseline ":1:file" # stage 1
359+
baseline ":5:file" # invalid stage
359360
baseline ":foo" # not found
360361
# parents
361362
baseline "a"
@@ -381,6 +382,10 @@ EOF
381382
baseline "b^3^2"
382383
baseline "a^^3^2"
383384
385+
# invalid
386+
baseline "^^"
387+
baseline "^^HEAD"
388+
384389
baseline "@{-1}"
385390
baseline "@{-2}"
386391
baseline "@{-3}"

gix/tests/gix/revision/spec/from_bytes/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ mod index {
6464
"Path \"file\" did not exist in index at stage 1. It does exist at stage 0. It exists on disk",
6565
);
6666

67+
assert_eq!(
68+
parse_spec(":5:file", &repo).unwrap_err().to_string(),
69+
"Path \"5:file\" did not exist in index at stage 0. It does not exist on disk",
70+
"invalid stage ids are interpreted as part of the filename"
71+
);
72+
6773
assert_eq!(
6874
parse_spec(":foo", &repo).unwrap_err().to_string(),
6975
"Path \"foo\" did not exist in index at stage 0. It does not exist on disk",

gix/tests/gix/revision/spec/from_bytes/traverse.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@ fn complex() -> crate::Result {
2424
#[test]
2525
fn freestanding_negation_yields_descriptive_error() -> crate::Result {
2626
let repo = repo("complex_graph")?;
27-
let expected = "The rev-spec is malformed and misses a ref name";
28-
assert_eq!(parse_spec("^", &repo).unwrap_err().to_string(), expected);
27+
for revspec in ["^^", "^^HEAD"] {
28+
assert_eq!(
29+
parse_spec(revspec, &repo).unwrap_err().to_string(),
30+
"Tried to navigate the commit-graph without providing an anchor first"
31+
);
32+
}
33+
assert_eq!(
34+
parse_spec("^", &repo).unwrap_err().to_string(),
35+
"The rev-spec is malformed and misses a ref name"
36+
);
2937
assert_eq!(
3038
parse_spec("^!", &repo).unwrap_err().to_string(),
3139
"The ref partially named \"!\" could not be found"

0 commit comments

Comments
 (0)