diff options
Diffstat (limited to '')
-rw-r--r-- | models/migrations/v1_20/v250.go | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/models/migrations/v1_20/v250.go b/models/migrations/v1_20/v250.go new file mode 100644 index 0000000..86388ef --- /dev/null +++ b/models/migrations/v1_20/v250.go @@ -0,0 +1,135 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_20 //nolint + +import ( + "strings" + + "code.gitea.io/gitea/modules/json" + + "xorm.io/xorm" +) + +func ChangeContainerMetadataMultiArch(x *xorm.Engine) error { + sess := x.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + return err + } + + type PackageVersion struct { + ID int64 `xorm:"pk autoincr"` + MetadataJSON string `xorm:"metadata_json"` + } + + type PackageBlob struct{} + + // Get all relevant packages (manifest list images have a container.manifest.reference property) + + var pvs []*PackageVersion + err := sess. + Table("package_version"). + Select("id, metadata_json"). + Where("id IN (SELECT DISTINCT ref_id FROM package_property WHERE ref_type = 0 AND name = 'container.manifest.reference')"). + Find(&pvs) + if err != nil { + return err + } + + type MetadataOld struct { + Type string `json:"type"` + IsTagged bool `json:"is_tagged"` + Platform string `json:"platform,omitempty"` + Description string `json:"description,omitempty"` + Authors []string `json:"authors,omitempty"` + Licenses string `json:"license,omitempty"` + ProjectURL string `json:"project_url,omitempty"` + RepositoryURL string `json:"repository_url,omitempty"` + DocumentationURL string `json:"documentation_url,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + ImageLayers []string `json:"layer_creation,omitempty"` + MultiArch map[string]string `json:"multiarch,omitempty"` + } + + type Manifest struct { + Platform string `json:"platform"` + Digest string `json:"digest"` + Size int64 `json:"size"` + } + + type MetadataNew struct { + Type string `json:"type"` + IsTagged bool `json:"is_tagged"` + Platform string `json:"platform,omitempty"` + Description string `json:"description,omitempty"` + Authors []string `json:"authors,omitempty"` + Licenses string `json:"license,omitempty"` + ProjectURL string `json:"project_url,omitempty"` + RepositoryURL string `json:"repository_url,omitempty"` + DocumentationURL string `json:"documentation_url,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + ImageLayers []string `json:"layer_creation,omitempty"` + Manifests []*Manifest `json:"manifests,omitempty"` + } + + for _, pv := range pvs { + var old *MetadataOld + if err := json.Unmarshal([]byte(pv.MetadataJSON), &old); err != nil { + return err + } + + // Calculate the size of every contained manifest + + manifests := make([]*Manifest, 0, len(old.MultiArch)) + for platform, digest := range old.MultiArch { + size, err := sess. + Table("package_blob"). + Join("INNER", "package_file", "package_blob.id = package_file.blob_id"). + Join("INNER", "package_version pv", "pv.id = package_file.version_id"). + Join("INNER", "package_version pv2", "pv2.package_id = pv.package_id"). + Where("pv.lower_version = ? AND pv2.id = ?", strings.ToLower(digest), pv.ID). + SumInt(new(PackageBlob), "size") + if err != nil { + return err + } + + manifests = append(manifests, &Manifest{ + Platform: platform, + Digest: digest, + Size: size, + }) + } + + // Convert to new metadata format + + newMetadata := &MetadataNew{ + Type: old.Type, + IsTagged: old.IsTagged, + Platform: old.Platform, + Description: old.Description, + Authors: old.Authors, + Licenses: old.Licenses, + ProjectURL: old.ProjectURL, + RepositoryURL: old.RepositoryURL, + DocumentationURL: old.DocumentationURL, + Labels: old.Labels, + ImageLayers: old.ImageLayers, + Manifests: manifests, + } + + metadataJSON, err := json.Marshal(newMetadata) + if err != nil { + return err + } + + pv.MetadataJSON = string(metadataJSON) + + if _, err := sess.ID(pv.ID).Update(pv); err != nil { + return err + } + } + + return sess.Commit() +} |