forgejo/modules/git/repo_base_nogogit.go
zeripath 5cb0c9aa0d
Propagate context and ensure git commands run in request context ()
This PR continues the work in  by progressively ensuring that git
commands run within the request context.

This now means that the if there is a git repo already open in the context it will be used instead of reopening it.

Signed-off-by: Andrew Thornton <art27@cantab.net>
2022-01-19 23:26:57 +00:00

106 lines
2.9 KiB
Go

// Copyright 2015 The Gogs Authors. All rights reserved.
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:build !gogit
// +build !gogit
package git
import (
"bufio"
"context"
"errors"
"path/filepath"
"code.gitea.io/gitea/modules/log"
)
// Repository represents a Git repository.
type Repository struct {
Path string
tagCache *ObjectCache
gpgSettings *GPGSettings
batchCancel context.CancelFunc
batchReader *bufio.Reader
batchWriter WriteCloserError
checkCancel context.CancelFunc
checkReader *bufio.Reader
checkWriter WriteCloserError
Ctx context.Context
}
// OpenRepository opens the repository at the given path.
func OpenRepository(repoPath string) (*Repository, error) {
return OpenRepositoryCtx(DefaultContext, repoPath)
}
// OpenRepositoryCtx opens the repository at the given path with the provided context.
func OpenRepositoryCtx(ctx context.Context, repoPath string) (*Repository, error) {
repoPath, err := filepath.Abs(repoPath)
if err != nil {
return nil, err
} else if !isDir(repoPath) {
return nil, errors.New("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{
Path: repoPath,
tagCache: newObjectCache(),
Ctx: ctx,
}
repo.batchWriter, repo.batchReader, repo.batchCancel = CatFileBatch(ctx, repoPath)
repo.checkWriter, repo.checkReader, repo.checkCancel = CatFileBatchCheck(ctx, repo.Path)
return repo, nil
}
// CatFileBatch obtains a CatFileBatch for this repository
func (repo *Repository) CatFileBatch(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
if repo.batchCancel == nil || repo.batchReader.Buffered() > 0 {
log.Debug("Opening temporary cat file batch for: %s", repo.Path)
return CatFileBatch(ctx, repo.Path)
}
return repo.batchWriter, repo.batchReader, func() {}
}
// CatFileBatchCheck obtains a CatFileBatchCheck for this repository
func (repo *Repository) CatFileBatchCheck(ctx context.Context) (WriteCloserError, *bufio.Reader, func()) {
if repo.checkCancel == nil || repo.checkReader.Buffered() > 0 {
log.Debug("Opening temporary cat file batch-check: %s", repo.Path)
return CatFileBatchCheck(ctx, repo.Path)
}
return repo.checkWriter, repo.checkReader, func() {}
}
// Close this repository, in particular close the underlying gogitStorage if this is not nil
func (repo *Repository) Close() (err error) {
if repo == nil {
return
}
if repo.batchCancel != nil {
repo.batchCancel()
repo.batchReader = nil
repo.batchWriter = nil
repo.batchCancel = nil
}
if repo.checkCancel != nil {
repo.checkCancel()
repo.checkCancel = nil
repo.checkReader = nil
repo.checkWriter = nil
}
return
}