Package registry changes (#19305)

* removed debug logs
* fixed SELECT
* removed unneeded error type
* use common SearchVersions method
* remove empty container upload versions
* return err
This commit is contained in:
KN4CK3R 2022-04-06 03:32:09 +02:00 committed by GitHub
parent 8ddcd37f13
commit 5e242e021b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 185 additions and 150 deletions

View file

@ -9,11 +9,15 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"testing" "testing"
"time"
"code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
container_model "code.gitea.io/gitea/models/packages/container"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
packages_service "code.gitea.io/gitea/services/packages"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -43,7 +47,7 @@ func TestPackageAPI(t *testing.T) {
DecodeJSON(t, resp, &apiPackages) DecodeJSON(t, resp, &apiPackages)
assert.Len(t, apiPackages, 1) assert.Len(t, apiPackages, 1)
assert.Equal(t, string(packages.TypeGeneric), apiPackages[0].Type) assert.Equal(t, string(packages_model.TypeGeneric), apiPackages[0].Type)
assert.Equal(t, packageName, apiPackages[0].Name) assert.Equal(t, packageName, apiPackages[0].Name)
assert.Equal(t, packageVersion, apiPackages[0].Version) assert.Equal(t, packageVersion, apiPackages[0].Version)
assert.NotNil(t, apiPackages[0].Creator) assert.NotNil(t, apiPackages[0].Creator)
@ -62,7 +66,7 @@ func TestPackageAPI(t *testing.T) {
var p *api.Package var p *api.Package
DecodeJSON(t, resp, &p) DecodeJSON(t, resp, &p)
assert.Equal(t, string(packages.TypeGeneric), p.Type) assert.Equal(t, string(packages_model.TypeGeneric), p.Type)
assert.Equal(t, packageName, p.Name) assert.Equal(t, packageName, p.Name)
assert.Equal(t, packageVersion, p.Version) assert.Equal(t, packageVersion, p.Version)
assert.NotNil(t, p.Creator) assert.NotNil(t, p.Creator)
@ -100,3 +104,26 @@ func TestPackageAPI(t *testing.T) {
MakeRequest(t, req, http.StatusNoContent) MakeRequest(t, req, http.StatusNoContent)
}) })
} }
func TestPackageCleanup(t *testing.T) {
defer prepareTestEnv(t)()
time.Sleep(time.Second)
pbs, err := packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0))
assert.NoError(t, err)
assert.NotEmpty(t, pbs)
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion)
assert.NoError(t, err)
err = packages_service.Cleanup(nil, time.Duration(0))
assert.NoError(t, err)
pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0))
assert.NoError(t, err)
assert.Empty(t, pbs)
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion)
assert.ErrorIs(t, err, packages_model.ErrPackageNotExist)
}

View file

