diff --git a/command.go b/command.go index c279df1a..bdc366d4 100644 --- a/command.go +++ b/command.go @@ -22,6 +22,12 @@ type Command struct { envs []string } +// CommandOptions contains options for running a command. +type CommandOptions struct { + Args []string + Envs []string +} + // String returns the string representation of the command. func (c *Command) String() string { if len(c.args) == 0 { @@ -50,6 +56,15 @@ func (c *Command) AddEnvs(envs ...string) *Command { return c } +// AddOptions adds options to the command. +func (c *Command) AddOptions(opts ...CommandOptions) *Command { + for _, opt := range opts { + c.AddArgs(opt.Args...) + c.AddEnvs(opt.Envs...) + } + return c +} + // AddCommitter appends given committer to the command. func (c *Command) AddCommitter(committer *Signature) *Command { c.AddEnvs("GIT_COMMITTER_NAME="+committer.Name, "GIT_COMMITTER_EMAIL="+committer.Email) @@ -87,36 +102,52 @@ func (w *limitDualWriter) Write(p []byte) (int, error) { return w.w.Write(p) } -// RunInDirPipelineWithTimeout executes the command in given directory and -// timeout duration. It pipes stdout and stderr to supplied io.Writer. -// DefaultTimeout will be used if the timeout duration is less than +// RunInDirOptions contains options for running a command in a directory. +type RunInDirOptions struct { + // Stdin is the input to the command. + Stdin io.Reader + // Stdout is the outputs from the command. + Stdout io.Writer + // Stderr is the error output from the command. + Stderr io.Writer + // Timeout is the duration to wait before timing out. + Timeout time.Duration +} + +// RunInDirWithOptions executes the command in given directory and options. It +// pipes stdin from supplied io.Reader, and pipes stdout and stderr to supplied +// io.Writer. DefaultTimeout will be used if the timeout duration is less than // time.Nanosecond (i.e. less than or equal to 0). It returns an ErrExecTimeout // if the execution was timed out. -func (c *Command) RunInDirPipelineWithTimeout(timeout time.Duration, stdout, stderr io.Writer, dir string) (err error) { - if timeout < time.Nanosecond { - timeout = DefaultTimeout +func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err error) { + var opt RunInDirOptions + if len(opts) > 0 { + opt = opts[0] + } + if opt.Timeout < time.Nanosecond { + opt.Timeout = DefaultTimeout } buf := new(bytes.Buffer) - w := stdout + w := opt.Stdout if logOutput != nil { buf.Grow(512) w = &limitDualWriter{ W: buf, N: int64(buf.Cap()), - w: stdout, + w: opt.Stdout, } } defer func() { if len(dir) == 0 { - log("[timeout: %v] %s\n%s", timeout, c, buf.Bytes()) + log("[timeout: %v] %s\n%s", opt.Timeout, c, buf.Bytes()) } else { - log("[timeout: %v] %s: %s\n%s", timeout, dir, c, buf.Bytes()) + log("[timeout: %v] %s: %s\n%s", opt.Timeout, dir, c, buf.Bytes()) } }() - ctx, cancel := context.WithTimeout(context.Background(), timeout) + ctx, cancel := context.WithTimeout(context.Background(), opt.Timeout) defer func() { cancel() if err == context.DeadlineExceeded { @@ -129,8 +160,9 @@ func (c *Command) RunInDirPipelineWithTimeout(timeout time.Duration, stdout, std cmd.Env = append(os.Environ(), c.envs...) } cmd.Dir = dir + cmd.Stdin = opt.Stdin cmd.Stdout = w - cmd.Stderr = stderr + cmd.Stderr = opt.Stderr if err = cmd.Start(); err != nil { return err } @@ -153,6 +185,21 @@ func (c *Command) RunInDirPipelineWithTimeout(timeout time.Duration, stdout, std case err = <-result: return err } + +} + +// RunInDirPipelineWithTimeout executes the command in given directory and +// timeout duration. It pipes stdout and stderr to supplied io.Writer. +// DefaultTimeout will be used if the timeout duration is less than +// time.Nanosecond (i.e. less than or equal to 0). It returns an ErrExecTimeout +// if the execution was timed out. +func (c *Command) RunInDirPipelineWithTimeout(timeout time.Duration, stdout, stderr io.Writer, dir string) (err error) { + return c.RunInDirWithOptions(dir, RunInDirOptions{ + Stdin: nil, + Stdout: stdout, + Stderr: stderr, + Timeout: timeout, + }) } // RunInDirPipeline executes the command in given directory and default timeout diff --git a/go.mod b/go.mod index ed031acc..6fc895ca 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/gogs/git-module -go 1.12 +go 1.13 require ( github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 diff --git a/repo.go b/repo.go index 2cb3b385..d54cebac 100644 --- a/repo.go +++ b/repo.go @@ -60,6 +60,8 @@ type InitOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Init initializes a new Git repository. @@ -74,7 +76,7 @@ func Init(path string, opts ...InitOptions) error { return err } - cmd := NewCommand("init") + cmd := NewCommand("init").AddOptions(opt.CommandOptions) if opt.Bare { cmd.AddArgs("--bare") } @@ -116,6 +118,8 @@ type CloneOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Clone clones the repository from remote URL to the destination. @@ -130,7 +134,7 @@ func Clone(url, dst string, opts ...CloneOptions) error { return err } - cmd := NewCommand("clone") + cmd := NewCommand("clone").AddOptions(opt.CommandOptions) if opt.Mirror { cmd.AddArgs("--mirror") } @@ -160,6 +164,8 @@ type FetchOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Fetch fetches updates for the repository. @@ -169,7 +175,7 @@ func (r *Repository) Fetch(opts ...FetchOptions) error { opt = opts[0] } - cmd := NewCommand("fetch") + cmd := NewCommand("fetch").AddOptions(opt.CommandOptions) if opt.Prune { cmd.AddArgs("--prune") } @@ -193,6 +199,8 @@ type PullOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Pull pulls updates for the repository. @@ -202,7 +210,7 @@ func (r *Repository) Pull(opts ...PullOptions) error { opt = opts[0] } - cmd := NewCommand("pull") + cmd := NewCommand("pull").AddOptions(opt.CommandOptions) if opt.Rebase { cmd.AddArgs("--rebase") } @@ -224,11 +232,11 @@ func (r *Repository) Pull(opts ...PullOptions) error { // // Docs: https://git-scm.com/docs/git-push type PushOptions struct { - // The environment variables set for the push. - Envs []string // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Push pushes local changes to given remote and branch for the repository in @@ -239,9 +247,8 @@ func Push(repoPath, remote, branch string, opts ...PushOptions) error { opt = opts[0] } - _, err := NewCommand("push", remote, branch). - AddEnvs(opt.Envs...). - RunInDirWithTimeout(opt.Timeout, repoPath) + cmd := NewCommand("push").AddOptions(opt.CommandOptions).AddArgs(remote, branch) + _, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath) return err } @@ -264,6 +271,8 @@ type CheckoutOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Checkout checks out to given branch for the repository in given path. @@ -273,7 +282,7 @@ func Checkout(repoPath, branch string, opts ...CheckoutOptions) error { opt = opts[0] } - cmd := NewCommand("checkout") + cmd := NewCommand("checkout").AddOptions(opt.CommandOptions) if opt.BaseBranch != "" { cmd.AddArgs("-b") } @@ -305,6 +314,8 @@ type ResetOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Reset resets working tree to given revision for the repository in given path. @@ -319,7 +330,7 @@ func Reset(repoPath, rev string, opts ...ResetOptions) error { cmd.AddArgs("--hard") } - _, err := cmd.AddArgs(rev).RunInDir(repoPath) + _, err := cmd.AddOptions(opt.CommandOptions).AddArgs(rev).RunInDir(repoPath) return err } @@ -341,6 +352,8 @@ type MoveOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Move moves a file, a directory, or a symlink file or directory from source to @@ -351,7 +364,7 @@ func Move(repoPath, src, dst string, opts ...MoveOptions) error { opt = opts[0] } - _, err := NewCommand("mv", src, dst).RunInDirWithTimeout(opt.Timeout, repoPath) + _, err := NewCommand("mv").AddOptions(opt.CommandOptions).AddArgs(src, dst).RunInDirWithTimeout(opt.Timeout, repoPath) return err } @@ -377,6 +390,8 @@ type AddOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Add adds local changes to index for the repository in given path. @@ -386,7 +401,7 @@ func Add(repoPath string, opts ...AddOptions) error { opt = opts[0] } - cmd := NewCommand("add") + cmd := NewCommand("add").AddOptions(opt.CommandOptions) if opt.All { cmd.AddArgs("--all") } @@ -417,6 +432,8 @@ type CommitOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // CreateCommit commits local changes with given author, committer and message @@ -433,8 +450,9 @@ func CreateCommit(repoPath string, committer *Signature, message string, opts .. if opt.Author == nil { opt.Author = committer } - cmd.AddArgs(fmt.Sprintf("--author='%s <%s>'", opt.Author.Name, opt.Author.Email)) - cmd.AddArgs("-m", message) + cmd = cmd.AddArgs(fmt.Sprintf("--author='%s <%s>'", opt.Author.Name, opt.Author.Email)). + AddArgs("-m", message). + AddOptions(opt.CommandOptions) _, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath) // No stderr but exit status 1 means nothing to commit. @@ -469,6 +487,8 @@ type ShowNameStatusOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // ShowNameStatus returns name status of given revision of the repository in @@ -503,7 +523,10 @@ func ShowNameStatus(repoPath, rev string, opts ...ShowNameStatusOptions) (*NameS }() stderr := new(bytes.Buffer) - err := NewCommand("show", "--name-status", "--pretty=format:''", rev).RunInDirPipelineWithTimeout(opt.Timeout, w, stderr, repoPath) + cmd := NewCommand("show", "--name-status", "--pretty=format:''"). + AddOptions(opt.CommandOptions). + AddArgs(rev) + err := cmd.RunInDirPipelineWithTimeout(opt.Timeout, w, stderr, repoPath) _ = w.Close() // Close writer to exit parsing goroutine if err != nil { return nil, concatenateError(err, stderr.String()) @@ -530,6 +553,8 @@ type RevParseOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RevParse returns full length (40) commit ID by given revision in the @@ -540,7 +565,10 @@ func (r *Repository) RevParse(rev string, opts ...RevParseOptions) (string, erro opt = opts[0] } - commitID, err := NewCommand("rev-parse", rev).RunInDirWithTimeout(opt.Timeout, r.path) + commitID, err := NewCommand("rev-parse"). + AddOptions(opt.CommandOptions). + AddArgs(rev). + RunInDirWithTimeout(opt.Timeout, r.path) if err != nil { if strings.Contains(err.Error(), "exit status 128") { return "", ErrRevisionNotExist @@ -569,6 +597,8 @@ type CountObjectsOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // CountObjects returns disk usage report of the repository in given path. @@ -578,7 +608,9 @@ func CountObjects(repoPath string, opts ...CountObjectsOptions) (*CountObject, e opt = opts[0] } - stdout, err := NewCommand("count-objects", "-v").RunInDirWithTimeout(opt.Timeout, repoPath) + stdout, err := NewCommand("count-objects", "-v"). + AddOptions(opt.CommandOptions). + RunInDirWithTimeout(opt.Timeout, repoPath) if err != nil { return nil, err } @@ -627,11 +659,11 @@ func (r *Repository) CountObjects(opts ...CountObjectsOptions) (*CountObject, er // // Docs: https://git-scm.com/docs/git-fsck type FsckOptions struct { - // The additional arguments to be applied. - Args []string // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Fsck verifies the connectivity and validity of the objects in the database @@ -642,10 +674,7 @@ func Fsck(repoPath string, opts ...FsckOptions) error { opt = opts[0] } - cmd := NewCommand("fsck") - if len(opt.Args) > 0 { - cmd.AddArgs(opt.Args...) - } + cmd := NewCommand("fsck").AddOptions(opt.CommandOptions) _, err := cmd.RunInDirWithTimeout(opt.Timeout, repoPath) return err } diff --git a/repo_blame.go b/repo_blame.go index 5be6eb29..d9b46b90 100644 --- a/repo_blame.go +++ b/repo_blame.go @@ -15,6 +15,8 @@ type BlameOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // BlameFile returns blame results of the file with the given revision of the @@ -25,7 +27,10 @@ func (r *Repository) BlameFile(rev, file string, opts ...BlameOptions) (*Blame, opt = opts[0] } - stdout, err := NewCommand("blame", "-l", "-s", rev, "--", file).RunInDirWithTimeout(opt.Timeout, r.path) + stdout, err := NewCommand("blame"). + AddOptions(opt.CommandOptions). + AddArgs("-l", "-s", rev, "--", file). + RunInDirWithTimeout(opt.Timeout, r.path) if err != nil { return nil, err } diff --git a/repo_commit.go b/repo_commit.go index 89fe27ba..f7ce3bc2 100644 --- a/repo_commit.go +++ b/repo_commit.go @@ -73,6 +73,8 @@ type CatFileCommitOptions struct { // The timeout duration before giving up for each shell command execution. // The default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // CatFileCommit returns the commit corresponding to the given revision of the @@ -95,7 +97,10 @@ func (r *Repository) CatFileCommit(rev string, opts ...CatFileCommitOptions) (*C return nil, err } - stdout, err := NewCommand("cat-file", "commit", commitID).RunInDirWithTimeout(opt.Timeout, r.path) + stdout, err := NewCommand("cat-file"). + AddOptions(opt.CommandOptions). + AddArgs("commit", commitID). + RunInDirWithTimeout(opt.Timeout, r.path) if err != nil { return nil, err } @@ -118,6 +123,8 @@ type CatFileTypeOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // CatFileType returns the object type of given revision of the repository. @@ -127,7 +134,10 @@ func (r *Repository) CatFileType(rev string, opts ...CatFileTypeOptions) (Object opt = opts[0] } - typ, err := NewCommand("cat-file", "-t", rev).RunInDirWithTimeout(opt.Timeout, r.path) + typ, err := NewCommand("cat-file"). + AddOptions(opt.CommandOptions). + AddArgs("-t", rev). + RunInDirWithTimeout(opt.Timeout, r.path) if err != nil { return "", err } @@ -166,6 +176,8 @@ type LogOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } func escapePath(path string) string { @@ -205,7 +217,9 @@ func (r *Repository) Log(rev string, opts ...LogOptions) ([]*Commit, error) { opt = opts[0] } - cmd := NewCommand("log", "--pretty="+LogFormatHashOnly, rev) + cmd := NewCommand("log"). + AddOptions(opt.CommandOptions). + AddArgs("--pretty="+LogFormatHashOnly, rev) if opt.MaxCount > 0 { cmd.AddArgs("--max-count=" + strconv.Itoa(opt.MaxCount)) } @@ -242,6 +256,8 @@ type CommitByRevisionOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // CommitByRevision returns a commit by given revision. @@ -252,9 +268,10 @@ func (r *Repository) CommitByRevision(rev string, opts ...CommitByRevisionOption } commits, err := r.Log(rev, LogOptions{ - MaxCount: 1, - Path: opt.Path, - Timeout: opt.Timeout, + MaxCount: 1, + Path: opt.Path, + Timeout: opt.Timeout, + CommandOptions: opt.CommandOptions, }) if err != nil { if strings.Contains(err.Error(), "bad revision") { @@ -277,6 +294,8 @@ type CommitsByPageOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // CommitsByPage returns a paginated list of commits in the state of given @@ -288,10 +307,11 @@ func (r *Repository) CommitsByPage(rev string, page, size int, opts ...CommitsBy } return r.Log(rev, LogOptions{ - MaxCount: size, - Skip: (page - 1) * size, - Path: opt.Path, - Timeout: opt.Timeout, + MaxCount: size, + Skip: (page - 1) * size, + Path: opt.Path, + Timeout: opt.Timeout, + CommandOptions: opt.CommandOptions, }) } @@ -306,6 +326,8 @@ type SearchCommitsOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // SearchCommits searches commit message with given pattern in the state of @@ -322,6 +344,7 @@ func (r *Repository) SearchCommits(rev, pattern string, opts ...SearchCommitsOpt RegexpIgnoreCase: true, Path: opt.Path, Timeout: opt.Timeout, + CommandOptions: opt.CommandOptions, }) } @@ -335,6 +358,8 @@ type CommitsSinceOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // CommitsSince returns a list of commits since given time. The returned list is @@ -346,9 +371,10 @@ func (r *Repository) CommitsSince(rev string, since time.Time, opts ...CommitsSi } return r.Log(rev, LogOptions{ - Since: since, - Path: opt.Path, - Timeout: opt.Timeout, + Since: since, + Path: opt.Path, + Timeout: opt.Timeout, + CommandOptions: opt.CommandOptions, }) } @@ -363,6 +389,8 @@ type DiffNameOnlyOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // DiffNameOnly returns a list of changed files between base and head revisions @@ -373,7 +401,9 @@ func DiffNameOnly(repoPath, base, head string, opts ...DiffNameOnlyOptions) ([]s opt = opts[0] } - cmd := NewCommand("diff", "--name-only") + cmd := NewCommand("diff"). + AddOptions(opt.CommandOptions). + AddArgs("--name-only") if opt.NeedsMergeBase { cmd.AddArgs(base + "..." + head) } else { @@ -421,6 +451,8 @@ type RevListCountOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RevListCount returns number of total commits up to given refspec of the @@ -435,7 +467,9 @@ func (r *Repository) RevListCount(refspecs []string, opts ...RevListCountOptions return 0, errors.New("must have at least one refspec") } - cmd := NewCommand("rev-list", "--count") + cmd := NewCommand("rev-list"). + AddOptions(opt.CommandOptions). + AddArgs("--count") cmd.AddArgs(refspecs...) cmd.AddArgs("--") if opt.Path != "" { @@ -459,6 +493,8 @@ type RevListOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RevList returns a list of commits based on given refspecs in reverse @@ -473,7 +509,7 @@ func (r *Repository) RevList(refspecs []string, opts ...RevListOptions) ([]*Comm return nil, errors.New("must have at least one refspec") } - cmd := NewCommand("rev-list") + cmd := NewCommand("rev-list").AddOptions(opt.CommandOptions) cmd.AddArgs(refspecs...) cmd.AddArgs("--") if opt.Path != "" { @@ -495,6 +531,8 @@ type LatestCommitTimeOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // LatestCommitTime returns the time of latest commit of the repository. @@ -504,11 +542,13 @@ func (r *Repository) LatestCommitTime(opts ...LatestCommitTimeOptions) (time.Tim opt = opts[0] } - cmd := NewCommand("for-each-ref", - "--count=1", - "--sort=-committerdate", - "--format=%(committerdate:iso8601)", - ) + cmd := NewCommand("for-each-ref"). + AddOptions(opt.CommandOptions). + AddArgs( + "--count=1", + "--sort=-committerdate", + "--format=%(committerdate:iso8601)", + ) if opt.Branch != "" { cmd.AddArgs(RefsHeads + opt.Branch) } diff --git a/repo_diff.go b/repo_diff.go index 206ddeb0..03d4f2bc 100644 --- a/repo_diff.go +++ b/repo_diff.go @@ -21,6 +21,8 @@ type DiffOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Diff returns a parsed diff object between given commits of the repository. @@ -39,13 +41,19 @@ func (r *Repository) Diff(rev string, maxFiles, maxFileLines, maxLineChars int, if opt.Base == "" { // First commit of repository if commit.ParentsCount() == 0 { - cmd.AddArgs("show", "--full-index", rev) + cmd = cmd.AddArgs("show"). + AddOptions(opt.CommandOptions). + AddArgs("--full-index", rev) } else { c, _ := commit.Parent(0) - cmd.AddArgs("diff", "--full-index", "-M", c.ID.String(), rev) + cmd = cmd.AddArgs("diff"). + AddOptions(opt.CommandOptions). + AddArgs("--full-index", "-M", c.ID.String(), rev) } } else { - cmd.AddArgs("diff", "--full-index", "-M", opt.Base, rev) + cmd = cmd.AddArgs("diff"). + AddOptions(opt.CommandOptions). + AddArgs("--full-index", "-M", opt.Base, rev) } stdout, w := io.Pipe() @@ -78,6 +86,8 @@ type RawDiffOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RawDiff dumps diff of repository in given revision directly to given @@ -97,17 +107,25 @@ func (r *Repository) RawDiff(rev string, diffType RawDiffFormat, w io.Writer, op switch diffType { case RawDiffNormal: if commit.ParentsCount() == 0 { - cmd.AddArgs("show", "--full-index", rev) + cmd = cmd.AddArgs("show"). + AddOptions(opt.CommandOptions). + AddArgs("--full-index", rev) } else { c, _ := commit.Parent(0) - cmd.AddArgs("diff", "--full-index", "-M", c.ID.String(), rev) + cmd = cmd.AddArgs("diff"). + AddOptions(opt.CommandOptions). + AddArgs("--full-index", "-M", c.ID.String(), rev) } case RawDiffPatch: if commit.ParentsCount() == 0 { - cmd.AddArgs("format-patch", "--full-index", "--no-signature", "--stdout", "--root", rev) + cmd = cmd.AddArgs("format-patch"). + AddOptions(opt.CommandOptions). + AddArgs("--full-index", "--no-signature", "--stdout", "--root", rev) } else { c, _ := commit.Parent(0) - cmd.AddArgs("format-patch", "--full-index", "--no-signature", "--stdout", rev+"..."+c.ID.String()) + cmd = cmd.AddArgs("format-patch"). + AddOptions(opt.CommandOptions). + AddArgs("--full-index", "--no-signature", "--stdout", rev+"..."+c.ID.String()) } default: return fmt.Errorf("invalid diffType: %s", diffType) @@ -125,6 +143,8 @@ type DiffBinaryOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // DiffBinary returns binary patch between base and head revisions that could be @@ -135,5 +155,8 @@ func (r *Repository) DiffBinary(base, head string, opts ...DiffBinaryOptions) ([ opt = opts[0] } - return NewCommand("diff", "--full-index", "--binary", base, head).RunInDirWithTimeout(opt.Timeout, r.path) + return NewCommand("diff"). + AddOptions(opt.CommandOptions). + AddArgs("--full-index", "--binary", base, head). + RunInDirWithTimeout(opt.Timeout, r.path) } diff --git a/repo_pull.go b/repo_pull.go index cd416a9a..6f0c7bd2 100644 --- a/repo_pull.go +++ b/repo_pull.go @@ -16,6 +16,8 @@ type MergeBaseOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // MergeBase returns merge base between base and head revisions of the @@ -26,7 +28,10 @@ func MergeBase(repoPath, base, head string, opts ...MergeBaseOptions) (string, e opt = opts[0] } - stdout, err := NewCommand("merge-base", base, head).RunInDirWithTimeout(opt.Timeout, repoPath) + stdout, err := NewCommand("merge-base"). + AddOptions(opt.CommandOptions). + AddArgs(base, head). + RunInDirWithTimeout(opt.Timeout, repoPath) if err != nil { if strings.Contains(err.Error(), "exit status 1") { return "", ErrNoMergeBase diff --git a/repo_reference.go b/repo_reference.go index 01affca9..a1e56ec5 100644 --- a/repo_reference.go +++ b/repo_reference.go @@ -178,6 +178,8 @@ type ShowRefOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // ShowRef returns a list of references in the repository. @@ -187,7 +189,7 @@ func (r *Repository) ShowRef(opts ...ShowRefOptions) ([]*Reference, error) { opt = opts[0] } - cmd := NewCommand("show-ref") + cmd := NewCommand("show-ref").AddOptions(opt.CommandOptions) if opt.Heads { cmd.AddArgs("--heads") } diff --git a/repo_remote.go b/repo_remote.go index e0d8c496..8a97afe0 100644 --- a/repo_remote.go +++ b/repo_remote.go @@ -26,6 +26,8 @@ type LsRemoteOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // LsRemote returns a list references in the remote repository. @@ -35,7 +37,7 @@ func LsRemote(url string, opts ...LsRemoteOptions) ([]*Reference, error) { opt = opts[0] } - cmd := NewCommand("ls-remote", "--quiet") + cmd := NewCommand("ls-remote", "--quiet").AddOptions(opt.CommandOptions) if opt.Heads { cmd.AddArgs("--heads") } @@ -93,6 +95,8 @@ type RemoteAddOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Deprecated: Use RemoteAddOptions instead. @@ -105,7 +109,7 @@ func RemoteAdd(repoPath, name, url string, opts ...RemoteAddOptions) error { opt = opts[0] } - cmd := NewCommand("remote", "add") + cmd := NewCommand("remote", "add").AddOptions(opt.CommandOptions) if opt.Fetch { cmd.AddArgs("-f") } @@ -140,6 +144,8 @@ type RemoteRemoveOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Deprecated: Use RemoteRemoveOptions instead. @@ -152,7 +158,10 @@ func RemoteRemove(repoPath, name string, opts ...RemoteRemoveOptions) error { opt = opts[0] } - _, err := NewCommand("remote", "remove", name).RunInDirWithTimeout(opt.Timeout, repoPath) + _, err := NewCommand("remote", "remove"). + AddOptions(opt.CommandOptions). + AddArgs(name). + RunInDirWithTimeout(opt.Timeout, repoPath) if err != nil { // the error status may differ from git clients if strings.Contains(err.Error(), "error: No such remote") || @@ -186,6 +195,8 @@ type RemotesOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Remotes lists remotes of the repository in given path. @@ -195,7 +206,9 @@ func Remotes(repoPath string, opts ...RemotesOptions) ([]string, error) { opt = opts[0] } - stdout, err := NewCommand("remote").RunInDirWithTimeout(opt.Timeout, repoPath) + stdout, err := NewCommand("remote"). + AddOptions(opt.CommandOptions). + RunInDirWithTimeout(opt.Timeout, repoPath) if err != nil { return nil, err } @@ -221,6 +234,8 @@ type RemoteGetURLOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RemoteGetURL retrieves URL(s) of a remote of the repository in given path. @@ -230,7 +245,7 @@ func RemoteGetURL(repoPath, name string, opts ...RemoteGetURLOptions) ([]string, opt = opts[0] } - cmd := NewCommand("remote", "get-url") + cmd := NewCommand("remote", "get-url").AddOptions(opt.CommandOptions) if opt.Push { cmd.AddArgs("--push") } @@ -262,6 +277,8 @@ type RemoteSetURLOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RemoteSetURL sets first URL of the remote with given name of the repository @@ -272,7 +289,7 @@ func RemoteSetURL(repoPath, name, newurl string, opts ...RemoteSetURLOptions) er opt = opts[0] } - cmd := NewCommand("remote", "set-url") + cmd := NewCommand("remote", "set-url").AddOptions(opt.CommandOptions) if opt.Push { cmd.AddArgs("--push") } @@ -311,6 +328,8 @@ type RemoteSetURLAddOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RemoteSetURLAdd appends an URL to the remote with given name of the @@ -321,7 +340,9 @@ func RemoteSetURLAdd(repoPath, name, newurl string, opts ...RemoteSetURLAddOptio opt = opts[0] } - cmd := NewCommand("remote", "set-url", "--add") + cmd := NewCommand("remote", "set-url"). + AddOptions(opt.CommandOptions). + AddArgs("--add") if opt.Push { cmd.AddArgs("--push") } @@ -351,6 +372,8 @@ type RemoteSetURLDeleteOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RemoteSetURLDelete deletes the remote with given name of the repository in @@ -361,7 +384,9 @@ func RemoteSetURLDelete(repoPath, name, regex string, opts ...RemoteSetURLDelete opt = opts[0] } - cmd := NewCommand("remote", "set-url", "--delete") + cmd := NewCommand("remote", "set-url"). + AddOptions(opt.CommandOptions). + AddArgs("--delete") if opt.Push { cmd.AddArgs("--push") } diff --git a/repo_tag.go b/repo_tag.go index 4615f587..74d10fdc 100644 --- a/repo_tag.go +++ b/repo_tag.go @@ -105,6 +105,8 @@ type TagOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // Tag returns a Git tag by given name, e.g. "v1.0.0". @@ -116,9 +118,10 @@ func (r *Repository) Tag(name string, opts ...TagOptions) (*Tag, error) { refsepc := RefsTags + name refs, err := r.ShowRef(ShowRefOptions{ - Tags: true, - Patterns: []string{refsepc}, - Timeout: opt.Timeout, + Tags: true, + Patterns: []string{refsepc}, + Timeout: opt.Timeout, + CommandOptions: opt.CommandOptions, }) if err != nil { return nil, err @@ -150,6 +153,8 @@ type TagsOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // RepoTags returns a list of tags of the repository in given path. @@ -164,7 +169,7 @@ func RepoTags(repoPath string, opts ...TagsOptions) ([]string, error) { return nil, err } - cmd := NewCommand("tag", "--list") + cmd := NewCommand("tag", "--list").AddOptions(opt.CommandOptions) var sorted bool if opt.SortKey != "" { @@ -218,6 +223,8 @@ type CreateTagOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // CreateTag creates a new tag on given revision. @@ -227,7 +234,7 @@ func (r *Repository) CreateTag(name, rev string, opts ...CreateTagOptions) error opt = opts[0] } - cmd := NewCommand("tag") + cmd := NewCommand("tag").AddOptions(opt.CommandOptions) if opt.Annotated { cmd.AddArgs("-a", name) cmd.AddArgs("--message", opt.Message) diff --git a/repo_tree.go b/repo_tree.go index a445ef31..fe98bb39 100644 --- a/repo_tree.go +++ b/repo_tree.go @@ -92,6 +92,8 @@ type LsTreeOptions struct { // The timeout duration before giving up for each shell command execution. The // default timeout duration will be used when not supplied. Timeout time.Duration + // The additional options to be passed to the underlying git. + CommandOptions } // LsTree returns the tree object in the repository by given revision. @@ -111,7 +113,10 @@ func (r *Repository) LsTree(rev string, opts ...LsTreeOptions) (*Tree, error) { repo: r, } - stdout, err := NewCommand("ls-tree", rev).RunInDirWithTimeout(opt.Timeout, r.path) + stdout, err := NewCommand("ls-tree"). + AddOptions(opt.CommandOptions). + AddArgs(rev). + RunInDirWithTimeout(opt.Timeout, r.path) if err != nil { return nil, err }