mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Change git.cmd to RunWithContext (#18693)
Change all `cmd...Pipeline` commands to `cmd.RunWithContext`. #18553 Co-authored-by: Martin Scholz <martin.scholz@versasec.com>
This commit is contained in:
		@@ -34,7 +34,11 @@ func EnsureValidGitRepository(ctx context.Context, repoPath string) error {
 | 
			
		||||
	stderr := strings.Builder{}
 | 
			
		||||
	err := NewCommand(ctx, "rev-parse").
 | 
			
		||||
		SetDescription(fmt.Sprintf("%s rev-parse [repo_path: %s]", GitExecutable, repoPath)).
 | 
			
		||||
		RunInDirFullPipeline(repoPath, nil, &stderr, nil)
 | 
			
		||||
		RunWithContext(&RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repoPath,
 | 
			
		||||
			Stderr:  &stderr,
 | 
			
		||||
		})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ConcatenateError(err, (&stderr).String())
 | 
			
		||||
	}
 | 
			
		||||
@@ -61,7 +65,13 @@ func CatFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError,
 | 
			
		||||
		stderr := strings.Builder{}
 | 
			
		||||
		err := NewCommand(ctx, "cat-file", "--batch-check").
 | 
			
		||||
			SetDescription(fmt.Sprintf("%s cat-file --batch-check [repo_path: %s] (%s:%d)", GitExecutable, repoPath, filename, line)).
 | 
			
		||||
			RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
 | 
			
		||||
			RunWithContext(&RunContext{
 | 
			
		||||
				Timeout: -1,
 | 
			
		||||
				Dir:     repoPath,
 | 
			
		||||
				Stdin:   batchStdinReader,
 | 
			
		||||
				Stdout:  batchStdoutWriter,
 | 
			
		||||
				Stderr:  &stderr,
 | 
			
		||||
			})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
			
		||||
			_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
			
		||||
@@ -100,7 +110,13 @@ func CatFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi
 | 
			
		||||
		stderr := strings.Builder{}
 | 
			
		||||
		err := NewCommand(ctx, "cat-file", "--batch").
 | 
			
		||||
			SetDescription(fmt.Sprintf("%s cat-file --batch [repo_path: %s] (%s:%d)", GitExecutable, repoPath, filename, line)).
 | 
			
		||||
			RunInDirFullPipeline(repoPath, batchStdoutWriter, &stderr, batchStdinReader)
 | 
			
		||||
			RunWithContext(&RunContext{
 | 
			
		||||
				Timeout: -1,
 | 
			
		||||
				Dir:     repoPath,
 | 
			
		||||
				Stdin:   batchStdinReader,
 | 
			
		||||
				Stdout:  batchStdoutWriter,
 | 
			
		||||
				Stderr:  &stderr,
 | 
			
		||||
			})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
			
		||||
			_ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
			
		||||
 
 | 
			
		||||
@@ -486,7 +486,12 @@ 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...).RunInDirPipeline(repoPath, w, stderr)
 | 
			
		||||
	err := NewCommand(ctx, args...).RunWithContext(&RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repoPath,
 | 
			
		||||
		Stdout:  w,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	})
 | 
			
		||||
	w.Close() // Close writer to exit parsing goroutine
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, ConcatenateError(err, stderr.String())
 | 
			
		||||
 
 | 
			
		||||
