diff --git a/gix-refspec/src/parse.rs b/gix-refspec/src/parse.rs index 6ead38ed4aa..d64efa5d102 100644 --- a/gix-refspec/src/parse.rs +++ b/gix-refspec/src/parse.rs @@ -75,7 +75,10 @@ pub(crate) mod function { } }; - let (mut src, dst) = match spec.find_byte(b':') { + // Split on the last colon like `strrchr()` in Git's `parse_refspec()` does, so that a + // push source may itself contain one - `:/message` and `:` are both valid + // revisions. With a single colon this is the same position as the first one. + let (mut src, dst) = match spec.rfind_byte(b':') { Some(pos) => { if mode == Mode::Negative { return Err(Error::NegativeWithDestination); diff --git a/gix-refspec/tests/fixtures/generated-archives/parse_baseline.tar b/gix-refspec/tests/fixtures/generated-archives/parse_baseline.tar index d5e60c90195..1b46d5beec4 100644 Binary files a/gix-refspec/tests/fixtures/generated-archives/parse_baseline.tar and b/gix-refspec/tests/fixtures/generated-archives/parse_baseline.tar differ diff --git a/gix-refspec/tests/fixtures/generated-archives/parse_baseline_sha256.tar b/gix-refspec/tests/fixtures/generated-archives/parse_baseline_sha256.tar index 947fbb4c7ae..1b46d5beec4 100644 Binary files a/gix-refspec/tests/fixtures/generated-archives/parse_baseline_sha256.tar and b/gix-refspec/tests/fixtures/generated-archives/parse_baseline_sha256.tar differ diff --git a/gix-refspec/tests/fixtures/parse_baseline.sh b/gix-refspec/tests/fixtures/parse_baseline.sh index 1a899fdeb42..8cc54efa38f 100755 --- a/gix-refspec/tests/fixtures/parse_baseline.sh +++ b/gix-refspec/tests/fixtures/parse_baseline.sh @@ -40,6 +40,11 @@ baseline push '^' baseline fetch '^refs/heads/qa/*/*' baseline push '^refs/heads/qa/*/*' + +# a fetch source is a ref name, so it can't hold the colon that a push source may +baseline fetch 'a:b:c' +baseline fetch ':/message:refs/heads/x' + baseline push 'main~1' baseline fetch 'main~1' baseline push 'main~1:other~1' @@ -92,6 +97,12 @@ baseline fetch 'refs/heads/main:refs/remotes/frotz/xyzzy' baseline push 'main~1:refs/remotes/frotz/backup' baseline push 'HEAD~4:refs/remotes/frotz/new' +# Git splits on the last colon, so a push source may contain one itself +baseline push 'a:b:c' +baseline push 'a:b:c:d' +baseline push ':/message:refs/heads/x' +baseline push 'HEAD:path:refs/heads/x' + baseline push 'HEAD' baseline fetch 'HEAD' baseline push '@'