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())
}