@@ -301,9 +301,12 @@ func GetAffectedFiles(repo *Repository, oldCommitID, newCommitID string, env []s
 | 
			
		||||
 | 
			
		||||
	// Run `git diff --name-only` to get the names of the changed files
 | 
			
		||||
	err = NewCommand(repo.Ctx, "diff", "--name-only", oldCommitID, newCommitID).
 | 
			
		||||
		RunInDirTimeoutEnvFullPipelineFunc(env, -1, repo.Path,
 | 
			
		||||
			stdoutWriter, nil, nil,
 | 
			
		||||
			func(ctx context.Context, cancel context.CancelFunc) error {
 | 
			
		||||
		RunWithContext(&RunContext{
 | 
			
		||||
			Env:     env,
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repo.Path,
 | 
			
		||||
			Stdout:  stdoutWriter,
 | 
			
		||||
			PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
 | 
			
		||||
				// Close the writer end of the pipe to begin processing
 | 
			
		||||
				_ = stdoutWriter.Close()
 | 
			
		||||
				defer func() {
 | 
			
		||||
@@ -320,7 +323,8 @@ func GetAffectedFiles(repo *Repository, oldCommitID, newCommitID string, env []s
 | 
			
		||||
					affectedFiles = append(affectedFiles, path)
 | 
			
		||||
				}
 | 
			
		||||
				return scanner.Err()
 | 
			
		||||
			})
 | 
			
		||||
			},
 | 
			
		||||
		})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("Unable to get affected files for commits from %s to %s in %s: %v", oldCommitID, newCommitID, repo.Path, err)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,12 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		stderr := strings.Builder{}
 | 
			
		||||
		err := NewCommand(ctx, args...).RunInDirFullPipeline(repository, stdoutWriter, &stderr, nil)
 | 
			
		||||
		err := NewCommand(ctx, args...).RunWithContext(&RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repository,
 | 
			
		||||
			Stdout:  stdoutWriter,
 | 
			
		||||
			Stderr:  &stderr,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
			
		||||
		} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,13 @@ func CatFileBatchCheck(ctx context.Context, shasToCheckReader *io.PipeReader, ca
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	var errbuf strings.Builder
 | 
			
		||||
	cmd := git.NewCommand(ctx, "cat-file", "--batch-check")
 | 
			
		||||
	if err := cmd.RunInDirFullPipeline(tmpBasePath, catFileCheckWriter, stderr, shasToCheckReader); err != nil {
 | 
			
		||||
	if err := cmd.RunWithContext(&git.RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     tmpBasePath,
 | 
			
		||||
		Stdin:   shasToCheckReader,
 | 
			
		||||
		Stdout:  catFileCheckWriter,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		_ = catFileCheckWriter.CloseWithError(fmt.Errorf("git cat-file --batch-check [%s]: %v - %s", tmpBasePath, err, errbuf.String()))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -40,7 +46,12 @@ func CatFileBatchCheckAllObjects(ctx context.Context, catFileCheckWriter *io.Pip
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	var errbuf strings.Builder
 | 
			
		||||
	cmd := git.NewCommand(ctx, "cat-file", "--batch-check", "--batch-all-objects")
 | 
			
		||||
	if err := cmd.RunInDirPipeline(tmpBasePath, catFileCheckWriter, stderr); err != nil {
 | 
			
		||||
	if err := cmd.RunWithContext(&git.RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     tmpBasePath,
 | 
			
		||||
		Stdout:  catFileCheckWriter,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		log.Error("git cat-file --batch-check --batch-all-object [%s]: %v - %s", tmpBasePath, err, errbuf.String())
 | 
			
		||||
		err = fmt.Errorf("git cat-file --batch-check --batch-all-object [%s]: %v - %s", tmpBasePath, err, errbuf.String())
 | 
			
		||||
		_ = catFileCheckWriter.CloseWithError(err)
 | 
			
		||||
@@ -56,7 +67,13 @@ func CatFileBatch(ctx context.Context, shasToBatchReader *io.PipeReader, catFile
 | 
			
		||||
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	var errbuf strings.Builder
 | 
			
		||||
	if err := git.NewCommand(ctx, "cat-file", "--batch").RunInDirFullPipeline(tmpBasePath, catFileBatchWriter, stderr, shasToBatchReader); err != nil {
 | 
			
		||||
	if err := git.NewCommand(ctx, "cat-file", "--batch").RunWithContext(&git.RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     tmpBasePath,
 | 
			
		||||
		Stdout:  catFileBatchWriter,
 | 
			
		||||
		Stdin:   shasToBatchReader,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		_ = shasToBatchReader.CloseWithError(fmt.Errorf("git rev-list [%s]: %v - %s", tmpBasePath, err, errbuf.String()))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,12 @@ func FindLFSFile(repo *git.Repository, hash git.SHA1) ([]*LFSResult, error) {
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		stderr := strings.Builder{}
 | 
			
		||||
		err := git.NewCommand(repo.Ctx, "rev-list", "--all").RunInDirPipeline(repo.Path, revListWriter, &stderr)
 | 
			
		||||
		err := git.NewCommand(repo.Ctx, "rev-list", "--all").RunWithContext(&git.RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repo.Path,
 | 
			
		||||
			Stdout:  revListWriter,
 | 
			
		||||
			Stderr:  &stderr,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = revListWriter.CloseWithError(git.ConcatenateError(err, (&stderr).String()))
 | 
			
		||||
		} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,13 @@ func NameRevStdin(ctx context.Context, shasToNameReader *io.PipeReader, nameRevS
 | 
			
		||||
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	var errbuf strings.Builder
 | 
			
		||||
	if err := git.NewCommand(ctx, "name-rev", "--stdin", "--name-only", "--always").RunInDirFullPipeline(tmpBasePath, nameRevStdinWriter, stderr, shasToNameReader); err != nil {
 | 
			
		||||
	if err := git.NewCommand(ctx, "name-rev", "--stdin", "--name-only", "--always").RunWithContext(&git.RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     tmpBasePath,
 | 
			
		||||
		Stdout:  nameRevStdinWriter,
 | 
			
		||||
		Stdin:   shasToNameReader,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		_ = shasToNameReader.CloseWithError(fmt.Errorf("git name-rev [%s]: %v - %s", tmpBasePath, err, errbuf.String()))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,12 @@ func RevListAllObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sy
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	var errbuf strings.Builder
 | 
			
		||||
	cmd := git.NewCommand(ctx, "rev-list", "--objects", "--all")
 | 
			
		||||
	if err := cmd.RunInDirPipeline(basePath, revListWriter, stderr); err != nil {
 | 
			
		||||
	if err := cmd.RunWithContext(&git.RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     basePath,
 | 
			
		||||
		Stdout:  revListWriter,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		log.Error("git rev-list --objects --all [%s]: %v - %s", basePath, err, errbuf.String())
 | 
			
		||||
		err = fmt.Errorf("git rev-list --objects --all [%s]: %v - %s", basePath, err, errbuf.String())
 | 
			
		||||
		_ = revListWriter.CloseWithError(err)
 | 
			
		||||
@@ -40,7 +45,12 @@ func RevListObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync.
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	var errbuf strings.Builder
 | 
			
		||||
	cmd := git.NewCommand(ctx, "rev-list", "--objects", headSHA, "--not", baseSHA)
 | 
			
		||||
	if err := cmd.RunInDirPipeline(tmpBasePath, revListWriter, stderr); err != nil {
 | 
			
		||||
	if err := cmd.RunWithContext(&git.RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     tmpBasePath,
 | 
			
		||||
		Stdout:  revListWriter,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		log.Error("git rev-list [%s]: %v - %s", tmpBasePath, err, errbuf.String())
 | 
			
		||||
		errChan <- fmt.Errorf("git rev-list [%s]: %v - %s", tmpBasePath, err, errbuf.String())
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -204,7 +204,13 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
 | 
			
		||||
		opts.Timeout = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := cmd.RunInDirTimeoutEnvPipeline(opts.Env, opts.Timeout, repoPath, &outbuf, &errbuf)
 | 
			
		||||
	err := cmd.RunWithContext(&RunContext{
 | 
			
		||||
		Env:     opts.Env,
 | 
			
		||||
		Timeout: opts.Timeout,
 | 
			
		||||
		Dir:     repoPath,
 | 
			
		||||
		Stdout:  &outbuf,
 | 
			
		||||
		Stderr:  &errbuf,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if strings.Contains(errbuf.String(), "non-fast-forward") {
 | 
			
		||||
			return &ErrPushOutOfDate{
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,12 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	var stderr strings.Builder
 | 
			
		||||
	err := NewCommand(ctx, args...).RunInDirPipeline(repo.Path, target, &stderr)
 | 
			
		||||
	err := NewCommand(ctx, args...).RunWithContext(&RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repo.Path,
 | 
			
		||||
		Stdout:  target,
 | 
			
		||||
		Stderr:  &stderr,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ConcatenateError(err, stderr.String())
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,13 @@ func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[
 | 
			
		||||
 | 
			
		||||
	cmd := NewCommand(repo.Ctx, cmdArgs...)
 | 
			
		||||
 | 
			
		||||
	if err := cmd.RunInDirTimeoutEnvPipeline(env, -1, repo.Path, stdOut, stdErr); err != nil {
 | 
			
		||||
	if err := cmd.RunWithContext(&RunContext{
 | 
			
		||||
		Env:     env,
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repo.Path,
 | 
			
		||||
		Stdout:  stdOut,
 | 
			
		||||
		Stderr:  stdErr,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("failed to run check-attr: %v\n%s\n%s", err, stdOut.String(), stdErr.String())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -182,9 +188,17 @@ func (c *CheckAttributeReader) Run() error {
 | 
			
		||||
		_ = c.Close()
 | 
			
		||||
	}()
 | 
			
		||||
	stdErr := new(bytes.Buffer)
 | 
			
		||||
	err := c.cmd.RunInDirTimeoutEnvFullPipelineFunc(c.env, -1, c.Repo.Path, c.stdOut, stdErr, c.stdinReader, func(_ context.Context, _ context.CancelFunc) error {
 | 
			
		||||
		close(c.running)
 | 
			
		||||
		return nil
 | 
			
		||||
	err := c.cmd.RunWithContext(&RunContext{
 | 
			
		||||
		Env:     c.env,
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     c.Repo.Path,
 | 
			
		||||
		Stdin:   c.stdinReader,
 | 
			
		||||
		Stdout:  c.stdOut,
 | 
			
		||||
		Stderr:  stdErr,
 | 
			
		||||
		PipelineFunc: func(_ context.Context, _ context.CancelFunc) error {
 | 
			
		||||
			close(c.running)
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil && c.ctx.Err() != nil && err.Error() != "signal: killed" {
 | 
			
		||||
		return fmt.Errorf("failed to run attr-check. Error: %w\nStderr: %s", err, stdErr.String())
 | 
			
		||||
 
 | 
			
		||||
@@ -96,7 +96,12 @@ func walkShowRef(ctx context.Context, repoPath, arg string, skip, limit int, wal
 | 
			
		||||
		if arg != "" {
 | 
			
		||||
			args = append(args, arg)
 | 
			
		||||
		}
 | 
			
		||||
		err := NewCommand(ctx, args...).RunInDirPipeline(repoPath, stdoutWriter, stderrBuilder)
 | 
			
		||||
		err := NewCommand(ctx, args...).RunWithContext(&RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repoPath,
 | 
			
		||||
			Stdout:  stdoutWriter,
 | 
			
		||||
			Stderr:  stderrBuilder,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if stderrBuilder.Len() == 0 {
 | 
			
		||||
				_ = stdoutWriter.Close()
 | 
			
		||||
 
 | 
			
		||||
@@ -211,7 +211,12 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
 | 
			
		||||
		err := NewCommand(repo.Ctx, "log", revision, "--follow",
 | 
			
		||||
			"--max-count="+strconv.Itoa(setting.Git.CommitsRangeSize*page),
 | 
			
		||||
			prettyLogFormat, "--", file).
 | 
			
		||||
			RunInDirPipeline(repo.Path, stdoutWriter, &stderr)
 | 
			
		||||
			RunWithContext(&RunContext{
 | 
			
		||||
				Timeout: -1,
 | 
			
		||||
				Dir:     repo.Path,
 | 
			
		||||
				Stdout:  stdoutWriter,
 | 
			
		||||
				Stderr:  &stderr,
 | 
			
		||||
			})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
 | 
			
		||||
		} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -147,13 +147,23 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := NewCommand(repo.Ctx, "diff", "-z", "--name-only", base+separator+head).
 | 
			
		||||
		RunInDirPipeline(repo.Path, w, stderr); err != nil {
 | 
			
		||||
		RunWithContext(&RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repo.Path,
 | 
			
		||||
			Stdout:  w,
 | 
			
		||||
			Stderr:  stderr,
 | 
			
		||||
		}); err != nil {
 | 
			
		||||
		if strings.Contains(stderr.String(), "no merge base") {
 | 
			
		||||
			// git >= 2.28 now returns an error if base and head have become unrelated.
 | 
			
		||||
			// previously it would return the results of git diff -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).RunInDirPipeline(repo.Path, w, stderr); err == nil {
 | 
			
		||||
			if err = NewCommand(repo.Ctx, "diff", "-z", "--name-only", base, head).RunWithContext(&RunContext{
 | 
			
		||||
				Timeout: -1,
 | 
			
		||||
				Dir:     repo.Path,
 | 
			
		||||
				Stdout:  w,
 | 
			
		||||
				Stderr:  stderr,
 | 
			
		||||
			}); err == nil {
 | 
			
		||||
				return w.numLines, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -238,28 +248,46 @@ 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).
 | 
			
		||||
		RunInDirPipeline(repo.Path, w, nil)
 | 
			
		||||
	return NewCommand(repo.Ctx, "diff", "-p", base, head).RunWithContext(&RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repo.Path,
 | 
			
		||||
		Stdout:  w,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDiffBinary generates and returns patch data between given revisions, including binary diffs.
 | 
			
		||||
func (repo *Repository) GetDiffBinary(base, head string, w io.Writer) error {
 | 
			
		||||
	if CheckGitVersionAtLeast("1.7.7") == nil {
 | 
			
		||||
		return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram", base, head).
 | 
			
		||||
			RunInDirPipeline(repo.Path, w, nil)
 | 
			
		||||
		return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--histogram", base, head).RunWithContext(&RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repo.Path,
 | 
			
		||||
			Stdout:  w,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--patience", base, head).
 | 
			
		||||
		RunInDirPipeline(repo.Path, w, nil)
 | 
			
		||||
	return NewCommand(repo.Ctx, "diff", "-p", "--binary", "--patience", base, head).RunWithContext(&RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repo.Path,
 | 
			
		||||
		Stdout:  w,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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).
 | 
			
		||||
		RunInDirPipeline(repo.Path, w, stderr)
 | 
			
		||||
		RunWithContext(&RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			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).
 | 
			
		||||
			RunInDirPipeline(repo.Path, w, nil)
 | 
			
		||||
			RunWithContext(&RunContext{
 | 
			
		||||
				Timeout: -1,
 | 
			
		||||
				Dir:     repo.Path,
 | 
			
		||||
				Stdout:  w,
 | 
			
		||||
			})
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
@@ -268,7 +296,12 @@ func (repo *Repository) GetPatch(base, head string, w io.Writer) error {
 | 
			
		||||
func (repo *Repository) GetDiffFromMergeBase(base, head string, w io.Writer) error {
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	err := NewCommand(repo.Ctx, "diff", "-p", "--binary", base+"..."+head).
 | 
			
		||||
		RunInDirPipeline(repo.Path, w, stderr)
 | 
			
		||||
		RunWithContext(&RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repo.Path,
 | 
			
		||||
			Stdout:  w,
 | 
			
		||||
			Stderr:  stderr,
 | 
			
		||||
		})
 | 
			
		||||
	if err != nil && bytes.Contains(stderr.Bytes(), []byte("no merge base")) {
 | 
			
		||||
		return repo.GetDiffBinary(base, head, w)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -106,7 +106,13 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
 | 
			
		||||
			buffer.WriteByte('\000')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return cmd.RunInDirFullPipeline(repo.Path, stdout, stderr, bytes.NewReader(buffer.Bytes()))
 | 
			
		||||
	return cmd.RunWithContext(&RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repo.Path,
 | 
			
		||||
		Stdin:   bytes.NewReader(buffer.Bytes()),
 | 
			
		||||
		Stdout:  stdout,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddObjectToIndex adds the provided object hash to the index at the provided filename
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,13 @@ func (repo *Repository) hashObject(reader io.Reader) (string, error) {
 | 
			
		||||
	cmd := NewCommand(repo.Ctx, "hash-object", "-w", "--stdin")
 | 
			
		||||
	stdout := new(bytes.Buffer)
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	err := cmd.RunInDirFullPipeline(repo.Path, stdout, stderr, reader)
 | 
			
		||||
	err := cmd.RunWithContext(&RunContext{
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repo.Path,
 | 
			
		||||
		Stdin:   reader,
 | 
			
		||||
		Stdout:  stdout,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,12 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) {
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		stderrBuilder := &strings.Builder{}
 | 
			
		||||
		err := NewCommand(repo.Ctx, "for-each-ref").RunInDirPipeline(repo.Path, stdoutWriter, stderrBuilder)
 | 
			
		||||
		err := NewCommand(repo.Ctx, "for-each-ref").RunWithContext(&RunContext{
 | 
			
		||||
			Timeout: -1,
 | 
			
		||||
			Dir:     repo.Path,
 | 
			
		||||
			Stdout:  stdoutWriter,
 | 
			
		||||
			Stderr:  stderrBuilder,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			_ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String()))
 | 
			
		||||
		} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -67,12 +67,14 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stderr := new(strings.Builder)
 | 
			
		||||
	err = NewCommand(repo.Ctx, args...).RunInDirTimeoutEnvFullPipelineFunc(
 | 
			
		||||
		nil, -1, repo.Path,
 | 
			
		||||
		stdoutWriter, stderr, nil,
 | 
			
		||||
		func(ctx context.Context, cancel context.CancelFunc) error {
 | 
			
		||||
	err = NewCommand(repo.Ctx, args...).RunWithContext(&RunContext{
 | 
			
		||||
		Env:     []string{},
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repo.Path,
 | 
			
		||||
		Stdout:  stdoutWriter,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
		PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
 | 
			
		||||
			_ = stdoutWriter.Close()
 | 
			
		||||
 | 
			
		||||
			scanner := bufio.NewScanner(stdoutReader)
 | 
			
		||||
			scanner.Split(bufio.ScanLines)
 | 
			
		||||
			stats.CommitCount = 0
 | 
			
		||||
@@ -103,11 +105,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
 | 
			
		||||
				case 4: // E-mail
 | 
			
		||||
					email := strings.ToLower(l)
 | 
			
		||||
					if _, ok := authors[email]; !ok {
 | 
			
		||||
						authors[email] = &CodeActivityAuthor{
 | 
			
		||||
							Name:    author,
 | 
			
		||||
							Email:   email,
 | 
			
		||||
							Commits: 0,
 | 
			
		||||
						}
 | 
			
		||||
						authors[email] = &CodeActivityAuthor{Name: author, Email: email, Commits: 0}
 | 
			
		||||
					}
 | 
			
		||||
					authors[email].Commits++
 | 
			
		||||
				default: // Changed file
 | 
			
		||||
@@ -128,7 +126,6 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			a := make([]*CodeActivityAuthor, 0, len(authors))
 | 
			
		||||
			for _, v := range authors {
 | 
			
		||||
				a = append(a, v)
 | 
			
		||||
@@ -137,14 +134,13 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
 | 
			
		||||
			sort.Slice(a, func(i, j int) bool {
 | 
			
		||||
				return a[i].Commits > a[j].Commits
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			stats.AuthorCount = int64(len(authors))
 | 
			
		||||
			stats.ChangedFiles = int64(len(files))
 | 
			
		||||
			stats.Authors = a
 | 
			
		||||
 | 
			
		||||
			_ = stdoutReader.Close()
 | 
			
		||||
			return nil
 | 
			
		||||
		})
 | 
			
		||||
		},
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Failed to get GetCodeActivityStats for repository.\nError: %w\nStderr: %s", err, stderr)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,14 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
 | 
			
		||||
 | 
			
		||||
	stdout := new(bytes.Buffer)
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	err = cmd.RunInDirTimeoutEnvFullPipeline(env, -1, repo.Path, stdout, stderr, messageBytes)
 | 
			
		||||
	err = cmd.RunWithContext(&RunContext{
 | 
			
		||||
		Env:     env,
 | 
			
		||||
		Timeout: -1,
 | 
			
		||||
		Dir:     repo.Path,
 | 
			
		||||
		Stdin:   messageBytes,
 | 
			
		||||
		Stdout:  stdout,
 | 
			
		||||
		Stderr:  stderr,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return SHA1{}, ConcatenateError(err, stderr.String())
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user