Files
mstore/app/imageoper/ociaux.go
T
2026-03-11 19:47:40 +02:00

189 lines
5.1 KiB
Go

/*
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
*
* This work is published and licensed under a Creative Commons
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
*
* Distribution of this work is permitted, but commercial use and
* modifications are strictly prohibited.
*/
package imageoper
import (
"encoding/json"
//"mstore/pkg/auxoci"
"mstore/pkg/auxtool"
"mstore/pkg/auxuuid"
"mstore/pkg/descr"
ocidigest "github.com/opencontainers/go-digest"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
const (
oiiMediaType = "application/vnd.oci.image.index.v1+json"
oimMediaType = "application/vnd.oci.image.manifest.v1+json"
)
func indexFromManigestDescrs(mandescrs []descr.Manifest) (ocispec.Index, []byte, error) {
var err error
var indexdata []byte
index := ocispec.Index{
MediaType: oiiMediaType,
Manifests: make([]ocispec.Descriptor, 0),
}
index.Versioned.SchemaVersion = 2
for _, mandescr := range mandescrs {
var man ocispec.Manifest
man.Subject = &ocispec.Descriptor{}
man.Subject.Platform = &ocispec.Platform{}
man.Config = ocispec.Descriptor{}
man.Config.Platform = &ocispec.Platform{}
err = json.Unmarshal([]byte(mandescr.Payload), &man)
if err != nil {
return index, indexdata, err
}
digobj, err := ocidigest.Parse(mandescr.Digest)
if err != nil {
return index, indexdata, err
}
size := int64(len(mandescr.Payload))
descriptor := ocispec.Descriptor{
MediaType: mandescr.ContentType,
Digest: digobj,
Size: size,
Platform: man.Subject.Platform,
}
index.Manifests = append(index.Manifests, descriptor)
}
indexdata, err = json.Marshal(index)
if err != nil {
return index, indexdata, err
}
indexdata = indexdata
return index, indexdata, err
}
func descrsFromManifest(name, reference string, manifest *ocispec.Manifest, rawManifest []byte) (descr.Manifest, []descr.Blob, error) {
var err error
mandescr := descr.Manifest{}
//configDescr := descr.Blob{}
blobDescrs := make([]descr.Blob, 0)
timestamp := auxtool.TimeNow()
// Make manifest descriptor
manifestDigest := ocidigest.SHA256.FromBytes(rawManifest).String()
mandescr = descr.Manifest{
ID: auxuuid.NewUUID(),
Name: name,
Reference: reference,
Digest: manifestDigest,
ContentType: manifest.MediaType,
Payload: string(rawManifest),
CreatedAt: timestamp,
UpdatedAt: timestamp,
}
// Make config descriptor
ociConfig := manifest.Config
configDescr := descr.Blob{
ID: auxuuid.NewUUID(),
Name: name,
Reference: reference,
MediaType: ociConfig.MediaType,
Digest: string(ociConfig.Digest),
Size: ociConfig.Size,
CreatedAt: timestamp,
UpdatedAt: timestamp,
}
blobDescrs = append(blobDescrs, configDescr)
// Make blob descriptions
layerMap := make(map[string]bool)
for _, layer := range manifest.Layers {
blobDescr := descr.Blob{
ID: auxuuid.NewUUID(),
Name: name,
Reference: reference,
MediaType: layer.MediaType,
Digest: string(layer.Digest),
Size: layer.Size,
CreatedAt: timestamp,
UpdatedAt: timestamp,
}
_, alreadyAdded := layerMap[string(layer.Digest)]
if !alreadyAdded {
blobDescrs = append(blobDescrs, blobDescr)
layerMap[string(layer.Digest)] = true
}
}
return mandescr, blobDescrs, err
}
func layersDiff(name, reference string, existingManifest, incomingManifest *ocispec.Manifest, rawManifest []byte) ([]descr.Blob, []descr.Blob, error) {
var err error
newBlobDescrs := make([]descr.Blob, 0)
delBlobDescrs := make([]descr.Blob, 0)
// Calculating old layers
delLayers := make([]ocispec.Descriptor, 0)
for _, oldLayer := range existingManifest.Layers {
uniq := true
for _, newLayer := range incomingManifest.Layers {
if oldLayer.Digest == newLayer.Digest {
uniq = false
}
}
if uniq {
delLayers = append(delLayers, oldLayer)
}
}
// Calculating new layers
newLayers := make([]ocispec.Descriptor, 0)
for _, newLayer := range incomingManifest.Layers {
uniq := true
for _, oldLayer := range existingManifest.Layers {
if oldLayer.Digest == newLayer.Digest {
uniq = false
}
}
if uniq {
newLayers = append(newLayers, newLayer)
}
}
if incomingManifest.Config.Digest != existingManifest.Config.Digest {
delLayers = append(delLayers, existingManifest.Config)
newLayers = append(newLayers, incomingManifest.Config)
}
// Converting to new blob
timestamp := auxtool.TimeNow()
for _, layer := range newLayers {
blobDescr := descr.Blob{
ID: auxuuid.NewUUID(),
Name: name,
Reference: reference,
MediaType: layer.MediaType,
Digest: string(layer.Digest),
Size: layer.Size,
CreatedAt: timestamp,
UpdatedAt: timestamp,
}
newBlobDescrs = append(newBlobDescrs, blobDescr)
}
// Converting to old blobs
for _, layer := range delLayers {
blobDescr := descr.Blob{
ID: auxuuid.NewUUID(),
Name: name,
Reference: reference,
MediaType: layer.MediaType,
Digest: string(layer.Digest),
Size: layer.Size,
}
delBlobDescrs = append(delBlobDescrs, blobDescr)
}
return newBlobDescrs, delBlobDescrs, err
}