Move some functions to gitrepo package (#35543)

Refactor Git command functions to use WithXXX methods instead of
exposing RunOpts.
This change simplifies reuse across gitrepo and improves consistency,
encapsulation, and maintainability of command options.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Lunny Xiao
2025-10-07 02:06:51 -07:00
committed by GitHub
parent c9e7fde8b3
commit 69f5ee970c
114 changed files with 1188 additions and 919 deletions

View File

@@ -29,12 +29,7 @@ func CreateArchive(ctx context.Context, repo Repository, format string, target i
cmd.AddDynamicArguments(commitID)
var stderr strings.Builder
err := cmd.Run(ctx, &gitcmd.RunOpts{
Dir: repoPath(repo),
Stdout: target,
Stderr: &stderr,
})
if err != nil {
if err := RunCmd(ctx, repo, cmd.WithStdout(target).WithStderr(&stderr)); err != nil {
return gitcmd.ConcatenateError(err, stderr.String())
}
return nil
@@ -49,23 +44,23 @@ func CreateBundle(ctx context.Context, repo Repository, commit string, out io.Wr
defer cleanup()
env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(repoPath(repo), "objects"))
_, _, err = gitcmd.NewCommand("init", "--bare").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env})
_, _, err = gitcmd.NewCommand("init", "--bare").WithDir(tmp).WithEnv(env).RunStdString(ctx)
if err != nil {
return err
}
_, _, err = gitcmd.NewCommand("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env})
_, _, err = gitcmd.NewCommand("reset", "--soft").AddDynamicArguments(commit).WithDir(tmp).WithEnv(env).RunStdString(ctx)
if err != nil {
return err
}
_, _, err = gitcmd.NewCommand("branch", "-m", "bundle").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env})
_, _, err = gitcmd.NewCommand("branch", "-m", "bundle").WithDir(tmp).WithEnv(env).RunStdString(ctx)
if err != nil {
return err
}
tmpFile := filepath.Join(tmp, "bundle")
_, _, err = gitcmd.NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env})
_, _, err = gitcmd.NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").WithDir(tmp).WithEnv(env).RunStdString(ctx)
if err != nil {
return err
}

View File

