Skip to content

Commit e524f63

Browse files
authored
Fix git error handling (#32401)
1 parent 13a2038 commit e524f63

File tree

10 files changed

+35
-89
lines changed

10 files changed

+35
-89
lines changed

modules/git/error.go

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,14 @@
44
package git
55

66
import (
7+
"context"
8+
"errors"
79
"fmt"
810
"strings"
9-
"time"
1011

1112
"code.gitea.io/gitea/modules/util"
1213
)
1314

14-
// ErrExecTimeout error when exec timed out
15-
type ErrExecTimeout struct {
16-
Duration time.Duration
17-
}
18-
19-
// IsErrExecTimeout if some error is ErrExecTimeout
20-
func IsErrExecTimeout(err error) bool {
21-
_, ok := err.(ErrExecTimeout)
22-
return ok
23-
}
24-
25-
func (err ErrExecTimeout) Error() string {
26-
return fmt.Sprintf("execution is timeout [duration: %v]", err.Duration)
27-
}
28-
2915
// ErrNotExist commit not exist error
3016
type ErrNotExist struct {
3117
ID string
@@ -62,21 +48,6 @@ func IsErrBadLink(err error) bool {
6248
return ok
6349
}
6450

65-
// ErrUnsupportedVersion error when required git version not matched
66-
type ErrUnsupportedVersion struct {
67-
Required string
68-
}
69-
70-
// IsErrUnsupportedVersion if some error is ErrUnsupportedVersion
71-
func IsErrUnsupportedVersion(err error) bool {
72-
_, ok := err.(ErrUnsupportedVersion)
73-
return ok
74-
}
75-
76-
func (err ErrUnsupportedVersion) Error() string {
77-
return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
78-
}
79-
8051
// ErrBranchNotExist represents a "BranchNotExist" kind of error.
8152
type ErrBranchNotExist struct {
8253
Name string
@@ -185,3 +156,10 @@ func IsErrMoreThanOne(err error) bool {
185156
func (err *ErrMoreThanOne) Error() string {
186157
return fmt.Sprintf("ErrMoreThanOne Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
187158
}
159+
160+
func IsErrCanceledOrKilled(err error) bool {
161+
// When "cancel()" a git command's context, the returned error of "Run()" could be one of them:
162+
// - context.Canceled
163+
// - *exec.ExitError: "signal: killed"
164+
return err != nil && (errors.Is(err, context.Canceled) || err.Error() == "signal: killed")
165+
}

modules/git/repo_attribute.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,7 @@ func (c *CheckAttributeReader) Run() error {
166166
Stdout: c.stdOut,
167167
Stderr: stdErr,
168168
})
169-
if err != nil && // If there is an error we need to return but:
170-
c.ctx.Err() != err && // 1. Ignore the context error if the context is cancelled or exceeds the deadline (RunWithContext could return c.ctx.Err() which is Canceled or DeadlineExceeded)
171-
err.Error() != "signal: killed" { // 2. We should not pass up errors due to the program being killed
169+
if err != nil && !IsErrCanceledOrKilled(err) {
172170
return fmt.Errorf("failed to run attr-check. Error: %w\nStderr: %s", err, stdErr.String())
173171
}
174172
return nil

routers/api/v1/repo/repo.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
repo_model "code.gitea.io/gitea/models/repo"
2222
unit_model "code.gitea.io/gitea/models/unit"
2323
user_model "code.gitea.io/gitea/models/user"
24-
"code.gitea.io/gitea/modules/git"
2524
"code.gitea.io/gitea/modules/gitrepo"
2625
"code.gitea.io/gitea/modules/label"
2726
"code.gitea.io/gitea/modules/log"
@@ -739,10 +738,8 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
739738
if opts.DefaultBranch != nil && repo.DefaultBranch != *opts.DefaultBranch && (repo.IsEmpty || ctx.Repo.GitRepo.IsBranchExist(*opts.DefaultBranch)) {
740739
if !repo.IsEmpty {
741740
if err := gitrepo.SetDefaultBranch(ctx, ctx.Repo.Repository, *opts.DefaultBranch); err != nil {
742-
if !git.IsErrUnsupportedVersion(err) {
743-
ctx.Error(http.StatusInternalServerError, "SetDefaultBranch", err)
744-
return err
745-
}
741+
ctx.Error(http.StatusInternalServerError, "SetDefaultBranch", err)
742+
return err
746743
}
747744
updateRepoLicense = true
748745
}

routers/private/default_branch.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"net/http"
99

1010
repo_model "code.gitea.io/gitea/models/repo"
11-
"code.gitea.io/gitea/modules/git"
1211
"code.gitea.io/gitea/modules/gitrepo"
1312
"code.gitea.io/gitea/modules/private"
1413
gitea_context "code.gitea.io/gitea/services/context"
@@ -23,12 +22,10 @@ func SetDefaultBranch(ctx *gitea_context.PrivateContext) {
2322

2423
ctx.Repo.Repository.DefaultBranch = branch
2524
if err := gitrepo.SetDefaultBranch(ctx, ctx.Repo.Repository, ctx.Repo.Repository.DefaultBranch); err != nil {
26-
if !git.IsErrUnsupportedVersion(err) {
27-
ctx.JSON(http.StatusInternalServerError, private.Response{
28-
Err: fmt.Sprintf("Unable to set default branch on repository: %s/%s Error: %v", ownerName, repoName, err),
29-
})
30-
return
31-
}
25+
ctx.JSON(http.StatusInternalServerError, private.Response{
26+
Err: fmt.Sprintf("Unable to set default branch on repository: %s/%s Error: %v", ownerName, repoName, err),
27+
})
28+
return
3229
}
3330

3431
if err := repo_model.UpdateDefaultBranch(ctx, ctx.Repo.Repository); err != nil {

routers/web/repo/githttp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
467467
Stderr: &stderr,
468468
UseContextTimeout: true,
469469
}); err != nil {
470-
if err.Error() != "signal: killed" {
470+
if !git.IsErrCanceledOrKilled(err) {
471471
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getRepoDir(), err, stderr.String())
472472
}
473473
return

services/gitdiff/gitdiff.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, fi
11621162
Dir: repoPath,
11631163
Stdout: writer,
11641164
Stderr: stderr,
1165-
}); err != nil && err.Error() != "signal: killed" {
1165+
}); err != nil && !git.IsErrCanceledOrKilled(err) {
11661166
log.Error("error during GetDiff(git diff dir: %s): %v, stderr: %s", repoPath, err, stderr.String())
11671167
}
11681168

services/mirror/mirror_pull.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -613,14 +613,8 @@ func checkAndUpdateEmptyRepository(ctx context.Context, m *repo_model.Mirror, re
613613
}
614614
// Update the git repository default branch
615615
if err := gitrepo.SetDefaultBranch(ctx, m.Repo, m.Repo.DefaultBranch); err != nil {
616-
if !git.IsErrUnsupportedVersion(err) {
617-
log.Error("Failed to update default branch of underlying git repository %-v. Error: %v", m.Repo, err)
618-
desc := fmt.Sprintf("Failed to update default branch of underlying git repository '%s': %v", m.Repo.RepoPath(), err)
619-
if err = system_model.CreateRepositoryNotice(desc); err != nil {
620-
log.Error("CreateRepositoryNotice: %v", err)
621-
}
622-
return false
623-
}
616+
log.Error("Failed to update default branch of underlying git repository %-v. Error: %v", m.Repo, err)
617+
return false
624618
}
625619
m.Repo.IsEmpty = false
626620
// Update the is empty and default_branch columns

services/repository/branch.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -602,12 +602,7 @@ func SetRepoDefaultBranch(ctx context.Context, repo *repo_model.Repository, gitR
602602
log.Error("CancelPreviousJobs: %v", err)
603603
}
604604

605-
if err := gitrepo.SetDefaultBranch(ctx, repo, newBranchName); err != nil {
606-
if !git.IsErrUnsupportedVersion(err) {
607-
return err
608-
}
609-
}
610-
return nil
605+
return gitrepo.SetDefaultBranch(ctx, repo, newBranchName)
611606
}); err != nil {
612607
return err
613608
}

services/repository/files/temp_repo.go

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -339,18 +339,15 @@ func (t *TemporaryUploadRepository) Push(doer *user_model.User, commitHash, bran
339339
func (t *TemporaryUploadRepository) DiffIndex() (*gitdiff.Diff, error) {
340340
stdoutReader, stdoutWriter, err := os.Pipe()
341341
if err != nil {
342-
log.Error("Unable to open stdout pipe: %v", err)
343-
return nil, fmt.Errorf("Unable to open stdout pipe: %w", err)
342+
return nil, fmt.Errorf("unable to open stdout pipe: %w", err)
344343
}
345344
defer func() {
346345
_ = stdoutReader.Close()
347346
_ = stdoutWriter.Close()
348347
}()
349348
stderr := new(bytes.Buffer)
350349
var diff *gitdiff.Diff
351-
var finalErr error
352-
353-
if err := git.NewCommand(t.ctx, "diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD").
350+
err = git.NewCommand(t.ctx, "diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD").
354351
Run(&git.RunOpts{
355352
Timeout: 30 * time.Second,
356353
Dir: t.basePath,
@@ -359,27 +356,19 @@ func (t *TemporaryUploadRepository) DiffIndex() (*gitdiff.Diff, error) {
359356
PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error {
360357
_ = stdoutWriter.Close()
361358
defer cancel()
362-
diff, finalErr = gitdiff.ParsePatch(t.ctx, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader, "")
363-
if finalErr != nil {
364-
log.Error("ParsePatch: %v", finalErr)
365-
cancel()
366-
}
359+
var diffErr error
360+
diff, diffErr = gitdiff.ParsePatch(t.ctx, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader, "")
367361
_ = stdoutReader.Close()
368-
return finalErr
362+
if diffErr != nil {
363+
// if the diffErr is not nil, it will be returned as the error of "Run()"
364+
return fmt.Errorf("ParsePatch: %w", diffErr)
365+
}
366+
return nil
369367
},
370-
}); err != nil {
371-
if finalErr != nil {
372-
log.Error("Unable to ParsePatch in temporary repo %s (%s). Error: %v", t.repo.FullName(), t.basePath, finalErr)
373-
return nil, finalErr
374-
}
375-
376-
// If the process exited early, don't error
377-
if err != context.Canceled {
378-
log.Error("Unable to run diff-index pipeline in temporary repo %s (%s). Error: %v\nStderr: %s",
379-
t.repo.FullName(), t.basePath, err, stderr)
380-
return nil, fmt.Errorf("Unable to run diff-index pipeline in temporary repo %s. Error: %w\nStderr: %s",
381-
t.repo.FullName(), err, stderr)
382-
}
368+
})
369+
if err != nil && !git.IsErrCanceledOrKilled(err) {
370+
log.Error("Unable to diff-index in temporary repo %s (%s). Error: %v\nStderr: %s", t.repo.FullName(), t.basePath, err, stderr)
371+
return nil, fmt.Errorf("unable to run diff-index pipeline in temporary repo: %w", err)
383372
}
384373

385374
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(t.ctx, t.basePath, git.TrustedCmdArgs{"--cached"}, "HEAD")

services/repository/push.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
183183
repo.IsEmpty = false
184184
if repo.DefaultBranch != setting.Repository.DefaultBranch {
185185
if err := gitrepo.SetDefaultBranch(ctx, repo, repo.DefaultBranch); err != nil {
186-
if !git.IsErrUnsupportedVersion(err) {
187-
return err
188-
}
186+
return err
189187
}
190188
}
191189
// Update the is empty and default_branch columns

0 commit comments

Comments
 (0)