forked from TrueCloudLab/distribution
1d33874951
Go 1.13 and up enforce import paths to be versioned if a project contains a go.mod and has released v2 or up. The current v2.x branches (and releases) do not yet have a go.mod, and therefore are still allowed to be imported with a non-versioned import path (go modules add a `+incompatible` annotation in that case). However, now that this project has a `go.mod` file, incompatible import paths will not be accepted by go modules, and attempting to use code from this repository will fail. This patch uses `v3` for the import-paths (not `v2`), because changing import paths itself is a breaking change, which means that the next release should increment the "major" version to comply with SemVer (as go modules dictate). Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
98 lines
2.8 KiB
Go
98 lines
2.8 KiB
Go
package schema1
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/distribution/distribution/v3"
|
|
"github.com/distribution/distribution/v3/manifest"
|
|
"github.com/distribution/distribution/v3/reference"
|
|
"github.com/docker/libtrust"
|
|
"github.com/opencontainers/go-digest"
|
|
)
|
|
|
|
// referenceManifestBuilder is a type for constructing manifests from schema1
|
|
// dependencies.
|
|
type referenceManifestBuilder struct {
|
|
Manifest
|
|
pk libtrust.PrivateKey
|
|
}
|
|
|
|
// NewReferenceManifestBuilder is used to build new manifests for the current
|
|
// schema version using schema1 dependencies.
|
|
func NewReferenceManifestBuilder(pk libtrust.PrivateKey, ref reference.Named, architecture string) distribution.ManifestBuilder {
|
|
tag := ""
|
|
if tagged, isTagged := ref.(reference.Tagged); isTagged {
|
|
tag = tagged.Tag()
|
|
}
|
|
|
|
return &referenceManifestBuilder{
|
|
Manifest: Manifest{
|
|
Versioned: manifest.Versioned{
|
|
SchemaVersion: 1,
|
|
},
|
|
Name: ref.Name(),
|
|
Tag: tag,
|
|
Architecture: architecture,
|
|
},
|
|
pk: pk,
|
|
}
|
|
}
|
|
|
|
func (mb *referenceManifestBuilder) Build(ctx context.Context) (distribution.Manifest, error) {
|
|
m := mb.Manifest
|
|
if len(m.FSLayers) == 0 {
|
|
return nil, errors.New("cannot build manifest with zero layers or history")
|
|
}
|
|
|
|
m.FSLayers = make([]FSLayer, len(mb.Manifest.FSLayers))
|
|
m.History = make([]History, len(mb.Manifest.History))
|
|
copy(m.FSLayers, mb.Manifest.FSLayers)
|
|
copy(m.History, mb.Manifest.History)
|
|
|
|
return Sign(&m, mb.pk)
|
|
}
|
|
|
|
// AppendReference adds a reference to the current ManifestBuilder
|
|
func (mb *referenceManifestBuilder) AppendReference(d distribution.Describable) error {
|
|
r, ok := d.(Reference)
|
|
if !ok {
|
|
return fmt.Errorf("unable to add non-reference type to v1 builder")
|
|
}
|
|
|
|
// Entries need to be prepended
|
|
mb.Manifest.FSLayers = append([]FSLayer{{BlobSum: r.Digest}}, mb.Manifest.FSLayers...)
|
|
mb.Manifest.History = append([]History{r.History}, mb.Manifest.History...)
|
|
return nil
|
|
|
|
}
|
|
|
|
// References returns the current references added to this builder
|
|
func (mb *referenceManifestBuilder) References() []distribution.Descriptor {
|
|
refs := make([]distribution.Descriptor, len(mb.Manifest.FSLayers))
|
|
for i := range mb.Manifest.FSLayers {
|
|
layerDigest := mb.Manifest.FSLayers[i].BlobSum
|
|
history := mb.Manifest.History[i]
|
|
ref := Reference{layerDigest, 0, history}
|
|
refs[i] = ref.Descriptor()
|
|
}
|
|
return refs
|
|
}
|
|
|
|
// Reference describes a manifest v2, schema version 1 dependency.
|
|
// An FSLayer associated with a history entry.
|
|
type Reference struct {
|
|
Digest digest.Digest
|
|
Size int64 // if we know it, set it for the descriptor.
|
|
History History
|
|
}
|
|
|
|
// Descriptor describes a reference
|
|
func (r Reference) Descriptor() distribution.Descriptor {
|
|
return distribution.Descriptor{
|
|
MediaType: MediaTypeManifestLayer,
|
|
Digest: r.Digest,
|
|
Size: r.Size,
|
|
}
|
|
}
|