@ -65,14 +65,14 @@ func findPropertyValues(ctx context.Context, propertyName string, ownerID int64,
in2 := builder. in2 := builder.
Select("package_file.id"). Select("package_file.id").
From("package_file"). From("package_file").
Join("INNER", "package_version", "package_version.id = package_file.version_id"). InnerJoin("package_version", "package_version.id = package_file.version_id").
Join("INNER", "package", "package.id = package_version.package_id"). InnerJoin("package", "package.id = package_version.package_id").
Where(cond) Where(cond)
query := builder. query := builder.
Select("package_property.value, MAX(package_file.created_unix) AS created_unix"). Select("package_property.value, MAX(package_file.created_unix) AS created_unix").
From("package_property"). From("package_property").
Join("INNER", "package_file", "package_file.id = package_property.ref_id"). InnerJoin("package_file", "package_file.id = package_property.ref_id").
Where(builder.Eq{"package_property.name": propertyName}.And(builder.In("package_property.ref_id", in2))). Where(builder.Eq{"package_property.name": propertyName}.And(builder.In("package_property.ref_id", in2))).
GroupBy("package_property.value"). GroupBy("package_property.value").
OrderBy("created_unix DESC") OrderBy("created_unix DESC")

View file

@ -74,8 +74,8 @@ func SearchRecipes(ctx context.Context, opts *RecipeSearchOptions) ([]string, er
query := builder. query := builder.
Select("package.name, package_version.version, package_file.id"). Select("package.name, package_version.version, package_file.id").
From("package_file"). From("package_file").
Join("INNER", "package_version", "package_version.id = package_file.version_id"). InnerJoin("package_version", "package_version.id = package_file.version_id").
Join("INNER", "package", "package.id = package_version.package_id"). InnerJoin("package", "package.id = package_version.package_id").
Where(cond) Where(cond)
results := make([]struct { results := make([]struct {

View file

@ -190,13 +190,15 @@ func GetPackagesByType(ctx context.Context, ownerID int64, packageType Type) ([]
// DeletePackagesIfUnreferenced deletes a package if there are no associated versions // DeletePackagesIfUnreferenced deletes a package if there are no associated versions
func DeletePackagesIfUnreferenced(ctx context.Context) error { func DeletePackagesIfUnreferenced(ctx context.Context) error {
in := builder. in := builder.
Select("package_version.package_id"). Select("package.id").
From("package"). From("package").
Join("LEFT", "package_version", "package_version.package_id = package.id"). LeftJoin("package_version", "package_version.package_id = package.id").
Where(builder.Expr("package_version.id IS NULL")) Where(builder.Expr("package_version.id IS NULL"))
_, err := db.GetEngine(ctx). _, err := db.GetEngine(ctx).
Where(builder.In("package.id", in)). // double select workaround for MySQL
// https://stackoverflow.com/questions/4471277/mysql-delete-from-with-subquery-as-condition
Where(builder.In("package.id", builder.Select("id").From(in, "temp"))).
Delete(&Package{}) Delete(&Package{})
return err return err

View file

@ -67,7 +67,7 @@ func FindExpiredUnreferencedBlobs(ctx context.Context, olderThan time.Duration)
pbs := make([]*PackageBlob, 0, 10) pbs := make([]*PackageBlob, 0, 10)
return pbs, db.GetEngine(ctx). return pbs, db.GetEngine(ctx).
Table("package_blob"). Table("package_blob").
Join("LEFT OUTER", "package_file", "package_file.blob_id = package_blob.id"). Join("LEFT", "package_file", "package_file.blob_id = package_blob.id").
Where("package_file.id IS NULL AND package_blob.created_unix < ?", time.Now().Add(-olderThan).Unix()). Where("package_file.id IS NULL AND package_blob.created_unix < ?", time.Now().Add(-olderThan).Unix()).
Find(&pbs) Find(&pbs)
} }

View file

@ -147,7 +147,7 @@ func (opts *PackageFileSearchOptions) toConds() builder.Cond {
in := builder. in := builder.
Select("package_version.id"). Select("package_version.id").
From("package_version"). From("package_version").
Join("INNER", "package", "package.id = package_version.package_id"). InnerJoin("package", "package.id = package_version.package_id").
Where(versionCond) Where(versionCond)
cond = cond.And(builder.In("package_file.version_id", in)) cond = cond.And(builder.In("package_file.version_id", in))

View file

@ -12,16 +12,13 @@ import (
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"xorm.io/builder" "xorm.io/builder"
) )
var ( // ErrDuplicatePackageVersion indicates a duplicated package version error
// ErrDuplicatePackageVersion indicates a duplicated package version error var ErrDuplicatePackageVersion = errors.New("Package version already exists")
ErrDuplicatePackageVersion = errors.New("Package version does exist already")
// ErrPackageVersionNotExist indicates a package version not exist error
ErrPackageVersionNotExist = errors.New("Package version does not exist")
)
func init() { func init() {
db.RegisterModel(new(PackageVersion)) db.RegisterModel(new(PackageVersion))
@ -99,75 +96,49 @@ func GetInternalVersionByNameAndVersion(ctx context.Context, ownerID int64, pack
} }
func getVersionByNameAndVersion(ctx context.Context, ownerID int64, packageType Type, name, version string, isInternal bool) (*PackageVersion, error) { func getVersionByNameAndVersion(ctx context.Context, ownerID int64, packageType Type, name, version string, isInternal bool) (*PackageVersion, error) {
var cond builder.Cond = builder.Eq{ pvs, _, err := SearchVersions(ctx, &PackageSearchOptions{
"package.owner_id": ownerID, OwnerID: ownerID,
"package.type": packageType, Type: packageType,
"package.lower_name": strings.ToLower(name), Name: SearchValue{
"package_version.is_internal": isInternal, ExactMatch: true,
} Value: name,
pv := &PackageVersion{ },
LowerVersion: strings.ToLower(version), Version: SearchValue{
} ExactMatch: true,
has, err := db.GetEngine(ctx). Value: version,
Join("INNER", "package", "package.id = package_version.package_id"). },
Where(cond). IsInternal: isInternal,
Get(pv) Paginator: db.NewAbsoluteListOptions(0, 1),
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
if !has { if len(pvs) == 0 {
return nil, ErrPackageNotExist return nil, ErrPackageNotExist
} }
return pvs[0], nil
return pv, nil
} }
// GetVersionsByPackageType gets all versions of a specific type // GetVersionsByPackageType gets all versions of a specific type
func GetVersionsByPackageType(ctx context.Context, ownerID int64, packageType Type) ([]*PackageVersion, error) { func GetVersionsByPackageType(ctx context.Context, ownerID int64, packageType Type) ([]*PackageVersion, error) {
var cond builder.Cond = builder.Eq{ pvs, _, err := SearchVersions(ctx, &PackageSearchOptions{
"package.owner_id": ownerID, OwnerID: ownerID,
"package.type": packageType, Type: packageType,
"package_version.is_internal": false, })
} return pvs, err
pvs := make([]*PackageVersion, 0, 10)
return pvs, db.GetEngine(ctx).
Where(cond).
Join("INNER", "package", "package.id = package_version.package_id").
Find(&pvs)
} }
// GetVersionsByPackageName gets all versions of a specific package // GetVersionsByPackageName gets all versions of a specific package
func GetVersionsByPackageName(ctx context.Context, ownerID int64, packageType Type, name string) ([]*PackageVersion, error) { func GetVersionsByPackageName(ctx context.Context, ownerID int64, packageType Type, name string) ([]*PackageVersion, error) {
var cond builder.Cond = builder.Eq{ pvs, _, err := SearchVersions(ctx, &PackageSearchOptions{
"package.owner_id": ownerID, OwnerID: ownerID,
"package.type": packageType, Type: packageType,
"package.lower_name": strings.ToLower(name), Name: SearchValue{
"package_version.is_internal": false, ExactMatch: true,
} Value: name,
},
pvs := make([]*PackageVersion, 0, 10) })
return pvs, db.GetEngine(ctx). return pvs, err
Where(cond).
Join("INNER", "package", "package.id = package_version.package_id").
Find(&pvs)
}
// GetVersionsByFilename gets all versions which are linked to a filename
func GetVersionsByFilename(ctx context.Context, ownerID int64, packageType Type, filename string) ([]*PackageVersion, error) {
var cond builder.Cond = builder.Eq{
"package.owner_id": ownerID,
"package.type": packageType,
"package_file.lower_name": strings.ToLower(filename),
"package_version.is_internal": false,
}
pvs := make([]*PackageVersion, 0, 10)
return pvs, db.GetEngine(ctx).
Where(cond).
Join("INNER", "package_file", "package_file.version_id = package_version.id").
Join("INNER", "package", "package.id = package_version.package_id").
Find(&pvs)
} }
// DeleteVersionByID deletes a version by id // DeleteVersionByID deletes a version by id
@ -183,21 +154,32 @@ func HasVersionFileReferences(ctx context.Context, versionID int64) (bool, error
}) })
} }
// SearchValue describes a value to search
// If ExactMatch is true, the field must match the value otherwise a LIKE search is performed.
type SearchValue struct {
Value string
ExactMatch bool
}
// PackageSearchOptions are options for SearchXXX methods // PackageSearchOptions are options for SearchXXX methods
// Besides IsInternal are all fields optional and are not used if they have their default value (nil, "", 0)
type PackageSearchOptions struct { type PackageSearchOptions struct {
OwnerID int64 OwnerID int64
RepoID int64 RepoID int64
Type string Type Type
PackageID int64 PackageID int64
QueryName string Name SearchValue // only results with the specific name are found
QueryVersion string Version SearchValue // only results with the specific version are found
Properties map[string]string Properties map[string]string // only results are found which contain all listed version properties with the specific value
IsInternal bool
HasFileWithName string // only results are found which are associated with a file with the specific name
HasFiles util.OptionalBool // only results are found which have associated files
Sort string Sort string
db.Paginator db.Paginator
} }
func (opts *PackageSearchOptions) toConds() builder.Cond { func (opts *PackageSearchOptions) toConds() builder.Cond {
var cond builder.Cond = builder.Eq{"package_version.is_internal": false} var cond builder.Cond = builder.Eq{"package_version.is_internal": opts.IsInternal}
if opts.OwnerID != 0 { if opts.OwnerID != 0 {
cond = cond.And(builder.Eq{"package.owner_id": opts.OwnerID}) cond = cond.And(builder.Eq{"package.owner_id": opts.OwnerID})
@ -211,11 +193,19 @@ func (opts *PackageSearchOptions) toConds() builder.Cond {
if opts.PackageID != 0 { if opts.PackageID != 0 {
cond = cond.And(builder.Eq{"package.id": opts.PackageID}) cond = cond.And(builder.Eq{"package.id": opts.PackageID})
} }
if opts.QueryName != "" { if opts.Name.Value != "" {
cond = cond.And(builder.Like{"package.lower_name", strings.ToLower(opts.QueryName)}) if opts.Name.ExactMatch {
cond = cond.And(builder.Eq{"package.lower_name": strings.ToLower(opts.Name.Value)})
} else {
cond = cond.And(builder.Like{"package.lower_name", strings.ToLower(opts.Name.Value)})
}
}
if opts.Version.Value != "" {
if opts.Version.ExactMatch {
cond = cond.And(builder.Eq{"package_version.lower_version": strings.ToLower(opts.Version.Value)})
} else {
cond = cond.And(builder.Like{"package_version.lower_version", strings.ToLower(opts.Version.Value)})
} }
if opts.QueryVersion != "" {
cond = cond.And(builder.Like{"package_version.lower_version", strings.ToLower(opts.QueryVersion)})
} }
if len(opts.Properties) != 0 { if len(opts.Properties) != 0 {
@ -238,6 +228,22 @@ func (opts *PackageSearchOptions) toConds() builder.Cond {
}) })
} }
if opts.HasFileWithName != "" {
fileCond := builder.Expr("package_file.version_id = package_version.id").And(builder.Eq{"package_file.lower_name": strings.ToLower(opts.HasFileWithName)})
cond = cond.And(builder.Exists(builder.Select("package_file.id").From("package_file").Where(fileCond)))
}
if !opts.HasFiles.IsNone() {
var filesCond builder.Cond = builder.Exists(builder.Select("package_file.id").From("package_file").Where(builder.Expr("package_file.version_id = package_version.id")))
if opts.HasFiles.IsFalse() {
filesCond = builder.Not{filesCond}
}
cond = cond.And(filesCond)
}
return cond return cond
} }
@ -297,20 +303,3 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P
count, err := sess.FindAndCount(&pvs) count, err := sess.FindAndCount(&pvs)
return pvs, count, err return pvs, count, err
} }
// FindVersionsByPropertyNameAndValue gets all package versions which are associated with a specific property + value
func FindVersionsByPropertyNameAndValue(ctx context.Context, packageID int64, name, value string) ([]*PackageVersion, error) {
var cond builder.Cond = builder.Eq{
"package_property.ref_type": PropertyTypeVersion,
"package_property.name": name,
"package_property.value": value,
"package_version.package_id": packageID,
"package_version.is_internal": false,
}
pvs := make([]*PackageVersion, 0, 5)
return pvs, db.GetEngine(ctx).
Where(cond).
Join("INNER", "package_property", "package_property.ref_id = package_version.id").
Find(&pvs)
}

View file

@ -63,8 +63,8 @@ func SearchPackages(ctx *context.Context) {
opts := &packages_model.PackageSearchOptions{ opts := &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID, OwnerID: ctx.Package.Owner.ID,
Type: string(packages_model.TypeComposer), Type: packages_model.TypeComposer,
QueryName: ctx.FormTrim("q"), Name: packages_model.SearchValue{Value: ctx.FormTrim("q")},
Paginator: &paginator, Paginator: &paginator,
} }
if ctx.FormTrim("type") != "" { if ctx.FormTrim("type") != "" {

View file

@ -256,7 +256,12 @@ func setPackageTag(tag string, pv *packages_model.PackageVersion, deleteOnly boo
} }
defer committer.Close() defer committer.Close()
pvs, err := packages_model.FindVersionsByPropertyNameAndValue(ctx, pv.PackageID, npm_module.TagProperty, tag) pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
PackageID: pv.PackageID,
Properties: map[string]string{
npm_module.TagProperty: tag,
},
})
if err != nil { if err != nil {
return err return err
} }

View file

@ -40,8 +40,8 @@ func ServiceIndex(ctx *context.Context) {
func SearchService(ctx *context.Context) { func SearchService(ctx *context.Context) {
pvs, count, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ pvs, count, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID, OwnerID: ctx.Package.Owner.ID,
Type: string(packages_model.TypeNuGet), Type: packages_model.TypeNuGet,
QueryName: ctx.FormTrim("q"), Name: packages_model.SearchValue{Value: ctx.FormTrim("q")},
Paginator: db.NewAbsoluteListOptions( Paginator: db.NewAbsoluteListOptions(
ctx.FormInt("skip"), ctx.FormInt("skip"),
ctx.FormInt("take"), ctx.FormInt("take"),

View file

@ -41,7 +41,7 @@ func EnumeratePackages(ctx *context.Context) {
func EnumeratePackagesLatest(ctx *context.Context) { func EnumeratePackagesLatest(ctx *context.Context) {
pvs, _, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{ pvs, _, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID, OwnerID: ctx.Package.Owner.ID,
Type: string(packages_model.TypeRubyGems), Type: packages_model.TypeRubyGems,
}) })
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
@ -96,7 +96,7 @@ func ServePackageSpecification(ctx *context.Context) {
return return
} }
pvs, err := packages_model.GetVersionsByFilename(ctx, ctx.Package.Owner.ID, packages_model.TypeRubyGems, filename[:len(filename)-10]+"gem") pvs, err := getVersionsByFilename(ctx, filename[:len(filename)-10]+"gem")
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
return return
@ -158,7 +158,7 @@ func ServePackageSpecification(ctx *context.Context) {
func DownloadPackageFile(ctx *context.Context) { func DownloadPackageFile(ctx *context.Context) {
filename := ctx.Params("filename") filename := ctx.Params("filename")
pvs, err := packages_model.GetVersionsByFilename(ctx, ctx.Package.Owner.ID, packages_model.TypeRubyGems, filename) pvs, err := getVersionsByFilename(ctx, filename)
if err != nil { if err != nil {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
return return
@ -283,3 +283,12 @@ func DeletePackage(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err) apiError(ctx, http.StatusInternalServerError, err)
} }
} }
func getVersionsByFilename(ctx *context.Context, filename string) ([]*packages_model.PackageVersion, error) {
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID,
Type: packages_model.TypeRubyGems,
HasFileWithName: filename,
})
return pvs, err
}

View file

@ -56,8 +56,8 @@ func ListPackages(ctx *context.APIContext) {
pvs, count, err := packages.SearchVersions(ctx, &packages.PackageSearchOptions{ pvs, count, err := packages.SearchVersions(ctx, &packages.PackageSearchOptions{
OwnerID: ctx.Package.Owner.ID, OwnerID: ctx.Package.Owner.ID,
Type: packageType, Type: packages.Type(packageType),
QueryName: query, Name: packages.SearchValue{Value: query},
Paginator: &listOptions, Paginator: &listOptions,
}) })
if err != nil { if err != nil {

View file

@ -31,8 +31,8 @@ func Packages(ctx *context.Context) {
sort := ctx.FormTrim("sort") sort := ctx.FormTrim("sort")
pvs, total, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ pvs, total, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
QueryName: query, Type: packages_model.Type(packageType),
Type: packageType, Name: packages_model.SearchValue{Value: query},
Sort: sort, Sort: sort,
Paginator: &db.ListOptions{ Paginator: &db.ListOptions{
PageSize: setting.UI.PackagesPagingNum, PageSize: setting.UI.PackagesPagingNum,

View file

@ -34,8 +34,8 @@ func Packages(ctx *context.Context) {
}, },
OwnerID: ctx.ContextUser.ID, OwnerID: ctx.ContextUser.ID,
RepoID: ctx.Repo.Repository.ID, RepoID: ctx.Repo.Repository.ID,
QueryName: query, Type: packages.Type(packageType),
Type: packageType, Name: packages.SearchValue{Value: query},
}) })
if err != nil { if err != nil {
ctx.ServerError("SearchLatestVersions", err) ctx.ServerError("SearchLatestVersions", err)

View file

@ -44,8 +44,8 @@ func ListPackages(ctx *context.Context) {
Page: page, Page: page,
}, },
OwnerID: ctx.ContextUser.ID, OwnerID: ctx.ContextUser.ID,
Type: packageType, Type: packages_model.Type(packageType),
QueryName: query, Name: packages_model.SearchValue{Value: query},
}) })
if err != nil { if err != nil {
ctx.ServerError("SearchLatestVersions", err) ctx.ServerError("SearchLatestVersions", err)
@ -221,7 +221,10 @@ func ListPackageVersions(ctx *context.Context) {
pvs, total, err = packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ pvs, total, err = packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
Paginator: pagination, Paginator: pagination,
PackageID: p.ID, PackageID: p.ID,
QueryVersion: query, Version: packages_model.SearchValue{
ExactMatch: false,
Value: query,
},
}) })
if err != nil { if err != nil {
ctx.ServerError("SearchVersions", err) ctx.ServerError("SearchVersions", err)

View file

@ -10,6 +10,7 @@ import (
packages_model "code.gitea.io/gitea/models/packages" packages_model "code.gitea.io/gitea/models/packages"
container_model "code.gitea.io/gitea/models/packages/container" container_model "code.gitea.io/gitea/models/packages/container"
"code.gitea.io/gitea/modules/util"
) )
// Cleanup removes expired container data // Cleanup removes expired container data
@ -43,10 +44,7 @@ func cleanupExpiredUploadedBlobs(ctx context.Context, olderThan time.Duration) e
return err return err
} }
versions := make(map[int64]struct{})
for _, pf := range pfs { for _, pf := range pfs {
versions[pf.VersionID] = struct{}{}
if err := packages_model.DeleteAllProperties(ctx, packages_model.PropertyTypeFile, pf.ID); err != nil { if err := packages_model.DeleteAllProperties(ctx, packages_model.PropertyTypeFile, pf.ID); err != nil {
return err return err
} }
@ -55,21 +53,28 @@ func cleanupExpiredUploadedBlobs(ctx context.Context, olderThan time.Duration) e
} }
} }
for versionID := range versions { pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
has, err := packages_model.HasVersionFileReferences(ctx, versionID) Type: packages_model.TypeContainer,
Version: packages_model.SearchValue{
ExactMatch: true,
Value: container_model.UploadVersion,
},
IsInternal: true,
HasFiles: util.OptionalBoolFalse,
})
if err != nil { if err != nil {
return err return err
} }
if !has {
if err := packages_model.DeleteAllProperties(ctx, packages_model.PropertyTypeVersion, versionID); err != nil { for _, pv := range pvs {
if err := packages_model.DeleteAllProperties(ctx, packages_model.PropertyTypeVersion, pv.ID); err != nil {
return err return err
} }
if err := packages_model.DeleteVersionByID(ctx, versionID); err != nil { if err := packages_model.DeleteVersionByID(ctx, pv.ID); err != nil {
return err return err
} }
} }
}
return nil return nil
} }

