diff --git a/integration/copy_test.go b/integration/copy_test.go index 320b2e8c..d2e979ba 100644 --- a/integration/copy_test.go +++ b/integration/copy_test.go @@ -154,7 +154,10 @@ func (s *CopySuite) TestCopySimple(c *check.C) { // docker v2s2 -> OCI image layout without image name ociDest = "busybox-latest-noimage" defer os.RemoveAll(ociDest) - assertSkopeoFails(c, ".*Error initializing destination oci:busybox-latest-noimage:: cannot save image with empty reference name.*", "copy", "docker://busybox:latest", "oci:"+ociDest) + assertSkopeoSucceeds(c, "", "copy", "docker://busybox:latest", "oci:"+ociDest) + _, err = os.Stat(ociDest) + c.Assert(err, check.IsNil) + } // Check whether dir: images in dir1 and dir2 are equal, ignoring schema1 signatures. diff --git a/vendor/github.com/containers/image/docker/archive/dest.go b/vendor/github.com/containers/image/docker/archive/dest.go index ff149025..c88aea3b 100644 --- a/vendor/github.com/containers/image/docker/archive/dest.go +++ b/vendor/github.com/containers/image/docker/archive/dest.go @@ -17,10 +17,6 @@ type archiveImageDestination struct { } func newImageDestination(sys *types.SystemContext, ref archiveReference) (types.ImageDestination, error) { - if ref.destinationRef == nil { - return nil, errors.Errorf("docker-archive: destination reference not supplied (must be of form :)") - } - // ref.path can be either a pipe or a regular file // in the case of a pipe, we require that we can open it for write // in the case of a regular file, we don't want to overwrite any pre-existing file diff --git a/vendor/github.com/containers/image/docker/archive/transport.go b/vendor/github.com/containers/image/docker/archive/transport.go index f8cb77c0..f345b343 100644 --- a/vendor/github.com/containers/image/docker/archive/transport.go +++ b/vendor/github.com/containers/image/docker/archive/transport.go @@ -41,7 +41,9 @@ func (t archiveTransport) ValidatePolicyConfigurationScope(scope string) error { // archiveReference is an ImageReference for Docker images. type archiveReference struct { - destinationRef reference.NamedTagged // only used for destinations + // only used for destinations + // archiveReference.destinationRef is optional and can be nil for destinations as well. + destinationRef reference.NamedTagged path string } diff --git a/vendor/github.com/containers/image/docker/tarfile/dest.go b/vendor/github.com/containers/image/docker/tarfile/dest.go index 42954c55..b6791af9 100644 --- a/vendor/github.com/containers/image/docker/tarfile/dest.go +++ b/vendor/github.com/containers/image/docker/tarfile/dest.go @@ -23,10 +23,9 @@ import ( // Destination is a partial implementation of types.ImageDestination for writing to an io.Writer. type Destination struct { - writer io.Writer - tar *tar.Writer - reference reference.NamedTagged - repoTags []reference.NamedTagged + writer io.Writer + tar *tar.Writer + repoTags []reference.NamedTagged // Other state. blobs map[digest.Digest]types.BlobInfo // list of already-sent blobs config []byte @@ -34,12 +33,15 @@ type Destination struct { // NewDestination returns a tarfile.Destination for the specified io.Writer. func NewDestination(dest io.Writer, ref reference.NamedTagged) *Destination { + repoTags := []reference.NamedTagged{} + if ref != nil { + repoTags = append(repoTags, ref) + } return &Destination{ - writer: dest, - tar: tar.NewWriter(dest), - reference: ref, - repoTags: []reference.NamedTagged{ref}, - blobs: make(map[digest.Digest]types.BlobInfo), + writer: dest, + tar: tar.NewWriter(dest), + repoTags: repoTags, + blobs: make(map[digest.Digest]types.BlobInfo), } } @@ -168,8 +170,15 @@ func (d *Destination) ReapplyBlob(ctx context.Context, info types.BlobInfo) (typ } func (d *Destination) createRepositoriesFile(rootLayerID string) error { - repositories := map[string]map[string]string{ - d.reference.Name(): {d.reference.Tag(): rootLayerID}} + repositories := map[string]map[string]string{} + for _, repoTag := range d.repoTags { + if val, ok := repositories[repoTag.Name()]; ok { + val[repoTag.Tag()] = rootLayerID + } else { + repositories[repoTag.Name()] = map[string]string{repoTag.Tag(): rootLayerID} + } + } + b, err := json.Marshal(repositories) if err != nil { return errors.Wrap(err, "Error marshaling repositories") diff --git a/vendor/github.com/containers/image/oci/layout/oci_dest.go b/vendor/github.com/containers/image/oci/layout/oci_dest.go index e0761c69..a1e27b5d 100644 --- a/vendor/github.com/containers/image/oci/layout/oci_dest.go +++ b/vendor/github.com/containers/image/oci/layout/oci_dest.go @@ -25,10 +25,6 @@ type ociImageDestination struct { // newImageDestination returns an ImageDestination for writing to an existing directory. func newImageDestination(sys *types.SystemContext, ref ociReference) (types.ImageDestination, error) { - if ref.image == "" { - return nil, errors.Errorf("cannot save image with empty reference name (syntax must be of form ::)") - } - var index *imgspecv1.Index if indexExists(ref) { var err error @@ -217,13 +213,11 @@ func (d *ociImageDestination) PutManifest(ctx context.Context, m []byte) error { return err } - if d.ref.image == "" { - return errors.Errorf("cannot save image with empyt image.ref.name") + if d.ref.image != "" { + annotations := make(map[string]string) + annotations["org.opencontainers.image.ref.name"] = d.ref.image + desc.Annotations = annotations } - - annotations := make(map[string]string) - annotations["org.opencontainers.image.ref.name"] = d.ref.image - desc.Annotations = annotations desc.Platform = &imgspecv1.Platform{ Architecture: runtime.GOARCH, OS: runtime.GOOS, diff --git a/vendor/github.com/containers/image/oci/layout/oci_transport.go b/vendor/github.com/containers/image/oci/layout/oci_transport.go index 95a9def2..857c8081 100644 --- a/vendor/github.com/containers/image/oci/layout/oci_transport.go +++ b/vendor/github.com/containers/image/oci/layout/oci_transport.go @@ -55,7 +55,9 @@ type ociReference struct { // (But in general, we make no attempt to be completely safe against concurrent hostile filesystem modifications.) dir string // As specified by the user. May be relative, contain symlinks, etc. resolvedDir string // Absolute path with no symlinks, at least at the time of its creation. Primarily used for policy namespaces. - image string // If image=="", it means the only image in the index.json is used + // If image=="", it means the "only image" in the index.json is used in the case it is a source + // for destinations, the image name annotation "image.ref.name" is not added to the index.json + image string } // ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an OCI ImageReference. diff --git a/vendor/github.com/containers/image/pkg/docker/config/config.go b/vendor/github.com/containers/image/pkg/docker/config/config.go index 3edab053..724aef4e 100644 --- a/vendor/github.com/containers/image/pkg/docker/config/config.go +++ b/vendor/github.com/containers/image/pkg/docker/config/config.go @@ -149,13 +149,15 @@ func getPathToAuth(sys *types.SystemContext) (string, error) { runtimeDir := os.Getenv("XDG_RUNTIME_DIR") if runtimeDir != "" { + // This function does not in general need to separately check that the returned path exists; that’s racy, and callers will fail accessing the file anyway. + // We are checking for os.IsNotExist here only to give the user better guidance what to do in this special case. _, err := os.Stat(runtimeDir) if os.IsNotExist(err) { // This means the user set the XDG_RUNTIME_DIR variable and either forgot to create the directory - // or made a typo while setting the environment variable - // so we log the error and return an empty string as the path + // or made a typo while setting the environment variable, + // so return an error referring to $XDG_RUNTIME_DIR instead of …/authCfgFileName inside. return "", errors.Wrapf(err, "%q directory set by $XDG_RUNTIME_DIR does not exist. Either create the directory or unset $XDG_RUNTIME_DIR.", runtimeDir) - } + } // else ignore err and let the caller fail accessing …/authCfgFileName. runtimeDir = filepath.Join(runtimeDir, authCfg) } else { runtimeDir = filepath.Join(defaultPath, authCfg, strconv.Itoa(os.Getuid()))