Skip to content

Commit 1f32170

Browse files
authored
Move some functions to gitrepo package (#35503)
1 parent 7bf2972 commit 1f32170

File tree

22 files changed

+190
-198
lines changed

22 files changed

+190
-198
lines changed

modules/git/repo_blame.go

Lines changed: 0 additions & 25 deletions
This file was deleted.

modules/git/repo_branch.go

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,70 +5,12 @@
55
package git
66

77
import (
8-
"context"
9-
"errors"
10-
"strings"
11-
128
"code.gitea.io/gitea/modules/git/gitcmd"
139
)
1410

1511
// BranchPrefix base dir of the branch information file store on git
1612
const BranchPrefix = "refs/heads/"
1713

18-
// IsReferenceExist returns true if given reference exists in the repository.
19-
func IsReferenceExist(ctx context.Context, repoPath, name string) bool {
20-
_, _, err := gitcmd.NewCommand("show-ref", "--verify").AddDashesAndList(name).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
21-
return err == nil
22-
}
23-
24-
// IsBranchExist returns true if given branch exists in the repository.
25-
func IsBranchExist(ctx context.Context, repoPath, name string) bool {
26-
return IsReferenceExist(ctx, repoPath, BranchPrefix+name)
27-
}
28-
29-
func GetDefaultBranch(ctx context.Context, repoPath string) (string, error) {
30-
stdout, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
31-
if err != nil {
32-
return "", err
33-
}
34-
stdout = strings.TrimSpace(stdout)
35-
if !strings.HasPrefix(stdout, BranchPrefix) {
36-
return "", errors.New("the HEAD is not a branch: " + stdout)
37-
}
38-
return strings.TrimPrefix(stdout, BranchPrefix), nil
39-
}
40-
41-
// DeleteBranchOptions Option(s) for delete branch
42-
type DeleteBranchOptions struct {
43-
Force bool
44-
}
45-
46-
// DeleteBranch delete a branch by name on repository.
47-
func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) error {
48-
cmd := gitcmd.NewCommand("branch")
49-
50-
if opts.Force {
51-
cmd.AddArguments("-D")
52-
} else {
53-
cmd.AddArguments("-d")
54-
}
55-
56-
cmd.AddDashesAndList(name)
57-
_, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
58-
59-
return err
60-
}
61-
62-
// CreateBranch create a new branch
63-
func (repo *Repository) CreateBranch(branch, oldbranchOrCommit string) error {
64-
cmd := gitcmd.NewCommand("branch")
65-
cmd.AddDashesAndList(branch, oldbranchOrCommit)
66-
67-
_, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
68-
69-
return err
70-
}
71-
7214
// AddRemote adds a new remote to repository.
7315
func (repo *Repository) AddRemote(name, url string, fetch bool) error {
7416
cmd := gitcmd.NewCommand("remote", "add")
@@ -80,9 +22,3 @@ func (repo *Repository) AddRemote(name, url string, fetch bool) error {
8022
_, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
8123
return err
8224
}
83-
84-
// RenameBranch rename a branch
85-
func (repo *Repository) RenameBranch(from, to string) error {
86-
_, _, err := gitcmd.NewCommand("branch", "-m").AddDynamicArguments(from, to).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path})
87-
return err
88-
}

modules/git/repo_compare.go

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@ package git
77
import (
88
"bufio"
99
"bytes"
10-
"context"
1110
"errors"
1211
"fmt"
1312
"io"
1413
"os"
1514
"path/filepath"
1615
"regexp"
17-
"strconv"
1816
"strings"
1917

2018
"code.gitea.io/gitea/modules/git/gitcmd"
@@ -87,57 +85,8 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis
8785
return w.numLines, nil
8886
}
8987

90-
// GetDiffShortStatByCmdArgs counts number of changed files, number of additions and deletions
91-
// TODO: it can be merged with another "GetDiffShortStat" in the future
92-
func GetDiffShortStatByCmdArgs(ctx context.Context, repoPath string, trustedArgs gitcmd.TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
93-
// Now if we call:
94-
// $ git diff --shortstat 1ebb35b98889ff77299f24d82da426b434b0cca0...788b8b1440462d477f45b0088875
95-
// we get:
96-
// " 9902 files changed, 2034198 insertions(+), 298800 deletions(-)\n"
97-
cmd := gitcmd.NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...)
98-
stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath})
99-
if err != nil {
100-
return 0, 0, 0, err
101-
}
102-
103-
return parseDiffStat(stdout)
104-
}
105-
106-
var shortStatFormat = regexp.MustCompile(
107-
`\s*(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?`)
108-
10988
var patchCommits = regexp.MustCompile(`^From\s(\w+)\s`)
11089