@@ -10,7 +10,7 @@ import (
)
func LineBlame(ctx context.Context, repo Repository, revision, file string, line uint) (string, error) {
return runCmdString(ctx, repo,
return RunCmdString(ctx, repo,
gitcmd.NewCommand("blame").
AddOptionFormat("-L %d,%d", line, line).
AddOptionValues("-p", revision).

View File

@@ -36,14 +36,14 @@ func GetBranchCommitID(ctx context.Context, repo Repository, branch string) (str
// SetDefaultBranch sets default branch of repository.
func SetDefaultBranch(ctx context.Context, repo Repository, name string) error {
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("symbolic-ref", "HEAD").
_, err := RunCmdString(ctx, repo, gitcmd.NewCommand("symbolic-ref", "HEAD").
AddDynamicArguments(git.BranchPrefix+name))
return err
}
// GetDefaultBranch gets default branch of repository.
func GetDefaultBranch(ctx context.Context, repo Repository) (string, error) {
stdout, err := runCmdString(ctx, repo, gitcmd.NewCommand("symbolic-ref", "HEAD"))
stdout, err := RunCmdString(ctx, repo, gitcmd.NewCommand("symbolic-ref", "HEAD"))
if err != nil {
return "", err
}
@@ -56,7 +56,7 @@ func GetDefaultBranch(ctx context.Context, repo Repository) (string, error) {
// IsReferenceExist returns true if given reference exists in the repository.
func IsReferenceExist(ctx context.Context, repo Repository, name string) bool {
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("show-ref", "--verify").AddDashesAndList(name))
_, err := RunCmdString(ctx, repo, gitcmd.NewCommand("show-ref", "--verify").AddDashesAndList(name))
return err == nil
}
@@ -76,7 +76,7 @@ func DeleteBranch(ctx context.Context, repo Repository, name string, force bool)
}
cmd.AddDashesAndList(name)
_, err := runCmdString(ctx, repo, cmd)
_, err := RunCmdString(ctx, repo, cmd)
return err
}
@@ -85,12 +85,12 @@ func CreateBranch(ctx context.Context, repo Repository, branch, oldbranchOrCommi
cmd := gitcmd.NewCommand("branch")
cmd.AddDashesAndList(branch, oldbranchOrCommit)
_, err := runCmdString(ctx, repo, cmd)
_, err := RunCmdString(ctx, repo, cmd)
return err
}
// RenameBranch rename a branch
func RenameBranch(ctx context.Context, repo Repository, from, to string) error {
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("branch", "-m").AddDynamicArguments(from, to))
_, err := RunCmdString(ctx, repo, gitcmd.NewCommand("branch", "-m").AddDynamicArguments(from, to))
return err
}

View File

@@ -9,7 +9,15 @@ import (
"code.gitea.io/gitea/modules/git/gitcmd"
)
func runCmdString(ctx context.Context, repo Repository, cmd *gitcmd.Command) (string, error) {
res, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
func RunCmd(ctx context.Context, repo Repository, cmd *gitcmd.Command) error {
return cmd.WithDir(repoPath(repo)).WithParentCallerInfo().Run(ctx)
}
func RunCmdString(ctx context.Context, repo Repository, cmd *gitcmd.Command) (string, error) {
res, _, err := cmd.WithDir(repoPath(repo)).WithParentCallerInfo().RunStdString(ctx)
return res, err
}
func RunCmdBytes(ctx context.Context, repo Repository, cmd *gitcmd.Command) ([]byte, []byte, error) {
return cmd.WithDir(repoPath(repo)).WithParentCallerInfo().RunStdBytes(ctx)
}

View File

@@ -22,7 +22,7 @@ type DivergeObject struct {
func GetDivergingCommits(ctx context.Context, repo Repository, baseBranch, targetBranch string) (*DivergeObject, error) {
cmd := gitcmd.NewCommand("rev-list", "--count", "--left-right").
AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--")
stdout, _, err1 := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
stdout, err1 := RunCmdString(ctx, repo, cmd)
if err1 != nil {
return nil, err1
}

View File

@@ -12,7 +12,7 @@ import (
)
func GitConfigGet(ctx context.Context, repo Repository, key string) (string, error) {
result, err := runCmdString(ctx, repo, gitcmd.NewCommand("config", "--get").
result, err := RunCmdString(ctx, repo, gitcmd.NewCommand("config", "--get").
AddDynamicArguments(key))
if err != nil {
return "", err
@@ -27,7 +27,7 @@ func getRepoConfigLockKey(repoStoragePath string) string {
// GitConfigAdd add a git configuration key to a specific value for the given repository.
func GitConfigAdd(ctx context.Context, repo Repository, key, value string) error {
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("config", "--add").
_, err := RunCmdString(ctx, repo, gitcmd.NewCommand("config", "--add").
AddDynamicArguments(key, value))
return err
})
@@ -38,7 +38,7 @@ func GitConfigAdd(ctx context.Context, repo Repository, key, value string) error
// If the key exists, it will be updated to the new value.
func GitConfigSet(ctx context.Context, repo Repository, key, value string) error {
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
_, err := runCmdString(ctx, repo, gitcmd.NewCommand("config").
_, err := RunCmdString(ctx, repo, gitcmd.NewCommand("config").
AddDynamicArguments(key, value))
return err
})

View File

@@ -20,7 +20,7 @@ func GetDiffShortStatByCmdArgs(ctx context.Context, repo Repository, trustedArgs
// we get:
// " 9902 files changed, 2034198 insertions(+), 298800 deletions(-)\n"
cmd := gitcmd.NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...)
stdout, err := runCmdString(ctx, repo, cmd)
stdout, err := RunCmdString(ctx, repo, cmd)
if err != nil {
return 0, 0, 0, err
}

View File

@@ -12,5 +12,5 @@ import (
// Fsck verifies the connectivity and validity of the objects in the database
func Fsck(ctx context.Context, repo Repository, timeout time.Duration, args gitcmd.TrustedCmdArgs) error {
return gitcmd.NewCommand("fsck").AddArguments(args...).Run(ctx, &gitcmd.RunOpts{Timeout: timeout, Dir: repoPath(repo)})
return RunCmd(ctx, repo, gitcmd.NewCommand("fsck").AddArguments(args...).WithTimeout(timeout))
}

View File

@@ -10,12 +10,10 @@ import (
)
func UpdateRef(ctx context.Context, repo Repository, refName, newCommitID string) error {
_, _, err := gitcmd.NewCommand("update-ref").AddDynamicArguments(refName, newCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
return err
return RunCmd(ctx, repo, gitcmd.NewCommand("update-ref").AddDynamicArguments(refName, newCommitID))
}
func RemoveRef(ctx context.Context, repo Repository, refName string) error {
_, _, err := gitcmd.NewCommand("update-ref", "--no-deref", "-d").
AddDynamicArguments(refName).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)})
return err
return RunCmd(ctx, repo, gitcmd.NewCommand("update-ref", "--no-deref", "-d").
AddDynamicArguments(refName))
}

View File

@@ -36,7 +36,7 @@ func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL st
return errors.New("unknown remote option: " + string(options[0]))
}
}
_, err := runCmdString(ctx, repo, cmd.AddDynamicArguments(remoteName, remoteURL))
_, err := RunCmdString(ctx, repo, cmd.AddDynamicArguments(remoteName, remoteURL))
return err
})
}
@@ -44,7 +44,7 @@ func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL st
func GitRemoteRemove(ctx context.Context, repo Repository, remoteName string) error {
return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error {
cmd := gitcmd.NewCommand("remote", "rm").AddDynamicArguments(remoteName)
_, err := runCmdString(ctx, repo, cmd)
_, err := RunCmdString(ctx, repo, cmd)
return err
})
}
@@ -63,22 +63,18 @@ func GitRemoteGetURL(ctx context.Context, repo Repository, remoteName string) (*
// GitRemotePrune prunes the remote branches that no longer exist in the remote repository.
func GitRemotePrune(ctx context.Context, repo Repository, remoteName string, timeout time.Duration, stdout, stderr io.Writer) error {
return gitcmd.NewCommand("remote", "prune").AddDynamicArguments(remoteName).
Run(ctx, &gitcmd.RunOpts{
Timeout: timeout,
Dir: repoPath(repo),
Stdout: stdout,
Stderr: stderr,
})
return RunCmd(ctx, repo, gitcmd.NewCommand("remote", "prune").
AddDynamicArguments(remoteName).
WithTimeout(timeout).
WithStdout(stdout).
WithStderr(stderr))
}
// GitRemoteUpdatePrune updates the remote branches and prunes the ones that no longer exist in the remote repository.
func GitRemoteUpdatePrune(ctx context.Context, repo Repository, remoteName string, timeout time.Duration, stdout, stderr io.Writer) error {
return gitcmd.NewCommand("remote", "update", "--prune").AddDynamicArguments(remoteName).
Run(ctx, &gitcmd.RunOpts{
Timeout: timeout,
Dir: repoPath(repo),
Stdout: stdout,
Stderr: stderr,
})
return RunCmd(ctx, repo, gitcmd.NewCommand("remote", "update", "--prune").
AddDynamicArguments(remoteName).
WithTimeout(timeout).
WithStdout(stdout).
WithStderr(stderr))
}

37
modules/gitrepo/size.go Normal file
View File

@@ -0,0 +1,37 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package gitrepo
import (
"os"
"path/filepath"
)
const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
// CalcRepositorySize returns the disk consumption for a given path
func CalcRepositorySize(repo Repository) (int64, error) {
var size int64
err := filepath.WalkDir(repoPath(repo), func(_ string, entry os.DirEntry, err error) error {
if os.IsNotExist(err) { // ignore the error because some files (like temp/lock file) may be deleted during traversing.
return nil
} else if err != nil {
return err
}
if entry.IsDir() {
return nil
}
info, err := entry.Info()
if os.IsNotExist(err) { // ignore the error as above
return nil
} else if err != nil {
return err
}
if (info.Mode() & notRegularFileMode) == 0 {
size += info.Size()
}
return nil
})
return size, err
}