From 7dced311d1119d98dbdd60f6d47fdde5abbff7d7 Mon Sep 17 00:00:00 2001
From: umohnani8 <umohnani@redhat.com>
Date: Wed, 16 May 2018 11:41:08 -0400
Subject: [PATCH] Allow push/save without image reference

If the user uses the image ID when saving to either docker-archive
or oci-archive, then do not save a reference in the manifest/index.json.
If the user chooses to push without an image reference, i.e <transport>:<path>
it should be valid and succeed.

Signed-off-by: umohnani8 <umohnani@redhat.com>

Closes: #782
Approved by: rhatdan
---
 cmd/podman/save.go    | 10 +++++-----
 libpod/image/pull.go  | 12 ++++++++++--
 test/e2e/push_test.go | 18 ++++++++++++++++++
 vendor.conf           |  2 +-
 4 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/cmd/podman/save.go b/cmd/podman/save.go
index c3e87f145b..32ac37f896 100644
--- a/cmd/podman/save.go
+++ b/cmd/podman/save.go
@@ -112,15 +112,15 @@ func saveCmd(c *cli.Context) error {
 	// only one image is supported for now
 	// future pull requests will fix this
 	for _, image := range args {
-		dest := dst
-		// need dest to be in the format transport:path:reference for the following transports
-		if strings.Contains(dst, libpod.OCIArchive) || strings.Contains(dst, libpod.DockerArchive) {
-			dest = dst + ":" + image
-		}
 		newImage, err := runtime.ImageRuntime().NewFromLocal(image)
 		if err != nil {
 			return err
 		}
+		dest := dst
+		// need dest to be in the format transport:path:reference for the following transports
+		if (strings.Contains(dst, libpod.OCIArchive) || strings.Contains(dst, libpod.DockerArchive)) && !strings.Contains(newImage.ID(), image) {
+			dest = dst + ":" + image
+		}
 		if err := newImage.PushImage(getContext(), dest, manifestType, "", "", writer, c.Bool("compress"), libpodImage.SigningOptions{}, &libpodImage.DockerRegistryOptions{}, false); err != nil {
 			if err2 := os.Remove(output); err2 != nil {
 				logrus.Errorf("error deleting %q: %v", output, err)
diff --git a/libpod/image/pull.go b/libpod/image/pull.go
index 2746d1bc5a..38a8435deb 100644
--- a/libpod/image/pull.go
+++ b/libpod/image/pull.go
@@ -123,10 +123,18 @@ func (ir *Runtime) getPullListFromRef(ctx context.Context, srcRef types.ImageRef
 			return nil, errors.Wrapf(err, "error loading manifest for %q", srcRef)
 		}
 
+		var dest string
 		if manifest.Annotations == nil || manifest.Annotations["org.opencontainers.image.ref.name"] == "" {
-			return nil, errors.Errorf("error, archive doesn't have a name annotation. Cannot store image with no name")
+			// If the input image has no image.ref.name, we need to feed it a dest anyways
+			// use the hex of the digest
+			dest, err = getImageDigest(ctx, srcRef, sc)
+			if err != nil {
+				return nil, errors.Wrapf(err, "error getting image digest; image reference not found")
+			}
+		} else {
+			dest = manifest.Annotations["org.opencontainers.image.ref.name"]
 		}
-		pullInfo, err := ir.getPullStruct(srcRef, manifest.Annotations["org.opencontainers.image.ref.name"])
+		pullInfo, err := ir.getPullStruct(srcRef, dest)
 		if err != nil {
 			return nil, err
 		}
diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go
index 46ec4ccbda..b5a1002f25 100644
--- a/test/e2e/push_test.go
+++ b/test/e2e/push_test.go
@@ -206,4 +206,22 @@ var _ = Describe("Podman push", func() {
 		Expect(clean.ExitCode()).To(Equal(0))
 	})
 
+	It("podman push to docker-archive no reference", func() {
+		session := podmanTest.Podman([]string{"push", ALPINE, "docker-archive:/tmp/alp"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		clean := podmanTest.SystemExec("rm", []string{"/tmp/alp"})
+		clean.WaitWithDefaultTimeout()
+		Expect(clean.ExitCode()).To(Equal(0))
+	})
+
+	It("podman push to oci-archive no reference", func() {
+		session := podmanTest.Podman([]string{"push", ALPINE, "oci-archive:/tmp/alp-oci"})
+		session.WaitWithDefaultTimeout()
+		Expect(session.ExitCode()).To(Equal(0))
+		clean := podmanTest.SystemExec("rm", []string{"/tmp/alp-oci"})
+		clean.WaitWithDefaultTimeout()
+		Expect(clean.ExitCode()).To(Equal(0))
+	})
+
 })
diff --git a/vendor.conf b/vendor.conf
index 33e6db9f45..26d1628621 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -10,7 +10,7 @@ github.com/containerd/cgroups 77e628511d924b13a77cebdc73b757a47f6d751b
 github.com/containerd/continuity master
 github.com/containernetworking/cni v0.6.0
 github.com/containernetworking/plugins 1fb94a4222eafc6f948eacdca9c9f2158b427e53
-github.com/containers/image 88423e35d5f11939b0db4fb8f2939fc04adf2463
+github.com/containers/image 3143027065e31d25d8d2b6fe84b250a320fd9130
 github.com/containers/storage e454acf9874d6c399ccb87d03fc4dcbe8c1a4cc6
 github.com/coreos/go-systemd v14
 github.com/cri-o/ocicni master