]> source.dussan.org Git - gitea.git/commitdiff
Fix `IsObjectExist` with gogit (#31790)
authorJason Song <i@wolfogre.com>
Fri, 9 Aug 2024 02:40:45 +0000 (10:40 +0800)
committerGitHub <noreply@github.com>
Fri, 9 Aug 2024 02:40:45 +0000 (02:40 +0000)
Fix #31271.

When gogit is enabled, `IsObjectExist` calls
`repo.gogitRepo.ResolveRevision`, which is not correct. It's for
checking references not objects, it could work with commit hash since
it's both a valid reference and a commit object, but it doesn't work
with blob objects.

So it causes #31271 because it reports that all blob objects do not
exist.

modules/git/repo_branch_gogit.go
modules/git/repo_branch_nogogit.go
modules/git/repo_branch_test.go
modules/markup/html.go

index d1ec14d81155fddb6120ce269c59990eb5981688..dbc4a5fedc91b0575124a1859a9e74e37279bb95 100644 (file)
@@ -14,28 +14,33 @@ import (
        "github.com/go-git/go-git/v5/plumbing/storer"
 )
 
-// IsObjectExist returns true if given reference exists in the repository.
+// IsObjectExist returns true if the given object exists in the repository.
+// FIXME: Inconsistent behavior with nogogit edition
+// Unlike the implementation of IsObjectExist in nogogit edition, it does not support short hashes here.
+// For example, IsObjectExist("153f451") will return false, but it will return true in nogogit edition.
+// To fix this, the solution could be adding support for short hashes in gogit edition if it's really needed.
 func (repo *Repository) IsObjectExist(name string) bool {
        if name == "" {
                return false
        }
 
-       _, err := repo.gogitRepo.ResolveRevision(plumbing.Revision(name))
-
+       _, err := repo.gogitRepo.Object(plumbing.AnyObject, plumbing.NewHash(name))
        return err == nil
 }
 
 // IsReferenceExist returns true if given reference exists in the repository.
+// FIXME: Inconsistent behavior with nogogit edition
+// Unlike the implementation of IsObjectExist in nogogit edition, it does not support blob hashes here.
+// For example, IsObjectExist([existing_blob_hash]) will return false, but it will return true in nogogit edition.
+// To fix this, the solution could be refusing to support blob hashes in nogogit edition since a blob hash is not a reference.
 func (repo *Repository) IsReferenceExist(name string) bool {
        if name == "" {
                return false
        }
 
-       reference, err := repo.gogitRepo.Reference(plumbing.ReferenceName(name), true)
-       if err != nil {
-               return false
-       }
-       return reference.Type() != plumbing.InvalidReference
+       _, err := repo.gogitRepo.ResolveRevision(plumbing.Revision(name))
+
+       return err == nil
 }
 
 // IsBranchExist returns true if given branch exists in current repository.
index 470faebe25f79b42de9de7acc6131916813dd5f2..63d0f7268a65d96271dfa8c4b4f0f8401fc60b7e 100644 (file)
@@ -16,7 +16,7 @@ import (
        "code.gitea.io/gitea/modules/log"
 )
 
-// IsObjectExist returns true if given reference exists in the repository.
+// IsObjectExist returns true if the given object exists in the repository.
 func (repo *Repository) IsObjectExist(name string) bool {
        if name == "" {
                return false
index fe788946e500b5cf220ef8b611252912ad64b48f..009c545832a4944f3b04231796a67fd7bfe003ca 100644 (file)
@@ -8,6 +8,7 @@ import (
        "testing"
 
        "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
 )
 
 func TestRepository_GetBranches(t *testing.T) {
@@ -94,3 +95,107 @@ func BenchmarkGetRefsBySha(b *testing.B) {
        _, _ = bareRepo5.GetRefsBySha("c83380d7056593c51a699d12b9c00627bd5743e9", "")
        _, _ = bareRepo5.GetRefsBySha("58a4bcc53ac13e7ff76127e0fb518b5262bf09af", "")
 }
+
+func TestRepository_IsObjectExist(t *testing.T) {
+       repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare"))
+       require.NoError(t, err)
+       defer repo.Close()
+
+       // FIXME: Inconsistent behavior between gogit and nogogit editions
+       // See the comment of IsObjectExist in gogit edition for more details.
+       supportShortHash := !isGogit
+
+       tests := []struct {
+               name string
+               arg  string
+               want bool
+       }{
+               {
+                       name: "empty",
+                       arg:  "",
+                       want: false,
+               },
+               {
+                       name: "branch",
+                       arg:  "master",
+                       want: false,
+               },
+               {
+                       name: "commit hash",
+                       arg:  "ce064814f4a0d337b333e646ece456cd39fab612",
+                       want: true,
+               },
+               {
+                       name: "short commit hash",
+                       arg:  "ce06481",
+                       want: supportShortHash,
+               },
+               {
+                       name: "blob hash",
+                       arg:  "153f451b9ee7fa1da317ab17a127e9fd9d384310",
+                       want: true,
+               },
+               {
+                       name: "short blob hash",
+                       arg:  "153f451",
+                       want: supportShortHash,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       assert.Equal(t, tt.want, repo.IsObjectExist(tt.arg))
+               })
+       }
+}
+
+func TestRepository_IsReferenceExist(t *testing.T) {
+       repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare"))
+       require.NoError(t, err)
+       defer repo.Close()
+
+       // FIXME: Inconsistent behavior between gogit and nogogit editions
+       // See the comment of IsReferenceExist in gogit edition for more details.
+       supportBlobHash := !isGogit
+
+       tests := []struct {
+               name string
+               arg  string
+               want bool
+       }{
+               {
+                       name: "empty",
+                       arg:  "",
+                       want: false,
+               },
+               {
+                       name: "branch",
+                       arg:  "master",
+                       want: true,
+               },
+               {
+                       name: "commit hash",
+                       arg:  "ce064814f4a0d337b333e646ece456cd39fab612",
+                       want: true,
+               },
+               {
+                       name: "short commit hash",
+                       arg:  "ce06481",
+                       want: true,
+               },
+               {
+                       name: "blob hash",
+                       arg:  "153f451b9ee7fa1da317ab17a127e9fd9d384310",
+                       want: supportBlobHash,
+               },
+               {
+                       name: "short blob hash",
+                       arg:  "153f451",
+                       want: supportBlobHash,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       assert.Equal(t, tt.want, repo.IsReferenceExist(tt.arg))
+               })
+       }
+}
index b8069d459a0758718b81fe2961a05707d5a53168..8d3327c49eb8b1aa795a5254be357121db06a11a 100644 (file)
@@ -1144,7 +1144,8 @@ func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
                                })
                        }
 
-                       exist = ctx.GitRepo.IsObjectExist(hash)
+                       // Don't use IsObjectExist since it doesn't support short hashs with gogit edition.
+                       exist = ctx.GitRepo.IsReferenceExist(hash)
                        ctx.ShaExistCache[hash] = exist
                }