diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2022-10-23 22:44:45 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-23 22:44:45 +0800 |
commit | dcd9fc7ee894700f702f3847d7d2a41d6a009b7e (patch) | |
tree | 76b1d6fdb2a760f3da57bbe566146d1c79ab5a87 /modules/git | |
parent | 4eeea7b30ee5d90ed4e9410ec5c7d0252ada3a3b (diff) | |
download | gitea-dcd9fc7ee894700f702f3847d7d2a41d6a009b7e.tar.gz gitea-dcd9fc7ee894700f702f3847d7d2a41d6a009b7e.zip |
Refactor git command arguments and make all arguments to be safe to be used (#21535)
Follow #21464
Make all git command arguments strictly safe. Most changes are one-to-one replacing, keep all existing logic.
Diffstat (limited to 'modules/git')
-rw-r--r-- | modules/git/command.go | 63 | ||||
-rw-r--r-- | modules/git/commit.go | 50 | ||||
-rw-r--r-- | modules/git/diff.go | 23 | ||||
-rw-r--r-- | modules/git/git.go | 18 | ||||
-rw-r--r-- | modules/git/log_name_status.go | 17 | ||||
-rw-r--r-- | modules/git/pipeline/revlist.go | 2 | ||||
-rw-r--r-- | modules/git/remote.go | 4 | ||||
-rw-r--r-- | modules/git/repo.go | 28 | ||||
-rw-r--r-- | modules/git/repo_archive.go | 15 | ||||
-rw-r--r-- | modules/git/repo_attribute.go | 26 | ||||
-rw-r--r-- | modules/git/repo_blame.go | 7 | ||||
-rw-r--r-- | modules/git/repo_branch.go | 14 | ||||
-rw-r--r-- | modules/git/repo_branch_nogogit.go | 14 | ||||
-rw-r--r-- | modules/git/repo_commit.go | 76 | ||||
-rw-r--r-- | modules/git/repo_commit_gogit.go | 2 | ||||
-rw-r--r-- | modules/git/repo_commit_nogogit.go | 8 | ||||
-rw-r--r-- | modules/git/repo_compare.go | 30 | ||||
-rw-r--r-- | modules/git/repo_index.go | 13 | ||||
-rw-r--r-- | modules/git/repo_stats.go | 4 | ||||
-rw-r--r-- | modules/git/repo_tag.go | 8 | ||||
-rw-r--r-- | modules/git/repo_tag_nogogit.go | 2 | ||||
-rw-r--r-- | modules/git/repo_tree.go | 6 | ||||
-rw-r--r-- | modules/git/repo_tree_gogit.go | 2 | ||||
-rw-r--r-- | modules/git/tree.go | 9 | ||||
-rw-r--r-- | modules/git/tree_nogogit.go | 8 |
25 files changed, 236 insertions, 213 deletions
diff --git a/modules/git/command.go b/modules/git/command.go index ed06dd9b08..abf40b0cd7 100644 --- a/modules/git/command.go +++ b/modules/git/command.go @@ -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 diff --git a/modules/git/commit.go b/modules/git/commit.go index 8fac9921b1..061adc1082 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -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, ""} diff --git a/modules/git/diff.go b/modules/git/diff.go index f75ebd4fd2..13ff6bd1e6 100644 --- a/modules/git/diff.go +++ b/modules/git/diff.go @@ -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, diff --git a/modules/git/git.go b/modules/git/git.go index 28899222e7..18d62838df 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -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}) } diff --git a/modules/git/log_name_status.go b/modules/git/log_name_status.go index 469932525f..dee4fc226e 100644 --- a/modules/git/log_name_status.go +++ b/modules/git/log_name_status.go @@ -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, diff --git a/modules/git/pipeline/revlist.go b/modules/git/pipeline/revlist.go index 02619cb583..5f62e85e7f 100644 --- a/modules/git/pipeline/revlist.go +++ b/modules/git/pipeline/revlist.go @@ -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, diff --git a/modules/git/remote.go b/modules/git/remote.go index cbb4ac6126..c416eea136 100644 --- a/modules/git/remote.go +++ b/modules/git/remote.go @@ -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}) diff --git a/modules/git/repo.go b/modules/git/repo.go index 3176e27695..575b686e29 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -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 } diff --git a/modules/git/repo_archive.go b/modules/git/repo_archive.go index 4a97989949..a0cbfba5d9 100644 --- a/modules/git/repo_archive.go +++ b/modules/git/repo_archive.go @@ -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, diff --git a/modules/git/repo_attribute.go b/modules/git/repo_attribute.go index 21ff93e498..60dc993dc2 100644 --- a/modules/git/repo_attribute.go +++ b/modules/git/repo_attribute.go @@ -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, diff --git a/modules/git/repo_blame.go b/modules/git/repo_blame.go index 6fe6d235ba..8a3707aa09 100644 --- a/modules/git/repo_blame.go +++ b/modules/git/repo_blame.go @@ -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 } diff --git a/modules/git/repo_branch.go b/modules/git/repo_branch.go index 17d243808e..a3fc7e0c42 100644 --- a/modules/git/repo_branch.go +++ b/modules/git/repo_branch.go @@ -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 } diff --git a/modules/git/repo_branch_nogogit.go b/modules/git/repo_branch_nogogit.go index 91112d0190..95c3718841 100644 --- a/modules/git/repo_branch_nogogit.go +++ b/modules/git/repo_branch_nogogit.go @@ -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, diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index ec72593b80..90259fd746 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -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(prettyLogFormat, id.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 } diff --git a/modules/git/repo_commit_gogit.go b/modules/git/repo_commit_gogit.go index 9333b0d7b7..14fec3f9c6 100644 --- a/modules/git/repo_commit_gogit.go +++ b/modules/git/repo_commit_gogit.go @@ -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") { diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go index efea307b37..13a7be778f 100644 --- a/modules/git/repo_commit_nogogit.go +++ b/modules/git/repo_commit_nogogit.go @@ -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 } diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go index 589a7eae00..aad78370ff 100644 --- a/modules/git/repo_compare.go +++ b/modules/git/repo_compare.go @@ -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, diff --git a/modules/git/repo_index.go b/modules/git/repo_index.go index 50d82c77d7..5542883288 100644 --- a/modules/git/repo_index.go +++ b/modules/git/repo_index.go @@ -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 } diff --git a/modules/git/repo_stats.go b/modules/git/repo_stats.go index 7eccf9a190..002e2525e2 100644 --- a/modules/git/repo_stats.go +++ b/modules/git/repo_stats.go @@ -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 { diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index 8444e8d035..fd0de7b3a1 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -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 { diff --git a/modules/git/repo_tag_nogogit.go b/modules/git/repo_tag_nogogit.go index 72c1c979dc..5d3aace52f 100644 --- a/modules/git/repo_tag_nogogit.go +++ b/modules/git/repo_tag_nogogit.go @@ -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 } diff --git a/modules/git/repo_tree.go b/modules/git/repo_tree.go index 2ea3f0187a..ba81bfc6db 100644 --- a/modules/git/repo_tree.go +++ b/modules/git/repo_tree.go @@ -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 { diff --git a/modules/git/repo_tree_gogit.go b/modules/git/repo_tree_gogit.go index eef09cddd6..e720164936 100644 --- a/modules/git/repo_tree_gogit.go +++ b/modules/git/repo_tree_gogit.go @@ -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 } diff --git a/modules/git/tree.go b/modules/git/tree.go index a83336f3db..f5944dd29c 100644 --- a/modules/git/tree.go +++ b/modules/git/tree.go @@ -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 diff --git a/modules/git/tree_nogogit.go b/modules/git/tree_nogogit.go index d61d19e4c2..5cbb5ffc94 100644 --- a/modules/git/tree_nogogit.go +++ b/modules/git/tree_nogogit.go @@ -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 |