History

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. ---------

Lunny Xiao committed 2 years ago

Commit 5f82ead1 parent 60e4a9884 files · +426 −273Browse files

Showing the changes to modules/git (4 of 84 files). Show all

Unified · Split

4 files
  1. modules/git/repo_base.go +0 −44
  2. modules/git/repo_branch.go +0 −23
  3. modules/git/repo_branch_gogit.go +0 −29
  4. modules/git/repo_branch_nogogit.go +4 −9
modules/git/repo_base.go+0−44
@@ -3,48 +3,4 @@ · 2 unmodified lines
3 3
4package git4package git
5 5
6import (
7 "context"
8 "io"
9)
10
11var isGogit bool6var isGogit bool
12
13// contextKey is a value for use with context.WithValue.
14type 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
19var RepositoryContextKey = &contextKey{"repository"}
20
21// RepositoryFromContext attempts to get the repository from the context
22func 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
37type nopCloser func()
38
39func (nopCloser) Close() error { return nil }
40
41// RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it
42func 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+0−23
@@ -86,29 +86,6 @@ func (repo *Repository) GetBranch(branch string) (*Branch, error) { · 85 unmodified lines
86 }, nil86 }, nil
87}87}
88 88
89// GetBranchesByPath returns a branch by it's path
90// if limit = 0 it will not limit
91func 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
102func 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
112// GetBranches returns a slice of *git.Branch89// GetBranches returns a slice of *git.Branch
113func (repo *Repository) GetBranches(skip, limit int) ([]*Branch, int, error) {90func (repo *Repository) GetBranches(skip, limit int) ([]*Branch, int, error) {
114 brs, countAll, err := repo.GetBranchNames(skip, limit)91 brs, countAll, err := repo.GetBranchNames(skip, limit)
modules/git/repo_branch_gogit.go+0−29
@@ -7,7 +7,6 @@ · 6 unmodified lines
7package git7package git
8 8
9import (9import (
10 "context"
11 "sort"10 "sort"
12 "strings"11 "strings"
13 12
@@ -95,34 +94,6 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) { · 81 unmodified lines
95 return branchNames, len(branchData), nil94 return branchNames, len(branchData), nil
96}95}
97 96
98// WalkReferences walks all the references from the repository
99// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.
100func 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
126// WalkReferences walks all the references from the repository97// WalkReferences walks all the references from the repository
127func (repo *Repository) WalkReferences(arg ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {98func (repo *Repository) WalkReferences(arg ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
128 i := 099 i := 0
modules/git/repo_branch_nogogit.go+4−9
@@ -65,11 +65,6 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) { · 64 unmodified lines
65 return callShowRef(repo.Ctx, repo.Path, BranchPrefix, TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit)65 return callShowRef(repo.Ctx, repo.Path, BranchPrefix, TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit)
66}66}
67 67
68// WalkReferences walks all the references from the repository
69func 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
73// WalkReferences walks all the references from the repository68// WalkReferences walks all the references from the repository
74// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.69// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.
75func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {70func (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 · 5 unmodified lines
81 args = TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}76 args = TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}
82 }77 }
83 78
84 return walkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn)79 return WalkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn)
85}80}
86 81
87// callShowRef return refs, if limit = 0 it will not limit82// callShowRef return refs, if limit = 0 it will not limit
88func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) {83func 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 {
90 branchName = strings.TrimPrefix(branchName, trimPrefix)85 branchName = strings.TrimPrefix(branchName, trimPrefix)
91 branchNames = append(branchNames, branchName)86 branchNames = append(branchNames, branchName)
92 87
@@ -95,7 +90,7 @@ func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs Tru · 2 unmodified lines
95 return branchNames, countAll, err90 return branchNames, countAll, err
96}91}
97 92
98func walkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {93func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
99 stdoutReader, stdoutWriter := io.Pipe()94 stdoutReader, stdoutWriter := io.Pipe()
100 defer func() {95 defer func() {
101 _ = stdoutReader.Close()96 _ = stdoutReader.Close()
@@ -189,7 +184,7 @@ func walkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, · 87 unmodified lines
189// GetRefsBySha returns all references filtered with prefix that belong to a sha commit hash184// GetRefsBySha returns all references filtered with prefix that belong to a sha commit hash
190func (repo *Repository) GetRefsBySha(sha, prefix string) ([]string, error) {185func (repo *Repository) GetRefsBySha(sha, prefix string) ([]string, error) {
191 var revList []string186 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 {
193 if walkSha == sha && strings.HasPrefix(refname, prefix) {188 if walkSha == sha && strings.HasPrefix(refname, prefix) {
194 revList = append(revList, refname)189 revList = append(revList, refname)
195 }190 }