@@ -10,6 +10,7 @@ import (
1010 "io"
1111 "os"
1212 "strings"
13+ "time"
1314
1415 "code.gitea.io/gitea/models/db"
1516 packages_model "code.gitea.io/gitea/models/packages"
@@ -23,19 +24,19 @@ import (
2324 notify_service "code.gitea.io/gitea/services/notify"
2425 packages_service "code.gitea.io/gitea/services/packages"
2526
26- digest "github.com/opencontainers/go-digest"
27+ "github.com/opencontainers/go-digest"
2728 oci "github.com/opencontainers/image-spec/specs-go/v1"
2829)
2930
30- func isValidMediaType (mt string ) bool {
31+ func isMediaTypeValid (mt string ) bool {
3132 return strings .HasPrefix (mt , "application/vnd.docker." ) || strings .HasPrefix (mt , "application/vnd.oci." )
3233}
3334
34- func isImageManifestMediaType (mt string ) bool {
35+ func isMediaTypeImageManifest (mt string ) bool {
3536 return strings .EqualFold (mt , oci .MediaTypeImageManifest ) || strings .EqualFold (mt , "application/vnd.docker.distribution.manifest.v2+json" )
3637}
3738
38- func isImageIndexMediaType (mt string ) bool {
39+ func isMediaTypeImageIndex (mt string ) bool {
3940 return strings .EqualFold (mt , oci .MediaTypeImageIndex ) || strings .EqualFold (mt , "application/vnd.docker.distribution.manifest.list.v2+json" )
4041}
4142
@@ -64,22 +65,22 @@ func processManifest(ctx context.Context, mci *manifestCreationInfo, buf *packag
6465 return "" , err
6566 }
6667
67- if ! isValidMediaType (mci .MediaType ) {
68+ if ! isMediaTypeValid (mci .MediaType ) {
6869 mci .MediaType = index .MediaType
69- if ! isValidMediaType (mci .MediaType ) {
70+ if ! isMediaTypeValid (mci .MediaType ) {
7071 return "" , errManifestInvalid .WithMessage ("MediaType not recognized" )
7172 }
7273 }
7374
74- if isImageManifestMediaType (mci .MediaType ) {
75- return processImageManifest (ctx , mci , buf )
76- } else if isImageIndexMediaType (mci .MediaType ) {
77- return processImageManifestIndex (ctx , mci , buf )
75+ if isMediaTypeImageManifest (mci .MediaType ) {
76+ return processOciImageManifest (ctx , mci , buf )
77+ } else if isMediaTypeImageIndex (mci .MediaType ) {
78+ return processOciImageIndex (ctx , mci , buf )
7879 }
7980 return "" , errManifestInvalid
8081}
8182
82- func processImageManifest (ctx context.Context , mci * manifestCreationInfo , buf * packages_module.HashedBuffer ) (string , error ) {
83+ func processOciImageManifest (ctx context.Context , mci * manifestCreationInfo , buf * packages_module.HashedBuffer ) (string , error ) {
8384 manifestDigest := ""
8485
8586 err := func () error {
@@ -156,7 +157,7 @@ func processImageManifest(ctx context.Context, mci *manifestCreationInfo, buf *p
156157 }
157158
158159 for _ , ref := range blobReferences {
159- if err : = createFileFromBlobReference (ctx , pv , uploadVersion , ref ); err != nil {
160+ if _ , err = createFileFromBlobReference (ctx , pv , uploadVersion , ref ); err != nil {
160161 return err
161162 }
162163 }
@@ -196,7 +197,7 @@ func processImageManifest(ctx context.Context, mci *manifestCreationInfo, buf *p
196197 return manifestDigest , nil
197198}
198199
199- func processImageManifestIndex (ctx context.Context , mci * manifestCreationInfo , buf * packages_module.HashedBuffer ) (string , error ) {
200+ func processOciImageIndex (ctx context.Context , mci * manifestCreationInfo , buf * packages_module.HashedBuffer ) (string , error ) {
200201 manifestDigest := ""
201202
202203 err := func () error {
@@ -221,7 +222,7 @@ func processImageManifestIndex(ctx context.Context, mci *manifestCreationInfo, b
221222 }
222223
223224 for _ , manifest := range index .Manifests {
224- if ! isImageManifestMediaType (manifest .MediaType ) {
225+ if ! isMediaTypeImageManifest (manifest .MediaType ) {
225226 return errManifestInvalid
226227 }
227228
@@ -349,24 +350,31 @@ func createPackageAndVersion(ctx context.Context, mci *manifestCreationInfo, met
349350 LowerVersion : strings .ToLower (mci .Reference ),
350351 MetadataJSON : string (metadataJSON ),
351352 }
352- var pv * packages_model.PackageVersion
353- if pv , err = packages_model . GetOrInsertVersion ( ctx , _pv ); err != nil {
353+ pv , err := packages_model .GetOrInsertVersion ( ctx , _pv )
354+ if err != nil {
354355 if ! errors .Is (err , packages_model .ErrDuplicatePackageVersion ) {
355356 log .Error ("Error inserting package: %v" , err )
356357 return nil , err
357358 }
358359
359- if err = packages_service .DeletePackageVersionAndReferences (ctx , pv ); err != nil {
360- return nil , err
361- }
362-
363- // keep download count on overwrite
364- _pv .DownloadCount = pv .DownloadCount
365-
366- if pv , err = packages_model .GetOrInsertVersion (ctx , _pv ); err != nil {
367- if ! errors .Is (err , packages_model .ErrDuplicatePackageVersion ) {
368- log .Error ("Error inserting package: %v" , err )
369- return nil , err
360+ if isMediaTypeImageIndex (mci .MediaType ) {
361+ if pv .CreatedUnix .AsTime ().Before (time .Now ().Add (- 24 * time .Hour )) {
362+ if err = packages_service .DeletePackageVersionAndReferences (ctx , pv ); err != nil {
363+ return nil , err
364+ }
365+ // keep download count on overwriting
366+ _pv .DownloadCount = pv .DownloadCount
367+ if pv , err = packages_model .GetOrInsertVersion (ctx , _pv ); err != nil {
368+ if ! errors .Is (err , packages_model .ErrDuplicatePackageVersion ) {
369+ log .Error ("Error inserting package: %v" , err )
370+ return nil , err
371+ }
372+ }
373+ } else {
374+ err = packages_model .UpdateVersion (ctx , & packages_model.PackageVersion {ID : pv .ID , MetadataJSON : _pv .MetadataJSON })
375+ if err != nil {
376+ return nil , err
377+ }
370378 }
371379 }
372380 }
@@ -376,14 +384,12 @@ func createPackageAndVersion(ctx context.Context, mci *manifestCreationInfo, met
376384 }
377385
378386 if mci .IsTagged {
379- if _ , err := packages_model .InsertProperty (ctx , packages_model .PropertyTypeVersion , pv .ID , container_module .PropertyManifestTagged , "" ); err != nil {
380- log .Error ("Error setting package version property: %v" , err )
387+ if err = packages_model .InsertOrUpdateProperty (ctx , packages_model .PropertyTypeVersion , pv .ID , container_module .PropertyManifestTagged , "" ); err != nil {
381388 return nil , err
382389 }
383390 }
384391 for _ , manifest := range metadata .Manifests {
385- if _ , err := packages_model .InsertProperty (ctx , packages_model .PropertyTypeVersion , pv .ID , container_module .PropertyManifestReference , manifest .Digest ); err != nil {
386- log .Error ("Error setting package version property: %v" , err )
392+ if err = packages_model .InsertOrUpdateProperty (ctx , packages_model .PropertyTypeVersion , pv .ID , container_module .PropertyManifestReference , manifest .Digest ); err != nil {
387393 return nil , err
388394 }
389395 }
@@ -400,30 +406,33 @@ type blobReference struct {
400406 IsLead bool
401407}
402408
403- func createFileFromBlobReference (ctx context.Context , pv , uploadVersion * packages_model.PackageVersion , ref * blobReference ) error {
409+ func createFileFromBlobReference (ctx context.Context , pv , uploadVersion * packages_model.PackageVersion , ref * blobReference ) ( * packages_model. PackageFile , error ) {
404410 if ref .File .Blob .Size != ref .ExpectedSize {
405- return errSizeInvalid
411+ return nil , errSizeInvalid
406412 }
407413
408414 if ref .Name == "" {
409415 ref .Name = strings .ToLower ("sha256_" + ref .File .Blob .HashSHA256 )
410416 }
411417
412418 pf := & packages_model.PackageFile {
413- VersionID : pv .ID ,
414- BlobID : ref .File .Blob .ID ,
415- Name : ref .Name ,
416- LowerName : ref .Name ,
417- IsLead : ref .IsLead ,
419+ VersionID : pv .ID ,
420+ BlobID : ref .File .Blob .ID ,
421+ Name : ref .Name ,
422+ LowerName : ref .Name ,
423+ CompositeKey : string (ref .Digest ),
424+ // FIXME: old data doesn't have this field set, so we can't use it unless there is a migration fix
425+ // at the moment, there is a workaround in GetContainerBlob to tolerate this
426+ IsLead : ref .IsLead ,
418427 }
419428 var err error
420429 if pf , err = packages_model .TryInsertFile (ctx , pf ); err != nil {
421430 if errors .Is (err , packages_model .ErrDuplicatePackageFile ) {
422431 // Skip this blob because the manifest contains the same filesystem layer multiple times.
423- return nil
432+ return pf , nil
424433 }
425434 log .Error ("Error inserting package file: %v" , err )
426- return err
435+ return nil , err
427436 }
428437
429438 props := map [string ]string {
@@ -433,18 +442,18 @@ func createFileFromBlobReference(ctx context.Context, pv, uploadVersion *package
433442 for name , value := range props {
434443 if _ , err := packages_model .InsertProperty (ctx , packages_model .PropertyTypeFile , pf .ID , name , value ); err != nil {
435444 log .Error ("Error setting package file property: %v" , err )
436- return err
445+ return nil , err
437446 }
438447 }
439448
440- // Remove the file from the blob upload version
449+ // Remove the ref file (old file) from the blob upload version
441450 if uploadVersion != nil && ref .File .File != nil && uploadVersion .ID == ref .File .File .VersionID {
442451 if err := packages_service .DeletePackageFile (ctx , ref .File .File ); err != nil {
443- return err
452+ return nil , err
444453 }
445454 }
446455
447- return nil
456+ return pf , nil
448457}
449458
450459func createManifestBlob (ctx context.Context , mci * manifestCreationInfo , pv * packages_model.PackageVersion , buf * packages_module.HashedBuffer ) (* packages_model.PackageBlob , bool , string , error ) {
@@ -471,14 +480,34 @@ func createManifestBlob(ctx context.Context, mci *manifestCreationInfo, pv *pack
471480 }
472481
473482 manifestDigest := digestFromHashSummer (buf )
474- err = createFileFromBlobReference (ctx , pv , nil , & blobReference {
483+ pf , err : = createFileFromBlobReference (ctx , pv , nil , & blobReference {
475484 Digest : digest .Digest (manifestDigest ),
476485 MediaType : mci .MediaType ,
477486 Name : container_model .ManifestFilename ,
478487 File : & packages_model.PackageFileDescriptor {Blob : pb },
479488 ExpectedSize : pb .Size ,
480489 IsLead : true ,
481490 })
491+ if err != nil {
492+ return nil , false , "" , err
493+ }
482494
495+ oldManifestFiles , _ , err := packages_model .SearchFiles (ctx , & packages_model.PackageFileSearchOptions {
496+ OwnerID : mci .Owner .ID ,
497+ PackageType : packages_model .TypeContainer ,
498+ VersionID : pv .ID ,
499+ Query : container_model .ManifestFilename ,
500+ })
501+ if err != nil {
502+ return nil , false , "" , err
503+ }
504+ for _ , oldManifestFile := range oldManifestFiles {
505+ if oldManifestFile .ID != pf .ID && oldManifestFile .IsLead {
506+ err = packages_model .UpdateFile (ctx , & packages_model.PackageFile {ID : oldManifestFile .ID , IsLead : false }, []string {"is_lead" })
507+ if err != nil {
508+ return nil , false , "" , err
509+ }
510+ }
511+ }
483512 return pb , ! exists , manifestDigest , err
484513}
0 commit comments