Skip to content

Commit 5f82ead

Browse files
lunnydelvh
andauthored
Simplify how git repositories are opened (#28937)
## Purpose This is a refactor toward building an abstraction over managing git repositories. Afterwards, it does not matter anymore if they are stored on the local disk or somewhere remote. ## What this PR changes We used `git.OpenRepository` everywhere previously. Now, we should split them into two distinct functions: Firstly, there are temporary repositories which do not change: ```go git.OpenRepository(ctx, diskPath) ``` Gitea managed repositories having a record in the database in the `repository` table are moved into the new package `gitrepo`: ```go gitrepo.OpenRepository(ctx, repo_model.Repo) ``` Why is `repo_model.Repository` the second parameter instead of file path? Because then we can easily adapt our repository storage strategy. The repositories can be stored locally, however, they could just as well be stored on a remote server. ## Further changes in other PRs - A Git Command wrapper on package `gitrepo` could be created. i.e. `NewCommand(ctx, repo_model.Repository, commands...)`. `git.RunOpts{Dir: repo.RepoPath()}`, the directory should be empty before invoking this method and it can be filled in the function only. #28940 - Remove the `RepoPath()`/`WikiPath()` functions to reduce the possibility of mistakes. --------- Co-authored-by: delvh <[email protected]>
1 parent 60e4a98 commit 5f82ead

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+426
-273
lines changed

cmd/admin.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"code.gitea.io/gitea/models/db"
1212
repo_model "code.gitea.io/gitea/models/repo"
1313
"code.gitea.io/gitea/modules/git"
14+
"code.gitea.io/gitea/modules/gitrepo"
1415
"code.gitea.io/gitea/modules/log"
1516
repo_module "code.gitea.io/gitea/modules/repository"
1617

@@ -122,7 +123,7 @@ func runRepoSyncReleases(_ *cli.Context) error {
122123
log.Trace("Processing next %d repos of %d", len(repos), count)
123124
for _, repo := range repos {
124125
log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath())
125-
gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())
126+
gitRepo, err := gitrepo.OpenRepository(ctx, repo)
126127
if err != nil {
127128
log.Warn("OpenRepository: %v", err)
128129
continue

models/activities/repo_activity.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
repo_model "code.gitea.io/gitea/models/repo"
1515
user_model "code.gitea.io/gitea/models/user"
1616
"code.gitea.io/gitea/modules/git"
17+
"code.gitea.io/gitea/modules/gitrepo"
1718

1819
"xorm.io/xorm"
1920
)
@@ -65,7 +66,7 @@ func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom
6566
return nil, fmt.Errorf("FillUnresolvedIssues: %w", err)
6667
}
6768
if code {
68-
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath())
69+
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
6970
if err != nil {
7071
return nil, fmt.Errorf("OpenRepository: %w", err)
7172
}
@@ -82,7 +83,7 @@ func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom
8283

8384
// GetActivityStatsTopAuthors returns top author stats for git commits for all branches
8485
func GetActivityStatsTopAuthors(ctx context.Context, repo *repo_model.Repository, timeFrom time.Time, count int) ([]*ActivityAuthorData, error) {
85-
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath())
86+
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo)
8687
if err != nil {
8788
return nil, fmt.Errorf("OpenRepository: %w", err)
8889
}

models/issues/comment.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
repo_model "code.gitea.io/gitea/models/repo"
1919
user_model "code.gitea.io/gitea/models/user"
2020
"code.gitea.io/gitea/modules/container"
21-
"code.gitea.io/gitea/modules/git"
21+
"code.gitea.io/gitea/modules/gitrepo"
2222
"code.gitea.io/gitea/modules/json"
2323
"code.gitea.io/gitea/modules/log"
2424
"code.gitea.io/gitea/modules/references"
@@ -762,8 +762,7 @@ func (c *Comment) LoadPushCommits(ctx context.Context) (err error) {
762762
c.OldCommit = data.CommitIDs[0]
763763
c.NewCommit = data.CommitIDs[1]
764764
} else {
765-
repoPath := c.Issue.Repo.RepoPath()
766-
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath)
765+
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, c.Issue.Repo)
767766
if err != nil {
768767
return err
769768
}

