浏览代码

Remove reference package dependency from the api.

Signed-off-by: David Calavera <david.calavera@gmail.com>
David Calavera 9 年之前
父节点
当前提交
47afe6bd0a

+ 4 - 5
api/server/router/image/backend.go

@@ -4,7 +4,6 @@ import (
 	"io"
 
 	"github.com/docker/docker/api/types/backend"
-	"github.com/docker/docker/reference"
 	"github.com/docker/engine-api/types"
 	"github.com/docker/engine-api/types/registry"
 	"golang.org/x/net/context"
@@ -28,17 +27,17 @@ type imageBackend interface {
 	ImageHistory(imageName string) ([]*types.ImageHistory, error)
 	Images(filterArgs string, filter string, all bool) ([]*types.Image, error)
 	LookupImage(name string) (*types.ImageInspect, error)
-	TagImage(newTag reference.Named, imageName string) error
+	TagImage(imageName, repository, tag string) error
 }
 
 type importExportBackend interface {
 	LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
-	ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
+	ImportImage(src string, repository, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
 	ExportImage(names []string, outStream io.Writer) error
 }
 
 type registryBackend interface {
-	PullImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
-	PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
+	PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
+	PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
 	SearchRegistryForImages(ctx context.Context, term string, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error)
 }

+ 21 - 85
api/server/router/image/image_routes.go

@@ -3,20 +3,17 @@ package image
 import (
 	"encoding/base64"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"io"
 	"net/http"
 	"net/url"
 	"strings"
 
-	"github.com/docker/distribution/digest"
 	"github.com/docker/distribution/registry/api/errcode"
 	"github.com/docker/docker/api/server/httputils"
 	"github.com/docker/docker/api/types/backend"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/streamformatter"
-	"github.com/docker/docker/reference"
 	"github.com/docker/engine-api/types"
 	"github.com/docker/engine-api/types/container"
 	"golang.org/x/net/context"
@@ -89,46 +86,26 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
 	w.Header().Set("Content-Type", "application/json")
 
 	if image != "" { //pull
-		// Special case: "pull -a" may send an image name with a
-		// trailing :. This is ugly, but let's not break API
-		// compatibility.
-		image = strings.TrimSuffix(image, ":")
-
-		var ref reference.Named
-		ref, err = reference.ParseNamed(image)
-		if err == nil {
-			if tag != "" {
-				// The "tag" could actually be a digest.
-				var dgst digest.Digest
-				dgst, err = digest.ParseDigest(tag)
-				if err == nil {
-					ref, err = reference.WithDigest(ref, dgst)
-				} else {
-					ref, err = reference.WithTag(ref, tag)
-				}
+		metaHeaders := map[string][]string{}
+		for k, v := range r.Header {
+			if strings.HasPrefix(k, "X-Meta-") {
+				metaHeaders[k] = v
 			}
-			if err == nil {
-				metaHeaders := map[string][]string{}
-				for k, v := range r.Header {
-					if strings.HasPrefix(k, "X-Meta-") {
-						metaHeaders[k] = v
-					}
-				}
-
-				authEncoded := r.Header.Get("X-Registry-Auth")
-				authConfig := &types.AuthConfig{}
-				if authEncoded != "" {
-					authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
-					if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
-						// for a pull it is not an error if no auth was given
-						// to increase compatibility with the existing api it is defaulting to be empty
-						authConfig = &types.AuthConfig{}
-					}
-				}
-
-				err = s.backend.PullImage(ctx, ref, metaHeaders, authConfig, output)
+		}
+
+		authEncoded := r.Header.Get("X-Registry-Auth")
+		authConfig := &types.AuthConfig{}
+		if authEncoded != "" {
+			authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
+			if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
+				// for a pull it is not an error if no auth was given
+				// to increase compatibility with the existing api it is defaulting to be empty
+				authConfig = &types.AuthConfig{}
 			}
 		}
+
+		err = s.backend.PullImage(ctx, image, tag, metaHeaders, authConfig, output)
+
 		// Check the error from pulling an image to make sure the request
 		// was authorized. Modify the status if the request was
 		// unauthorized to respond with 401 rather than 500.
@@ -136,31 +113,11 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
 			err = errcode.ErrorCodeUnauthorized.WithMessage(fmt.Sprintf("Authentication is required: %s", err))
 		}
 	} else { //import
-		var newRef reference.Named
-		if repo != "" {
-			var err error
-			newRef, err = reference.ParseNamed(repo)
-			if err != nil {
-				return err
-			}
-
-			if _, isCanonical := newRef.(reference.Canonical); isCanonical {
-				return errors.New("cannot import digest reference")
-			}
-
-			if tag != "" {
-				newRef, err = reference.WithTag(newRef, tag)
-				if err != nil {
-					return err
-				}
-			}
-		}
-
 		src := r.Form.Get("fromSrc")
 		// 'err' MUST NOT be defined within this block, we need any error
 		// generated from the download to be available to the output
 		// stream processing below
-		err = s.backend.ImportImage(src, newRef, message, r.Body, output, r.Form["changes"])
+		err = s.backend.ImportImage(src, repo, tag, message, r.Body, output, r.Form["changes"])
 	}
 	if err != nil {
 		if !output.Flushed() {
@@ -200,25 +157,15 @@ func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter,
 		}
 	}
 
-	ref, err := reference.ParseNamed(vars["name"])
-	if err != nil {
-		return err
-	}
+	image := vars["name"]
 	tag := r.Form.Get("tag")
-	if tag != "" {
-		// Push by digest is not supported, so only tags are supported.
-		ref, err = reference.WithTag(ref, tag)
-		if err != nil {
-			return err
-		}
-	}
 
 	output := ioutils.NewWriteFlusher(w)
 	defer output.Close()
 
 	w.Header().Set("Content-Type", "application/json")
 
-	if err := s.backend.PushImage(ctx, ref, metaHeaders, authConfig, output); err != nil {
+	if err := s.backend.PushImage(ctx, image, tag, metaHeaders, authConfig, output); err != nil {
 		if !output.Flushed() {
 			return err
 		}
@@ -322,18 +269,7 @@ func (s *imageRouter) postImagesTag(ctx context.Context, w http.ResponseWriter,
 	if err := httputils.ParseForm(r); err != nil {
 		return err
 	}
-	repo := r.Form.Get("repo")
-	tag := r.Form.Get("tag")
-	newTag, err := reference.WithName(repo)
-	if err != nil {
-		return err
-	}
-	if tag != "" {
-		if newTag, err = reference.WithTag(newTag, tag); err != nil {
-			return err
-		}
-	}
-	if err := s.backend.TagImage(newTag, vars["name"]); err != nil {
+	if err := s.backend.TagImage(vars["name"], r.Form.Get("repo"), r.Form.Get("tag")); err != nil {
 		return err
 	}
 	w.WriteHeader(http.StatusCreated)

+ 2 - 1
builder/builder.go

@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/api/types/backend"
+	"github.com/docker/docker/image"
 	"github.com/docker/docker/reference"
 	"github.com/docker/engine-api/types"
 	"github.com/docker/engine-api/types/container"
@@ -109,7 +110,7 @@ type Backend interface {
 	// GetImageOnBuild looks up a Docker image referenced by `name`.
 	GetImageOnBuild(name string) (Image, error)
 	// TagImage tags an image with newTag
-	TagImage(newTag reference.Named, imageName string) error
+	TagImageWithReference(image.ID, reference.Named) error
 	// PullOnBuild tells Docker to pull image referenced by `name`.
 	PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (Image, error)
 	// ContainerAttachRaw attaches to container.

+ 3 - 1
builder/dockerfile/builder.go

@@ -12,6 +12,7 @@ import (
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/builder"
 	"github.com/docker/docker/builder/dockerfile/parser"
+	"github.com/docker/docker/image"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/reference"
 	"github.com/docker/engine-api/types"
@@ -256,8 +257,9 @@ func (b *Builder) build(config *types.ImageBuildOptions, context builder.Context
 		return "", fmt.Errorf("No image was generated. Is your Dockerfile empty?")
 	}
 
+	imageID := image.ID(b.image)
 	for _, rt := range repoAndTags {
-		if err := b.docker.TagImage(rt, b.image); err != nil {
+		if err := b.docker.TagImageWithReference(imageID, rt); err != nil {
 			return "", err
 		}
 	}

+ 1 - 1
daemon/commit.go

@@ -215,7 +215,7 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
 				return "", err
 			}
 		}
-		if err := daemon.TagImage(newTag, id.String()); err != nil {
+		if err := daemon.TagImageWithReference(id, newTag); err != nil {
 			return "", err
 		}
 	}

+ 0 - 114
daemon/daemon.go

@@ -38,7 +38,6 @@ import (
 	_ "github.com/docker/docker/daemon/graphdriver/register"
 	"github.com/docker/docker/daemon/logger"
 	"github.com/docker/docker/daemon/network"
-	"github.com/docker/docker/distribution"
 	dmetadata "github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/distribution/xfer"
 	"github.com/docker/docker/dockerversion"
@@ -951,21 +950,6 @@ func (daemon *Daemon) changes(container *container.Container) ([]archive.Change,
 	return container.RWLayer.Changes()
 }
 
-// TagImage creates the tag specified by newTag, pointing to the image named
-// imageName (alternatively, imageName can also be an image ID).
-func (daemon *Daemon) TagImage(newTag reference.Named, imageName string) error {
-	imageID, err := daemon.GetImageID(imageName)
-	if err != nil {
-		return err
-	}
-	if err := daemon.referenceStore.AddTag(newTag, imageID, true); err != nil {
-		return err
-	}
-
-	daemon.LogImageEvent(imageID.String(), newTag.String(), "tag")
-	return nil
-}
-
 func writeDistributionProgress(cancelFunc func(), outStream io.Writer, progressChan <-chan progress.Progress) {
 	progressOutput := streamformatter.NewJSONStreamFormatter().NewProgressOutput(outStream, false)
 	operationCancelled := false
@@ -996,69 +980,6 @@ func isBrokenPipe(e error) bool {
 	return e == syscall.EPIPE
 }
 
-// PullImage initiates a pull operation. image is the repository name to pull, and
-// tag may be either empty, or indicate a specific tag to pull.
-func (daemon *Daemon) PullImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
-	// Include a buffer so that slow client connections don't affect
-	// transfer performance.
-	progressChan := make(chan progress.Progress, 100)
-
-	writesDone := make(chan struct{})
-
-	ctx, cancelFunc := context.WithCancel(ctx)
-
-	go func() {
-		writeDistributionProgress(cancelFunc, outStream, progressChan)
-		close(writesDone)
-	}()
-
-	imagePullConfig := &distribution.ImagePullConfig{
-		MetaHeaders:      metaHeaders,
-		AuthConfig:       authConfig,
-		ProgressOutput:   progress.ChanOutput(progressChan),
-		RegistryService:  daemon.RegistryService,
-		ImageEventLogger: daemon.LogImageEvent,
-		MetadataStore:    daemon.distributionMetadataStore,
-		ImageStore:       daemon.imageStore,
-		ReferenceStore:   daemon.referenceStore,
-		DownloadManager:  daemon.downloadManager,
-	}
-
-	err := distribution.Pull(ctx, ref, imagePullConfig)
-	close(progressChan)
-	<-writesDone
-	return err
-}
-
-// PullOnBuild tells Docker to pull image referenced by `name`.
-func (daemon *Daemon) PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (builder.Image, error) {
-	ref, err := reference.ParseNamed(name)
-	if err != nil {
-		return nil, err
-	}
-	ref = reference.WithDefaultTag(ref)
-
-	pullRegistryAuth := &types.AuthConfig{}
-	if len(authConfigs) > 0 {
-		// The request came with a full auth config file, we prefer to use that
-		repoInfo, err := daemon.RegistryService.ResolveRepository(ref)
-		if err != nil {
-			return nil, err
-		}
-
-		resolvedConfig := registry.ResolveAuthConfig(
-			authConfigs,
-			repoInfo.Index,
-		)
-		pullRegistryAuth = &resolvedConfig
-	}
-
-	if err := daemon.PullImage(ctx, ref, nil, pullRegistryAuth, output); err != nil {
-		return nil, err
-	}
-	return daemon.GetImage(name)
-}
-
 // ExportImage exports a list of images to the given output stream. The
 // exported images are archived into a tar when written to the output
 // stream. All images with the given tag and all versions containing
@@ -1069,41 +990,6 @@ func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error {
 	return imageExporter.Save(names, outStream)
 }
 
-// PushImage initiates a push operation on the repository named localName.
-func (daemon *Daemon) PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
-	// Include a buffer so that slow client connections don't affect
-	// transfer performance.
-	progressChan := make(chan progress.Progress, 100)
-
-	writesDone := make(chan struct{})
-
-	ctx, cancelFunc := context.WithCancel(ctx)
-
-	go func() {
-		writeDistributionProgress(cancelFunc, outStream, progressChan)
-		close(writesDone)
-	}()
-
-	imagePushConfig := &distribution.ImagePushConfig{
-		MetaHeaders:      metaHeaders,
-		AuthConfig:       authConfig,
-		ProgressOutput:   progress.ChanOutput(progressChan),
-		RegistryService:  daemon.RegistryService,
-		ImageEventLogger: daemon.LogImageEvent,
-		MetadataStore:    daemon.distributionMetadataStore,
-		LayerStore:       daemon.layerStore,
-		ImageStore:       daemon.imageStore,
-		ReferenceStore:   daemon.referenceStore,
-		TrustKey:         daemon.trustKey,
-		UploadManager:    daemon.uploadManager,
-	}
-
-	err := distribution.Push(ctx, ref, imagePushConfig)
-	close(progressChan)
-	<-writesDone
-	return err
-}
-
 // LookupImage looks up an image by name and returns it as an ImageInspect
 // structure.
 func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {

+ 106 - 0
daemon/image_pull.go

@@ -0,0 +1,106 @@
+package daemon
+
+import (
+	"io"
+	"strings"
+
+	"github.com/docker/distribution/digest"
+	"github.com/docker/docker/builder"
+	"github.com/docker/docker/distribution"
+	"github.com/docker/docker/pkg/progress"
+	"github.com/docker/docker/reference"
+	"github.com/docker/docker/registry"
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// PullImage initiates a pull operation. image is the repository name to pull, and
+// tag may be either empty, or indicate a specific tag to pull.
+func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
+	// Special case: "pull -a" may send an image name with a
+	// trailing :. This is ugly, but let's not break API
+	// compatibility.
+	image = strings.TrimSuffix(image, ":")
+
+	ref, err := reference.ParseNamed(image)
+	if err != nil {
+		return err
+	}
+
+	if tag != "" {
+		// The "tag" could actually be a digest.
+		var dgst digest.Digest
+		dgst, err = digest.ParseDigest(tag)
+		if err == nil {
+			ref, err = reference.WithDigest(ref, dgst)
+		} else {
+			ref, err = reference.WithTag(ref, tag)
+		}
+		if err != nil {
+			return err
+		}
+	}
+
+	return daemon.pullImageWithReference(ctx, ref, metaHeaders, authConfig, outStream)
+}
+
+// PullOnBuild tells Docker to pull image referenced by `name`.
+func (daemon *Daemon) PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (builder.Image, error) {
+	ref, err := reference.ParseNamed(name)
+	if err != nil {
+		return nil, err
+	}
+	ref = reference.WithDefaultTag(ref)
+
+	pullRegistryAuth := &types.AuthConfig{}
+	if len(authConfigs) > 0 {
+		// The request came with a full auth config file, we prefer to use that
+		repoInfo, err := daemon.RegistryService.ResolveRepository(ref)
+		if err != nil {
+			return nil, err
+		}
+
+		resolvedConfig := registry.ResolveAuthConfig(
+			authConfigs,
+			repoInfo.Index,
+		)
+		pullRegistryAuth = &resolvedConfig
+	}
+
+	if err := daemon.pullImageWithReference(ctx, ref, nil, pullRegistryAuth, output); err != nil {
+		return nil, err
+	}
+	return daemon.GetImage(name)
+}
+
+func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
+	// Include a buffer so that slow client connections don't affect
+	// transfer performance.
+	progressChan := make(chan progress.Progress, 100)
+
+	writesDone := make(chan struct{})
+
+	ctx, cancelFunc := context.WithCancel(ctx)
+
+	go func() {
+		writeDistributionProgress(cancelFunc, outStream, progressChan)
+		close(writesDone)
+	}()
+
+	imagePullConfig := &distribution.ImagePullConfig{
+		MetaHeaders:      metaHeaders,
+		AuthConfig:       authConfig,
+		ProgressOutput:   progress.ChanOutput(progressChan),
+		RegistryService:  daemon.RegistryService,
+		ImageEventLogger: daemon.LogImageEvent,
+		MetadataStore:    daemon.distributionMetadataStore,
+		ImageStore:       daemon.imageStore,
+		ReferenceStore:   daemon.referenceStore,
+		DownloadManager:  daemon.downloadManager,
+	}
+
+	err := distribution.Pull(ctx, ref, imagePullConfig)
+	close(progressChan)
+	<-writesDone
+	return err
+}

+ 58 - 0
daemon/image_push.go

@@ -0,0 +1,58 @@
+package daemon
+
+import (
+	"io"
+
+	"github.com/docker/docker/distribution"
+	"github.com/docker/docker/pkg/progress"
+	"github.com/docker/docker/reference"
+	"github.com/docker/engine-api/types"
+	"golang.org/x/net/context"
+)
+
+// PushImage initiates a push operation on the repository named localName.
+func (daemon *Daemon) PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
+	ref, err := reference.ParseNamed(image)
+	if err != nil {
+		return err
+	}
+	if tag != "" {
+		// Push by digest is not supported, so only tags are supported.
+		ref, err = reference.WithTag(ref, tag)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Include a buffer so that slow client connections don't affect
+	// transfer performance.
+	progressChan := make(chan progress.Progress, 100)
+
+	writesDone := make(chan struct{})
+
+	ctx, cancelFunc := context.WithCancel(ctx)
+
+	go func() {
+		writeDistributionProgress(cancelFunc, outStream, progressChan)
+		close(writesDone)
+	}()
+
+	imagePushConfig := &distribution.ImagePushConfig{
+		MetaHeaders:      metaHeaders,
+		AuthConfig:       authConfig,
+		ProgressOutput:   progress.ChanOutput(progressChan),
+		RegistryService:  daemon.RegistryService,
+		ImageEventLogger: daemon.LogImageEvent,
+		MetadataStore:    daemon.distributionMetadataStore,
+		LayerStore:       daemon.layerStore,
+		ImageStore:       daemon.imageStore,
+		ReferenceStore:   daemon.referenceStore,
+		TrustKey:         daemon.trustKey,
+		UploadManager:    daemon.uploadManager,
+	}
+
+	err = distribution.Push(ctx, ref, imagePushConfig)
+	close(progressChan)
+	<-writesDone
+	return err
+}

+ 37 - 0
daemon/image_tag.go

@@ -0,0 +1,37 @@
+package daemon
+
+import (
+	"github.com/docker/docker/image"
+	"github.com/docker/docker/reference"
+)
+
+// TagImage creates the tag specified by newTag, pointing to the image named
+// imageName (alternatively, imageName can also be an image ID).
+func (daemon *Daemon) TagImage(imageName, repository, tag string) error {
+	imageID, err := daemon.GetImageID(imageName)
+	if err != nil {
+		return err
+	}
+
+	newTag, err := reference.WithName(repository)
+	if err != nil {
+		return err
+	}
+	if tag != "" {
+		if newTag, err = reference.WithTag(newTag, tag); err != nil {
+			return err
+		}
+	}
+
+	return daemon.TagImageWithReference(imageID, newTag)
+}
+
+// TagImageWithReference adds the given reference to the image ID provided.
+func (daemon *Daemon) TagImageWithReference(imageID image.ID, newTag reference.Named) error {
+	if err := daemon.referenceStore.AddTag(newTag, imageID, true); err != nil {
+		return err
+	}
+
+	daemon.LogImageEvent(imageID.String(), newTag.String(), "tag")
+	return nil
+}

+ 26 - 5
daemon/import.go

@@ -2,6 +2,7 @@ package daemon
 
 import (
 	"encoding/json"
+	"errors"
 	"io"
 	"net/http"
 	"net/url"
@@ -24,13 +25,33 @@ import (
 // inConfig (if src is "-"), or from a URI specified in src. Progress output is
 // written to outStream. Repository and tag names can optionally be given in
 // the repo and tag arguments, respectively.
-func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
+func (daemon *Daemon) ImportImage(src string, repository, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
 	var (
-		sf   = streamformatter.NewJSONStreamFormatter()
-		rc   io.ReadCloser
-		resp *http.Response
+		sf     = streamformatter.NewJSONStreamFormatter()
+		rc     io.ReadCloser
+		resp   *http.Response
+		newRef reference.Named
 	)
 
+	if repository != "" {
+		var err error
+		newRef, err = reference.ParseNamed(repository)
+		if err != nil {
+			return err
+		}
+
+		if _, isCanonical := newRef.(reference.Canonical); isCanonical {
+			return errors.New("cannot import digest reference")
+		}
+
+		if tag != "" {
+			newRef, err = reference.WithTag(newRef, tag)
+			if err != nil {
+				return err
+			}
+		}
+	}
+
 	config, err := dockerfile.BuildFromConfig(&container.Config{}, changes)
 	if err != nil {
 		return err
@@ -103,7 +124,7 @@ func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string
 
 	// FIXME: connect with commit code and call refstore directly
 	if newRef != nil {
-		if err := daemon.TagImage(newRef, id.String()); err != nil {
+		if err := daemon.TagImageWithReference(id, newRef); err != nil {
 			return err
 		}
 	}