]> source.dussan.org Git - gitea.git/commitdiff
Refactor the usage of batch catfile (#31754) (#31889)
authorGiteabot <teabot@gitea.io>
Tue, 20 Aug 2024 17:55:14 +0000 (01:55 +0800)
committerGitHub <noreply@github.com>
Tue, 20 Aug 2024 17:55:14 +0000 (01:55 +0800)
Backport #31754 by @lunny

When opening a repository, it will call `ensureValidRepository` and also
`CatFileBatch`. But sometimes these will not be used until repository
closed. So it's a waste of CPU to invoke 3 times git command for every
open repository.

This PR removed all of these from `OpenRepository` but only kept
checking whether the folder exists. When a batch is necessary, the
necessary functions will be invoked.

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
15 files changed:
modules/git/batch.go [new file with mode: 0644]
modules/git/batch_reader.go
modules/git/blob_nogogit.go
modules/git/commit_info_nogogit.go
modules/git/pipeline/lfs_nogogit.go
modules/git/repo_base_nogogit.go
modules/git/repo_branch_nogogit.go
modules/git/repo_commit_nogogit.go
modules/git/repo_language_stats_nogogit.go
modules/git/repo_tag_nogogit.go
modules/git/repo_tree_nogogit.go
modules/git/tree_entry_nogogit.go
modules/git/tree_nogogit.go
modules/indexer/code/bleve/bleve.go
modules/indexer/code/elasticsearch/elasticsearch.go

diff --git a/modules/git/batch.go b/modules/git/batch.go
new file mode 100644 (file)
index 0000000..3ec4f1d
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package git
+
+import (
+       "bufio"
+       "context"
+)
+
+type Batch struct {
+       cancel context.CancelFunc
+       Reader *bufio.Reader
+       Writer WriteCloserError
+}
+
+func (repo *Repository) NewBatch(ctx context.Context) (*Batch, error) {
+       // Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
+       if err := ensureValidGitRepository(ctx, repo.Path); err != nil {
+               return nil, err
+       }
+
+       var batch Batch
+       batch.Writer, batch.Reader, batch.cancel = catFileBatch(ctx, repo.Path)
+       return &batch, nil
+}
+
+func (repo *Repository) NewBatchCheck(ctx context.Context) (*Batch, error) {
+       // Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
+       if err := ensureValidGitRepository(ctx, repo.Path); err != nil {
+               return nil, err
+       }
+
+       var check Batch
+       check.Writer, check.Reader, check.cancel = catFileBatchCheck(ctx, repo.Path)
+       return &check, nil
+}
+
+func (b *Batch) Close() {
+       if b.cancel != nil {
+               b.cancel()
+               b.Reader = nil
+               b.Writer = nil
+               b.cancel = nil
+       }
+}
index c988d6ab86ed4214454e0dc3e46b54b4de6d66d3..3b1a466b2eaa90a17b7bf74c1602a39ec144900a 100644 (file)
@@ -26,10 +26,10 @@ type WriteCloserError interface {
        CloseWithError(err error) error
 }
 
-// EnsureValidGitRepository runs git rev-parse in the repository path - thus ensuring that the repository is a valid repository.
+// ensureValidGitRepository runs git rev-parse in the repository path - thus ensuring that the repository is a valid repository.
 // Run before opening git cat-file.
 // This is needed otherwise the git cat-file will hang for invalid repositories.
-func EnsureValidGitRepository(ctx context.Context, repoPath string) error {
+func ensureValidGitRepository(ctx context.Context, repoPath string) error {
        stderr := strings.Builder{}
        err := NewCommand(ctx, "rev-parse").
                SetDescription(fmt.Sprintf("%s rev-parse [repo_path: %s]", GitExecutable, repoPath)).
@@ -43,8 +43,8 @@ func EnsureValidGitRepository(ctx context.Context, repoPath string) error {
        return nil
 }
 
-// CatFileBatchCheck opens git cat-file --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
-func CatFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
+// catFileBatchCheck opens git cat-file --batch-check in the provided repo and returns a stdin pipe, a stdout reader and cancel function
+func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
        batchStdinReader, batchStdinWriter := io.Pipe()
        batchStdoutReader, batchStdoutWriter := io.Pipe()
        ctx, ctxCancel := context.WithCancel(ctx)
@@ -93,8 +93,8 @@ func CatFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
        return batchStdinWriter, batchReader, cancel
 }
 
-// CatFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
-func CatFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
+// catFileBatch opens git cat-file --batch in the provided repo and returns a stdin pipe, a stdout reader and cancel function
+func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufio.Reader, func()) {
        // We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
        // so let's create a batch stdin and stdout
        batchStdinReader, batchStdinWriter := io.Pipe()
index 945a6bc432c29bd0b586cc2c755d587da49513db..af3ce376d6a46965893e0171ba4a9462d4b80b67 100644 (file)
@@ -26,9 +26,12 @@ type Blob struct {
 // DataAsync gets a ReadCloser for the contents of a blob without reading it all.
 // Calling the Close function on the result will discard all unread output.
 func (b *Blob) DataAsync() (io.ReadCloser, error) {
-       wr, rd, cancel := b.repo.CatFileBatch(b.repo.Ctx)
+       wr, rd, cancel, err := b.repo.CatFileBatch(b.repo.Ctx)
+       if err != nil {
+               return nil, err
+       }
 
-       _, err := wr.Write([]byte(b.ID.String() + "\n"))
+       _, err = wr.Write([]byte(b.ID.String() + "\n"))
        if err != nil {
                cancel()
                return nil, err
@@ -64,9 +67,13 @@ func (b *Blob) Size() int64 {
                return b.size
        }
 
-       wr, rd, cancel := b.repo.CatFileBatchCheck(b.repo.Ctx)
+       wr, rd, cancel, err := b.repo.CatFileBatchCheck(b.repo.Ctx)
+       if err != nil {
+               log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
+               return 0
+       }
        defer cancel()
-       _, err := wr.Write([]byte(b.ID.String() + "\n"))
+       _, err = wr.Write([]byte(b.ID.String() + "\n"))
        if err != nil {
                log.Debug("error whilst reading size for %s in %s. Error: %v", b.ID.String(), b.repo.Path, err)
                return 0
index a5d18694f7384f70d74aaa5c89ac7aa098004544..03ad49b90dc661ed42cabeffb7e41e97fb6d70f5 100644 (file)
@@ -124,7 +124,10 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
                return nil, err
        }
 
-       batchStdinWriter, batchReader, cancel := commit.repo.CatFileBatch(ctx)
+       batchStdinWriter, batchReader, cancel, err := commit.repo.CatFileBatch(ctx)
+       if err != nil {
+               return nil, err
+       }
        defer cancel()
 
        commitsMap := map[string]*Commit{}
index 349cfbd9ce5a2332a6e67f1080feccde5df51879..b22805c1327e902dc4b63ee146039fa2bfea6c2a 100644 (file)
@@ -46,7 +46,10 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
 
        // Next feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
        // so let's create a batch stdin and stdout
-       batchStdinWriter, batchReader, cancel := repo.CatFileBatch(repo.Ctx)
+       batchStdinWriter, batchReader, cancel, err := repo.CatFileBatch(repo.Ctx)
+       if err != nil {
+               return nil, err
+       }
        defer cancel()
 
        // We'll use a scanner for the revList because it's simpler than a bufio.Reader
index bc241cdd7950070396123fb3c195e36e4c500eda..3eb2e2ee6b2f0dd1dbe406f880740ec836ca62a1 100644 (file)
@@ -25,15 +25,11 @@ type Repository struct {
 
        gpgSettings *GPGSettings
 
-       batchInUse  bool
-       batchCancel context.CancelFunc
-       batchReader *bufio.Reader
-       batchWriter WriteCloserError
+       batchInUse bool
+       batch      *Batch
 
-       checkInUse  bool
-       checkCancel context.CancelFunc
-       checkReader *bufio.Reader
-       checkWriter WriteCloserError
+       checkInUse bool
+       check      *Batch
 
        Ctx             context.Context
        LastCommitCache *LastCommitCache
@@ -55,63 +51,75 @@ func OpenRepository(ctx context.Context, repoPath string) (*Repository, error) {
                return nil, util.NewNotExistErrorf("no such file or directory")
        }
 
-       // Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
-       if err := EnsureValidGitRepository(ctx, repoPath); err != nil {
-               return nil, err
-       }
-
-       repo := &Repository{
+       return &Repository{
                Path:     repoPath,
                tagCache: newObjectCache(),
                Ctx:      ctx,
-       }
-
-       repo.batchWriter, repo.batchReader, repo.batchCancel = CatFileBatch(ctx, repoPath)
-       repo.checkWriter, repo.checkReader, repo.checkCancel = CatFileBatchCheck(ctx, repoPath)
-
-       return repo, nil
+       }, nil
 }
 
 // CatFileBatch obtains a CatFileBatch for this repository
-func (repo *Repository) CatFileBatch(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
-       if repo.batchCancel == nil || repo.batchInUse {
-               log.Debug("Opening temporary cat file batch for: %s", repo.Path)
-               return CatFileBatch(ctx, repo.Path)
+func (repo *Repository) CatFileBatch(ctx context.Context) (WriteCloserError, *bufio.Reader, func(), error) {
+       if repo.batch == nil {
+               var err error
+               repo.batch, err = repo.NewBatch(ctx)
+               if err != nil {
+                       return nil, nil, nil, err
+               }
        }
-       repo.batchInUse = true
-       return repo.batchWriter, repo.batchReader, func() {
-               repo.batchInUse = false
+
+       if !repo.batchInUse {
+               repo.batchInUse = true
+               return repo.batch.Writer, repo.batch.Reader, func() {
+                       repo.batchInUse = false
+               }, nil
        }
+
+       log.Debug("Opening temporary cat file batch for: %s", repo.Path)
+       tempBatch, err := repo.NewBatch(ctx)
+       if err != nil {
+               return nil, nil, nil, err
+       }
+       return tempBatch.Writer, tempBatch.Reader, tempBatch.Close, nil
 }
 
 // CatFileBatchCheck obtains a CatFileBatchCheck for this repository
-func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
-       if repo.checkCancel == nil || repo.checkInUse {
-               log.Debug("Opening temporary cat file batch-check for: %s", repo.Path)
-               return CatFileBatchCheck(ctx, repo.Path)
+func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError, *bufio.Reader, func(), error) {
+       if repo.check == nil {
+               var err error
+               repo.check, err = repo.NewBatchCheck(ctx)
+               if err != nil {
+                       return nil, nil, nil, err
+               }
        }
-       repo.checkInUse = true
-       return repo.checkWriter, repo.checkReader, func() {
-               repo.checkInUse = false
+
+       if !repo.checkInUse {
+               repo.checkInUse = true
+               return repo.check.Writer, repo.check.Reader, func() {
+                       repo.checkInUse = false
+               }, nil
+       }
+
+       log.Debug("Opening temporary cat file batch-check for: %s", repo.Path)
+       tempBatchCheck, err := repo.NewBatchCheck(ctx)
+       if err != nil {
+               return nil, nil, nil, err
        }
+       return tempBatchCheck.Writer, tempBatchCheck.Reader, tempBatchCheck.Close, nil
 }
 
 func (repo *Repository) Close() error {
        if repo == nil {
                return nil
        }
-       if repo.batchCancel != nil {
-               repo.batchCancel()
-               repo.batchReader = nil
-               repo.batchWriter = nil
-               repo.batchCancel = nil
+       if repo.batch != nil {
+               repo.batch.Close()
+               repo.batch = nil
                repo.batchInUse = false
        }
-       if repo.checkCancel != nil {
-               repo.checkCancel()
-               repo.checkCancel = nil
-               repo.checkReader = nil
-               repo.checkWriter = nil
+       if repo.check != nil {
+               repo.check.Close()
+               repo.check = nil
                repo.checkInUse = false
        }
        repo.LastCommitCache = nil
index 63d0f7268a65d96271dfa8c4b4f0f8401fc60b7e..0d2efd4a6b41e784b651ff2bf068be1e9b7fe91a 100644 (file)
@@ -22,9 +22,13 @@ func (repo *Repository) IsObjectExist(name string) bool {
                return false
        }
 
-       wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
+       wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
+       if err != nil {
+               log.Debug("Error writing to CatFileBatchCheck %v", err)
+               return false
+       }
        defer cancel()
-       _, err := wr.Write([]byte(name + "\n"))
+       _, err = wr.Write([]byte(name + "\n"))
        if err != nil {
                log.Debug("Error writing to CatFileBatchCheck %v", err)
                return false
@@ -39,9 +43,13 @@ func (repo *Repository) IsReferenceExist(name string) bool {
                return false
        }
 
-       wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
+       wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
+       if err != nil {
+               log.Debug("Error writing to CatFileBatchCheck %v", err)
+               return false
+       }
        defer cancel()
-       _, err := wr.Write([]byte(name + "\n"))
+       _, err = wr.Write([]byte(name + "\n"))
        if err != nil {
                log.Debug("Error writing to CatFileBatchCheck %v", err)
                return false
index ae4c21aaa3d7172b7bd5786f995d9f8ff946016e..f5ed282a45b1bdb3fb963036ad47eef180644fda 100644 (file)
@@ -33,9 +33,12 @@ func (repo *Repository) ResolveReference(name string) (string, error) {
 
 // GetRefCommitID returns the last commit ID string of given reference (branch or tag).
 func (repo *Repository) GetRefCommitID(name string) (string, error) {
-       wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
+       wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
+       if err != nil {
+               return "", err
+       }
        defer cancel()
-       _, err := wr.Write([]byte(name + "\n"))
+       _, err = wr.Write([]byte(name + "\n"))
        if err != nil {
                return "", err
        }
@@ -61,12 +64,19 @@ func (repo *Repository) RemoveReference(name string) error {
 
 // IsCommitExist returns true if given commit exists in current repository.
 func (repo *Repository) IsCommitExist(name string) bool {
+       if err := ensureValidGitRepository(repo.Ctx, repo.Path); err != nil {
+               log.Error("IsCommitExist: %v", err)
+               return false
+       }
        _, _, err := NewCommand(repo.Ctx, "cat-file", "-e").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
        return err == nil
 }
 
 func (repo *Repository) getCommit(id ObjectID) (*Commit, error) {
-       wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
+       wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
+       if err != nil {
+               return nil, err
+       }
        defer cancel()
 
        _, _ = wr.Write([]byte(id.String() + "\n"))
@@ -143,7 +153,10 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) {
                }
        }
 
-       wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
+       wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
+       if err != nil {
+               return nil, err
+       }
        defer cancel()
        _, err = wr.Write([]byte(commitID + "\n"))
        if err != nil {
index 318fc091ce3bb97400d8dbf93b95a7d08e22ac11..de7707bd6cd8bb507e9d1684ed6aed8b1e3197f5 100644 (file)
@@ -20,7 +20,10 @@ import (
 func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, error) {
        // We will feed the commit IDs in order into cat-file --batch, followed by blobs as necessary.
        // so let's create a batch stdin and stdout
-       batchStdinWriter, batchReader, cancel := repo.CatFileBatch(repo.Ctx)
+       batchStdinWriter, batchReader, cancel, err := repo.CatFileBatch(repo.Ctx)
+       if err != nil {
+               return nil, err
+       }
        defer cancel()
 
        writeID := func(id string) error {
index cbab39f8c576dca35052c7c538db90b99fa2843e..8b06a6a1c3c4e7a85d1b5ff923c0bbe5ec294ca4 100644 (file)
@@ -31,9 +31,12 @@ func (repo *Repository) GetTags(skip, limit int) (tags []string, err error) {
 
 // GetTagType gets the type of the tag, either commit (simple) or tag (annotated)
 func (repo *Repository) GetTagType(id ObjectID) (string, error) {
-       wr, rd, cancel := repo.CatFileBatchCheck(repo.Ctx)
+       wr, rd, cancel, err := repo.CatFileBatchCheck(repo.Ctx)
+       if err != nil {
+               return "", err
+       }
        defer cancel()
-       _, err := wr.Write([]byte(id.String() + "\n"))
+       _, err = wr.Write([]byte(id.String() + "\n"))
        if err != nil {
                return "", err
        }
@@ -89,7 +92,10 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
        }
 
        // The tag is an annotated tag with a message.
-       wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
+       wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
+       if err != nil {
+               return nil, err
+       }
        defer cancel()
 
        if _, err := wr.Write([]byte(tagID.String() + "\n")); err != nil {
index e82012de6f6c24a6a0ee536e89d22ed419fe762c..d74769ccb2122b3538c4c8fcaa882bab05a2adcd 100644 (file)
@@ -10,7 +10,10 @@ import (
 )
 
 func (repo *Repository) getTree(id ObjectID) (*Tree, error) {
-       wr, rd, cancel := repo.CatFileBatch(repo.Ctx)
+       wr, rd, cancel, err := repo.CatFileBatch(repo.Ctx)
+       if err != nil {
+               return nil, err
+       }
        defer cancel()
 
        _, _ = wr.Write([]byte(id.String() + "\n"))
index 89244e27ee80e588a4383406fc3437e4d64298e5..1c3bcd197a01dfe0efc8f9b364b2cb6b14b12f27 100644 (file)
@@ -42,9 +42,13 @@ func (te *TreeEntry) Size() int64 {
                return te.size
        }
 
-       wr, rd, cancel := te.ptree.repo.CatFileBatchCheck(te.ptree.repo.Ctx)
+       wr, rd, cancel, err := te.ptree.repo.CatFileBatchCheck(te.ptree.repo.Ctx)
+       if err != nil {
+               log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err)
+               return 0
+       }
        defer cancel()
-       _, err := wr.Write([]byte(te.ID.String() + "\n"))
+       _, err = wr.Write([]byte(te.ID.String() + "\n"))
        if err != nil {
                log.Debug("error whilst reading size for %s in %s. Error: %v", te.ID.String(), te.ptree.repo.Path, err)
                return 0
index a591485082ce63afd7de76c1302d6405491f41fa..c5e5b06a387ab538db5f9010108524eb8b161690 100644 (file)
@@ -33,7 +33,10 @@ func (t *Tree) ListEntries() (Entries, error) {
        }
 
        if t.repo != nil {
-               wr, rd, cancel := t.repo.CatFileBatch(t.repo.Ctx)
+               wr, rd, cancel, err := t.repo.CatFileBatch(t.repo.Ctx)
+               if err != nil {
+                       return nil, err
+               }
                defer cancel()
 
                _, _ = wr.Write([]byte(t.ID.String() + "\n"))
index 8056b58ec2350f0da05f99ff032121dde12d564d..542bdfb50141ab2d194a105cb7854d92e60f47c4 100644 (file)
@@ -16,10 +16,10 @@ import (
        "code.gitea.io/gitea/modules/analyze"
        "code.gitea.io/gitea/modules/charset"
        "code.gitea.io/gitea/modules/git"
+       "code.gitea.io/gitea/modules/gitrepo"
        "code.gitea.io/gitea/modules/indexer/code/internal"
        indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
        inner_bleve "code.gitea.io/gitea/modules/indexer/internal/bleve"
-       "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/timeutil"
        "code.gitea.io/gitea/modules/typesniffer"
@@ -189,21 +189,23 @@ func (b *Indexer) addDelete(filename string, repo *repo_model.Repository, batch
 func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error {
        batch := inner_bleve.NewFlushingBatch(b.inner.Indexer, maxBatchSize)
        if len(changes.Updates) > 0 {
-               // Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
-               if err := git.EnsureValidGitRepository(ctx, repo.RepoPath()); err != nil {
-                       log.Error("Unable to open git repo: %s for %-v: %v", repo.RepoPath(), repo, err)
+               r, err := gitrepo.OpenRepository(ctx, repo)
+               if err != nil {
                        return err
                }
-
-               batchWriter, batchReader, cancel := git.CatFileBatch(ctx, repo.RepoPath())
-               defer cancel()
+               defer r.Close()
+               gitBatch, err := r.NewBatch(ctx)
+               if err != nil {
+                       return err
+               }
+               defer gitBatch.Close()
 
                for _, update := range changes.Updates {
-                       if err := b.addUpdate(ctx, batchWriter, batchReader, sha, update, repo, batch); err != nil {
+                       if err := b.addUpdate(ctx, gitBatch.Writer, gitBatch.Reader, sha, update, repo, batch); err != nil {
                                return err
                        }
                }
-               cancel()
+               gitBatch.Close()
        }
        for _, filename := range changes.RemovedFilenames {
                if err := b.addDelete(filename, repo, batch); err != nil {
index e4622fd66ef958969e637589891acc6b0edbc7db..0bda180fac9ce8267ebc4350107dedf9e50a00aa 100644 (file)
@@ -15,11 +15,11 @@ import (
        "code.gitea.io/gitea/modules/analyze"
        "code.gitea.io/gitea/modules/charset"
        "code.gitea.io/gitea/modules/git"
+       "code.gitea.io/gitea/modules/gitrepo"
        "code.gitea.io/gitea/modules/indexer/code/internal"
        indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
        inner_elasticsearch "code.gitea.io/gitea/modules/indexer/internal/elasticsearch"
        "code.gitea.io/gitea/modules/json"
-       "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/setting"
        "code.gitea.io/gitea/modules/timeutil"
        "code.gitea.io/gitea/modules/typesniffer"
@@ -154,17 +154,19 @@ func (b *Indexer) addDelete(filename string, repo *repo_model.Repository) elasti
 func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error {
        reqs := make([]elastic.BulkableRequest, 0)
        if len(changes.Updates) > 0 {
-               // Now because of some insanity with git cat-file not immediately failing if not run in a valid git directory we need to run git rev-parse first!
-               if err := git.EnsureValidGitRepository(ctx, repo.RepoPath()); err != nil {
-                       log.Error("Unable to open git repo: %s for %-v: %v", repo.RepoPath(), repo, err)
+               r, err := gitrepo.OpenRepository(ctx, repo)
+               if err != nil {
                        return err
                }
-
-               batchWriter, batchReader, cancel := git.CatFileBatch(ctx, repo.RepoPath())
-               defer cancel()
+               defer r.Close()
+               batch, err := r.NewBatch(ctx)
+               if err != nil {
+                       return err
+               }
+               defer batch.Close()
 
                for _, update := range changes.Updates {
-                       updateReqs, err := b.addUpdate(ctx, batchWriter, batchReader, sha, update, repo)
+                       updateReqs, err := b.addUpdate(ctx, batch.Writer, batch.Reader, sha, update, repo)
                        if err != nil {
                                return err
                        }
@@ -172,7 +174,7 @@ func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha st
                                reqs = append(reqs, updateReqs...)
                        }
                }
-               cancel()
+               batch.Close()
        }
 
        for _, filename := range changes.RemovedFilenames {