refactor: remove Path field from git.Repository (#38552)

The "path" details should be hidden to other packages

By the way, fix a resource leaking in gogit's CommitNodeIndex
(the file was not closed in CacheCommit)
This commit is contained in:
wxiaoguang
2026-07-21 02:03:28 +08:00
committed by GitHub
parent 9dc04289aa
commit a4526d5a82
28 changed files with 146 additions and 107 deletions

View File

@@ -205,6 +205,8 @@ func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
}
type runOpts struct {
// TODO: this struct should be removed, the fields can be just merged into the command
Env []string
Timeout time.Duration
@@ -213,7 +215,7 @@ type runOpts struct {
// * /some/path/.git
// * /some/path/.git/gitea-data/data/repositories/user/repo.git
// If "user/repo.git" is invalid/broken, then running git command in it will use "/some/path/.git", and produce unexpected results
// The correct approach is to use `--git-dir" global argument
// The correct approach is to use `--git-dir" global argument or "GIT_DIR=..." environment variable.
Dir string
PipelineFunc func(Context) error

View File

@@ -5,6 +5,7 @@ package gitcmd
import (
"path/filepath"
"sync/atomic"
"gitea.dev/modules/setting"
)
@@ -19,6 +20,8 @@ type RepositoryFacade interface {
// * absolute path: will be used as-is
// * in the future: maybe URI for more flexible definitions
GitRepoLocation() string
LogString() string
}
func (c *Command) WithRepo(repo RepositoryFacade) *Command {
@@ -26,31 +29,69 @@ func (c *Command) WithRepo(repo RepositoryFacade) *Command {
return c
}
// RepoLocalPath returns an absolute path for a RepositoryFacade.
// TODO: most of the calls to this function should be replaced with a "Repo FS" in the future
// to handle file accesses in the git repo (e.g.: read, write, list, remove).
func RepoLocalPath(repo RepositoryFacade) string {
repoLoc := repo.GitRepoLocation()
if filepath.IsAbs(repoLoc) {
return repoLoc
}
return filepath.Join(setting.RepoRootPath, filepath.FromSlash(repoLoc))
if setting.RepoRootPath == "" {
panic("repo root path is not initialized")
}
// the repo root path and the repo loc should all have been cleaned, so we can safely join them together
return setting.RepoRootPath + string(filepath.Separator) + filepath.FromSlash(repoLoc)
}
type repositoryUnmanaged string
func repoLogNameByLocation(loc string) string {
t := filepath.FromSlash(loc)
// hide the parent paths, then the name should be safe for end users
return ".../" + filepath.Base(filepath.Dir(t)) + "/" + filepath.Base(t)
}
func (r repositoryUnmanaged) GitRepoManagedID() string {
type repositoryUnmanaged struct {
loc string
logName atomic.Pointer[string]
}
func (r *repositoryUnmanaged) LogString() string {
s := r.logName.Load()
if s == nil {
s = new(repoLogNameByLocation(r.loc))
r.logName.Store(s)
}
return *s
}
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 (r *repositoryUnmanaged) GitRepoLocation() string {
return r.loc
}
// RepositoryUnmanaged returns a RepositoryFacade for a repository that might not be managed by Gitea.
// If the path is not absolute, then it is relative to setting.RepoRootPath
// This function is mainly for maintaining the owner's repo when the repo is not managed yet.
// e.g.: init, clone, transfer, rename, adopt, etc., and temp repo creation and modification.
func RepositoryUnmanaged(s string) RepositoryFacade {
return repositoryUnmanaged(s)
return &repositoryUnmanaged{loc: filepath.Clean(s)}
}
type repositoryManaged struct {
id string
loc string
id, loc string
logName atomic.Pointer[string]
}
func (r *repositoryManaged) LogString() string {
s := r.logName.Load()
if s == nil {
s = new(repoLogNameByLocation(r.loc))
r.logName.Store(s)
}
return *s
}
func (r *repositoryManaged) GitRepoManagedID() string {
@@ -62,5 +103,5 @@ func (r *repositoryManaged) GitRepoLocation() string {
}
func RepositoryManaged(id, loc string) RepositoryFacade {
return &repositoryManaged{id, loc}
return &repositoryManaged{id: id, loc: filepath.Clean(loc)}
}