From 286959cdb388b5371c4f48ef512a5637b8679657 Mon Sep 17 00:00:00 2001 From: Josh Deprez Date: Tue, 18 Jul 2023 16:04:08 +1000 Subject: [PATCH] Clean-retry on "fatal: bad object" --- internal/job/executor.go | 3 ++- internal/job/git.go | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/job/executor.go b/internal/job/executor.go index 47bba96981..a841fa4f6d 100644 --- a/internal/job/executor.go +++ b/internal/job/executor.go @@ -1166,7 +1166,8 @@ func (e *Executor) CheckoutPhase(ctx context.Context) error { switch ge.Type { // These types can fail because of corrupted checkouts case gitErrorClean, gitErrorCleanSubmodules, gitErrorClone, - gitErrorCheckoutRetryClean, gitErrorFetchRetryClean: + gitErrorCheckoutRetryClean, gitErrorFetchRetryClean, + gitErrorFetchBadObject: // Otherwise, don't clean the checkout dir default: return err diff --git a/internal/job/git.go b/internal/job/git.go index 83a9d24d18..303496eae0 100644 --- a/internal/job/git.go +++ b/internal/job/git.go @@ -23,6 +23,7 @@ const ( gitErrorClone gitErrorFetch gitErrorFetchRetryClean + gitErrorFetchBadObject gitErrorClean gitErrorCleanSubmodules ) @@ -139,6 +140,16 @@ func gitFetch(ctx context.Context, sh shellRunner, gitFetchFlags, repository str } if err := sh.Run(ctx, "git", commandArgs...); err != nil { + // "fatal: bad object" can happen when the local repo in the checkout + // directory is corrupted, not just the remote or the mirror. + // When using git mirrors, the existing checkout directory might have a + // reference to an object that it expects in the mirror, but the mirror + // no longer contains it (for whatever reason). + // See the NOTE under --shared at https://git-scm.com/docs/git-clone. + if strings.HasPrefix(err.Error(), "fatal: bad object") { + return &gitError{error: err, Type: gitErrorFetchBadObject} + } + // 128 is extremely broad, but it seems permissions errors, network unreachable errors etc, don't result in it if exitErr := new(exec.ExitError); errors.As(err, &exitErr) && exitErr.ExitCode() == 128 { return &gitError{error: err, Type: gitErrorFetchRetryClean}