111-
func parseDiffStat(stdout string) (numFiles, totalAdditions, totalDeletions int, err error) {
112-
if len(stdout) == 0 || stdout == "\n" {
113-
return 0, 0, 0, nil
114-
}
115-
groups := shortStatFormat.FindStringSubmatch(stdout)
116-
if len(groups) != 4 {
117-
return 0, 0, 0, fmt.Errorf("unable to parse shortstat: %s groups: %s", stdout, groups)
118-
}
119-
120-
numFiles, err = strconv.Atoi(groups[1])
121-
if err != nil {
122-
return 0, 0, 0, fmt.Errorf("unable to parse shortstat: %s. Error parsing NumFiles %w", stdout, err)
123-
}
124-
125-
if len(groups[2]) != 0 {
126-
totalAdditions, err = strconv.Atoi(groups[2])
127-
if err != nil {
128-
return 0, 0, 0, fmt.Errorf("unable to parse shortstat: %s. Error parsing NumAdditions %w", stdout, err)
129-
}
130-
}
131-
132-
if len(groups[3]) != 0 {
133-
totalDeletions, err = strconv.Atoi(groups[3])
134-
if err != nil {
135-
return 0, 0, 0, fmt.Errorf("unable to parse shortstat: %s. Error parsing NumDeletions %w", stdout, err)
136-
}
137-
}
138-
return numFiles, totalAdditions, totalDeletions, err
139-
}
140-
14190
// GetDiff generates and returns patch data between given revisions, optimized for human readability
14291
func (repo *Repository) GetDiff(compareArg string, w io.Writer) error {
14392
stderr := new(bytes.Buffer)

modules/gitrepo/blame.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package gitrepo
5+
6+
import (
7+
"context"
8+
9+
"code.gitea.io/gitea/modules/git/gitcmd"
10+
)
11+
12+
func LineBlame(ctx context.Context, repo Repository, revision, file string, line uint) (string, error) {
13+
return runCmdString(ctx, repo,
14+
gitcmd.NewCommand("blame").
15+
AddOptionFormat("-L %d,%d", line, line).
16+
AddOptionValues("-p", revision).
17+
AddDashesAndList(file))
18+
}

modules/gitrepo/branch.go

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ package gitrepo
55

66
import (
77
"context"
8+
"errors"
9+
"strings"
810

911
"code.gitea.io/gitea/modules/git"
1012
"code.gitea.io/gitea/modules/git/gitcmd"
@@ -34,23 +36,61 @@ func GetBranchCommitID(ctx context.Context, repo Repository, branch string) (str
3436

3537
// SetDefaultBranch sets default branch of repository.
3638
func SetDefaultBranch(ctx context.Context, repo Repository, name string) error {
37-
_, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD").
38-
AddDynamicArguments(git.BranchPrefix+name).
39-
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
39+
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("symbolic-ref", "HEAD").
40+
AddDynamicArguments(git.BranchPrefix+name))
4041
return err
4142
}
4243

4344
// GetDefaultBranch gets default branch of repository.
4445
func GetDefaultBranch(ctx context.Context, repo Repository) (string, error) {
45-
return git.GetDefaultBranch(ctx, repoPath(repo))
46+
stdout, err := runCmdString(ctx, repo, gitcmd.NewCommand("symbolic-ref", "HEAD"))
47+
if err != nil {
48+
return "", err
49+
}
50+
stdout = strings.TrimSpace(stdout)
51+
if !strings.HasPrefix(stdout, git.BranchPrefix) {
52+
return "", errors.New("the HEAD is not a branch: " + stdout)
53+
}
54+
return strings.TrimPrefix(stdout, git.BranchPrefix), nil
4655
}
4756

4857
// IsReferenceExist returns true if given reference exists in the repository.
4958
func IsReferenceExist(ctx context.Context, repo Repository, name string) bool {
50-
return git.IsReferenceExist(ctx, repoPath(repo), name)
59+
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("show-ref", "--verify").AddDashesAndList(name))
60+
return err == nil
5161
}
5262

5363
// IsBranchExist returns true if given branch exists in the repository.
5464
func IsBranchExist(ctx context.Context, repo Repository, name string) bool {
5565
return IsReferenceExist(ctx, repo, git.BranchPrefix+name)
5666
}
67+
68+
// DeleteBranch delete a branch by name on repository.
69+
func DeleteBranch(ctx context.Context, repo Repository, name string, force bool) error {
70+
cmd := gitcmd.NewCommand("branch")
71+
72+
if force {
73+
cmd.AddArguments("-D")
74+
} else {
75+
cmd.AddArguments("-d")
76+
}
77+
78+
cmd.AddDashesAndList(name)
79+
_, err := runCmdString(ctx, repo, cmd)
80+
return err
81+
}
82+
83+
// CreateBranch create a new branch
84+
func CreateBranch(ctx context.Context, repo Repository, branch, oldbranchOrCommit string) error {
85+
cmd := gitcmd.NewCommand("branch")
86+
cmd.AddDashesAndList(branch, oldbranchOrCommit)
87+
88+
_, err := runCmdString(ctx, repo, cmd)
89+
return err
90+
}
91+
92+
// RenameBranch rename a branch
93+
func RenameBranch(ctx context.Context, repo Repository, from, to string) error {
94+
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("branch", "-m").AddDynamicArguments(from, to))
95+
return err
96+
}

