From 429ba9c010a06e9e89ad8b77b20350c093fd9447 Mon Sep 17 00:00:00 2001 From: Md Ferdous Alam Date: Tue, 24 Feb 2026 10:25:34 +0600 Subject: [PATCH] Use case-insensitive matching for Git error "Not a valid object name" (#36728) Fixes #36727 Git is lowercasing the `fatal: Not a valid object name` error message to follow its CodingGuidelines. This change makes the string matching case-insensitive so it works with both the current and future Git versions. --------- Co-authored-by: wxiaoguang --- modules/git/gitcmd/command_test.go | 13 +++++++++---- modules/git/gitcmd/error.go | 7 +++++++ modules/git/tree_nogogit.go | 2 +- routers/web/repo/pull.go | 6 +++--- services/wiki/wiki.go | 4 ++-- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/modules/git/gitcmd/command_test.go b/modules/git/gitcmd/command_test.go index 662356bc3f..6e4214d995 100644 --- a/modules/git/gitcmd/command_test.go +++ b/modules/git/gitcmd/command_test.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "os" + "strings" "testing" "time" @@ -49,9 +50,11 @@ func TestRunWithContextStd(t *testing.T) { stdout, stderr, err := cmd.RunStdString(t.Context()) if assert.Error(t, err) { assert.Equal(t, stderr, err.Stderr()) - assert.Equal(t, "fatal: Not a valid object name no-such\n", err.Stderr()) + stderrLower := strings.ToLower(stderr) // see: IsStdErrorNotValidObjectName + assert.Equal(t, "fatal: not a valid object name no-such\n", stderrLower) // FIXME: GIT-CMD-STDERR: it is a bad design, the stderr should not be put in the error message - assert.Equal(t, "exit status 128 - fatal: Not a valid object name no-such", err.Error()) + errLower := strings.ToLower(err.Error()) + assert.Equal(t, "exit status 128 - fatal: not a valid object name no-such", errLower) assert.Empty(t, stdout) } } @@ -61,9 +64,11 @@ func TestRunWithContextStd(t *testing.T) { stdout, stderr, err := cmd.RunStdBytes(t.Context()) if assert.Error(t, err) { assert.Equal(t, string(stderr), err.Stderr()) - assert.Equal(t, "fatal: Not a valid object name no-such\n", err.Stderr()) + stderrLower := strings.ToLower(err.Stderr()) // see: IsStdErrorNotValidObjectName + assert.Equal(t, "fatal: not a valid object name no-such\n", stderrLower) // FIXME: GIT-CMD-STDERR: it is a bad design, the stderr should not be put in the error message - assert.Equal(t, "exit status 128 - fatal: Not a valid object name no-such", err.Error()) + errLower := strings.ToLower(err.Error()) + assert.Equal(t, "exit status 128 - fatal: not a valid object name no-such", errLower) assert.Empty(t, stdout) } } diff --git a/modules/git/gitcmd/error.go b/modules/git/gitcmd/error.go index 066b37f10d..b674068c40 100644 --- a/modules/git/gitcmd/error.go +++ b/modules/git/gitcmd/error.go @@ -77,6 +77,13 @@ func IsErrorCanceledOrKilled(err error) bool { return errors.Is(err, context.Canceled) || IsErrorSignalKilled(err) } +func IsStdErrorNotValidObjectName(err error) 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") +} + type pipelineError struct { error } diff --git a/modules/git/tree_nogogit.go b/modules/git/tree_nogogit.go index d50c1ad629..5d951dad0d 100644 --- a/modules/git/tree_nogogit.go +++ b/modules/git/tree_nogogit.go @@ -65,7 +65,7 @@ func (t *Tree) ListEntries() (Entries, error) { stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).WithDir(t.repo.Path).RunStdBytes(t.repo.Ctx) if runErr != nil { - if strings.Contains(runErr.Error(), "fatal: Not a valid object name") || strings.Contains(runErr.Error(), "fatal: not a tree object") { + if gitcmd.IsStdErrorNotValidObjectName(runErr) || strings.Contains(runErr.Error(), "fatal: not a tree object") { return nil, ErrNotExist{ ID: t.ID.String(), } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index d306927001..0578ab540f 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -282,7 +282,7 @@ func prepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue) compareInfo, err := git_service.GetCompareInfo(ctx, ctx.Repo.Repository, ctx.Repo.Repository, ctx.Repo.GitRepo, git.RefName(baseCommit), git.RefName(pull.GetGitHeadRefName()), false, false) if err != nil { - if strings.Contains(err.Error(), "fatal: Not a valid object name") || strings.Contains(err.Error(), "unknown revision or path not in the working tree") { + if gitcmd.IsStdErrorNotValidObjectName(err) || strings.Contains(err.Error(), "unknown revision or path not in the working tree") { ctx.Data["IsPullRequestBroken"] = true ctx.Data["BaseTarget"] = pull.BaseBranch ctx.Data["NumCommits"] = 0 @@ -442,7 +442,7 @@ func prepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git_s compareInfo, err := git_service.GetCompareInfo(ctx, pull.BaseRepo, pull.BaseRepo, baseGitRepo, git.RefName(pull.MergeBase), git.RefName(pull.GetGitHeadRefName()), false, false) if err != nil { - if strings.Contains(err.Error(), "fatal: Not a valid object name") { + if gitcmd.IsStdErrorNotValidObjectName(err) { ctx.Data["IsPullRequestBroken"] = true ctx.Data["BaseTarget"] = pull.BaseBranch ctx.Data["NumCommits"] = 0 @@ -584,7 +584,7 @@ func prepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git_s compareInfo, err := git_service.GetCompareInfo(ctx, pull.BaseRepo, pull.BaseRepo, baseGitRepo, git.RefNameFromBranch(pull.BaseBranch), git.RefName(pull.GetGitHeadRefName()), false, false) if err != nil { - if strings.Contains(err.Error(), "fatal: Not a valid object name") { + if gitcmd.IsStdErrorNotValidObjectName(err) { ctx.Data["IsPullRequestBroken"] = true ctx.Data["BaseTarget"] = pull.BaseBranch ctx.Data["NumCommits"] = 0 diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index a025f26051..5bc62d451e 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -8,7 +8,6 @@ import ( "context" "fmt" "os" - "strings" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" @@ -16,6 +15,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/graceful" @@ -59,7 +59,7 @@ func prepareGitPath(gitRepo *git.Repository, defaultWikiBranch string, wikiPath // Look for both files filesInIndex, err := gitRepo.LsTree(defaultWikiBranch, unescaped, gitPath) if err != nil { - if strings.Contains(err.Error(), "Not a valid object name") { + if gitcmd.IsStdErrorNotValidObjectName(err) { return false, gitPath, nil // branch doesn't exist } log.Error("Wiki LsTree failed, err: %v", err)