diff --git a/cmd/hook.go b/cmd/hook.go index b741127ca3..2f866dd396 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -15,6 +15,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" repo_module "code.gitea.io/gitea/modules/repository" @@ -312,7 +313,7 @@ func runHookPostReceive(ctx context.Context, c *cli.Command) error { setup(ctx, c.Bool("debug")) // First of all run update-server-info no matter what - if _, _, err := git.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil { + if _, _, err := gitcmd.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil { return fmt.Errorf("failed to call 'git update-server-info': %w", err) } diff --git a/cmd/serv.go b/cmd/serv.go index 60f7fb92ff..76d8c81544 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -21,6 +21,7 @@ import ( "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/lfstransfer" "code.gitea.io/gitea/modules/log" @@ -312,30 +313,30 @@ func runServ(ctx context.Context, c *cli.Command) error { return nil } - var gitcmd *exec.Cmd - gitBinPath := filepath.Dir(git.GitExecutable) // e.g. /usr/bin - gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack + var command *exec.Cmd + gitBinPath := filepath.Dir(gitcmd.GitExecutable) // e.g. /usr/bin + gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack if _, err := os.Stat(gitBinVerb); err != nil { // if the command "git-upload-pack" doesn't exist, try to split "git-upload-pack" to use the sub-command with git // ps: Windows only has "git.exe" in the bin path, so Windows always uses this way verbFields := strings.SplitN(verb, "-", 2) if len(verbFields) == 2 { // use git binary with the sub-command part: "C:\...\bin\git.exe", "upload-pack", ... - gitcmd = exec.CommandContext(ctx, git.GitExecutable, verbFields[1], repoPath) + command = exec.CommandContext(ctx, gitcmd.GitExecutable, verbFields[1], repoPath) } } - if gitcmd == nil { + if command == nil { // by default, use the verb (it has been checked above by allowedCommands) - gitcmd = exec.CommandContext(ctx, gitBinVerb, repoPath) + command = exec.CommandContext(ctx, gitBinVerb, repoPath) } - process.SetSysProcAttribute(gitcmd) - gitcmd.Dir = setting.RepoRootPath - gitcmd.Stdout = os.Stdout - gitcmd.Stdin = os.Stdin - gitcmd.Stderr = os.Stderr - gitcmd.Env = append(gitcmd.Env, os.Environ()...) - gitcmd.Env = append(gitcmd.Env, + process.SetSysProcAttribute(command) + command.Dir = setting.RepoRootPath + command.Stdout = os.Stdout + command.Stdin = os.Stdin + command.Stderr = os.Stderr + command.Env = append(command.Env, os.Environ()...) + command.Env = append(command.Env, repo_module.EnvRepoIsWiki+"="+strconv.FormatBool(results.IsWiki), repo_module.EnvRepoName+"="+results.RepoName, repo_module.EnvRepoUsername+"="+results.OwnerName, @@ -350,9 +351,9 @@ func runServ(ctx context.Context, c *cli.Command) error { ) // to avoid breaking, here only use the minimal environment variables for the "gitea serv" command. // it could be re-considered whether to use the same git.CommonGitCmdEnvs() as "git" command later. - gitcmd.Env = append(gitcmd.Env, git.CommonCmdServEnvs()...) + command.Env = append(command.Env, gitcmd.CommonCmdServEnvs()...) - if err = gitcmd.Run(); err != nil { + if err = command.Run(); err != nil { return fail(ctx, "Failed to execute git command", "Failed to execute git command: %v", err) } diff --git a/models/migrations/v1_12/v128.go b/models/migrations/v1_12/v128.go index d2e8b86a3d..34746dcdc4 100644 --- a/models/migrations/v1_12/v128.go +++ b/models/migrations/v1_12/v128.go @@ -12,6 +12,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -83,17 +84,17 @@ func FixMergeBase(ctx context.Context, x *xorm.Engine) error { if !pr.HasMerged { var err error - pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = gitcmd.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { var err2 error - pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err2 = gitcmd.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err2 != nil { log.Error("Unable to get merge base for PR ID %d, Index %d in %s/%s. Error: %v & %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err, err2) continue } } } else { - parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue @@ -105,9 +106,9 @@ func FixMergeBase(ctx context.Context, x *xorm.Engine) error { refs := append([]string{}, parents[1:]...) refs = append(refs, gitRefName) - cmd := git.NewCommand("merge-base").AddDashesAndList(refs...) + cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...) - pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue diff --git a/models/migrations/v1_12/v134.go b/models/migrations/v1_12/v134.go index 189d80cc52..d31cc3abdb 100644 --- a/models/migrations/v1_12/v134.go +++ b/models/migrations/v1_12/v134.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -80,7 +80,7 @@ func RefixMergeBase(ctx context.Context, x *xorm.Engine) error { gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index) - parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue @@ -93,9 +93,9 @@ func RefixMergeBase(ctx context.Context, x *xorm.Engine) error { // we should recalculate refs := append([]string{}, parents[1:]...) refs = append(refs, gitRefName) - cmd := git.NewCommand("merge-base").AddDashesAndList(refs...) + cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...) - pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue diff --git a/modules/git/attribute/batch.go b/modules/git/attribute/batch.go index 4e31fda575..9f805d55c5 100644 --- a/modules/git/attribute/batch.go +++ b/modules/git/attribute/batch.go @@ -12,6 +12,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -23,7 +24,7 @@ type BatchChecker struct { stdOut *nulSeparatedAttributeWriter ctx context.Context cancel context.CancelFunc - cmd *git.Command + cmd *gitcmd.Command } // NewBatchChecker creates a check attribute reader for the current repository and provided commit ID @@ -76,7 +77,7 @@ func NewBatchChecker(repo *git.Repository, treeish string, attributes []string) _ = lw.Close() }() stdErr := new(bytes.Buffer) - err := cmd.Run(ctx, &git.RunOpts{ + err := cmd.Run(ctx, &gitcmd.RunOpts{ Env: envs, Dir: repo.Path, Stdin: stdinReader, diff --git a/modules/git/attribute/checker.go b/modules/git/attribute/checker.go index 167b31416e..4b313adf37 100644 --- a/modules/git/attribute/checker.go +++ b/modules/git/attribute/checker.go @@ -11,12 +11,13 @@ import ( "os" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) -func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attributes []string) (*git.Command, []string, func(), error) { +func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attributes []string) (*gitcmd.Command, []string, func(), error) { cancel := func() {} envs := []string{"GIT_FLUSH=1"} - cmd := git.NewCommand("check-attr", "-z") + cmd := gitcmd.NewCommand("check-attr", "-z") if len(attributes) == 0 { cmd.AddArguments("--all") } @@ -70,7 +71,7 @@ func CheckAttributes(ctx context.Context, gitRepo *git.Repository, treeish strin stdOut := new(bytes.Buffer) stdErr := new(bytes.Buffer) - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Env: append(os.Environ(), envs...), Dir: gitRepo.Path, Stdout: stdOut, diff --git a/modules/git/batch_reader.go b/modules/git/batch_reader.go index 7bbab76bb8..f09f4144c8 100644 --- a/modules/git/batch_reader.go +++ b/modules/git/batch_reader.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "github.com/djherbis/buffer" @@ -29,13 +30,13 @@ type WriteCloserError interface { // This is needed otherwise the git cat-file will hang for invalid repositories. func ensureValidGitRepository(ctx context.Context, repoPath string) error { stderr := strings.Builder{} - err := NewCommand("rev-parse"). - Run(ctx, &RunOpts{ + err := gitcmd.NewCommand("rev-parse"). + Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stderr: &stderr, }) if err != nil { - return ConcatenateError(err, (&stderr).String()) + return gitcmd.ConcatenateError(err, (&stderr).String()) } return nil } @@ -61,8 +62,8 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, go func() { stderr := strings.Builder{} - err := NewCommand("cat-file", "--batch-check"). - Run(ctx, &RunOpts{ + err := gitcmd.NewCommand("cat-file", "--batch-check"). + Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdin: batchStdinReader, Stdout: batchStdoutWriter, @@ -71,8 +72,8 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, UseContextTimeout: true, }) if err != nil { - _ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) - _ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String())) + _ = batchStdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) + _ = batchStdinReader.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) } else { _ = batchStdoutWriter.Close() _ = batchStdinReader.Close() @@ -109,8 +110,8 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi go func() { stderr := strings.Builder{} - err := NewCommand("cat-file", "--batch"). - Run(ctx, &RunOpts{ + err := gitcmd.NewCommand("cat-file", "--batch"). + Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdin: batchStdinReader, Stdout: batchStdoutWriter, @@ -119,8 +120,8 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi UseContextTimeout: true, }) if err != nil { - _ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) - _ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String())) + _ = batchStdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) + _ = batchStdinReader.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) } else { _ = batchStdoutWriter.Close() _ = batchStdinReader.Close() diff --git a/modules/git/blame.go b/modules/git/blame.go index db10df129e..50cadc41c2 100644 --- a/modules/git/blame.go +++ b/modules/git/blame.go @@ -10,6 +10,7 @@ import ( "io" "os" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) @@ -141,7 +142,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath } }() - cmd := NewCommand("blame", "--porcelain") + cmd := gitcmd.NewCommand("blame", "--porcelain") if DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore { ignoreRevsFileName, ignoreRevsFileCleanup, err = tryCreateBlameIgnoreRevsFile(commit) @@ -165,7 +166,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath go func() { stderr := bytes.Buffer{} // TODO: it doesn't work for directories (the directories shouldn't be "blamed"), and the "err" should be returned by "Read" but not by "Close" - err := cmd.Run(ctx, &RunOpts{ + err := cmd.Run(ctx, &gitcmd.RunOpts{ UseContextTimeout: true, Dir: repoPath, Stdout: stdout, diff --git a/modules/git/commit.go b/modules/git/commit.go index 0dc894d3ab..a0c5955ae8 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/util" ) @@ -87,12 +88,12 @@ func (c *Commit) GetCommitByPath(relpath string) (*Commit, error) { // AddChanges marks local changes to be ready for commit. func AddChanges(ctx context.Context, repoPath string, all bool, files ...string) error { - cmd := NewCommand().AddArguments("add") + cmd := gitcmd.NewCommand().AddArguments("add") if all { cmd.AddArguments("--all") } cmd.AddDashesAndList(files...) - _, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + _, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) return err } @@ -106,7 +107,7 @@ type CommitChangesOptions struct { // CommitChanges commits local changes with given committer, author and message. // If author is nil, it will be the same as committer. func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptions) error { - cmd := NewCommand() + cmd := gitcmd.NewCommand() if opts.Committer != nil { cmd.AddOptionValues("-c", "user.name="+opts.Committer.Name) cmd.AddOptionValues("-c", "user.email="+opts.Committer.Email) @@ -121,7 +122,7 @@ func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptio } cmd.AddOptionFormat("--message=%s", opts.Message) - _, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + _, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) // No stderr but exit status 1 means nothing to commit. if err != nil && err.Error() == "exit status 1" { return nil @@ -131,7 +132,7 @@ func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptio // AllCommitsCount returns count of all commits in repository func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, files ...string) (int64, error) { - cmd := NewCommand("rev-list") + cmd := gitcmd.NewCommand("rev-list") if hidePRRefs { cmd.AddArguments("--exclude=" + PullPrefix + "*") } @@ -140,7 +141,7 @@ func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, file cmd.AddDashesAndList(files...) } - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return 0, err } @@ -160,7 +161,7 @@ type CommitsCountOptions struct { // CommitsCount returns number of total commits of until given revision. func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error) { - cmd := NewCommand("rev-list", "--count") + cmd := gitcmd.NewCommand("rev-list", "--count") cmd.AddDynamicArguments(opts.Revision...) @@ -172,7 +173,7 @@ func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error) cmd.AddDashesAndList(opts.RelPath...) } - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: opts.RepoPath}) + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: opts.RepoPath}) if err != nil { return 0, err } @@ -207,7 +208,7 @@ func (c *Commit) HasPreviousCommit(objectID ObjectID) (bool, error) { return false, nil } - _, _, err := NewCommand("merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(c.repo.Ctx, &RunOpts{Dir: c.repo.Path}) + _, _, err := gitcmd.NewCommand("merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(c.repo.Ctx, &gitcmd.RunOpts{Dir: c.repo.Path}) if err == nil { return true, nil } @@ -348,12 +349,12 @@ func (c *Commit) GetFileContent(filename string, limit int) (string, error) { // GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only') func (c *Commit) GetBranchName() (string, error) { - cmd := NewCommand("name-rev") + cmd := gitcmd.NewCommand("name-rev") if DefaultFeatures().CheckVersionAtLeast("2.13.0") { cmd.AddArguments("--exclude", "refs/tags/*") } cmd.AddArguments("--name-only", "--no-undefined").AddDynamicArguments(c.ID.String()) - data, _, err := cmd.RunStdString(c.repo.Ctx, &RunOpts{Dir: c.repo.Path}) + data, _, err := cmd.RunStdString(c.repo.Ctx, &gitcmd.RunOpts{Dir: c.repo.Path}) if err != nil { // handle special case where git can not describe commit if strings.Contains(err.Error(), "cannot describe") { @@ -431,14 +432,14 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi }() stderr := new(bytes.Buffer) - err := NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(ctx, &RunOpts{ + err := gitcmd.NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdout: w, Stderr: stderr, }) w.Close() // Close writer to exit parsing goroutine if err != nil { - return nil, ConcatenateError(err, stderr.String()) + return nil, gitcmd.ConcatenateError(err, stderr.String()) } <-done @@ -447,7 +448,7 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi // GetFullCommitID returns full length (40) of commit ID by given short SHA in a repository. func GetFullCommitID(ctx context.Context, repoPath, shortID string) (string, error) { - commitID, _, err := NewCommand("rev-parse").AddDynamicArguments(shortID).RunStdString(ctx, &RunOpts{Dir: repoPath}) + commitID, _, err := gitcmd.NewCommand("rev-parse").AddDynamicArguments(shortID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { if strings.Contains(err.Error(), "exit status 128") { return "", ErrNotExist{shortID, ""} diff --git a/modules/git/config.go b/modules/git/config.go index 3a717908b9..2eafe971b3 100644 --- a/modules/git/config.go +++ b/modules/git/config.go @@ -11,13 +11,14 @@ import ( "runtime" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" ) // syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem) func syncGitConfig(ctx context.Context) (err error) { - if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil { - return fmt.Errorf("unable to prepare git home directory %s, err: %w", HomeDir(), err) + if err = os.MkdirAll(gitcmd.HomeDir(), os.ModePerm); err != nil { + return fmt.Errorf("unable to prepare git home directory %s, err: %w", gitcmd.HomeDir(), err) } // first, write user's git config options to git config file @@ -117,8 +118,8 @@ func syncGitConfig(ctx context.Context) (err error) { } func configSet(ctx context.Context, key, value string) error { - stdout, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) - if err != nil && !IsErrorExitCode(err, 1) { + stdout, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) + if err != nil && !gitcmd.IsErrorExitCode(err, 1) { return fmt.Errorf("failed to get git config %s, err: %w", key, err) } @@ -127,7 +128,7 @@ func configSet(ctx context.Context, key, value string) error { return nil } - _, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) + _, _, err = gitcmd.NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to set git global config %s, err: %w", key, err) } @@ -136,14 +137,14 @@ func configSet(ctx context.Context, key, value string) error { } func configSetNonExist(ctx context.Context, key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) + _, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) if err == nil { // already exist return nil } - if IsErrorExitCode(err, 1) { + if gitcmd.IsErrorExitCode(err, 1) { // not exist, set new config - _, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) + _, _, err = gitcmd.NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to set git global config %s, err: %w", key, err) } @@ -154,14 +155,14 @@ func configSetNonExist(ctx context.Context, key, value string) error { } func configAddNonExist(ctx context.Context, key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) + _, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) if err == nil { // already exist return nil } - if IsErrorExitCode(err, 1) { + if gitcmd.IsErrorExitCode(err, 1) { // not exist, add new config - _, _, err = NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(ctx, nil) + _, _, err = gitcmd.NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to add git global config %s, err: %w", key, err) } @@ -171,16 +172,16 @@ func configAddNonExist(ctx context.Context, key, value string) error { } func configUnsetAll(ctx context.Context, key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) + _, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) if err == nil { // exist, need to remove - _, _, err = NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) + _, _, err = gitcmd.NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to unset git global config %s, err: %w", key, err) } return nil } - if IsErrorExitCode(err, 1) { + if gitcmd.IsErrorExitCode(err, 1) { // not exist return nil } diff --git a/modules/git/config_test.go b/modules/git/config_test.go index 911e0e0184..237feb67d5 100644 --- a/modules/git/config_test.go +++ b/modules/git/config_test.go @@ -8,13 +8,14 @@ import ( "strings" "testing" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" ) func gitConfigContains(sub string) bool { - if b, err := os.ReadFile(HomeDir() + "/.gitconfig"); err == nil { + if b, err := os.ReadFile(gitcmd.HomeDir() + "/.gitconfig"); err == nil { return strings.Contains(string(b), sub) } return false diff --git a/modules/git/diff.go b/modules/git/diff.go index 35d115be0e..d185cc9277 100644 --- a/modules/git/diff.go +++ b/modules/git/diff.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -34,8 +35,8 @@ func GetRawDiff(repo *Repository, commitID string, diffType RawDiffType, writer // GetReverseRawDiff dumps the reverse diff results of repository in given commit ID to io.Writer. func GetReverseRawDiff(ctx context.Context, repoPath, commitID string, writer io.Writer) error { stderr := new(bytes.Buffer) - cmd := NewCommand("show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID) - if err := cmd.Run(ctx, &RunOpts{ + cmd := gitcmd.NewCommand("show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID) + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdout: writer, Stderr: stderr, @@ -56,7 +57,7 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff files = append(files, file) } - cmd := NewCommand() + cmd := gitcmd.NewCommand() switch diffType { case RawDiffNormal: if len(startCommit) != 0 { @@ -89,7 +90,7 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff } stderr := new(bytes.Buffer) - if err = cmd.Run(repo.Ctx, &RunOpts{ + if err = cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: writer, Stderr: stderr, @@ -312,8 +313,8 @@ func GetAffectedFiles(repo *Repository, branchName, oldCommitID, newCommitID str affectedFiles := make([]string, 0, 32) // Run `git diff --name-only` to get the names of the changed files - err = NewCommand("diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID). - Run(repo.Ctx, &RunOpts{ + err = gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID). + Run(repo.Ctx, &gitcmd.RunOpts{ Env: env, Dir: repo.Path, Stdout: stdoutWriter, diff --git a/modules/git/git.go b/modules/git/git.go index 0a2e87a2ea..161fa42196 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -9,12 +9,12 @@ import ( "errors" "fmt" "os" - "os/exec" "path/filepath" "runtime" "strings" "time" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -33,10 +33,7 @@ type Features struct { SupportCheckAttrOnBare bool // >= 2.40 } -var ( - GitExecutable = "git" // the command name of git, will be updated to an absolute path during initialization - defaultFeatures *Features -) +var defaultFeatures *Features func (f *Features) CheckVersionAtLeast(atLeast string) bool { return f.gitVersion.Compare(version.Must(version.NewVersion(atLeast))) >= 0 @@ -60,7 +57,7 @@ func DefaultFeatures() *Features { } func loadGitVersionFeatures() (*Features, error) { - stdout, _, runErr := NewCommand("version").RunStdString(context.Background(), nil) + stdout, _, runErr := gitcmd.NewCommand("version").RunStdString(context.Background(), nil) if runErr != nil { return nil, runErr } @@ -129,32 +126,6 @@ func ensureGitVersion() error { return nil } -// SetExecutablePath changes the path of git executable and checks the file permission and version. -func SetExecutablePath(path string) error { - // If path is empty, we use the default value of GitExecutable "git" to search for the location of git. - if path != "" { - GitExecutable = path - } - absPath, err := exec.LookPath(GitExecutable) - if err != nil { - return fmt.Errorf("git not found: %w", err) - } - GitExecutable = absPath - return nil -} - -// HomeDir is the home dir for git to store the global config file used by Gitea internally -func HomeDir() string { - if setting.Git.HomePath == "" { - // strict check, make sure the git module is initialized correctly. - // attention: when the git module is called in gitea sub-command (serv/hook), the log module might not obviously show messages to users/developers. - // for example: if there is gitea git hook code calling git.NewCommand before git.InitXxx, the integration test won't show the real failure reasons. - log.Fatal("Unable to init Git's HomeDir, incorrect initialization of the setting and git modules") - return "" - } - return setting.Git.HomePath -} - // InitSimple initializes git module with a very simple step, no config changes, no global command arguments. // This method doesn't change anything to filesystem. At the moment, it is only used by some Gitea sub-commands. func InitSimple() error { @@ -167,10 +138,10 @@ func InitSimple() error { } if setting.Git.Timeout.Default > 0 { - defaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second + gitcmd.SetDefaultCommandExecutionTimeout(time.Duration(setting.Git.Timeout.Default) * time.Second) } - if err := SetExecutablePath(setting.Git.Path); err != nil { + if err := gitcmd.SetExecutablePath(setting.Git.Path); err != nil { return err } @@ -185,7 +156,7 @@ func InitSimple() error { // when git works with gnupg (commit signing), there should be a stable home for gnupg commands if _, ok := os.LookupEnv("GNUPGHOME"); !ok { - _ = os.Setenv("GNUPGHOME", filepath.Join(HomeDir(), ".gnupg")) + _ = os.Setenv("GNUPGHOME", filepath.Join(gitcmd.HomeDir(), ".gnupg")) } return nil } diff --git a/modules/git/command.go b/modules/git/gitcmd/command.go similarity index 99% rename from modules/git/command.go rename to modules/git/gitcmd/command.go index eeb987feb0..ed2f6fb647 100644 --- a/modules/git/command.go +++ b/modules/git/gitcmd/command.go @@ -2,7 +2,7 @@ // Copyright 2016 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package git +package gitcmd import ( "bytes" @@ -32,6 +32,10 @@ type TrustedCmdArgs []internal.CmdArg // defaultCommandExecutionTimeout default command execution timeout duration var defaultCommandExecutionTimeout = 360 * time.Second +func SetDefaultCommandExecutionTimeout(timeout time.Duration) { + defaultCommandExecutionTimeout = timeout +} + // DefaultLocale is the default LC_ALL to run git commands in. const DefaultLocale = "C" diff --git a/modules/git/command_race_test.go b/modules/git/gitcmd/command_race_test.go similarity index 98% rename from modules/git/command_race_test.go rename to modules/git/gitcmd/command_race_test.go index a6aa3a1580..aee2272808 100644 --- a/modules/git/command_race_test.go +++ b/modules/git/gitcmd/command_race_test.go @@ -3,7 +3,7 @@ //go:build race -package git +package gitcmd import ( "context" diff --git a/modules/git/command_test.go b/modules/git/gitcmd/command_test.go similarity index 83% rename from modules/git/command_test.go rename to modules/git/gitcmd/command_test.go index 85976e289e..544a97f64c 100644 --- a/modules/git/command_test.go +++ b/modules/git/gitcmd/command_test.go @@ -1,14 +1,30 @@ // Copyright 2022 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package git +package gitcmd import ( + "fmt" + "os" "testing" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/tempdir" + "github.com/stretchr/testify/assert" ) +func TestMain(m *testing.M) { + gitHomePath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("git-home") + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "unable to create temp dir: %v", err) + os.Exit(1) + } + defer cleanup() + + setting.Git.HomePath = gitHomePath +} + func TestRunWithContextStd(t *testing.T) { cmd := NewCommand("--version") stdout, stderr, err := cmd.RunStdString(t.Context(), &RunOpts{}) diff --git a/modules/git/gitcmd/env.go b/modules/git/gitcmd/env.go new file mode 100644 index 0000000000..269b51a253 --- /dev/null +++ b/modules/git/gitcmd/env.go @@ -0,0 +1,40 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitcmd + +import ( + "fmt" + "os/exec" + + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" +) + +var GitExecutable = "git" // the command name of git, will be updated to an absolute path during initialization + +// SetExecutablePath changes the path of git executable and checks the file permission and version. +func SetExecutablePath(path string) error { + // If path is empty, we use the default value of GitExecutable "git" to search for the location of git. + if path != "" { + GitExecutable = path + } + absPath, err := exec.LookPath(GitExecutable) + if err != nil { + return fmt.Errorf("git not found: %w", err) + } + GitExecutable = absPath + return nil +} + +// HomeDir is the home dir for git to store the global config file used by Gitea internally +func HomeDir() string { + if setting.Git.HomePath == "" { + // strict check, make sure the git module is initialized correctly. + // attention: when the git module is called in gitea sub-command (serv/hook), the log module might not obviously show messages to users/developers. + // for example: if there is gitea git hook code calling NewCommand before git.InitXxx, the integration test won't show the real failure reasons. + log.Fatal("Unable to init Git's HomeDir, incorrect initialization of the setting and git modules") + return "" + } + return setting.Git.HomePath +} diff --git a/modules/git/gitcmd/utils.go b/modules/git/gitcmd/utils.go new file mode 100644 index 0000000000..ee24eb6a9a --- /dev/null +++ b/modules/git/gitcmd/utils.go @@ -0,0 +1,14 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitcmd + +import "fmt" + +// ConcatenateError concatenats an error with stderr string +func ConcatenateError(err error, stderr string) error { + if len(stderr) == 0 { + return err + } + return fmt.Errorf("%w - %s", err, stderr) +} diff --git a/modules/git/grep.go b/modules/git/grep.go index 66711650c9..f5f6f12041 100644 --- a/modules/git/grep.go +++ b/modules/git/grep.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" ) @@ -60,7 +61,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO 2^@repo: go-gitea/gitea */ var results []*GrepResult - cmd := NewCommand("grep", "--null", "--break", "--heading", "--line-number", "--full-name") + cmd := gitcmd.NewCommand("grep", "--null", "--break", "--heading", "--line-number", "--full-name") cmd.AddOptionValues("--context", strconv.Itoa(opts.ContextLineNumber)) switch opts.GrepMode { case GrepModeExact: @@ -83,7 +84,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO cmd.AddDashesAndList(opts.PathspecList...) opts.MaxResultLimit = util.IfZero(opts.MaxResultLimit, 50) stderr := bytes.Buffer{} - err = cmd.Run(ctx, &RunOpts{ + err = cmd.Run(ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr, @@ -135,11 +136,11 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO }, }) // git grep exits by cancel (killed), usually it is caused by the limit of results - if IsErrorExitCode(err, -1) && stderr.Len() == 0 { + if gitcmd.IsErrorExitCode(err, -1) && stderr.Len() == 0 { return results, nil } // git grep exits with 1 if no results are found - if IsErrorExitCode(err, 1) && stderr.Len() == 0 { + if gitcmd.IsErrorExitCode(err, 1) && stderr.Len() == 0 { return nil, nil } if err != nil && !errors.Is(err, context.Canceled) { diff --git a/modules/git/log_name_status.go b/modules/git/log_name_status.go index dfdef38ef9..7a5192f58b 100644 --- a/modules/git/log_name_status.go +++ b/modules/git/log_name_status.go @@ -14,6 +14,7 @@ import ( "strings" "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/git/gitcmd" "github.com/djherbis/buffer" "github.com/djherbis/nio/v3" @@ -34,7 +35,7 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p _ = stdoutWriter.Close() } - cmd := NewCommand() + cmd := gitcmd.NewCommand() cmd.AddArguments("log", "--name-status", "-c", "--format=commit%x00%H %P%x00", "--parents", "--no-renames", "-t", "-z").AddDynamicArguments(head) var files []string @@ -64,13 +65,13 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p go func() { stderr := strings.Builder{} - err := cmd.Run(ctx, &RunOpts{ + err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: repository, Stdout: stdoutWriter, Stderr: &stderr, }) if err != nil { - _ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) return } diff --git a/modules/git/pipeline/catfile.go b/modules/git/pipeline/catfile.go index 5ddc36cc01..ced8532e6d 100644 --- a/modules/git/pipeline/catfile.go +++ b/modules/git/pipeline/catfile.go @@ -13,7 +13,7 @@ import ( "strings" "sync" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -25,8 +25,8 @@ func CatFileBatchCheck(ctx context.Context, shasToCheckReader *io.PipeReader, ca stderr := new(bytes.Buffer) var errbuf strings.Builder - cmd := git.NewCommand("cat-file", "--batch-check") - if err := cmd.Run(ctx, &git.RunOpts{ + cmd := gitcmd.NewCommand("cat-file", "--batch-check") + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdin: shasToCheckReader, Stdout: catFileCheckWriter, @@ -43,8 +43,8 @@ func CatFileBatchCheckAllObjects(ctx context.Context, catFileCheckWriter *io.Pip stderr := new(bytes.Buffer) var errbuf strings.Builder - cmd := git.NewCommand("cat-file", "--batch-check", "--batch-all-objects") - if err := cmd.Run(ctx, &git.RunOpts{ + cmd := gitcmd.NewCommand("cat-file", "--batch-check", "--batch-all-objects") + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: catFileCheckWriter, Stderr: stderr, @@ -64,7 +64,7 @@ func CatFileBatch(ctx context.Context, shasToBatchReader *io.PipeReader, catFile stderr := new(bytes.Buffer) var errbuf strings.Builder - if err := git.NewCommand("cat-file", "--batch").Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("cat-file", "--batch").Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: catFileBatchWriter, Stdin: shasToBatchReader, diff --git a/modules/git/pipeline/lfs_nogogit.go b/modules/git/pipeline/lfs_nogogit.go index c5eed73701..d2f147854d 100644 --- a/modules/git/pipeline/lfs_nogogit.go +++ b/modules/git/pipeline/lfs_nogogit.go @@ -14,6 +14,7 @@ import ( "sync" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) // FindLFSFile finds commits that contain a provided pointer file hash @@ -32,13 +33,13 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err go func() { stderr := strings.Builder{} - err := git.NewCommand("rev-list", "--all").Run(repo.Ctx, &git.RunOpts{ + err := gitcmd.NewCommand("rev-list", "--all").Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: revListWriter, Stderr: &stderr, }) if err != nil { - _ = revListWriter.CloseWithError(git.ConcatenateError(err, (&stderr).String())) + _ = revListWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) } else { _ = revListWriter.Close() } diff --git a/modules/git/pipeline/namerev.go b/modules/git/pipeline/namerev.go index 06731c5051..0081f7a26d 100644 --- a/modules/git/pipeline/namerev.go +++ b/modules/git/pipeline/namerev.go @@ -11,7 +11,7 @@ import ( "strings" "sync" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) // NameRevStdin runs name-rev --stdin @@ -22,7 +22,7 @@ func NameRevStdin(ctx context.Context, shasToNameReader *io.PipeReader, nameRevS stderr := new(bytes.Buffer) var errbuf strings.Builder - if err := git.NewCommand("name-rev", "--stdin", "--name-only", "--always").Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("name-rev", "--stdin", "--name-only", "--always").Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: nameRevStdinWriter, Stdin: shasToNameReader, diff --git a/modules/git/pipeline/revlist.go b/modules/git/pipeline/revlist.go index 31627a0f3a..9d4ff75434 100644 --- a/modules/git/pipeline/revlist.go +++ b/modules/git/pipeline/revlist.go @@ -12,7 +12,7 @@ import ( "strings" "sync" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -23,8 +23,8 @@ func RevListAllObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sy stderr := new(bytes.Buffer) var errbuf strings.Builder - cmd := git.NewCommand("rev-list", "--objects", "--all") - if err := cmd.Run(ctx, &git.RunOpts{ + cmd := gitcmd.NewCommand("rev-list", "--objects", "--all") + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: basePath, Stdout: revListWriter, Stderr: stderr, @@ -42,11 +42,11 @@ func RevListObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync. defer revListWriter.Close() stderr := new(bytes.Buffer) var errbuf strings.Builder - cmd := git.NewCommand("rev-list", "--objects").AddDynamicArguments(headSHA) + cmd := gitcmd.NewCommand("rev-list", "--objects").AddDynamicArguments(headSHA) if baseSHA != "" { cmd = cmd.AddArguments("--not").AddDynamicArguments(baseSHA) } - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: revListWriter, Stderr: stderr, diff --git a/modules/git/remote.go b/modules/git/remote.go index 283d26484b..9f12142f91 100644 --- a/modules/git/remote.go +++ b/modules/git/remote.go @@ -9,19 +9,20 @@ import ( "net/url" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" ) // GetRemoteAddress returns remote url of git repository in the repoPath with special remote name func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) { - var cmd *Command + var cmd *gitcmd.Command if DefaultFeatures().CheckVersionAtLeast("2.7") { - cmd = NewCommand("remote", "get-url").AddDynamicArguments(remoteName) + cmd = gitcmd.NewCommand("remote", "get-url").AddDynamicArguments(remoteName) } else { - cmd = NewCommand("config", "--get").AddDynamicArguments("remote." + remoteName + ".url") + cmd = gitcmd.NewCommand("config", "--get").AddDynamicArguments("remote." + remoteName + ".url") } - result, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + result, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return "", err } diff --git a/modules/git/repo.go b/modules/git/repo.go index 8e7b427bd0..38cb4592a0 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -17,6 +17,7 @@ import ( "strings" "time" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/proxy" "code.gitea.io/gitea/modules/setting" ) @@ -40,9 +41,9 @@ func (repo *Repository) GetAllCommitsCount() (int64, error) { func (repo *Repository) ShowPrettyFormatLogToList(ctx context.Context, revisionRange string) ([]*Commit, error) { // avoid: ambiguous argument 'refs/a...refs/b': unknown revision or path not in the working tree. Use '--': 'git [...] -- [...]' - logs, _, err := NewCommand("log").AddArguments(prettyLogFormat). + logs, _, err := gitcmd.NewCommand("log").AddArguments(prettyLogFormat). AddDynamicArguments(revisionRange).AddArguments("--"). - RunStdBytes(ctx, &RunOpts{Dir: repo.Path}) + RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -70,7 +71,7 @@ func (repo *Repository) parsePrettyFormatLogToList(logs []byte) ([]*Commit, erro // IsRepoURLAccessible checks if given repository URL is accessible. func IsRepoURLAccessible(ctx context.Context, url string) bool { - _, _, err := NewCommand("ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(ctx, nil) + _, _, err := gitcmd.NewCommand("ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(ctx, nil) return err == nil } @@ -81,7 +82,7 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma return err } - cmd := NewCommand("init") + cmd := gitcmd.NewCommand("init") if !IsValidObjectFormat(objectFormatName) { return fmt.Errorf("invalid object format: %s", objectFormatName) @@ -93,15 +94,15 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma if bare { cmd.AddArguments("--bare") } - _, _, err = cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + _, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) return err } // IsEmpty Check if repository is empty. func (repo *Repository) IsEmpty() (bool, error) { var errbuf, output strings.Builder - if err := NewCommand().AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("rev-list", "-n", "1", "--all"). - Run(repo.Ctx, &RunOpts{ + if err := gitcmd.NewCommand().AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("rev-list", "-n", "1", "--all"). + Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: &output, Stderr: &errbuf, @@ -137,7 +138,7 @@ func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error { return err } - cmd := NewCommand().AddArguments("clone") + cmd := gitcmd.NewCommand().AddArguments("clone") if opts.SkipTLSVerify { cmd.AddArguments("-c", "http.sslVerify=false") } @@ -178,13 +179,13 @@ func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error { } stderr := new(bytes.Buffer) - if err = cmd.Run(ctx, &RunOpts{ + if err = cmd.Run(ctx, &gitcmd.RunOpts{ Timeout: opts.Timeout, Env: envs, Stdout: io.Discard, Stderr: stderr, }); err != nil { - return ConcatenateError(err, stderr.String()) + return gitcmd.ConcatenateError(err, stderr.String()) } return nil } @@ -201,7 +202,7 @@ type PushOptions struct { // Push pushs local commits to given remote branch. func Push(ctx context.Context, repoPath string, opts PushOptions) error { - cmd := NewCommand("push") + cmd := gitcmd.NewCommand("push") if opts.Force { cmd.AddArguments("-f") } @@ -214,7 +215,7 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error { } cmd.AddDashesAndList(remoteBranchArgs...) - stdout, stderr, err := cmd.RunStdString(ctx, &RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath}) + stdout, stderr, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath}) if err != nil { if strings.Contains(stderr, "non-fast-forward") { return &ErrPushOutOfDate{StdOut: stdout, StdErr: stderr, Err: err} @@ -233,8 +234,8 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error { // GetLatestCommitTime returns time for latest commit in repository (across all branches) func GetLatestCommitTime(ctx context.Context, repoPath string) (time.Time, error) { - cmd := NewCommand("for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)") - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + cmd := gitcmd.NewCommand("for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)") + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return time.Time{}, err } @@ -250,9 +251,9 @@ type DivergeObject struct { // GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (do DivergeObject, err error) { - cmd := NewCommand("rev-list", "--count", "--left-right"). + cmd := gitcmd.NewCommand("rev-list", "--count", "--left-right"). AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--") - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return do, err } @@ -281,23 +282,23 @@ func (repo *Repository) CreateBundle(ctx context.Context, commit string, out io. defer cleanup() env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(repo.Path, "objects")) - _, _, err = NewCommand("init", "--bare").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env}) + _, _, err = gitcmd.NewCommand("init", "--bare").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env}) if err != nil { return err } - _, _, err = NewCommand("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx, &RunOpts{Dir: tmp, Env: env}) + _, _, err = gitcmd.NewCommand("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env}) if err != nil { return err } - _, _, err = NewCommand("branch", "-m", "bundle").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env}) + _, _, err = gitcmd.NewCommand("branch", "-m", "bundle").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env}) if err != nil { return err } tmpFile := filepath.Join(tmp, "bundle") - _, _, err = NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env}) + _, _, err = gitcmd.NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env}) if err != nil { return err } diff --git a/modules/git/repo_archive.go b/modules/git/repo_archive.go index 0b2f6f2a45..e12300345f 100644 --- a/modules/git/repo_archive.go +++ b/modules/git/repo_archive.go @@ -10,6 +10,8 @@ import ( "io" "path/filepath" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // ArchiveType archive types @@ -53,7 +55,7 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t return fmt.Errorf("unknown format: %v", format) } - cmd := NewCommand("archive") + cmd := gitcmd.NewCommand("archive") if usePrefix { cmd.AddOptionFormat("--prefix=%s", filepath.Base(strings.TrimSuffix(repo.Path, ".git"))+"/") } @@ -61,13 +63,13 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t cmd.AddDynamicArguments(commitID) var stderr strings.Builder - err := cmd.Run(ctx, &RunOpts{ + err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: target, Stderr: &stderr, }) if err != nil { - return ConcatenateError(err, stderr.String()) + return gitcmd.ConcatenateError(err, stderr.String()) } return nil } diff --git a/modules/git/repo_blame.go b/modules/git/repo_blame.go index 6941a76c42..04f74049aa 100644 --- a/modules/git/repo_blame.go +++ b/modules/git/repo_blame.go @@ -5,14 +5,16 @@ package git import ( "fmt" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // LineBlame returns the latest commit at the given line func (repo *Repository) LineBlame(revision, path, file string, line uint) (*Commit, error) { - res, _, err := NewCommand("blame"). + res, _, err := gitcmd.NewCommand("blame"). AddOptionFormat("-L %d,%d", line, line). AddOptionValues("-p", revision). - AddDashesAndList(file).RunStdString(repo.Ctx, &RunOpts{Dir: path}) + AddDashesAndList(file).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: path}) if err != nil { return nil, err } diff --git a/modules/git/repo_branch.go b/modules/git/repo_branch.go index eac2031003..5d4c05bb28 100644 --- a/modules/git/repo_branch.go +++ b/modules/git/repo_branch.go @@ -8,6 +8,8 @@ import ( "context" "errors" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // BranchPrefix base dir of the branch information file store on git @@ -15,7 +17,7 @@ const BranchPrefix = "refs/heads/" // IsReferenceExist returns true if given reference exists in the repository. func IsReferenceExist(ctx context.Context, repoPath, name string) bool { - _, _, err := NewCommand("show-ref", "--verify").AddDashesAndList(name).RunStdString(ctx, &RunOpts{Dir: repoPath}) + _, _, err := gitcmd.NewCommand("show-ref", "--verify").AddDashesAndList(name).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) return err == nil } @@ -25,7 +27,7 @@ func IsBranchExist(ctx context.Context, repoPath, name string) bool { } func GetDefaultBranch(ctx context.Context, repoPath string) (string, error) { - stdout, _, err := NewCommand("symbolic-ref", "HEAD").RunStdString(ctx, &RunOpts{Dir: repoPath}) + stdout, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return "", err } @@ -43,7 +45,7 @@ type DeleteBranchOptions struct { // DeleteBranch delete a branch by name on repository. func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) error { - cmd := NewCommand("branch") + cmd := gitcmd.NewCommand("branch") if opts.Force { cmd.AddArguments("-D") @@ -52,35 +54,35 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro } cmd.AddDashesAndList(name) - _, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // CreateBranch create a new branch func (repo *Repository) CreateBranch(branch, oldbranchOrCommit string) error { - cmd := NewCommand("branch") + cmd := gitcmd.NewCommand("branch") cmd.AddDashesAndList(branch, oldbranchOrCommit) - _, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // AddRemote adds a new remote to repository. func (repo *Repository) AddRemote(name, url string, fetch bool) error { - cmd := NewCommand("remote", "add") + cmd := gitcmd.NewCommand("remote", "add") if fetch { cmd.AddArguments("-f") } cmd.AddDynamicArguments(name, url) - _, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // RenameBranch rename a branch func (repo *Repository) RenameBranch(from, to string) error { - _, _, err := NewCommand("branch", "-m").AddDynamicArguments(from, to).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("branch", "-m").AddDynamicArguments(from, to).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } diff --git a/modules/git/repo_branch_nogogit.go b/modules/git/repo_branch_nogogit.go index 0d11198523..255c2974e9 100644 --- a/modules/git/repo_branch_nogogit.go +++ b/modules/git/repo_branch_nogogit.go @@ -13,6 +13,7 @@ import ( "io" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -70,25 +71,25 @@ func (repo *Repository) IsBranchExist(name string) bool { // GetBranchNames returns branches from the repository, skipping "skip" initial branches and // returning at most "limit" branches, or all branches if "limit" is 0. func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) { - return callShowRef(repo.Ctx, repo.Path, BranchPrefix, TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit) + return callShowRef(repo.Ctx, repo.Path, BranchPrefix, gitcmd.TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit) } // WalkReferences walks all the references from the repository // refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty. func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) { - var args TrustedCmdArgs + var args gitcmd.TrustedCmdArgs switch refType { case ObjectTag: - args = TrustedCmdArgs{TagPrefix, "--sort=-taggerdate"} + args = gitcmd.TrustedCmdArgs{TagPrefix, "--sort=-taggerdate"} case ObjectBranch: - args = TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"} + args = gitcmd.TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"} } return WalkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn) } // callShowRef return refs, if limit = 0 it will not limit -func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) { +func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs gitcmd.TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) { countAll, err = WalkShowRef(ctx, repoPath, extraArgs, skip, limit, func(_, branchName string) error { branchName = strings.TrimPrefix(branchName, trimPrefix) branchNames = append(branchNames, branchName) @@ -98,7 +99,7 @@ func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs Tru return branchNames, countAll, err } -func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) { +func WalkShowRef(ctx context.Context, repoPath string, extraArgs gitcmd.TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) { stdoutReader, stdoutWriter := io.Pipe() defer func() { _ = stdoutReader.Close() @@ -107,9 +108,9 @@ func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, go func() { stderrBuilder := &strings.Builder{} - args := TrustedCmdArgs{"for-each-ref", "--format=%(objectname) %(refname)"} + args := gitcmd.TrustedCmdArgs{"for-each-ref", "--format=%(objectname) %(refname)"} args = append(args, extraArgs...) - err := NewCommand(args...).Run(ctx, &RunOpts{ + err := gitcmd.NewCommand(args...).Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdout: stdoutWriter, Stderr: stderrBuilder, @@ -119,7 +120,7 @@ func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, _ = stdoutWriter.Close() return } - _ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderrBuilder.String())) } else { _ = stdoutWriter.Close() } diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 4066a1ca7b..6e5911f1dd 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -12,6 +12,7 @@ import ( "strings" "code.gitea.io/gitea/modules/cache" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" ) @@ -59,7 +60,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com relpath = `\` + relpath } - stdout, _, runErr := NewCommand("log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, runErr := gitcmd.NewCommand("log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } @@ -74,7 +75,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com // GetCommitByPath returns the last commit of relative path. func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) { - stdout, _, runErr := NewCommand("log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, runErr := gitcmd.NewCommand("log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } @@ -91,7 +92,7 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) { // commitsByRangeWithTime returns the specific page commits before current revision, with not, since, until support func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int, not, since, until string) ([]*Commit, error) { - cmd := NewCommand("log"). + cmd := gitcmd.NewCommand("log"). AddOptionFormat("--skip=%d", (page-1)*pageSize). AddOptionFormat("--max-count=%d", pageSize). AddArguments(prettyLogFormat). @@ -107,7 +108,7 @@ func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int, cmd.AddOptionFormat("--until=%s", until) } - stdout, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -117,7 +118,7 @@ func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int, func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([]*Commit, error) { // add common arguments to git command - addCommonSearchArgs := func(c *Command) { + addCommonSearchArgs := func(c *gitcmd.Command) { // ignore case c.AddArguments("-i") @@ -141,7 +142,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([ } // create new git log command with limit of 100 commits - cmd := NewCommand("log", "-100", prettyLogFormat).AddDynamicArguments(id.String()) + cmd := gitcmd.NewCommand("log", "-100", prettyLogFormat).AddDynamicArguments(id.String()) // pretend that all refs along with HEAD were listed on command line as // https://git-scm.com/docs/git-log#Documentation/git-log.txt---all @@ -161,7 +162,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([ // search for commits matching given constraints and keywords in commit msg addCommonSearchArgs(cmd) - stdout, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -175,14 +176,14 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([ // ignore anything not matching a valid sha pattern if id.Type().IsValid(v) { // create new git log command with 1 commit limit - hashCmd := NewCommand("log", "-1", prettyLogFormat) + hashCmd := gitcmd.NewCommand("log", "-1", prettyLogFormat) // add previous arguments except for --grep and --all addCommonSearchArgs(hashCmd) // add keyword as hashCmd.AddDynamicArguments(v) // search with given constraints for commit matching sha hash of v - hashMatching, _, err := hashCmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + hashMatching, _, err := hashCmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil || bytes.Contains(stdout, hashMatching) { continue } @@ -197,7 +198,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([ // FileChangedBetweenCommits Returns true if the file changed between commit IDs id1 and id2 // You must ensure that id1 and id2 are valid commit ids. func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bool, error) { - stdout, _, err := NewCommand("diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return false, err } @@ -232,7 +233,7 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) }() go func() { stderr := strings.Builder{} - gitCmd := NewCommand("rev-list"). + gitCmd := gitcmd.NewCommand("rev-list"). AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize). AddOptionFormat("--skip=%d", (opts.Page-1)*setting.Git.CommitsRangeSize) gitCmd.AddDynamicArguments(opts.Revision) @@ -248,13 +249,13 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) } gitCmd.AddDashesAndList(opts.File) - err := gitCmd.Run(repo.Ctx, &RunOpts{ + err := gitCmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr, }) if err != nil { - _ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) } else { _ = stdoutWriter.Close() } @@ -290,11 +291,11 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) // FilesCountBetween return the number of files changed between two commits func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) { - stdout, _, err := NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID+"..."+endCommitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID+"..."+endCommitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil && strings.Contains(err.Error(), "no merge base") { // git >= 2.28 now returns an error if startCommitID and endCommitID have become unrelated. // previously it would return the results of git diff --name-only startCommitID endCommitID so let's try that... - stdout, _, err = NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } if err != nil { return 0, err @@ -308,13 +309,13 @@ func (repo *Repository) CommitsBetween(last, before *Commit) ([]*Commit, error) var stdout []byte var err error if before == nil { - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } else { - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil && strings.Contains(err.Error(), "no merge base") { // future versions of git >= 2.28 are likely to return an error if before and last have become unrelated. // previously it would return the results of git rev-list before last so let's try that... - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } } if err != nil { @@ -328,22 +329,22 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in var stdout []byte var err error if before == nil { - stdout, _, err = NewCommand("rev-list"). + stdout, _, err = gitcmd.NewCommand("rev-list"). AddOptionValues("--max-count", strconv.Itoa(limit)). AddOptionValues("--skip", strconv.Itoa(skip)). - AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } else { - stdout, _, err = NewCommand("rev-list"). + stdout, _, err = gitcmd.NewCommand("rev-list"). AddOptionValues("--max-count", strconv.Itoa(limit)). AddOptionValues("--skip", strconv.Itoa(skip)). - AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil && strings.Contains(err.Error(), "no merge base") { // future versions of git >= 2.28 are likely to return an error if before and last have become unrelated. // previously it would return the results of git rev-list --max-count n before last so let's try that... - stdout, _, err = NewCommand("rev-list"). + stdout, _, err = gitcmd.NewCommand("rev-list"). AddOptionValues("--max-count", strconv.Itoa(limit)). AddOptionValues("--skip", strconv.Itoa(skip)). - AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } } if err != nil { @@ -358,13 +359,13 @@ func (repo *Repository) CommitsBetweenNotBase(last, before *Commit, baseBranch s var stdout []byte var err error if before == nil { - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } else { - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil && strings.Contains(err.Error(), "no merge base") { // future versions of git >= 2.28 are likely to return an error if before and last have become unrelated. // previously it would return the results of git rev-list before last so let's try that... - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } } if err != nil { @@ -410,13 +411,13 @@ func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) { // commitsBefore the limit is depth, not total number of returned commits. func (repo *Repository) commitsBefore(id ObjectID, limit int) ([]*Commit, error) { - cmd := NewCommand("log", prettyLogFormat) + cmd := gitcmd.NewCommand("log", prettyLogFormat) if limit > 0 { cmd.AddOptionFormat("-%d", limit) } cmd.AddDynamicArguments(id.String()) - stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } @@ -453,10 +454,10 @@ func (repo *Repository) getCommitsBeforeLimit(id ObjectID, num int) ([]*Commit, func (repo *Repository) getBranches(env []string, commitID string, limit int) ([]string, error) { if DefaultFeatures().CheckVersionAtLeast("2.7.0") { - stdout, _, err := NewCommand("for-each-ref", "--format=%(refname:strip=2)"). + stdout, _, err := gitcmd.NewCommand("for-each-ref", "--format=%(refname:strip=2)"). AddOptionFormat("--count=%d", limit). AddOptionValues("--contains", commitID, BranchPrefix). - RunStdString(repo.Ctx, &RunOpts{ + RunStdString(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Env: env, }) @@ -468,7 +469,7 @@ func (repo *Repository) getBranches(env []string, commitID string, limit int) ([ return branches, nil } - stdout, _, err := NewCommand("branch").AddOptionValues("--contains", commitID).RunStdString(repo.Ctx, &RunOpts{ + stdout, _, err := gitcmd.NewCommand("branch").AddOptionValues("--contains", commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Env: env, }) @@ -510,7 +511,7 @@ func (repo *Repository) GetCommitsFromIDs(commitIDs []string) []*Commit { // IsCommitInBranch check if the commit is on the branch func (repo *Repository) IsCommitInBranch(commitID, branch string) (r bool, err error) { - stdout, _, err := NewCommand("branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return false, err } @@ -536,10 +537,10 @@ func (repo *Repository) AddLastCommitCache(cacheKey, fullName, sha string) error // GetCommitBranchStart returns the commit where the branch diverged func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID string) (string, error) { - cmd := NewCommand("log", prettyLogFormat) + cmd := gitcmd.NewCommand("log", prettyLogFormat) cmd.AddDynamicArguments(endCommitID) - stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &RunOpts{ + stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Env: env, }) diff --git a/modules/git/repo_commit_gogit.go b/modules/git/repo_commit_gogit.go index a88902e209..c830e52b7e 100644 --- a/modules/git/repo_commit_gogit.go +++ b/modules/git/repo_commit_gogit.go @@ -9,6 +9,8 @@ package git import ( "strings" + "code.gitea.io/gitea/modules/git/gitcmd" + "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/hash" "github.com/go-git/go-git/v5/plumbing/object" @@ -59,7 +61,7 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) { } } - actualCommitID, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + actualCommitID, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) actualCommitID = strings.TrimSpace(actualCommitID) if err != nil { if strings.Contains(err.Error(), "unknown revision or path") || diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go index 3ead3e2216..f00d407ae0 100644 --- a/modules/git/repo_commit_nogogit.go +++ b/modules/git/repo_commit_nogogit.go @@ -11,12 +11,13 @@ import ( "io" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) // ResolveReference resolves a name to a reference func (repo *Repository) ResolveReference(name string) (string, error) { - stdout, _, err := NewCommand("show-ref", "--hash").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("show-ref", "--hash").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { if strings.Contains(err.Error(), "not a valid ref") { return "", ErrNotExist{name, ""} @@ -52,13 +53,13 @@ func (repo *Repository) GetRefCommitID(name string) (string, error) { // SetReference sets the commit ID string of given reference (e.g. branch or tag). func (repo *Repository) SetReference(name, commitID string) error { - _, _, err := NewCommand("update-ref").AddDynamicArguments(name, commitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("update-ref").AddDynamicArguments(name, commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // RemoveReference removes the given reference (e.g. branch or tag). func (repo *Repository) RemoveReference(name string) error { - _, _, err := NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } @@ -68,7 +69,7 @@ func (repo *Repository) IsCommitExist(name string) bool { log.Error("IsCommitExist: %v", err) return false } - _, _, err := NewCommand("cat-file", "-e").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("cat-file", "-e").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err == nil } diff --git a/modules/git/repo_commitgraph.go b/modules/git/repo_commitgraph.go index 62c6378054..331c799b33 100644 --- a/modules/git/repo_commitgraph.go +++ b/modules/git/repo_commitgraph.go @@ -6,13 +6,15 @@ package git import ( "context" "fmt" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // WriteCommitGraph write commit graph to speed up repo access // this requires git v2.18 to be installed func WriteCommitGraph(ctx context.Context, repoPath string) error { if DefaultFeatures().CheckVersionAtLeast("2.18") { - if _, _, err := NewCommand("commit-graph", "write").RunStdString(ctx, &RunOpts{Dir: repoPath}); err != nil { + if _, _, err := gitcmd.NewCommand("commit-graph", "write").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}); err != nil { return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err) } } diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go index 56251a87a0..69a7314d5c 100644 --- a/modules/git/repo_compare.go +++ b/modules/git/repo_compare.go @@ -16,6 +16,8 @@ import ( "regexp" "strconv" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // GetMergeBase checks and returns merge base of two branches and the reference used as base. @@ -27,13 +29,13 @@ func (repo *Repository) GetMergeBase(tmpRemote, base, head string) (string, stri if tmpRemote != "origin" { tmpBaseName := RemotePrefix + tmpRemote + "/tmp_" + base // Fetch commit into a temporary branch in order to be able to handle commits and tags - _, _, err := NewCommand("fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base+":"+tmpBaseName).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base+":"+tmpBaseName).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err == nil { base = tmpBaseName } } - stdout, _, err := NewCommand("merge-base").AddDashesAndList(base, head).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("merge-base").AddDashesAndList(base, head).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return strings.TrimSpace(stdout), base, err } @@ -61,8 +63,8 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis } // avoid: ambiguous argument 'refs/a...refs/b': unknown revision or path not in the working tree. Use '--': 'git [...] -- [...]' - if err := NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base+separator+head).AddArguments("--"). - Run(repo.Ctx, &RunOpts{ + if err := gitcmd.NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base+separator+head).AddArguments("--"). + Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, Stderr: stderr, @@ -72,7 +74,7 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis // previously it would return the results of git diff -z --name-only base head so let's try that... w = &lineCountWriter{} stderr.Reset() - if err = NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base, head).AddArguments("--").Run(repo.Ctx, &RunOpts{ + if err = gitcmd.NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base, head).AddArguments("--").Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, Stderr: stderr, @@ -87,13 +89,13 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis // GetDiffShortStatByCmdArgs counts number of changed files, number of additions and deletions // TODO: it can be merged with another "GetDiffShortStat" in the future -func GetDiffShortStatByCmdArgs(ctx context.Context, repoPath string, trustedArgs TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) { +func GetDiffShortStatByCmdArgs(ctx context.Context, repoPath string, trustedArgs gitcmd.TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) { // Now if we call: // $ git diff --shortstat 1ebb35b98889ff77299f24d82da426b434b0cca0...788b8b1440462d477f45b0088875 // we get: // " 9902 files changed, 2034198 insertions(+), 298800 deletions(-)\n" - cmd := NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...) - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + cmd := gitcmd.NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...) + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return 0, 0, 0, err } @@ -139,8 +141,8 @@ func parseDiffStat(stdout string) (numFiles, totalAdditions, totalDeletions int, // GetDiff generates and returns patch data between given revisions, optimized for human readability func (repo *Repository) GetDiff(compareArg string, w io.Writer) error { stderr := new(bytes.Buffer) - return NewCommand("diff", "-p").AddDynamicArguments(compareArg). - Run(repo.Ctx, &RunOpts{ + return gitcmd.NewCommand("diff", "-p").AddDynamicArguments(compareArg). + Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, Stderr: stderr, @@ -149,7 +151,7 @@ func (repo *Repository) GetDiff(compareArg string, w io.Writer) error { // GetDiffBinary generates and returns patch data between given revisions, including binary diffs. func (repo *Repository) GetDiffBinary(compareArg string, w io.Writer) error { - return NewCommand("diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(repo.Ctx, &RunOpts{ + return gitcmd.NewCommand("diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, }) @@ -158,8 +160,8 @@ func (repo *Repository) GetDiffBinary(compareArg string, w io.Writer) error { // GetPatch generates and returns format-patch data between given revisions, able to be used with `git apply` func (repo *Repository) GetPatch(compareArg string, w io.Writer) error { stderr := new(bytes.Buffer) - return NewCommand("format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg). - Run(repo.Ctx, &RunOpts{ + return gitcmd.NewCommand("format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg). + Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, Stderr: stderr, @@ -174,13 +176,13 @@ func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, err if err != nil { return nil, err } - cmd := NewCommand("diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z") + cmd := gitcmd.NewCommand("diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z") if base == objectFormat.EmptyObjectID().String() { cmd.AddDynamicArguments(head) } else { cmd.AddDynamicArguments(base, head) } - stdout, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } diff --git a/modules/git/repo_gpg.go b/modules/git/repo_gpg.go index 0021a7bda7..a999d2dbc6 100644 --- a/modules/git/repo_gpg.go +++ b/modules/git/repo_gpg.go @@ -9,6 +9,7 @@ import ( "os" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/process" ) @@ -42,7 +43,7 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings, Sign: true, } - value, _, _ := NewCommand("config", "--get", "commit.gpgsign").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) sign, valid := ParseBool(strings.TrimSpace(value)) if !sign || !valid { gpgSettings.Sign = false @@ -50,16 +51,16 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings, return gpgSettings, nil } - signingKey, _, _ := NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) gpgSettings.KeyID = strings.TrimSpace(signingKey) - format, _, _ := NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + format, _, _ := gitcmd.NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) gpgSettings.Format = strings.TrimSpace(format) - defaultEmail, _, _ := NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + defaultEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) gpgSettings.Email = strings.TrimSpace(defaultEmail) - defaultName, _, _ := NewCommand("config", "--get", "user.name").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + defaultName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) gpgSettings.Name = strings.TrimSpace(defaultName) if err := gpgSettings.LoadPublicKeyContent(); err != nil { diff --git a/modules/git/repo_index.go b/modules/git/repo_index.go index 4879121a41..e7b3792d95 100644 --- a/modules/git/repo_index.go +++ b/modules/git/repo_index.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" ) @@ -21,7 +22,7 @@ func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string) } if len(treeish) != objectFormat.FullLength() { - res, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return err } @@ -41,7 +42,7 @@ func (repo *Repository) readTreeToIndex(id ObjectID, indexFilename ...string) er if len(indexFilename) > 0 { env = append(os.Environ(), "GIT_INDEX_FILE="+indexFilename[0]) } - _, _, err := NewCommand("read-tree").AddDynamicArguments(id.String()).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path, Env: env}) + _, _, err := gitcmd.NewCommand("read-tree").AddDynamicArguments(id.String()).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path, Env: env}) if err != nil { return err } @@ -74,14 +75,14 @@ func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (tmpIndexFilena // EmptyIndex empties the index func (repo *Repository) EmptyIndex() error { - _, _, err := NewCommand("read-tree", "--empty").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("read-tree", "--empty").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // LsFiles checks if the given filenames are in the index func (repo *Repository) LsFiles(filenames ...string) ([]string, error) { - cmd := NewCommand("ls-files", "-z").AddDashesAndList(filenames...) - res, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + cmd := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...) + res, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -99,7 +100,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error { if err != nil { return err } - cmd := NewCommand("update-index", "--remove", "-z", "--index-info") + cmd := gitcmd.NewCommand("update-index", "--remove", "-z", "--index-info") stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) buffer := new(bytes.Buffer) @@ -109,7 +110,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error { buffer.WriteString("0 blob " + objectFormat.EmptyObjectID().String() + "\t" + file + "\000") } } - return cmd.Run(repo.Ctx, &RunOpts{ + return cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdin: bytes.NewReader(buffer.Bytes()), Stdout: stdout, @@ -125,7 +126,7 @@ type IndexObjectInfo struct { // AddObjectsToIndex adds the provided object hashes to the index at the provided filenames func (repo *Repository) AddObjectsToIndex(objects ...IndexObjectInfo) error { - cmd := NewCommand("update-index", "--add", "--replace", "-z", "--index-info") + cmd := gitcmd.NewCommand("update-index", "--add", "--replace", "-z", "--index-info") stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) buffer := new(bytes.Buffer) @@ -133,7 +134,7 @@ func (repo *Repository) AddObjectsToIndex(objects ...IndexObjectInfo) error { // using format: mode SP type SP sha1 TAB path buffer.WriteString(object.Mode + " blob " + object.Object.String() + "\t" + object.Filename + "\000") } - return cmd.Run(repo.Ctx, &RunOpts{ + return cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdin: bytes.NewReader(buffer.Bytes()), Stdout: stdout, @@ -148,7 +149,7 @@ func (repo *Repository) AddObjectToIndex(mode string, object ObjectID, filename // WriteTree writes the current index as a tree to the object db and returns its hash func (repo *Repository) WriteTree() (*Tree, error) { - stdout, _, runErr := NewCommand("write-tree").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, runErr := gitcmd.NewCommand("write-tree").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } diff --git a/modules/git/repo_object.go b/modules/git/repo_object.go index 08e0413311..e8f6510c23 100644 --- a/modules/git/repo_object.go +++ b/modules/git/repo_object.go @@ -8,6 +8,8 @@ import ( "bytes" "io" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // ObjectType git object type @@ -66,15 +68,15 @@ func (repo *Repository) HashObject(reader io.Reader) (ObjectID, error) { } func (repo *Repository) hashObject(reader io.Reader, save bool) (string, error) { - var cmd *Command + var cmd *gitcmd.Command if save { - cmd = NewCommand("hash-object", "-w", "--stdin") + cmd = gitcmd.NewCommand("hash-object", "-w", "--stdin") } else { - cmd = NewCommand("hash-object", "--stdin") + cmd = gitcmd.NewCommand("hash-object", "--stdin") } stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) - err := cmd.Run(repo.Ctx, &RunOpts{ + err := cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdin: reader, Stdout: stdout, diff --git a/modules/git/repo_ref.go b/modules/git/repo_ref.go index 554f9f73e1..577e17c45d 100644 --- a/modules/git/repo_ref.go +++ b/modules/git/repo_ref.go @@ -7,6 +7,7 @@ import ( "context" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" ) @@ -18,7 +19,7 @@ func (repo *Repository) GetRefs() ([]*Reference, error) { // ListOccurrences lists all refs of the given refType the given commit appears in sorted by creation date DESC // refType should only be a literal "branch" or "tag" and nothing else func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA string) ([]string, error) { - cmd := NewCommand() + cmd := gitcmd.NewCommand() switch refType { case "branch": cmd.AddArguments("branch") @@ -27,7 +28,7 @@ func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA default: return nil, util.NewInvalidArgumentErrorf(`can only use "branch" or "tag" for refType, but got %q`, refType) } - stdout, _, err := cmd.AddArguments("--no-color", "--sort=-creatordate", "--contains").AddDynamicArguments(commitSHA).RunStdString(ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := cmd.AddArguments("--no-color", "--sort=-creatordate", "--contains").AddDynamicArguments(commitSHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } diff --git a/modules/git/repo_ref_nogogit.go b/modules/git/repo_ref_nogogit.go index 8d34713eaf..784efecc65 100644 --- a/modules/git/repo_ref_nogogit.go +++ b/modules/git/repo_ref_nogogit.go @@ -9,6 +9,8 @@ import ( "bufio" "io" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // GetRefsFiltered returns all references of the repository that matches patterm exactly or starting with. @@ -21,13 +23,13 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) { go func() { stderrBuilder := &strings.Builder{} - err := NewCommand("for-each-ref").Run(repo.Ctx, &RunOpts{ + err := gitcmd.NewCommand("for-each-ref").Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, Stderr: stderrBuilder, }) if err != nil { - _ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderrBuilder.String())) } else { _ = stdoutWriter.Close() } diff --git a/modules/git/repo_stats.go b/modules/git/repo_stats.go index 8c6f31c38c..22082325ef 100644 --- a/modules/git/repo_stats.go +++ b/modules/git/repo_stats.go @@ -14,6 +14,7 @@ import ( "time" "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/git/gitcmd" ) // CodeActivityStats represents git statistics data @@ -40,9 +41,9 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string) since := fromTime.Format(time.RFC3339) - stdout, _, runErr := NewCommand("rev-list", "--count", "--no-merges", "--branches=*", "--date=iso"). + stdout, _, runErr := gitcmd.NewCommand("rev-list", "--count", "--no-merges", "--branches=*", "--date=iso"). AddOptionFormat("--since=%s", since). - RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } @@ -62,7 +63,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string) _ = stdoutWriter.Close() }() - gitCmd := NewCommand("log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso"). + gitCmd := gitcmd.NewCommand("log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso"). AddOptionFormat("--since=%s", since) if len(branch) == 0 { gitCmd.AddArguments("--branches=*") @@ -71,7 +72,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string) } stderr := new(strings.Builder) - err = gitCmd.Run(repo.Ctx, &RunOpts{ + err = gitCmd.Run(repo.Ctx, &gitcmd.RunOpts{ Env: []string{}, Dir: repo.Path, Stdout: stdoutWriter, diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index c8d72eee02..0cb0932459 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -10,6 +10,7 @@ import ( "strings" "code.gitea.io/gitea/modules/git/foreachref" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" ) @@ -18,13 +19,13 @@ const TagPrefix = "refs/tags/" // CreateTag create one tag in the repository func (repo *Repository) CreateTag(name, revision string) error { - _, _, err := NewCommand("tag").AddDashesAndList(name, revision).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("tag").AddDashesAndList(name, revision).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // CreateAnnotatedTag create one annotated tag in the repository func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error { - _, _, err := NewCommand("tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } @@ -34,7 +35,7 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) { return "", fmt.Errorf("SHA is too short: %s", sha) } - stdout, _, err := NewCommand("show-ref", "--tags", "-d").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("show-ref", "--tags", "-d").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return "", err } @@ -57,7 +58,7 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) { // GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA) func (repo *Repository) GetTagID(name string) (string, error) { - stdout, _, err := NewCommand("show-ref", "--tags").AddDashesAndList(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("show-ref", "--tags").AddDashesAndList(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return "", err } @@ -114,14 +115,14 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) { defer stdoutReader.Close() defer stdoutWriter.Close() stderr := strings.Builder{} - rc := &RunOpts{Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr} + rc := &gitcmd.RunOpts{Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr} go func() { - err := NewCommand("for-each-ref"). + err := gitcmd.NewCommand("for-each-ref"). AddOptionFormat("--format=%s", forEachRefFmt.Flag()). AddArguments("--sort", "-*creatordate", "refs/tags").Run(repo.Ctx, rc) if err != nil { - _ = stdoutWriter.CloseWithError(ConcatenateError(err, stderr.String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderr.String())) } else { _ = stdoutWriter.Close() } diff --git a/modules/git/repo_tree.go b/modules/git/repo_tree.go index 309a73d759..1d8c940951 100644 --- a/modules/git/repo_tree.go +++ b/modules/git/repo_tree.go @@ -9,6 +9,8 @@ import ( "os" "strings" "time" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // CommitTreeOpts represents the possible options to CommitTree @@ -33,7 +35,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt "GIT_COMMITTER_EMAIL="+committer.Email, "GIT_COMMITTER_DATE="+commitTimeStr, ) - cmd := NewCommand("commit-tree").AddDynamicArguments(tree.ID.String()) + cmd := gitcmd.NewCommand("commit-tree").AddDynamicArguments(tree.ID.String()) for _, parent := range opts.Parents { cmd.AddArguments("-p").AddDynamicArguments(parent) @@ -58,7 +60,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) - err := cmd.Run(repo.Ctx, &RunOpts{ + err := cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Env: env, Dir: repo.Path, Stdin: messageBytes, @@ -66,7 +68,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt Stderr: stderr, }) if err != nil { - return nil, ConcatenateError(err, stderr.String()) + return nil, gitcmd.ConcatenateError(err, stderr.String()) } return NewIDFromString(strings.TrimSpace(stdout.String())) } diff --git a/modules/git/repo_tree_gogit.go b/modules/git/repo_tree_gogit.go index f77cd83612..40524d0c34 100644 --- a/modules/git/repo_tree_gogit.go +++ b/modules/git/repo_tree_gogit.go @@ -9,6 +9,8 @@ package git import ( "errors" + "code.gitea.io/gitea/modules/git/gitcmd" + "github.com/go-git/go-git/v5/plumbing" ) @@ -36,7 +38,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) { } if len(idStr) != objectFormat.FullLength() { - res, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 31a32f1a9e..58824adc82 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -9,6 +9,7 @@ import ( "fmt" "os" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -24,7 +25,7 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul if err != nil { return nil, err } - opts := &RunOpts{ + opts := &gitcmd.RunOpts{ Dir: repoPath, Stdout: stdoutWriter, PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { @@ -45,7 +46,7 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul return scanner.Err() }, } - err = NewCommand("ls-tree", "-r", "--", "HEAD").Run(ctx, opts) + err = gitcmd.NewCommand("ls-tree", "-r", "--", "HEAD").Run(ctx, opts) if err != nil { return nil, fmt.Errorf("GetTemplateSubmoduleCommits: error running git ls-tree: %v", err) } @@ -56,8 +57,8 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul // It is only for generating new repos based on existing template, requires the .gitmodules file to be already present in the work dir. func AddTemplateSubmoduleIndexes(ctx context.Context, repoPath string, submodules []TemplateSubmoduleCommit) error { for _, submodule := range submodules { - cmd := NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path) - if stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}); err != nil { + cmd := gitcmd.NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path) + if stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}); err != nil { log.Error("Unable to add %s as submodule to repo %s: stdout %s\nError: %v", submodule.Path, repoPath, stdout, err) return err } diff --git a/modules/git/submodule_test.go b/modules/git/submodule_test.go index 55ac0971a5..d2df8b2a91 100644 --- a/modules/git/submodule_test.go +++ b/modules/git/submodule_test.go @@ -8,6 +8,8 @@ import ( "path/filepath" "testing" + "code.gitea.io/gitea/modules/git/gitcmd" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -30,14 +32,14 @@ func TestAddTemplateSubmoduleIndexes(t *testing.T) { ctx := t.Context() tmpDir := t.TempDir() var err error - _, _, err = NewCommand("init").RunStdString(ctx, &RunOpts{Dir: tmpDir}) + _, _, err = gitcmd.NewCommand("init").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir}) require.NoError(t, err) _ = os.Mkdir(filepath.Join(tmpDir, "new-dir"), 0o755) err = AddTemplateSubmoduleIndexes(ctx, tmpDir, []TemplateSubmoduleCommit{{Path: "new-dir", Commit: "1234567890123456789012345678901234567890"}}) require.NoError(t, err) - _, _, err = NewCommand("add", "--all").RunStdString(ctx, &RunOpts{Dir: tmpDir}) + _, _, err = gitcmd.NewCommand("add", "--all").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir}) require.NoError(t, err) - _, _, err = NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(ctx, &RunOpts{Dir: tmpDir}) + _, _, err = gitcmd.NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir}) require.NoError(t, err) submodules, err := GetTemplateSubmoduleCommits(t.Context(), tmpDir) require.NoError(t, err) diff --git a/modules/git/tree.go b/modules/git/tree.go index 38fb45f3b1..a8c4929c7c 100644 --- a/modules/git/tree.go +++ b/modules/git/tree.go @@ -7,6 +7,8 @@ package git import ( "bytes" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // NewTree create a new tree according the repository and tree id @@ -48,10 +50,10 @@ func (t *Tree) SubTree(rpath string) (*Tree, error) { // LsTree checks if the given filenames are in the tree func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error) { - cmd := NewCommand("ls-tree", "-z", "--name-only"). + cmd := gitcmd.NewCommand("ls-tree", "-z", "--name-only"). AddDashesAndList(append([]string{ref}, filenames...)...) - res, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + res, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -65,9 +67,9 @@ func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error // GetTreePathLatestCommit returns the latest commit of a tree path func (repo *Repository) GetTreePathLatestCommit(refName, treePath string) (*Commit, error) { - stdout, _, err := NewCommand("rev-list", "-1"). + stdout, _, err := gitcmd.NewCommand("rev-list", "-1"). AddDynamicArguments(refName).AddDashesAndList(treePath). - RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } diff --git a/modules/git/tree_nogogit.go b/modules/git/tree_nogogit.go index f88788418e..045d78c42c 100644 --- a/modules/git/tree_nogogit.go +++ b/modules/git/tree_nogogit.go @@ -8,6 +8,8 @@ package git import ( "io" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // Tree represents a flat directory listing. @@ -70,7 +72,7 @@ func (t *Tree) ListEntries() (Entries, error) { } } - stdout, _, runErr := NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(t.repo.Ctx, &RunOpts{Dir: t.repo.Path}) + stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(t.repo.Ctx, &gitcmd.RunOpts{Dir: t.repo.Path}) if runErr != nil { if strings.Contains(runErr.Error(), "fatal: Not a valid object name") || strings.Contains(runErr.Error(), "fatal: not a tree object") { return nil, ErrNotExist{ @@ -91,15 +93,15 @@ func (t *Tree) ListEntries() (Entries, error) { // listEntriesRecursive returns all entries of current tree recursively including all subtrees // extraArgs could be "-l" to get the size, which is slower -func (t *Tree) listEntriesRecursive(extraArgs TrustedCmdArgs) (Entries, error) { +func (t *Tree) listEntriesRecursive(extraArgs gitcmd.TrustedCmdArgs) (Entries, error) { if t.entriesRecursiveParsed { return t.entriesRecursive, nil } - stdout, _, runErr := NewCommand("ls-tree", "-t", "-r"). + stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-t", "-r"). AddArguments(extraArgs...). AddDynamicArguments(t.ID.String()). - RunStdBytes(t.repo.Ctx, &RunOpts{Dir: t.repo.Path}) + RunStdBytes(t.repo.Ctx, &gitcmd.RunOpts{Dir: t.repo.Path}) if runErr != nil { return nil, runErr } @@ -120,5 +122,5 @@ func (t *Tree) ListEntriesRecursiveFast() (Entries, error) { // ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees, with size func (t *Tree) ListEntriesRecursiveWithSize() (Entries, error) { - return t.listEntriesRecursive(TrustedCmdArgs{"--long"}) + return t.listEntriesRecursive(gitcmd.TrustedCmdArgs{"--long"}) } diff --git a/modules/git/utils.go b/modules/git/utils.go index e2bdf7866b..b5f188904a 100644 --- a/modules/git/utils.go +++ b/modules/git/utils.go @@ -6,7 +6,6 @@ package git import ( "crypto/sha1" "encoding/hex" - "fmt" "io" "strconv" "strings" @@ -42,14 +41,6 @@ func (oc *ObjectCache[T]) Get(id string) (T, bool) { return obj, has } -// ConcatenateError concatenats an error with stderr string -func ConcatenateError(err error, stderr string) error { - if len(stderr) == 0 { - return err - } - return fmt.Errorf("%w - %s", err, stderr) -} - // ParseBool returns the boolean value represented by the string as per git's git_config_bool // true will be returned for the result if the string is empty, but valid will be false. // "true", "yes", "on" are all true, true diff --git a/modules/gitrepo/branch.go b/modules/gitrepo/branch.go index d7857819e4..4d571f583d 100644 --- a/modules/gitrepo/branch.go +++ b/modules/gitrepo/branch.go @@ -7,6 +7,7 @@ import ( "context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) // GetBranchesByPath returns a branch by its path @@ -33,9 +34,9 @@ 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 := git.NewCommand("symbolic-ref", "HEAD"). + _, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD"). AddDynamicArguments(git.BranchPrefix+name). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err } diff --git a/modules/gitrepo/config.go b/modules/gitrepo/config.go index 84ef1eadf6..c028c6afe8 100644 --- a/modules/gitrepo/config.go +++ b/modules/gitrepo/config.go @@ -7,14 +7,14 @@ import ( "context" "strings" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/globallock" ) func GitConfigGet(ctx context.Context, repo Repository, key string) (string, error) { - result, _, err := git.NewCommand("config", "--get"). + result, _, err := gitcmd.NewCommand("config", "--get"). AddDynamicArguments(key). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) if err != nil { return "", err } @@ -28,9 +28,9 @@ 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 := git.NewCommand("config", "--add"). + _, _, err := gitcmd.NewCommand("config", "--add"). AddDynamicArguments(key, value). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err }) } @@ -40,9 +40,9 @@ 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 := git.NewCommand("config"). + _, _, err := gitcmd.NewCommand("config"). AddDynamicArguments(key, value). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err }) } diff --git a/modules/gitrepo/fsck.go b/modules/gitrepo/fsck.go index bcec6aa03f..ffccff28a9 100644 --- a/modules/gitrepo/fsck.go +++ b/modules/gitrepo/fsck.go @@ -7,10 +7,10 @@ import ( "context" "time" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) // Fsck verifies the connectivity and validity of the objects in the database -func Fsck(ctx context.Context, repo Repository, timeout time.Duration, args git.TrustedCmdArgs) error { - return git.NewCommand("fsck").AddArguments(args...).Run(ctx, &git.RunOpts{Timeout: timeout, Dir: repoPath(repo)}) +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)}) } diff --git a/modules/gitrepo/remote.go b/modules/gitrepo/remote.go index ba32c2a1d8..20d3cd21da 100644 --- a/modules/gitrepo/remote.go +++ b/modules/gitrepo/remote.go @@ -10,6 +10,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" giturl "code.gitea.io/gitea/modules/git/url" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/util" @@ -24,7 +25,7 @@ const ( func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL string, options ...RemoteOption) error { return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error { - cmd := git.NewCommand("remote", "add") + cmd := gitcmd.NewCommand("remote", "add") if len(options) > 0 { switch options[0] { case RemoteOptionMirrorPush: @@ -37,15 +38,15 @@ func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL st } _, _, err := cmd. AddDynamicArguments(remoteName, remoteURL). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err }) } func GitRemoteRemove(ctx context.Context, repo Repository, remoteName string) error { return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error { - cmd := git.NewCommand("remote", "rm").AddDynamicArguments(remoteName) - _, _, err := cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + cmd := gitcmd.NewCommand("remote", "rm").AddDynamicArguments(remoteName) + _, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err }) } @@ -64,8 +65,8 @@ 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 git.NewCommand("remote", "prune").AddDynamicArguments(remoteName). - Run(ctx, &git.RunOpts{ + return gitcmd.NewCommand("remote", "prune").AddDynamicArguments(remoteName). + Run(ctx, &gitcmd.RunOpts{ Timeout: timeout, Dir: repoPath(repo), Stdout: stdout, @@ -75,8 +76,8 @@ func GitRemotePrune(ctx context.Context, repo Repository, remoteName string, tim // 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 git.NewCommand("remote", "update", "--prune").AddDynamicArguments(remoteName). - Run(ctx, &git.RunOpts{ + return gitcmd.NewCommand("remote", "update", "--prune").AddDynamicArguments(remoteName). + Run(ctx, &gitcmd.RunOpts{ Timeout: timeout, Dir: repoPath(repo), Stdout: stdout, diff --git a/modules/indexer/code/bleve/bleve.go b/modules/indexer/code/bleve/bleve.go index 70f0995a01..c233f491e3 100644 --- a/modules/indexer/code/bleve/bleve.go +++ b/modules/indexer/code/bleve/bleve.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/analyze" "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/indexer" path_filter "code.gitea.io/gitea/modules/indexer/code/bleve/token/path" "code.gitea.io/gitea/modules/indexer/code/internal" @@ -162,7 +163,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro var err error if !update.Sized { var stdout string - stdout, _, err = git.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, err = gitcmd.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { return err } diff --git a/modules/indexer/code/elasticsearch/elasticsearch.go b/modules/indexer/code/elasticsearch/elasticsearch.go index 90330739ec..b08d837a2a 100644 --- a/modules/indexer/code/elasticsearch/elasticsearch.go +++ b/modules/indexer/code/elasticsearch/elasticsearch.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/analyze" "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/indexer" "code.gitea.io/gitea/modules/indexer/code/internal" indexer_internal "code.gitea.io/gitea/modules/indexer/internal" @@ -147,7 +148,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro var err error if !update.Sized { var stdout string - stdout, _, err = git.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, err = gitcmd.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { return nil, err } diff --git a/modules/indexer/code/git.go b/modules/indexer/code/git.go index 41bc74e6ec..f1513d66b0 100644 --- a/modules/indexer/code/git.go +++ b/modules/indexer/code/git.go @@ -10,13 +10,14 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/indexer/code/internal" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) func getDefaultBranchSha(ctx context.Context, repo *repo_model.Repository) (string, error) { - stdout, _, err := git.NewCommand("show-ref", "-s").AddDynamicArguments(git.BranchPrefix+repo.DefaultBranch).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, err := gitcmd.NewCommand("show-ref", "-s").AddDynamicArguments(git.BranchPrefix+repo.DefaultBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { return "", err } @@ -32,8 +33,8 @@ func getRepoChanges(ctx context.Context, repo *repo_model.Repository, revision s needGenesis := len(status.CommitSha) == 0 if !needGenesis { - hasAncestorCmd := git.NewCommand("merge-base").AddDynamicArguments(status.CommitSha, revision) - stdout, _, _ := hasAncestorCmd.RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + hasAncestorCmd := gitcmd.NewCommand("merge-base").AddDynamicArguments(status.CommitSha, revision) + stdout, _, _ := hasAncestorCmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) needGenesis = len(stdout) == 0 } @@ -86,7 +87,7 @@ func parseGitLsTreeOutput(stdout []byte) ([]internal.FileUpdate, error) { // genesisChanges get changes to add repo to the indexer for the first time func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) { var changes internal.RepoChanges - stdout, _, runErr := git.NewCommand("ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision).RunStdBytes(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, runErr := gitcmd.NewCommand("ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision).RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if runErr != nil { return nil, runErr } @@ -98,8 +99,8 @@ func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision s // nonGenesisChanges get changes since the previous indexer update func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) { - diffCmd := git.NewCommand("diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision) - stdout, _, runErr := diffCmd.RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + diffCmd := gitcmd.NewCommand("diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision) + stdout, _, runErr := diffCmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if runErr != nil { // previous commit sha may have been removed by a force push, so // try rebuilding from scratch @@ -115,9 +116,9 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio updatedFilenames := make([]string, 0, 10) updateChanges := func() error { - cmd := git.NewCommand("ls-tree", "--full-tree", "-l").AddDynamicArguments(revision). + cmd := gitcmd.NewCommand("ls-tree", "--full-tree", "-l").AddDynamicArguments(revision). AddDashesAndList(updatedFilenames...) - lsTreeStdout, _, err := cmd.RunStdBytes(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + lsTreeStdout, _, err := cmd.RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { return err } diff --git a/routers/init.go b/routers/init.go index 2281260a6f..6cd85728c2 100644 --- a/routers/init.go +++ b/routers/init.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/eventsource" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/highlight" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" @@ -114,7 +115,7 @@ func InitWebInstallPage(ctx context.Context) { // InitWebInstalled is for the global configuration of an installed instance func InitWebInstalled(ctx context.Context) { mustInit(git.InitFull) - log.Info("Git version: %s (home: %s)", git.DefaultFeatures().VersionInfo(), git.HomeDir()) + log.Info("Git version: %s (home: %s)", git.DefaultFeatures().VersionInfo(), gitcmd.HomeDir()) if !git.DefaultFeatures().SupportHashSha256 { log.Warn("sha256 hash support is disabled - requires Git >= 2.42." + util.Iif(git.DefaultFeatures().UsingGogit, " Gogit is currently unsupported.", "")) } diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index dd9d0bc15e..99a0b450d7 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" @@ -188,7 +189,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r // 2. Disallow force pushes to protected branches if oldCommitID != objectFormat.EmptyObjectID().String() { - output, _, err := git.NewCommand("rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath(), Env: ctx.env}) + output, _, err := gitcmd.NewCommand("rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath(), Env: ctx.env}) if err != nil { log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err) ctx.JSON(http.StatusInternalServerError, private.Response{ diff --git a/routers/private/hook_verification.go b/routers/private/hook_verification.go index 57d0964ead..a69c3b04eb 100644 --- a/routers/private/hook_verification.go +++ b/routers/private/hook_verification.go @@ -10,6 +10,7 @@ import ( "os" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" asymkey_service "code.gitea.io/gitea/services/asymkey" ) @@ -27,18 +28,18 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env [] _ = stdoutWriter.Close() }() - var command *git.Command + var command *gitcmd.Command objectFormat, _ := repo.GetObjectFormat() if oldCommitID == objectFormat.EmptyObjectID().String() { // When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all": // List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits // So, it only lists the new commits received, doesn't list the commits already present in the receiving repository - command = git.NewCommand("rev-list").AddDynamicArguments(newCommitID).AddArguments("--not", "--all") + command = gitcmd.NewCommand("rev-list").AddDynamicArguments(newCommitID).AddArguments("--not", "--all") } else { - command = git.NewCommand("rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID) + command = gitcmd.NewCommand("rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID) } // This is safe as force pushes are already forbidden - err = command.Run(repo.Ctx, &git.RunOpts{ + err = command.Run(repo.Ctx, &gitcmd.RunOpts{ Env: env, Dir: repo.Path, Stdout: stdoutWriter, @@ -84,8 +85,8 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error { commitID := git.MustIDFromString(sha) - return git.NewCommand("cat-file", "commit").AddDynamicArguments(sha). - Run(repo.Ctx, &git.RunOpts{ + return gitcmd.NewCommand("cat-file", "commit").AddDynamicArguments(sha). + Run(repo.Ctx, &gitcmd.RunOpts{ Env: env, Dir: repo.Path, Stdout: stdoutWriter, diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index a7084bf0ae..2e56f6934a 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -28,6 +28,7 @@ import ( csv_module "code.gitea.io/gitea/modules/csv" "code.gitea.io/gitea/modules/fileicon" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" @@ -569,7 +570,7 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo { func PrepareCompareDiff( ctx *context.Context, ci *common.CompareInfo, - whitespaceBehavior git.TrustedCmdArgs, + whitespaceBehavior gitcmd.TrustedCmdArgs, ) (nothingToCompare bool) { repo := ctx.Repo.Repository headCommitID := ci.CompareInfo.HeadCommitID diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go index deb3ae4f3a..ab649b6f15 100644 --- a/routers/web/repo/githttp.go +++ b/routers/web/repo/githttp.go @@ -26,6 +26,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -315,7 +316,7 @@ func dummyInfoRefs(ctx *context.Context) { return } - refs, _, err := git.NewCommand("receive-pack", "--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &git.RunOpts{Dir: tmpDir}) + refs, _, err := gitcmd.NewCommand("receive-pack", "--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &gitcmd.RunOpts{Dir: tmpDir}) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(refs))) } @@ -393,12 +394,12 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string // one or more key=value pairs separated by colons var safeGitProtocolHeader = regexp.MustCompile(`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$`) -func prepareGitCmdWithAllowedService(service string) (*git.Command, error) { +func prepareGitCmdWithAllowedService(service string) (*gitcmd.Command, error) { if service == "receive-pack" { - return git.NewCommand("receive-pack"), nil + return gitcmd.NewCommand("receive-pack"), nil } if service == "upload-pack" { - return git.NewCommand("upload-pack"), nil + return gitcmd.NewCommand("upload-pack"), nil } return nil, fmt.Errorf("service %q is not allowed", service) @@ -448,7 +449,7 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) { var stderr bytes.Buffer cmd.AddArguments("--stateless-rpc").AddDynamicArguments(h.getRepoDir()) - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: h.getRepoDir(), Env: append(os.Environ(), h.environ...), Stdout: ctx.Resp, @@ -488,7 +489,7 @@ func getServiceType(ctx *context.Context) string { } func updateServerInfo(ctx gocontext.Context, dir string) []byte { - out, _, err := git.NewCommand("update-server-info").RunStdBytes(ctx, &git.RunOpts{Dir: dir}) + out, _, err := gitcmd.NewCommand("update-server-info").RunStdBytes(ctx, &gitcmd.RunOpts{Dir: dir}) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(out))) } @@ -518,7 +519,7 @@ func GetInfoRefs(ctx *context.Context) { } h.environ = append(os.Environ(), h.environ...) - refs, _, err := cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &git.RunOpts{Env: h.environ, Dir: h.getRepoDir()}) + refs, _, err := cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &gitcmd.RunOpts{Env: h.environ, Dir: h.getRepoDir()}) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(refs))) } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 889219b256..c9ea836899 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -26,6 +26,7 @@ import ( "code.gitea.io/gitea/modules/emoji" "code.gitea.io/gitea/modules/fileicon" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/graceful" @@ -233,7 +234,7 @@ func GetMergedBaseCommitID(ctx *context.Context, issue *issues_model.Issue) stri } if commitSHA != "" { // Get immediate parent of the first commit in the patch, grab history back - parentCommit, _, err = git.NewCommand("rev-list", "-1", "--skip=1").AddDynamicArguments(commitSHA).RunStdString(ctx, &git.RunOpts{Dir: ctx.Repo.GitRepo.Path}) + parentCommit, _, err = gitcmd.NewCommand("rev-list", "-1", "--skip=1").AddDynamicArguments(commitSHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: ctx.Repo.GitRepo.Path}) if err == nil { parentCommit = strings.TrimSpace(parentCommit) } diff --git a/services/agit/agit.go b/services/agit/agit.go index 9d2d122cfb..4ed867b358 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -15,6 +15,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" @@ -198,9 +199,9 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. } if !forcePush.Value() { - output, _, err := git.NewCommand("rev-list", "--max-count=1"). + output, _, err := gitcmd.NewCommand("rev-list", "--max-count=1"). AddDynamicArguments(oldCommitID, "^"+opts.NewCommitIDs[i]). - RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()}) if err != nil { return nil, fmt.Errorf("failed to detect force push: %w", err) } else if len(output) > 0 { diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 8fd2adc8b4..4fde342bea 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -17,6 +17,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" @@ -116,16 +117,16 @@ func SigningKey(ctx context.Context, repoPath string) (*git.SigningKey, *git.Sig if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" { // Can ignore the error here as it means that commit.gpgsign is not set - value, _, _ := git.NewCommand("config", "--get", "commit.gpgsign").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) sign, valid := git.ParseBool(strings.TrimSpace(value)) if !sign || !valid { return nil, nil } - format, _, _ := git.NewCommand("config", "--default", git.SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) - signingKey, _, _ := git.NewCommand("config", "--get", "user.signingkey").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) - signingName, _, _ := git.NewCommand("config", "--get", "user.name").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) - signingEmail, _, _ := git.NewCommand("config", "--get", "user.email").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + format, _, _ := gitcmd.NewCommand("config", "--default", git.SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) + signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) + signingName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) + signingEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if strings.TrimSpace(signingKey) == "" { return nil, nil diff --git a/services/cron/tasks_basic.go b/services/cron/tasks_basic.go index 841981787d..48380b7b9a 100644 --- a/services/cron/tasks_basic.go +++ b/services/cron/tasks_basic.go @@ -11,7 +11,7 @@ import ( git_model "code.gitea.io/gitea/models/git" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/services/auth" "code.gitea.io/gitea/services/migrations" @@ -59,7 +59,7 @@ func registerRepoHealthCheck() { }, func(ctx context.Context, _ *user_model.User, config Config) error { rhcConfig := config.(*RepoHealthCheckConfig) // the git args are set by config, they can be safe to be trusted - return repo_service.GitFsckRepos(ctx, rhcConfig.Timeout, git.ToTrustedCmdArgs(rhcConfig.Args)) + return repo_service.GitFsckRepos(ctx, rhcConfig.Timeout, gitcmd.ToTrustedCmdArgs(rhcConfig.Args)) }) } diff --git a/services/cron/tasks_extended.go b/services/cron/tasks_extended.go index 3747111984..74fb12430d 100644 --- a/services/cron/tasks_extended.go +++ b/services/cron/tasks_extended.go @@ -10,7 +10,7 @@ import ( activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" issue_indexer "code.gitea.io/gitea/modules/indexer/issues" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/updatechecker" @@ -61,7 +61,7 @@ func registerGarbageCollectRepositories() { }, func(ctx context.Context, _ *user_model.User, config Config) error { rhcConfig := config.(*RepoHealthCheckConfig) // the git args are set by config, they can be safe to be trusted - return repo_service.GitGcRepos(ctx, rhcConfig.Timeout, git.ToTrustedCmdArgs(rhcConfig.Args)) + return repo_service.GitGcRepos(ctx, rhcConfig.Timeout, gitcmd.ToTrustedCmdArgs(rhcConfig.Args)) }) } diff --git a/services/doctor/heads.go b/services/doctor/heads.go index bbfd40da5e..4354505806 100644 --- a/services/doctor/heads.go +++ b/services/doctor/heads.go @@ -8,6 +8,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -18,9 +19,9 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool) numReposUpdated := 0 err := iterateRepositories(ctx, func(repo *repo_model.Repository) error { numRepos++ - _, _, defaultBranchErr := git.NewCommand("rev-parse").AddDashesAndList(repo.DefaultBranch).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + _, _, defaultBranchErr := gitcmd.NewCommand("rev-parse").AddDashesAndList(repo.DefaultBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) - head, _, headErr := git.NewCommand("symbolic-ref", "--short", "HEAD").RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + head, _, headErr := gitcmd.NewCommand("symbolic-ref", "--short", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) // what we expect: default branch is valid, and HEAD points to it if headErr == nil && defaultBranchErr == nil && head == repo.DefaultBranch { @@ -46,7 +47,7 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool) } // otherwise, let's try fixing HEAD - err := git.NewCommand("symbolic-ref").AddDashesAndList("HEAD", git.BranchPrefix+repo.DefaultBranch).Run(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + err := gitcmd.NewCommand("symbolic-ref").AddDashesAndList("HEAD", git.BranchPrefix+repo.DefaultBranch).Run(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { logger.Warn("Failed to fix HEAD for %s/%s: %v", repo.OwnerName, repo.Name, err) return nil diff --git a/services/doctor/mergebase.go b/services/doctor/mergebase.go index cbd8aa59fd..a078d54dad 100644 --- a/services/doctor/mergebase.go +++ b/services/doctor/mergebase.go @@ -12,6 +12,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "xorm.io/builder" @@ -42,17 +43,17 @@ func checkPRMergeBase(ctx context.Context, logger log.Logger, autofix bool) erro if !pr.HasMerged { var err error - pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, pr.GetGitHeadRefName()).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = gitcmd.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, pr.GetGitHeadRefName()).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { var err2 error - pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err2 = gitcmd.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err2 != nil { logger.Warn("Unable to get merge base for PR ID %d, #%d onto %s in %s/%s. Error: %v & %v", pr.ID, pr.Index, pr.BaseBranch, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, err, err2) return nil } } } else { - parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { logger.Warn("Unable to get parents for merged PR ID %d, #%d onto %s in %s/%s. Error: %v", pr.ID, pr.Index, pr.BaseBranch, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, err) return nil @@ -64,8 +65,8 @@ func checkPRMergeBase(ctx context.Context, logger log.Logger, autofix bool) erro refs := append([]string{}, parents[1:]...) refs = append(refs, pr.GetGitHeadRefName()) - cmd := git.NewCommand("merge-base").AddDashesAndList(refs...) - pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...) + pr.MergeBase, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { logger.Warn("Unable to get merge base for merged PR ID %d, #%d onto %s in %s/%s. Error: %v", pr.ID, pr.Index, pr.BaseBranch, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, err) return nil diff --git a/services/gitdiff/git_diff_tree.go b/services/gitdiff/git_diff_tree.go index ed94bfbfe4..eeb354c1b6 100644 --- a/services/gitdiff/git_diff_tree.go +++ b/services/gitdiff/git_diff_tree.go @@ -13,6 +13,7 @@ import ( "strings" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -55,12 +56,12 @@ func runGitDiffTree(ctx context.Context, gitRepo *git.Repository, useMergeBase b return nil, err } - cmd := git.NewCommand("diff-tree", "--raw", "-r", "--find-renames", "--root") + cmd := gitcmd.NewCommand("diff-tree", "--raw", "-r", "--find-renames", "--root") if useMergeBase { cmd.AddArguments("--merge-base") } cmd.AddDynamicArguments(baseCommitID, headCommitID) - stdout, _, runErr := cmd.RunStdString(ctx, &git.RunOpts{Dir: gitRepo.Path}) + stdout, _, runErr := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: gitRepo.Path}) if runErr != nil { log.Warn("git diff-tree: %v", runErr) return nil, runErr diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 7c99e049d5..1bb7c05ba2 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -26,6 +26,7 @@ import ( "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git/attribute" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/highlight" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" @@ -1090,7 +1091,7 @@ type DiffOptions struct { MaxLines int MaxLineCharacters int MaxFiles int - WhitespaceBehavior git.TrustedCmdArgs + WhitespaceBehavior gitcmd.TrustedCmdArgs DirectComparison bool } @@ -1131,7 +1132,7 @@ func getDiffBasic(ctx context.Context, gitRepo *git.Repository, opts *DiffOption return nil, nil, nil, err } - cmdDiff := git.NewCommand(). + cmdDiff := gitcmd.NewCommand(). AddArguments("diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"). AddArguments(opts.WhitespaceBehavior...) @@ -1158,7 +1159,7 @@ func getDiffBasic(ctx context.Context, gitRepo *git.Repository, opts *DiffOption go func() { stderr := &bytes.Buffer{} - if err := cmdDiff.Run(cmdCtx, &git.RunOpts{ + if err := cmdDiff.Run(cmdCtx, &gitcmd.RunOpts{ Timeout: time.Duration(setting.Git.Timeout.Default) * time.Second, Dir: repoPath, Stdout: writer, @@ -1395,8 +1396,8 @@ func CommentMustAsDiff(ctx context.Context, c *issues_model.Comment) *Diff { } // GetWhitespaceFlag returns git diff flag for treating whitespaces -func GetWhitespaceFlag(whitespaceBehavior string) git.TrustedCmdArgs { - whitespaceFlags := map[string]git.TrustedCmdArgs{ +func GetWhitespaceFlag(whitespaceBehavior string) gitcmd.TrustedCmdArgs { + whitespaceFlags := map[string]gitcmd.TrustedCmdArgs{ "ignore-all": {"-w"}, "ignore-change": {"-b"}, "ignore-eol": {"--ignore-space-at-eol"}, diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index 83815caeb5..7b64b6b5f8 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/setting" @@ -602,7 +603,7 @@ func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) { require.NoError(t, err) defer gitRepo.Close() - for _, behavior := range []git.TrustedCmdArgs{{"-w"}, {"--ignore-space-at-eol"}, {"-b"}, nil} { + for _, behavior := range []gitcmd.TrustedCmdArgs{{"-w"}, {"--ignore-space-at-eol"}, {"-b"}, nil} { diffs, err := GetDiffForAPI(t.Context(), gitRepo, &DiffOptions{ AfterCommitID: "d8e0bbb45f200e67d9a784ce55bd90821af45ebd", diff --git a/services/migrations/dump.go b/services/migrations/dump.go index 8edd567b08..385759800e 100644 --- a/services/migrations/dump.go +++ b/services/migrations/dump.go @@ -18,6 +18,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/repository" @@ -488,7 +489,7 @@ func (g *RepositoryDumper) handlePullRequest(ctx context.Context, pr *base.PullR if pr.Head.CloneURL == "" || pr.Head.Ref == "" { // Set head information if pr.Head.SHA is available if pr.Head.SHA != "" { - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.gitPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.gitPath()}) if err != nil { log.Error("PR #%d in %s/%s unable to update-ref for pr HEAD: %v", pr.Number, g.repoOwner, g.repoName, err) } @@ -518,7 +519,7 @@ func (g *RepositoryDumper) handlePullRequest(ctx context.Context, pr *base.PullR if !ok { // Set head information if pr.Head.SHA is available if pr.Head.SHA != "" { - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.gitPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.gitPath()}) if err != nil { log.Error("PR #%d in %s/%s unable to update-ref for pr HEAD: %v", pr.Number, g.repoOwner, g.repoName, err) } @@ -553,7 +554,7 @@ func (g *RepositoryDumper) handlePullRequest(ctx context.Context, pr *base.PullR fetchArg = git.BranchPrefix + fetchArg } - _, _, err = git.NewCommand("fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(ctx, &git.RunOpts{Dir: g.gitPath()}) + _, _, err = gitcmd.NewCommand("fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.gitPath()}) if err != nil { log.Error("Fetch branch from %s failed: %v", pr.Head.CloneURL, err) // We need to continue here so that the Head.Ref is reset and we attempt to set the gitref for the PR @@ -577,7 +578,7 @@ func (g *RepositoryDumper) handlePullRequest(ctx context.Context, pr *base.PullR pr.Head.SHA = headSha } if pr.Head.SHA != "" { - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.gitPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.gitPath()}) if err != nil { log.Error("unable to set %s as the local head for PR #%d from %s in %s/%s. Error: %v", pr.Head.SHA, pr.Number, pr.Head.Ref, g.repoOwner, g.repoName, err) } diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 75eb06d01f..512468a832 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -20,6 +20,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/label" "code.gitea.io/gitea/modules/log" @@ -662,7 +663,7 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(ctx context.Context, pr *ba fetchArg = git.BranchPrefix + fetchArg } - _, _, err = git.NewCommand("fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(ctx, &git.RunOpts{Dir: g.repo.RepoPath()}) + _, _, err = gitcmd.NewCommand("fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.repo.RepoPath()}) if err != nil { log.Error("Fetch branch from %s failed: %v", pr.Head.CloneURL, err) return head, nil @@ -681,7 +682,7 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(ctx context.Context, pr *ba pr.Head.SHA = headSha } - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.repo.RepoPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.repo.RepoPath()}) if err != nil { return "", err } @@ -698,13 +699,13 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(ctx context.Context, pr *ba // The SHA is empty log.Warn("Empty reference, no pull head for PR #%d in %s/%s", pr.Number, g.repoOwner, g.repoName) } else { - _, _, err = git.NewCommand("rev-list", "--quiet", "-1").AddDynamicArguments(pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.repo.RepoPath()}) + _, _, err = gitcmd.NewCommand("rev-list", "--quiet", "-1").AddDynamicArguments(pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.repo.RepoPath()}) if err != nil { // Git update-ref remove bad references with a relative path log.Warn("Deprecated local head %s for PR #%d in %s/%s, removing %s", pr.Head.SHA, pr.Number, g.repoOwner, g.repoName, pr.GetGitHeadRefName()) } else { // set head information - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.repo.RepoPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.repo.RepoPath()}) if err != nil { log.Error("unable to set %s as the local head for PR #%d from %s in %s/%s. Error: %v", pr.Head.SHA, pr.Number, pr.Head.Ref, g.repoOwner, g.repoName, err) } diff --git a/services/migrations/gitea_uploader_test.go b/services/migrations/gitea_uploader_test.go index 4856b66c6e..08efef5de6 100644 --- a/services/migrations/gitea_uploader_test.go +++ b/services/migrations/gitea_uploader_test.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -238,7 +239,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { baseRef := "master" // this is very different from the real situation. It should be a bare repository for all the Gitea managed repositories assert.NoError(t, git.InitRepository(t.Context(), fromRepo.RepoPath(), false, fromRepo.ObjectFormatName)) - err := git.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(t.Context(), &git.RunOpts{Dir: fromRepo.RepoPath()}) + err := gitcmd.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(t.Context(), &gitcmd.RunOpts{Dir: fromRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte("# Testing Repository\n\nOriginally created in: "+fromRepo.RepoPath()), 0o644)) assert.NoError(t, git.AddChanges(t.Context(), fromRepo.RepoPath(), true)) @@ -262,7 +263,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { // fromRepo branch1 // headRef := "branch1" - _, _, err = git.NewCommand("checkout", "-b").AddDynamicArguments(headRef).RunStdString(t.Context(), &git.RunOpts{Dir: fromRepo.RepoPath()}) + _, _, err = gitcmd.NewCommand("checkout", "-b").AddDynamicArguments(headRef).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: fromRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte("SOMETHING"), 0o644)) assert.NoError(t, git.AddChanges(t.Context(), fromRepo.RepoPath(), true)) @@ -286,7 +287,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { assert.NoError(t, git.Clone(t.Context(), fromRepo.RepoPath(), forkRepo.RepoPath(), git.CloneRepoOptions{ Branch: headRef, })) - _, _, err = git.NewCommand("checkout", "-b").AddDynamicArguments(forkHeadRef).RunStdString(t.Context(), &git.RunOpts{Dir: forkRepo.RepoPath()}) + _, _, err = gitcmd.NewCommand("checkout", "-b").AddDynamicArguments(forkHeadRef).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: forkRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(forkRepo.RepoPath(), "README.md"), []byte("# branch2 "+forkRepo.RepoPath()), 0o644)) assert.NoError(t, git.AddChanges(t.Context(), forkRepo.RepoPath(), true)) diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index b9000f2703..6a87aa8a27 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -13,6 +13,7 @@ import ( system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" giturl "code.gitea.io/gitea/modules/git/url" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/globallock" @@ -255,7 +256,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo log.Trace("SyncMirrors [repo: %-v]: running git remote update...", m.Repo) // use fetch but not remote update because git fetch support --tags but remote update doesn't - cmd := git.NewCommand("fetch") + cmd := gitcmd.NewCommand("fetch") if m.EnablePrune { cmd.AddArguments("--prune") } @@ -271,7 +272,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo stdoutBuilder := strings.Builder{} stderrBuilder := strings.Builder{} - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Timeout: timeout, Dir: repoPath, Env: envs, @@ -296,7 +297,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo // Successful prune - reattempt mirror stderrBuilder.Reset() stdoutBuilder.Reset() - if err = cmd.Run(ctx, &git.RunOpts{ + if err = cmd.Run(ctx, &gitcmd.RunOpts{ Timeout: timeout, Dir: repoPath, Stdout: &stdoutBuilder, diff --git a/services/pull/check.go b/services/pull/check.go index 7fcec22f49..c2ee49b6bb 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/graceful" @@ -280,9 +281,9 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com prHeadRef := pr.GetGitHeadRefName() // Check if the pull request is merged into BaseBranch - if _, _, err := git.NewCommand("merge-base", "--is-ancestor"). + if _, _, err := gitcmd.NewCommand("merge-base", "--is-ancestor"). AddDynamicArguments(prHeadRef, pr.BaseBranch). - RunStdString(ctx, &git.RunOpts{Dir: pr.BaseRepo.RepoPath()}); err != nil { + RunStdString(ctx, &gitcmd.RunOpts{Dir: pr.BaseRepo.RepoPath()}); err != nil { if strings.Contains(err.Error(), "exit status 1") { // prHeadRef is not an ancestor of the base branch return nil, nil @@ -308,9 +309,9 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com objectFormat := git.ObjectFormatFromName(pr.BaseRepo.ObjectFormatName) // Get the commit from BaseBranch where the pull request got merged - mergeCommit, _, err := git.NewCommand("rev-list", "--ancestry-path", "--merges", "--reverse"). + mergeCommit, _, err := gitcmd.NewCommand("rev-list", "--ancestry-path", "--merges", "--reverse"). AddDynamicArguments(prHeadCommitID+".."+pr.BaseBranch). - RunStdString(ctx, &git.RunOpts{Dir: pr.BaseRepo.RepoPath()}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: pr.BaseRepo.RepoPath()}) if err != nil { return nil, fmt.Errorf("git rev-list --ancestry-path --merges --reverse: %w", err) } else if len(mergeCommit) < objectFormat.FullLength() { diff --git a/services/pull/merge.go b/services/pull/merge.go index a941c20435..4d6afb8d33 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -26,6 +26,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/httplib" "code.gitea.io/gitea/modules/log" @@ -400,7 +401,7 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use ) mergeCtx.env = append(mergeCtx.env, repo_module.EnvPushTrigger+"="+string(pushTrigger)) - pushCmd := git.NewCommand("push", "origin").AddDynamicArguments(baseBranch + ":" + git.BranchPrefix + pr.BaseBranch) + pushCmd := gitcmd.NewCommand("push", "origin").AddDynamicArguments(baseBranch + ":" + git.BranchPrefix + pr.BaseBranch) // Push back to upstream. // This cause an api call to "/api/internal/hook/post-receive/...", @@ -430,7 +431,7 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use } func commitAndSignNoAuthor(ctx *mergeContext, message string) error { - cmdCommit := git.NewCommand("commit").AddOptionFormat("--message=%s", message) + cmdCommit := gitcmd.NewCommand("commit").AddOptionFormat("--message=%s", message) if ctx.signKey == nil { cmdCommit.AddArguments("--no-gpg-sign") } else { @@ -499,7 +500,7 @@ func (err ErrMergeDivergingFastForwardOnly) Error() string { return fmt.Sprintf("Merge DivergingFastForwardOnly Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut) } -func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *git.Command) error { +func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *gitcmd.Command) error { if err := cmd.Run(ctx, ctx.RunOpts()); err != nil { // Merge will leave a MERGE_HEAD file in the .git folder if there is a conflict if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "MERGE_HEAD")); statErr == nil { diff --git a/services/pull/merge_ff_only.go b/services/pull/merge_ff_only.go index 6c3a68b95b..22a560e29c 100644 --- a/services/pull/merge_ff_only.go +++ b/services/pull/merge_ff_only.go @@ -5,13 +5,13 @@ package pull import ( repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) // doMergeStyleFastForwardOnly merges the tracking into the current HEAD - which is assumed to be staging branch (equal to the pr.BaseBranch) func doMergeStyleFastForwardOnly(ctx *mergeContext) error { - cmd := git.NewCommand("merge", "--ff-only").AddDynamicArguments(trackingBranch) + cmd := gitcmd.NewCommand("merge", "--ff-only").AddDynamicArguments(trackingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleFastForwardOnly, cmd); err != nil { log.Error("%-v Unable to merge tracking into base: %v", ctx.pr, err) return err diff --git a/services/pull/merge_merge.go b/services/pull/merge_merge.go index 118d21c7cd..bc94400f21 100644 --- a/services/pull/merge_merge.go +++ b/services/pull/merge_merge.go @@ -5,13 +5,13 @@ package pull import ( repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) // doMergeStyleMerge merges the tracking branch into the current HEAD - which is assumed to be the staging branch (equal to the pr.BaseBranch) func doMergeStyleMerge(ctx *mergeContext, message string) error { - cmd := git.NewCommand("merge", "--no-ff", "--no-commit").AddDynamicArguments(trackingBranch) + cmd := gitcmd.NewCommand("merge", "--no-ff", "--no-commit").AddDynamicArguments(trackingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleMerge, cmd); err != nil { log.Error("%-v Unable to merge tracking into base: %v", ctx.pr, err) return err diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go index 31a1e13734..d7152560d2 100644 --- a/services/pull/merge_prepare.go +++ b/services/pull/merge_prepare.go @@ -18,6 +18,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" asymkey_service "code.gitea.io/gitea/services/asymkey" ) @@ -31,10 +32,10 @@ type mergeContext struct { env []string } -func (ctx *mergeContext) RunOpts() *git.RunOpts { +func (ctx *mergeContext) RunOpts() *gitcmd.RunOpts { ctx.outbuf.Reset() ctx.errbuf.Reset() - return &git.RunOpts{ + return &gitcmd.RunOpts{ Env: ctx.env, Dir: ctx.tmpBasePath, Stdout: ctx.outbuf, @@ -73,7 +74,7 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque } if expectedHeadCommitID != "" { - trackingCommitID, _, err := git.NewCommand("show-ref", "--hash").AddDynamicArguments(git.BranchPrefix+trackingBranch).RunStdString(ctx, &git.RunOpts{Dir: mergeCtx.tmpBasePath}) + trackingCommitID, _, err := gitcmd.NewCommand("show-ref", "--hash").AddDynamicArguments(git.BranchPrefix+trackingBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: mergeCtx.tmpBasePath}) if err != nil { defer cancel() log.Error("failed to get sha of head branch in %-v: show-ref[%s] --hash refs/heads/tracking: %v", mergeCtx.pr, mergeCtx.tmpBasePath, err) @@ -151,7 +152,7 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error { } setConfig := func(key, value string) error { - if err := git.NewCommand("config", "--local").AddDynamicArguments(key, value). + if err := gitcmd.NewCommand("config", "--local").AddDynamicArguments(key, value). Run(ctx, ctx.RunOpts()); err != nil { log.Error("git config [%s -> %q]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("git config [%s -> %q]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String()) @@ -184,7 +185,7 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error { } // Read base branch index - if err := git.NewCommand("read-tree", "HEAD"). + if err := gitcmd.NewCommand("read-tree", "HEAD"). Run(ctx, ctx.RunOpts()); err != nil { log.Error("git read-tree HEAD: %v\n%s\n%s", err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("Unable to read base branch in to the index: %w\n%s\n%s", err, ctx.outbuf.String(), ctx.errbuf.String()) @@ -221,8 +222,8 @@ func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string, o return 0, nil, nil } - err = git.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "-r", "-z", "--root").AddDynamicArguments(baseBranch, headBranch). - Run(ctx, &git.RunOpts{ + err = gitcmd.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "-r", "-z", "--root").AddDynamicArguments(baseBranch, headBranch). + Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdout: diffOutWriter, PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { @@ -272,7 +273,7 @@ func (err ErrRebaseConflicts) Error() string { // if there is a conflict it will return an ErrRebaseConflicts func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) error { // Checkout head branch - if err := git.NewCommand("checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch). + if err := gitcmd.NewCommand("checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch). Run(ctx, ctx.RunOpts()); err != nil { return fmt.Errorf("unable to git checkout tracking as staging in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) } @@ -280,7 +281,7 @@ func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) ctx.errbuf.Reset() // Rebase before merging - if err := git.NewCommand("rebase").AddDynamicArguments(baseBranch). + if err := gitcmd.NewCommand("rebase").AddDynamicArguments(baseBranch). Run(ctx, ctx.RunOpts()); err != nil { // Rebase will leave a REBASE_HEAD file in .git if there is a conflict if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "REBASE_HEAD")); statErr == nil { diff --git a/services/pull/merge_rebase.go b/services/pull/merge_rebase.go index dd7c8761f0..1d7395ebca 100644 --- a/services/pull/merge_rebase.go +++ b/services/pull/merge_rebase.go @@ -9,6 +9,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" ) @@ -16,7 +17,7 @@ import ( // getRebaseAmendMessage composes the message to amend commits in rebase merge of a pull request. func getRebaseAmendMessage(ctx *mergeContext, baseGitRepo *git.Repository) (message string, err error) { // Get existing commit message. - commitMessage, _, err := git.NewCommand("show", "--format=%B", "-s").RunStdString(ctx, &git.RunOpts{Dir: ctx.tmpBasePath}) + commitMessage, _, err := gitcmd.NewCommand("show", "--format=%B", "-s").RunStdString(ctx, &gitcmd.RunOpts{Dir: ctx.tmpBasePath}) if err != nil { return "", err } @@ -42,7 +43,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error { return fmt.Errorf("Failed to get full commit id for HEAD: %w", err) } - cmd := git.NewCommand("merge", "--ff-only").AddDynamicArguments(stagingBranch) + cmd := gitcmd.NewCommand("merge", "--ff-only").AddDynamicArguments(stagingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleRebase, cmd); err != nil { log.Error("Unable to merge staging into base: %v", err) return err @@ -73,7 +74,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error { } if newMessage != "" { - if err := git.NewCommand("commit", "--amend").AddOptionFormat("--message=%s", newMessage).Run(ctx, &git.RunOpts{Dir: ctx.tmpBasePath}); err != nil { + if err := gitcmd.NewCommand("commit", "--amend").AddOptionFormat("--message=%s", newMessage).Run(ctx, &gitcmd.RunOpts{Dir: ctx.tmpBasePath}); err != nil { log.Error("Unable to amend commit message: %v", err) return err } @@ -84,7 +85,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error { // Perform rebase merge with merge commit. func doMergeRebaseMergeCommit(ctx *mergeContext, message string) error { - cmd := git.NewCommand("merge").AddArguments("--no-ff", "--no-commit").AddDynamicArguments(stagingBranch) + cmd := gitcmd.NewCommand("merge").AddArguments("--no-ff", "--no-commit").AddDynamicArguments(stagingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleRebaseMerge, cmd); err != nil { log.Error("Unable to merge staging into base: %v", err) @@ -105,7 +106,7 @@ func doMergeStyleRebase(ctx *mergeContext, mergeStyle repo_model.MergeStyle, mes } // Checkout base branch again - if err := git.NewCommand("checkout").AddDynamicArguments(baseBranch). + if err := gitcmd.NewCommand("checkout").AddDynamicArguments(baseBranch). Run(ctx, ctx.RunOpts()); err != nil { log.Error("git checkout base prior to merge post staging rebase %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("git checkout base prior to merge post staging rebase %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) diff --git a/services/pull/merge_squash.go b/services/pull/merge_squash.go index 0049c0b117..99c4311e04 100644 --- a/services/pull/merge_squash.go +++ b/services/pull/merge_squash.go @@ -10,6 +10,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) @@ -57,7 +58,7 @@ func doMergeStyleSquash(ctx *mergeContext, message string) error { return fmt.Errorf("getAuthorSignatureSquash: %w", err) } - cmdMerge := git.NewCommand("merge", "--squash").AddDynamicArguments(trackingBranch) + cmdMerge := gitcmd.NewCommand("merge", "--squash").AddDynamicArguments(trackingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleSquash, cmdMerge); err != nil { log.Error("%-v Unable to merge --squash tracking into base: %v", ctx.pr, err) return err @@ -68,7 +69,7 @@ func doMergeStyleSquash(ctx *mergeContext, message string) error { message = AddCommitMessageTailer(message, "Co-authored-by", sig.String()) message = AddCommitMessageTailer(message, "Co-committed-by", sig.String()) // FIXME: this one should be removed, it is not really used or widely used } - cmdCommit := git.NewCommand("commit"). + cmdCommit := gitcmd.NewCommand("commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email). AddOptionFormat("--message=%s", message) if ctx.signKey == nil { diff --git a/services/pull/patch.go b/services/pull/patch.go index e5f8f678bc..674ae01253 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/graceful" @@ -90,7 +91,7 @@ func testPullRequestTmpRepoBranchMergeable(ctx context.Context, prCtx *prTmpRepo defer gitRepo.Close() // 1. update merge base - pr.MergeBase, _, err = git.NewCommand("merge-base", "--", "base", "tracking").RunStdString(ctx, &git.RunOpts{Dir: prCtx.tmpBasePath}) + pr.MergeBase, _, err = gitcmd.NewCommand("merge-base", "--", "base", "tracking").RunStdString(ctx, &gitcmd.RunOpts{Dir: prCtx.tmpBasePath}) if err != nil { var err2 error pr.MergeBase, err2 = gitRepo.GetRefCommitID(git.BranchPrefix + "base") @@ -190,7 +191,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f } // Need to get the objects from the object db to attempt to merge - root, _, err := git.NewCommand("unpack-file").AddDynamicArguments(file.stage1.sha).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + root, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage1.sha).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return fmt.Errorf("unable to get root object: %s at path: %s for merging. Error: %w", file.stage1.sha, file.stage1.path, err) } @@ -199,7 +200,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f _ = util.Remove(filepath.Join(tmpBasePath, root)) }() - base, _, err := git.NewCommand("unpack-file").AddDynamicArguments(file.stage2.sha).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + base, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage2.sha).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return fmt.Errorf("unable to get base object: %s at path: %s for merging. Error: %w", file.stage2.sha, file.stage2.path, err) } @@ -207,7 +208,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f defer func() { _ = util.Remove(base) }() - head, _, err := git.NewCommand("unpack-file").AddDynamicArguments(file.stage3.sha).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + head, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage3.sha).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return fmt.Errorf("unable to get head object:%s at path: %s for merging. Error: %w", file.stage3.sha, file.stage3.path, err) } @@ -217,13 +218,13 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f }() // now git merge-file annoyingly takes a different order to the merge-tree ... - _, _, conflictErr := git.NewCommand("merge-file").AddDynamicArguments(base, root, head).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + _, _, conflictErr := gitcmd.NewCommand("merge-file").AddDynamicArguments(base, root, head).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if conflictErr != nil { return &errMergeConflict{file.stage2.path} } // base now contains the merged data - hash, _, err := git.NewCommand("hash-object", "-w", "--path").AddDynamicArguments(file.stage2.path, base).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + hash, _, err := gitcmd.NewCommand("hash-object", "-w", "--path").AddDynamicArguments(file.stage2.path, base).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return err } @@ -248,7 +249,7 @@ func AttemptThreeWayMerge(ctx context.Context, gitPath string, gitRepo *git.Repo defer cancel() // First we use read-tree to do a simple three-way merge - if _, _, err := git.NewCommand("read-tree", "-m").AddDynamicArguments(base, ours, theirs).RunStdString(ctx, &git.RunOpts{Dir: gitPath}); err != nil { + if _, _, err := gitcmd.NewCommand("read-tree", "-m").AddDynamicArguments(base, ours, theirs).RunStdString(ctx, &gitcmd.RunOpts{Dir: gitPath}); err != nil { log.Error("Unable to run read-tree -m! Error: %v", err) return false, nil, fmt.Errorf("unable to run read-tree -m! Error: %w", err) } @@ -322,9 +323,9 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * // No conflicts detected so we need to check if the patch is empty... // a. Write the newly merged tree and check the new tree-hash var treeHash string - treeHash, _, err = git.NewCommand("write-tree").RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + treeHash, _, err = gitcmd.NewCommand("write-tree").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { - lsfiles, _, _ := git.NewCommand("ls-files", "-u").RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + lsfiles, _, _ := gitcmd.NewCommand("ls-files", "-u").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) return false, fmt.Errorf("unable to write unconflicted tree: %w\n`git ls-files -u`:\n%s", err, lsfiles) } treeHash = strings.TrimSpace(treeHash) @@ -381,7 +382,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * log.Trace("PullRequest[%d].testPullRequestTmpRepoBranchMergeable (patchPath): %s", pr.ID, patchPath) // 4. Read the base branch in to the index of the temporary repository - _, _, err = git.NewCommand("read-tree", "base").RunStdString(gitRepo.Ctx, &git.RunOpts{Dir: tmpBasePath}) + _, _, err = gitcmd.NewCommand("read-tree", "base").RunStdString(gitRepo.Ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return false, fmt.Errorf("git read-tree %s: %w", pr.BaseBranch, err) } @@ -394,7 +395,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * prConfig := prUnit.PullRequestsConfig() // 6. Prepare the arguments to apply the patch against the index - cmdApply := git.NewCommand("apply", "--check", "--cached") + cmdApply := gitcmd.NewCommand("apply", "--check", "--cached") if prConfig.IgnoreWhitespaceConflicts { cmdApply.AddArguments("--ignore-whitespace") } @@ -425,7 +426,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * // 8. Run the check command conflict = false - err = cmdApply.Run(gitRepo.Ctx, &git.RunOpts{ + err = cmdApply.Run(gitRepo.Ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stderr: stderrWriter, PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { diff --git a/services/pull/patch_unmerged.go b/services/pull/patch_unmerged.go index 200d2233e9..9164035480 100644 --- a/services/pull/patch_unmerged.go +++ b/services/pull/patch_unmerged.go @@ -13,7 +13,7 @@ import ( "strconv" "strings" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -72,8 +72,8 @@ func readUnmergedLsFileLines(ctx context.Context, tmpBasePath string, outputChan }() stderr := &strings.Builder{} - err = git.NewCommand("ls-files", "-u", "-z"). - Run(ctx, &git.RunOpts{ + err = gitcmd.NewCommand("ls-files", "-u", "-z"). + Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: lsFilesWriter, Stderr: stderr, @@ -116,7 +116,7 @@ func readUnmergedLsFileLines(ctx context.Context, tmpBasePath string, outputChan }, }) if err != nil { - outputChan <- &lsFileLine{err: fmt.Errorf("git ls-files -u -z: %w", git.ConcatenateError(err, stderr.String()))} + outputChan <- &lsFileLine{err: fmt.Errorf("git ls-files -u -z: %w", gitcmd.ConcatenateError(err, stderr.String()))} } } diff --git a/services/pull/pull.go b/services/pull/pull.go index 20d33b5331..c5bb60ccb1 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -25,6 +25,7 @@ import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/graceful" @@ -511,14 +512,14 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest, return false, fmt.Errorf("GetMergeBase: %w", err) } - cmd := git.NewCommand("diff", "--name-only", "-z").AddDynamicArguments(newCommitID, oldCommitID, base) + cmd := gitcmd.NewCommand("diff", "--name-only", "-z").AddDynamicArguments(newCommitID, oldCommitID, base) stdoutReader, stdoutWriter, err := os.Pipe() if err != nil { return false, fmt.Errorf("unable to open pipe for to run diff: %w", err) } stderr := new(bytes.Buffer) - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: prCtx.tmpBasePath, Stdout: stdoutWriter, Stderr: stderr, @@ -533,7 +534,7 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest, if err == util.ErrNotEmpty { return true, nil } - err = git.ConcatenateError(err, stderr.String()) + err = gitcmd.ConcatenateError(err, stderr.String()) log.Error("Unable to run diff on %s %s %s in tempRepo for PR[%d]%s/%s...%s/%s: Error: %v", newCommitID, oldCommitID, base, @@ -635,7 +636,7 @@ func UpdateRef(ctx context.Context, pr *issues_model.PullRequest) (err error) { return err } - _, _, err = git.NewCommand("update-ref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.HeadCommitID).RunStdString(ctx, &git.RunOpts{Dir: pr.BaseRepo.RepoPath()}) + _, _, err = gitcmd.NewCommand("update-ref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.HeadCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: pr.BaseRepo.RepoPath()}) if err != nil { log.Error("Unable to update ref in base repository for PR[%d] Error: %v", pr.ID, err) } diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 89f150fd92..8750b4288a 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -15,6 +15,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -36,10 +37,10 @@ type prTmpRepoContext struct { errbuf *strings.Builder // any use should be preceded by a Reset and preferably after use } -func (ctx *prTmpRepoContext) RunOpts() *git.RunOpts { +func (ctx *prTmpRepoContext) RunOpts() *gitcmd.RunOpts { ctx.outbuf.Reset() ctx.errbuf.Reset() - return &git.RunOpts{ + return &gitcmd.RunOpts{ Dir: ctx.tmpBasePath, Stdout: ctx.outbuf, Stderr: ctx.errbuf, @@ -101,7 +102,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) remoteRepoName := "head_repo" baseBranch := "base" - fetchArgs := git.TrustedCmdArgs{"--no-tags"} + fetchArgs := gitcmd.TrustedCmdArgs{"--no-tags"} if git.DefaultFeatures().CheckVersionAtLeast("2.25.0") { // Writing the commit graph can be slow and is not needed here fetchArgs = append(fetchArgs, "--no-write-commit-graph") @@ -131,21 +132,21 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) return nil, nil, fmt.Errorf("Unable to add base repository to temporary repo [%s -> tmpBasePath]: %w", pr.BaseRepo.FullName(), err) } - if err := git.NewCommand("remote", "add", "-t").AddDynamicArguments(pr.BaseBranch).AddArguments("-m").AddDynamicArguments(pr.BaseBranch).AddDynamicArguments("origin", baseRepoPath). + if err := gitcmd.NewCommand("remote", "add", "-t").AddDynamicArguments(pr.BaseBranch).AddArguments("-m").AddDynamicArguments(pr.BaseBranch).AddDynamicArguments("origin", baseRepoPath). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to add base repository as origin [%s -> %s]: %v\n%s\n%s", pr, pr.BaseRepo.FullName(), tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() return nil, nil, fmt.Errorf("Unable to add base repository as origin [%s -> tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), err, prCtx.outbuf.String(), prCtx.errbuf.String()) } - if err := git.NewCommand("fetch", "origin").AddArguments(fetchArgs...).AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch). + if err := gitcmd.NewCommand("fetch", "origin").AddArguments(fetchArgs...).AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n%s", pr, pr.BaseRepo.FullName(), pr.BaseBranch, tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() return nil, nil, fmt.Errorf("Unable to fetch origin base branch [%s:%s -> base, original_base in tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), pr.BaseBranch, err, prCtx.outbuf.String(), prCtx.errbuf.String()) } - if err := git.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseBranch). + if err := gitcmd.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseBranch). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to set HEAD as base branch in [%s]: %v\n%s\n%s", pr, tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() @@ -158,7 +159,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) return nil, nil, fmt.Errorf("Unable to add head base repository to temporary repo [%s -> tmpBasePath]: %w", pr.HeadRepo.FullName(), err) } - if err := git.NewCommand("remote", "add").AddDynamicArguments(remoteRepoName, headRepoPath). + if err := gitcmd.NewCommand("remote", "add").AddDynamicArguments(remoteRepoName, headRepoPath). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to add head repository as head_repo [%s -> %s]: %v\n%s\n%s", pr, pr.HeadRepo.FullName(), tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() @@ -176,7 +177,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) } else { headBranch = pr.GetGitHeadRefName() } - if err := git.NewCommand("fetch").AddArguments(fetchArgs...).AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch). + if err := gitcmd.NewCommand("fetch").AddArguments(fetchArgs...).AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch). Run(ctx, prCtx.RunOpts()); err != nil { cancel() if !gitrepo.IsBranchExist(ctx, pr.HeadRepo, pr.HeadBranch) { diff --git a/services/pull/update_rebase.go b/services/pull/update_rebase.go index 9ff062f99c..3b5d3afba5 100644 --- a/services/pull/update_rebase.go +++ b/services/pull/update_rebase.go @@ -12,6 +12,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -27,7 +28,7 @@ func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullReques defer cancel() // Determine the old merge-base before the rebase - we use this for LFS push later on - oldMergeBase, _, _ := git.NewCommand("merge-base").AddDashesAndList(baseBranch, trackingBranch).RunStdString(ctx, &git.RunOpts{Dir: mergeCtx.tmpBasePath}) + oldMergeBase, _, _ := gitcmd.NewCommand("merge-base").AddDashesAndList(baseBranch, trackingBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: mergeCtx.tmpBasePath}) oldMergeBase = strings.TrimSpace(oldMergeBase) // Rebase the tracking branch on to the base as the staging branch @@ -62,7 +63,7 @@ func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullReques headUser = pr.HeadRepo.Owner } - pushCmd := git.NewCommand("push", "-f", "head_repo"). + pushCmd := gitcmd.NewCommand("push", "-f", "head_repo"). AddDynamicArguments(stagingBranch + ":" + git.BranchPrefix + pr.HeadBranch) // Push back to the head repository. @@ -71,7 +72,7 @@ func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullReques mergeCtx.outbuf.Reset() mergeCtx.errbuf.Reset() - if err := pushCmd.Run(ctx, &git.RunOpts{ + if err := pushCmd.Run(ctx, &gitcmd.RunOpts{ Env: repo_module.FullPushingEnvironment( headUser, doer, diff --git a/services/release/release.go b/services/release/release.go index 1e2132bb60..3c5392c993 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -15,6 +15,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -370,8 +371,8 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re } } - if stdout, _, err := git.NewCommand("tag", "-d").AddDashesAndList(rel.TagName). - RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}); err != nil && !strings.Contains(err.Error(), "not found") { + if stdout, _, err := gitcmd.NewCommand("tag", "-d").AddDashesAndList(rel.TagName). + RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}); err != nil && !strings.Contains(err.Error(), "not found") { log.Error("DeleteReleaseByID (git tag -d): %d in %v Failed:\nStdout: %s\nError: %v", rel.ID, repo, stdout, err) return fmt.Errorf("git tag -d: %w", err) } diff --git a/services/repository/check.go b/services/repository/check.go index 46eb4d7e7c..46394ba48e 100644 --- a/services/repository/check.go +++ b/services/repository/check.go @@ -13,7 +13,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -23,7 +23,7 @@ import ( ) // GitFsckRepos calls 'git fsck' to check repository health. -func GitFsckRepos(ctx context.Context, timeout time.Duration, args git.TrustedCmdArgs) error { +func GitFsckRepos(ctx context.Context, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { log.Trace("Doing: GitFsck") if err := db.Iterate( @@ -47,7 +47,7 @@ func GitFsckRepos(ctx context.Context, timeout time.Duration, args git.TrustedCm } // GitFsckRepo calls 'git fsck' to check an individual repository's health. -func GitFsckRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args git.TrustedCmdArgs) error { +func GitFsckRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { log.Trace("Running health check on repository %-v", repo.FullName()) if err := gitrepo.Fsck(ctx, repo, timeout, args); err != nil { log.Warn("Failed to health check repository (%-v): %v", repo.FullName(), err) @@ -59,7 +59,7 @@ func GitFsckRepo(ctx context.Context, repo *repo_model.Repository, timeout time. } // GitGcRepos calls 'git gc' to remove unnecessary files and optimize the local repository -func GitGcRepos(ctx context.Context, timeout time.Duration, args git.TrustedCmdArgs) error { +func GitGcRepos(ctx context.Context, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { log.Trace("Doing: GitGcRepos") if err := db.Iterate( @@ -84,12 +84,12 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args git.TrustedCmdA } // GitGcRepo calls 'git gc' to remove unnecessary files and optimize the local repository -func GitGcRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args git.TrustedCmdArgs) error { +func GitGcRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { log.Trace("Running git gc on %-v", repo) - command := git.NewCommand("gc").AddArguments(args...) + command := gitcmd.NewCommand("gc").AddArguments(args...) var stdout string var err error - stdout, _, err = command.RunStdString(ctx, &git.RunOpts{Timeout: timeout, Dir: repo.RepoPath()}) + stdout, _, err = command.RunStdString(ctx, &gitcmd.RunOpts{Timeout: timeout, Dir: repo.RepoPath()}) if err != nil { log.Error("Repository garbage collection failed for %-v. Stdout: %s\nError: %v", repo, stdout, err) desc := fmt.Sprintf("Repository garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err) diff --git a/services/repository/contributors_graph.go b/services/repository/contributors_graph.go index a4ae505313..a7fb130cb5 100644 --- a/services/repository/contributors_graph.go +++ b/services/repository/contributors_graph.go @@ -19,6 +19,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -125,13 +126,13 @@ func getExtendedCommitStats(repo *git.Repository, revision string /*, limit int _ = stdoutWriter.Close() }() - gitCmd := git.NewCommand("log", "--shortstat", "--no-merges", "--pretty=format:---%n%aN%n%aE%n%as", "--reverse") + gitCmd := gitcmd.NewCommand("log", "--shortstat", "--no-merges", "--pretty=format:---%n%aN%n%aE%n%as", "--reverse") // AddOptionFormat("--max-count=%d", limit) gitCmd.AddDynamicArguments(baseCommit.ID.String()) var extendedCommitStats []*ExtendedCommitStats stderr := new(strings.Builder) - err = gitCmd.Run(repo.Ctx, &git.RunOpts{ + err = gitCmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, Stderr: stderr, diff --git a/services/repository/create.go b/services/repository/create.go index 9f0716c191..3006bfaeaf 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -22,6 +22,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -68,8 +69,8 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir ) // Clone to temporary path and do the init commit. - if stdout, _, err := git.NewCommand("clone").AddDynamicArguments(repo.RepoPath(), tmpDir). - RunStdString(ctx, &git.RunOpts{Dir: "", Env: env}); err != nil { + if stdout, _, err := gitcmd.NewCommand("clone").AddDynamicArguments(repo.RepoPath(), tmpDir). + RunStdString(ctx, &gitcmd.RunOpts{Dir: "", Env: env}); err != nil { log.Error("Failed to clone from %v into %s: stdout: %s\nError: %v", repo, tmpDir, stdout, err) return fmt.Errorf("git clone: %w", err) } @@ -313,7 +314,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, owner *user_model.User, licenses = append(licenses, opts.License) var stdout string - stdout, _, err = git.NewCommand("rev-parse", "HEAD").RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, err = gitcmd.NewCommand("rev-parse", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { log.Error("CreateRepository(git rev-parse HEAD) in %v: Stdout: %s\nError: %v", repo, stdout, err) return nil, fmt.Errorf("CreateRepository(git rev-parse HEAD): %w", err) @@ -474,8 +475,8 @@ func updateGitRepoAfterCreate(ctx context.Context, repo *repo_model.Repository) return fmt.Errorf("checkDaemonExportOK: %w", err) } - if stdout, _, err := git.NewCommand("update-server-info"). - RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}); err != nil { + if stdout, _, err := gitcmd.NewCommand("update-server-info"). + RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}); err != nil { log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err) return fmt.Errorf("CreateRepository(git update-server-info): %w", err) } diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index 11a8744b7f..093072dff2 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -12,6 +12,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -159,12 +160,12 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user stdout := &strings.Builder{} stderr := &strings.Builder{} - cmdApply := git.NewCommand("apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary") + cmdApply := gitcmd.NewCommand("apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary") if git.DefaultFeatures().CheckVersionAtLeast("2.32") { cmdApply.AddArguments("-3") } - if err := cmdApply.Run(ctx, &git.RunOpts{ + if err := cmdApply.Run(ctx, &gitcmd.RunOpts{ Dir: t.basePath, Stdout: stdout, Stderr: stderr, diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index c2f61c8223..dcbe368357 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -17,6 +17,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -53,7 +54,7 @@ func (t *TemporaryUploadRepository) Close() { // Clone the base repository to our path and set branch as the HEAD func (t *TemporaryUploadRepository) Clone(ctx context.Context, branch string, bare bool) error { - cmd := git.NewCommand("clone", "-s", "-b").AddDynamicArguments(branch, t.repo.RepoPath(), t.basePath) + cmd := gitcmd.NewCommand("clone", "-s", "-b").AddDynamicArguments(branch, t.repo.RepoPath(), t.basePath) if bare { cmd.AddArguments("--bare") } @@ -97,7 +98,7 @@ func (t *TemporaryUploadRepository) Init(ctx context.Context, objectFormatName s // SetDefaultIndex sets the git index to our HEAD func (t *TemporaryUploadRepository) SetDefaultIndex(ctx context.Context) error { - if _, _, err := git.NewCommand("read-tree", "HEAD").RunStdString(ctx, &git.RunOpts{Dir: t.basePath}); err != nil { + if _, _, err := gitcmd.NewCommand("read-tree", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}); err != nil { return fmt.Errorf("SetDefaultIndex: %w", err) } return nil @@ -105,7 +106,7 @@ func (t *TemporaryUploadRepository) SetDefaultIndex(ctx context.Context) error { // RefreshIndex looks at the current index and checks to see if merges or updates are needed by checking stat() information. func (t *TemporaryUploadRepository) RefreshIndex(ctx context.Context) error { - if _, _, err := git.NewCommand("update-index", "--refresh").RunStdString(ctx, &git.RunOpts{Dir: t.basePath}); err != nil { + if _, _, err := gitcmd.NewCommand("update-index", "--refresh").RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}); err != nil { return fmt.Errorf("RefreshIndex: %w", err) } return nil @@ -116,8 +117,8 @@ func (t *TemporaryUploadRepository) LsFiles(ctx context.Context, filenames ...st stdOut := new(bytes.Buffer) stdErr := new(bytes.Buffer) - if err := git.NewCommand("ls-files", "-z").AddDashesAndList(filenames...). - Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...). + Run(ctx, &gitcmd.RunOpts{ Dir: t.basePath, Stdout: stdOut, Stderr: stdErr, @@ -152,8 +153,8 @@ func (t *TemporaryUploadRepository) RemoveFilesFromIndex(ctx context.Context, fi } } - if err := git.NewCommand("update-index", "--remove", "-z", "--index-info"). - Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("update-index", "--remove", "-z", "--index-info"). + Run(ctx, &gitcmd.RunOpts{ Dir: t.basePath, Stdin: stdIn, Stdout: stdOut, @@ -169,8 +170,8 @@ func (t *TemporaryUploadRepository) HashObjectAndWrite(ctx context.Context, cont stdOut := new(bytes.Buffer) stdErr := new(bytes.Buffer) - if err := git.NewCommand("hash-object", "-w", "--stdin"). - Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("hash-object", "-w", "--stdin"). + Run(ctx, &gitcmd.RunOpts{ Dir: t.basePath, Stdin: content, Stdout: stdOut, @@ -185,7 +186,7 @@ func (t *TemporaryUploadRepository) HashObjectAndWrite(ctx context.Context, cont // AddObjectToIndex adds the provided object hash to the index with the provided mode and path func (t *TemporaryUploadRepository) AddObjectToIndex(ctx context.Context, mode, objectHash, objectPath string) error { - if _, _, err := git.NewCommand("update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(ctx, &git.RunOpts{Dir: t.basePath}); err != nil { + if _, _, err := gitcmd.NewCommand("update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}); err != nil { stderr := err.Error() if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched { return ErrFilePathInvalid{ @@ -201,7 +202,7 @@ func (t *TemporaryUploadRepository) AddObjectToIndex(ctx context.Context, mode, // WriteTree writes the current index as a tree to the object db and returns its hash func (t *TemporaryUploadRepository) WriteTree(ctx context.Context) (string, error) { - stdout, _, err := git.NewCommand("write-tree").RunStdString(ctx, &git.RunOpts{Dir: t.basePath}) + stdout, _, err := gitcmd.NewCommand("write-tree").RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}) if err != nil { log.Error("Unable to write tree in temporary repo: %s(%s): Error: %v", t.repo.FullName(), t.basePath, err) return "", fmt.Errorf("Unable to write-tree in temporary repo for: %s Error: %w", t.repo.FullName(), err) @@ -219,7 +220,7 @@ func (t *TemporaryUploadRepository) GetLastCommitByRef(ctx context.Context, ref if ref == "" { ref = "HEAD" } - stdout, _, err := git.NewCommand("rev-parse").AddDynamicArguments(ref).RunStdString(ctx, &git.RunOpts{Dir: t.basePath}) + stdout, _, err := gitcmd.NewCommand("rev-parse").AddDynamicArguments(ref).RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}) if err != nil { log.Error("Unable to get last ref for %s in temporary repo: %s(%s): Error: %v", ref, t.repo.FullName(), t.basePath, err) return "", fmt.Errorf("Unable to rev-parse %s in temporary repo for: %s Error: %w", ref, t.repo.FullName(), err) @@ -287,7 +288,7 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit _, _ = messageBytes.WriteString(opts.CommitMessage) _, _ = messageBytes.WriteString("\n") - cmdCommitTree := git.NewCommand("commit-tree").AddDynamicArguments(opts.TreeHash) + cmdCommitTree := gitcmd.NewCommand("commit-tree").AddDynamicArguments(opts.TreeHash) if opts.ParentCommitID != "" { cmdCommitTree.AddOptionValues("-p", opts.ParentCommitID) } @@ -337,7 +338,7 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) if err := cmdCommitTree. - Run(ctx, &git.RunOpts{ + Run(ctx, &gitcmd.RunOpts{ Env: env, Dir: t.basePath, Stdin: messageBytes, @@ -389,8 +390,8 @@ func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context) (*gitdiff.Dif }() stderr := new(bytes.Buffer) var diff *gitdiff.Diff - err = git.NewCommand("diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD"). - Run(ctx, &git.RunOpts{ + err = gitcmd.NewCommand("diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD"). + Run(ctx, &gitcmd.RunOpts{ Timeout: 30 * time.Second, Dir: t.basePath, Stdout: stdoutWriter, diff --git a/services/repository/fork.go b/services/repository/fork.go index 8bd3498b17..05909f0e0d 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -146,13 +147,13 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork } // 3 - Clone the repository - cloneCmd := git.NewCommand("clone", "--bare") + cloneCmd := gitcmd.NewCommand("clone", "--bare") if opts.SingleBranch != "" { cloneCmd.AddArguments("--single-branch", "--branch").AddDynamicArguments(opts.SingleBranch) } var stdout []byte if stdout, _, err = cloneCmd.AddDynamicArguments(opts.BaseRepo.RepoPath(), repo.RepoPath()). - RunStdBytes(ctx, &git.RunOpts{Timeout: 10 * time.Minute}); err != nil { + RunStdBytes(ctx, &gitcmd.RunOpts{Timeout: 10 * time.Minute}); err != nil { log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", repo, opts.BaseRepo, stdout, err) return nil, fmt.Errorf("git clone: %w", err) } diff --git a/services/repository/generate.go b/services/repository/generate.go index b92d148d21..c03d9b51a7 100644 --- a/services/repository/generate.go +++ b/services/repository/generate.go @@ -18,6 +18,7 @@ import ( git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/log" @@ -234,8 +235,8 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r return err } - if stdout, _, err := git.NewCommand("remote", "add", "origin").AddDynamicArguments(repo.RepoPath()). - RunStdString(ctx, &git.RunOpts{Dir: tmpDir, Env: env}); err != nil { + if stdout, _, err := gitcmd.NewCommand("remote", "add", "origin").AddDynamicArguments(repo.RepoPath()). + RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir, Env: env}); err != nil { log.Error("Unable to add %v as remote origin to temporary repo to %s: stdout %s\nError: %v", repo, tmpDir, stdout, err) return fmt.Errorf("git remote add: %w", err) } diff --git a/services/repository/gitgraph/graph.go b/services/repository/gitgraph/graph.go index d06d18c1b4..3bc97b7bbc 100644 --- a/services/repository/gitgraph/graph.go +++ b/services/repository/gitgraph/graph.go @@ -11,6 +11,7 @@ import ( "strings" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" ) @@ -22,7 +23,7 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo page = 1 } - graphCmd := git.NewCommand("log", "--graph", "--date-order", "--decorate=full") + graphCmd := gitcmd.NewCommand("log", "--graph", "--date-order", "--decorate=full") if hidePRRefs { graphCmd.AddArguments("--exclude=" + git.PullPrefix + "*") @@ -53,7 +54,7 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo scanner := bufio.NewScanner(stdoutReader) - if err := graphCmd.Run(r.Ctx, &git.RunOpts{ + if err := graphCmd.Run(r.Ctx, &gitcmd.RunOpts{ Dir: r.Path, Stdout: stdoutWriter, Stderr: stderr, diff --git a/services/repository/init.go b/services/repository/init.go index 1eeeb4aa4f..c905d1f6a3 100644 --- a/services/repository/init.go +++ b/services/repository/init.go @@ -11,7 +11,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -33,13 +33,13 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi committerName := sig.Name committerEmail := sig.Email - if stdout, _, err := git.NewCommand("add", "--all"). - RunStdString(ctx, &git.RunOpts{Dir: tmpPath}); err != nil { + if stdout, _, err := gitcmd.NewCommand("add", "--all"). + RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpPath}); err != nil { log.Error("git add --all failed: Stdout: %s\nError: %v", stdout, err) return fmt.Errorf("git add --all: %w", err) } - cmd := git.NewCommand("commit", "--message=Initial commit"). + cmd := gitcmd.NewCommand("commit", "--message=Initial commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email) sign, key, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) @@ -64,7 +64,7 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi ) if stdout, _, err := cmd. - RunStdString(ctx, &git.RunOpts{Dir: tmpPath, Env: env}); err != nil { + RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpPath, Env: env}); err != nil { log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.LogString(), stdout, err) return fmt.Errorf("git commit: %w", err) } @@ -73,8 +73,8 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi defaultBranch = setting.Repository.DefaultBranch } - if stdout, _, err := git.NewCommand("push", "origin").AddDynamicArguments("HEAD:"+defaultBranch). - RunStdString(ctx, &git.RunOpts{Dir: tmpPath, Env: repo_module.InternalPushingEnvironment(u, repo)}); err != nil { + if stdout, _, err := gitcmd.NewCommand("push", "origin").AddDynamicArguments("HEAD:"+defaultBranch). + RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpPath, Env: repo_module.InternalPushingEnvironment(u, repo)}); err != nil { log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err) return fmt.Errorf("git push: %w", err) } diff --git a/services/repository/migrate.go b/services/repository/migrate.go index 66622f1601..db1f020b9f 100644 --- a/services/repository/migrate.go +++ b/services/repository/migrate.go @@ -16,6 +16,7 @@ import ( unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" @@ -225,9 +226,9 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, // this is necessary for sync local tags from remote configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName()) - if stdout, _, err := git.NewCommand("config"). + if stdout, _, err := gitcmd.NewCommand("config"). AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`). - RunStdString(ctx, &git.RunOpts{Dir: repoPath}); err != nil { + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}); err != nil { log.Error("MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*) in %v: Stdout: %s\nError: %v", repo, stdout, err) return repo, fmt.Errorf("error in MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*): %w", err) } diff --git a/tests/integration/api_repo_git_tags_test.go b/tests/integration/api_repo_git_tags_test.go index d1d742cd80..6bdb40f786 100644 --- a/tests/integration/api_repo_git_tags_test.go +++ b/tests/integration/api_repo_git_tags_test.go @@ -12,7 +12,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -30,8 +30,8 @@ func TestAPIGitTags(t *testing.T) { token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) // Set up git config for the tagger - _ = git.NewCommand("config", "user.name").AddDynamicArguments(user.Name).Run(t.Context(), &git.RunOpts{Dir: repo.RepoPath()}) - _ = git.NewCommand("config", "user.email").AddDynamicArguments(user.Email).Run(t.Context(), &git.RunOpts{Dir: repo.RepoPath()}) + _ = gitcmd.NewCommand("config", "user.name").AddDynamicArguments(user.Name).Run(t.Context(), &gitcmd.RunOpts{Dir: repo.RepoPath()}) + _ = gitcmd.NewCommand("config", "user.email").AddDynamicArguments(user.Email).Run(t.Context(), &gitcmd.RunOpts{Dir: repo.RepoPath()}) gitRepo, _ := gitrepo.OpenRepository(t.Context(), repo) defer gitRepo.Close() diff --git a/tests/integration/git_general_test.go b/tests/integration/git_general_test.go index 1f6d3c940f..d243f0f4af 100644 --- a/tests/integration/git_general_test.go +++ b/tests/integration/git_general_test.go @@ -29,6 +29,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/commitstatus" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -193,9 +194,9 @@ func lfsCommitAndPushTest(t *testing.T, dstPath string, sizes ...int) (pushedFil t.Run("CommitAndPushLFS", func(t *testing.T) { defer tests.PrintCurrentTest(t)() prefix := "lfs-data-file-" - err := git.NewCommand("lfs").AddArguments("install").Run(t.Context(), &git.RunOpts{Dir: dstPath}) + err := gitcmd.NewCommand("lfs").AddArguments("install").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) - _, _, err = git.NewCommand("lfs").AddArguments("track").AddDynamicArguments(prefix+"*").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("lfs").AddArguments("track").AddDynamicArguments(prefix+"*").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) err = git.AddChanges(t.Context(), dstPath, false, ".gitattributes") assert.NoError(t, err) @@ -311,20 +312,20 @@ func lockTest(t *testing.T, repoPath string) { } func lockFileTest(t *testing.T, filename, repoPath string) { - _, _, err := git.NewCommand("lfs").AddArguments("locks").RunStdString(t.Context(), &git.RunOpts{Dir: repoPath}) + _, _, err := gitcmd.NewCommand("lfs").AddArguments("locks").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: repoPath}) assert.NoError(t, err) - _, _, err = git.NewCommand("lfs").AddArguments("lock").AddDynamicArguments(filename).RunStdString(t.Context(), &git.RunOpts{Dir: repoPath}) + _, _, err = gitcmd.NewCommand("lfs").AddArguments("lock").AddDynamicArguments(filename).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: repoPath}) assert.NoError(t, err) - _, _, err = git.NewCommand("lfs").AddArguments("locks").RunStdString(t.Context(), &git.RunOpts{Dir: repoPath}) + _, _, err = gitcmd.NewCommand("lfs").AddArguments("locks").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: repoPath}) assert.NoError(t, err) - _, _, err = git.NewCommand("lfs").AddArguments("unlock").AddDynamicArguments(filename).RunStdString(t.Context(), &git.RunOpts{Dir: repoPath}) + _, _, err = gitcmd.NewCommand("lfs").AddArguments("unlock").AddDynamicArguments(filename).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: repoPath}) assert.NoError(t, err) } func doCommitAndPush(t *testing.T, size int, repoPath, prefix string) string { name, err := generateCommitWithNewData(t.Context(), size, repoPath, "user2@example.com", "User Two", prefix) assert.NoError(t, err) - _, _, err = git.NewCommand("push", "origin", "master").RunStdString(t.Context(), &git.RunOpts{Dir: repoPath}) // Push + _, _, err = gitcmd.NewCommand("push", "origin", "master").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: repoPath}) // Push assert.NoError(t, err) return name } @@ -424,7 +425,7 @@ func doBranchProtectPRMerge(baseCtx *APITestContext, dstPath string) func(t *tes // Try to force push without force push permissions, which should fail t.Run("ForcePushWithoutForcePermissions", func(t *testing.T) { t.Run("CreateDivergentHistory", func(t *testing.T) { - git.NewCommand("reset", "--hard", "HEAD~1").Run(t.Context(), &git.RunOpts{Dir: dstPath}) + gitcmd.NewCommand("reset", "--hard", "HEAD~1").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) _, err := generateCommitWithNewData(t.Context(), testFileSizeSmall, dstPath, "user2@example.com", "User Two", "branch-data-file-new") assert.NoError(t, err) }) @@ -847,7 +848,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string }) t.Run("Push", func(t *testing.T) { - err := git.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+headBranch).Run(t.Context(), &git.RunOpts{Dir: dstPath}) + err := gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+headBranch).Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.NoError(t, err) unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+1) @@ -865,7 +866,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string assert.Contains(t, "Testing commit 1", prMsg.Body) assert.Equal(t, commit, prMsg.Head.Sha) - _, _, err = git.NewCommand("push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/"+headBranch).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/"+headBranch).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.NoError(t, err) unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+2) @@ -913,7 +914,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string }) t.Run("Push2", func(t *testing.T) { - err := git.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+headBranch).Run(t.Context(), &git.RunOpts{Dir: dstPath}) + err := gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+headBranch).Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.NoError(t, err) unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+2) @@ -923,7 +924,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, headBranch string assert.False(t, prMsg.HasMerged) assert.Equal(t, commit, prMsg.Head.Sha) - _, _, err = git.NewCommand("push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/"+headBranch).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/"+headBranch).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.NoError(t, err) unittest.AssertCount(t, &issues_model.PullRequest{}, pullNum+2) diff --git a/tests/integration/git_helper_for_declarative_test.go b/tests/integration/git_helper_for_declarative_test.go index dda8f694a7..91c30f7278 100644 --- a/tests/integration/git_helper_for_declarative_test.go +++ b/tests/integration/git_helper_for_declarative_test.go @@ -16,6 +16,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/ssh" "code.gitea.io/gitea/modules/util" @@ -121,7 +122,7 @@ func doGitInitTestRepository(dstPath string) func(*testing.T) { // Init repository in dstPath assert.NoError(t, git.InitRepository(t.Context(), dstPath, false, git.Sha1ObjectFormat.Name())) // forcibly set default branch to master - _, _, err := git.NewCommand("symbolic-ref", "HEAD", git.BranchPrefix+"master").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD", git.BranchPrefix+"master").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(dstPath, "README.md"), []byte("# Testing Repository\n\nOriginally created in: "+dstPath), 0o644)) assert.NoError(t, git.AddChanges(t.Context(), dstPath, true)) @@ -140,21 +141,21 @@ func doGitInitTestRepository(dstPath string) func(*testing.T) { func doGitAddRemote(dstPath, remoteName string, u *url.URL) func(*testing.T) { return func(t *testing.T) { - _, _, err := git.NewCommand("remote", "add").AddDynamicArguments(remoteName, u.String()).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("remote", "add").AddDynamicArguments(remoteName, u.String()).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) } } func doGitPushTestRepository(dstPath string, args ...string) func(*testing.T) { return func(t *testing.T) { - _, _, err := git.NewCommand("push", "-u").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("push", "-u").AddArguments(gitcmd.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) } } func doGitPushTestRepositoryFail(dstPath string, args ...string) func(*testing.T) { return func(t *testing.T) { - _, _, err := git.NewCommand("push").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("push").AddArguments(gitcmd.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.Error(t, err) } } @@ -179,28 +180,28 @@ func doGitAddSomeCommits(dstPath, branch string) func(*testing.T) { func doGitCreateBranch(dstPath, branch string) func(*testing.T) { return func(t *testing.T) { - _, _, err := git.NewCommand("checkout", "-b").AddDynamicArguments(branch).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("checkout", "-b").AddDynamicArguments(branch).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) } } func doGitCheckoutBranch(dstPath string, args ...string) func(*testing.T) { return func(t *testing.T) { - _, _, err := git.NewCommand().AddArguments("checkout").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand().AddArguments("checkout").AddArguments(gitcmd.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) } } func doGitMerge(dstPath string, args ...string) func(*testing.T) { return func(t *testing.T) { - _, _, err := git.NewCommand("merge").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("merge").AddArguments(gitcmd.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) } } func doGitPull(dstPath string, args ...string) func(*testing.T) { return func(t *testing.T) { - _, _, err := git.NewCommand().AddArguments("pull").AddArguments(git.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand().AddArguments("pull").AddArguments(gitcmd.ToTrustedCmdArgs(args)...).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) } } diff --git a/tests/integration/git_lfs_ssh_test.go b/tests/integration/git_lfs_ssh_test.go index 64a403f513..6bb9a748b4 100644 --- a/tests/integration/git_lfs_ssh_test.go +++ b/tests/integration/git_lfs_ssh_test.go @@ -11,7 +11,7 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/common" @@ -45,7 +45,7 @@ func TestGitLFSSSH(t *testing.T) { setting.LFS.AllowPureSSH = true require.NoError(t, cfg.Save()) - _, _, cmdErr := git.NewCommand("config", "lfs.sshtransfer", "always").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, cmdErr := gitcmd.NewCommand("config", "lfs.sshtransfer", "always").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, cmdErr) lfsCommitAndPushTest(t, dstPath, 10) }) diff --git a/tests/integration/git_misc_test.go b/tests/integration/git_misc_test.go index eb039c7c1c..2510bc648f 100644 --- a/tests/integration/git_misc_test.go +++ b/tests/integration/git_misc_test.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" files_service "code.gitea.io/gitea/services/repository/files" @@ -100,10 +101,10 @@ func TestAgitPullPush(t *testing.T) { assert.NoError(t, err) // push to create an agit pull request - err = git.NewCommand("push", "origin", + err = gitcmd.NewCommand("push", "origin", "-o", "title=test-title", "-o", "description=test-description", "HEAD:refs/for/master/test-agit-push", - ).Run(t.Context(), &git.RunOpts{Dir: dstPath}) + ).Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) // check pull request exist @@ -117,20 +118,20 @@ func TestAgitPullPush(t *testing.T) { assert.NoError(t, err) // push 2 - err = git.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push").Run(t.Context(), &git.RunOpts{Dir: dstPath}) + err = gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) // reset to first commit - err = git.NewCommand("reset", "--hard", "HEAD~1").Run(t.Context(), &git.RunOpts{Dir: dstPath}) + err = gitcmd.NewCommand("reset", "--hard", "HEAD~1").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) // test force push without confirm - _, stderr, err := git.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, stderr, err := gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.Error(t, err) assert.Contains(t, stderr, "[remote rejected] HEAD -> refs/for/master/test-agit-push (request `force-push` push option)") // test force push with confirm - err = git.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push", "-o", "force-push").Run(t.Context(), &git.RunOpts{Dir: dstPath}) + err = gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-push", "-o", "force-push").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) }) } @@ -156,10 +157,10 @@ func TestAgitReviewStaleness(t *testing.T) { assert.NoError(t, err) // create PR via agit - err = git.NewCommand("push", "origin", + err = gitcmd.NewCommand("push", "origin", "-o", "title=Test agit Review Staleness", "-o", "description=Testing review staleness", "HEAD:refs/for/master/test-agit-review", - ).Run(t.Context(), &git.RunOpts{Dir: dstPath}) + ).Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ @@ -199,7 +200,7 @@ func TestAgitReviewStaleness(t *testing.T) { _, err = generateCommitWithNewData(t.Context(), testFileSizeSmall, dstPath, "user2@example.com", "User Two", "updated-") assert.NoError(t, err) - err = git.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-review").Run(t.Context(), &git.RunOpts{Dir: dstPath}) + err = gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master/test-agit-review").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) // Reload PR to get updated commit ID diff --git a/tests/integration/git_push_test.go b/tests/integration/git_push_test.go index 577b32a89b..b02387c3b9 100644 --- a/tests/integration/git_push_test.go +++ b/tests/integration/git_push_test.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" repo_service "code.gitea.io/gitea/services/repository" "github.com/stretchr/testify/assert" @@ -204,8 +205,8 @@ func TestPushPullRefs(t *testing.T) { dstPath := t.TempDir() doGitClone(dstPath, u)(t) - cmd := git.NewCommand("push", "--delete", "origin", "refs/pull/2/head") - stdout, stderr, err := cmd.RunStdString(t.Context(), &git.RunOpts{ + cmd := gitcmd.NewCommand("push", "--delete", "origin", "refs/pull/2/head") + stdout, stderr, err := cmd.RunStdString(t.Context(), &gitcmd.RunOpts{ Dir: dstPath, }) assert.Error(t, err) diff --git a/tests/integration/pull_create_test.go b/tests/integration/pull_create_test.go index aeff5e2b4e..18f7e80e82 100644 --- a/tests/integration/pull_create_test.go +++ b/tests/integration/pull_create_test.go @@ -13,7 +13,7 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/tests" @@ -265,7 +265,7 @@ func TestCreateAgitPullWithReadPermission(t *testing.T) { t.Run("add commit", doGitAddSomeCommits(dstPath, "master")) t.Run("do agit pull create", func(t *testing.T) { - err := git.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+"test-topic").Run(t.Context(), &git.RunOpts{Dir: dstPath}) + err := gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic="+"test-topic").Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) }) }) diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index bbcdba2531..72bf8ab4b0 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -27,6 +27,7 @@ import ( "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/commitstatus" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/queue" "code.gitea.io/gitea/modules/setting" @@ -294,12 +295,12 @@ func TestCantMergeUnrelated(t *testing.T) { }) path := repo_model.RepoPath(user1.Name, repo1.Name) - err := git.NewCommand("read-tree", "--empty").Run(t.Context(), &git.RunOpts{Dir: path}) + err := gitcmd.NewCommand("read-tree", "--empty").Run(t.Context(), &gitcmd.RunOpts{Dir: path}) assert.NoError(t, err) stdin := strings.NewReader("Unrelated File") var stdout strings.Builder - err = git.NewCommand("hash-object", "-w", "--stdin").Run(t.Context(), &git.RunOpts{ + err = gitcmd.NewCommand("hash-object", "-w", "--stdin").Run(t.Context(), &gitcmd.RunOpts{ Dir: path, Stdin: stdin, Stdout: &stdout, @@ -308,10 +309,10 @@ func TestCantMergeUnrelated(t *testing.T) { assert.NoError(t, err) sha := strings.TrimSpace(stdout.String()) - _, _, err = git.NewCommand("update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments("100644", sha, "somewher-over-the-rainbow").RunStdString(t.Context(), &git.RunOpts{Dir: path}) + _, _, err = gitcmd.NewCommand("update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments("100644", sha, "somewher-over-the-rainbow").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: path}) assert.NoError(t, err) - treeSha, _, err := git.NewCommand("write-tree").RunStdString(t.Context(), &git.RunOpts{Dir: path}) + treeSha, _, err := gitcmd.NewCommand("write-tree").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: path}) assert.NoError(t, err) treeSha = strings.TrimSpace(treeSha) @@ -331,8 +332,8 @@ func TestCantMergeUnrelated(t *testing.T) { _, _ = messageBytes.WriteString("\n") stdout.Reset() - err = git.NewCommand("commit-tree").AddDynamicArguments(treeSha). - Run(t.Context(), &git.RunOpts{ + err = gitcmd.NewCommand("commit-tree").AddDynamicArguments(treeSha). + Run(t.Context(), &gitcmd.RunOpts{ Env: env, Dir: path, Stdin: messageBytes, @@ -341,7 +342,7 @@ func TestCantMergeUnrelated(t *testing.T) { assert.NoError(t, err) commitSha := strings.TrimSpace(stdout.String()) - _, _, err = git.NewCommand("branch", "unrelated").AddDynamicArguments(commitSha).RunStdString(t.Context(), &git.RunOpts{Dir: path}) + _, _, err = gitcmd.NewCommand("branch", "unrelated").AddDynamicArguments(commitSha).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: path}) assert.NoError(t, err) testEditFileToNewBranch(t, session, "user1", "repo1", "master", "conflict", "README.md", "Hello, World (Edited Once)\n") @@ -925,13 +926,13 @@ func TestPullAutoMergeAfterCommitStatusSucceedAndApprovalForAgitFlow(t *testing. stderrBuf := &bytes.Buffer{} - err = git.NewCommand("push", "origin", "HEAD:refs/for/master", "-o"). + err = gitcmd.NewCommand("push", "origin", "HEAD:refs/for/master", "-o"). AddDynamicArguments(`topic=test/head2`). AddArguments("-o"). AddDynamicArguments(`title="create a test pull request with agit"`). AddArguments("-o"). AddDynamicArguments(`description="This PR is a test pull request which created with agit"`). - Run(t.Context(), &git.RunOpts{Dir: dstPath, Stderr: stderrBuf}) + Run(t.Context(), &gitcmd.RunOpts{Dir: dstPath, Stderr: stderrBuf}) assert.NoError(t, err) assert.Contains(t, stderrBuf.String(), setting.AppURL+"user2/repo1/pulls/6") diff --git a/tests/integration/repo_tag_test.go b/tests/integration/repo_tag_test.go index 2ee492c4b5..98581cb6da 100644 --- a/tests/integration/repo_tag_test.go +++ b/tests/integration/repo_tag_test.go @@ -15,7 +15,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/services/release" "code.gitea.io/gitea/tests" @@ -55,10 +55,10 @@ func TestCreateNewTagProtected(t *testing.T) { doGitClone(dstPath, u)(t) - _, _, err := git.NewCommand("tag", "v-2").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("tag", "v-2").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) - _, _, err = git.NewCommand("push", "--tags").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "--tags").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.Error(t, err) assert.Contains(t, err.Error(), "Tag v-2 is protected") }) @@ -75,20 +75,20 @@ func TestCreateNewTagProtected(t *testing.T) { doGitClone(dstPath, u)(t) - _, _, err := git.NewCommand("tag", "v-1.1", "-m", "force update", "--force").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("tag", "v-1.1", "-m", "force update", "--force").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.NoError(t, err) - _, _, err = git.NewCommand("push", "--tags").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "--tags").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.NoError(t, err) - _, _, err = git.NewCommand("tag", "v-1.1", "-m", "force update v2", "--force").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("tag", "v-1.1", "-m", "force update v2", "--force").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.NoError(t, err) - _, _, err = git.NewCommand("push", "--tags").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "--tags").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.Error(t, err) assert.Contains(t, err.Error(), "the tag already exists in the remote") - _, _, err = git.NewCommand("push", "--tags", "--force").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "--tags", "--force").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) require.NoError(t, err) req := NewRequestf(t, "GET", "/%s/releases/tag/v-1.1", repo.FullName()) resp := MakeRequest(t, req, http.StatusOK) @@ -137,15 +137,15 @@ func TestRepushTag(t *testing.T) { doGitClone(dstPath, u)(t) // create and push a tag - _, _, err := git.NewCommand("tag", "v2.0").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err := gitcmd.NewCommand("tag", "v2.0").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) - _, _, err = git.NewCommand("push", "origin", "--tags", "v2.0").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "origin", "--tags", "v2.0").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) // create a release for the tag createdRelease := createNewReleaseUsingAPI(t, token, owner, repo, "v2.0", "", "Release of v2.0", "desc") assert.False(t, createdRelease.IsDraft) // delete the tag - _, _, err = git.NewCommand("push", "origin", "--delete", "v2.0").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "origin", "--delete", "v2.0").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) // query the release by API and it should be a draft req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, "v2.0")) @@ -154,7 +154,7 @@ func TestRepushTag(t *testing.T) { DecodeJSON(t, resp, &respRelease) assert.True(t, respRelease.IsDraft) // re-push the tag - _, _, err = git.NewCommand("push", "origin", "--tags", "v2.0").RunStdString(t.Context(), &git.RunOpts{Dir: dstPath}) + _, _, err = gitcmd.NewCommand("push", "origin", "--tags", "v2.0").RunStdString(t.Context(), &gitcmd.RunOpts{Dir: dstPath}) assert.NoError(t, err) // query the release by API and it should not be a draft req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, "v2.0"))