modules/gitrepo/command.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package gitrepo
5+
6+
import (
7+
"context"
8+
9+
"code.gitea.io/gitea/modules/git/gitcmd"
10+
)
11+
12+
func runCmdString(ctx context.Context, repo Repository, cmd *gitcmd.Command) (string, error) {
13+
res, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
14+
return res, err
15+
}

modules/gitrepo/config.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ import (
1212
)
1313

1414
func GitConfigGet(ctx context.Context, repo Repository, key string) (string, error) {
15-
result, _, err := gitcmd.NewCommand("config", "--get").
16-
AddDynamicArguments(key).
17-
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
15+
result, err := runCmdString(ctx, repo, gitcmd.NewCommand("config", "--get").
16+
AddDynamicArguments(key))
1817
if err != nil {
1918
return "", err
2019
}
@@ -28,9 +27,8 @@ func getRepoConfigLockKey(repoStoragePath string) string {
2827
// GitConfigAdd add a git configuration key to a specific value for the given repository.
2928
func GitConfigAdd(ctx context.Context, repo Repository, key, value string) error {
3029
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
31-
_, _, err := gitcmd.NewCommand("config", "--add").
32-
AddDynamicArguments(key, value).
33-
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
30+
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("config", "--add").
31+
AddDynamicArguments(key, value))
3432
return err
3533
})
3634
}
@@ -40,9 +38,8 @@ func GitConfigAdd(ctx context.Context, repo Repository, key, value string) error
4038
// If the key exists, it will be updated to the new value.
4139
func GitConfigSet(ctx context.Context, repo Repository, key, value string) error {
4240
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
43-
_, _, err := gitcmd.NewCommand("config").
44-
AddDynamicArguments(key, value).
45-
RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
41+
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("config").
42+
AddDynamicArguments(key, value))
4643
return err
4744
})
4845
}

modules/gitrepo/diff.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package gitrepo
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"regexp"
10+
"strconv"
11+
12+
"code.gitea.io/gitea/modules/git/gitcmd"
13+
)
14+
15+
// GetDiffShortStatByCmdArgs counts number of changed files, number of additions and deletions
16+
// TODO: it can be merged with another "GetDiffShortStat" in the future
17+
func GetDiffShortStatByCmdArgs(ctx context.Context, repo Repository, trustedArgs gitcmd.TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
18+
// Now if we call:
19+
// $ git diff --shortstat 1ebb35b98889ff77299f24d82da426b434b0cca0...788b8b1440462d477f45b0088875
20+
// we get:
21+
// " 9902 files changed, 2034198 insertions(+), 298800 deletions(-)\n"
22+
cmd := gitcmd.NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...)
23+
stdout, err := runCmdString(ctx, repo, cmd)
24+
if err != nil {
25+
return 0, 0, 0, err
26+
}
27+
28+
return parseDiffStat(stdout)
29+
}
30+
31+
var shortStatFormat = regexp.MustCompile(
32+
`\s*(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?`)
33+
34+
func parseDiffStat(stdout string) (numFiles, totalAdditions, totalDeletions int, err error) {
35+
if len(stdout) == 0 || stdout == "\n" {
36+
return 0, 0, 0, nil
37+
}
38+
groups := shortStatFormat.FindStringSubmatch(stdout)
39+
if len(groups) != 4 {
40+
return 0, 0, 0, fmt.Errorf("unable to parse shortstat: %s groups: %s", stdout, groups)
41+
}
42+
43+
numFiles, err = strconv.Atoi(groups[1])
44+
if err != nil {
45+
return 0, 0, 0, fmt.Errorf("unable to parse shortstat: %s. Error parsing NumFiles %w", stdout, err)
46+
}
47+
48+
if len(groups[2]) != 0 {
49+
totalAdditions, err = strconv.Atoi(groups[2])
50+
if err != nil {
51+
return 0, 0, 0, fmt.Errorf("unable to parse shortstat: %s. Error parsing NumAdditions %w", stdout, err)
52+
}
53+
}
54+
55+
if len(groups[3]) != 0 {
56+
totalDeletions, err = strconv.Atoi(groups[3])
57+
if err != nil {
58+
return 0, 0, 0, fmt.Errorf("unable to parse shortstat: %s. Error parsing NumDeletions %w", stdout, err)
59+
}
60+
}
61+
return numFiles, totalAdditions, totalDeletions, err
62+
}

0 commit comments

Comments
 (0)