models/issues/pull.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
repo_model "code.gitea.io/gitea/models/repo"
2020
user_model "code.gitea.io/gitea/models/user"
2121
"code.gitea.io/gitea/modules/git"
22+
"code.gitea.io/gitea/modules/gitrepo"
2223
"code.gitea.io/gitea/modules/log"
2324
"code.gitea.io/gitea/modules/setting"
2425
"code.gitea.io/gitea/modules/timeutil"
@@ -865,7 +866,7 @@ func PullRequestCodeOwnersReview(ctx context.Context, pull *Issue, pr *PullReque
865866
return err
866867
}
867868

868-
repo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath())
869+
repo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo)
869870
if err != nil {
870871
return err
871872
}

models/repo/repo.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,14 @@ func init() {
196196
db.RegisterModel(new(Repository))
197197
}
198198

199+
func (repo *Repository) GetName() string {
200+
return repo.Name
201+
}
202+
203+
func (repo *Repository) GetOwnerName() string {
204+
return repo.OwnerName
205+
}
206+
199207
// SanitizedOriginalURL returns a sanitized OriginalURL
200208
func (repo *Repository) SanitizedOriginalURL() string {
201209
if repo.OriginalURL == "" {

modules/context/api.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import (
1111
"net/url"
1212
"strings"
1313

14-
repo_model "code.gitea.io/gitea/models/repo"
1514
"code.gitea.io/gitea/models/unit"
1615
user_model "code.gitea.io/gitea/models/user"
1716
mc "code.gitea.io/gitea/modules/cache"
1817
"code.gitea.io/gitea/modules/git"
18+
"code.gitea.io/gitea/modules/gitrepo"
1919
"code.gitea.io/gitea/modules/httpcache"
2020
"code.gitea.io/gitea/modules/log"
2121
"code.gitea.io/gitea/modules/setting"
@@ -224,7 +224,7 @@ func APIContexter() func(http.Handler) http.Handler {
224224
defer baseCleanUp()
225225

226226
ctx.Base.AppendContextValue(apiContextKey, ctx)
227-
ctx.Base.AppendContextValueFunc(git.RepositoryContextKey, func() any { return ctx.Repo.GitRepo })
227+
ctx.Base.AppendContextValueFunc(gitrepo.RepositoryContextKey, func() any { return ctx.Repo.GitRepo })
228228

229229
// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
230230
if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
@@ -278,10 +278,9 @@ func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context
278278

279279
// For API calls.
280280
if ctx.Repo.GitRepo == nil {
281-
repoPath := repo_model.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
282-
gitRepo, err := git.OpenRepository(ctx, repoPath)
281+
gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
283282
if err != nil {
284-
ctx.Error(http.StatusInternalServerError, "RepoRef Invalid repo "+repoPath, err)
283+
ctx.Error(http.StatusInternalServerError, fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err)
285284
return cancel
286285
}
287286
ctx.Repo.GitRepo = gitRepo

modules/context/context.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
"code.gitea.io/gitea/models/unit"
1818
user_model "code.gitea.io/gitea/models/user"
1919
mc "code.gitea.io/gitea/modules/cache"
20-
"code.gitea.io/gitea/modules/git"
20+
"code.gitea.io/gitea/modules/gitrepo"
2121
"code.gitea.io/gitea/modules/httpcache"
2222
"code.gitea.io/gitea/modules/setting"
2323
"code.gitea.io/gitea/modules/templates"
@@ -163,7 +163,7 @@ func Contexter() func(next http.Handler) http.Handler {
163163
ctx.Data["PageData"] = ctx.PageData
164164

165165
ctx.Base.AppendContextValue(WebContextKey, ctx)
166-
ctx.Base.AppendContextValueFunc(git.RepositoryContextKey, func() any { return ctx.Repo.GitRepo })
166+
ctx.Base.AppendContextValueFunc(gitrepo.RepositoryContextKey, func() any { return ctx.Repo.GitRepo })
167167

168168
ctx.Csrf = PrepareCSRFProtector(csrfOpts, ctx)
169169

modules/context/repo.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
user_model "code.gitea.io/gitea/models/user"
2424
"code.gitea.io/gitea/modules/cache"
2525
"code.gitea.io/gitea/modules/git"
26+
"code.gitea.io/gitea/modules/gitrepo"
2627
code_indexer "code.gitea.io/gitea/modules/indexer/code"
2728
"code.gitea.io/gitea/modules/log"
2829
repo_module "code.gitea.io/gitea/modules/repository"
@@ -633,7 +634,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
633634
return nil
634635
}
635636

636-
gitRepo, err := git.OpenRepository(ctx, repo_model.RepoPath(userName, repoName))
637+
gitRepo, err := gitrepo.OpenRepository(ctx, repo)
637638
if err != nil {
638639
if strings.Contains(err.Error(), "repository does not exist") || strings.Contains(err.Error(), "no such file or directory") {
639640
log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err)
@@ -645,7 +646,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
645646
}
646647
return nil
647648
}
648-
ctx.ServerError("RepoAssignment Invalid repo "+repo_model.RepoPath(userName, repoName), err)
649+
ctx.ServerError("RepoAssignment Invalid repo "+repo.FullName(), err)
649650
return nil
650651
}
651652
if ctx.Repo.GitRepo != nil {
@@ -920,10 +921,9 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
920921
)
921922

922923
if ctx.Repo.GitRepo == nil {
923-
repoPath := repo_model.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
924-
ctx.Repo.GitRepo, err = git.OpenRepository(ctx, repoPath)
924+
ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
925925
if err != nil {
926-
ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
926+
ctx.ServerError(fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err)
927927
return nil
928928
}
929929
// We opened it, we should close it

modules/contexttest/context_tests.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
"code.gitea.io/gitea/models/unittest"
1919
user_model "code.gitea.io/gitea/models/user"
2020
"code.gitea.io/gitea/modules/context"
21-
"code.gitea.io/gitea/modules/git"
21+
"code.gitea.io/gitea/modules/gitrepo"
2222
"code.gitea.io/gitea/modules/templates"
2323
"code.gitea.io/gitea/modules/translation"
2424
"code.gitea.io/gitea/modules/web/middleware"
@@ -107,7 +107,7 @@ func LoadRepoCommit(t *testing.T, ctx gocontext.Context) {
107107
assert.FailNow(t, "context is not *context.Context or *context.APIContext")
108108
}
109109

110-
gitRepo, err := git.OpenRepository(ctx, repo.Repository.RepoPath())
110+
gitRepo, err := gitrepo.OpenRepository(ctx, repo.Repository)
111111
assert.NoError(t, err)
112112
defer gitRepo.Close()
113113
branch, err := gitRepo.GetHEADBranch()
@@ -137,7 +137,7 @@ func LoadUser(t *testing.T, ctx gocontext.Context, userID int64) {
137137
func LoadGitRepo(t *testing.T, ctx *context.Context) {
138138
assert.NoError(t, ctx.Repo.Repository.LoadOwner(ctx))
139139
var err error
140-
ctx.Repo.GitRepo, err = git.OpenRepository(ctx, ctx.Repo.Repository.RepoPath())
140+
ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository)
141141
assert.NoError(t, err)
142142
}
143143

modules/git/repo_base.go

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,4 @@
33

44
package git
55

6-
import (
7-
"context"
8-
"io"
9-
)
10-
116
var isGogit bool
12-
13-
// contextKey is a value for use with context.WithValue.
14-
type contextKey struct {
15-
name string
16-
}
17-
18-
// RepositoryContextKey is a context key. It is used with context.Value() to get the current Repository for the context
19-
var RepositoryContextKey = &contextKey{"repository"}
20-
21-
// RepositoryFromContext attempts to get the repository from the context
22-
func RepositoryFromContext(ctx context.Context, path string) *Repository {
23-
value := ctx.Value(RepositoryContextKey)
24-
if value == nil {
25-
return nil
26-
}
27-
28-
if repo, ok := value.(*Repository); ok && repo != nil {
29-
if repo.Path == path {
30-
return repo
31-
}
32-
}
33-
34-
return nil
35-
}
36-
37-
type nopCloser func()
38-
39-
func (nopCloser) Close() error { return nil }
40-
41-
// RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it
42-
func RepositoryFromContextOrOpen(ctx context.Context, path string) (*Repository, io.Closer, error) {
43-
gitRepo := RepositoryFromContext(ctx, path)
44-
if gitRepo != nil {
45-
return gitRepo, nopCloser(nil), nil
46-
}
47-
48-
gitRepo, err := OpenRepository(ctx, path)
49-
return gitRepo, gitRepo, err
50-
}

modules/git/repo_branch.go

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -86,29 +86,6 @@ func (repo *Repository) GetBranch(branch string) (*Branch, error) {
8686
}, nil
8787
}
8888

89-
// GetBranchesByPath returns a branch by it's path
90-
// if limit = 0 it will not limit
91-
func GetBranchesByPath(ctx context.Context, path string, skip, limit int) ([]*Branch, int, error) {
92-
gitRepo, err := OpenRepository(ctx, path)
93-
if err != nil {
94-
return nil, 0, err
95-
}
96-
defer gitRepo.Close()
97-
98-
return gitRepo.GetBranches(skip, limit)
99-
}
100-
101-
// GetBranchCommitID returns a branch commit ID by its name
102-
func GetBranchCommitID(ctx context.Context, path, branch string) (string, error) {
103-
gitRepo, err := OpenRepository(ctx, path)
104-
if err != nil {
105-
return "", err
106-
}
107-
defer gitRepo.Close()
108-
109-
return gitRepo.GetBranchCommitID(branch)
110-
}
111-
11289
// GetBranches returns a slice of *git.Branch
11390
func (repo *Repository) GetBranches(skip, limit int) ([]*Branch, int, error) {
11491
brs, countAll, err := repo.GetBranchNames(skip, limit)

modules/git/repo_branch_gogit.go

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
package git
88

99
import (
10-
"context"
1110
"sort"
1211
"strings"
1312

@@ -95,34 +94,6 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
9594
return branchNames, len(branchData), nil
9695
}
9796

98-
// WalkReferences walks all the references from the repository
99-
// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.
100-
func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) {
101-
repo := RepositoryFromContext(ctx, repoPath)
102-
if repo == nil {
103-
var err error
104-
repo, err = OpenRepository(ctx, repoPath)
105-
if err != nil {
106-
return 0, err
107-
}
108-
defer repo.Close()
109-
}
110-
111-
i := 0
112-
iter, err := repo.gogitRepo.References()
113-
if err != nil {
114-
return i, err
115-
}
116-
defer iter.Close()
117-
118-
err = iter.ForEach(func(ref *plumbing.Reference) error {
119-
err := walkfn(ref.Hash().String(), string(ref.Name()))
120-
i++
121-
return err
122-
})
123-
return i, err
124-
}
125-
12697
// WalkReferences walks all the references from the repository
12798
func (repo *Repository) WalkReferences(arg ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
12899
i := 0

modules/git/repo_branch_nogogit.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,6 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
6565
return callShowRef(repo.Ctx, repo.Path, BranchPrefix, TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit)
6666
}
6767

68-
// WalkReferences walks all the references from the repository
69-
func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) {
70-
return walkShowRef(ctx, repoPath, nil, 0, 0, walkfn)
71-
}
72-
7368
// WalkReferences walks all the references from the repository
7469
// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.
7570
func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
@@ -81,12 +76,12 @@ func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walk
8176
args = TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}
8277
}
8378

