fix: restore missing blob file when re-publishing a package (#39239)

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Huang-404-Q
2026-09-05 10:33:36 +02:00
committed by GitHub
co-authored by wxiaoguang
parent e4455fb494
commit efa69e7230
10 changed files with 145 additions and 76 deletions
+1 -21
View File
@@ -8,7 +8,6 @@ import (
"encoding/hex"
"errors"
"fmt"
"os"
"strings"
"gitea.dev/models/db"
@@ -18,7 +17,6 @@ import (
"gitea.dev/modules/log"
packages_module "gitea.dev/modules/packages"
container_module "gitea.dev/modules/packages/container"
"gitea.dev/modules/util"
packages_service "gitea.dev/services/packages"
"github.com/opencontainers/go-digest"
@@ -51,28 +49,10 @@ func saveAsPackageBlobInternal(ctx context.Context, hsr packages_module.HashedSi
if err := packages_service.CheckSizeQuotaExceeded(ctx, pci.Creator, pci.Owner, packages_model.TypeContainer, hsr.Size()); err != nil {
return err
}
pb, exists, err = packages_model.GetOrInsertBlob(ctx, pb)
pb, exists, err = packages_service.GetOrSavePackageBlob(ctx, contentStore, pb, hsr)
if err != nil {
log.Error("Error inserting package blob: %v", err)
return err
}
// FIXME: Workaround to be removed in v1.20
// https://github.com/go-gitea/gitea/issues/19586
if exists {
err = contentStore.Has(packages_module.BlobHash256Key(pb.HashSHA256))
if err != nil && (errors.Is(err, util.ErrNotExist) || errors.Is(err, os.ErrNotExist)) {
log.Debug("Package registry inconsistent: blob %s does not exist on file system", pb.HashSHA256)
exists = false
}
}
if !exists {
if err := contentStore.Save(packages_module.BlobHash256Key(pb.HashSHA256), hsr, hsr.Size()); err != nil {
log.Error("Error saving package blob in content store: %v", err)
return err
}
}
return createFileForBlob(ctx, uploadVersion, pb)
})
if err != nil {
+11 -16
View File
@@ -9,7 +9,6 @@ import (
"io"
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"
@@ -28,7 +27,6 @@ import (
"gitea.dev/modules/setting"
"gitea.dev/modules/storage"
"gitea.dev/modules/structs"
"gitea.dev/modules/util"
"gitea.dev/routers/api/packages/helper"
auth_service "gitea.dev/services/auth"
"gitea.dev/services/context"
@@ -250,7 +248,7 @@ func PostBlobsUploads(ctx *context.Context) {
mount := ctx.FormTrim("mount")
from := ctx.FormTrim("from")
if mount != "" {
blob, _ := workaroundGetContainerBlob(ctx, &container_model.BlobSearchOptions{
blob, _ := getExistingContainerBlob(ctx, &container_model.BlobSearchOptions{
Repository: from,
Digest: mount,
})
@@ -506,7 +504,7 @@ func getBlobFromContext(ctx *context.Context) (*packages_model.PackageFileDescri
return nil, container_model.ErrContainerBlobNotExist
}
return workaroundGetContainerBlob(ctx, &container_model.BlobSearchOptions{
return getExistingContainerBlob(ctx, &container_model.BlobSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Image: ctx.PathParam("image"),
Digest: string(d),
@@ -643,7 +641,7 @@ func getManifestFromContext(ctx *context.Context) (*packages_model.PackageFileDe
return nil, err
}
return workaroundGetContainerBlob(ctx, opts)
return getExistingContainerBlob(ctx, opts)
}
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#checking-if-content-exists-in-the-registry
@@ -789,23 +787,20 @@ func GetTagsList(ctx *context.Context) {
})
}
// FIXME: Workaround to be removed in v1.20.
// Update maybe we should never really remote it, as long as there is legacy data?
// https://github.com/go-gitea/gitea/issues/19586
func workaroundGetContainerBlob(ctx *context.Context, opts *container_model.BlobSearchOptions) (*packages_model.PackageFileDescriptor, error) {
// getExistingContainerBlob checks if the blob exists in the database and content store, and returns the package file descriptor if it does.
func getExistingContainerBlob(ctx *context.Context, opts *container_model.BlobSearchOptions) (*packages_model.PackageFileDescriptor, error) {
blob, err := container_model.GetContainerBlob(ctx, opts)
if err != nil {
return nil, err
}
err = packages_module.NewContentStore().Has(packages_module.BlobHash256Key(blob.Blob.HashSHA256))
storeKey := packages_module.BlobHash256Key(blob.Blob.HashSHA256)
sz, err := packages_module.NewContentStore().OptionalSize(storeKey)
if err != nil {
if errors.Is(err, util.ErrNotExist) || errors.Is(err, os.ErrNotExist) {
log.Debug("Package registry inconsistent: blob %s does not exist on file system", blob.Blob.HashSHA256)
return nil, container_model.ErrContainerBlobNotExist
}
return nil, err
return nil, fmt.Errorf("unable to check object size in content store: %w", err)
}
if sz.ValueOrDefault(-1) != blob.Blob.Size {
return nil, container_model.ErrContainerBlobNotExist
}
return blob, nil
}
+1 -19
View File
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"io"
"os"
"strings"
"gitea.dev/models/db"
@@ -20,7 +19,6 @@ import (
"gitea.dev/modules/log"
packages_module "gitea.dev/modules/packages"
container_module "gitea.dev/modules/packages/container"
"gitea.dev/modules/util"
notify_service "gitea.dev/services/notify"
packages_service "gitea.dev/services/packages"
container_service "gitea.dev/services/packages/container"
@@ -379,26 +377,10 @@ func createFileFromBlobReference(ctx context.Context, pv, uploadVersion *package
}
func createManifestBlob(ctx context.Context, contentStore *packages_module.ContentStore, mci *manifestCreationInfo, pv *packages_model.PackageVersion, buf *packages_module.HashedBuffer) (_ *packages_model.PackageBlob, created bool, manifestDigest string, _ error) {
pb, exists, err := packages_model.GetOrInsertBlob(ctx, packages_service.NewPackageBlob(buf))
pb, exists, err := packages_service.GetOrSavePackageBlob(ctx, contentStore, packages_service.NewPackageBlob(buf), buf)
if err != nil {
log.Error("Error inserting package blob: %v", err)
return nil, false, "", err
}
// FIXME: Workaround to be removed in v1.20
// https://github.com/go-gitea/gitea/issues/19586
if exists {
err = contentStore.Has(packages_module.BlobHash256Key(pb.HashSHA256))
if err != nil && (errors.Is(err, util.ErrNotExist) || errors.Is(err, os.ErrNotExist)) {
log.Debug("Package registry inconsistent: blob %s does not exist on file system", pb.HashSHA256)
exists = false
}
}
if !exists {
if err := contentStore.Save(packages_module.BlobHash256Key(pb.HashSHA256), buf, buf.Size()); err != nil {
log.Error("Error saving package blob in content store: %v", err)
return nil, false, "", err
}
}
manifestDigest = digestFromHashSummer(buf)
pf, err := createFileFromBlobReference(ctx, pv, nil, &blobReference{