Skip to content

Commit 5e242e0

Browse files
authored
Package registry changes (#19305)
* removed debug logs * fixed SELECT * removed unneeded error type * use common SearchVersions method * remove empty container upload versions * return err
1 parent 8ddcd37 commit 5e242e0

File tree

17 files changed

+185
-150
lines changed

17 files changed

+185
-150
lines changed

integrations/api_packages_test.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ import (
99
"fmt"
1010
"net/http"
1111
"testing"
12+
"time"
1213

13-
"code.gitea.io/gitea/models/packages"
14+
"code.gitea.io/gitea/models/db"
15+
packages_model "code.gitea.io/gitea/models/packages"
16+
container_model "code.gitea.io/gitea/models/packages/container"
1417
"code.gitea.io/gitea/models/unittest"
1518
user_model "code.gitea.io/gitea/models/user"
1619
api "code.gitea.io/gitea/modules/structs"
20+
packages_service "code.gitea.io/gitea/services/packages"
1721

1822
"github.com/stretchr/testify/assert"
1923
)
@@ -43,7 +47,7 @@ func TestPackageAPI(t *testing.T) {
4347
DecodeJSON(t, resp, &apiPackages)
4448

4549
assert.Len(t, apiPackages, 1)
46-
assert.Equal(t, string(packages.TypeGeneric), apiPackages[0].Type)
50+
assert.Equal(t, string(packages_model.TypeGeneric), apiPackages[0].Type)
4751
assert.Equal(t, packageName, apiPackages[0].Name)
4852
assert.Equal(t, packageVersion, apiPackages[0].Version)
4953
assert.NotNil(t, apiPackages[0].Creator)
@@ -62,7 +66,7 @@ func TestPackageAPI(t *testing.T) {
6266
var p *api.Package
6367
DecodeJSON(t, resp, &p)
6468

65-
assert.Equal(t, string(packages.TypeGeneric), p.Type)
69+
assert.Equal(t, string(packages_model.TypeGeneric), p.Type)
6670
assert.Equal(t, packageName, p.Name)
6771
assert.Equal(t, packageVersion, p.Version)
6872
assert.NotNil(t, p.Creator)
@@ -100,3 +104,26 @@ func TestPackageAPI(t *testing.T) {
100104
MakeRequest(t, req, http.StatusNoContent)
101105
})
102106
}
107+
108+
func TestPackageCleanup(t *testing.T) {
109+
defer prepareTestEnv(t)()
110+
111+
time.Sleep(time.Second)
112+
113+
pbs, err := packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0))
114+
assert.NoError(t, err)
115+
assert.NotEmpty(t, pbs)
116+
117+
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion)
118+
assert.NoError(t, err)
119+
120+
err = packages_service.Cleanup(nil, time.Duration(0))
121+
assert.NoError(t, err)
122+
123+
pbs, err = packages_model.FindExpiredUnreferencedBlobs(db.DefaultContext, time.Duration(0))
124+
assert.NoError(t, err)
125+
assert.Empty(t, pbs)
126+
127+
_, err = packages_model.GetInternalVersionByNameAndVersion(db.DefaultContext, 2, packages_model.TypeContainer, "test", container_model.UploadVersion)
128+
assert.ErrorIs(t, err, packages_model.ErrPackageNotExist)
129+
}

