From ee997bb0041a99bc569cb9cd4a4c273721bd60ce Mon Sep 17 00:00:00 2001 From: Jason Song Date: Thu, 25 Jul 2024 17:13:26 +0800 Subject: [PATCH 1/2] feat: lfs object error --- modules/lfs/http_client.go | 7 +++---- modules/lfs/shared.go | 35 ++++++++++++++++++++++++++++++++++ modules/repository/repo.go | 5 +++++ services/repository/migrate.go | 1 + 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/modules/lfs/http_client.go b/modules/lfs/http_client.go index 7ee2449b0ec4..4859fe61e1db 100644 --- a/modules/lfs/http_client.go +++ b/modules/lfs/http_client.go @@ -136,14 +136,13 @@ func (c *HTTPClient) performOperation(ctx context.Context, objects []Pointer, dc for _, object := range result.Objects { if object.Error != nil { - objectError := errors.New(object.Error.Message) - log.Trace("Error on object %v: %v", object.Pointer, objectError) + log.Trace("Error on object %v: %v", object.Pointer, object.Error) if uc != nil { - if _, err := uc(object.Pointer, objectError); err != nil { + if _, err := uc(object.Pointer, object.Error); err != nil { return err } } else { - if err := dc(object.Pointer, nil, objectError); err != nil { + if err := dc(object.Pointer, nil, object.Error); err != nil { return err } } diff --git a/modules/lfs/shared.go b/modules/lfs/shared.go index 675d2328b7d1..2fc9f4adf929 100644 --- a/modules/lfs/shared.go +++ b/modules/lfs/shared.go @@ -4,6 +4,8 @@ package lfs import ( + "errors" + "fmt" "time" ) @@ -64,6 +66,39 @@ type ObjectError struct { Message string `json:"message"` } +var ( + // See https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md#successful-responses + // LFS object error codes should match HTTP status codes where possible: + // 404 - The object does not exist on the server. + // 409 - The specified hash algorithm disagrees with the server's acceptable options. + // 410 - The object was removed by the owner. + // 422 - Validation error. + + ErrObjectNotFound = errors.New("the object does not exist on the server") + ErrObjectHashMismatch = errors.New("the specified hash algorithm disagrees with the server's acceptable options") + ErrObjectRemoved = errors.New("the object was removed by the owner") + ErrObjectValidation = errors.New("validation error") +) + +func (e *ObjectError) Error() string { + return fmt.Sprintf("[%d] %s", e.Code, e.Message) +} + +func (e *ObjectError) Unwrap() error { + switch e.Code { + case 404: + return ErrObjectNotFound + case 409: + return ErrObjectHashMismatch + case 410: + return ErrObjectRemoved + case 422: + return ErrObjectValidation + default: + return errors.New(e.Message) + } +} + // PointerBlob associates a Git blob with a Pointer. type PointerBlob struct { Hash string diff --git a/modules/repository/repo.go b/modules/repository/repo.go index cb926084baae..9ba94e14011c 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -5,6 +5,7 @@ package repository import ( "context" + "errors" "fmt" "io" "strings" @@ -181,6 +182,10 @@ func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Re downloadObjects := func(pointers []lfs.Pointer) error { err := lfsClient.Download(ctx, pointers, func(p lfs.Pointer, content io.ReadCloser, objectError error) error { if objectError != nil { + if errors.Is(objectError, lfs.ErrObjectNotFound) { + log.Warn("Repo[%-v]: Ignore missing LFS object %-v: %v", repo, p, objectError) + return nil + } return objectError } diff --git a/services/repository/migrate.go b/services/repository/migrate.go index df5cc67ae1cd..2e901791b4ad 100644 --- a/services/repository/migrate.go +++ b/services/repository/migrate.go @@ -169,6 +169,7 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, lfsClient := lfs.NewClient(endpoint, httpTransport) if err = repo_module.StoreMissingLfsObjectsInRepository(ctx, repo, gitRepo, lfsClient); err != nil { log.Error("Failed to store missing LFS objects for repository: %v", err) + return repo, fmt.Errorf("StoreMissingLfsObjectsInRepository: %w", err) } } } From 7ebf151258e14af260136722195fe0fe9059ad71 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Fri, 26 Jul 2024 10:21:38 +0800 Subject: [PATCH 2/2] fix: ErrObjectNotExist --- modules/lfs/shared.go | 6 ++++-- modules/repository/repo.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/lfs/shared.go b/modules/lfs/shared.go index 2fc9f4adf929..a4326b57b2f5 100644 --- a/modules/lfs/shared.go +++ b/modules/lfs/shared.go @@ -7,6 +7,8 @@ import ( "errors" "fmt" "time" + + "code.gitea.io/gitea/modules/util" ) const ( @@ -74,7 +76,7 @@ var ( // 410 - The object was removed by the owner. // 422 - Validation error. - ErrObjectNotFound = errors.New("the object does not exist on the server") + ErrObjectNotExist = util.ErrNotExist // the object does not exist on the server ErrObjectHashMismatch = errors.New("the specified hash algorithm disagrees with the server's acceptable options") ErrObjectRemoved = errors.New("the object was removed by the owner") ErrObjectValidation = errors.New("validation error") @@ -87,7 +89,7 @@ func (e *ObjectError) Error() string { func (e *ObjectError) Unwrap() error { switch e.Code { case 404: - return ErrObjectNotFound + return ErrObjectNotExist case 409: return ErrObjectHashMismatch case 410: diff --git a/modules/repository/repo.go b/modules/repository/repo.go index 9ba94e14011c..3d1899b2fe00 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -182,7 +182,7 @@ func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Re downloadObjects := func(pointers []lfs.Pointer) error { err := lfsClient.Download(ctx, pointers, func(p lfs.Pointer, content io.ReadCloser, objectError error) error { if objectError != nil { - if errors.Is(objectError, lfs.ErrObjectNotFound) { + if errors.Is(objectError, lfs.ErrObjectNotExist) { log.Warn("Repo[%-v]: Ignore missing LFS object %-v: %v", repo, p, objectError) return nil }