mirror of
https://github.com/go-gitea/gitea.git
synced 2026-06-15 08:04:04 +00:00
fix: refactor git error handling and make archive streaming handle non-existing commit id (#38007)
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -9,6 +9,8 @@ import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
type RunStdError interface {
|
||||
@@ -41,32 +43,14 @@ func (r *runStdError) Stderr() string {
|
||||
}
|
||||
|
||||
func ErrorAsStderr(err error) (string, bool) {
|
||||
var runErr RunStdError
|
||||
if errors.As(err, &runErr) {
|
||||
if runErr, ok := errors.AsType[RunStdError](err); ok {
|
||||
return runErr.Stderr(), true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func StderrHasPrefix(err error, prefix string) bool {
|
||||
stderr, ok := ErrorAsStderr(err)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return strings.HasPrefix(stderr, prefix)
|
||||
}
|
||||
|
||||
func StderrContains(err error, sub string) bool {
|
||||
stderr, ok := ErrorAsStderr(err)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return strings.Contains(stderr, sub)
|
||||
}
|
||||
|
||||
func IsErrorExitCode(err error, code int) bool {
|
||||
var exitError *exec.ExitError
|
||||
if errors.As(err, &exitError) {
|
||||
if exitError, ok := errors.AsType[*exec.ExitError](err); ok {
|
||||
return exitError.ExitCode() == code
|
||||
}
|
||||
return false
|
||||
@@ -85,11 +69,41 @@ func IsErrorCanceledOrKilled(err error) bool {
|
||||
return errors.Is(err, context.Canceled) || IsErrorSignalKilled(err)
|
||||
}
|
||||
|
||||
func IsStdErrorNotValidObjectName(err error) bool {
|
||||
type StderrPrefix string
|
||||
|
||||
type StderrSubStr string
|
||||
|
||||
const (
|
||||
StderrNotValidObjectName StderrPrefix = "fatal: not a valid object name"
|
||||
StderrNotTreeObject StderrPrefix = "fatal: not a tree object"
|
||||
StderrPathSpec StderrPrefix = "fatal: pathspec"
|
||||
StderrBadRevision StderrPrefix = "fatal: bad revision"
|
||||
|
||||
StderrNoSuchRemote1 StderrPrefix = "fatal: no such remote" // git < 2.30, exit status 128
|
||||
StderrNoSuchRemote2 StderrPrefix = "error: no such remote" // git >= 2.30. exit status 2
|
||||
|
||||
// fatal: ambiguous argument 'origin': unknown revision or path not in the working tree.
|
||||
StderrUnknownRevisionOrPath StderrSubStr = "unknown revision or path not in the working tree"
|
||||
)
|
||||
|
||||
func IsStderr[T StderrPrefix | StderrSubStr](err error, check T) bool {
|
||||
stderr, ok := ErrorAsStderr(err)
|
||||
// Git is lowercasing the "fatal: Not a valid object name" error message
|
||||
// ref: https://lore.kernel.org/git/pull.2052.git.1771836302101.gitgitgadget@gmail.com
|
||||
return ok && strings.Contains(strings.ToLower(stderr), "fatal: not a valid object name")
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
checkLen := len(check)
|
||||
if len(stderr) < checkLen {
|
||||
return false
|
||||
}
|
||||
switch any(check).(type) {
|
||||
case StderrPrefix:
|
||||
// Git is lowercasing the "fatal: Not a valid object name" error message
|
||||
// ref: https://lore.kernel.org/git/pull.2052.git.1771836302101.gitgitgadget@gmail.com
|
||||
return util.AsciiEqualFold(stderr[:checkLen], string(check))
|
||||
case StderrSubStr:
|
||||
return strings.Contains(stderr, string(check))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type pipelineError struct {
|
||||
|
||||
Reference in New Issue
Block a user