models/packages/conan/references.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,14 @@ func findPropertyValues(ctx context.Context, propertyName string, ownerID int64,
6565
in2 := builder.
6666
Select("package_file.id").
6767
From("package_file").
68-
Join("INNER", "package_version", "package_version.id = package_file.version_id").
69-
Join("INNER", "package", "package.id = package_version.package_id").
68+
InnerJoin("package_version", "package_version.id = package_file.version_id").
69+
InnerJoin("package", "package.id = package_version.package_id").
7070
Where(cond)
7171

7272
query := builder.
7373
Select("package_property.value, MAX(package_file.created_unix) AS created_unix").
7474
From("package_property").
75-
Join("INNER", "package_file", "package_file.id = package_property.ref_id").
75+
InnerJoin("package_file", "package_file.id = package_property.ref_id").
7676
Where(builder.Eq{"package_property.name": propertyName}.And(builder.In("package_property.ref_id", in2))).
7777
GroupBy("package_property.value").
7878
OrderBy("created_unix DESC")

models/packages/conan/search.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ func SearchRecipes(ctx context.Context, opts *RecipeSearchOptions) ([]string, er
7474
query := builder.
7575
Select("package.name, package_version.version, package_file.id").
7676
From("package_file").
77-
Join("INNER", "package_version", "package_version.id = package_file.version_id").
78-
Join("INNER", "package", "package.id = package_version.package_id").
77+
InnerJoin("package_version", "package_version.id = package_file.version_id").
78+
InnerJoin("package", "package.id = package_version.package_id").
7979
Where(cond)
8080

8181
results := make([]struct {

models/packages/package.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,15 @@ func GetPackagesByType(ctx context.Context, ownerID int64, packageType Type) ([]
190190
// DeletePackagesIfUnreferenced deletes a package if there are no associated versions
191191
func DeletePackagesIfUnreferenced(ctx context.Context) error {
192192
in := builder.
193-
Select("package_version.package_id").
193+
Select("package.id").
194194
From("package").
195-
Join("LEFT", "package_version", "package_version.package_id = package.id").
195+
LeftJoin("package_version", "package_version.package_id = package.id").
196196
Where(builder.Expr("package_version.id IS NULL"))
197197

198198
_, err := db.GetEngine(ctx).
199-
Where(builder.In("package.id", in)).
199+
// double select workaround for MySQL
200+
// https://stackoverflow.com/questions/4471277/mysql-delete-from-with-subquery-as-condition
201+
Where(builder.In("package.id", builder.Select("id").From(in, "temp"))).
200202
Delete(&Package{})
201203

202204
return err

models/packages/package_blob.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func FindExpiredUnreferencedBlobs(ctx context.Context, olderThan time.Duration)
6767
pbs := make([]*PackageBlob, 0, 10)
6868
return pbs, db.GetEngine(ctx).
6969
Table("package_blob").
70-
Join("LEFT OUTER", "package_file", "package_file.blob_id = package_blob.id").
70+
Join("LEFT", "package_file", "package_file.blob_id = package_blob.id").
7171
Where("package_file.id IS NULL AND package_blob.created_unix < ?", time.Now().Add(-olderThan).Unix()).
7272
Find(&pbs)
7373
}

models/packages/package_file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func (opts *PackageFileSearchOptions) toConds() builder.Cond {
147147
in := builder.
148148
Select("package_version.id").
149149
From("package_version").
150-
Join("INNER", "package", "package.id = package_version.package_id").
150+
InnerJoin("package", "package.id = package_version.package_id").
151151
Where(versionCond)
152152

153153
cond = cond.And(builder.In("package_file.version_id", in))

models/packages/package_version.go

Lines changed: 81 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,13 @@ import (
1212

1313
"code.gitea.io/gitea/models/db"
1414
"code.gitea.io/gitea/modules/timeutil"
15+
"code.gitea.io/gitea/modules/util"
1516

1617
"xorm.io/builder"
1718
)
1819

19-
var (
20-
// ErrDuplicatePackageVersion indicates a duplicated package version error
21-
ErrDuplicatePackageVersion = errors.New("Package version does exist already")
22-
// ErrPackageVersionNotExist indicates a package version not exist error
23-
ErrPackageVersionNotExist = errors.New("Package version does not exist")
24-
)
20+
// ErrDuplicatePackageVersion indicates a duplicated package version error
21+
var ErrDuplicatePackageVersion = errors.New("Package version already exists")
2522

2623
func init() {
2724
db.RegisterModel(new(PackageVersion))
@@ -99,75 +96,49 @@ func GetInternalVersionByNameAndVersion(ctx context.Context, ownerID int64, pack
9996
}
10097

10198
func getVersionByNameAndVersion(ctx context.Context, ownerID int64, packageType Type, name, version string, isInternal bool) (*PackageVersion, error) {
102-
var cond builder.Cond = builder.Eq{
103-
"package.owner_id": ownerID,
104-
"package.type": packageType,
105-
"package.lower_name": strings.ToLower(name),
106-
"package_version.is_internal": isInternal,
107-
}
108-
pv := &PackageVersion{
109-
LowerVersion: strings.ToLower(version),
110-
}
111-
has, err := db.GetEngine(ctx).
112-
Join("INNER", "package", "package.id = package_version.package_id").
113-
Where(cond).
114-
Get(pv)
99+
pvs, _, err := SearchVersions(ctx, &PackageSearchOptions{
100+
OwnerID: ownerID,
101+
Type: packageType,
102+
Name: SearchValue{
103+
ExactMatch: true,
104+
Value: name,
105+
},
106+
Version: SearchValue{
107+
ExactMatch: true,
108+
Value: version,
109+
},
110+
IsInternal: isInternal,
111+
Paginator: db.NewAbsoluteListOptions(0, 1),
112+
})
115113
if err != nil {
116114
return nil, err
117115
}
118-
if !has {
116+
if len(pvs) == 0 {
119117
return nil, ErrPackageNotExist
120118
}
121-
122-
return pv, nil
119+
return pvs[0], nil
123120
}
124121

125122
// GetVersionsByPackageType gets all versions of a specific type
126123
func GetVersionsByPackageType(ctx context.Context, ownerID int64, packageType Type) ([]*PackageVersion, error) {
127-
var cond builder.Cond = builder.Eq{
128-
"package.owner_id": ownerID,
129-
"package.type": packageType,
130-
"package_version.is_internal": false,
131-
}
132-
133-
pvs := make([]*PackageVersion, 0, 10)
134-
return pvs, db.GetEngine(ctx).
135-
Where(cond).
136-
Join("INNER", "package", "package.id = package_version.package_id").
137-
Find(&pvs)
124+
pvs, _, err := SearchVersions(ctx, &PackageSearchOptions{
125+
OwnerID: ownerID,
126+
Type: packageType,
127+
})
128+
return pvs, err
138129
}
139130

140131
// GetVersionsByPackageName gets all versions of a specific package
141132
func GetVersionsByPackageName(ctx context.Context, ownerID int64, packageType Type, name string) ([]*PackageVersion, error) {
142-
var cond builder.Cond = builder.Eq{
143-
"package.owner_id": ownerID,
144-
"package.type": packageType,
145-
"package.lower_name": strings.ToLower(name),
146-
"package_version.is_internal": false,
147-
}
148-
149-
pvs := make([]*PackageVersion, 0, 10)
150-
return pvs, db.GetEngine(ctx).
151-
Where(cond).
152-
Join("INNER", "package", "package.id = package_version.package_id").
153-
Find(&pvs)
154-
}
155-
156-
// GetVersionsByFilename gets all versions which are linked to a filename
157-
func GetVersionsByFilename(ctx context.Context, ownerID int64, packageType Type, filename string) ([]*PackageVersion, error) {
158-
var cond builder.Cond = builder.Eq{
159-
"package.owner_id": ownerID,
160-
"package.type": packageType,
161-
"package_file.lower_name": strings.ToLower(filename),
162-
"package_version.is_internal": false,
163-
}
164-
165-
pvs := make([]*PackageVersion, 0, 10)
166-
return pvs, db.GetEngine(ctx).
167-
Where(cond).
168-
Join("INNER", "package_file", "package_file.version_id = package_version.id").
169-
Join("INNER", "package", "package.id = package_version.package_id").
170-
Find(&pvs)
133+
pvs, _, err := SearchVersions(ctx, &PackageSearchOptions{
134+
OwnerID: ownerID,
135+
Type: packageType,
136+
Name: SearchValue{
137+
ExactMatch: true,
138+
Value: name,
139+
},
140+
})
141+
return pvs, err
171142
}
172143

173144
// DeleteVersionByID deletes a version by id
@@ -183,21 +154,32 @@ func HasVersionFileReferences(ctx context.Context, versionID int64) (bool, error
183154
})
184155
}
185156

157+
// SearchValue describes a value to search
158+
// If ExactMatch is true, the field must match the value otherwise a LIKE search is performed.
159+
type SearchValue struct {
160+
Value string
161+
ExactMatch bool
162+
}
163+
186164
// PackageSearchOptions are options for SearchXXX methods
165+
// Besides IsInternal are all fields optional and are not used if they have their default value (nil, "", 0)
187166
type PackageSearchOptions struct {
188-
OwnerID int64
189-
RepoID int64
190-
Type string
191-
PackageID int64
192-
QueryName string
193-
QueryVersion string
194-
Properties map[string]string
195-
Sort string
167+
OwnerID int64
168+
RepoID int64
169+
Type Type
170+
PackageID int64
171+
Name SearchValue // only results with the specific name are found
172+
Version SearchValue // only results with the specific version are found
173+
Properties map[string]string // only results are found which contain all listed version properties with the specific value
174+
IsInternal bool
175+
HasFileWithName string // only results are found which are associated with a file with the specific name
176+
HasFiles util.OptionalBool // only results are found which have associated files
177+
Sort string
196178
db.Paginator
197179
}
198180

199181
func (opts *PackageSearchOptions) toConds() builder.Cond {
200-
var cond builder.Cond = builder.Eq{"package_version.is_internal": false}
182+
var cond builder.Cond = builder.Eq{"package_version.is_internal": opts.IsInternal}
201183

202184
if opts.OwnerID != 0 {
203185
cond = cond.And(builder.Eq{"package.owner_id": opts.OwnerID})
@@ -211,11 +193,19 @@ func (opts *PackageSearchOptions) toConds() builder.Cond {
211193
if opts.PackageID != 0 {
212194
cond = cond.And(builder.Eq{"package.id": opts.PackageID})
213195
}
214-
if opts.QueryName != "" {
215-
cond = cond.And(builder.Like{"package.lower_name", strings.ToLower(opts.QueryName)})
196+
if opts.Name.Value != "" {
197+
if opts.Name.ExactMatch {
198+
cond = cond.And(builder.Eq{"package.lower_name": strings.ToLower(opts.Name.Value)})
199+
} else {
200+
cond = cond.And(builder.Like{"package.lower_name", strings.ToLower(opts.Name.Value)})
201+
}
216202
}
217-
if opts.QueryVersion != "" {
218-
cond = cond.And(builder.Like{"package_version.lower_version", strings.ToLower(opts.QueryVersion)})
203+
if opts.Version.Value != "" {
204+
if opts.Version.ExactMatch {
205+
cond = cond.And(builder.Eq{"package_version.lower_version": strings.ToLower(opts.Version.Value)})
206+
} else {
207+
cond = cond.And(builder.Like{"package_version.lower_version", strings.ToLower(opts.Version.Value)})
208+
}
219209
}
220210

221211
if len(opts.Properties) != 0 {
@@ -238,6 +228,22 @@ func (opts *PackageSearchOptions) toConds() builder.Cond {
238228
})
239229
}
240230

231+
if opts.HasFileWithName != "" {
232+
fileCond := builder.Expr("package_file.version_id = package_version.id").And(builder.Eq{"package_file.lower_name": strings.ToLower(opts.HasFileWithName)})
233+
234+
cond = cond.And(builder.Exists(builder.Select("package_file.id").From("package_file").Where(fileCond)))
235+
}
236+
237+
if !opts.HasFiles.IsNone() {
238+
var filesCond builder.Cond = builder.Exists(builder.Select("package_file.id").From("package_file").Where(builder.Expr("package_file.version_id = package_version.id")))
239+
240+
if opts.HasFiles.IsFalse() {
241+
filesCond = builder.Not{filesCond}
242+
}
243+
244+
cond = cond.And(filesCond)
245+
}
246+
241247
return cond
242248
}
243249

@@ -297,20 +303,3 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P
297303
count, err := sess.FindAndCount(&pvs)
298304
return pvs, count, err
299305
}
300-
301-
// FindVersionsByPropertyNameAndValue gets all package versions which are associated with a specific property + value
302-
func FindVersionsByPropertyNameAndValue(ctx context.Context, packageID int64, name, value string) ([]*PackageVersion, error) {
303-
var cond builder.Cond = builder.Eq{
304-
"package_property.ref_type": PropertyTypeVersion,
305-
"package_property.name": name,
306-
"package_property.value": value,
307-
"package_version.package_id": packageID,
308-
"package_version.is_internal": false,
309-
}
310-
311-
pvs := make([]*PackageVersion, 0, 5)
312-
return pvs, db.GetEngine(ctx).
313-
Where(cond).
314-
Join("INNER", "package_property", "package_property.ref_id = package_version.id").
315-
Find(&pvs)
316-
}

routers/api/packages/composer/composer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ func SearchPackages(ctx *context.Context) {
6363

6464
opts := &packages_model.PackageSearchOptions{
6565
OwnerID: ctx.Package.Owner.ID,
66-
Type: string(packages_model.TypeComposer),
67-
QueryName: ctx.FormTrim("q"),
66+
Type: packages_model.TypeComposer,
67+
Name: packages_model.SearchValue{Value: ctx.FormTrim("q")},
6868
Paginator: &paginator,
6969
}
7070
if ctx.FormTrim("type") != "" {

routers/api/packages/npm/npm.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,12 @@ func setPackageTag(tag string, pv *packages_model.PackageVersion, deleteOnly boo
256256
}
257257
defer committer.Close()
258258

259-
pvs, err := packages_model.FindVersionsByPropertyNameAndValue(ctx, pv.PackageID, npm_module.TagProperty, tag)
259+
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
260+
PackageID: pv.PackageID,
261+
Properties: map[string]string{
262+
npm_module.TagProperty: tag,
263+
},
264+
})
260265
if err != nil {
261266
return err
262267
}

0 commit comments

Comments
 (0)