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  }