code.gitea.io/gitea@v1.21.7/models/migrations/v1_20/v250.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package v1_20 //nolint 5 6 import ( 7 "strings" 8 9 "code.gitea.io/gitea/modules/json" 10 11 "xorm.io/xorm" 12 ) 13 14 func ChangeContainerMetadataMultiArch(x *xorm.Engine) error { 15 sess := x.NewSession() 16 defer sess.Close() 17 18 if err := sess.Begin(); err != nil { 19 return err 20 } 21 22 type PackageVersion struct { 23 ID int64 `xorm:"pk autoincr"` 24 MetadataJSON string `xorm:"metadata_json"` 25 } 26 27 type PackageBlob struct{} 28 29 // Get all relevant packages (manifest list images have a container.manifest.reference property) 30 31 var pvs []*PackageVersion 32 err := sess. 33 Table("package_version"). 34 Select("id, metadata_json"). 35 Where("id IN (SELECT DISTINCT ref_id FROM package_property WHERE ref_type = 0 AND name = 'container.manifest.reference')"). 36 Find(&pvs) 37 if err != nil { 38 return err 39 } 40 41 type MetadataOld struct { 42 Type string `json:"type"` 43 IsTagged bool `json:"is_tagged"` 44 Platform string `json:"platform,omitempty"` 45 Description string `json:"description,omitempty"` 46 Authors []string `json:"authors,omitempty"` 47 Licenses string `json:"license,omitempty"` 48 ProjectURL string `json:"project_url,omitempty"` 49 RepositoryURL string `json:"repository_url,omitempty"` 50 DocumentationURL string `json:"documentation_url,omitempty"` 51 Labels map[string]string `json:"labels,omitempty"` 52 ImageLayers []string `json:"layer_creation,omitempty"` 53 MultiArch map[string]string `json:"multiarch,omitempty"` 54 } 55 56 type Manifest struct { 57 Platform string `json:"platform"` 58 Digest string `json:"digest"` 59 Size int64 `json:"size"` 60 } 61 62 type MetadataNew struct { 63 Type string `json:"type"` 64 IsTagged bool `json:"is_tagged"` 65 Platform string `json:"platform,omitempty"` 66 Description string `json:"description,omitempty"` 67 Authors []string `json:"authors,omitempty"` 68 Licenses string `json:"license,omitempty"` 69 ProjectURL string `json:"project_url,omitempty"` 70 RepositoryURL string `json:"repository_url,omitempty"` 71 DocumentationURL string `json:"documentation_url,omitempty"` 72 Labels map[string]string `json:"labels,omitempty"` 73 ImageLayers []string `json:"layer_creation,omitempty"` 74 Manifests []*Manifest `json:"manifests,omitempty"` 75 } 76 77 for _, pv := range pvs { 78 var old *MetadataOld 79 if err := json.Unmarshal([]byte(pv.MetadataJSON), &old); err != nil { 80 return err 81 } 82 83 // Calculate the size of every contained manifest 84 85 manifests := make([]*Manifest, 0, len(old.MultiArch)) 86 for platform, digest := range old.MultiArch { 87 size, err := sess. 88 Table("package_blob"). 89 Join("INNER", "package_file", "package_blob.id = package_file.blob_id"). 90 Join("INNER", "package_version pv", "pv.id = package_file.version_id"). 91 Join("INNER", "package_version pv2", "pv2.package_id = pv.package_id"). 92 Where("pv.lower_version = ? AND pv2.id = ?", strings.ToLower(digest), pv.ID). 93 SumInt(new(PackageBlob), "size") 94 if err != nil { 95 return err 96 } 97 98 manifests = append(manifests, &Manifest{ 99 Platform: platform, 100 Digest: digest, 101 Size: size, 102 }) 103 } 104 105 // Convert to new metadata format 106 107 new := &MetadataNew{ 108 Type: old.Type, 109 IsTagged: old.IsTagged, 110 Platform: old.Platform, 111 Description: old.Description, 112 Authors: old.Authors, 113 Licenses: old.Licenses, 114 ProjectURL: old.ProjectURL, 115 RepositoryURL: old.RepositoryURL, 116 DocumentationURL: old.DocumentationURL, 117 Labels: old.Labels, 118 ImageLayers: old.ImageLayers, 119 Manifests: manifests, 120 } 121 122 metadataJSON, err := json.Marshal(new) 123 if err != nil { 124 return err 125 } 126 127 pv.MetadataJSON = string(metadataJSON) 128 129 if _, err := sess.ID(pv.ID).Update(pv); err != nil { 130 return err 131 } 132 } 133 134 return sess.Commit() 135 }