mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-08-19 06:01:31 +02:00
Fixes #25918
The migration fails on MSSQL because xorm tries to update the primary
key column. xorm prevents this if the column is marked as auto
increment:
c622cdaf89/internal/statements/update.go (L38-L40)
I think it would be better if xorm would check for primary key columns
here because updating such columns is bad practice. It looks like if
that auto increment check should do the same.
fyi @lunny
136 lines
4.1 KiB
Go
136 lines
4.1 KiB
Go
// 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
|
|
|
|
new := &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(new)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
pv.MetadataJSON = string(metadataJSON)
|
|
|
|
if _, err := sess.ID(pv.ID).Update(pv); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return sess.Commit()
|
|
}
|