]> source.dussan.org Git - gitea.git/commitdiff
Refactor git command arguments and make all arguments to be safe to be used (#21535)
authorwxiaoguang <wxiaoguang@gmail.com>
Sun, 23 Oct 2022 14:44:45 +0000 (22:44 +0800)
committerGitHub <noreply@github.com>
Sun, 23 Oct 2022 14:44:45 +0000 (22:44 +0800)
Follow #21464

Make all git command arguments strictly safe. Most changes are one-to-one replacing, keep all existing logic.

71 files changed:
models/migrations/v128.go
models/migrations/v134.go
modules/doctor/heads.go
modules/doctor/mergebase.go
modules/git/command.go
modules/git/commit.go
modules/git/diff.go
modules/git/git.go
modules/git/log_name_status.go
modules/git/pipeline/revlist.go
modules/git/remote.go
modules/git/repo.go
modules/git/repo_archive.go
modules/git/repo_attribute.go
modules/git/repo_blame.go
modules/git/repo_branch.go
modules/git/repo_branch_nogogit.go
modules/git/repo_commit.go
modules/git/repo_commit_gogit.go
modules/git/repo_commit_nogogit.go
modules/git/repo_compare.go
modules/git/repo_index.go
modules/git/repo_stats.go
modules/git/repo_tag.go
modules/git/repo_tag_nogogit.go
modules/git/repo_tree.go
modules/git/repo_tree_gogit.go
modules/git/tree.go
modules/git/tree_nogogit.go
modules/gitgraph/graph.go
modules/indexer/code/bleve.go
modules/indexer/code/elastic_search.go
modules/indexer/code/git.go
modules/repository/generate.go
modules/repository/init.go
modules/repository/push.go
routers/private/hook_pre_receive.go
routers/private/hook_verification.go
routers/web/repo/blame.go
routers/web/repo/compare.go
routers/web/repo/http.go
routers/web/repo/lfs.go
routers/web/repo/pull.go
routers/web/repo/view.go
services/agit/agit.go
services/cron/tasks_basic.go
services/cron/tasks_extended.go
services/gitdiff/gitdiff.go
services/gitdiff/gitdiff_test.go
services/migrations/dump.go
services/migrations/gitea_uploader.go
services/migrations/gitea_uploader_test.go
services/mirror/mirror_pull.go
services/mirror/mirror_push.go
services/pull/check.go
services/pull/merge.go
services/pull/patch.go
services/pull/pull.go
services/pull/temp_repo.go
services/release/release.go
services/repository/check.go
services/repository/files/patch.go
services/repository/files/temp_repo.go
services/repository/files/update.go
services/repository/files/upload.go
services/repository/fork.go
tests/integration/api_repo_git_tags_test.go
tests/integration/git_clone_wiki_test.go
tests/integration/git_helper_for_declarative_test.go
tests/integration/git_test.go
tests/integration/pull_merge_test.go

index 2aa68f9b6474de485cb4a94a0726c6c50ce700a3..aba0ed6897680fd0bc9e948a0adc5b5f0fd2e03c 100644 (file)
@@ -83,17 +83,17 @@ func fixMergeBase(x *xorm.Engine) error {
 
                        if !pr.HasMerged {
                                var err error
-                               pr.MergeBase, _, err = git.NewCommand(git.DefaultContext, "merge-base", "--", pr.BaseBranch, gitRefName).RunStdString(&git.RunOpts{Dir: repoPath})
+                               pr.MergeBase, _, err = git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(&git.RunOpts{Dir: repoPath})
                                if err != nil {
                                        var err2 error
-                                       pr.MergeBase, _, err2 = git.NewCommand(git.DefaultContext, "rev-parse", git.BranchPrefix+pr.BaseBranch).RunStdString(&git.RunOpts{Dir: repoPath})
+                                       pr.MergeBase, _, err2 = git.NewCommand(git.DefaultContext, "rev-parse").AddDynamicArguments(git.BranchPrefix + pr.BaseBranch).RunStdString(&git.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(git.DefaultContext, "rev-list", "--parents", "-n", "1"pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
+                               parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.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
@@ -103,10 +103,11 @@ func fixMergeBase(x *xorm.Engine) error {
                                        continue
                                }
 
-                               args := append([]string{"merge-base", "--"}, parents[1:]...)
-                               args = append(args, gitRefName)
+                               refs := append([]string{}, parents[1:]...)
+                               refs = append(refs, gitRefName)
+                               cmd := git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(refs...)
 
-                               pr.MergeBase, _, err = git.NewCommand(git.DefaultContext, args...).RunStdString(&git.RunOpts{Dir: repoPath})
+                               pr.MergeBase, _, err = cmd.RunStdString(&git.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
index 16e8ec8e9425b1670794a1507946218fe8f013cc..06d0f8276ac19c085fb4f8a777eaa8cd1c7760d3 100644 (file)
@@ -80,7 +80,7 @@ func refixMergeBase(x *xorm.Engine) error {
 
                        gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index)
 
-                       parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1"pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
+                       parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.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
@@ -91,10 +91,11 @@ func refixMergeBase(x *xorm.Engine) error {
                        }
 
                        // we should recalculate
-                       args := append([]string{"merge-base", "--"}, parents[1:]...)
-                       args = append(args, gitRefName)
+                       refs := append([]string{}, parents[1:]...)
+                       refs = append(refs, gitRefName)
+                       cmd := git.NewCommand(git.DefaultContext, "merge-base").AddDashesAndList(refs...)
 
-                       pr.MergeBase, _, err = git.NewCommand(git.DefaultContext, args...).RunStdString(&git.RunOpts{Dir: repoPath})
+                       pr.MergeBase, _, err = cmd.RunStdString(&git.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
index ec14aa4eadb1b89f3d6c0f69b340b4422531e109..7f3b2a8a029636049bd805f2eefdc4d4d0144304 100644 (file)
@@ -21,7 +21,7 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool)
                numRepos++
                runOpts := &git.RunOpts{Dir: repo.RepoPath()}
 
-               _, _, defaultBranchErr := git.NewCommand(ctx, "rev-parse", "--", repo.DefaultBranch).RunStdString(runOpts)
+               _, _, defaultBranchErr := git.NewCommand(ctx, "rev-parse").AddDashesAndList(repo.DefaultBranch).RunStdString(runOpts)
 
                head, _, headErr := git.NewCommand(ctx, "symbolic-ref", "--short", "HEAD").RunStdString(runOpts)
 
@@ -49,7 +49,7 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool)
                }
 
                // otherwise, let's try fixing HEAD
-               err := git.NewCommand(ctx, "symbolic-ref", "--", "HEAD", repo.DefaultBranch).Run(runOpts)
+               err := git.NewCommand(ctx, "symbolic-ref").AddDashesAndList("HEAD", repo.DefaultBranch).Run(runOpts)
                if err != nil {
                        logger.Warn("Failed to fix HEAD for %s/%s: %v", repo.OwnerName, repo.Name, err)
                        return nil
index 46369290a13d71ea94742f1956a05337466adb69..4a10c72e6e79b02a15e1f27474172ee6ef8110f8 100644 (file)
@@ -44,17 +44,17 @@ func checkPRMergeBase(ctx context.Context, logger log.Logger, autofix bool) erro
 
                        if !pr.HasMerged {
                                var err error
-                               pr.MergeBase, _, err = git.NewCommand(ctx, "merge-base", "--", pr.BaseBranch, pr.GetGitRefName()).RunStdString(&git.RunOpts{Dir: repoPath})
+                               pr.MergeBase, _, err = git.NewCommand(ctx, "merge-base").AddDashesAndList(pr.BaseBranch, pr.GetGitRefName()).RunStdString(&git.RunOpts{Dir: repoPath})
                                if err != nil {
                                        var err2 error
-                                       pr.MergeBase, _, err2 = git.NewCommand(ctx, "rev-parse", git.BranchPrefix+pr.BaseBranch).RunStdString(&git.RunOpts{Dir: repoPath})
+                                       pr.MergeBase, _, err2 = git.NewCommand(ctx, "rev-parse").AddDynamicArguments(git.BranchPrefix + pr.BaseBranch).RunStdString(&git.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(ctx, "rev-list", "--parents", "-n", "1"pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
+                               parentsString, _, err := git.NewCommand(ctx, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.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,10 +64,10 @@ func checkPRMergeBase(ctx context.Context, logger log.Logger, autofix bool) erro
                                        return nil
                                }
 
-                               args := append([]string{"merge-base", "--"}, parents[1:]...)
-                               args = append(args, pr.GetGitRefName())
-
-                               pr.MergeBase, _, err = git.NewCommand(ctx, args...).RunStdString(&git.RunOpts{Dir: repoPath})
+                               refs := append([]string{}, parents[1:]...)
+                               refs = append(refs, pr.GetGitRefName())
+                               cmd := git.NewCommand(ctx, "merge-base").AddDashesAndList(refs...)
+                               pr.MergeBase, _, err = cmd.RunStdString(&git.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
index ed06dd9b08de946b1a6d0944cc0137cef7a574b0..abf40b0cd76b3c6e013b156368fa5a510b604ff1 100644 (file)
@@ -24,7 +24,7 @@ import (
 
 var (
        // globalCommandArgs global command args for external package setting
-       globalCommandArgs []string
+       globalCommandArgs []CmdArg
 
        // defaultCommandExecutionTimeout default command execution timeout duration
        defaultCommandExecutionTimeout = 360 * time.Second
@@ -43,6 +43,8 @@ type Command struct {
        brokenArgs       []string
 }
 
+type CmdArg string
+
 func (c *Command) String() string {
        if len(c.args) == 0 {
                return c.name
@@ -52,13 +54,18 @@ func (c *Command) String() string {
 
 // NewCommand creates and returns a new Git Command based on given command and arguments.
 // Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
-func NewCommand(ctx context.Context, args ...string) *Command {
+func NewCommand(ctx context.Context, args ...CmdArg) *Command {
        // Make an explicit copy of globalCommandArgs, otherwise append might overwrite it
-       cargs := make([]string, len(globalCommandArgs))
-       copy(cargs, globalCommandArgs)
+       cargs := make([]string, 0, len(globalCommandArgs)+len(args))
+       for _, arg := range globalCommandArgs {
+               cargs = append(cargs, string(arg))
+       }
+       for _, arg := range args {
+               cargs = append(cargs, string(arg))
+       }
        return &Command{
                name:             GitExecutable,
-               args:             append(cargs, args...),
+               args:             cargs,
                parentContext:    ctx,
                globalArgsLength: len(globalCommandArgs),
        }
@@ -66,16 +73,20 @@ func NewCommand(ctx context.Context, args ...string) *Command {
 
 // NewCommandNoGlobals creates and returns a new Git Command based on given command and arguments only with the specify args and don't care global command args
 // Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
-func NewCommandNoGlobals(args ...string) *Command {
+func NewCommandNoGlobals(args ...CmdArg) *Command {
        return NewCommandContextNoGlobals(DefaultContext, args...)
 }
 
 // NewCommandContextNoGlobals creates and returns a new Git Command based on given command and arguments only with the specify args and don't care global command args
 // Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
-func NewCommandContextNoGlobals(ctx context.Context, args ...string) *Command {
+func NewCommandContextNoGlobals(ctx context.Context, args ...CmdArg) *Command {
+       cargs := make([]string, 0, len(args))
+       for _, arg := range args {
+               cargs = append(cargs, string(arg))
+       }
        return &Command{
                name:          GitExecutable,
-               args:          args,
+               args:          cargs,
                parentContext: ctx,
        }
 }
@@ -93,10 +104,12 @@ func (c *Command) SetDescription(desc string) *Command {
        return c
 }
 
-// AddArguments adds new argument(s) to the command. Each argument must be safe to be trusted.
+// AddArguments adds new git argument(s) to the command. Each argument must be safe to be trusted.
 // User-provided arguments should be passed to AddDynamicArguments instead.
-func (c *Command) AddArguments(args ...string) *Command {
-       c.args = append(c.args, args...)
+func (c *Command) AddArguments(args ...CmdArg) *Command {
+       for _, arg := range args {
+               c.args = append(c.args, string(arg))
+       }
        return c
 }
 
@@ -115,6 +128,26 @@ func (c *Command) AddDynamicArguments(args ...string) *Command {
        return c
 }
 
+// AddDashesAndList adds the "--" and then add the list as arguments, it's usually for adding file list
+// At the moment, this function can be only called once, maybe in future it can be refactored to support multiple calls (if necessary)
+func (c *Command) AddDashesAndList(list ...string) *Command {
+       c.args = append(c.args, "--")
+       // Some old code also checks `arg != ""`, IMO it's not necessary.
+       // If the check is needed, the list should be prepared before the call to this function
+       c.args = append(c.args, list...)
+       return c
+}
+
+// CmdArgCheck checks whether the string is safe to be used as a dynamic argument.
+// It panics if the check fails. Usually it should not be used, it's just for refactoring purpose
+// deprecated
+func CmdArgCheck(s string) CmdArg {
+       if s != "" && s[0] == '-' {
+               panic("invalid git cmd argument: " + s)
+       }
+       return CmdArg(s)
+}
+
 // RunOpts represents parameters to run the command. If UseContextTimeout is specified, then Timeout is ignored.
 type RunOpts struct {
        Env               []string
@@ -153,7 +186,7 @@ func CommonGitCmdEnvs() []string {
        }...)
 }
 
-// CommonCmdServEnvs is like CommonGitCmdEnvs but it only returns minimal required environment variables for the "gitea serv" command
+// CommonCmdServEnvs is like CommonGitCmdEnvs, but it only returns minimal required environment variables for the "gitea serv" command
 func CommonCmdServEnvs() []string {
        return commonBaseEnvs()
 }
@@ -318,12 +351,12 @@ func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
 }
 
 // AllowLFSFiltersArgs return globalCommandArgs with lfs filter, it should only be used for tests
-func AllowLFSFiltersArgs() []string {
+func AllowLFSFiltersArgs() []CmdArg {
        // Now here we should explicitly allow lfs filters to run
-       filteredLFSGlobalArgs := make([]string, len(globalCommandArgs))
+       filteredLFSGlobalArgs := make([]CmdArg, len(globalCommandArgs))
        j := 0
        for _, arg := range globalCommandArgs {
-               if strings.Contains(arg, "lfs") {
+               if strings.Contains(string(arg), "lfs") {
                        j--
                } else {
                        filteredLFSGlobalArgs[j] = arg
index 8fac9921b13d6dc23fe61edbe68c14a680607a4e..061adc1082355b870f6316cc3410ef71b9afae9b 100644 (file)
@@ -92,13 +92,13 @@ func AddChanges(repoPath string, all bool, files ...string) error {
 }
 
 // AddChangesWithArgs marks local changes to be ready for commit.
-func AddChangesWithArgs(repoPath string, globalArgs []string, all bool, files ...string) error {
+func AddChangesWithArgs(repoPath string, globalArgs []CmdArg, all bool, files ...string) error {
        cmd := NewCommandNoGlobals(append(globalArgs, "add")...)
        if all {
                cmd.AddArguments("--all")
        }
-       cmd.AddArguments("--")
-       _, _, err := cmd.AddArguments(files...).RunStdString(&RunOpts{Dir: repoPath})
+       cmd.AddDashesAndList(files...)
+       _, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
        return err
 }
 
@@ -112,17 +112,17 @@ 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(repoPath string, opts CommitChangesOptions) error {
-       cargs := make([]string, len(globalCommandArgs))
+       cargs := make([]CmdArg, len(globalCommandArgs))
        copy(cargs, globalCommandArgs)
        return CommitChangesWithArgs(repoPath, cargs, opts)
 }
 
 // CommitChangesWithArgs commits local changes with given committer, author and message.
 // If author is nil, it will be the same as committer.
-func CommitChangesWithArgs(repoPath string, args []string, opts CommitChangesOptions) error {
+func CommitChangesWithArgs(repoPath string, args []CmdArg, opts CommitChangesOptions) error {
        cmd := NewCommandNoGlobals(args...)
        if opts.Committer != nil {
-               cmd.AddArguments("-c", "user.name="+opts.Committer.Name, "-c", "user.email="+opts.Committer.Email)
+               cmd.AddArguments("-c", CmdArg("user.name="+opts.Committer.Name), "-c", CmdArg("user.email="+opts.Committer.Email))
        }
        cmd.AddArguments("commit")
 
@@ -130,9 +130,9 @@ func CommitChangesWithArgs(repoPath string, args []string, opts CommitChangesOpt
                opts.Author = opts.Committer
        }
        if opts.Author != nil {
-               cmd.AddArguments(fmt.Sprintf("--author='%s <%s>'", opts.Author.Name, opts.Author.Email))
+               cmd.AddArguments(CmdArg(fmt.Sprintf("--author='%s <%s>'", opts.Author.Name, opts.Author.Email)))
        }
-       cmd.AddArguments("-m"opts.Message)
+       cmd.AddArguments("-m").AddDynamicArguments(opts.Message)
 
        _, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
        // No stderr but exit status 1 means nothing to commit.
@@ -144,15 +144,13 @@ func CommitChangesWithArgs(repoPath string, args []string, opts CommitChangesOpt
 
 // AllCommitsCount returns count of all commits in repository
 func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, files ...string) (int64, error) {
-       args := []string{"--all", "--count"}
+       cmd := NewCommand(ctx, "rev-list")
        if hidePRRefs {
-               args = append([]string{"--exclude=" + PullPrefix + "*"}, args...)
+               cmd.AddArguments("--exclude=" + PullPrefix + "*")
        }
-       cmd := NewCommand(ctx, "rev-list")
-       cmd.AddArguments(args...)
+       cmd.AddArguments("--all", "--count")
        if len(files) > 0 {
-               cmd.AddArguments("--")
-               cmd.AddArguments(files...)
+               cmd.AddDashesAndList(files...)
        }
 
        stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
@@ -168,8 +166,7 @@ func CommitsCountFiles(ctx context.Context, repoPath string, revision, relpath [
        cmd := NewCommand(ctx, "rev-list", "--count")
        cmd.AddDynamicArguments(revision...)
        if len(relpath) > 0 {
-               cmd.AddArguments("--")
-               cmd.AddArguments(relpath...)
+               cmd.AddDashesAndList(relpath...)
        }
 
        stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
@@ -209,7 +206,7 @@ func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) {
                return false, nil
        }
 
-       _, _, err := NewCommand(c.repo.Ctx, "merge-base", "--is-ancestor"that, this).RunStdString(&RunOpts{Dir: c.repo.Path})
+       _, _, err := NewCommand(c.repo.Ctx, "merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(&RunOpts{Dir: c.repo.Path})
        if err == nil {
                return true, nil
        }
@@ -392,15 +389,12 @@ func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
 
 // GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only')
 func (c *Commit) GetBranchName() (string, error) {
-       args := []string{
-               "name-rev",
-       }
+       cmd := NewCommand(c.repo.Ctx, "name-rev")
        if CheckGitVersionAtLeast("2.13.0") == nil {
-               args = append(args, "--exclude", "refs/tags/*")
+               cmd.AddArguments("--exclude", "refs/tags/*")
        }
-       args = append(args, "--name-only", "--no-undefined", c.ID.String())
-
-       data, _, err := NewCommand(c.repo.Ctx, args...).RunStdString(&RunOpts{Dir: c.repo.Path})
+       cmd.AddArguments("--name-only", "--no-undefined").AddDynamicArguments(c.ID.String())
+       data, _, err := cmd.RunStdString(&RunOpts{Dir: c.repo.Path})
        if err != nil {
                // handle special case where git can not describe commit
                if strings.Contains(err.Error(), "cannot describe") {
@@ -426,7 +420,7 @@ func (c *Commit) LoadBranchName() (err error) {
 
 // GetTagName gets the current tag name for given commit
 func (c *Commit) GetTagName() (string, error) {
-       data, _, err := NewCommand(c.repo.Ctx, "describe", "--exact-match", "--tags", "--always"c.ID.String()).RunStdString(&RunOpts{Dir: c.repo.Path})
+       data, _, err := NewCommand(c.repo.Ctx, "describe", "--exact-match", "--tags", "--always").AddDynamicArguments(c.ID.String()).RunStdString(&RunOpts{Dir: c.repo.Path})
        if err != nil {
                // handle special case where there is no tag for this commit
                if strings.Contains(err.Error(), "no tag exactly matches") {
@@ -503,9 +497,7 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi
        }()
 
        stderr := new(bytes.Buffer)
-       args := []string{"log", "--name-status", "-c", "--pretty=format:", "--parents", "--no-renames", "-z", "-1", commitID}
-
-       err := NewCommand(ctx, args...).Run(&RunOpts{
+       err := NewCommand(ctx, "log", "--name-status", "-c", "--pretty=format:", "--parents", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(&RunOpts{
                Dir:    repoPath,
                Stdout: w,
                Stderr: stderr,
@@ -521,7 +513,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(ctx, "rev-parse"shortID).RunStdString(&RunOpts{Dir: repoPath})
+       commitID, _, err := NewCommand(ctx, "rev-parse").AddDynamicArguments(shortID).RunStdString(&RunOpts{Dir: repoPath})
        if err != nil {
                if strings.Contains(err.Error(), "exit status 128") {
                        return "", ErrNotExist{shortID, ""}
index f75ebd4fd21d3a6ecb5b9ffb3c0cdfb743ed114d..13ff6bd1e6a5bbd4f8865ba6e212fe1242f34749 100644 (file)
@@ -35,7 +35,7 @@ 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(ctx, "show", "--pretty=format:revert %H%n", "-R"commitID)
+       cmd := NewCommand(ctx, "show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID)
        if err := cmd.Run(&RunOpts{
                Dir:    repoPath,
                Stdout: writer,
@@ -52,39 +52,38 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff
        if err != nil {
                return err
        }
-       fileArgs := make([]string, 0)
+       var files []string
        if len(file) > 0 {
-               fileArgs = append(fileArgs, "--", file)
+               files = append(files, file)
        }
 
-       var args []string
+       cmd := NewCommand(repo.Ctx)
        switch diffType {
        case RawDiffNormal:
                if len(startCommit) != 0 {
-                       args = append([]string{"diff", "-M", startCommit, endCommit}, fileArgs...)
+                       cmd.AddArguments("diff", "-M").AddDynamicArguments(startCommit, endCommit).AddDashesAndList(files...)
                } else if commit.ParentCount() == 0 {
-                       args = append([]string{"show", endCommit}, fileArgs...)
+                       cmd.AddArguments("show").AddDynamicArguments(endCommit).AddDashesAndList(files...)
                } else {
                        c, _ := commit.Parent(0)
-                       args = append([]string{"diff", "-M", c.ID.String(), endCommit}, fileArgs...)
+                       cmd.AddArguments("diff", "-M").AddDynamicArguments(c.ID.String(), endCommit).AddDashesAndList(files...)
                }
        case RawDiffPatch:
                if len(startCommit) != 0 {
                        query := fmt.Sprintf("%s...%s", endCommit, startCommit)
-                       args = append([]string{"format-patch", "--no-signature", "--stdout", "--root", query}, fileArgs...)
+                       cmd.AddArguments("format-patch", "--no-signature", "--stdout", "--root").AddDynamicArguments(query).AddDashesAndList(files...)
                } else if commit.ParentCount() == 0 {
-                       args = append([]string{"format-patch", "--no-signature", "--stdout", "--root", endCommit}, fileArgs...)
+                       cmd.AddArguments("format-patch", "--no-signature", "--stdout", "--root").AddDynamicArguments(endCommit).AddDashesAndList(files...)
                } else {
                        c, _ := commit.Parent(0)
                        query := fmt.Sprintf("%s...%s", endCommit, c.ID.String())
-                       args = append([]string{"format-patch", "--no-signature", "--stdout", query}, fileArgs...)
+                       cmd.AddArguments("format-patch", "--no-signature", "--stdout").AddDynamicArguments(query).AddDashesAndList(files...)
                }
        default:
                return fmt.Errorf("invalid diffType: %s", diffType)
        }
 
        stderr := new(bytes.Buffer)
-       cmd := NewCommand(repo.Ctx, args...)
        if err = cmd.Run(&RunOpts{
                Dir:    repo.Path,
                Stdout: writer,
@@ -287,7 +286,7 @@ func GetAffectedFiles(repo *Repository, oldCommitID, newCommitID string, env []s
        affectedFiles := make([]string, 0, 32)
 
        // Run `git diff --name-only` to get the names of the changed files
-       err = NewCommand(repo.Ctx, "diff", "--name-only"oldCommitID, newCommitID).
+       err = NewCommand(repo.Ctx, "diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID).
                Run(&RunOpts{
                        Env:    env,
                        Dir:    repo.Path,
index 28899222e7efd2540ecd3f911d02f702506ce10b..18d62838df166eb93687d65636b0bce87ba05fa5 100644 (file)
@@ -313,7 +313,7 @@ func CheckGitVersionAtLeast(atLeast string) error {
 }
 
 func configSet(key, value string) error {
-       stdout, _, err := NewCommand(DefaultContext, "config", "--get"key).RunStdString(nil)
+       stdout, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil)
        if err != nil && !err.IsExitCode(1) {
                return fmt.Errorf("failed to get git config %s, err: %w", key, err)
        }
@@ -323,7 +323,7 @@ func configSet(key, value string) error {
                return nil
        }
 
-       _, _, err = NewCommand(DefaultContext, "config", "--global"key, value).RunStdString(nil)
+       _, _, err = NewCommand(DefaultContext, "config", "--global").AddDynamicArguments(key, value).RunStdString(nil)
        if err != nil {
                return fmt.Errorf("failed to set git global config %s, err: %w", key, err)
        }
@@ -332,14 +332,14 @@ func configSet(key, value string) error {
 }
 
 func configSetNonExist(key, value string) error {
-       _, _, err := NewCommand(DefaultContext, "config", "--get"key).RunStdString(nil)
+       _, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil)
        if err == nil {
                // already exist
                return nil
        }
        if err.IsExitCode(1) {
                // not exist, set new config
-               _, _, err = NewCommand(DefaultContext, "config", "--global"key, value).RunStdString(nil)
+               _, _, err = NewCommand(DefaultContext, "config", "--global").AddDynamicArguments(key, value).RunStdString(nil)
                if err != nil {
                        return fmt.Errorf("failed to set git global config %s, err: %w", key, err)
                }
@@ -350,14 +350,14 @@ func configSetNonExist(key, value string) error {
 }
 
 func configAddNonExist(key, value string) error {
-       _, _, err := NewCommand(DefaultContext, "config", "--get"key, regexp.QuoteMeta(value)).RunStdString(nil)
+       _, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)
        if err == nil {
                // already exist
                return nil
        }
        if err.IsExitCode(1) {
                // not exist, add new config
-               _, _, err = NewCommand(DefaultContext, "config", "--global", "--add"key, value).RunStdString(nil)
+               _, _, err = NewCommand(DefaultContext, "config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(nil)
                if err != nil {
                        return fmt.Errorf("failed to add git global config %s, err: %w", key, err)
                }
@@ -367,10 +367,10 @@ func configAddNonExist(key, value string) error {
 }
 
 func configUnsetAll(key, value string) error {
-       _, _, err := NewCommand(DefaultContext, "config", "--get"key).RunStdString(nil)
+       _, _, err := NewCommand(DefaultContext, "config", "--get").AddDynamicArguments(key).RunStdString(nil)
        if err == nil {
                // exist, need to remove
-               _, _, err = NewCommand(DefaultContext, "config", "--global", "--unset-all"key, regexp.QuoteMeta(value)).RunStdString(nil)
+               _, _, err = NewCommand(DefaultContext, "config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(nil)
                if err != nil {
                        return fmt.Errorf("failed to unset git global config %s, err: %w", key, err)
                }
@@ -384,6 +384,6 @@ func configUnsetAll(key, value string) error {
 }
 
 // Fsck verifies the connectivity and validity of the objects in the database
-func Fsck(ctx context.Context, repoPath string, timeout time.Duration, args ...string) error {
+func Fsck(ctx context.Context, repoPath string, timeout time.Duration, args ...CmdArg) error {
        return NewCommand(ctx, "fsck").AddArguments(args...).Run(&RunOpts{Timeout: timeout, Dir: repoPath})
 }
index 469932525fb517dd2d2ad3d995c9ba0e913b750b..dee4fc226ef270bf66ae690cdda4b0a1685d141f 100644 (file)
@@ -35,30 +35,33 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p
                _ = stdoutWriter.Close()
        }
 
-       args := make([]string, 0, 8+len(paths))
-       args = append(args, "log", "--name-status", "-c", "--format=commit%x00%H %P%x00", "--parents", "--no-renames", "-t", "-z", head, "--")
+       cmd := NewCommand(ctx)
+       cmd.AddArguments("log", "--name-status", "-c", "--format=commit%x00%H %P%x00", "--parents", "--no-renames", "-t", "-z").AddDynamicArguments(head)
+
+       var files []string
        if len(paths) < 70 {
                if treepath != "" {
-                       args = append(args, treepath)
+                       files = append(files, treepath)
                        for _, pth := range paths {
                                if pth != "" {
-                                       args = append(args, path.Join(treepath, pth))
+                                       files = append(files, path.Join(treepath, pth))
                                }
                        }
                } else {
                        for _, pth := range paths {
                                if pth != "" {
-                                       args = append(args, pth)
+                                       files = append(files, pth)
                                }
                        }
                }
        } else if treepath != "" {
-               args = append(args, treepath)
+               files = append(files, treepath)
        }
+       cmd.AddDashesAndList(files...)
 
        go func() {
                stderr := strings.Builder{}
-               err := NewCommand(ctx, args...).Run(&RunOpts{
+               err := cmd.Run(&RunOpts{
                        Dir:    repository,
                        Stdout: stdoutWriter,
                        Stderr: &stderr,
index 02619cb58304fbd830559270905783dd3bbf3fc9..5f62e85e7f784caec5c3dadd9e4dbf1cdb953465 100644 (file)
@@ -43,7 +43,7 @@ func RevListObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync.
        defer revListWriter.Close()
        stderr := new(bytes.Buffer)
        var errbuf strings.Builder
-       cmd := git.NewCommand(ctx, "rev-list", "--objects", headSHA, "--not", baseSHA)
+       cmd := git.NewCommand(ctx, "rev-list", "--objects").AddDynamicArguments(headSHA).AddArguments("--not").AddDynamicArguments(baseSHA)
        if err := cmd.Run(&git.RunOpts{
                Dir:    tmpBasePath,
                Stdout: revListWriter,
index cbb4ac6126b8663696fe6d27955548f41b37ab23..c416eea136851823fd00e60cabc17903c1439934 100644 (file)
@@ -14,9 +14,9 @@ import (
 func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) {
        var cmd *Command
        if CheckGitVersionAtLeast("2.7") == nil {
-               cmd = NewCommand(ctx, "remote", "get-url"remoteName)
+               cmd = NewCommand(ctx, "remote", "get-url").AddDynamicArguments(remoteName)
        } else {
-               cmd = NewCommand(ctx, "config", "--get", "remote."+remoteName+".url")
+               cmd = NewCommand(ctx, "config", "--get").AddDynamicArguments("remote." + remoteName + ".url")
        }
 
        result, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
index 3176e276959a0501892dd062f03133f122a533d1..575b686e2967f406c6fd6635825b77e10536a002 100644 (file)
@@ -59,7 +59,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(ctx, "ls-remote", "-q", "-h"url, "HEAD").RunStdString(nil)
+       _, _, err := NewCommand(ctx, "ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(nil)
        return err == nil
 }
 
@@ -112,13 +112,11 @@ type CloneRepoOptions struct {
 
 // Clone clones original repository to target path.
 func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error {
-       cargs := make([]string, len(globalCommandArgs))
-       copy(cargs, globalCommandArgs)
-       return CloneWithArgs(ctx, from, to, cargs, opts)
+       return CloneWithArgs(ctx, globalCommandArgs, from, to, opts)
 }
 
 // CloneWithArgs original repository to target path.
-func CloneWithArgs(ctx context.Context, from, to string, args []string, opts CloneRepoOptions) (err error) {
+func CloneWithArgs(ctx context.Context, args []CmdArg, from, to string, opts CloneRepoOptions) (err error) {
        toDir := path.Dir(to)
        if err = os.MkdirAll(toDir, os.ModePerm); err != nil {
                return err
@@ -144,15 +142,15 @@ func CloneWithArgs(ctx context.Context, from, to string, args []string, opts Clo
                cmd.AddArguments("--no-checkout")
        }
        if opts.Depth > 0 {
-               cmd.AddArguments("--depth"strconv.Itoa(opts.Depth))
+               cmd.AddArguments("--depth").AddDynamicArguments(strconv.Itoa(opts.Depth))
        }
        if opts.Filter != "" {
-               cmd.AddArguments("--filter"opts.Filter)
+               cmd.AddArguments("--filter").AddDynamicArguments(opts.Filter)
        }
        if len(opts.Branch) > 0 {
-               cmd.AddArguments("-b"opts.Branch)
+               cmd.AddArguments("-b").AddDynamicArguments(opts.Branch)
        }
-       cmd.AddArguments("--", from, to)
+       cmd.AddDashesAndList(from, to)
 
        if strings.Contains(from, "://") && strings.Contains(from, "@") {
                cmd.SetDescription(fmt.Sprintf("clone branch %s from %s to %s (shared: %t, mirror: %t, depth: %d)", opts.Branch, util.SanitizeCredentialURLs(from), to, opts.Shared, opts.Mirror, opts.Depth))
@@ -203,10 +201,12 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
        if opts.Mirror {
                cmd.AddArguments("--mirror")
        }
-       cmd.AddArguments("--", opts.Remote)
+       remoteBranchArgs := []string{opts.Remote}
        if len(opts.Branch) > 0 {
-               cmd.AddArguments(opts.Branch)
+               remoteBranchArgs = append(remoteBranchArgs, opts.Branch)
        }
+       cmd.AddDashesAndList(remoteBranchArgs...)
+
        if strings.Contains(opts.Remote, "://") && strings.Contains(opts.Remote, "@") {
                cmd.SetDescription(fmt.Sprintf("push branch %s to %s (force: %t, mirror: %t)", opts.Branch, util.SanitizeCredentialURLs(opts.Remote), opts.Force, opts.Mirror))
        } else {
@@ -276,7 +276,7 @@ type DivergeObject struct {
 
 func checkDivergence(ctx context.Context, repoPath, baseBranch, targetBranch string) (int, error) {
        branches := fmt.Sprintf("%s..%s", baseBranch, targetBranch)
-       cmd := NewCommand(ctx, "rev-list", "--count"branches)
+       cmd := NewCommand(ctx, "rev-list", "--count").AddDynamicArguments(branches)
        stdout, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
        if err != nil {
                return -1, err
@@ -319,7 +319,7 @@ func (repo *Repository) CreateBundle(ctx context.Context, commit string, out io.
                return err
        }
 
-       _, _, err = NewCommand(ctx, "reset", "--soft"commit).RunStdString(&RunOpts{Dir: tmp, Env: env})
+       _, _, err = NewCommand(ctx, "reset", "--soft").AddDynamicArguments(commit).RunStdString(&RunOpts{Dir: tmp, Env: env})
        if err != nil {
                return err
        }
@@ -330,7 +330,7 @@ func (repo *Repository) CreateBundle(ctx context.Context, commit string, out io.
        }
 
        tmpFile := filepath.Join(tmp, "bundle")
-       _, _, err = NewCommand(ctx, "bundle", "create"tmpFile, "bundle", "HEAD").RunStdString(&RunOpts{Dir: tmp, Env: env})
+       _, _, err = NewCommand(ctx, "bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(&RunOpts{Dir: tmp, Env: env})
        if err != nil {
                return err
        }
index 4a97989949f3f3f8f83101dcaec139e159f459a8..a0cbfba5d965df03afbe2fcdff470c0e6902b6a2 100644 (file)
@@ -44,20 +44,15 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t
                return fmt.Errorf("unknown format: %v", format)
        }
 
-       args := []string{
-               "archive",
-       }
+       cmd := NewCommand(ctx, "archive")
        if usePrefix {
-               args = append(args, "--prefix="+filepath.Base(strings.TrimSuffix(repo.Path, ".git"))+"/")
+               cmd.AddArguments(CmdArg("--prefix=" + filepath.Base(strings.TrimSuffix(repo.Path, ".git")) + "/"))
        }
-
-       args = append(args,
-               "--format="+format.String(),
-               commitID,
-       )
+       cmd.AddArguments(CmdArg("--format=" + format.String()))
+       cmd.AddDynamicArguments(commitID)
 
        var stderr strings.Builder
-       err := NewCommand(ctx, args...).Run(&RunOpts{
+       err := cmd.Run(&RunOpts{
                Dir:    repo.Path,
                Stdout: target,
                Stderr: &stderr,
index 21ff93e498f177602f19c2c037b6a0a1a4c83cae..60dc993dc207da3c87bca054189a2a4bfd703b3e 100644 (file)
@@ -20,7 +20,7 @@ import (
 type CheckAttributeOpts struct {
        CachedOnly    bool
        AllAttributes bool
-       Attributes    []string
+       Attributes    []CmdArg
        Filenames     []string
        IndexFile     string
        WorkTree      string
@@ -44,31 +44,23 @@ func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[
        stdOut := new(bytes.Buffer)
        stdErr := new(bytes.Buffer)
 
-       cmdArgs := []string{"check-attr", "-z"}
+       cmd := NewCommand(repo.Ctx, "check-attr", "-z")
 
        if opts.AllAttributes {
-               cmdArgs = append(cmdArgs, "-a")
+               cmd.AddArguments("-a")
        } else {
                for _, attribute := range opts.Attributes {
                        if attribute != "" {
-                               cmdArgs = append(cmdArgs, attribute)
+                               cmd.AddArguments(attribute)
                        }
                }
        }
 
        if opts.CachedOnly {
-               cmdArgs = append(cmdArgs, "--cached")
-       }
-
-       cmdArgs = append(cmdArgs, "--")
-
-       for _, arg := range opts.Filenames {
-               if arg != "" {
-                       cmdArgs = append(cmdArgs, arg)
-               }
+               cmd.AddArguments("--cached")
        }
 
-       cmd := NewCommand(repo.Ctx, cmdArgs...)
+       cmd.AddDashesAndList(opts.Filenames...)
 
        if err := cmd.Run(&RunOpts{
                Env:    env,
@@ -106,7 +98,7 @@ func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[
 // CheckAttributeReader provides a reader for check-attribute content that can be long running
 type CheckAttributeReader struct {
        // params
-       Attributes []string
+       Attributes []CmdArg
        Repo       *Repository
        IndexFile  string
        WorkTree   string
@@ -122,7 +114,7 @@ type CheckAttributeReader struct {
 
 // Init initializes the CheckAttributeReader
 func (c *CheckAttributeReader) Init(ctx context.Context) error {
-       cmdArgs := []string{"check-attr", "--stdin", "-z"}
+       cmdArgs := []CmdArg{"check-attr", "--stdin", "-z"}
 
        if len(c.IndexFile) > 0 {
                cmdArgs = append(cmdArgs, "--cached")
@@ -401,7 +393,7 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
        }
 
        checker := &CheckAttributeReader{
-               Attributes: []string{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language"},
+               Attributes: []CmdArg{"linguist-vendored", "linguist-generated", "linguist-language", "gitlab-language"},
                Repo:       repo,
                IndexFile:  indexFilename,
                WorkTree:   worktree,
index 6fe6d235ba925a58ddd85090de5fc3a823e3c54c..8a3707aa09183e1d72cc9cf043b38b0d5d7af193 100644 (file)
@@ -8,13 +8,16 @@ import "fmt"
 
 // FileBlame return the Blame object of file
 func (repo *Repository) FileBlame(revision, path, file string) ([]byte, error) {
-       stdout, _, err := NewCommand(repo.Ctx, "blame", "--root", "--", file).RunStdBytes(&RunOpts{Dir: path})
+       stdout, _, err := NewCommand(repo.Ctx, "blame", "--root").AddDashesAndList(file).RunStdBytes(&RunOpts{Dir: path})
        return stdout, err
 }
 
 // LineBlame returns the latest commit at the given line
 func (repo *Repository) LineBlame(revision, path, file string, line uint) (*Commit, error) {
-       res, _, err := NewCommand(repo.Ctx, "blame", fmt.Sprintf("-L %d,%d", line, line), "-p", revision, "--", file).RunStdString(&RunOpts{Dir: path})
+       res, _, err := NewCommand(repo.Ctx, "blame").
+               AddArguments(CmdArg(fmt.Sprintf("-L %d,%d", line, line))).
+               AddArguments("-p").AddDynamicArguments(revision).
+               AddDashesAndList(file).RunStdString(&RunOpts{Dir: path})
        if err != nil {
                return nil, err
        }
index 17d243808e9c0fc9bad85fb2529d6b858e664765..a3fc7e0c4216be0d52546f508f9a6fee4046b8bb 100644 (file)
@@ -25,7 +25,7 @@ const PullRequestPrefix = "refs/for/"
 
 // IsReferenceExist returns true if given reference exists in the repository.
 func IsReferenceExist(ctx context.Context, repoPath, name string) bool {
-       _, _, err := NewCommand(ctx, "show-ref", "--verify", "--", name).RunStdString(&RunOpts{Dir: repoPath})
+       _, _, err := NewCommand(ctx, "show-ref", "--verify").AddDashesAndList(name).RunStdString(&RunOpts{Dir: repoPath})
        return err == nil
 }
 
@@ -66,7 +66,7 @@ func (repo *Repository) GetHEADBranch() (*Branch, error) {
 
 // SetDefaultBranch sets default branch of repository.
 func (repo *Repository) SetDefaultBranch(name string) error {
-       _, _, err := NewCommand(repo.Ctx, "symbolic-ref", "HEAD", BranchPrefix+name).RunStdString(&RunOpts{Dir: repo.Path})
+       _, _, err := NewCommand(repo.Ctx, "symbolic-ref", "HEAD").AddDynamicArguments(BranchPrefix + name).RunStdString(&RunOpts{Dir: repo.Path})
        return err
 }
 
@@ -141,7 +141,7 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro
                cmd.AddArguments("-d")
        }
 
-       cmd.AddArguments("--", name)
+       cmd.AddDashesAndList(name)
        _, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
 
        return err
@@ -150,7 +150,7 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro
 // CreateBranch create a new branch
 func (repo *Repository) CreateBranch(branch, oldbranchOrCommit string) error {
        cmd := NewCommand(repo.Ctx, "branch")
-       cmd.AddArguments("--", branch, oldbranchOrCommit)
+       cmd.AddDashesAndList(branch, oldbranchOrCommit)
 
        _, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
 
@@ -163,7 +163,7 @@ func (repo *Repository) AddRemote(name, url string, fetch bool) error {
        if fetch {
                cmd.AddArguments("-f")
        }
-       cmd.AddArguments(name, url)
+       cmd.AddDynamicArguments(name, url)
 
        _, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
        return err
@@ -171,7 +171,7 @@ func (repo *Repository) AddRemote(name, url string, fetch bool) error {
 
 // RemoveRemote removes a remote from repository.
 func (repo *Repository) RemoveRemote(name string) error {
-       _, _, err := NewCommand(repo.Ctx, "remote", "rm"name).RunStdString(&RunOpts{Dir: repo.Path})
+       _, _, err := NewCommand(repo.Ctx, "remote", "rm").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
        return err
 }
 
@@ -182,6 +182,6 @@ func (branch *Branch) GetCommit() (*Commit, error) {
 
 // RenameBranch rename a branch
 func (repo *Repository) RenameBranch(from, to string) error {
-       _, _, err := NewCommand(repo.Ctx, "branch", "-m"from, to).RunStdString(&RunOpts{Dir: repo.Path})
+       _, _, err := NewCommand(repo.Ctx, "branch", "-m").AddDynamicArguments(from, to).RunStdString(&RunOpts{Dir: repo.Path})
        return err
 }
index 91112d0190d93000d69f7efa39001db415309489..95c371884199efc17dfb88fec48b9eec5784be8b 100644 (file)
@@ -63,7 +63,7 @@ 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, []string{BranchPrefix, "--sort=-committerdate"}, skip, limit)
+       return callShowRef(repo.Ctx, repo.Path, BranchPrefix, []CmdArg{BranchPrefix, "--sort=-committerdate"}, skip, limit)
 }
 
 // WalkReferences walks all the references from the repository
@@ -74,19 +74,19 @@ func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refn
 // 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 []string
+       var args []CmdArg
        switch refType {
        case ObjectTag:
-               args = []string{TagPrefix, "--sort=-taggerdate"}
+               args = []CmdArg{TagPrefix, "--sort=-taggerdate"}
        case ObjectBranch:
-               args = []string{BranchPrefix, "--sort=-committerdate"}
+               args = []CmdArg{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 []string, skip, limit int) (branchNames []string, countAll int, err error) {
+func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs []CmdArg, 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)
@@ -96,7 +96,7 @@ func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs []s
        return branchNames, countAll, err
 }
 
-func walkShowRef(ctx context.Context, repoPath string, extraArgs []string, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
+func walkShowRef(ctx context.Context, repoPath string, extraArgs []CmdArg, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
        stdoutReader, stdoutWriter := io.Pipe()
        defer func() {
                _ = stdoutReader.Close()
@@ -105,7 +105,7 @@ func walkShowRef(ctx context.Context, repoPath string, extraArgs []string, skip,
 
        go func() {
                stderrBuilder := &strings.Builder{}
-               args := []string{"for-each-ref", "--format=%(objectname) %(refname)"}
+               args := []CmdArg{"for-each-ref", "--format=%(objectname) %(refname)"}
                args = append(args, extraArgs...)
                err := NewCommand(ctx, args...).Run(&RunOpts{
                        Dir:    repoPath,
index ec72593b80a4e7affdd2fbe6cc59205d45a258c5..90259fd74664cb0a76e82ba4f63348e3e40e5a25 100644 (file)
@@ -61,7 +61,7 @@ func (repo *Repository) getCommitByPathWithID(id SHA1, relpath string) (*Commit,
                relpath = `\` + relpath
        }
 
-       stdout, _, runErr := NewCommand(repo.Ctx, "log", "-1", prettyLogFormat, id.String(), "--", relpath).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, runErr := NewCommand(repo.Ctx, "log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(&RunOpts{Dir: repo.Path})
        if runErr != nil {
                return nil, runErr
        }
@@ -76,7 +76,7 @@ func (repo *Repository) getCommitByPathWithID(id SHA1, relpath string) (*Commit,
 
 // GetCommitByPath returns the last commit of relative path.
 func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
-       stdout, _, runErr := NewCommand(repo.Ctx, "log", "-1", prettyLogFormat, "--", relpath).RunStdBytes(&RunOpts{Dir: repo.Path})
+       stdout, _, runErr := NewCommand(repo.Ctx, "log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(&RunOpts{Dir: repo.Path})
        if runErr != nil {
                return nil, runErr
        }
@@ -89,8 +89,10 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
 }
 
 func (repo *Repository) commitsByRange(id SHA1, page, pageSize int) ([]*Commit, error) {
-       stdout, _, err := NewCommand(repo.Ctx, "log", id.String(), "--skip="+strconv.Itoa((page-1)*pageSize),
-               "--max-count="+strconv.Itoa(pageSize), prettyLogFormat).RunStdBytes(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "log").
+               AddArguments(CmdArg("--skip="+strconv.Itoa((page-1)*pageSize)), CmdArg("--max-count="+strconv.Itoa(pageSize)), prettyLogFormat).
+               AddDynamicArguments(id.String()).
+               RunStdBytes(&RunOpts{Dir: repo.Path})
        if err != nil {
                return nil, err
        }
@@ -99,30 +101,30 @@ func (repo *Repository) commitsByRange(id SHA1, page, pageSize int) ([]*Commit,
 
 func (repo *Repository) searchCommits(id SHA1, opts SearchCommitsOptions) ([]*Commit, error) {
        // create new git log command with limit of 100 commis
-       cmd := NewCommand(repo.Ctx, "log", id.String(), "-100", prettyLogFormat)
+       cmd := NewCommand(repo.Ctx, "log", "-100", prettyLogFormat).AddDynamicArguments(id.String())
        // ignore case
-       args := []string{"-i"}
+       args := []CmdArg{"-i"}
 
        // add authors if present in search query
        if len(opts.Authors) > 0 {
                for _, v := range opts.Authors {
-                       args = append(args, "--author="+v)
+                       args = append(args, CmdArg("--author="+v))
                }
        }
 
        // add committers if present in search query
        if len(opts.Committers) > 0 {
                for _, v := range opts.Committers {
-                       args = append(args, "--committer="+v)
+                       args = append(args, CmdArg("--committer="+v))
                }
        }
 
        // add time constraints if present in search query
        if len(opts.After) > 0 {
-               args = append(args, "--after="+opts.After)
+               args = append(args, CmdArg("--after="+opts.After))
        }
        if len(opts.Before) > 0 {
-               args = append(args, "--before="+opts.Before)
+               args = append(args, CmdArg("--before="+opts.Before))
        }
 
        // pretend that all refs along with HEAD were listed on command line as <commis>
@@ -136,7 +138,7 @@ func (repo *Repository) searchCommits(id SHA1, opts SearchCommitsOptions) ([]*Co
        // note this is done only for command created above
        if len(opts.Keywords) > 0 {
                for _, v := range opts.Keywords {
-                       cmd.AddArguments("--grep=" + v)
+                       cmd.AddArguments(CmdArg("--grep=" + v))
                }
        }
 
@@ -178,7 +180,7 @@ func (repo *Repository) searchCommits(id SHA1, opts SearchCommitsOptions) ([]*Co
 }
 
 func (repo *Repository) getFilesChanged(id1, id2 string) ([]string, error) {
-       stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only"id1, id2).RunStdBytes(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only").AddDynamicArguments(id1, id2).RunStdBytes(&RunOpts{Dir: repo.Path})
        if err != nil {
                return nil, err
        }
@@ -188,7 +190,7 @@ func (repo *Repository) getFilesChanged(id1, id2 string) ([]string, error) {
 // 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(repo.Ctx, "diff", "--name-only", "-z", id1, id2, "--", filename).RunStdBytes(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(&RunOpts{Dir: repo.Path})
        if err != nil {
                return false, err
        }
@@ -211,12 +213,11 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
        }()
        go func() {
                stderr := strings.Builder{}
-               gitCmd := NewCommand(repo.Ctx, "rev-list",
-                       "--max-count="+strconv.Itoa(setting.Git.CommitsRangeSize*page),
-                       "--skip="+strconv.Itoa(skip),
-               )
+               gitCmd := NewCommand(repo.Ctx, "rev-list").
+                       AddArguments(CmdArg("--max-count=" + strconv.Itoa(setting.Git.CommitsRangeSize*page))).
+                       AddArguments(CmdArg("--skip=" + strconv.Itoa(skip)))
                gitCmd.AddDynamicArguments(revision)
-               gitCmd.AddArguments("--", file)
+               gitCmd.AddDashesAndList(file)
                err := gitCmd.Run(&RunOpts{
                        Dir:    repo.Path,
                        Stdout: stdoutWriter,
@@ -257,11 +258,11 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
 
 // FilesCountBetween return the number of files changed between two commits
 func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) {
-       stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only", startCommitID+"..."+endCommitID).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only").AddDynamicArguments(startCommitID + "..." + endCommitID).RunStdString(&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(repo.Ctx, "diff", "--name-only"startCommitID, endCommitID).RunStdString(&RunOpts{Dir: repo.Path})
+               stdout, _, err = NewCommand(repo.Ctx, "diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(&RunOpts{Dir: repo.Path})
        }
        if err != nil {
                return 0, err
@@ -275,13 +276,13 @@ func (repo *Repository) CommitsBetween(last, before *Commit) ([]*Commit, error)
        var stdout []byte
        var err error
        if before == nil {
-               stdout, _, err = NewCommand(repo.Ctx, "rev-list"last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
+               stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
        } else {
-               stdout, _, err = NewCommand(repo.Ctx, "rev-list", before.ID.String()+".."+last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
+               stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String() + ".." + last.ID.String()).RunStdBytes(&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(repo.Ctx, "rev-list"before.ID.String(), last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
+                       stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
                }
        }
        if err != nil {
@@ -295,13 +296,22 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in
        var stdout []byte
        var err error
        if before == nil {
-               stdout, _, err = NewCommand(repo.Ctx, "rev-list", "--max-count", strconv.Itoa(limit), "--skip", strconv.Itoa(skip), last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
+               stdout, _, err = NewCommand(repo.Ctx, "rev-list",
+                       "--max-count", CmdArg(strconv.Itoa(limit)),
+                       "--skip", CmdArg(strconv.Itoa(skip))).
+                       AddDynamicArguments(last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
        } else {
-               stdout, _, err = NewCommand(repo.Ctx, "rev-list", "--max-count", strconv.Itoa(limit), "--skip", strconv.Itoa(skip), before.ID.String()+".."+last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
+               stdout, _, err = NewCommand(repo.Ctx, "rev-list",
+                       "--max-count", CmdArg(strconv.Itoa(limit)),
+                       "--skip", CmdArg(strconv.Itoa(skip))).
+                       AddDynamicArguments(before.ID.String() + ".." + last.ID.String()).RunStdBytes(&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(repo.Ctx, "rev-list", "--max-count", strconv.Itoa(limit), "--skip", strconv.Itoa(skip), before.ID.String(), last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
+                       stdout, _, err = NewCommand(repo.Ctx, "rev-list",
+                               "--max-count", CmdArg(strconv.Itoa(limit)),
+                               "--skip", CmdArg(strconv.Itoa(skip))).
+                               AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(&RunOpts{Dir: repo.Path})
                }
        }
        if err != nil {
@@ -342,9 +352,9 @@ func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) {
 func (repo *Repository) commitsBefore(id SHA1, limit int) ([]*Commit, error) {
        cmd := NewCommand(repo.Ctx, "log")
        if limit > 0 {
-               cmd.AddArguments("-"+strconv.Itoa(limit), prettyLogFormat, id.String())
+               cmd.AddArguments(CmdArg("-"+strconv.Itoa(limit)), prettyLogFormat).AddDynamicArguments(id.String())
        } else {
-               cmd.AddArguments(prettyLogFormatid.String())
+               cmd.AddArguments(prettyLogFormat).AddDynamicArguments(id.String())
        }
 
        stdout, _, runErr := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
@@ -384,7 +394,11 @@ func (repo *Repository) getCommitsBeforeLimit(id SHA1, num int) ([]*Commit, erro
 
 func (repo *Repository) getBranches(commit *Commit, limit int) ([]string, error) {
        if CheckGitVersionAtLeast("2.7.0") == nil {
-               stdout, _, err := NewCommand(repo.Ctx, "for-each-ref", "--count="+strconv.Itoa(limit), "--format=%(refname:strip=2)", "--contains", commit.ID.String(), BranchPrefix).RunStdString(&RunOpts{Dir: repo.Path})
+               stdout, _, err := NewCommand(repo.Ctx, "for-each-ref",
+                       CmdArg("--count="+strconv.Itoa(limit)),
+                       "--format=%(refname:strip=2)", "--contains").
+                       AddDynamicArguments(commit.ID.String(), BranchPrefix).
+                       RunStdString(&RunOpts{Dir: repo.Path})
                if err != nil {
                        return nil, err
                }
@@ -393,7 +407,7 @@ func (repo *Repository) getBranches(commit *Commit, limit int) ([]string, error)
                return branches, nil
        }
 
-       stdout, _, err := NewCommand(repo.Ctx, "branch", "--contains"commit.ID.String()).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "branch", "--contains").AddDynamicArguments(commit.ID.String()).RunStdString(&RunOpts{Dir: repo.Path})
        if err != nil {
                return nil, err
        }
@@ -432,7 +446,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(repo.Ctx, "branch", "--contains"commitID, branch).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(&RunOpts{Dir: repo.Path})
        if err != nil {
                return false, err
        }
index 9333b0d7b756b484c1863fa92393ef010cbc273d..14fec3f9c6bd06640e8a12cb4f3bf61fd6835fac 100644 (file)
@@ -49,7 +49,7 @@ func (repo *Repository) ConvertToSHA1(commitID string) (SHA1, error) {
                }
        }
 
-       actualCommitID, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify"commitID).RunStdString(&RunOpts{Dir: repo.Path})
+       actualCommitID, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(&RunOpts{Dir: repo.Path})
        if err != nil {
                if strings.Contains(err.Error(), "unknown revision or path") ||
                        strings.Contains(err.Error(), "fatal: Needed a single revision") {
index efea307b37a2e3a14f8a04e8486a6febd236b48a..13a7be778f583aaf6e6c3ba5a12967098d9e10a1 100644 (file)
@@ -17,7 +17,7 @@ import (
 
 // ResolveReference resolves a name to a reference
 func (repo *Repository) ResolveReference(name string) (string, error) {
-       stdout, _, err := NewCommand(repo.Ctx, "show-ref", "--hash"name).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "show-ref", "--hash").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
        if err != nil {
                if strings.Contains(err.Error(), "not a valid ref") {
                        return "", ErrNotExist{name, ""}
@@ -50,19 +50,19 @@ 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(repo.Ctx, "update-ref"name, commitID).RunStdString(&RunOpts{Dir: repo.Path})
+       _, _, err := NewCommand(repo.Ctx, "update-ref").AddDynamicArguments(name, commitID).RunStdString(&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(repo.Ctx, "update-ref", "--no-deref", "-d"name).RunStdString(&RunOpts{Dir: repo.Path})
+       _, _, err := NewCommand(repo.Ctx, "update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
        return err
 }
 
 // IsCommitExist returns true if given commit exists in current repository.
 func (repo *Repository) IsCommitExist(name string) bool {
-       _, _, err := NewCommand(repo.Ctx, "cat-file", "-e"name).RunStdString(&RunOpts{Dir: repo.Path})
+       _, _, err := NewCommand(repo.Ctx, "cat-file", "-e").AddDynamicArguments(name).RunStdString(&RunOpts{Dir: repo.Path})
        return err == nil
 }
 
index 589a7eae00bf52d80b59237c471f3465739d873c..aad78370ff21462ed1ac82004d928e0cbf42b3d8 100644 (file)
@@ -40,13 +40,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(repo.Ctx, "fetch", "--no-tags", tmpRemote, "--", base+":"+tmpBaseName).RunStdString(&RunOpts{Dir: repo.Path})
+               _, _, err := NewCommand(repo.Ctx, "fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base + ":" + tmpBaseName).RunStdString(&RunOpts{Dir: repo.Path})
                if err == nil {
                        base = tmpBaseName
                }
        }
 
-       stdout, _, err := NewCommand(repo.Ctx, "merge-base", "--", base, head).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "merge-base").AddDashesAndList(base, head).RunStdString(&RunOpts{Dir: repo.Path})
        return strings.TrimSpace(stdout), base, err
 }
 
@@ -94,7 +94,7 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string,
                // We have a common base - therefore we know that ... should work
                if !fileOnly {
                        var logs []byte
-                       logs, _, err = NewCommand(repo.Ctx, "log", baseCommitID+separator+headBranch, prettyLogFormat).RunStdBytes(&RunOpts{Dir: repo.Path})
+                       logs, _, err = NewCommand(repo.Ctx, "log").AddDynamicArguments(baseCommitID + separator + headBranch).AddArguments(prettyLogFormat).RunStdBytes(&RunOpts{Dir: repo.Path})
                        if err != nil {
                                return nil, err
                        }
@@ -147,7 +147,7 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis
                separator = ".."
        }
 
-       if err := NewCommand(repo.Ctx, "diff", "-z", "--name-only", base+separator+head).
+       if err := NewCommand(repo.Ctx, "diff", "-z", "--name-only").AddDynamicArguments(base + separator + head).
                Run(&RunOpts{
                        Dir:    repo.Path,
                        Stdout: w,
@@ -158,7 +158,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(repo.Ctx, "diff", "-z", "--name-only"base, head).Run(&RunOpts{
+                       if err = NewCommand(repo.Ctx, "diff", "-z", "--name-only").AddDynamicArguments(base, head).Run(&RunOpts{
                                Dir:    repo.Path,
                                Stdout: w,
                                Stderr: stderr,
@@ -173,20 +173,20 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis
 
 // GetDiffShortStat counts number of changed files, number of additions and deletions
 func (repo *Repository) GetDiffShortStat(base, head string) (numFiles, totalAdditions, totalDeletions int, err error) {
-       numFiles, totalAdditions, totalDeletions, err = GetDiffShortStat(repo.Ctx, repo.Path, base+"..."+head)
+       numFiles, totalAdditions, totalDeletions, err = GetDiffShortStat(repo.Ctx, repo.Path, CmdArgCheck(base+"..."+head))
        if err != nil && strings.Contains(err.Error(), "no merge base") {
-               return GetDiffShortStat(repo.Ctx, repo.Path, base, head)
+               return GetDiffShortStat(repo.Ctx, repo.Path, CmdArgCheck(base), CmdArgCheck(head))
        }
        return numFiles, totalAdditions, totalDeletions, err
 }
 
 // GetDiffShortStat counts number of changed files, number of additions and deletions
-func GetDiffShortStat(ctx context.Context, repoPath string, args ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
+func GetDiffShortStat(ctx context.Context, repoPath string, args ...CmdArg) (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"
-       args = append([]string{
+       args = append([]CmdArg{
                "diff",
                "--shortstat",
        }, args...)
@@ -247,7 +247,7 @@ func (repo *Repository) GetDiffOrPatch(base, head string, w io.Writer, patch, bi
 
 // GetDiff generates and returns patch data between given revisions, optimized for human readability
 func (repo *Repository) GetDiff(base, head string, w io.Writer) error {
-       return NewCommand(repo.Ctx, "diff", "-p"base, head).Run(&RunOpts{
+       return NewCommand(repo.Ctx, "diff", "-p").AddDynamicArguments(base, head).Run(&RunOpts{
                Dir:    repo.Path,
                Stdout: w,
        })
@@ -255,7 +255,7 @@ func (repo *Repository) GetDiff(base, head string, w io.Writer) error {
 
 // GetDiffBinary generates and returns patch data between given revisions, including binary diffs.
 func (repo *Repository) GetDiffBinary(base, head string, w io.Writer) error {
-       return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram"base, head).Run(&RunOpts{
+       return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram").AddDynamicArguments(base, head).Run(&RunOpts{
                Dir:    repo.Path,
                Stdout: w,
        })
@@ -264,14 +264,14 @@ func (repo *Repository) GetDiffBinary(base, head 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(base, head string, w io.Writer) error {
        stderr := new(bytes.Buffer)
-       err := NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout", base+"..."+head).
+       err := NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(base + "..." + head).
                Run(&RunOpts{
                        Dir:    repo.Path,
                        Stdout: w,
                        Stderr: stderr,
                })
        if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) {
-               return NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout"base, head).
+               return NewCommand(repo.Ctx, "format-patch", "--binary", "--stdout").AddDynamicArguments(base, head).
                        Run(&RunOpts{
                                Dir:    repo.Path,
                                Stdout: w,
@@ -282,7 +282,7 @@ func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
 
 // GetFilesChangedBetween returns a list of all files that have been changed between the given commits
 func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, error) {
-       stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only", base+".."+head).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "diff", "--name-only").AddDynamicArguments(base + ".." + head).RunStdString(&RunOpts{Dir: repo.Path})
        if err != nil {
                return nil, err
        }
@@ -292,7 +292,7 @@ func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, err
 // GetDiffFromMergeBase generates and return patch data from merge base to head
 func (repo *Repository) GetDiffFromMergeBase(base, head string, w io.Writer) error {
        stderr := new(bytes.Buffer)
-       err := NewCommand(repo.Ctx, "diff", "-p", "--binary", base+"..."+head).
+       err := NewCommand(repo.Ctx, "diff", "-p", "--binary").AddDynamicArguments(base + "..." + head).
                Run(&RunOpts{
                        Dir:    repo.Path,
                        Stdout: w,
index 50d82c77d7ed87339cf688a290d49a32bbec1249..5542883288c63f1c57f9fa98b4d3da26cc567bbc 100644 (file)
@@ -18,7 +18,7 @@ import (
 // ReadTreeToIndex reads a treeish to the index
 func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string) error {
        if len(treeish) != 40 {
-               res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify"treeish).RunStdString(&RunOpts{Dir: repo.Path})
+               res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(&RunOpts{Dir: repo.Path})
                if err != nil {
                        return err
                }
@@ -38,7 +38,7 @@ func (repo *Repository) readTreeToIndex(id SHA1, indexFilename ...string) error
        if len(indexFilename) > 0 {
                env = append(os.Environ(), "GIT_INDEX_FILE="+indexFilename[0])
        }
-       _, _, err := NewCommand(repo.Ctx, "read-tree"id.String()).RunStdString(&RunOpts{Dir: repo.Path, Env: env})
+       _, _, err := NewCommand(repo.Ctx, "read-tree").AddDynamicArguments(id.String()).RunStdString(&RunOpts{Dir: repo.Path, Env: env})
        if err != nil {
                return err
        }
@@ -75,12 +75,7 @@ func (repo *Repository) EmptyIndex() error {
 
 // LsFiles checks if the given filenames are in the index
 func (repo *Repository) LsFiles(filenames ...string) ([]string, error) {
-       cmd := NewCommand(repo.Ctx, "ls-files", "-z", "--")
-       for _, arg := range filenames {
-               if arg != "" {
-                       cmd.AddArguments(arg)
-               }
-       }
+       cmd := NewCommand(repo.Ctx, "ls-files", "-z").AddDashesAndList(filenames...)
        res, _, err := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
        if err != nil {
                return nil, err
@@ -116,7 +111,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
 
 // AddObjectToIndex adds the provided object hash to the index at the provided filename
 func (repo *Repository) AddObjectToIndex(mode string, object SHA1, filename string) error {
-       cmd := NewCommand(repo.Ctx, "update-index", "--add", "--replace", "--cacheinfo"mode, object.String(), filename)
+       cmd := NewCommand(repo.Ctx, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, object.String(), filename)
        _, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
        return err
 }
index 7eccf9a19043fd2d1fd4d35650a3b458a120af0e..002e2525e2e8cffecc7468bc3138c8cb7eab8632 100644 (file)
@@ -41,7 +41,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
 
        since := fromTime.Format(time.RFC3339)
 
-       stdout, _, runErr := NewCommand(repo.Ctx, "rev-list", "--count", "--no-merges", "--branches=*", "--date=iso", fmt.Sprintf("--since='%s'", since)).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, runErr := NewCommand(repo.Ctx, "rev-list", "--count", "--no-merges", "--branches=*", "--date=iso", CmdArg(fmt.Sprintf("--since='%s'", since))).RunStdString(&RunOpts{Dir: repo.Path})
        if runErr != nil {
                return nil, runErr
        }
@@ -61,7 +61,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
                _ = stdoutWriter.Close()
        }()
 
-       gitCmd := NewCommand(repo.Ctx, "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso", fmt.Sprintf("--since='%s'", since))
+       gitCmd := NewCommand(repo.Ctx, "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso", CmdArg(fmt.Sprintf("--since='%s'", since)))
        if len(branch) == 0 {
                gitCmd.AddArguments("--branches=*")
        } else {
index 8444e8d035a0b141916972c28785a7ff452efd7e..fd0de7b3a1c5998a6202b3ec08b909a179ff2985 100644 (file)
@@ -25,13 +25,13 @@ func IsTagExist(ctx context.Context, repoPath, name string) bool {
 
 // CreateTag create one tag in the repository
 func (repo *Repository) CreateTag(name, revision string) error {
-       _, _, err := NewCommand(repo.Ctx, "tag", "--", name, revision).RunStdString(&RunOpts{Dir: repo.Path})
+       _, _, err := NewCommand(repo.Ctx, "tag").AddDashesAndList(name, revision).RunStdString(&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(repo.Ctx, "tag", "-a", "-m", message, "--", name, revision).RunStdString(&RunOpts{Dir: repo.Path})
+       _, _, err := NewCommand(repo.Ctx, "tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(&RunOpts{Dir: repo.Path})
        return err
 }
 
@@ -64,7 +64,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(repo.Ctx, "show-ref", "--tags", "--", name).RunStdString(&RunOpts{Dir: repo.Path})
+       stdout, _, err := NewCommand(repo.Ctx, "show-ref", "--tags").AddDashesAndList(name).RunStdString(&RunOpts{Dir: repo.Path})
        if err != nil {
                return "", err
        }
@@ -122,7 +122,7 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) {
        rc := &RunOpts{Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr}
 
        go func() {
-               err := NewCommand(repo.Ctx, "for-each-ref", "--format", forEachRefFmt.Flag(), "--sort", "-*creatordate", "refs/tags").Run(rc)
+               err := NewCommand(repo.Ctx, "for-each-ref", CmdArg("--format="+forEachRefFmt.Flag()), "--sort", "-*creatordate", "refs/tags").Run(rc)
                if err != nil {
                        _ = stdoutWriter.CloseWithError(ConcatenateError(err, stderr.String()))
                } else {
index 72c1c979dc401f463a97e070410e6b1ca674c96d..5d3aace52fdd775b9467276e56c241c2a2ec200f 100644 (file)
@@ -26,7 +26,7 @@ func (repo *Repository) IsTagExist(name string) bool {
 // GetTags returns all tags of the repository.
 // returning at most limit tags, or all if limit is 0.
 func (repo *Repository) GetTags(skip, limit int) (tags []string, err error) {
-       tags, _, err = callShowRef(repo.Ctx, repo.Path, TagPrefix, []string{TagPrefix, "--sort=-taggerdate"}, skip, limit)
+       tags, _, err = callShowRef(repo.Ctx, repo.Path, TagPrefix, []CmdArg{TagPrefix, "--sort=-taggerdate"}, skip, limit)
        return tags, err
 }
 
index 2ea3f0187a1852e5ccc47c07f1afda5a4eebcf4c..ba81bfc6dbbf1d33863505e884f52e9c5773e97f 100644 (file)
@@ -35,10 +35,10 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
                "GIT_COMMITTER_EMAIL="+committer.Email,
                "GIT_COMMITTER_DATE="+commitTimeStr,
        )
-       cmd := NewCommand(repo.Ctx, "commit-tree"tree.ID.String())
+       cmd := NewCommand(repo.Ctx, "commit-tree").AddDynamicArguments(tree.ID.String())
 
        for _, parent := range opts.Parents {
-               cmd.AddArguments("-p"parent)
+               cmd.AddArguments("-p").AddDynamicArguments(parent)
        }
 
        messageBytes := new(bytes.Buffer)
@@ -46,7 +46,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
        _, _ = messageBytes.WriteString("\n")
 
        if opts.KeyID != "" || opts.AlwaysSign {
-               cmd.AddArguments(fmt.Sprintf("-S%s", opts.KeyID))
+               cmd.AddArguments(CmdArg(fmt.Sprintf("-S%s", opts.KeyID)))
        }
 
        if opts.NoGPGSign {
index eef09cddd6a5bce841e74b58360f19f7be8c5c90..e72016493622fb9daf0caa7ce644e0687e4ccfc0 100644 (file)
@@ -21,7 +21,7 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) {
 // GetTree find the tree object in the repository.
 func (repo *Repository) GetTree(idStr string) (*Tree, error) {
        if len(idStr) != 40 {
-               res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify"idStr).RunStdString(&RunOpts{Dir: repo.Path})
+               res, _, err := NewCommand(repo.Ctx, "rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(&RunOpts{Dir: repo.Path})
                if err != nil {
                        return nil, err
                }
index a83336f3dbd353660b0324b70f7b24483135954b..f5944dd29c21945d83c96d8078f1b203b1c7c70f 100644 (file)
@@ -49,12 +49,9 @@ 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(repo.Ctx, "ls-tree", "-z", "--name-only", "--", ref)
-       for _, arg := range filenames {
-               if arg != "" {
-                       cmd.AddArguments(arg)
-               }
-       }
+       cmd := NewCommand(repo.Ctx, "ls-tree", "-z", "--name-only").
+               AddDashesAndList(append([]string{ref}, filenames...)...)
+
        res, _, err := cmd.RunStdBytes(&RunOpts{Dir: repo.Path})
        if err != nil {
                return nil, err
index d61d19e4c2e42e1cccc052b1b40515546365f2d3..5cbb5ffc94a847e32be2370fa26596b034bfa2c0 100644 (file)
@@ -80,7 +80,7 @@ func (t *Tree) ListEntries() (Entries, error) {
                }
        }
 
-       stdout, _, runErr := NewCommand(t.repo.Ctx, "ls-tree", "-l"t.ID.String()).RunStdBytes(&RunOpts{Dir: t.repo.Path})
+       stdout, _, runErr := NewCommand(t.repo.Ctx, "ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(&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{
@@ -101,13 +101,13 @@ 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 ...string) (Entries, error) {
+func (t *Tree) listEntriesRecursive(extraArgs ...CmdArg) (Entries, error) {
        if t.entriesRecursiveParsed {
                return t.entriesRecursive, nil
        }
 
-       args := append([]string{"ls-tree", "-t", "-r"}, extraArgs...)
-       args = append(args, t.ID.String())
+       args := append([]CmdArg{"ls-tree", "-t", "-r"}, extraArgs...)
+       args = append(args, CmdArg(t.ID.String()))
        stdout, _, runErr := NewCommand(t.repo.Ctx, args...).RunStdBytes(&RunOpts{Dir: t.repo.Path})
        if runErr != nil {
                return nil, runErr
index 0f3c02134482fd2537389b94220020c437357907..d6342c928006ca47df8ee3377895e5f2d40b1cfa 100644 (file)
@@ -37,16 +37,15 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
        graphCmd.AddArguments(
                "-C",
                "-M",
-               fmt.Sprintf("-n %d", setting.UI.GraphMaxCommitNum*page),
+               git.CmdArg(fmt.Sprintf("-n %d", setting.UI.GraphMaxCommitNum*page)),
                "--date=iso",
-               fmt.Sprintf("--pretty=format:%s", format))
+               git.CmdArg(fmt.Sprintf("--pretty=format:%s", format)))
 
        if len(branches) > 0 {
                graphCmd.AddDynamicArguments(branches...)
        }
        if len(files) > 0 {
-               graphCmd.AddArguments("--")
-               graphCmd.AddArguments(files...)
+               graphCmd.AddDashesAndList(files...)
        }
        graph := NewGraph()
 
index 0b31f7119c4fbdd738b37cc2496b2d5f307de9e6..f1298b01ed7e1137ae3db35701b95a4692e48e71 100644 (file)
@@ -194,7 +194,7 @@ func (b *BleveIndexer) addUpdate(ctx context.Context, batchWriter git.WriteClose
        var err error
        if !update.Sized {
                var stdout string
-               stdout, _, err = git.NewCommand(ctx, "cat-file", "-s"update.BlobSha).RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
+               stdout, _, err = git.NewCommand(ctx, "cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
                if err != nil {
                        return err
                }
index 7727bfacdef1d4248a0bf5a60308b52f021f3347..108a224675650ea0b3eb536c2fdb96e95022927e 100644 (file)
@@ -223,7 +223,7 @@ func (b *ElasticSearchIndexer) addUpdate(ctx context.Context, batchWriter git.Wr
        var err error
        if !update.Sized {
                var stdout string
-               stdout, _, err = git.NewCommand(ctx, "cat-file", "-s"update.BlobSha).RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
+               stdout, _, err = git.NewCommand(ctx, "cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
                if err != nil {
                        return nil, err
                }
index 66d76377ade70856596be3a4f75eaeb3bfbf00af..774dcc814991dbe9a09d761aa0fee426a748b837 100644 (file)
@@ -29,7 +29,7 @@ type repoChanges struct {
 }
 
 func getDefaultBranchSha(ctx context.Context, repo *repo_model.Repository) (string, error) {
-       stdout, _, err := git.NewCommand(ctx, "show-ref", "-s", git.BranchPrefix+repo.DefaultBranch).RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
+       stdout, _, err := git.NewCommand(ctx, "show-ref", "-s").AddDynamicArguments(git.BranchPrefix + repo.DefaultBranch).RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
        if err != nil {
                return "", err
        }
@@ -92,7 +92,7 @@ func parseGitLsTreeOutput(stdout []byte) ([]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) (*repoChanges, error) {
        var changes repoChanges
-       stdout, _, runErr := git.NewCommand(ctx, "ls-tree", "--full-tree", "-l", "-r"revision).RunStdBytes(&git.RunOpts{Dir: repo.RepoPath()})
+       stdout, _, runErr := git.NewCommand(ctx, "ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision).RunStdBytes(&git.RunOpts{Dir: repo.RepoPath()})
        if runErr != nil {
                return nil, runErr
        }
@@ -104,7 +104,7 @@ 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) (*repoChanges, error) {
-       diffCmd := git.NewCommand(ctx, "diff", "--name-status"repo.CodeIndexerStatus.CommitSha, revision)
+       diffCmd := git.NewCommand(ctx, "diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision)
        stdout, _, runErr := diffCmd.RunStdString(&git.RunOpts{Dir: repo.RepoPath()})
        if runErr != nil {
                // previous commit sha may have been removed by a force push, so
@@ -169,8 +169,8 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio
                }
        }
 
-       cmd := git.NewCommand(ctx, "ls-tree", "--full-tree", "-l", revision, "--")
-       cmd.AddArguments(updatedFilenames...)
+       cmd := git.NewCommand(ctx, "ls-tree", "--full-tree", "-l").AddDynamicArguments(revision).
+               AddDashesAndList(updatedFilenames...)
        lsTreeStdout, _, err := cmd.RunStdBytes(&git.RunOpts{Dir: repo.RepoPath()})
        if err != nil {
                return nil, err
index 4d76d33993dd986dd264b145bf2ff6bd6b50a6de..a69dd12a7893d71f074d73eba421b97c5959e063 100644 (file)
@@ -211,7 +211,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r
        }
 
        repoPath := repo.RepoPath()
-       if stdout, _, err := git.NewCommand(ctx, "remote", "add", "origin"repoPath).
+       if stdout, _, err := git.NewCommand(ctx, "remote", "add", "origin").AddDynamicArguments(repoPath).
                SetDescription(fmt.Sprintf("generateRepoCommit (git remote add): %s to %s", templateRepoPath, tmpDir)).
                RunStdString(&git.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)
index 37ed0748b4d347446b9f7cc3062f9142e4ca0c1f..473729a5997e0e43646246ad3482240259e1cc08 100644 (file)
@@ -228,7 +228,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir,
        )
 
        // Clone to temporary path and do the init commit.
-       if stdout, _, err := git.NewCommand(ctx, "clone"repoPath, tmpDir).
+       if stdout, _, err := git.NewCommand(ctx, "clone").AddDynamicArguments(repoPath, tmpDir).
                SetDescription(fmt.Sprintf("prepareRepoCommit (git clone): %s to %s", repoPath, tmpDir)).
                RunStdString(&git.RunOpts{Dir: "", Env: env}); err != nil {
                log.Error("Failed to clone from %v into %s: stdout: %s\nError: %v", repo, tmpDir, stdout, err)
@@ -317,14 +317,14 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
                return fmt.Errorf("git add --all: %v", err)
        }
 
-       args := []string{
-               "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
+       cmd := git.NewCommand(ctx,
+               "commit", git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email)),
                "-m", "Initial commit",
-       }
+       )
 
        sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u)
        if sign {
-               args = append(args, "-S"+keyID)
+               cmd.AddArguments(git.CmdArg("-S" + keyID))
 
                if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
                        // need to set the committer to the KeyID owner
@@ -332,7 +332,7 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
                        committerEmail = signer.Email
                }
        } else {
-               args = append(args, "--no-gpg-sign")
+               cmd.AddArguments("--no-gpg-sign")
        }
 
        env = append(env,
@@ -340,10 +340,10 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
                "GIT_COMMITTER_EMAIL="+committerEmail,
        )
 
-       if stdout, _, err := git.NewCommand(ctx, args...).
+       if stdout, _, err := cmd.
                SetDescription(fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath)).
                RunStdString(&git.RunOpts{Dir: tmpPath, Env: env}); err != nil {
-               log.Error("Failed to commit: %v: Stdout: %s\nError: %v", args, stdout, err)
+               log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.String(), stdout, err)
                return fmt.Errorf("git commit: %v", err)
        }
 
@@ -351,7 +351,7 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
                defaultBranch = setting.Repository.DefaultBranch
        }
 
-       if stdout, _, err := git.NewCommand(ctx, "push", "origin", "HEAD:"+defaultBranch).
+       if stdout, _, err := git.NewCommand(ctx, "push", "origin").AddDynamicArguments("HEAD:" + defaultBranch).
                SetDescription(fmt.Sprintf("initRepoCommit (git push): %s", tmpPath)).
                RunStdString(&git.RunOpts{Dir: tmpPath, Env: InternalPushingEnvironment(u, repo)}); err != nil {
                log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err)
index e1dbd5d2fcfb081f9e8ca141adae3afa67ece689..4e4b4000b1a85ade5da6be5e9100f769dfa746a5 100644 (file)
@@ -104,7 +104,7 @@ func IsForcePush(ctx context.Context, opts *PushUpdateOptions) (bool, error) {
                return false, nil
        }
 
-       output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1"opts.OldCommitID, "^"+opts.NewCommitID).
+       output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(opts.OldCommitID, "^"+opts.NewCommitID).
                RunStdString(&git.RunOpts{Dir: repo_model.RepoPath(opts.RepoUserName, opts.RepoName)})
        if err != nil {
                return false, err
index 3e7d1fe9ef6985a6f11abfe48bcab88ea79d77ed..fdd0a0bc3a0426fc93e660cc1ce4c5067a3d40fb 100644 (file)
@@ -186,7 +186,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID, refFullN
 
        // 2. Disallow force pushes to protected branches
        if git.EmptySHA != oldCommitID {
-               output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1"oldCommitID, "^"+newCommitID).RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: ctx.env})
+               output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(&git.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{
index dfa6195b19717b99c54755bbd475989f7bea7248..8a2d1cf33db331f4b51ec9e2debb68c7b047bd50 100644 (file)
@@ -44,7 +44,7 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env []
        }()
 
        // This is safe as force pushes are already forbidden
-       err = git.NewCommand(repo.Ctx, "rev-list", oldCommitID+"..."+newCommitID).
+       err = git.NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID).
                Run(&git.RunOpts{
                        Env:    env,
                        Dir:    repo.Path,
@@ -91,7 +91,7 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error {
        }()
        hash := git.MustIDFromString(sha)
 
-       return git.NewCommand(repo.Ctx, "cat-file", "commit"sha).
+       return git.NewCommand(repo.Ctx, "cat-file", "commit").AddDynamicArguments(sha).
                Run(&git.RunOpts{
                        Env:    env,
                        Dir:    repo.Path,
index c53a53b471934cc27aa0dcbe19aa9a631935682d..64a6f0ec538509a313446f61feb77d636542acc3 100644 (file)
@@ -216,7 +216,7 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
 
                filename2attribute2info, err := ctx.Repo.GitRepo.CheckAttribute(git.CheckAttributeOpts{
                        CachedOnly: true,
-                       Attributes: []string{"linguist-language", "gitlab-language"},
+                       Attributes: []git.CmdArg{"linguist-language", "gitlab-language"},
                        Filenames:  []string{ctx.Repo.TreePath},
                        IndexFile:  indexFilename,
                        WorkTree:   worktree,
index e7e68d3c5e92d30e95b86498ef70b9f98864aca3..db6b59471ff4703301b77296d1380707ff8014c9 100644 (file)
@@ -560,7 +560,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 func PrepareCompareDiff(
        ctx *context.Context,
        ci *CompareInfo,
-       whitespaceBehavior string,
+       whitespaceBehavior git.CmdArg,
 ) bool {
        var (
                repo  = ctx.Repo.Repository
index 5aa2bcd13471be242871741a9138ab2bb45758ff..1ec781bb13d5033f2695df819a6368748e526ffc 100644 (file)
@@ -398,7 +398,7 @@ func (h *serviceHandler) sendFile(contentType, file string) {
 var safeGitProtocolHeader = regexp.MustCompile(`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$`)
 
 func getGitConfig(ctx gocontext.Context, option, dir string) string {
-       out, _, err := git.NewCommand(ctx, "config"option).RunStdString(&git.RunOpts{Dir: dir})
+       out, _, err := git.NewCommand(ctx, "config").AddDynamicArguments(option).RunStdString(&git.RunOpts{Dir: dir})
        if err != nil {
                log.Error("%v - %s", err, out)
        }
@@ -471,7 +471,7 @@ func serviceRPC(ctx gocontext.Context, h serviceHandler, service string) {
        }
 
        var stderr bytes.Buffer
-       cmd := git.NewCommand(h.r.Context(), service, "--stateless-rpc", h.dir)
+       cmd := git.NewCommand(h.r.Context(), git.CmdArgCheck(service), "--stateless-rpc").AddDynamicArguments(h.dir)
        cmd.SetDescription(fmt.Sprintf("%s %s %s [repo_path: %s]", git.GitExecutable, service, "--stateless-rpc", h.dir))
        if err := cmd.Run(&git.RunOpts{
                Dir:               h.dir,
@@ -543,7 +543,7 @@ func GetInfoRefs(ctx *context.Context) {
                }
                h.environ = append(os.Environ(), h.environ...)
 
-               refs, _, err := git.NewCommand(ctx, service, "--stateless-rpc", "--advertise-refs", ".").RunStdBytes(&git.RunOpts{Env: h.environ, Dir: h.dir})
+               refs, _, err := git.NewCommand(ctx, git.CmdArgCheck(service), "--stateless-rpc", "--advertise-refs", ".").RunStdBytes(&git.RunOpts{Env: h.environ, Dir: h.dir})
                if err != nil {
                        log.Error(fmt.Sprintf("%v - %s", err, string(refs)))
                }
index 633b8ab1a5139e9fddcda88375d706ada050f63f..41639c4603ac7436c180dc5b896f0d9526461078 100644 (file)
@@ -147,7 +147,7 @@ func LFSLocks(ctx *context.Context) {
        }
 
        name2attribute2info, err := gitRepo.CheckAttribute(git.CheckAttributeOpts{
-               Attributes: []string{"lockable"},
+               Attributes: []git.CmdArg{"lockable"},
                Filenames:  filenames,
                CachedOnly: true,
        })
index aa2c4cdb53b2ddc1edf5d0c2a84ea46e1441faba..fc95bbf240f0120665c058178361e19ccd8e38fb 100644 (file)
@@ -359,7 +359,7 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue)
                }
                if commitSHA != "" {
                        // Get immediate parent of the first commit in the patch, grab history back
-                       parentCommit, _, err = git.NewCommand(ctx, "rev-list", "-1", "--skip=1"commitSHA).RunStdString(&git.RunOpts{Dir: ctx.Repo.GitRepo.Path})
+                       parentCommit, _, err = git.NewCommand(ctx, "rev-list", "-1", "--skip=1").AddDynamicArguments(commitSHA).RunStdString(&git.RunOpts{Dir: ctx.Repo.GitRepo.Path})
                        if err == nil {
                                parentCommit = strings.TrimSpace(parentCommit)
                        }
index 3e869376ee376a486080280bd1987756172dbe2e..8cb45f623dd97710ada963810090991cbeb788e4 100644 (file)
@@ -551,7 +551,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
 
                                filename2attribute2info, err := ctx.Repo.GitRepo.CheckAttribute(git.CheckAttributeOpts{
                                        CachedOnly: true,
-                                       Attributes: []string{"linguist-language", "gitlab-language"},
+                                       Attributes: []git.CmdArg{"linguist-language", "gitlab-language"},
                                        Filenames:  []string{ctx.Repo.TreePath},
                                        IndexFile:  indexFilename,
                                        WorkTree:   worktree,
index 9f0ce75123350b3c60e7053c05250df3c4a22290..cea2b1f5805770a94fa1ef1c6102571201640456 100644 (file)
@@ -179,7 +179,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
                }
 
                if !forcePush {
-                       output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1"oldCommitID, "^"+opts.NewCommitIDs[i]).RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()})
+                       output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+opts.NewCommitIDs[i]).RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()})
                        if err != nil {
                                return nil, fmt.Errorf("Fail to detect force push: %v", err)
                        } else if len(output) > 0 {
index 0d7ef4af03080bb5a0a7f09d86cbaa22d8e8b26d..ca35f5be57d05168fd56f428939be130a9804e20 100644 (file)
@@ -12,6 +12,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/setting"
        "code.gitea.io/gitea/services/auth"
        "code.gitea.io/gitea/services/migrations"
@@ -58,7 +59,12 @@ func registerRepoHealthCheck() {
                Args:    []string{},
        }, func(ctx context.Context, _ *user_model.User, config Config) error {
                rhcConfig := config.(*RepoHealthCheckConfig)
-               return repo_service.GitFsck(ctx, rhcConfig.Timeout, rhcConfig.Args)
+               // the git args are set by config, they can be safe to be trusted
+               args := make([]git.CmdArg, 0, len(rhcConfig.Args))
+               for _, arg := range rhcConfig.Args {
+                       args = append(args, git.CmdArg(arg))
+               }
+               return repo_service.GitFsck(ctx, rhcConfig.Timeout, args)
        })
 }
 
index 04b9560be35aadb0956785f79221d6f6211910f1..c730477cbd06318af4222fce4e28c62cf7cfe0b7 100644 (file)
@@ -13,6 +13,7 @@ import (
        "code.gitea.io/gitea/models/db"
        "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/setting"
        "code.gitea.io/gitea/modules/updatechecker"
        repo_service "code.gitea.io/gitea/services/repository"
@@ -60,7 +61,12 @@ func registerGarbageCollectRepositories() {
                Args:    setting.Git.GCArgs,
        }, func(ctx context.Context, _ *user_model.User, config Config) error {
                rhcConfig := config.(*RepoHealthCheckConfig)
-               return repo_service.GitGcRepos(ctx, rhcConfig.Timeout, rhcConfig.Args...)
+               // the git args are set by config, they can be safe to be trusted
+               args := make([]git.CmdArg, 0, len(rhcConfig.Args))
+               for _, arg := range rhcConfig.Args {
+                       args = append(args, git.CmdArg(arg))
+               }
+               return repo_service.GitGcRepos(ctx, rhcConfig.Timeout, args...)
        })
 }
 
index e687d9ae9163bb44961ea8e0aba543efef19917a..3c8c5c81a56945a57a8aec2a509213e8feb4221c 100644 (file)
@@ -1056,7 +1056,7 @@ type DiffOptions struct {
        MaxLines           int
        MaxLineCharacters  int
        MaxFiles           int
-       WhitespaceBehavior string
+       WhitespaceBehavior git.CmdArg
        DirectComparison   bool
 }
 
@@ -1082,7 +1082,7 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
                argsLength += len(files) + 1
        }
 
-       diffArgs := make([]string, 0, argsLength)
+       diffArgs := make([]git.CmdArg, 0, argsLength)
        if (len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == git.EmptySHA) && commit.ParentCount() == 0 {
                diffArgs = append(diffArgs, "diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M")
                if len(opts.WhitespaceBehavior) != 0 {
@@ -1090,7 +1090,7 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
                }
                // append empty tree ref
                diffArgs = append(diffArgs, "4b825dc642cb6eb9a060e54bf8d69288fbee4904")
-               diffArgs = append(diffArgs, opts.AfterCommitID)
+               diffArgs = append(diffArgs, git.CmdArgCheck(opts.AfterCommitID))
        } else {
                actualBeforeCommitID := opts.BeforeCommitID
                if len(actualBeforeCommitID) == 0 {
@@ -1101,8 +1101,8 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
                if len(opts.WhitespaceBehavior) != 0 {
                        diffArgs = append(diffArgs, opts.WhitespaceBehavior)
                }
-               diffArgs = append(diffArgs, actualBeforeCommitID)
-               diffArgs = append(diffArgs, opts.AfterCommitID)
+               diffArgs = append(diffArgs, git.CmdArgCheck(actualBeforeCommitID))
+               diffArgs = append(diffArgs, git.CmdArgCheck(opts.AfterCommitID))
                opts.BeforeCommitID = actualBeforeCommitID
        }
 
@@ -1111,13 +1111,15 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
        // the skipping for us
        parsePatchSkipToFile := opts.SkipTo
        if opts.SkipTo != "" && git.CheckGitVersionAtLeast("2.31") == nil {
-               diffArgs = append(diffArgs, "--skip-to="+opts.SkipTo)
+               diffArgs = append(diffArgs, git.CmdArg("--skip-to="+opts.SkipTo))
                parsePatchSkipToFile = ""
        }
 
        if len(files) > 0 {
                diffArgs = append(diffArgs, "--")
-               diffArgs = append(diffArgs, files...)
+               for _, file := range files {
+                       diffArgs = append(diffArgs, git.CmdArg(file)) // it's safe to cast it to CmdArg because there is a "--" before
+               }
        }
 
        reader, writer := io.Pipe()
@@ -1126,7 +1128,7 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
                _ = writer.Close()
        }()
 
-       go func(ctx context.Context, diffArgs []string, repoPath string, writer *io.PipeWriter) {
+       go func(ctx context.Context, diffArgs []git.CmdArg, repoPath string, writer *io.PipeWriter) {
                cmd := git.NewCommand(ctx, diffArgs...)
                cmd.SetDescription(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath))
                if err := cmd.Run(&git.RunOpts{
@@ -1199,15 +1201,15 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
                separator = ".."
        }
 
-       shortstatArgs := []string{opts.BeforeCommitID + separator + opts.AfterCommitID}
+       shortstatArgs := []git.CmdArg{git.CmdArgCheck(opts.BeforeCommitID + separator + opts.AfterCommitID)}
        if len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == git.EmptySHA {
-               shortstatArgs = []string{git.EmptyTreeSHA, opts.AfterCommitID}
+               shortstatArgs = []git.CmdArg{git.EmptyTreeSHA, git.CmdArgCheck(opts.AfterCommitID)}
        }
        diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, shortstatArgs...)
        if err != nil && strings.Contains(err.Error(), "no merge base") {
                // git >= 2.28 now returns an error if base and head have become unrelated.
                // previously it would return the results of git diff --shortstat base head so let's try that...
-               shortstatArgs = []string{opts.BeforeCommitID, opts.AfterCommitID}
+               shortstatArgs = []git.CmdArg{git.CmdArgCheck(opts.BeforeCommitID), git.CmdArgCheck(opts.AfterCommitID)}
                diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, shortstatArgs...)
        }
        if err != nil {
@@ -1322,7 +1324,7 @@ func CommentMustAsDiff(c *issues_model.Comment) *Diff {
 }
 
 // GetWhitespaceFlag returns git diff flag for treating whitespaces
-func GetWhitespaceFlag(whitespaceBehavior string) string {
+func GetWhitespaceFlag(whitespaceBehavior string) git.CmdArg {
        whitespaceFlags := map[string]string{
                "ignore-all":    "-w",
                "ignore-change": "-b",
@@ -1331,7 +1333,7 @@ func GetWhitespaceFlag(whitespaceBehavior string) string {
        }
 
        if flag, ok := whitespaceFlags[whitespaceBehavior]; ok {
-               return flag
+               return git.CmdArg(flag)
        }
        log.Warn("unknown whitespace behavior: %q, default to 'show-all'", whitespaceBehavior)
        return ""
index dfdd4df9c4453d1a15e4aa01a457e0fc250d1cff..a7fd677fef09489b2660935e64852823aa861ed6 100644 (file)
@@ -627,7 +627,7 @@ func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) {
                return
        }
        defer gitRepo.Close()
-       for _, behavior := range []string{"-w", "--ignore-space-at-eol", "-b", ""} {
+       for _, behavior := range []git.CmdArg{"-w", "--ignore-space-at-eol", "-b", ""} {
                diffs, err := GetDiff(gitRepo,
                        &DiffOptions{
                                AfterCommitID:      "bd7063cc7c04689c4d082183d32a604ed27a24f9",
index 188f2775e07b0730d3ac0fef85cde5d4a45f8d13..31fb1b4cf3ba0c5b339fe0de547a67d560f8ca3d 100644 (file)
@@ -491,7 +491,7 @@ func (g *RepositoryDumper) handlePullRequest(pr *base.PullRequest) error {
        if pr.Head.CloneURL == "" || pr.Head.Ref == "" {
                // Set head information if pr.Head.SHA is available
                if pr.Head.SHA != "" {
-                       _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref"pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.RunOpts{Dir: g.gitPath()})
+                       _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref").AddDynamicArguments(pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.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)
                        }
@@ -521,7 +521,7 @@ func (g *RepositoryDumper) handlePullRequest(pr *base.PullRequest) error {
        if !ok {
                // Set head information if pr.Head.SHA is available
                if pr.Head.SHA != "" {
-                       _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref"pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.RunOpts{Dir: g.gitPath()})
+                       _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref").AddDynamicArguments(pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.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)
                        }
@@ -556,7 +556,7 @@ func (g *RepositoryDumper) handlePullRequest(pr *base.PullRequest) error {
                        fetchArg = git.BranchPrefix + fetchArg
                }
 
-               _, _, err = git.NewCommand(g.ctx, "fetch", "--no-tags", "--", remote, fetchArg).RunStdString(&git.RunOpts{Dir: g.gitPath()})
+               _, _, err = git.NewCommand(g.ctx, "fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(&git.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
@@ -580,7 +580,7 @@ func (g *RepositoryDumper) handlePullRequest(pr *base.PullRequest) error {
                pr.Head.SHA = headSha
        }
        if pr.Head.SHA != "" {
-               _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref"pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.RunOpts{Dir: g.gitPath()})
+               _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref").AddDynamicArguments(pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.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)
                }
index 83388391da26f287693443f3d3f43f74bcb6dc69..c4cb59f5723b91bdd41d6c5b25d2814c09b93df4 100644 (file)
@@ -626,7 +626,7 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(pr *base.PullRequest) (head
                                fetchArg = git.BranchPrefix + fetchArg
                        }
 
-                       _, _, err = git.NewCommand(g.ctx, "fetch", "--no-tags", "--", remote, fetchArg).RunStdString(&git.RunOpts{Dir: g.repo.RepoPath()})
+                       _, _, err = git.NewCommand(g.ctx, "fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(&git.RunOpts{Dir: g.repo.RepoPath()})
                        if err != nil {
                                log.Error("Fetch branch from %s failed: %v", pr.Head.CloneURL, err)
                                return head, nil
@@ -645,7 +645,7 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(pr *base.PullRequest) (head
                        pr.Head.SHA = headSha
                }
 
-               _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref"pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.RunOpts{Dir: g.repo.RepoPath()})
+               _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref").AddDynamicArguments(pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.RunOpts{Dir: g.repo.RepoPath()})
                if err != nil {
                        return "", err
                }
@@ -662,13 +662,13 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(pr *base.PullRequest) (head
                // 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(g.ctx, "rev-list", "--quiet", "-1"pr.Head.SHA).RunStdString(&git.RunOpts{Dir: g.repo.RepoPath()})
+               _, _, err = git.NewCommand(g.ctx, "rev-list", "--quiet", "-1").AddDynamicArguments(pr.Head.SHA).RunStdString(&git.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.GetGitRefName())
                } else {
                        // set head information
-                       _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref"pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.RunOpts{Dir: g.repo.RepoPath()})
+                       _, _, err = git.NewCommand(g.ctx, "update-ref", "--no-deref").AddDynamicArguments(pr.GetGitRefName(), pr.Head.SHA).RunStdString(&git.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)
                        }
index af6230decb70a2a0c7cb2bbf87dd6515244bbc3b..68a7182b07e09344fee7f31cf38f4b866abfb8cc 100644 (file)
@@ -234,7 +234,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) {
        fromRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
        baseRef := "master"
        assert.NoError(t, git.InitRepository(git.DefaultContext, fromRepo.RepoPath(), false))
-       err := git.NewCommand(git.DefaultContext, "symbolic-ref""HEAD", git.BranchPrefix+baseRef).Run(&git.RunOpts{Dir: fromRepo.RepoPath()})
+       err := git.NewCommand(git.DefaultContext, "symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(&git.RunOpts{Dir: fromRepo.RepoPath()})
        assert.NoError(t, err)
        assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte(fmt.Sprintf("# Testing Repository\n\nOriginally created in: %s", fromRepo.RepoPath())), 0o644))
        assert.NoError(t, git.AddChanges(fromRepo.RepoPath(), true))
@@ -258,7 +258,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) {
        // fromRepo branch1
        //
        headRef := "branch1"
-       _, _, err = git.NewCommand(git.DefaultContext, "checkout", "-b"headRef).RunStdString(&git.RunOpts{Dir: fromRepo.RepoPath()})
+       _, _, err = git.NewCommand(git.DefaultContext, "checkout", "-b").AddDynamicArguments(headRef).RunStdString(&git.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(fromRepo.RepoPath(), true))
@@ -279,10 +279,10 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) {
        //
        forkHeadRef := "branch2"
        forkRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 8})
-       assert.NoError(t, git.CloneWithArgs(git.DefaultContext, fromRepo.RepoPath(), forkRepo.RepoPath(), []string{}, git.CloneRepoOptions{
+       assert.NoError(t, git.CloneWithArgs(git.DefaultContext, nil, fromRepo.RepoPath(), forkRepo.RepoPath(), git.CloneRepoOptions{
                Branch: headRef,
        }))
-       _, _, err = git.NewCommand(git.DefaultContext, "checkout", "-b"forkHeadRef).RunStdString(&git.RunOpts{Dir: forkRepo.RepoPath()})
+       _, _, err = git.NewCommand(git.DefaultContext, "checkout", "-b").AddDynamicArguments(forkHeadRef).RunStdString(&git.RunOpts{Dir: forkRepo.RepoPath()})
        assert.NoError(t, err)
        assert.NoError(t, os.WriteFile(filepath.Join(forkRepo.RepoPath(), "README.md"), []byte(fmt.Sprintf("# branch2 %s", forkRepo.RepoPath())), 0o644))
        assert.NoError(t, git.AddChanges(forkRepo.RepoPath(), true))
index a72e7f72eb8b650aa5ba3a345839da41a2118fb3..6002e6b8edb28c7601f69aad09dc6ee46171ee84 100644 (file)
@@ -33,12 +33,12 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
        remoteName := m.GetRemoteName()
        repoPath := m.GetRepository().RepoPath()
        // Remove old remote
-       _, _, err := git.NewCommand(ctx, "remote", "rm"remoteName).RunStdString(&git.RunOpts{Dir: repoPath})
+       _, _, err := git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(remoteName).RunStdString(&git.RunOpts{Dir: repoPath})
        if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
                return err
        }
 
-       cmd := git.NewCommand(ctx, "remote", "add", remoteName, "--mirror=fetch", addr)
+       cmd := git.NewCommand(ctx, "remote", "add").AddDynamicArguments(remoteName).AddArguments("--mirror=fetch").AddDynamicArguments(addr)
        if strings.Contains(addr, "://") && strings.Contains(addr, "@") {
                cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=fetch %s [repo_path: %s]", remoteName, util.SanitizeCredentialURLs(addr), repoPath))
        } else {
@@ -53,12 +53,12 @@ func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error
                wikiPath := m.Repo.WikiPath()
                wikiRemotePath := repo_module.WikiRemoteURL(ctx, addr)
                // Remove old remote of wiki
-               _, _, err = git.NewCommand(ctx, "remote", "rm"remoteName).RunStdString(&git.RunOpts{Dir: wikiPath})
+               _, _, err = git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(remoteName).RunStdString(&git.RunOpts{Dir: wikiPath})
                if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
                        return err
                }
 
-               cmd = git.NewCommand(ctx, "remote", "add", remoteName, "--mirror=fetch", wikiRemotePath)
+               cmd = git.NewCommand(ctx, "remote", "add").AddDynamicArguments(remoteName).AddArguments("--mirror=fetch").AddDynamicArguments(wikiRemotePath)
                if strings.Contains(wikiRemotePath, "://") && strings.Contains(wikiRemotePath, "@") {
                        cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=fetch %s [repo_path: %s]", remoteName, util.SanitizeCredentialURLs(wikiRemotePath), wikiPath))
                } else {
@@ -169,7 +169,7 @@ func pruneBrokenReferences(ctx context.Context,
 
        stderrBuilder.Reset()
        stdoutBuilder.Reset()
-       pruneErr := git.NewCommand(ctx, "remote", "prune"m.GetRemoteName()).
+       pruneErr := git.NewCommand(ctx, "remote", "prune").AddDynamicArguments(m.GetRemoteName()).
                SetDescription(fmt.Sprintf("Mirror.runSync %ssPrune references: %s ", wiki, m.Repo.FullName())).
                Run(&git.RunOpts{
                        Timeout: timeout,
@@ -204,11 +204,11 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
 
        log.Trace("SyncMirrors [repo: %-v]: running git remote update...", m.Repo)
 
-       gitArgs := []string{"remote", "update"}
+       gitArgs := []git.CmdArg{"remote", "update"}
        if m.EnablePrune {
                gitArgs = append(gitArgs, "--prune")
        }
-       gitArgs = append(gitArgs, m.GetRemoteName())
+       gitArgs = append(gitArgs, git.CmdArgCheck(m.GetRemoteName()))
 
        remoteURL, remoteErr := git.GetRemoteURL(ctx, repoPath, m.GetRemoteName())
        if remoteErr != nil {
@@ -309,7 +309,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
                log.Trace("SyncMirrors [repo: %-v Wiki]: running git remote update...", m.Repo)
                stderrBuilder.Reset()
                stdoutBuilder.Reset()
-               if err := git.NewCommand(ctx, "remote", "update", "--prune"m.GetRemoteName()).
+               if err := git.NewCommand(ctx, "remote", "update", "--prune").AddDynamicArguments(m.GetRemoteName()).
                        SetDescription(fmt.Sprintf("Mirror.runSync Wiki: %s ", m.Repo.FullName())).
                        Run(&git.RunOpts{
                                Timeout: timeout,
@@ -336,7 +336,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
                                        stderrBuilder.Reset()
                                        stdoutBuilder.Reset()
 
-                                       if err = git.NewCommand(ctx, "remote", "update", "--prune"m.GetRemoteName()).
+                                       if err = git.NewCommand(ctx, "remote", "update", "--prune").AddDynamicArguments(m.GetRemoteName()).
                                                SetDescription(fmt.Sprintf("Mirror.runSync Wiki: %s ", m.Repo.FullName())).
                                                Run(&git.RunOpts{
                                                        Timeout: timeout,
index 0c8960d78bf204252d31b965f976af1c4d2d3c3c..60611130ba8cd525d0baa357de73834cc49c92e5 100644 (file)
@@ -29,7 +29,7 @@ var stripExitStatus = regexp.MustCompile(`exit status \d+ - `)
 // AddPushMirrorRemote registers the push mirror remote.
 func AddPushMirrorRemote(ctx context.Context, m *repo_model.PushMirror, addr string) error {
        addRemoteAndConfig := func(addr, path string) error {
-               cmd := git.NewCommand(ctx, "remote", "add", "--mirror=push"m.RemoteName, addr)
+               cmd := git.NewCommand(ctx, "remote", "add", "--mirror=push").AddDynamicArguments(m.RemoteName, addr)
                if strings.Contains(addr, "://") && strings.Contains(addr, "@") {
                        cmd.SetDescription(fmt.Sprintf("remote add %s --mirror=push %s [repo_path: %s]", m.RemoteName, util.SanitizeCredentialURLs(addr), path))
                } else {
@@ -38,10 +38,10 @@ func AddPushMirrorRemote(ctx context.Context, m *repo_model.PushMirror, addr str
                if _, _, err := cmd.RunStdString(&git.RunOpts{Dir: path}); err != nil {
                        return err
                }
-               if _, _, err := git.NewCommand(ctx, "config", "--add", "remote."+m.RemoteName+".push", "+refs/heads/*:refs/heads/*").RunStdString(&git.RunOpts{Dir: path}); err != nil {
+               if _, _, err := git.NewCommand(ctx, "config", "--add", git.CmdArg("remote."+m.RemoteName+".push"), "+refs/heads/*:refs/heads/*").RunStdString(&git.RunOpts{Dir: path}); err != nil {
                        return err
                }
-               if _, _, err := git.NewCommand(ctx, "config", "--add", "remote."+m.RemoteName+".push", "+refs/tags/*:refs/tags/*").RunStdString(&git.RunOpts{Dir: path}); err != nil {
+               if _, _, err := git.NewCommand(ctx, "config", "--add", git.CmdArg("remote."+m.RemoteName+".push"), "+refs/tags/*:refs/tags/*").RunStdString(&git.RunOpts{Dir: path}); err != nil {
                        return err
                }
                return nil
@@ -65,7 +65,7 @@ func AddPushMirrorRemote(ctx context.Context, m *repo_model.PushMirror, addr str
 
 // RemovePushMirrorRemote removes the push mirror remote.
 func RemovePushMirrorRemote(ctx context.Context, m *repo_model.PushMirror) error {
-       cmd := git.NewCommand(ctx, "remote", "rm"m.RemoteName)
+       cmd := git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(m.RemoteName)
        _ = m.GetRepository()
 
        if _, _, err := cmd.RunStdString(&git.RunOpts{Dir: m.Repo.RepoPath()}); err != nil {
index 288f4dc0b73b7cd54a5457d879bee6f9c95bdff7..765672190dc4c212de10c0d472edc8bff3ac143a 100644 (file)
@@ -185,7 +185,7 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com
        headFile := pr.GetGitRefName()
 
        // Check if a pull request is merged into BaseBranch
-       _, _, err = git.NewCommand(ctx, "merge-base", "--is-ancestor"headFile, pr.BaseBranch).
+       _, _, err = git.NewCommand(ctx, "merge-base", "--is-ancestor").AddDynamicArguments(headFile, pr.BaseBranch).
                RunStdString(&git.RunOpts{Dir: pr.BaseRepo.RepoPath(), Env: []string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()}})
        if err != nil {
                // Errors are signaled by a non-zero status that is not 1
@@ -206,7 +206,7 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com
        cmd := commitID[:40] + ".." + pr.BaseBranch
 
        // Get the commit from BaseBranch where the pull request got merged
-       mergeCommit, _, err := git.NewCommand(ctx, "rev-list", "--ancestry-path", "--merges", "--reverse"cmd).
+       mergeCommit, _, err := git.NewCommand(ctx, "rev-list", "--ancestry-path", "--merges", "--reverse").AddDynamicArguments(cmd).
                RunStdString(&git.RunOpts{Dir: "", Env: []string{"GIT_INDEX_FILE=" + indexTmpPath, "GIT_DIR=" + pr.BaseRepo.RepoPath()}})
        if err != nil {
                return nil, fmt.Errorf("git rev-list --ancestry-path --merges --reverse: %v", err)
index 6f3df6ab2a5a34e8f703cbdeab7f938d07a8a4ec..f9a4e6705f40ecda059b2e3d509ab324741d9a63 100644 (file)
@@ -244,7 +244,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
        stagingBranch := "staging"
 
        if expectedHeadCommitID != "" {
-               trackingCommitID, _, err := git.NewCommand(ctx, "show-ref", "--hash", git.BranchPrefix+trackingBranch).RunStdString(&git.RunOpts{Dir: tmpBasePath})
+               trackingCommitID, _, err := git.NewCommand(ctx, "show-ref", "--hash").AddDynamicArguments(git.BranchPrefix + trackingBranch).RunStdString(&git.RunOpts{Dir: tmpBasePath})
                if err != nil {
                        log.Error("show-ref[%s] --hash refs/heads/trackingn: %v", tmpBasePath, git.BranchPrefix+trackingBranch, err)
                        return "", fmt.Errorf("getDiffTree: %v", err)
@@ -360,15 +360,15 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
        committer := sig
 
        // Determine if we should sign
-       var signArg string
+       var signArg git.CmdArg
        sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, pr, doer, tmpBasePath, "HEAD", trackingBranch)
        if sign {
-               signArg = "-S" + keyID
+               signArg = git.CmdArg("-S" + keyID)
                if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
                        committer = signer
                }
        } else {
-               signArg = "--no-gpg-sign"
+               signArg = git.CmdArg("--no-gpg-sign")
        }
 
        commitTimeStr := time.Now().Format(time.RFC3339)
@@ -386,7 +386,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
        // Merge commits.
        switch mergeStyle {
        case repo_model.MergeStyleMerge:
-               cmd := git.NewCommand(ctx, "merge", "--no-ff", "--no-commit"trackingBranch)
+               cmd := git.NewCommand(ctx, "merge", "--no-ff", "--no-commit").AddDynamicArguments(trackingBranch)
                if err := runMergeCommand(pr, mergeStyle, cmd, tmpBasePath); err != nil {
                        log.Error("Unable to merge tracking into base: %v", err)
                        return "", err
@@ -402,7 +402,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
                fallthrough
        case repo_model.MergeStyleRebaseMerge:
                // Checkout head branch
-               if err := git.NewCommand(ctx, "checkout", "-b"stagingBranch, trackingBranch).
+               if err := git.NewCommand(ctx, "checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch).
                        Run(&git.RunOpts{
                                Dir:    tmpBasePath,
                                Stdout: &outbuf,
@@ -415,7 +415,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
                errbuf.Reset()
 
                // Rebase before merging
-               if err := git.NewCommand(ctx, "rebase"baseBranch).
+               if err := git.NewCommand(ctx, "rebase").AddDynamicArguments(baseBranch).
                        Run(&git.RunOpts{
                                Dir:    tmpBasePath,
                                Stdout: &outbuf,
@@ -468,7 +468,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
                }
 
                // Checkout base branch again
-               if err := git.NewCommand(ctx, "checkout"baseBranch).
+               if err := git.NewCommand(ctx, "checkout").AddDynamicArguments(baseBranch).
                        Run(&git.RunOpts{
                                Dir:    tmpBasePath,
                                Stdout: &outbuf,
@@ -486,7 +486,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
                } else {
                        cmd.AddArguments("--no-ff", "--no-commit")
                }
-               cmd.AddArguments(stagingBranch)
+               cmd.AddDynamicArguments(stagingBranch)
 
                // Prepare merge with commit
                if err := runMergeCommand(pr, mergeStyle, cmd, tmpBasePath); err != nil {
@@ -501,7 +501,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
                }
        case repo_model.MergeStyleSquash:
                // Merge with squash
-               cmd := git.NewCommand(ctx, "merge", "--squash"trackingBranch)
+               cmd := git.NewCommand(ctx, "merge", "--squash").AddDynamicArguments(trackingBranch)
                if err := runMergeCommand(pr, mergeStyle, cmd, tmpBasePath); err != nil {
                        log.Error("Unable to merge --squash tracking into base: %v", err)
                        return "", err
@@ -513,7 +513,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
                }
                sig := pr.Issue.Poster.NewGitSig()
                if signArg == "" {
-                       if err := git.NewCommand(ctx, "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", message).
+                       if err := git.NewCommand(ctx, "commit", git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email)), "-m").AddDynamicArguments(message).
                                Run(&git.RunOpts{
                                        Env:    env,
                                        Dir:    tmpBasePath,
@@ -528,7 +528,10 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
                                // add trailer
                                message += fmt.Sprintf("\nCo-authored-by: %s\nCo-committed-by: %s\n", sig.String(), sig.String())
                        }
-                       if err := git.NewCommand(ctx, "commit", signArg, fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", message).
+                       if err := git.NewCommand(ctx, "commit").
+                               AddArguments(signArg).
+                               AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email))).
+                               AddArguments("-m").AddDynamicArguments(message).
                                Run(&git.RunOpts{
                                        Env:    env,
                                        Dir:    tmpBasePath,
@@ -592,9 +595,9 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
        var pushCmd *git.Command
        if mergeStyle == repo_model.MergeStyleRebaseUpdate {
                // force push the rebase result to head branch
-               pushCmd = git.NewCommand(ctx, "push", "-f", "head_repo", stagingBranch+":"+git.BranchPrefix+pr.HeadBranch)
+               pushCmd = git.NewCommand(ctx, "push", "-f", "head_repo").AddDynamicArguments(stagingBranch + ":" + git.BranchPrefix + pr.HeadBranch)
        } else {
-               pushCmd = git.NewCommand(ctx, "push", "origin", baseBranch+":"+git.BranchPrefix+pr.BaseBranch)
+               pushCmd = git.NewCommand(ctx, "push", "origin").AddDynamicArguments(baseBranch + ":" + git.BranchPrefix + pr.BaseBranch)
        }
 
        // Push back to upstream.
@@ -629,10 +632,10 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
        return mergeCommitID, nil
 }
 
-func commitAndSignNoAuthor(ctx context.Context, pr *issues_model.PullRequest, message, signArg, tmpBasePath string, env []string) error {
+func commitAndSignNoAuthor(ctx context.Context, pr *issues_model.PullRequest, message string, signArg git.CmdArg, tmpBasePath string, env []string) error {
        var outbuf, errbuf strings.Builder
        if signArg == "" {
-               if err := git.NewCommand(ctx, "commit", "-m"message).
+               if err := git.NewCommand(ctx, "commit", "-m").AddDynamicArguments(message).
                        Run(&git.RunOpts{
                                Env:    env,
                                Dir:    tmpBasePath,
@@ -643,7 +646,7 @@ func commitAndSignNoAuthor(ctx context.Context, pr *issues_model.PullRequest, me
                        return fmt.Errorf("git commit [%s:%s -> %s:%s]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
                }
        } else {
-               if err := git.NewCommand(ctx, "commit", signArg, "-m", message).
+               if err := git.NewCommand(ctx, "commit").AddArguments(signArg).AddArguments("-m").AddDynamicArguments(message).
                        Run(&git.RunOpts{
                                Env:    env,
                                Dir:    tmpBasePath,
@@ -696,7 +699,7 @@ func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string) (
        getDiffTreeFromBranch := func(repoPath, baseBranch, headBranch string) (string, error) {
                var outbuf, errbuf strings.Builder
                // Compute the diff-tree for sparse-checkout
-               if err := git.NewCommand(ctx, "diff-tree", "--no-commit-id", "--name-only", "-r", "-z", "--root", baseBranch, headBranch, "--").
+               if err := git.NewCommand(ctx, "diff-tree", "--no-commit-id", "--name-only", "-r", "-z", "--root").AddDynamicArguments(baseBranch, headBranch).
                        Run(&git.RunOpts{
                                Dir:    repoPath,
                                Stdout: &outbuf,
index dafd57706915fdecb0db6e6ee50883cdb058b27d..b9f190826a496a81641892fe497965c954066e72 100644 (file)
@@ -178,7 +178,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, g
                }
 
                // Need to get the objects from the object db to attempt to merge
-               root, _, err := git.NewCommand(ctx, "unpack-file"file.stage1.sha).RunStdString(&git.RunOpts{Dir: tmpBasePath})
+               root, _, err := git.NewCommand(ctx, "unpack-file").AddDynamicArguments(file.stage1.sha).RunStdString(&git.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)
                }
@@ -187,7 +187,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, g
                        _ = util.Remove(filepath.Join(tmpBasePath, root))
                }()
 
-               base, _, err := git.NewCommand(ctx, "unpack-file"file.stage2.sha).RunStdString(&git.RunOpts{Dir: tmpBasePath})
+               base, _, err := git.NewCommand(ctx, "unpack-file").AddDynamicArguments(file.stage2.sha).RunStdString(&git.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)
                }
@@ -195,7 +195,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, g
                defer func() {
                        _ = util.Remove(base)
                }()
-               head, _, err := git.NewCommand(ctx, "unpack-file"file.stage3.sha).RunStdString(&git.RunOpts{Dir: tmpBasePath})
+               head, _, err := git.NewCommand(ctx, "unpack-file").AddDynamicArguments(file.stage3.sha).RunStdString(&git.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)
                }
@@ -205,13 +205,13 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, g
                }()
 
                // now git merge-file annoyingly takes a different order to the merge-tree ...
-               _, _, conflictErr := git.NewCommand(ctx, "merge-file"base, root, head).RunStdString(&git.RunOpts{Dir: tmpBasePath})
+               _, _, conflictErr := git.NewCommand(ctx, "merge-file").AddDynamicArguments(base, root, head).RunStdString(&git.RunOpts{Dir: tmpBasePath})
                if conflictErr != nil {
                        return &errMergeConflict{file.stage2.path}
                }
 
                // base now contains the merged data
-               hash, _, err := git.NewCommand(ctx, "hash-object", "-w", "--path"file.stage2.path, base).RunStdString(&git.RunOpts{Dir: tmpBasePath})
+               hash, _, err := git.NewCommand(ctx, "hash-object", "-w", "--path").AddDynamicArguments(file.stage2.path, base).RunStdString(&git.RunOpts{Dir: tmpBasePath})
                if err != nil {
                        return err
                }
@@ -235,7 +235,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(ctx, "read-tree", "-m"base, ours, theirs).RunStdString(&git.RunOpts{Dir: gitPath}); err != nil {
+       if _, _, err := git.NewCommand(ctx, "read-tree", "-m").AddDynamicArguments(base, ours, theirs).RunStdString(&git.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: %v", err)
        }
@@ -361,7 +361,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
-       args := []string{"apply", "--check", "--cached"}
+       args := []git.CmdArg{"apply", "--check", "--cached"}
        if prConfig.IgnoreWhitespaceConflicts {
                args = append(args, "--ignore-whitespace")
        }
@@ -370,7 +370,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo *
                args = append(args, "--3way")
                is3way = true
        }
-       args = append(args, patchPath)
+       args = append(args, git.CmdArgCheck(patchPath))
 
        // 7. Prep the pipe:
        //   - Here we could do the equivalent of:
index 9de7cb5d4f8e9c686ac98fa9fb809a77659850cf..3b58c675a37f9c3d40d1087e41c2e7cff52977c9 100644 (file)
@@ -490,7 +490,7 @@ func UpdateRef(ctx context.Context, pr *issues_model.PullRequest) (err error) {
                return err
        }
 
-       _, _, err = git.NewCommand(ctx, "update-ref"pr.GetGitRefName(), pr.HeadCommitID).RunStdString(&git.RunOpts{Dir: pr.BaseRepo.RepoPath()})
+       _, _, err = git.NewCommand(ctx, "update-ref").AddDynamicArguments(pr.GetGitRefName(), pr.HeadCommitID).RunStdString(&git.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)
        }
index c1456ef0a99ee59e7c89330f96f543004e67c4ca..6624f5659b605471503a64a3ca57f677e36950b1 100644 (file)
@@ -94,7 +94,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
        }
 
        var outbuf, errbuf strings.Builder
-       if err := git.NewCommand(ctx, "remote", "add", "-t", pr.BaseBranch, "-m", pr.BaseBranch, "origin", baseRepoPath).
+       if err := git.NewCommand(ctx, "remote", "add", "-t").AddDynamicArguments(pr.BaseBranch).AddArguments("-m").AddDynamicArguments(pr.BaseBranch).AddDynamicArguments("origin", baseRepoPath).
                Run(&git.RunOpts{
                        Dir:    tmpBasePath,
                        Stdout: &outbuf,
@@ -109,7 +109,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
        outbuf.Reset()
        errbuf.Reset()
 
-       if err := git.NewCommand(ctx, "fetch", "origin", "--no-tags", "--", pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).
+       if err := git.NewCommand(ctx, "fetch", "origin", "--no-tags").AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch).
                Run(&git.RunOpts{
                        Dir:    tmpBasePath,
                        Stdout: &outbuf,
@@ -124,7 +124,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
        outbuf.Reset()
        errbuf.Reset()
 
-       if err := git.NewCommand(ctx, "symbolic-ref""HEAD", git.BranchPrefix+baseBranch).
+       if err := git.NewCommand(ctx, "symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseBranch).
                Run(&git.RunOpts{
                        Dir:    tmpBasePath,
                        Stdout: &outbuf,
@@ -147,7 +147,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
                return "", fmt.Errorf("Unable to head base repository to temporary repo [%s -> tmpBasePath]: %v", pr.HeadRepo.FullName(), err)
        }
 
-       if err := git.NewCommand(ctx, "remote", "add"remoteRepoName, headRepoPath).
+       if err := git.NewCommand(ctx, "remote", "add").AddDynamicArguments(remoteRepoName, headRepoPath).
                Run(&git.RunOpts{
                        Dir:    tmpBasePath,
                        Stdout: &outbuf,
@@ -172,7 +172,7 @@ func createTemporaryRepo(ctx context.Context, pr *issues_model.PullRequest) (str
        } else {
                headBranch = pr.GetGitRefName()
        }
-       if err := git.NewCommand(ctx, "fetch", "--no-tags"remoteRepoName, headBranch+":"+trackingBranch).
+       if err := git.NewCommand(ctx, "fetch", "--no-tags").AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch).
                Run(&git.RunOpts{
                        Dir:    tmpBasePath,
                        Stdout: &outbuf,
index af1b0752320809df4a6942157f9eff13e102a318..25b89e1a0b6d7ef126ff289754d629a8b2a26b6b 100644 (file)
@@ -309,7 +309,7 @@ func DeleteReleaseByID(ctx context.Context, id int64, doer *user_model.User, del
                        }
                }
 
-               if stdout, _, err := git.NewCommand(ctx, "tag", "-d", "--", rel.TagName).
+               if stdout, _, err := git.NewCommand(ctx, "tag", "-d").AddDashesAndList(rel.TagName).
                        SetDescription(fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID)).
                        RunStdString(&git.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)
index 2417db6a271d0dd8619e0d84928028a542795e22..1b2da4cc0823bddd1cfe444a0f979d52db2130fd 100644 (file)
@@ -24,7 +24,7 @@ import (
 )
 
 // GitFsck calls 'git fsck' to check repository health.
-func GitFsck(ctx context.Context, timeout time.Duration, args []string) error {
+func GitFsck(ctx context.Context, timeout time.Duration, args []git.CmdArg) error {
        log.Trace("Doing: GitFsck")
 
        if err := db.Iterate(
@@ -58,9 +58,9 @@ func GitFsck(ctx context.Context, timeout time.Duration, args []string) error {
 }
 
 // GitGcRepos calls 'git gc' to remove unnecessary files and optimize the local repository
-func GitGcRepos(ctx context.Context, timeout time.Duration, args ...string) error {
+func GitGcRepos(ctx context.Context, timeout time.Duration, args ...git.CmdArg) error {
        log.Trace("Doing: GitGcRepos")
-       args = append([]string{"gc"}, args...)
+       args = append([]git.CmdArg{"gc"}, args...)
 
        if err := db.Iterate(
                ctx,
index d55d793f28cd39a7af9046ab066097de47839f0d..437890c488c63d6e7153f5cd1fa6d853e6ba4110 100644 (file)
@@ -139,7 +139,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
        stdout := &strings.Builder{}
        stderr := &strings.Builder{}
 
-       args := []string{"apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary"}
+       args := []git.CmdArg{"apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary"}
 
        if git.CheckGitVersionAtLeast("2.32") == nil {
                args = append(args, "-3")
index 1e60d55613fa0adbb44adf1fa0049529e4383bce..9513f2341e156799abb4a8c80415dafb1e50c5f6 100644 (file)
@@ -53,7 +53,7 @@ func (t *TemporaryUploadRepository) Close() {
 
 // Clone the base repository to our path and set branch as the HEAD
 func (t *TemporaryUploadRepository) Clone(branch string) error {
-       if _, _, err := git.NewCommand(t.ctx, "clone", "-s", "--bare", "-b"branch, t.repo.RepoPath(), t.basePath).RunStdString(nil); err != nil {
+       if _, _, err := git.NewCommand(t.ctx, "clone", "-s", "--bare", "-b").AddDynamicArguments(branch, t.repo.RepoPath(), t.basePath).RunStdString(nil); err != nil {
                stderr := err.Error()
                if matched, _ := regexp.MatchString(".*Remote branch .* not found in upstream origin.*", stderr); matched {
                        return git.ErrBranchNotExist{
@@ -104,14 +104,7 @@ func (t *TemporaryUploadRepository) LsFiles(filenames ...string) ([]string, erro
        stdOut := new(bytes.Buffer)
        stdErr := new(bytes.Buffer)
 
-       cmdArgs := []string{"ls-files", "-z", "--"}
-       for _, arg := range filenames {
-               if arg != "" {
-                       cmdArgs = append(cmdArgs, arg)
-               }
-       }
-
-       if err := git.NewCommand(t.ctx, cmdArgs...).
+       if err := git.NewCommand(t.ctx, "ls-files", "-z").AddDashesAndList(filenames...).
                Run(&git.RunOpts{
                        Dir:    t.basePath,
                        Stdout: stdOut,
@@ -177,7 +170,7 @@ func (t *TemporaryUploadRepository) HashObject(content io.Reader) (string, error
 
 // AddObjectToIndex adds the provided object hash to the index with the provided mode and path
 func (t *TemporaryUploadRepository) AddObjectToIndex(mode, objectHash, objectPath string) error {
-       if _, _, err := git.NewCommand(t.ctx, "update-index", "--add", "--replace", "--cacheinfo"mode, objectHash, objectPath).RunStdString(&git.RunOpts{Dir: t.basePath}); err != nil {
+       if _, _, err := git.NewCommand(t.ctx, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(&git.RunOpts{Dir: t.basePath}); err != nil {
                stderr := err.Error()
                if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched {
                        return models.ErrFilePathInvalid{
@@ -211,7 +204,7 @@ func (t *TemporaryUploadRepository) GetLastCommitByRef(ref string) (string, erro
        if ref == "" {
                ref = "HEAD"
        }
-       stdout, _, err := git.NewCommand(t.ctx, "rev-parse"ref).RunStdString(&git.RunOpts{Dir: t.basePath})
+       stdout, _, err := git.NewCommand(t.ctx, "rev-parse").AddDynamicArguments(ref).RunStdString(&git.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: %v", ref, t.repo.FullName(), err)
@@ -241,11 +234,11 @@ func (t *TemporaryUploadRepository) CommitTreeWithDate(parent string, author, co
        _, _ = messageBytes.WriteString(message)
        _, _ = messageBytes.WriteString("\n")
 
-       var args []string
+       var args []git.CmdArg
        if parent != "" {
-               args = []string{"commit-tree", treeHash, "-p", parent}
+               args = []git.CmdArg{"commit-tree", git.CmdArgCheck(treeHash), "-p", git.CmdArgCheck(parent)}
        } else {
-               args = []string{"commit-tree", treeHash}
+               args = []git.CmdArg{"commit-tree", git.CmdArgCheck(treeHash)}
        }
 
        var sign bool
@@ -257,7 +250,7 @@ func (t *TemporaryUploadRepository) CommitTreeWithDate(parent string, author, co
                sign, keyID, signer, _ = asymkey_service.SignInitialCommit(t.ctx, t.repo.RepoPath(), author)
        }
        if sign {
-               args = append(args, "-S"+keyID)
+               args = append(args, git.CmdArg("-S"+keyID))
                if t.repo.GetTrustModel() == repo_model.CommitterTrustModel || t.repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
                        if committerSig.Name != authorSig.Name || committerSig.Email != authorSig.Email {
                                // Add trailers
index 4615a9153a68a0b47065aa4b51359f54643f679a..87c622a9be3ccf9a122c712c23babdf2a8e0141d 100644 (file)
@@ -370,7 +370,7 @@ func CreateOrUpdateRepoFile(ctx context.Context, repo *repo_model.Repository, do
        if setting.LFS.StartServer && hasOldBranch {
                // Check there is no way this can return multiple infos
                filename2attribute2info, err := t.gitRepo.CheckAttribute(git.CheckAttributeOpts{
-                       Attributes: []string{"filter"},
+                       Attributes: []git.CmdArg{"filter"},
                        Filenames:  []string{treePath},
                        CachedOnly: true,
                })
index 327a2e121ca5af2b95f051bda93892aa3ea3dc4c..b2dadb6497c5b52a13cf30191d5ef631d24bca09 100644 (file)
@@ -96,7 +96,7 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
        var filename2attribute2info map[string]map[string]string
        if setting.LFS.StartServer {
                filename2attribute2info, err = t.gitRepo.CheckAttribute(git.CheckAttributeOpts{
-                       Attributes: []string{"filter"},
+                       Attributes: []git.CmdArg{"filter"},
                        Filenames:  names,
                        CachedOnly: true,
                })
index 32a516b79f992dca850d62f06aa78dd3704b1e80..af0ade99a9472c3306b41a57aa29ed968b7c0e43 100644 (file)
@@ -130,7 +130,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
 
                repoPath := repo_model.RepoPath(owner.Name, repo.Name)
                if stdout, _, err := git.NewCommand(txCtx,
-                       "clone", "--bare"oldRepoPath, repoPath).
+                       "clone", "--bare").AddDynamicArguments(oldRepoPath, repoPath).
                        SetDescription(fmt.Sprintf("ForkRepository(git clone): %s to %s", opts.BaseRepo.FullName(), repo.FullName())).
                        RunStdBytes(&git.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)
index 855eb2451e80c912b80cb0ca31b4fbf40eac6469..3357f9568dbdad6cde4e480fb43ecf477bb5b4f6 100644 (file)
@@ -29,8 +29,8 @@ func TestAPIGitTags(t *testing.T) {
        token := getTokenForLoggedInUser(t, session)
 
        // Set up git config for the tagger
-       _ = git.NewCommand(git.DefaultContext, "config", "user.name"user.Name).Run(&git.RunOpts{Dir: repo.RepoPath()})
-       _ = git.NewCommand(git.DefaultContext, "config", "user.email"user.Email).Run(&git.RunOpts{Dir: repo.RepoPath()})
+       _ = git.NewCommand(git.DefaultContext, "config", "user.name").AddDynamicArguments(user.Name).Run(&git.RunOpts{Dir: repo.RepoPath()})
+       _ = git.NewCommand(git.DefaultContext, "config", "user.email").AddDynamicArguments(user.Email).Run(&git.RunOpts{Dir: repo.RepoPath()})
 
        gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath())
        defer gitRepo.Close()
index 3e10b17d40bebd7fe393c9f7702c300500312306..e8764e6bd9f5daea05ae4e6b25d0af1a9f30a760 100644 (file)
@@ -41,7 +41,7 @@ func TestRepoCloneWiki(t *testing.T) {
                u, _ = url.Parse(r)
                u.User = url.UserPassword("user2", userPassword)
                t.Run("Clone", func(t *testing.T) {
-                       assert.NoError(t, git.CloneWithArgs(context.Background(), u.String(), dstPath, git.AllowLFSFiltersArgs(), git.CloneRepoOptions{}))
+                       assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstPath, git.CloneRepoOptions{}))
                        assertFileEqual(t, filepath.Join(dstPath, "Home.md"), []byte("# Home page\n\nThis is the home page!\n"))
                        assertFileExist(t, filepath.Join(dstPath, "Page-With-Image.md"))
                        assertFileExist(t, filepath.Join(dstPath, "Page-With-Spaced-Name.md"))
index 4f2e540883a00109fcfb2d91cee83e87a44e33e4..45b4f4447510dc70d9f9e51d55c1e6c6c766f6a7 100644 (file)
@@ -98,7 +98,7 @@ func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL), prepare ...bo
 
 func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
        return func(t *testing.T) {
-               assert.NoError(t, git.CloneWithArgs(context.Background(), u.String(), dstLocalPath, git.AllowLFSFiltersArgs(), git.CloneRepoOptions{}))
+               assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstLocalPath, git.CloneRepoOptions{}))
                exist, err := util.IsExist(filepath.Join(dstLocalPath, "README.md"))
                assert.NoError(t, err)
                assert.True(t, exist)
@@ -107,7 +107,7 @@ func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
 
 func doPartialGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
        return func(t *testing.T) {
-               assert.NoError(t, git.CloneWithArgs(context.Background(), u.String(), dstLocalPath, git.AllowLFSFiltersArgs(), git.CloneRepoOptions{
+               assert.NoError(t, git.CloneWithArgs(context.Background(), git.AllowLFSFiltersArgs(), u.String(), dstLocalPath, git.CloneRepoOptions{
                        Filter: "blob:none",
                }))
                exist, err := util.IsExist(filepath.Join(dstLocalPath, "README.md"))
@@ -150,47 +150,47 @@ 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(git.DefaultContext, "remote", "add"remoteName, u.String()).RunStdString(&git.RunOpts{Dir: dstPath})
+               _, _, err := git.NewCommand(git.DefaultContext, "remote", "add").AddDynamicArguments(remoteName, u.String()).RunStdString(&git.RunOpts{Dir: dstPath})
                assert.NoError(t, err)
        }
 }
 
-func doGitPushTestRepository(dstPath string, args ...string) func(*testing.T) {
+func doGitPushTestRepository(dstPath string, args ...git.CmdArg) func(*testing.T) {
        return func(t *testing.T) {
-               _, _, err := git.NewCommand(git.DefaultContext, append([]string{"push", "-u"}, args...)...).RunStdString(&git.RunOpts{Dir: dstPath})
+               _, _, err := git.NewCommand(git.DefaultContext, append([]git.CmdArg{"push", "-u"}, args...)...).RunStdString(&git.RunOpts{Dir: dstPath})
                assert.NoError(t, err)
        }
 }
 
-func doGitPushTestRepositoryFail(dstPath string, args ...string) func(*testing.T) {
+func doGitPushTestRepositoryFail(dstPath string, args ...git.CmdArg) func(*testing.T) {
        return func(t *testing.T) {
-               _, _, err := git.NewCommand(git.DefaultContext, append([]string{"push"}, args...)...).RunStdString(&git.RunOpts{Dir: dstPath})
+               _, _, err := git.NewCommand(git.DefaultContext, append([]git.CmdArg{"push"}, args...)...).RunStdString(&git.RunOpts{Dir: dstPath})
                assert.Error(t, err)
        }
 }
 
 func doGitCreateBranch(dstPath, branch string) func(*testing.T) {
        return func(t *testing.T) {
-               _, _, err := git.NewCommand(git.DefaultContext, "checkout", "-b"branch).RunStdString(&git.RunOpts{Dir: dstPath})
+               _, _, err := git.NewCommand(git.DefaultContext, "checkout", "-b").AddDynamicArguments(branch).RunStdString(&git.RunOpts{Dir: dstPath})
                assert.NoError(t, err)
        }
 }
 
-func doGitCheckoutBranch(dstPath string, args ...string) func(*testing.T) {
+func doGitCheckoutBranch(dstPath string, args ...git.CmdArg) func(*testing.T) {
        return func(t *testing.T) {
                _, _, err := git.NewCommandNoGlobals(append(append(git.AllowLFSFiltersArgs(), "checkout"), args...)...).RunStdString(&git.RunOpts{Dir: dstPath})
                assert.NoError(t, err)
        }
 }
 
-func doGitMerge(dstPath string, args ...string) func(*testing.T) {
+func doGitMerge(dstPath string, args ...git.CmdArg) func(*testing.T) {
        return func(t *testing.T) {
-               _, _, err := git.NewCommand(git.DefaultContext, append([]string{"merge"}, args...)...).RunStdString(&git.RunOpts{Dir: dstPath})
+               _, _, err := git.NewCommand(git.DefaultContext, append([]git.CmdArg{"merge"}, args...)...).RunStdString(&git.RunOpts{Dir: dstPath})
                assert.NoError(t, err)
        }
 }
 
-func doGitPull(dstPath string, args ...string) func(*testing.T) {
+func doGitPull(dstPath string, args ...git.CmdArg) func(*testing.T) {
        return func(t *testing.T) {
                _, _, err := git.NewCommandNoGlobals(append(append(git.AllowLFSFiltersArgs(), "pull"), args...)...).RunStdString(&git.RunOpts{Dir: dstPath})
                assert.NoError(t, err)
index bf5e809dab5980065d0ee520486f0ef4663e287f..6f656ef2ce6dda3f68280b5e035aa52680ae1d6a 100644 (file)
@@ -151,7 +151,7 @@ func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS strin
                prefix := "lfs-data-file-"
                err := git.NewCommand(git.DefaultContext, "lfs").AddArguments("install").Run(&git.RunOpts{Dir: dstPath})
                assert.NoError(t, err)
-               _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("track", prefix+"*").RunStdString(&git.RunOpts{Dir: dstPath})
+               _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("track").AddDynamicArguments(prefix + "*").RunStdString(&git.RunOpts{Dir: dstPath})
                assert.NoError(t, err)
                err = git.AddChanges(dstPath, false, ".gitattributes")
                assert.NoError(t, err)
@@ -279,11 +279,11 @@ func lockTest(t *testing.T, repoPath string) {
 func lockFileTest(t *testing.T, filename, repoPath string) {
        _, _, err := git.NewCommand(git.DefaultContext, "lfs").AddArguments("locks").RunStdString(&git.RunOpts{Dir: repoPath})
        assert.NoError(t, err)
-       _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("lock"filename).RunStdString(&git.RunOpts{Dir: repoPath})
+       _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("lock").AddDynamicArguments(filename).RunStdString(&git.RunOpts{Dir: repoPath})
        assert.NoError(t, err)
        _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("locks").RunStdString(&git.RunOpts{Dir: repoPath})
        assert.NoError(t, err)
-       _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("unlock"filename).RunStdString(&git.RunOpts{Dir: repoPath})
+       _, _, err = git.NewCommand(git.DefaultContext, "lfs").AddArguments("unlock").AddDynamicArguments(filename).RunStdString(&git.RunOpts{Dir: repoPath})
        assert.NoError(t, err)
 }
 
@@ -509,7 +509,7 @@ func doCreatePRAndSetManuallyMerged(ctx, baseCtx APITestContext, dstPath, baseBr
                }))
 
                t.Run("CreateHeadBranch", doGitCreateBranch(dstPath, headBranch))
-               t.Run("PushToHeadBranch", doGitPushTestRepository(dstPath, "origin", headBranch))
+               t.Run("PushToHeadBranch", doGitPushTestRepository(dstPath, "origin", git.CmdArgCheck(headBranch)))
                t.Run("CreateEmptyPullRequest", func(t *testing.T) {
                        pr, err = doAPICreatePullRequest(ctx, baseCtx.Username, baseCtx.Reponame, baseBranch, headBranch)(t)
                        assert.NoError(t, err)
@@ -736,7 +736,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, baseBranch, headB
                })
 
                t.Run("Push", func(t *testing.T) {
-                       err := git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o", "topic="+headBranch).Run(&git.RunOpts{Dir: dstPath})
+                       err := git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic=" + headBranch).Run(&git.RunOpts{Dir: dstPath})
                        if !assert.NoError(t, err) {
                                return
                        }
@@ -757,7 +757,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, baseBranch, headB
                        assert.Contains(t, "Testing commit 1", prMsg.Body)
                        assert.Equal(t, commit, prMsg.Head.Sha)
 
-                       _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master/test/"+headBranch).RunStdString(&git.RunOpts{Dir: dstPath})
+                       _, _, err = git.NewCommand(git.DefaultContext, "push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/" + headBranch).RunStdString(&git.RunOpts{Dir: dstPath})
                        if !assert.NoError(t, err) {
                                return
                        }
@@ -810,7 +810,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, baseBranch, headB
                })
 
                t.Run("Push2", func(t *testing.T) {
-                       err := git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o", "topic="+headBranch).Run(&git.RunOpts{Dir: dstPath})
+                       err := git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master", "-o").AddDynamicArguments("topic=" + headBranch).Run(&git.RunOpts{Dir: dstPath})
                        if !assert.NoError(t, err) {
                                return
                        }
@@ -822,7 +822,7 @@ func doCreateAgitFlowPull(dstPath string, ctx *APITestContext, baseBranch, headB
                        assert.Equal(t, false, prMsg.HasMerged)
                        assert.Equal(t, commit, prMsg.Head.Sha)
 
-                       _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "HEAD:refs/for/master/test/"+headBranch).RunStdString(&git.RunOpts{Dir: dstPath})
+                       _, _, err = git.NewCommand(git.DefaultContext, "push", "origin").AddDynamicArguments("HEAD:refs/for/master/test/" + headBranch).RunStdString(&git.RunOpts{Dir: dstPath})
                        if !assert.NoError(t, err) {
                                return
                        }
index 335dae4b38adf4b94d18101ee012db770e1f03e2..9bd430084dcc8fd35e7fbedc171a2ca2109a7d92 100644 (file)
@@ -287,7 +287,7 @@ func TestCantMergeUnrelated(t *testing.T) {
                assert.NoError(t, err)
                sha := strings.TrimSpace(stdout.String())
 
-               _, _, err = git.NewCommand(git.DefaultContext, "update-index", "--add", "--replace", "--cacheinfo", "100644", sha, "somewher-over-the-rainbow").RunStdString(&git.RunOpts{Dir: path})
+               _, _, err = git.NewCommand(git.DefaultContext, "update-index", "--add", "--replace", "--cacheinfo", "100644", git.CmdArgCheck(sha), "somewher-over-the-rainbow").RunStdString(&git.RunOpts{Dir: path})
                assert.NoError(t, err)
 
                treeSha, _, err := git.NewCommand(git.DefaultContext, "write-tree").RunStdString(&git.RunOpts{Dir: path})
@@ -310,7 +310,7 @@ func TestCantMergeUnrelated(t *testing.T) {
                _, _ = messageBytes.WriteString("\n")
 
                stdout.Reset()
-               err = git.NewCommand(git.DefaultContext, "commit-tree"treeSha).
+               err = git.NewCommand(git.DefaultContext, "commit-tree").AddDynamicArguments(treeSha).
                        Run(&git.RunOpts{
                                Env:    env,
                                Dir:    path,
@@ -320,7 +320,7 @@ func TestCantMergeUnrelated(t *testing.T) {
                assert.NoError(t, err)
                commitSha := strings.TrimSpace(stdout.String())
 
-               _, _, err = git.NewCommand(git.DefaultContext, "branch", "unrelated"commitSha).RunStdString(&git.RunOpts{Dir: path})
+               _, _, err = git.NewCommand(git.DefaultContext, "branch", "unrelated").AddDynamicArguments(commitSha).RunStdString(&git.RunOpts{Dir: path})
                assert.NoError(t, err)
 
                testEditFileToNewBranch(t, session, "user1", "repo1", "master", "conflict", "README.md", "Hello, World (Edited Once)\n")