refactor: git repo and relative path handling (#38522)

1. simplify "StorageRepo" code
2. simplify git.OpenRepository code
3. by the way, clean up some unused files in git test fixtures.
This commit is contained in:
wxiaoguang
2026-07-19 15:32:00 +08:00
committed by GitHub
parent ae176cd649
commit b06002f449
100 changed files with 315 additions and 290 deletions

View File

@@ -83,7 +83,7 @@ func AddCommitDivergenceToPulls(x db.EngineMigration) error {
log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID)
continue
}
repoStore := repo_model.StorageRepo(repo_model.RelativePath(baseRepo.OwnerName, baseRepo.Name))
repoStore := repo_model.CodeRepoByName(baseRepo.OwnerName, baseRepo.Name)
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
divergence, err := gitrepo.GetDivergingCommits(graceful.GetManager().HammerContext(), repoStore, pr.BaseBranch, gitRefName)
if err != nil {

View File

@@ -6,24 +6,14 @@ package v1_14
import (
"context"
"fmt"
"path/filepath"
"strings"
"gitea.dev/models/db"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/log"
"gitea.dev/modules/setting"
)
// Copy paste from models/repo.go because we cannot import models package
func repoPath(userName, repoName string) string {
return filepath.Join(userPath(userName), strings.ToLower(repoName)+".git")
}
func userPath(userName string) string {
return filepath.Join(setting.RepoRootPath, strings.ToLower(userName))
}
func FixPublisherIDforTagReleases(ctx context.Context, x db.EngineMigration) error {
type Release struct {
ID int64
@@ -108,7 +98,7 @@ func FixPublisherIDforTagReleases(ctx context.Context, x db.EngineMigration) err
return err
}
}
gitRepo, err = git.OpenRepository(repoPath(repo.OwnerName, repo.Name))
gitRepo, err = git.OpenRepository(repo_model.CodeRepoByName(repo.OwnerName, repo.Name))
if err != nil {
log.Error("Error whilst opening git repo for [%d]%s/%s. Error: %v", repo.ID, repo.OwnerName, repo.Name, err)
return err

View File

@@ -159,12 +159,12 @@ func migratePushMirrors(x db.EngineMigration) error {
func getRemoteAddress(ownerName, repoName, remoteName string) (string, error) {
ctx := context.Background()
relativePath := repo_model.RelativePath(ownerName, repoName)
if exist, _ := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(relativePath)); !exist {
repo := repo_model.CodeRepoByName(ownerName, repoName)
if exist, _ := gitrepo.IsRepositoryExist(ctx, repo); !exist {
return "", nil
}
u, err := gitrepo.GitRemoteGetURL(ctx, repo_model.StorageRepo(relativePath), remoteName)
u, err := gitrepo.GitRemoteGetURL(ctx, repo, remoteName)
if err != nil {
return "", err
}

View File

@@ -87,7 +87,7 @@ func FixReleaseSha1OnReleaseTable(ctx context.Context, x db.EngineMigration) err
userCache[repo.OwnerID] = user
}
gitRepo, err = gitrepo.OpenRepository(repo_model.StorageRepo(repo_model.RelativePath(user.Name, repo.Name)))
gitRepo, err = gitrepo.OpenRepository(repo_model.CodeRepoByName(user.Name, repo.Name))
if err != nil {
return err
}

View File

@@ -80,7 +80,7 @@ func (archiver *RepoArchiver) RelativePath() string {
return fmt.Sprintf("%d/%s/%s.%s", archiver.RepoID, archiver.CommitID[:2], archiver.CommitID, archiver.Type.String())
}
// repoArchiverForRelativePath takes a relativePath created from (archiver *RepoArchiver) RelativePath() and creates a shell repoArchiver struct representing it
// repoArchiverForRelativePath takes a relativePath created from RepoArchiver.RelativePath() and creates a shell repoArchiver struct representing it
func repoArchiverForRelativePath(relativePath string) (*RepoArchiver, error) {
parts := strings.SplitN(relativePath, "/", 3)
if len(parts) != 3 {

View File

@@ -226,30 +226,6 @@ func init() {
db.RegisterModel(new(Repository))
}
func RelativePath(ownerName, repoName string) string {
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
}
func (repo *Repository) GitRepoLocation() string {
return RelativePath(repo.OwnerName, repo.Name)
}
func (repo *Repository) GitRepoUniqueID() string {
return strconv.FormatInt(repo.ID, 10)
}
type StorageRepo string
func (sr StorageRepo) GitRepoUniqueID() string {
// TODO: need to correctly refactor this method in the future.
// "unique id" should be a cache-key-friendly string, but not a full repo path
return string(sr)
}
func (sr StorageRepo) GitRepoLocation() string {
return string(sr)
}
// SanitizedOriginalURL returns a sanitized OriginalURL
func (repo *Repository) SanitizedOriginalURL() string {
if repo.OriginalURL == "" {

View File

@@ -0,0 +1,56 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repo
import (
"strconv"
"strings"
"gitea.dev/modules/git/gitcmd"
)
func repoCodeGitRepoRelativePath(ownerName, repoName string) string {
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
}
func repoWikiGitRepoRelativePath(ownerName, repoName string) string {
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
}
// CodeRepoByName returns an unmanaged repository facade for the code repository of the given owner and repository name.
// Usually it is used for migration fixes or repository adoption/creation/rename/transfer.
func CodeRepoByName(ownerName, repoName string) gitcmd.RepositoryFacade {
return gitcmd.RepositoryUnmanaged(repoCodeGitRepoRelativePath(ownerName, repoName))
}
func WikiRepoByName(ownerName, repoName string) gitcmd.RepositoryFacade {
return gitcmd.RepositoryUnmanaged(repoWikiGitRepoRelativePath(ownerName, repoName))
}
func repoCodeGitRepoManagedID(repoID int64) string {
return "repo-" + strconv.FormatInt(repoID, 10)
}
func (repo *Repository) CodeStorageRepo() gitcmd.RepositoryFacade {
id := repoCodeGitRepoManagedID(repo.ID)
repoPath := repoCodeGitRepoRelativePath(repo.OwnerName, repo.Name)
return gitcmd.RepositoryManaged(id, repoPath)
}
func (repo *Repository) GitRepoLocation() string {
// TODO: use CodeGitRepo instead of this one
return repoCodeGitRepoRelativePath(repo.OwnerName, repo.Name)
}
func (repo *Repository) GitRepoManagedID() string {
// TODO: use CodeGitRepo instead of this one
return repoCodeGitRepoManagedID(repo.ID)
}
func (repo *Repository) WikiStorageRepo() gitcmd.RepositoryFacade {
// The wiki repository should have the same object format as the code repository. TODO: old comment, REALLY? Why?
id := "repo-wiki-" + strconv.FormatInt(repo.ID, 10)
repoPath := repoWikiGitRepoRelativePath(repo.OwnerName, repo.Name)
return gitcmd.RepositoryManaged(id, repoPath)
}

View File

@@ -0,0 +1,27 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repo_test
import (
"testing"
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
"github.com/stretchr/testify/assert"
)
func TestRepository_GitRepo(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
assert.Equal(t, "user2/repo1.git", repo_model.CodeRepoByName(repo.OwnerName, repo.Name).GitRepoLocation())
assert.Equal(t, "user2/repo1.git", repo.CodeStorageRepo().GitRepoLocation())
assert.Equal(t, "repo-1", repo.CodeStorageRepo().GitRepoManagedID())
assert.Equal(t, "user2/repo1.wiki.git", repo_model.WikiRepoByName(repo.OwnerName, repo.Name).GitRepoLocation())
assert.Equal(t, "user2/repo1.wiki.git", repo.WikiStorageRepo().GitRepoLocation())
assert.Equal(t, "repo-wiki-1", repo.WikiStorageRepo().GitRepoManagedID())
}

View File

@@ -7,7 +7,6 @@ package repo
import (
"context"
"fmt"
"strings"
user_model "gitea.dev/models/user"
"gitea.dev/modules/util"
@@ -74,13 +73,3 @@ func (err ErrWikiInvalidFileName) Unwrap() error {
func (repo *Repository) WikiCloneLink(ctx context.Context, doer *user_model.User) *CloneLink {
return repo.cloneLink(ctx, doer, repo.Name+".wiki")
}
func RelativeWikiPath(ownerName, repoName string) string {
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
}
// WikiStorageRepo returns the storage repo for the wiki like "owner-name/repo-name.wiki.git"
// The wiki repository should have the same object format as the code repository. TODO: REALLY? Why?
func (repo *Repository) WikiStorageRepo() StorageRepo {
return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name))
}

View File

@@ -20,11 +20,3 @@ func TestRepository_WikiCloneLink(t *testing.T) {
assert.Equal(t, "ssh://sshuser@try.gitea.io:3000/user2/repo1.wiki.git", cloneLink.SSH)
assert.Equal(t, "https://try.gitea.io/user2/repo1.wiki.git", cloneLink.HTTPS)
}
func TestRepository_RelativeWikiPath(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
assert.Equal(t, "user2/repo1.wiki.git", repo_model.RelativeWikiPath(repo.OwnerName, repo.Name))
assert.Equal(t, "user2/repo1.wiki.git", repo.WikiStorageRepo().GitRepoLocation())
}

View File

@@ -1,3 +0,0 @@
# Git Module
This module is merged from https://github.com/go-gitea/git which is a Go module to access Git through shell commands. Now it's a part of gitea's main repository for easier pull request.

View File

@@ -119,7 +119,7 @@ func Test_BatchChecker(t *testing.T) {
setting.AppDataPath = t.TempDir()
repoPath := "../tests/repos/language_stats_repo"
ctx := t.Context()
gitRepo, err := git.OpenRepository(repoPath)
gitRepo, err := git.OpenRepositoryLocal(repoPath)
require.NoError(t, err)
defer gitRepo.Close()
@@ -144,7 +144,7 @@ func Test_BatchChecker(t *testing.T) {
})
assert.NoError(t, err)
tempRepo, err := git.OpenRepository(dir)
tempRepo, err := git.OpenRepositoryLocal(dir)
assert.NoError(t, err)
defer tempRepo.Close()

View File

@@ -18,7 +18,7 @@ import (
func Test_Checker(t *testing.T) {
setting.AppDataPath = t.TempDir()
repoPath := "../tests/repos/language_stats_repo"
gitRepo, err := git.OpenRepository(repoPath)
gitRepo, err := git.OpenRepositoryLocal(repoPath)
require.NoError(t, err)
defer gitRepo.Close()
@@ -44,7 +44,7 @@ func Test_Checker(t *testing.T) {
})
assert.NoError(t, err)
tempRepo, err := git.OpenRepository(dir)
tempRepo, err := git.OpenRepositoryLocal(dir)
assert.NoError(t, err)
defer tempRepo.Close()

View File

@@ -16,7 +16,7 @@ import (
func TestBlob_Data(t *testing.T) {
output := "file2\n"
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
repo, err := OpenRepositoryLocal(bareRepo1Path)
require.NoError(t, err)
defer repo.Close()
@@ -36,7 +36,7 @@ func TestBlob_Data(t *testing.T) {
func Benchmark_Blob_Data(b *testing.B) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
repo, err := OpenRepositoryLocal(bareRepo1Path)
if err != nil {
b.Fatal(err)
}

View File

@@ -6,6 +6,8 @@ package git
import (
"context"
"io"
"gitea.dev/modules/git/gitcmd"
)
type BufferedReader interface {
@@ -45,7 +47,8 @@ type CatFileBatchCloser interface {
// NewBatch creates a "batch object provider (CatFileBatch)" for the given repository path to retrieve object info and content efficiently.
// The CatFileBatch and the readers create by it should only be used in the same goroutine.
func NewBatch(ctx context.Context, repoPath string) (CatFileBatchCloser, error) {
func NewBatch(ctx context.Context, repo RepositoryFacade) (CatFileBatchCloser, error) {
repoPath := gitcmd.RepoLocalPath(repo)
if DefaultFeatures().SupportCatFileBatchCommand {
return newCatFileBatchCommand(ctx, repoPath)
}

View File

@@ -9,6 +9,7 @@ import (
"path/filepath"
"testing"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/test"
"github.com/stretchr/testify/assert"
@@ -24,9 +25,10 @@ func TestCatFileBatch(t *testing.T) {
}
func testCatFileBatch(t *testing.T) {
repo1 := gitcmd.RepositoryUnmanaged(filepath.Join(testReposDir, "repo1_bare"))
t.Run("CorruptedGitRepo", func(t *testing.T) {
tmpDir := t.TempDir()
batch, err := NewBatch(t.Context(), tmpDir)
batch, err := NewBatch(t.Context(), gitcmd.RepositoryUnmanaged(tmpDir))
// as long as the directory exists, no error, because we can't really know whether the git repo is valid until we run commands
require.NoError(t, err)
defer batch.Close()
@@ -47,7 +49,7 @@ func testCatFileBatch(t *testing.T) {
assert.ErrorIs(t, err, expectedErr)
}
batch, err := NewBatch(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
batch, err := NewBatch(t.Context(), repo1)
require.NoError(t, err)
defer batch.Close()
_, err = batch.QueryInfo("e2129701f1a4d54dc44f03c93bca0a2aec7c5449")
@@ -79,7 +81,7 @@ func testCatFileBatch(t *testing.T) {
simulateQueryTerminated(t, nil, os.ErrClosed) // pipes are closed faster
})
batch, err := NewBatch(t.Context(), filepath.Join(testReposDir, "repo1_bare"))
batch, err := NewBatch(t.Context(), repo1)
require.NoError(t, err)
defer batch.Close()

View File

@@ -18,7 +18,7 @@ import (
)
func TestEntries_GetCommitsInfo_ContextErr(t *testing.T) {
repo, err := OpenRepository(filepath.Join(testReposDir, "repo1_bare"))
repo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo1_bare"))
require.NoError(t, err)
defer repo.Close()

View File

@@ -12,10 +12,6 @@ import (
"github.com/stretchr/testify/require"
)
const (
testReposDir = "tests/repos/"
)
func cloneRepo(tb testing.TB, url string) (string, error) {
repoDir := tb.TempDir()
if err := Clone(tb.Context(), url, repoDir, CloneRepoOptions{
@@ -132,7 +128,7 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
func TestEntries_GetCommitsInfo(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -142,7 +138,7 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
if err != nil {
assert.NoError(t, err)
}
clonedRepo1, err := OpenRepository(clonedPath)
clonedRepo1, err := OpenRepositoryLocal(clonedPath)
if err != nil {
assert.NoError(t, err)
}

View File

@@ -60,7 +60,7 @@ signed commit`
0x94, 0x33, 0xb2, 0xa6, 0x2b, 0x96, 0x4c, 0x17, 0xa4, 0x48, 0x5a, 0xe1, 0x80, 0xf4, 0x5f, 0x59,
0x5d, 0x3e, 0x69, 0xd3, 0x1b, 0x78, 0x60, 0x87, 0x77, 0x5e, 0x28, 0xc6, 0xb6, 0x39, 0x9d, 0xf0,
}
gitRepo, err := OpenRepository(filepath.Join(testReposDir, "repo1_bare_sha256"))
gitRepo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo1_bare_sha256"))
assert.NoError(t, err)
assert.NotNil(t, gitRepo)
defer gitRepo.Close()
@@ -103,7 +103,7 @@ signed commit`, commitFromReader.Signature.Payload)
func TestHasPreviousCommitSha256(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare_sha256")
repo, err := OpenRepository(bareRepo1Path)
repo, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer repo.Close()

View File

@@ -56,7 +56,7 @@ gpgsig -----BEGIN PGP SIGNATURE-----
empty commit`
sha := &Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2}
gitRepo, err := OpenRepository(filepath.Join(testReposDir, "repo1_bare"))
gitRepo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo1_bare"))
assert.NoError(t, err)
assert.NotNil(t, gitRepo)
defer gitRepo.Close()
@@ -120,7 +120,7 @@ gpgsig -----BEGIN PGP SIGNATURE-----
ISO-8859-1`
commitString = strings.ReplaceAll(commitString, "<SPACE>", " ")
sha := &Sha1Hash{0xfe, 0xaf, 0x4b, 0xa6, 0xbc, 0x63, 0x5f, 0xec, 0x44, 0x2f, 0x46, 0xdd, 0xd4, 0x51, 0x24, 0x16, 0xec, 0x43, 0xc2, 0xc2}
gitRepo, err := OpenRepository(filepath.Join(testReposDir, "repo1_bare"))
gitRepo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo1_bare"))
assert.NoError(t, err)
assert.NotNil(t, gitRepo)
defer gitRepo.Close()
@@ -162,7 +162,7 @@ ISO-8859-1`, commitFromReader.Signature.Payload)
func TestHasPreviousCommit(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
repo, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer repo.Close()
@@ -187,7 +187,7 @@ func TestHasPreviousCommit(t *testing.T) {
func Test_GetCommitBranchStart(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
repo, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer repo.Close()
commit, err := repo.GetBranchCommit(t.Context(), "branch1")

View File

@@ -198,9 +198,9 @@ func runGitTests(m interface{ Run() int }) int {
}
func LockConfigAndDo(ctx context.Context, repo RepositoryFacade, fn func(ctx context.Context) error) error {
return globallock.LockAndDo(ctx, "repo-config:"+repo.GitRepoUniqueID(), fn)
return globallock.LockAndDo(ctx, "repo-config:"+repo.GitRepoManagedID(), fn)
}
func LockWriteAndDo(ctx context.Context, repo RepositoryFacade, fn func(ctx context.Context) error) error {
return globallock.LockAndDo(ctx, "repo-write:"+repo.GitRepoUniqueID(), fn)
return globallock.LockAndDo(ctx, "repo-write:"+repo.GitRepoManagedID(), fn)
}

View File

@@ -10,6 +10,8 @@ import (
"github.com/stretchr/testify/assert"
)
const testReposDir = "tests/repos/"
func TestMain(m *testing.M) {
RunGitTests(m)
}

View File

@@ -10,7 +10,14 @@ import (
)
type RepositoryFacade interface {
GitRepoUniqueID() string
// GitRepoManagedID returns a "managed id", which should be a cache-key-friendly string.
// e.g.: ID with prefix&suffix or UUID
GitRepoManagedID() string
// GitRepoLocation returns the location for the git repository.
// * relative path: will be converted to an absolute path by setting.RepoRootPath
// * absolute path: will be used as-is
// * in the future: maybe URI for more flexible definitions
GitRepoLocation() string
}
@@ -26,3 +33,34 @@ func RepoLocalPath(repo RepositoryFacade) string {
}
return filepath.Join(setting.RepoRootPath, filepath.FromSlash(repoLoc))
}
type repositoryUnmanaged string
func (r repositoryUnmanaged) GitRepoManagedID() string {
panic("this repo is not managed by Gitea, can't be used in this managed context")
}
func (r repositoryUnmanaged) GitRepoLocation() string {
return string(r)
}
func RepositoryUnmanaged(s string) RepositoryFacade {
return repositoryUnmanaged(s)
}
type repositoryManaged struct {
id string
loc string
}
func (r *repositoryManaged) GitRepoManagedID() string {
return r.id
}
func (r *repositoryManaged) GitRepoLocation() string {
return r.loc
}
func RepositoryManaged(id, loc string) RepositoryFacade {
return &repositoryManaged{id, loc}
}

View File

@@ -11,7 +11,7 @@ import (
)
func TestGrepSearch(t *testing.T) {
repo, err := OpenRepository(filepath.Join(testReposDir, "language_stats_repo"))
repo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "language_stats_repo"))
assert.NoError(t, err)
defer repo.Close()

View File

@@ -18,7 +18,7 @@ import (
func TestRepository_GetLanguageStats(t *testing.T) {
setting.AppDataPath = t.TempDir()
repoPath := "../tests/repos/language_stats_repo"
gitRepo, err := git.OpenRepository(repoPath)
gitRepo, err := git.OpenRepositoryLocal(repoPath)
require.NoError(t, err)
defer gitRepo.Close()

View File

@@ -12,7 +12,7 @@ import (
func TestGetNotes(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -25,7 +25,7 @@ func TestGetNotes(t *testing.T) {
func TestGetNestedNotes(t *testing.T) {
repoPath := filepath.Join(testReposDir, "repo3_notes")
repo, err := OpenRepository(repoPath)
repo, err := OpenRepositoryLocal(repoPath)
assert.NoError(t, err)
defer repo.Close()
@@ -40,7 +40,7 @@ func TestGetNestedNotes(t *testing.T) {
func TestGetNonExistentNotes(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()

View File

@@ -15,7 +15,7 @@ import (
func TestFindLFSFile(t *testing.T) {
repoPath := "../../../tests/gitea-repositories-meta/user2/lfs.git"
gitRepo, err := git.OpenRepository(repoPath)
gitRepo, err := git.OpenRepositoryLocal(repoPath)
require.NoError(t, err)
defer gitRepo.Close()

View File

@@ -28,15 +28,23 @@ type RepositoryBase struct {
LastCommitCache *LastCommitCache
repoFacade RepositoryFacade
tagCache *ObjectCache[*Tag]
objectFormatCache ObjectFormat
}
func OpenRepository(repoPath string) (*Repository, error) {
repoPath, err := filepath.Abs(repoPath)
if err != nil {
return nil, err
}
var _ gitcmd.RepositoryFacade = (*Repository)(nil)
func (repo *Repository) GitRepoManagedID() string {
return repo.repoFacade.GitRepoManagedID()
}
func (repo *Repository) GitRepoLocation() string {
return repo.repoFacade.GitRepoLocation()
}
func OpenRepository(repo RepositoryFacade) (*Repository, error) {
repoPath := gitcmd.RepoLocalPath(repo)
exist, err := util.IsDir(repoPath)
if err != nil {
return nil, err
@@ -45,7 +53,7 @@ func OpenRepository(repoPath string) (*Repository, error) {
return nil, util.NewNotExistErrorf("no such file or directory")
}
gitRepo := &Repository{
RepositoryBase: RepositoryBase{Path: repoPath, tagCache: newObjectCache[*Tag]()},
RepositoryBase: RepositoryBase{Path: repoPath, tagCache: newObjectCache[*Tag](), repoFacade: repo},
}
if err = openRepositoryInternal(gitRepo); err != nil {
return nil, err
@@ -53,6 +61,16 @@ func OpenRepository(repoPath string) (*Repository, error) {
return gitRepo, nil
}
func OpenRepositoryLocal(localPath string) (_ *Repository, err error) {
if !filepath.IsAbs(localPath) {
localPath, err = filepath.Abs(localPath)
if err != nil {
return nil, err
}
}
return OpenRepository(gitcmd.RepositoryUnmanaged(localPath))
}
func (repo *Repository) Close() error {
if repo == nil {
setting.PanicInDevOrTesting("don't close a nil repository")

View File

@@ -42,7 +42,7 @@ func (repo *Repository) CatFileBatch(ctx context.Context) (_ CatFileBatch, close
}
if repo.catFileBatchCloser == nil {
repo.catFileBatchCloser, err = NewBatch(ctx, repo.Path)
repo.catFileBatchCloser, err = NewBatch(ctx, repo)
if err != nil {
repo.catFileBatchCloser = nil // otherwise it is "interface(nil)" and will cause wrong logic
return nil, nil, err
@@ -59,7 +59,7 @@ func (repo *Repository) CatFileBatch(ctx context.Context) (_ CatFileBatch, close
}
log.Debug("Opening temporary cat file batch for: %s", repo.Path)
tempBatch, err := NewBatch(ctx, repo.Path)
tempBatch, err := NewBatch(ctx, repo)
if err != nil {
return nil, nil, err
}

View File

@@ -6,6 +6,7 @@
package git
import (
"os"
"path/filepath"
"testing"
@@ -14,9 +15,13 @@ import (
func TestRepoCatFileBatch(t *testing.T) {
t.Run("MissingRepoAndClose", func(t *testing.T) {
repo, err := OpenRepository(filepath.Join(testReposDir, "repo1_bare"))
testDir := filepath.Join(t.TempDir(), "testdir")
_ = os.Mkdir(testDir, 0o755)
repo, err := OpenRepositoryLocal(testDir)
require.NoError(t, err)
// when the repo is missing (it usually occurs during testing because the fixtures are synced frequently)
err = os.Remove(testDir)
require.NoError(t, err)
repo.Path = "/no-such" // when the repo is missing (it usually occurs during testing because the fixtures are synced frequently)
_, _, err = repo.CatFileBatch(t.Context())
require.Error(t, err)
require.NoError(t, repo.Close()) // shouldn't panic

View File

@@ -14,7 +14,7 @@ import (
func TestRepository_GetBlob_Found(t *testing.T) {
repoPath := filepath.Join(testReposDir, "repo1_bare")
r, err := OpenRepository(repoPath)
r, err := OpenRepositoryLocal(repoPath)
assert.NoError(t, err)
defer r.Close()
@@ -42,7 +42,7 @@ func TestRepository_GetBlob_Found(t *testing.T) {
func TestRepository_GetBlob_NotExist(t *testing.T) {
repoPath := filepath.Join(testReposDir, "repo1_bare")
r, err := OpenRepository(repoPath)
r, err := OpenRepositoryLocal(repoPath)
assert.NoError(t, err)
defer r.Close()
@@ -56,7 +56,7 @@ func TestRepository_GetBlob_NotExist(t *testing.T) {
func TestRepository_GetBlob_NoId(t *testing.T) {
repoPath := filepath.Join(testReposDir, "repo1_bare")
r, err := OpenRepository(repoPath)
r, err := OpenRepositoryLocal(repoPath)
assert.NoError(t, err)
defer r.Close()

View File

@@ -13,7 +13,7 @@ import (
func TestRepository_GetBranches(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -41,7 +41,7 @@ func TestRepository_GetBranches(t *testing.T) {
func BenchmarkRepository_GetBranches(b *testing.B) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
if err != nil {
b.Fatal(err)
}
@@ -57,7 +57,7 @@ func BenchmarkRepository_GetBranches(b *testing.B) {
func TestGetRefsBySha(t *testing.T) {
bareRepo5Path := filepath.Join(testReposDir, "repo5_pulls")
bareRepo5, err := OpenRepository(bareRepo5Path)
bareRepo5, err := OpenRepositoryLocal(bareRepo5Path)
if err != nil {
t.Fatal(err)
}
@@ -84,7 +84,7 @@ func TestGetRefsBySha(t *testing.T) {
func BenchmarkGetRefsBySha(b *testing.B) {
bareRepo5Path := filepath.Join(testReposDir, "repo5_pulls")
bareRepo5, err := OpenRepository(bareRepo5Path)
bareRepo5, err := OpenRepositoryLocal(bareRepo5Path)
if err != nil {
b.Fatal(err)
}
@@ -98,7 +98,7 @@ func BenchmarkGetRefsBySha(b *testing.B) {
func TestRepository_IsObjectExist(t *testing.T) {
ctx := t.Context()
repo, err := OpenRepository(filepath.Join(testReposDir, "repo1_bare"))
repo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo1_bare"))
require.NoError(t, err)
defer repo.Close()
@@ -151,7 +151,7 @@ func TestRepository_IsObjectExist(t *testing.T) {
func TestRepository_IsReferenceExist(t *testing.T) {
ctx := t.Context()
repo, err := OpenRepository(filepath.Join(testReposDir, "repo1_bare"))
repo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo1_bare"))
require.NoError(t, err)
defer repo.Close()

View File

@@ -18,7 +18,7 @@ import (
func TestRepository_GetCommitBranches(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -45,7 +45,7 @@ func TestRepository_GetCommitBranches(t *testing.T) {
func TestGetTagCommitWithSignature(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -60,7 +60,7 @@ func TestGetTagCommitWithSignature(t *testing.T) {
func TestGetCommitWithBadCommitID(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -72,7 +72,7 @@ func TestGetCommitWithBadCommitID(t *testing.T) {
func TestIsCommitInBranch(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -87,7 +87,7 @@ func TestIsCommitInBranch(t *testing.T) {
func TestRepository_CommitsBetween(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo4_commitsbetween")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -109,7 +109,7 @@ func TestRepository_CommitsBetween(t *testing.T) {
func TestGetRefCommitID(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -136,7 +136,7 @@ func TestCommitsByFileAndRange(t *testing.T) {
defer test.MockVariableValue(&setting.Git.CommitsRangeSize, 2)()
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
require.NoError(t, err)
defer bareRepo1.Close()
@@ -179,7 +179,7 @@ M 100644 :1 b.txt
`))).RunStdString(t.Context())
require.NoError(t, runErr)
repoFollowRename, err := OpenRepository(repoFollowRenameDir)
repoFollowRename, err := OpenRepositoryLocal(repoFollowRenameDir)
require.NoError(t, err)
defer repoFollowRename.Close()

View File

@@ -12,10 +12,10 @@ import (
// WriteCommitGraph write commit graph to speed up repo access
// this requires git v2.18 to be installed
func WriteCommitGraph(ctx context.Context, repoPath string) error {
func WriteCommitGraph(ctx context.Context, repo RepositoryFacade) error {
if DefaultFeatures().CheckVersionAtLeast("2.18") {
if _, _, err := gitcmd.NewCommand("commit-graph", "write").WithDir(repoPath).RunStdString(ctx); err != nil {
return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err)
if _, _, err := gitcmd.NewCommand("commit-graph", "write").WithRepo(repo).RunStdString(ctx); err != nil {
return fmt.Errorf("unable to write commit-graph for '%s' : %w", repo.GitRepoLocation(), err)
}
}
return nil

View File

@@ -22,7 +22,7 @@ func TestGetFormatPatch(t *testing.T) {
return
}
repo, err := OpenRepository(clonedPath)
repo, err := OpenRepositoryLocal(clonedPath)
if err != nil {
assert.NoError(t, err)
return
@@ -50,7 +50,7 @@ func TestGetFormatPatch(t *testing.T) {
func TestReadPatch(t *testing.T) {
// Ensure we can read the patch files
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
repo, err := OpenRepositoryLocal(bareRepo1Path)
if err != nil {
assert.NoError(t, err)
return
@@ -88,7 +88,7 @@ func TestReadWritePullHead(t *testing.T) {
return
}
repo, err := OpenRepository(clonedPath)
repo, err := OpenRepositoryLocal(clonedPath)
if err != nil {
assert.NoError(t, err)
return
@@ -130,7 +130,7 @@ func TestReadWritePullHead(t *testing.T) {
func TestGetCommitFilesChanged(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
repo, err := OpenRepository(bareRepo1Path)
repo, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer repo.Close()

View File

@@ -12,7 +12,7 @@ import (
func TestRepository_GetRefs(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()
@@ -37,7 +37,7 @@ func TestRepository_GetRefs(t *testing.T) {
func TestRepository_GetRefsFiltered(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()

View File

@@ -13,7 +13,7 @@ import (
func TestRepository_GetCodeActivityStats(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
assert.NoError(t, err)
defer bareRepo1.Close()

View File

@@ -13,7 +13,7 @@ import (
func TestRepository_GetTagInfos(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
bareRepo1, err := OpenRepository(bareRepo1Path)
bareRepo1, err := OpenRepositoryLocal(bareRepo1Path)
if err != nil {
assert.NoError(t, err)
return
@@ -44,7 +44,7 @@ func TestRepository_GetTag(t *testing.T) {
return
}
bareRepo1, err := OpenRepository(clonedPath)
bareRepo1, err := OpenRepositoryLocal(clonedPath)
if err != nil {
assert.NoError(t, err)
return
@@ -136,7 +136,7 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
return
}
bareRepo1, err := OpenRepository(clonedPath)
bareRepo1, err := OpenRepositoryLocal(clonedPath)
if err != nil {
assert.NoError(t, err)
return

View File

@@ -15,7 +15,7 @@ import (
func TestRepoIsEmpty(t *testing.T) {
emptyRepo2Path := filepath.Join(testReposDir, "repo2_empty")
repo, err := OpenRepository(emptyRepo2Path)
repo, err := OpenRepositoryLocal(emptyRepo2Path)
assert.NoError(t, err)
defer repo.Close()
isEmpty, err := repo.IsEmpty(t.Context())

View File

@@ -1,3 +0,0 @@
Add some test files for GetLanguageStats
Signed-off-by: Andrew Thornton <art27@cantab.net>

View File

@@ -4,6 +4,7 @@
package git
import (
"path/filepath"
"testing"
"gitea.dev/modules/util"
@@ -13,7 +14,7 @@ import (
)
func TestFollowLink(t *testing.T) {
r, err := OpenRepository("tests/repos/repo1_bare")
r, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo1_bare"))
require.NoError(t, err)
defer r.Close()

View File

@@ -11,7 +11,7 @@ import (
)
func TestSubTree_Issue29101(t *testing.T) {
repo, err := OpenRepository(filepath.Join(testReposDir, "repo1_bare"))
repo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo1_bare"))
assert.NoError(t, err)
defer repo.Close()
@@ -27,7 +27,7 @@ func TestSubTree_Issue29101(t *testing.T) {
}
func Test_GetTreePathLatestCommit(t *testing.T) {
repo, err := OpenRepository(filepath.Join(testReposDir, "repo6_blame"))
repo, err := OpenRepositoryLocal(filepath.Join(testReposDir, "repo6_blame"))
assert.NoError(t, err)
defer repo.Close()

View File

@@ -1,14 +0,0 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"context"
"gitea.dev/modules/git"
)
func NewBatch(ctx context.Context, repo Repository) (git.CatFileBatchCloser, error) {
return git.NewBatch(ctx, repoPath(repo))
}

View File

@@ -9,6 +9,8 @@ import (
"gitea.dev/modules/git/gitcmd"
)
// TODO: all wrappers can be removed in next PR, because cmd now can accept Repository directly.
func RunCmd(ctx context.Context, repo Repository, cmd *gitcmd.Command) error {
return cmd.WithRepo(repo).WithParentCallerInfo().Run(ctx)
}

View File

@@ -1,14 +0,0 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"context"
"gitea.dev/modules/git"
)
func WriteCommitGraph(ctx context.Context, repo Repository) error {
return git.WriteCommitGraph(ctx, repoPath(repo))
}

View File

@@ -19,16 +19,14 @@ import (
type Repository = gitcmd.RepositoryFacade
var repoPath = gitcmd.RepoLocalPath
// OpenRepository opens the repository at the given relative path with the provided context.
func OpenRepository(repo Repository) (*git.Repository, error) {
return git.OpenRepository(repoPath(repo))
}
var (
repoPath = gitcmd.RepoLocalPath
OpenRepository = git.OpenRepository
)
// contextKey is a value for use with context.WithValue.
type contextKey struct {
uniqueID string
key string
}
// RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it
@@ -46,11 +44,11 @@ func RepositoryFromContextOrOpen(ctx context.Context, repo Repository) (*git.Rep
// RepositoryFromRequestContextOrOpen opens the repository at the given relative path in the provided request context.
// Caller shouldn't close the git repo manually, the git repo will be automatically closed when the request context is done.
func RepositoryFromRequestContextOrOpen(ctx reqctx.RequestContext, repo Repository) (*git.Repository, error) {
ck := contextKey{uniqueID: repo.GitRepoUniqueID()}
ck := contextKey{key: repo.GitRepoLocation()}
if gitRepo, ok := ctx.Value(ck).(*git.Repository); ok {
return gitRepo, nil
}
gitRepo, err := git.OpenRepository(repoPath(repo))
gitRepo, err := git.OpenRepository(repo)
if err != nil {
return nil, err
}

View File

@@ -7,17 +7,17 @@ import (
"path/filepath"
"testing"
"gitea.dev/models/repo"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/setting"
)
func mockRepository(repoPath string) repo.StorageRepo {
func mockRepository(repoPath string) gitcmd.RepositoryFacade {
if !filepath.IsAbs(repoPath) {
// resolve repository path relative to the unit test fixture directory
repoPath = filepath.Join(setting.GetGiteaTestSourceRoot(), "modules/git/tests/repos", repoPath)
}
return repo.StorageRepo(repoPath)
return gitcmd.RepositoryManaged(repoPath, repoPath)
}
func TestMain(m *testing.M) {

View File

@@ -212,7 +212,7 @@ 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 {
catfileBatch, err := gitrepo.NewBatch(ctx, repo)
catfileBatch, err := git.NewBatch(ctx, repo)
if err != nil {
return err
}

View File

@@ -183,7 +183,7 @@ func (b *Indexer) addDelete(filename string, repo *repo_model.Repository) es.Bul
func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha string, changes *internal.RepoChanges) error {
ops := make([]es.BulkOp, 0)
if len(changes.Updates) > 0 {
batch, err := gitrepo.NewBatch(ctx, repo)
batch, err := git.NewBatch(ctx, repo)
if err != nil {
return err
}

View File

@@ -99,7 +99,7 @@ func AdoptRepository(ctx *context.APIContext) {
ctx.APIErrorInternal(err)
return
}
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName)))
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
if err != nil {
ctx.APIErrorInternal(err)
return
@@ -161,7 +161,7 @@ func DeleteUnadoptedRepository(ctx *context.APIContext) {
ctx.APIErrorInternal(err)
return
}
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName)))
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
if err != nil {
ctx.APIErrorInternal(err)
return

View File

@@ -10,18 +10,15 @@ import (
"gitea.dev/modules/git"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var testReposDir = "tests/repos/"
func TestVerifyCommits(t *testing.T) {
unittest.PrepareTestEnv(t)
gitRepo, err := git.OpenRepository(testReposDir + "repo1_hook_verification")
if err != nil {
defer gitRepo.Close()
}
assert.NoError(t, err)
gitRepo, err := git.OpenRepositoryLocal("tests/repos/repo1_hook_verification")
require.NoError(t, err)
defer gitRepo.Close()
objectFormat, err := gitRepo.GetObjectFormat(t.Context())
assert.NoError(t, err)

View File

@@ -14,6 +14,7 @@ import (
"gitea.dev/models/unit"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/git/gitcmd"
"gitea.dev/modules/log"
"gitea.dev/modules/private"
"gitea.dev/modules/setting"
@@ -318,7 +319,8 @@ func ServCommand(ctx *context.PrivateContext) {
}
}
results.RepoStoragePath = util.Iif(results.IsWiki, repo_model.RelativeWikiPath(repo.OwnerName, repo.Name), repo.GitRepoLocation())
gitRepo := util.Iif(results.IsWiki, repo.WikiStorageRepo(), repo.CodeStorageRepo())
results.RepoStoragePath = gitcmd.RepoLocalPath(gitRepo)
log.Debug("Serv Results: %+v", results)
ctx.JSON(http.StatusOK, results)
// We will update the keys in a different call.

View File

@@ -134,7 +134,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
ctx.ServerError("IsRepositoryExist", err)
return
}
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, repoName)))
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, repoName))
if err != nil {
ctx.ServerError("IsDir", err)
return

View File

@@ -122,7 +122,7 @@ func LFSLocks(ctx *context.Context) {
return
}
gitRepo, err := git.OpenRepository(tmpBasePath)
gitRepo, err := git.OpenRepositoryLocal(tmpBasePath)
if err != nil {
log.Error("Unable to open temporary repository: %s (%v)", tmpBasePath, err)
ctx.ServerError("LFSLocks", fmt.Errorf("failed to open new temporary repository in: %s %w", tmpBasePath, err))

View File

@@ -41,7 +41,7 @@ data 12
err = gitcmd.NewCommand("fast-import").WithDir(repoPath).WithStdinBytes([]byte(stdin)).RunWithStderr(t.Context())
require.NoError(t, err)
gitRepo, err := git.OpenRepository(repoPath)
gitRepo, err := git.OpenRepositoryLocal(repoPath)
require.NoError(t, err)
defer gitRepo.Close()

View File

@@ -32,7 +32,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
return
}
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(repo_model.RelativePath(ctxUser.Name, dir)))
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.CodeRepoByName(ctxUser.Name, dir))
if err != nil {
ctx.ServerError("IsDir", err)
return

View File

@@ -62,7 +62,7 @@ func TestGetActionWorkflow_FallbackRef(t *testing.T) {
repoDir := buildWorkflowTestRepo(t)
gitRepo, err := git.OpenRepository(repoDir)
gitRepo, err := git.OpenRepositoryLocal(repoDir)
require.NoError(t, err)
defer gitRepo.Close()

View File

@@ -11,6 +11,7 @@ import (
"gitea.dev/models/db"
repo_model "gitea.dev/models/repo"
user_model "gitea.dev/models/user"
"gitea.dev/modules/git"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/log"
"gitea.dev/modules/structs"
@@ -162,7 +163,7 @@ func checkCommitGraph(ctx context.Context, logger log.Logger, autofix bool) erro
if !isExist {
numNeedUpdate++
if autofix {
if err := gitrepo.WriteCommitGraph(ctx, repo); err != nil {
if err := git.WriteCommitGraph(ctx, repo); err != nil {
logger.Error("Unable to write commit-graph in %s. Error: %v", repo.FullName(), err)
return err
}

View File

@@ -205,7 +205,7 @@ func TestGitDiffTree(t *testing.T) {
for _, tt := range test {
t.Run(tt.Name, func(t *testing.T) {
gitRepo, err := git.OpenRepository(tt.RepoPath)
gitRepo, err := git.OpenRepositoryLocal(tt.RepoPath)
assert.NoError(t, err)
defer gitRepo.Close()
@@ -414,7 +414,7 @@ func TestGitDiffTreeErrors(t *testing.T) {
for _, tt := range test {
t.Run(tt.Name, func(t *testing.T) {
gitRepo, err := git.OpenRepository(tt.RepoPath)
gitRepo, err := git.OpenRepositoryLocal(tt.RepoPath)
assert.NoError(t, err)
defer gitRepo.Close()

View File

@@ -601,7 +601,7 @@ func TestDiffLine_GetCommentSide(t *testing.T) {
}
func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) {
gitRepo, err := git.OpenRepository("../../modules/git/tests/repos/repo5_pulls")
gitRepo, err := git.OpenRepositoryLocal("../../modules/git/tests/repos/repo5_pulls")
require.NoError(t, err)
defer gitRepo.Close()
@@ -1188,7 +1188,7 @@ D test2.txt
D test10.txt`
require.NoError(t, gitcmd.NewCommand("fast-import").WithDir(pull.BaseRepo.RepoPath()).WithStdinBytes([]byte(stdin)).Run(t.Context()))
gitRepo, err := git.OpenRepository(pull.BaseRepo.RepoPath())
gitRepo, err := git.OpenRepositoryLocal(pull.BaseRepo.RepoPath())
assert.NoError(t, err)
defer gitRepo.Close()

View File

@@ -157,7 +157,9 @@ func (g *RepositoryDumper) CreateRepo(ctx context.Context, repo *base.Repository
if err != nil {
return fmt.Errorf("Clone: %w", err)
}
if err := git.WriteCommitGraph(ctx, repoPath); err != nil {
repoLocal := gitcmd.RepositoryUnmanaged(repoPath)
if err := git.WriteCommitGraph(ctx, repoLocal); err != nil {
return err
}
@@ -168,7 +170,7 @@ func (g *RepositoryDumper) CreateRepo(ctx context.Context, repo *base.Repository
if err := os.MkdirAll(wikiPath, os.ModePerm); err != nil {
return fmt.Errorf("Failed to remove %s: %w", wikiPath, err)
}
wikiLocal := gitcmd.RepositoryUnmanaged(wikiPath)
if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{
Mirror: true,
Quiet: true,
@@ -180,13 +182,13 @@ func (g *RepositoryDumper) CreateRepo(ctx context.Context, repo *base.Repository
if err := os.RemoveAll(wikiPath); err != nil {
return fmt.Errorf("Failed to remove %s: %w", wikiPath, err)
}
} else if err := git.WriteCommitGraph(ctx, wikiPath); err != nil {
} else if err := git.WriteCommitGraph(ctx, wikiLocal); err != nil {
return err
}
}
}
g.gitRepo, err = git.OpenRepository(g.gitPath())
g.gitRepo, err = git.OpenRepositoryLocal(g.gitPath())
return err
}

View File

@@ -172,7 +172,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*repo_module.SyncResu
return nil, false
}
}
if err := gitrepo.WriteCommitGraph(ctx, m.Repo); err != nil {
if err := git.WriteCommitGraph(ctx, m.Repo); err != nil {
log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err)
}
@@ -253,7 +253,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*repo_module.SyncResu
return nil, false
}
if err := gitrepo.WriteCommitGraph(ctx, m.Repo.WikiStorageRepo()); err != nil {
if err := git.WriteCommitGraph(ctx, m.Repo.WikiStorageRepo()); err != nil {
log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err)
}
}

View File

@@ -102,7 +102,7 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque
mergeCtx.sig = doer.NewGitSig()
mergeCtx.committer = mergeCtx.sig
gitRepo, err := git.OpenRepository(mergeCtx.tmpBasePath)
gitRepo, err := git.OpenRepositoryLocal(mergeCtx.tmpBasePath)
if err != nil {
defer cancel()
return nil, nil, fmt.Errorf("failed to open temp git repo for pr[%d]: %w", mergeCtx.pr.ID, err)

View File

@@ -25,7 +25,7 @@ func getAuthorSignatureSquash(ctx *mergeContext) (*git.Signature, error) {
// Try to get a signature from the same user in one of the commits, as the
// poster email might be private or commits might have a different signature
// than the primary email address of the poster.
gitRepo, err := git.OpenRepository(ctx.tmpBasePath)
gitRepo, err := git.OpenRepositoryLocal(ctx.tmpBasePath)
if err != nil {
log.Error("%-v Unable to open base repository: %v", ctx.pr, err)
return nil, err

View File

@@ -74,7 +74,7 @@ func checkPullRequestMergeableByTmpRepo(ctx context.Context, pr *issues_model.Pu
}
defer cancel()
gitRepo, err := git.OpenRepository(prCtx.tmpBasePath)
gitRepo, err := git.OpenRepositoryLocal(prCtx.tmpBasePath)
if err != nil {
return fmt.Errorf("OpenRepository: %w", err)
}

View File

@@ -213,10 +213,10 @@ func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, re
return err
}
relativePath := repo_model.RelativePath(u.Name, repoName)
exist, err := gitrepo.IsRepositoryExist(ctx, repo_model.StorageRepo(relativePath))
codeRepo := repo_model.CodeRepoByName(u.Name, repoName)
exist, err := gitrepo.IsRepositoryExist(ctx, codeRepo)
if err != nil {
log.Error("Unable to check if %s exists. Error: %v", relativePath, err)
log.Error("Unable to check if repo %s/%s exists. Error: %v", u.Name, repoName, err)
return err
}
if !exist {
@@ -235,7 +235,7 @@ func DeleteUnadoptedRepository(ctx context.Context, doer, u *user_model.User, re
}
}
return gitrepo.DeleteRepository(ctx, repo_model.StorageRepo(relativePath))
return gitrepo.DeleteRepository(ctx, codeRepo)
}
type unadoptedRepositories struct {

View File

@@ -79,7 +79,7 @@ func (t *TemporaryUploadRepository) Clone(ctx context.Context, branch string, ba
}
return fmt.Errorf("Clone: %w %s", err, stderr)
}
gitRepo, err := git.OpenRepository(t.basePath)
gitRepo, err := git.OpenRepositoryLocal(t.basePath)
if err != nil {
return err
}
@@ -92,7 +92,7 @@ func (t *TemporaryUploadRepository) Init(ctx context.Context, objectFormatName s
if err := git.InitRepository(ctx, t.basePath, false, objectFormatName); err != nil {
return err
}
gitRepo, err := git.OpenRepository(t.basePath)
gitRepo, err := git.OpenRepositoryLocal(t.basePath)
if err != nil {
return err
}

View File

@@ -16,7 +16,7 @@ import (
)
func BenchmarkGetCommitGraph(b *testing.B) {
currentRepo, err := git.OpenRepository(".")
currentRepo, err := git.OpenRepositoryLocal(".")
if err != nil || currentRepo == nil {
b.Error("Could not open repository")
}

View File

@@ -55,7 +55,7 @@ func cloneWiki(ctx context.Context, repo *repo_model.Repository, opts migration.
return "", err
}
if err := gitrepo.WriteCommitGraph(ctx, storageRepo); err != nil {
if err := git.WriteCommitGraph(ctx, storageRepo); err != nil {
cleanIncompleteWikiPath()
return "", err
}
@@ -102,7 +102,7 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
return repo, fmt.Errorf("clone error: %w", err)
}
if err := gitrepo.WriteCommitGraph(ctx, repo); err != nil {
if err := git.WriteCommitGraph(ctx, repo); err != nil {
return repo, err
}

View File

@@ -331,7 +331,7 @@ func CheckCreateRepository(ctx context.Context, doer, owner *user_model.User, na
} else if has {
return repo_model.ErrRepoAlreadyExist{Uname: owner.Name, Name: name}
}
repo := repo_model.StorageRepo(repo_model.RelativePath(owner.Name, name))
repo := repo_model.CodeRepoByName(owner.Name, name)
isExist, err := gitrepo.IsRepositoryExist(ctx, repo)
if err != nil {
log.Error("Unable to check if repo %s/%s exists, error: %v", owner.Name, name, err)

View File

@@ -94,7 +94,7 @@ func isRepositoryModelOrDirExist(ctx context.Context, u *user_model.User, repoNa
if err != nil {
return false, err
}
repo := repo_model.StorageRepo(repo_model.RelativePath(u.Name, repoName))
repo := repo_model.CodeRepoByName(u.Name, repoName)
isExist, err := gitrepo.IsRepositoryExist(ctx, repo)
return has || isExist, err
}
@@ -116,18 +116,19 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
}
if repoRenamed {
oldRelativePath, newRelativePath := repo_model.RelativePath(newOwnerName, repo.Name), repo_model.RelativePath(oldOwnerName, repo.Name)
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
log.Error("Unable to move repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
oldRelativePath, newRelativePath, err)
// revert the rename
from := repo_model.CodeRepoByName(newOwnerName, repo.Name)
to := repo_model.CodeRepoByName(oldOwnerName, repo.Name)
if err := gitrepo.RenameRepository(ctx, from, to); err != nil {
log.Error("Unable to revert repository %s/%s to %s/%s: %v", newOwnerName, repo.Name, oldOwnerName, repo.Name, err)
}
}
if wikiRenamed {
oldRelativePath, newRelativePath := repo_model.RelativeWikiPath(newOwnerName, repo.Name), repo_model.RelativeWikiPath(oldOwnerName, repo.Name)
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
log.Error("Unable to move wiki for repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name,
oldRelativePath, newRelativePath, err)
from := repo_model.WikiRepoByName(newOwnerName, repo.Name)
to := repo_model.WikiRepoByName(oldOwnerName, repo.Name)
if err := gitrepo.RenameRepository(ctx, from, to); err != nil {
log.Error("Unable to revert wiki repository %s/%s to %s/%s: %v", newOwnerName, repo.Name, oldOwnerName, repo.Name, err)
}
}
@@ -302,19 +303,21 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName
}
// Rename remote repository to new path and delete local copy.
oldRelativePath, newRelativePath := repo_model.RelativePath(oldOwner.Name, repo.Name), repo_model.RelativePath(newOwner.Name, repo.Name)
if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil {
oldCodeRepo := repo_model.CodeRepoByName(oldOwner.Name, repo.Name)
newCodeRepo := repo_model.CodeRepoByName(newOwner.Name, repo.Name)
if err := gitrepo.RenameRepository(ctx, oldCodeRepo, newCodeRepo); err != nil {
return fmt.Errorf("rename repository directory: %w", err)
}
repoRenamed = true
// Rename remote wiki repository to new path and delete local copy.
wikiStorageRepo := repo_model.StorageRepo(repo_model.RelativeWikiPath(oldOwner.Name, repo.Name))
if isExist, err := gitrepo.IsRepositoryExist(ctx, wikiStorageRepo); err != nil {
oldWikiRepo := repo_model.WikiRepoByName(oldOwner.Name, repo.Name)
if isExist, err := gitrepo.IsRepositoryExist(ctx, oldWikiRepo); err != nil {
log.Error("Unable to check if wiki of repo %s/%s exists. Error: %v", oldOwner.Name, repo.Name, err)
return err
} else if isExist {
if err := gitrepo.RenameRepository(ctx, wikiStorageRepo, repo_model.StorageRepo(repo_model.RelativeWikiPath(newOwner.Name, repo.Name))); err != nil {
newWikiRepo := repo_model.WikiRepoByName(newOwner.Name, repo.Name)
if err := gitrepo.RenameRepository(ctx, oldWikiRepo, newWikiRepo); err != nil {
return fmt.Errorf("rename repository wiki: %w", err)
}
wikiRenamed = true
@@ -373,14 +376,14 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR
}
}
if err = gitrepo.RenameRepository(ctx, repo,
repo_model.StorageRepo(repo_model.RelativePath(repo.OwnerName, newRepoName))); err != nil {
newCodeRepo := repo_model.CodeRepoByName(repo.OwnerName, newRepoName)
if err = gitrepo.RenameRepository(ctx, repo, newCodeRepo); err != nil {
return fmt.Errorf("rename repository directory: %w", err)
}
if HasWiki(ctx, repo) {
if err = gitrepo.RenameRepository(ctx, repo.WikiStorageRepo(), repo_model.StorageRepo(
repo_model.RelativeWikiPath(repo.OwnerName, newRepoName))); err != nil {
newWikiRepo := repo_model.WikiRepoByName(repo.OwnerName, newRepoName)
if err = gitrepo.RenameRepository(ctx, repo.WikiStorageRepo(), newWikiRepo); err != nil {
return fmt.Errorf("rename repository wiki: %w", err)
}
}

View File

@@ -123,7 +123,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
return fmt.Errorf("failed to clone repository: %s (%w)", repo.FullName(), err)
}
gitRepo, err := git.OpenRepository(basePath)
gitRepo, err := git.OpenRepositoryLocal(basePath)
if err != nil {
log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("failed to open new temporary repository in: %s %w", basePath, err)
@@ -282,7 +282,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
return fmt.Errorf("failed to clone repository: %s (%w)", repo.FullName(), err)
}
gitRepo, err := git.OpenRepository(basePath)
gitRepo, err := git.OpenRepositoryLocal(basePath)
if err != nil {
log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("failed to open new temporary repository in: %s %w", basePath, err)

View File

@@ -305,7 +305,7 @@ func TestPrepareWikiFileName_FirstPage(t *testing.T) {
err := git.InitRepository(t.Context(), tmpDir, true, git.Sha1ObjectFormat.Name())
assert.NoError(t, err)
gitRepo, err := git.OpenRepository(tmpDir)
gitRepo, err := git.OpenRepositoryLocal(tmpDir)
require.NoError(t, err)
defer gitRepo.Close()

View File

@@ -1,7 +0,0 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true

View File

@@ -1,2 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491734 +0100 commit (initial): Initial commit
cdaca8cf1d36e1e4e508a940f6e157e239beccfa cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491742 +0100 checkout: moving from master to branch1

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491742 +0100 branch: Created from cdaca8cf1d36e1e4e508a940f6e157e239beccfa

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491734 +0100 commit (initial): Initial commit

View File

@@ -1,7 +0,0 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true

View File

@@ -1,2 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491734 +0100 commit (initial): Initial commit
cdaca8cf1d36e1e4e508a940f6e157e239beccfa cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491742 +0100 checkout: moving from master to branch1

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491742 +0100 branch: Created from cdaca8cf1d36e1e4e508a940f6e157e239beccfa

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491734 +0100 commit (initial): Initial commit

View File

@@ -1,7 +0,0 @@
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true

View File

@@ -1,2 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491734 +0100 commit (initial): Initial commit
cdaca8cf1d36e1e4e508a940f6e157e239beccfa cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491742 +0100 checkout: moving from master to branch1

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491742 +0100 branch: Created from cdaca8cf1d36e1e4e508a940f6e157e239beccfa

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 cdaca8cf1d36e1e4e508a940f6e157e239beccfa user2 <user2@example.com> 1575491734 +0100 commit (initial): Initial commit

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 cbff181af4c9c7fee3cf6c106699e07d9a3f54e6 Gitea <gitea@fake.local> 1688672318 +0200

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 1978192d98bb1b65e11c2cf37da854fbf94bffd6 Gitea <gitea@fake.local> 1688672383 +0200 push

View File

@@ -1 +0,0 @@
0000000000000000000000000000000000000000 cbff181af4c9c7fee3cf6c106699e07d9a3f54e6 root <sauer.sebastian@gmail.com> 1688672317 +0200 push

View File

@@ -811,7 +811,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string
return
}
gitRepo, err := git.OpenRepository(dstPath)
gitRepo, err := git.OpenRepositoryLocal(dstPath)
require.NoError(t, err)
defer gitRepo.Close()

View File

@@ -87,7 +87,7 @@ func TestAgitPullPush(t *testing.T) {
dstPath := t.TempDir()
doGitClone(dstPath, u)(t)
gitRepo, err := git.OpenRepository(dstPath)
gitRepo, err := git.OpenRepositoryLocal(dstPath)
assert.NoError(t, err)
defer gitRepo.Close()
@@ -150,7 +150,7 @@ func TestAgitReviewStaleness(t *testing.T) {
dstPath := t.TempDir()
doGitClone(dstPath, u)(t)
gitRepo, err := git.OpenRepository(dstPath)
gitRepo, err := git.OpenRepositoryLocal(dstPath)
assert.NoError(t, err)
defer gitRepo.Close()

View File

@@ -205,7 +205,7 @@ func runTestGitPush(t *testing.T, u *url.URL, gitOperation func(t *testing.T, gi
doGitAddRemote(gitPath, "origin", u)(t)
gitRepo, err := git.OpenRepository(gitPath)
gitRepo, err := git.OpenRepositoryLocal(gitPath)
require.NoError(t, err)
defer gitRepo.Close()