84-
return walkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn)
79+
return WalkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn)
8580
}
8681

8782
// callShowRef return refs, if limit = 0 it will not limit
8883
func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) {
89-
countAll, err = walkShowRef(ctx, repoPath, extraArgs, skip, limit, func(_, branchName string) error {
84+
countAll, err = WalkShowRef(ctx, repoPath, extraArgs, skip, limit, func(_, branchName string) error {
9085
branchName = strings.TrimPrefix(branchName, trimPrefix)
9186
branchNames = append(branchNames, branchName)
9287

@@ -95,7 +90,7 @@ func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs Tru
9590
return branchNames, countAll, err
9691
}
9792

98-
func walkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
93+
func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
9994
stdoutReader, stdoutWriter := io.Pipe()
10095
defer func() {
10196
_ = stdoutReader.Close()
@@ -189,7 +184,7 @@ func walkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs,
189184
// GetRefsBySha returns all references filtered with prefix that belong to a sha commit hash
190185
func (repo *Repository) GetRefsBySha(sha, prefix string) ([]string, error) {
191186
var revList []string
192-
_, err := walkShowRef(repo.Ctx, repo.Path, nil, 0, 0, func(walkSha, refname string) error {
187+
_, err := WalkShowRef(repo.Ctx, repo.Path, nil, 0, 0, func(walkSha, refname string) error {
193188
if walkSha == sha && strings.HasPrefix(refname, prefix) {
194189
revList = append(revList, refname)
195190
}

0 commit comments

Comments
 (0)