mirror of
https://github.com/go-gitea/gitea.git
synced 2026-06-25 04:25:58 +00:00
feat(api): support ref suffixes in compare (#38148)
Compare API requests with a `^` or `~N` revision suffix (for example `compare/main...feature^`) were rejected with `400 Unsupported comparison syntax: ref with suffix`. The fix resolves the suffix to a commit before comparing, so `base...head^` and `~N` work on either side, the same as git. Only `^`/`~N` navigation is resolved. Pull request creation still requires plain branch refs, and the web compare page keeps rejecting suffixes since its branch selectors need separate UI work. Closes #33943
This commit is contained in:
@@ -228,13 +228,16 @@ func (ref RefName) RefWebLinkPath() string {
|
||||
return string(refType) + "/" + util.PathEscapeSegments(ref.ShortName())
|
||||
}
|
||||
|
||||
func ParseRefSuffix(ref string) (string, string) {
|
||||
func ParseRefSuffix(ref string) (refName, refSuffix string) {
|
||||
// Partially support https://git-scm.com/docs/gitrevisions
|
||||
if idx := strings.Index(ref, "@{"); idx != -1 {
|
||||
return ref[:idx], ref[idx:]
|
||||
suffixIdx := -1 // earliest suffix mark, so a combined suffix like "main~2^" stays intact
|
||||
for _, mark := range []string{"@{", "^", "~"} {
|
||||
if idx := strings.Index(ref, mark); idx != -1 && (suffixIdx == -1 || idx < suffixIdx) {
|
||||
suffixIdx = idx
|
||||
}
|
||||
}
|
||||
if idx := strings.Index(ref, "^"); idx != -1 {
|
||||
return ref[:idx], ref[idx:]
|
||||
if suffixIdx == -1 {
|
||||
return ref, ""
|
||||
}
|
||||
return ref, ""
|
||||
return ref[:suffixIdx], ref[suffixIdx:]
|
||||
}
|
||||
|
||||
@@ -37,3 +37,22 @@ func TestRefWebLinkPath(t *testing.T) {
|
||||
assert.Equal(t, "tag/foo", RefName("refs/tags/foo").RefWebLinkPath())
|
||||
assert.Equal(t, "commit/c0ffee", RefName("c0ffee").RefWebLinkPath())
|
||||
}
|
||||
|
||||
func TestParseRefSuffix(t *testing.T) {
|
||||
cases := []struct {
|
||||
ref, name, suffix string
|
||||
}{
|
||||
{"main", "main", ""},
|
||||
{"main^", "main", "^"},
|
||||
{"main^2", "main", "^2"},
|
||||
{"main~3", "main", "~3"},
|
||||
{"main@{yesterday}", "main", "@{yesterday}"},
|
||||
{"main~2^", "main", "~2^"},
|
||||
{"main^~2", "main", "^~2"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
name, suffix := ParseRefSuffix(c.ref)
|
||||
assert.Equal(t, c.name, name, "ref: %s", c.ref)
|
||||
assert.Equal(t, c.suffix, suffix, "ref: %s", c.ref)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user