mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-28 20:34:30 +09:00
Refactor git command stderr handling (#36402)
And clean up legacy fragile & incorrect logic
This commit is contained in:
@@ -88,7 +88,7 @@ func GitGcRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Du
|
||||
command := gitcmd.NewCommand("gc").AddArguments(args...)
|
||||
var stdout string
|
||||
var err error
|
||||
stdout, err = gitrepo.RunCmdString(ctx, repo, command)
|
||||
stdout, _, err = gitrepo.RunCmdString(ctx, repo, command)
|
||||
if err != nil {
|
||||
log.Error("Repository garbage collection failed for %-v. Stdout: %s\nError: %v", repo, stdout, err)
|
||||
desc := fmt.Sprintf("Repository garbage collection failed for %s. Stdout: %s\nError: %v", repo.RelativePath(), stdout, err)
|
||||
|
||||
@@ -131,10 +131,8 @@ func getExtendedCommitStats(repo *git.Repository, revision string /*, limit int
|
||||
gitCmd.AddDynamicArguments(baseCommit.ID.String())
|
||||
|
||||
var extendedCommitStats []*ExtendedCommitStats
|
||||
stderr := new(strings.Builder)
|
||||
err = gitCmd.WithDir(repo.Path).
|
||||
WithStdout(stdoutWriter).
|
||||
WithStderr(stderr).
|
||||
WithPipelineFunc(func(ctx context.Context, cancel context.CancelFunc) error {
|
||||
_ = stdoutWriter.Close()
|
||||
scanner := bufio.NewScanner(stdoutReader)
|
||||
@@ -191,9 +189,9 @@ func getExtendedCommitStats(repo *git.Repository, revision string /*, limit int
|
||||
_ = stdoutReader.Close()
|
||||
return nil
|
||||
}).
|
||||
Run(repo.Ctx)
|
||||
RunWithStderr(repo.Ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get ContributorsCommitStats for repository.\nError: %w\nStderr: %s", err, stderr)
|
||||
return nil, fmt.Errorf("ContributorsCommitStats: %w", err)
|
||||
}
|
||||
|
||||
return extendedCommitStats, nil
|
||||
|
||||
@@ -315,7 +315,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, owner *user_model.User,
|
||||
licenses = append(licenses, opts.License)
|
||||
|
||||
var stdout string
|
||||
stdout, err = gitrepo.RunCmdString(ctx, repo, gitcmd.NewCommand("rev-parse", "HEAD"))
|
||||
stdout, _, err = gitrepo.RunCmdString(ctx, repo, gitcmd.NewCommand("rev-parse", "HEAD"))
|
||||
if err != nil {
|
||||
log.Error("CreateRepository(git rev-parse HEAD) in %v: Stdout: %s\nError: %v", repo, stdout, err)
|
||||
return nil, fmt.Errorf("CreateRepository(git rev-parse HEAD): %w", err)
|
||||
@@ -476,7 +476,7 @@ func updateGitRepoAfterCreate(ctx context.Context, repo *repo_model.Repository)
|
||||
return fmt.Errorf("checkDaemonExportOK: %w", err)
|
||||
}
|
||||
|
||||
if stdout, err := gitrepo.RunCmdString(ctx, repo,
|
||||
if stdout, _, err := gitrepo.RunCmdString(ctx, repo,
|
||||
gitcmd.NewCommand("update-server-info")); err != nil {
|
||||
log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
|
||||
return fmt.Errorf("CreateRepository(git update-server-info): %w", err)
|
||||
|
||||
@@ -164,20 +164,15 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user
|
||||
}
|
||||
}
|
||||
|
||||
stdout := &strings.Builder{}
|
||||
stderr := &strings.Builder{}
|
||||
|
||||
cmdApply := gitcmd.NewCommand("apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary")
|
||||
if git.DefaultFeatures().CheckVersionAtLeast("2.32") {
|
||||
cmdApply.AddArguments("-3")
|
||||
}
|
||||
|
||||
if err := cmdApply.WithDir(t.basePath).
|
||||
WithStdout(stdout).
|
||||
WithStderr(stderr).
|
||||
WithStdin(strings.NewReader(opts.Content)).
|
||||
Run(ctx); err != nil {
|
||||
return nil, fmt.Errorf("Error: Stdout: %s\nStderr: %s\nErr: %w", stdout.String(), stderr.String(), err)
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return nil, fmt.Errorf("git apply error: %w", err)
|
||||
}
|
||||
|
||||
// Now write the tree
|
||||
|
||||
@@ -98,7 +98,7 @@ func (t *TemporaryUploadRepository) Init(ctx context.Context, objectFormatName s
|
||||
|
||||
// SetDefaultIndex sets the git index to our HEAD
|
||||
func (t *TemporaryUploadRepository) SetDefaultIndex(ctx context.Context) error {
|
||||
if _, _, err := gitcmd.NewCommand("read-tree", "HEAD").WithDir(t.basePath).RunStdString(ctx); err != nil {
|
||||
if err := gitcmd.NewCommand("read-tree", "HEAD").WithDir(t.basePath).RunWithStderr(ctx); err != nil {
|
||||
return fmt.Errorf("SetDefaultIndex: %w", err)
|
||||
}
|
||||
return nil
|
||||
@@ -106,7 +106,7 @@ func (t *TemporaryUploadRepository) SetDefaultIndex(ctx context.Context) error {
|
||||
|
||||
// RefreshIndex looks at the current index and checks to see if merges or updates are needed by checking stat() information.
|
||||
func (t *TemporaryUploadRepository) RefreshIndex(ctx context.Context) error {
|
||||
if _, _, err := gitcmd.NewCommand("update-index", "--refresh").WithDir(t.basePath).RunStdString(ctx); err != nil {
|
||||
if err := gitcmd.NewCommand("update-index", "--refresh").WithDir(t.basePath).RunWithStderr(ctx); err != nil {
|
||||
return fmt.Errorf("RefreshIndex: %w", err)
|
||||
}
|
||||
return nil
|
||||
@@ -115,16 +115,11 @@ func (t *TemporaryUploadRepository) RefreshIndex(ctx context.Context) error {
|
||||
// LsFiles checks if the given filename arguments are in the index
|
||||
func (t *TemporaryUploadRepository) LsFiles(ctx context.Context, filenames ...string) ([]string, error) {
|
||||
stdOut := new(bytes.Buffer)
|
||||
stdErr := new(bytes.Buffer)
|
||||
|
||||
if err := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...).
|
||||
WithDir(t.basePath).
|
||||
WithStdout(stdOut).
|
||||
WithStderr(stdErr).
|
||||
Run(ctx); err != nil {
|
||||
log.Error("Unable to run git ls-files for temporary repo: %s (%s) Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), t.basePath, err, stdOut.String(), stdErr.String())
|
||||
err = fmt.Errorf("Unable to run git ls-files for temporary repo of: %s Error: %w\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String())
|
||||
return nil, err
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return nil, fmt.Errorf("unable to run git ls-files for temporary repo of: %s, error: %w", t.repo.FullName(), err)
|
||||
}
|
||||
|
||||
fileList := make([]string, 0, len(filenames))
|
||||
@@ -149,8 +144,6 @@ func (t *TemporaryUploadRepository) RemoveFilesFromIndex(ctx context.Context, fi
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get object format for temporary repo: %q, error: %w", t.repo.FullName(), err)
|
||||
}
|
||||
stdOut := new(bytes.Buffer)
|
||||
stdErr := new(bytes.Buffer)
|
||||
stdIn := new(bytes.Buffer)
|
||||
for _, file := range filenames {
|
||||
if file != "" {
|
||||
@@ -162,11 +155,9 @@ func (t *TemporaryUploadRepository) RemoveFilesFromIndex(ctx context.Context, fi
|
||||
|
||||
if err := gitcmd.NewCommand("update-index", "--remove", "-z", "--index-info").
|
||||
WithDir(t.basePath).
|
||||
WithStdout(stdOut).
|
||||
WithStderr(stdErr).
|
||||
WithStdin(stdIn).
|
||||
Run(ctx); err != nil {
|
||||
return fmt.Errorf("unable to update-index for temporary repo: %q, error: %w\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String())
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return fmt.Errorf("unable to update-index for temporary repo: %q, error: %w", t.repo.FullName(), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -174,16 +165,12 @@ func (t *TemporaryUploadRepository) RemoveFilesFromIndex(ctx context.Context, fi
|
||||
// HashObjectAndWrite writes the provided content to the object db and returns its hash
|
||||
func (t *TemporaryUploadRepository) HashObjectAndWrite(ctx context.Context, content io.Reader) (string, error) {
|
||||
stdOut := new(bytes.Buffer)
|
||||
stdErr := new(bytes.Buffer)
|
||||
|
||||
if err := gitcmd.NewCommand("hash-object", "-w", "--stdin").
|
||||
WithDir(t.basePath).
|
||||
WithStdout(stdOut).
|
||||
WithStderr(stdErr).
|
||||
WithStdin(content).
|
||||
Run(ctx); err != nil {
|
||||
log.Error("Unable to hash-object to temporary repo: %s (%s) Error: %v\nstdout: %s\nstderr: %s", t.repo.FullName(), t.basePath, err, stdOut.String(), stdErr.String())
|
||||
return "", fmt.Errorf("Unable to hash-object to temporary repo: %s Error: %w\nstdout: %s\nstderr: %s", t.repo.FullName(), err, stdOut.String(), stdErr.String())
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return "", fmt.Errorf("unable to hash-object to temporary repo: %s, error: %w", t.repo.FullName(), err)
|
||||
}
|
||||
|
||||
return strings.TrimSpace(stdOut.String()), nil
|
||||
@@ -191,17 +178,15 @@ func (t *TemporaryUploadRepository) HashObjectAndWrite(ctx context.Context, cont
|
||||
|
||||
// AddObjectToIndex adds the provided object hash to the index with the provided mode and path
|
||||
func (t *TemporaryUploadRepository) AddObjectToIndex(ctx context.Context, mode, objectHash, objectPath string) error {
|
||||
if _, _, err := gitcmd.NewCommand("update-index", "--add", "--replace", "--cacheinfo").
|
||||
AddDynamicArguments(mode, objectHash, objectPath).WithDir(t.basePath).RunStdString(ctx); err != nil {
|
||||
stderr := err.Error()
|
||||
if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched {
|
||||
if err := gitcmd.NewCommand("update-index", "--add", "--replace", "--cacheinfo").
|
||||
AddDynamicArguments(mode, objectHash, objectPath).WithDir(t.basePath).RunWithStderr(ctx); err != nil {
|
||||
if matched, _ := regexp.MatchString(".*Invalid path '.*", err.Stderr()); matched {
|
||||
return ErrFilePathInvalid{
|
||||
Message: objectPath,
|
||||
Path: objectPath,
|
||||
}
|
||||
}
|
||||
log.Error("Unable to add object to index: %s %s %s in temporary repo %s(%s) Error: %v", mode, objectHash, objectPath, t.repo.FullName(), t.basePath, err)
|
||||
return fmt.Errorf("Unable to add object to index at %s in temporary repo %s Error: %w", objectPath, t.repo.FullName(), err)
|
||||
return fmt.Errorf("unable to add object to index at %s in temporary repo %s, error: %w", objectPath, t.repo.FullName(), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -342,18 +327,13 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit
|
||||
)
|
||||
|
||||
stdout := new(bytes.Buffer)
|
||||
stderr := new(bytes.Buffer)
|
||||
if err := cmdCommitTree.
|
||||
WithEnv(env).
|
||||
WithDir(t.basePath).
|
||||
WithStdout(stdout).
|
||||
WithStderr(stderr).
|
||||
WithStdin(messageBytes).
|
||||
Run(ctx); err != nil {
|
||||
log.Error("Unable to commit-tree in temporary repo: %s (%s) Error: %v\nStdout: %s\nStderr: %s",
|
||||
t.repo.FullName(), t.basePath, err, stdout, stderr)
|
||||
return "", fmt.Errorf("Unable to commit-tree in temporary repo: %s Error: %w\nStdout: %s\nStderr: %s",
|
||||
t.repo.FullName(), err, stdout, stderr)
|
||||
RunWithStderr(ctx); err != nil {
|
||||
return "", fmt.Errorf("unable to commit-tree in temporary repo: %s Error: %w", t.repo.FullName(), err)
|
||||
}
|
||||
return strings.TrimSpace(stdout.String()), nil
|
||||
}
|
||||
@@ -390,13 +370,11 @@ func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context) (*gitdiff.Dif
|
||||
_ = stdoutReader.Close()
|
||||
_ = stdoutWriter.Close()
|
||||
}()
|
||||
stderr := new(bytes.Buffer)
|
||||
var diff *gitdiff.Diff
|
||||
err = gitcmd.NewCommand("diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD").
|
||||
WithTimeout(30 * time.Second).
|
||||
WithDir(t.basePath).
|
||||
WithStdout(stdoutWriter).
|
||||
WithStderr(stderr).
|
||||
WithPipelineFunc(func(ctx context.Context, cancel context.CancelFunc) error {
|
||||
_ = stdoutWriter.Close()
|
||||
defer cancel()
|
||||
@@ -409,9 +387,8 @@ func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context) (*gitdiff.Dif
|
||||
}
|
||||
return nil
|
||||
}).
|
||||
Run(ctx)
|
||||
RunWithStderr(ctx)
|
||||
if err != nil && !git.IsErrCanceledOrKilled(err) {
|
||||
log.Error("Unable to diff-index in temporary repo %s (%s). Error: %v\nStderr: %s", t.repo.FullName(), t.basePath, err, stderr)
|
||||
return nil, fmt.Errorf("unable to run diff-index pipeline in temporary repo: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
@@ -45,7 +44,6 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
|
||||
}
|
||||
graph := NewGraph()
|
||||
|
||||
stderr := new(strings.Builder)
|
||||
stdoutReader, stdoutWriter, err := os.Pipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -57,7 +55,6 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
|
||||
if err := graphCmd.
|
||||
WithDir(r.Path).
|
||||
WithStdout(stdoutWriter).
|
||||
WithStderr(stderr).
|
||||
WithPipelineFunc(func(ctx context.Context, cancel context.CancelFunc) error {
|
||||
_ = stdoutWriter.Close()
|
||||
defer stdoutReader.Close()
|
||||
@@ -110,7 +107,7 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
|
||||
}
|
||||
return scanner.Err()
|
||||
}).
|
||||
Run(r.Ctx); err != nil {
|
||||
RunWithStderr(r.Ctx); err != nil {
|
||||
return graph, err
|
||||
}
|
||||
return graph, nil
|
||||
|
||||
@@ -225,7 +225,7 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
|
||||
|
||||
// this is necessary for sync local tags from remote
|
||||
configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName())
|
||||
if stdout, err := gitrepo.RunCmdString(ctx, repo,
|
||||
if stdout, _, err := gitrepo.RunCmdString(ctx, repo,
|
||||
gitcmd.NewCommand("config").
|
||||
AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`)); err != nil {
|
||||
log.Error("MigrateRepositoryGitData(git config --add <remote> +refs/tags/*:refs/tags/*) in %v: Stdout: %s\nError: %v", repo, stdout, err)
|
||||
|
||||
Reference in New Issue
Block a user