View file

@ -336,7 +336,7 @@ func DeletePackageFile(ctx context.Context, pf *packages_model.PackageFile) erro
return packages_model.DeleteFileByID(ctx, pf.ID) return packages_model.DeleteFileByID(ctx, pf.ID)
} }
// Cleanup removes old unreferenced package blobs // Cleanup removes expired package data
func Cleanup(unused context.Context, olderThan time.Duration) error { func Cleanup(unused context.Context, olderThan time.Duration) error {
ctx, committer, err := db.TxContext() ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
@ -345,24 +345,20 @@ func Cleanup(unused context.Context, olderThan time.Duration) error {
defer committer.Close() defer committer.Close()
if err := container_service.Cleanup(ctx, olderThan); err != nil { if err := container_service.Cleanup(ctx, olderThan); err != nil {
log.Error("hier")
return err return err
} }
if err := packages_model.DeletePackagesIfUnreferenced(ctx); err != nil { if err := packages_model.DeletePackagesIfUnreferenced(ctx); err != nil {
log.Error("hier2")
return err return err
} }
pbs, err := packages_model.FindExpiredUnreferencedBlobs(ctx, olderThan) pbs, err := packages_model.FindExpiredUnreferencedBlobs(ctx, olderThan)
if err != nil { if err != nil {
log.Error("hier3")
return err return err
} }
for _, pb := range pbs { for _, pb := range pbs {
if err := packages_model.DeleteBlobByID(ctx, pb.ID); err != nil { if err := packages_model.DeleteBlobByID(ctx, pb.ID); err != nil {
log.Error("hier4")
return err return err
} }
} }
@ -403,10 +399,9 @@ func GetFileStreamByPackageVersionAndFileID(ctx context.Context, owner *user_mod
pv, err := packages_model.GetVersionByID(ctx, versionID) pv, err := packages_model.GetVersionByID(ctx, versionID)
if err != nil { if err != nil {
if err == packages_model.ErrPackageVersionNotExist { if err != packages_model.ErrPackageNotExist {
return nil, nil, packages_model.ErrPackageNotExist
}
log.Error("Error getting package version: %v", err) log.Error("Error getting package version: %v", err)
}
return nil, nil, err return nil, nil, err
} }