From 2655954c2dd9d92c2394b04e4262543174c4c038 Mon Sep 17 00:00:00 2001
From: Tonis Tiigi <tonistiigi@gmail.com>
Date: Fri, 4 Dec 2015 13:55:15 -0800
Subject: [PATCH] Add own reference package wrapper

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
---
 api/client/build.go                |  9 ++--
 api/client/commit.go               |  6 +--
 api/client/create.go               | 23 +++++-----
 api/client/images.go               |  6 +--
 api/client/import.go               |  2 +-
 api/client/pull.go                 |  9 ++--
 api/client/push.go                 |  6 +--
 api/client/tag.go                  |  7 ++-
 api/client/trust.go                |  2 +-
 api/server/router/local/image.go   | 13 +++---
 daemon/commit.go                   |  2 +-
 daemon/daemon.go                   | 37 ++++++++-------
 daemon/daemon_unix.go              |  4 +-
 daemon/daemon_windows.go           |  7 ++-
 daemon/daemonbuilder/builder.go    |  6 +--
 daemon/errors.go                   |  7 ++-
 daemon/events/filter.go            |  2 +-
 daemon/image_delete.go             | 19 ++++----
 daemon/images.go                   | 12 ++---
 daemon/import.go                   |  4 +-
 distribution/pull.go               |  7 ++-
 distribution/pull_v1.go            |  8 ++--
 distribution/pull_v2.go            | 20 ++++----
 distribution/pull_v2_test.go       |  4 +-
 distribution/push.go               |  9 ++--
 distribution/push_v1.go            | 13 +++---
 distribution/push_v2.go            | 19 ++++----
 distribution/registry_unit_test.go |  2 +-
 image/tarexport/load.go            |  6 +--
 image/tarexport/save.go            | 13 +++---
 image/tarexport/tarexport.go       |  8 ++--
 migrate/v1/migratev1.go            | 15 +++---
 migrate/v1/migratev1_test.go       |  8 ++--
 reference/reference.go             | 60 ++++++++++++++++++++++++
 {tag => reference}/store.go        | 73 +++++++++++++++---------------
 {tag => reference}/store_test.go   | 41 ++++++++---------
 registry/config.go                 |  9 ++--
 registry/registry_mock_test.go     |  2 +-
 registry/registry_test.go          |  2 +-
 registry/service.go                |  2 +-
 registry/service_v1.go             |  2 +-
 registry/service_v2.go             |  2 +-
 registry/session.go                |  2 +-
 registry/types.go                  |  2 +-
 44 files changed, 278 insertions(+), 234 deletions(-)
 create mode 100644 reference/reference.go
 rename {tag => reference}/store.go (76%)
 rename {tag => reference}/store_test.go (89%)

diff --git a/api/client/build.go b/api/client/build.go
index d0930e11f1..ec47c6e49c 100644
--- a/api/client/build.go
+++ b/api/client/build.go
@@ -13,7 +13,6 @@ import (
 	"runtime"
 	"strings"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/builder/dockerignore"
@@ -29,8 +28,8 @@ import (
 	"github.com/docker/docker/pkg/streamformatter"
 	"github.com/docker/docker/pkg/ulimit"
 	"github.com/docker/docker/pkg/urlutil"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
-	tagpkg "github.com/docker/docker/tag"
 	"github.com/docker/docker/utils"
 	"github.com/docker/go-units"
 )
@@ -532,11 +531,11 @@ func rewriteDockerfileFrom(dockerfileName string, translator func(reference.Name
 
 			digested := false
 			switch ref.(type) {
-			case reference.Tagged:
-			case reference.Digested:
+			case reference.NamedTagged:
+			case reference.Canonical:
 				digested = true
 			default:
-				ref, err = reference.WithTag(ref, tagpkg.DefaultTag)
+				ref, err = reference.WithTag(ref, reference.DefaultTag)
 				if err != nil {
 					return nil, nil, err
 				}
diff --git a/api/client/commit.go b/api/client/commit.go
index b75520b243..9209cec22c 100644
--- a/api/client/commit.go
+++ b/api/client/commit.go
@@ -5,11 +5,11 @@ import (
 	"errors"
 	"fmt"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	Cli "github.com/docker/docker/cli"
 	"github.com/docker/docker/opts"
 	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/runconfig"
 )
@@ -51,9 +51,9 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
 		repositoryName = ref.Name()
 
 		switch x := ref.(type) {
-		case reference.Digested:
+		case reference.Canonical:
 			return errors.New("cannot commit to digest reference")
-		case reference.Tagged:
+		case reference.NamedTagged:
 			tag = x.Tag()
 		}
 	}
diff --git a/api/client/create.go b/api/client/create.go
index 857ef90aac..60d1838e28 100644
--- a/api/client/create.go
+++ b/api/client/create.go
@@ -5,14 +5,13 @@ import (
 	"io"
 	"os"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/client/lib"
 	"github.com/docker/docker/api/types"
 	Cli "github.com/docker/docker/cli"
 	"github.com/docker/docker/pkg/jsonmessage"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/runconfig"
-	tagpkg "github.com/docker/docker/tag"
 )
 
 func (cli *DockerCli) pullImage(image string) error {
@@ -27,13 +26,13 @@ func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
 
 	var tag string
 	switch x := ref.(type) {
-	case reference.Digested:
+	case reference.Canonical:
 		tag = x.Digest().String()
-	case reference.Tagged:
+	case reference.NamedTagged:
 		tag = x.Tag()
 	default:
 		// pull only the image tagged 'latest' if no tag was specified
-		tag = tagpkg.DefaultTag
+		tag = reference.DefaultTag
 	}
 
 	// Resolve the Repository name from fqn to RepositoryInfo
@@ -99,13 +98,13 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc
 		return nil, err
 	}
 
-	isDigested := false
+	isCanonical := false
 	switch ref.(type) {
-	case reference.Tagged:
-	case reference.Digested:
-		isDigested = true
+	case reference.NamedTagged:
+	case reference.Canonical:
+		isCanonical = true
 	default:
-		ref, err = reference.WithTag(ref, tagpkg.DefaultTag)
+		ref, err = reference.WithTag(ref, reference.DefaultTag)
 		if err != nil {
 			return nil, err
 		}
@@ -113,7 +112,7 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc
 
 	var trustedRef reference.Canonical
 
-	if isTrusted() && !isDigested {
+	if isTrusted() && !isCanonical {
 		var err error
 		trustedRef, err = cli.trustedReference(ref.(reference.NamedTagged))
 		if err != nil {
@@ -133,7 +132,7 @@ func (cli *DockerCli) createContainer(config *runconfig.Config, hostConfig *runc
 			if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil {
 				return nil, err
 			}
-			if trustedRef != nil && !isDigested {
+			if trustedRef != nil && !isCanonical {
 				if err := cli.tagTrusted(trustedRef, ref.(reference.NamedTagged)); err != nil {
 					return nil, err
 				}
diff --git a/api/client/images.go b/api/client/images.go
index 346c761bbb..d2d04f8131 100644
--- a/api/client/images.go
+++ b/api/client/images.go
@@ -6,13 +6,13 @@ import (
 	"text/tabwriter"
 	"time"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	Cli "github.com/docker/docker/cli"
 	"github.com/docker/docker/opts"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/reference"
 	"github.com/docker/go-units"
 )
 
@@ -98,9 +98,9 @@ func (cli *DockerCli) CmdImages(args ...string) error {
 				repo = ref.Name()
 
 				switch x := ref.(type) {
-				case reference.Digested:
+				case reference.Canonical:
 					digest = x.Digest().String()
-				case reference.Tagged:
+				case reference.NamedTagged:
 					tag = x.Tag()
 				}
 			}
diff --git a/api/client/import.go b/api/client/import.go
index 2e9be55f57..1b829c4374 100644
--- a/api/client/import.go
+++ b/api/client/import.go
@@ -5,13 +5,13 @@ import (
 	"io"
 	"os"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	Cli "github.com/docker/docker/cli"
 	"github.com/docker/docker/opts"
 	"github.com/docker/docker/pkg/jsonmessage"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/urlutil"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 )
 
diff --git a/api/client/pull.go b/api/client/pull.go
index 0144d99e7f..43cbc9e253 100644
--- a/api/client/pull.go
+++ b/api/client/pull.go
@@ -4,14 +4,13 @@ import (
 	"errors"
 	"fmt"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/client/lib"
 	"github.com/docker/docker/api/types"
 	Cli "github.com/docker/docker/cli"
 	"github.com/docker/docker/pkg/jsonmessage"
 	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
-	tagpkg "github.com/docker/docker/tag"
 )
 
 var errTagCantBeUsed = errors.New("tag can't be used with --all-tags/-a")
@@ -35,19 +34,19 @@ func (cli *DockerCli) CmdPull(args ...string) error {
 
 	var tag string
 	switch x := distributionRef.(type) {
-	case reference.Digested:
+	case reference.Canonical:
 		if *allTags {
 			return errTagCantBeUsed
 		}
 		tag = x.Digest().String()
-	case reference.Tagged:
+	case reference.NamedTagged:
 		if *allTags {
 			return errTagCantBeUsed
 		}
 		tag = x.Tag()
 	default:
 		if !*allTags {
-			tag = tagpkg.DefaultTag
+			tag = reference.DefaultTag
 			distributionRef, err = reference.WithTag(distributionRef, tag)
 			if err != nil {
 				return err
diff --git a/api/client/push.go b/api/client/push.go
index 5bfd82d390..cc78c3c5b3 100644
--- a/api/client/push.go
+++ b/api/client/push.go
@@ -4,12 +4,12 @@ import (
 	"errors"
 	"io"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/client/lib"
 	"github.com/docker/docker/api/types"
 	Cli "github.com/docker/docker/cli"
 	"github.com/docker/docker/pkg/jsonmessage"
 	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 )
 
@@ -30,9 +30,9 @@ func (cli *DockerCli) CmdPush(args ...string) error {
 
 	var tag string
 	switch x := ref.(type) {
-	case reference.Digested:
+	case reference.Canonical:
 		return errors.New("cannot push a digest reference")
-	case reference.Tagged:
+	case reference.NamedTagged:
 		tag = x.Tag()
 	}
 
diff --git a/api/client/tag.go b/api/client/tag.go
index 385a155c58..203d64421f 100644
--- a/api/client/tag.go
+++ b/api/client/tag.go
@@ -3,10 +3,10 @@ package client
 import (
 	"errors"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	Cli "github.com/docker/docker/cli"
 	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 )
 
@@ -25,13 +25,12 @@ func (cli *DockerCli) CmdTag(args ...string) error {
 		return err
 	}
 
-	_, isDigested := ref.(reference.Digested)
-	if isDigested {
+	if _, isCanonical := ref.(reference.Canonical); isCanonical {
 		return errors.New("refusing to create a tag with a digest reference")
 	}
 
 	tag := ""
-	tagged, isTagged := ref.(reference.Tagged)
+	tagged, isTagged := ref.(reference.NamedTagged)
 	if isTagged {
 		tag = tagged.Tag()
 	}
diff --git a/api/client/trust.go b/api/client/trust.go
index 14d52c48ae..9a18628b28 100644
--- a/api/client/trust.go
+++ b/api/client/trust.go
@@ -19,7 +19,6 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/distribution/registry/client/auth"
 	"github.com/docker/distribution/registry/client/transport"
 	"github.com/docker/docker/api/client/lib"
@@ -30,6 +29,7 @@ import (
 	"github.com/docker/docker/pkg/ioutils"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/tlsconfig"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"github.com/docker/notary/client"
 	"github.com/docker/notary/passphrase"
diff --git a/api/server/router/local/image.go b/api/server/router/local/image.go
index ce3ec3cd5d..15273ac276 100644
--- a/api/server/router/local/image.go
+++ b/api/server/router/local/image.go
@@ -12,7 +12,6 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/server/httputils"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/builder"
@@ -25,8 +24,8 @@ import (
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/streamformatter"
 	"github.com/docker/docker/pkg/ulimit"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/runconfig"
-	tagpkg "github.com/docker/docker/tag"
 	"github.com/docker/docker/utils"
 	"golang.org/x/net/context"
 )
@@ -156,7 +155,7 @@ func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r
 			}
 
 			switch newRef.(type) {
-			case reference.Digested:
+			case reference.Canonical:
 				return errors.New("cannot import digest reference")
 			}
 
@@ -498,12 +497,12 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
 			return nil, err
 		}
 
-		if _, isDigested := ref.(reference.Digested); isDigested {
-			return nil, errors.New("build tag cannot be a digest")
+		if _, isCanonical := ref.(reference.Canonical); isCanonical {
+			return nil, errors.New("build tag cannot contain a digest")
 		}
 
-		if _, isTagged := ref.(reference.Tagged); !isTagged {
-			ref, err = reference.WithTag(ref, tagpkg.DefaultTag)
+		if _, isTagged := ref.(reference.NamedTagged); !isTagged {
+			ref, err = reference.WithTag(ref, reference.DefaultTag)
 		}
 
 		nameWithTag := ref.String()
diff --git a/daemon/commit.go b/daemon/commit.go
index 1d3d738959..3e5744c0c2 100644
--- a/daemon/commit.go
+++ b/daemon/commit.go
@@ -7,7 +7,6 @@ import (
 	"strings"
 	"time"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/dockerversion"
@@ -15,6 +14,7 @@ import (
 	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/ioutils"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/runconfig"
 )
 
diff --git a/daemon/daemon.go b/daemon/daemon.go
index 2e38e6838c..73dc8d5b1b 100644
--- a/daemon/daemon.go
+++ b/daemon/daemon.go
@@ -19,7 +19,6 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
@@ -58,9 +57,9 @@ import (
 	"github.com/docker/docker/pkg/sysinfo"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/truncindex"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/runconfig"
-	"github.com/docker/docker/tag"
 	"github.com/docker/docker/utils"
 	volumedrivers "github.com/docker/docker/volume/drivers"
 	"github.com/docker/docker/volume/local"
@@ -138,7 +137,7 @@ type Daemon struct {
 	repository                string
 	containers                *contStore
 	execCommands              *exec.Store
-	tagStore                  tag.Store
+	referenceStore            reference.Store
 	downloadManager           *xfer.LayerDownloadManager
 	uploadManager             *xfer.LayerUploadManager
 	distributionMetadataStore dmetadata.Store
@@ -789,16 +788,16 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
 
 	eventsService := events.New()
 
-	tagStore, err := tag.NewTagStore(filepath.Join(imageRoot, "repositories.json"))
+	referenceStore, err := reference.NewReferenceStore(filepath.Join(imageRoot, "repositories.json"))
 	if err != nil {
 		return nil, fmt.Errorf("Couldn't create Tag store repositories: %s", err)
 	}
 
-	if err := restoreCustomImage(d.driver, d.imageStore, d.layerStore, tagStore); err != nil {
+	if err := restoreCustomImage(d.driver, d.imageStore, d.layerStore, referenceStore); err != nil {
 		return nil, fmt.Errorf("Couldn't restore custom images: %s", err)
 	}
 
-	if err := v1.Migrate(config.Root, d.driver.String(), d.layerStore, d.imageStore, tagStore, distributionMetadataStore); err != nil {
+	if err := v1.Migrate(config.Root, d.driver.String(), d.layerStore, d.imageStore, referenceStore, distributionMetadataStore); err != nil {
 		return nil, err
 	}
 
@@ -848,7 +847,7 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo
 	d.repository = daemonRepo
 	d.containers = &contStore{s: make(map[string]*container.Container)}
 	d.execCommands = exec.NewStore()
-	d.tagStore = tagStore
+	d.referenceStore = referenceStore
 	d.distributionMetadataStore = distributionMetadataStore
 	d.trustKey = trustKey
 	d.idIndex = truncindex.NewTruncIndex([]string{})
@@ -1045,7 +1044,7 @@ func (daemon *Daemon) TagImage(newTag reference.Named, imageName string) error {
 		return err
 	}
 	newTag = registry.NormalizeLocalReference(newTag)
-	if err := daemon.tagStore.AddTag(newTag, imageID, true); err != nil {
+	if err := daemon.referenceStore.AddTag(newTag, imageID, true); err != nil {
 		return err
 	}
 	daemon.EventsService.Log("tag", newTag.String(), "")
@@ -1091,7 +1090,7 @@ func (daemon *Daemon) PullImage(ref reference.Named, metaHeaders map[string][]st
 		EventsService:   daemon.EventsService,
 		MetadataStore:   daemon.distributionMetadataStore,
 		ImageStore:      daemon.imageStore,
-		TagStore:        daemon.tagStore,
+		ReferenceStore:  daemon.referenceStore,
 		DownloadManager: daemon.downloadManager,
 	}
 
@@ -1107,7 +1106,7 @@ func (daemon *Daemon) PullImage(ref reference.Named, metaHeaders map[string][]st
 // the same tag are exported. names is the set of tags to export, and
 // outStream is the writer which the images are written to.
 func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error {
-	imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.tagStore)
+	imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore)
 	return imageExporter.Save(names, outStream)
 }
 
@@ -1135,7 +1134,7 @@ func (daemon *Daemon) PushImage(ref reference.Named, metaHeaders map[string][]st
 		MetadataStore:   daemon.distributionMetadataStore,
 		LayerStore:      daemon.layerStore,
 		ImageStore:      daemon.imageStore,
-		TagStore:        daemon.tagStore,
+		ReferenceStore:  daemon.referenceStore,
 		TrustKey:        daemon.trustKey,
 		UploadManager:   daemon.uploadManager,
 	}
@@ -1154,14 +1153,14 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
 		return nil, fmt.Errorf("No such image: %s", name)
 	}
 
-	refs := daemon.tagStore.References(img.ID())
+	refs := daemon.referenceStore.References(img.ID())
 	repoTags := []string{}
 	repoDigests := []string{}
 	for _, ref := range refs {
 		switch ref.(type) {
-		case reference.Tagged:
+		case reference.NamedTagged:
 			repoTags = append(repoTags, ref.String())
-		case reference.Digested:
+		case reference.Canonical:
 			repoDigests = append(repoDigests, ref.String())
 		}
 	}
@@ -1215,7 +1214,7 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
 // complement of ImageExport.  The input stream is an uncompressed tar
 // ball containing images and metadata.
 func (daemon *Daemon) LoadImage(inTar io.ReadCloser, outStream io.Writer) error {
-	imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.tagStore)
+	imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore)
 	return imageExporter.Load(inTar, outStream)
 }
 
@@ -1271,7 +1270,7 @@ func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) {
 		h.ID = id.String()
 
 		var tags []string
-		for _, r := range daemon.tagStore.References(id) {
+		for _, r := range daemon.referenceStore.References(id) {
 			if _, ok := r.(reference.NamedTagged); ok {
 				tags = append(tags, r.String())
 			}
@@ -1303,12 +1302,12 @@ func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) {
 	// Treat it as a possible tag or digest reference
 	if ref, err := reference.ParseNamed(refOrID); err == nil {
 		ref = registry.NormalizeLocalReference(ref)
-		if id, err := daemon.tagStore.Get(ref); err == nil {
+		if id, err := daemon.referenceStore.Get(ref); err == nil {
 			return id, nil
 		}
-		if tagged, ok := ref.(reference.Tagged); ok {
+		if tagged, ok := ref.(reference.NamedTagged); ok {
 			if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil {
-				for _, namedRef := range daemon.tagStore.References(id) {
+				for _, namedRef := range daemon.referenceStore.References(id) {
 					if namedRef.Name() == ref.Name() {
 						return id, nil
 					}
diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go
index 1fc0a1b493..753bffe1e2 100755
--- a/daemon/daemon_unix.go
+++ b/daemon/daemon_unix.go
@@ -22,8 +22,8 @@ import (
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers/kernel"
 	"github.com/docker/docker/pkg/sysinfo"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/runconfig"
-	"github.com/docker/docker/tag"
 	"github.com/docker/libnetwork"
 	nwconfig "github.com/docker/libnetwork/config"
 	"github.com/docker/libnetwork/drivers/bridge"
@@ -694,7 +694,7 @@ func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container
 	daemon.Unmount(container)
 }
 
-func restoreCustomImage(driver graphdriver.Driver, is image.Store, ls layer.Store, ts tag.Store) error {
+func restoreCustomImage(driver graphdriver.Driver, is image.Store, ls layer.Store, rs reference.Store) error {
 	// Unix has no custom images to register
 	return nil
 }
diff --git a/daemon/daemon_windows.go b/daemon/daemon_windows.go
index bd35a2ee95..4ef30eb927 100644
--- a/daemon/daemon_windows.go
+++ b/daemon/daemon_windows.go
@@ -9,13 +9,12 @@ import (
 	"strings"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/container"
 	"github.com/docker/docker/daemon/graphdriver"
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
-	"github.com/docker/docker/tag"
+	"github.com/docker/docker/reference"
 	// register the windows graph driver
 	"github.com/docker/docker/daemon/graphdriver/windows"
 	"github.com/docker/docker/pkg/system"
@@ -153,7 +152,7 @@ func (daemon *Daemon) conditionalUnmountOnCleanup(container *container.Container
 	}
 }
 
-func restoreCustomImage(driver graphdriver.Driver, is image.Store, ls layer.Store, ts tag.Store) error {
+func restoreCustomImage(driver graphdriver.Driver, is image.Store, ls layer.Store, rs reference.Store) error {
 	if wd, ok := driver.(*windows.Driver); ok {
 		imageInfos, err := wd.GetCustomImageInfos()
 		if err != nil {
@@ -206,7 +205,7 @@ func restoreCustomImage(driver graphdriver.Driver, is image.Store, ls layer.Stor
 				return err
 			}
 
-			if err := ts.AddTag(ref, id, true); err != nil {
+			if err := rs.AddTag(ref, id, true); err != nil {
 				return err
 			}
 
diff --git a/daemon/daemonbuilder/builder.go b/daemon/daemonbuilder/builder.go
index 6da9896301..09bab93a4a 100644
--- a/daemon/daemonbuilder/builder.go
+++ b/daemon/daemonbuilder/builder.go
@@ -9,7 +9,6 @@ import (
 	"strings"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/builder"
@@ -20,6 +19,7 @@ import (
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/urlutil"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/runconfig"
 )
@@ -42,8 +42,8 @@ func (d Docker) Pull(name string) (*image.Image, error) {
 		return nil, err
 	}
 	switch ref.(type) {
-	case reference.Tagged:
-	case reference.Digested:
+	case reference.NamedTagged:
+	case reference.Canonical:
 	default:
 		ref, err = reference.WithTag(ref, "latest")
 		if err != nil {
diff --git a/daemon/errors.go b/daemon/errors.go
index 8ab411c0f0..8fff66b9ff 100644
--- a/daemon/errors.go
+++ b/daemon/errors.go
@@ -3,9 +3,8 @@ package daemon
 import (
 	"strings"
 
-	"github.com/docker/distribution/reference"
 	derr "github.com/docker/docker/errors"
-	tagpkg "github.com/docker/docker/tag"
+	"github.com/docker/docker/reference"
 )
 
 func (d *Daemon) imageNotExistToErrcode(err error) error {
@@ -13,12 +12,12 @@ func (d *Daemon) imageNotExistToErrcode(err error) error {
 		if strings.Contains(dne.RefOrID, "@") {
 			return derr.ErrorCodeNoSuchImageHash.WithArgs(dne.RefOrID)
 		}
-		tag := tagpkg.DefaultTag
+		tag := reference.DefaultTag
 		ref, err := reference.ParseNamed(dne.RefOrID)
 		if err != nil {
 			return derr.ErrorCodeNoSuchImageTag.WithArgs(dne.RefOrID, tag)
 		}
-		if tagged, isTagged := ref.(reference.Tagged); isTagged {
+		if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
 			tag = tagged.Tag()
 		}
 		return derr.ErrorCodeNoSuchImageTag.WithArgs(ref.Name(), tag)
diff --git a/daemon/events/filter.go b/daemon/events/filter.go
index fa751d54b5..084346cfff 100644
--- a/daemon/events/filter.go
+++ b/daemon/events/filter.go
@@ -1,9 +1,9 @@
 package events
 
 import (
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/pkg/jsonmessage"
+	"github.com/docker/docker/reference"
 )
 
 // Filter can filter out docker events from a stream
diff --git a/daemon/image_delete.go b/daemon/image_delete.go
index e2503c01d6..6d8b7b1bac 100644
--- a/daemon/image_delete.go
+++ b/daemon/image_delete.go
@@ -4,13 +4,12 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/container"
 	derr "github.com/docker/docker/errors"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/pkg/stringid"
-	tagpkg "github.com/docker/docker/tag"
+	"github.com/docker/docker/reference"
 )
 
 // ImageDelete deletes the image referenced by the given imageRef from this
@@ -58,7 +57,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
 		return nil, daemon.imageNotExistToErrcode(err)
 	}
 
-	repoRefs := daemon.tagStore.References(imgID)
+	repoRefs := daemon.referenceStore.References(imgID)
 
 	var removedRepositoryRef bool
 	if !isImageIDPrefix(imgID.String(), imageRef) {
@@ -151,11 +150,11 @@ func (daemon *Daemon) getContainerUsingImage(imageID image.ID) *container.Contai
 // tag is used. Returns the resolved image reference and an error.
 func (daemon *Daemon) removeImageRef(ref reference.Named) (reference.Named, error) {
 	switch ref.(type) {
-	case reference.Tagged:
-	case reference.Digested:
+	case reference.NamedTagged:
+	case reference.Canonical:
 	default:
 		var err error
-		ref, err = reference.WithTag(ref, tagpkg.DefaultTag)
+		ref, err = reference.WithTag(ref, reference.DefaultTag)
 		if err != nil {
 			return nil, err
 		}
@@ -164,7 +163,7 @@ func (daemon *Daemon) removeImageRef(ref reference.Named) (reference.Named, erro
 	// Ignore the boolean value returned, as far as we're concerned, this
 	// is an idempotent operation and it's okay if the reference didn't
 	// exist in the first place.
-	_, err := daemon.tagStore.Delete(ref)
+	_, err := daemon.referenceStore.Delete(ref)
 
 	return ref, err
 }
@@ -175,7 +174,7 @@ func (daemon *Daemon) removeImageRef(ref reference.Named) (reference.Named, erro
 // daemon's event service. An "Untagged" types.ImageDelete is added to the
 // given list of records.
 func (daemon *Daemon) removeAllReferencesToImageID(imgID image.ID, records *[]types.ImageDelete) error {
-	imageRefs := daemon.tagStore.References(imgID)
+	imageRefs := daemon.referenceStore.References(imgID)
 
 	for _, imageRef := range imageRefs {
 		parsedRef, err := daemon.removeImageRef(imageRef)
@@ -325,7 +324,7 @@ func (daemon *Daemon) checkImageDeleteHardConflict(imgID image.ID) *imageDeleteC
 
 func (daemon *Daemon) checkImageDeleteSoftConflict(imgID image.ID) *imageDeleteConflict {
 	// Check if any repository tags/digest reference this image.
-	if len(daemon.tagStore.References(imgID)) > 0 {
+	if len(daemon.referenceStore.References(imgID)) > 0 {
 		return &imageDeleteConflict{
 			imgID:   imgID,
 			message: "image is referenced in one or more repositories",
@@ -355,5 +354,5 @@ func (daemon *Daemon) checkImageDeleteSoftConflict(imgID image.ID) *imageDeleteC
 // that there are no repository references to the given image and it has no
 // child images.
 func (daemon *Daemon) imageIsDangling(imgID image.ID) bool {
-	return !(len(daemon.tagStore.References(imgID)) > 0 || len(daemon.imageStore.Children(imgID)) > 0)
+	return !(len(daemon.referenceStore.References(imgID)) > 0 || len(daemon.imageStore.Children(imgID)) > 0)
 }
diff --git a/daemon/images.go b/daemon/images.go
index 9220400271..a5ed6b18f3 100644
--- a/daemon/images.go
+++ b/daemon/images.go
@@ -5,11 +5,11 @@ import (
 	"path"
 	"sort"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
+	"github.com/docker/docker/reference"
 )
 
 var acceptedImageFilterTags = map[string]bool{
@@ -68,9 +68,9 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Imag
 
 	var filterTagged bool
 	if filter != "" {
-		filterRef, err := reference.Parse(filter)
+		filterRef, err := reference.ParseNamed(filter)
 		if err == nil { // parse error means wildcard repo
-			if _, ok := filterRef.(reference.Tagged); ok {
+			if _, ok := filterRef.(reference.NamedTagged); ok {
 				filterTagged = true
 			}
 		}
@@ -105,7 +105,7 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Imag
 
 		newImage := newImage(img, size)
 
-		for _, ref := range daemon.tagStore.References(id) {
+		for _, ref := range daemon.referenceStore.References(id) {
 			if filter != "" { // filter by tag/repo name
 				if filterTagged { // filter by tag, require full ref match
 					if ref.String() != filter {
@@ -115,10 +115,10 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Imag
 					continue
 				}
 			}
-			if _, ok := ref.(reference.Digested); ok {
+			if _, ok := ref.(reference.Canonical); ok {
 				newImage.RepoDigests = append(newImage.RepoDigests, ref.String())
 			}
-			if _, ok := ref.(reference.Tagged); ok {
+			if _, ok := ref.(reference.NamedTagged); ok {
 				newImage.RepoTags = append(newImage.RepoTags, ref.String())
 			}
 		}
diff --git a/daemon/import.go b/daemon/import.go
index 75010e346d..f09ab672aa 100644
--- a/daemon/import.go
+++ b/daemon/import.go
@@ -8,13 +8,13 @@ import (
 	"runtime"
 	"time"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/dockerversion"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/httputils"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/streamformatter"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/runconfig"
 )
 
@@ -90,7 +90,7 @@ func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string
 		return err
 	}
 
-	// FIXME: connect with commit code and call tagstore directly
+	// FIXME: connect with commit code and call refstore directly
 	if newRef != nil {
 		if err := daemon.TagImage(newRef, id.String()); err != nil {
 			return err
diff --git a/distribution/pull.go b/distribution/pull.go
index 9180de5084..e9408d5620 100644
--- a/distribution/pull.go
+++ b/distribution/pull.go
@@ -6,15 +6,14 @@ import (
 	"strings"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/daemon/events"
 	"github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/distribution/xfer"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/pkg/progress"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
-	"github.com/docker/docker/tag"
 	"golang.org/x/net/context"
 )
 
@@ -39,8 +38,8 @@ type ImagePullConfig struct {
 	MetadataStore metadata.Store
 	// ImageStore manages images.
 	ImageStore image.Store
-	// TagStore manages tags.
-	TagStore tag.Store
+	// ReferenceStore manages tags.
+	ReferenceStore reference.Store
 	// DownloadManager manages concurrent pulls.
 	DownloadManager *xfer.LayerDownloadManager
 }
diff --git a/distribution/pull_v1.go b/distribution/pull_v1.go
index 9bc229a83a..0a04216583 100644
--- a/distribution/pull_v1.go
+++ b/distribution/pull_v1.go
@@ -11,7 +11,6 @@ import (
 	"time"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/distribution/registry/client/transport"
 	"github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/distribution/xfer"
@@ -21,6 +20,7 @@ import (
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"golang.org/x/net/context"
 )
@@ -34,7 +34,7 @@ type v1Puller struct {
 }
 
 func (p *v1Puller) Pull(ctx context.Context, ref reference.Named) (fallback bool, err error) {
-	if _, isDigested := ref.(reference.Digested); isDigested {
+	if _, isCanonical := ref.(reference.Canonical); isCanonical {
 		// Allowing fallback, because HTTPS v1 is before HTTP v2
 		return true, registry.ErrNoSupport{Err: errors.New("Cannot pull by digest with v1 registry")}
 	}
@@ -84,7 +84,7 @@ func (p *v1Puller) pullRepository(ctx context.Context, ref reference.Named) erro
 
 	logrus.Debugf("Retrieving the tag list")
 	var tagsList map[string]string
-	tagged, isTagged := ref.(reference.Tagged)
+	tagged, isTagged := ref.(reference.NamedTagged)
 	if !isTagged {
 		tagsList, err = p.session.GetRemoteTags(repoData.Endpoints, p.repoInfo.RemoteName)
 	} else {
@@ -250,7 +250,7 @@ func (p *v1Puller) pullImage(ctx context.Context, v1ID, endpoint string, localNa
 		return err
 	}
 
-	if err := p.config.TagStore.AddTag(localNameRef, imageID, true); err != nil {
+	if err := p.config.ReferenceStore.AddTag(localNameRef, imageID, true); err != nil {
 		return err
 	}
 
diff --git a/distribution/pull_v2.go b/distribution/pull_v2.go
index 50244608f1..f9c47087bd 100644
--- a/distribution/pull_v2.go
+++ b/distribution/pull_v2.go
@@ -13,7 +13,6 @@ import (
 	"github.com/docker/distribution"
 	"github.com/docker/distribution/digest"
 	"github.com/docker/distribution/manifest/schema1"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/distribution/xfer"
 	"github.com/docker/docker/image"
@@ -22,6 +21,7 @@ import (
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"golang.org/x/net/context"
 )
@@ -55,13 +55,13 @@ func (p *v2Puller) Pull(ctx context.Context, ref reference.Named) (fallback bool
 func (p *v2Puller) pullV2Repository(ctx context.Context, ref reference.Named) (err error) {
 	var refs []reference.Named
 	taggedName := p.repoInfo.LocalName
-	if tagged, isTagged := ref.(reference.Tagged); isTagged {
+	if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
 		taggedName, err = reference.WithTag(p.repoInfo.LocalName, tagged.Tag())
 		if err != nil {
 			return err
 		}
 		refs = []reference.Named{taggedName}
-	} else if digested, isDigested := ref.(reference.Digested); isDigested {
+	} else if digested, isCanonical := ref.(reference.Canonical); isCanonical {
 		taggedName, err = reference.WithDigest(p.repoInfo.LocalName, digested.Digest())
 		if err != nil {
 			return err
@@ -197,9 +197,9 @@ func (ld *v2LayerDescriptor) Registered(diffID layer.DiffID) {
 
 func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdated bool, err error) {
 	tagOrDigest := ""
-	if tagged, isTagged := ref.(reference.Tagged); isTagged {
+	if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
 		tagOrDigest = tagged.Tag()
-	} else if digested, isDigested := ref.(reference.Digested); isDigested {
+	} else if digested, isCanonical := ref.(reference.Canonical); isCanonical {
 		tagOrDigest = digested.Digest().String()
 	} else {
 		return false, fmt.Errorf("internal error: reference has neither a tag nor a digest: %s", ref.String())
@@ -300,27 +300,27 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
 		progress.Message(p.config.ProgressOutput, "", "Digest: "+manifestDigest.String())
 	}
 
-	oldTagImageID, err := p.config.TagStore.Get(ref)
+	oldTagImageID, err := p.config.ReferenceStore.Get(ref)
 	if err == nil && oldTagImageID == imageID {
 		return false, nil
 	}
 
 	if canonical, ok := ref.(reference.Canonical); ok {
-		if err = p.config.TagStore.AddDigest(canonical, imageID, true); err != nil {
+		if err = p.config.ReferenceStore.AddDigest(canonical, imageID, true); err != nil {
 			return false, err
 		}
-	} else if err = p.config.TagStore.AddTag(ref, imageID, true); err != nil {
+	} else if err = p.config.ReferenceStore.AddTag(ref, imageID, true); err != nil {
 		return false, err
 	}
 
 	return true, nil
 }
 
-func verifyManifest(signedManifest *schema1.SignedManifest, ref reference.Reference) (m *schema1.Manifest, err error) {
+func verifyManifest(signedManifest *schema1.SignedManifest, ref reference.Named) (m *schema1.Manifest, err error) {
 	// If pull by digest, then verify the manifest digest. NOTE: It is
 	// important to do this first, before any other content validation. If the
 	// digest cannot be verified, don't even bother with those other things.
-	if digested, isDigested := ref.(reference.Digested); isDigested {
+	if digested, isCanonical := ref.(reference.Canonical); isCanonical {
 		verifier, err := digest.NewDigestVerifier(digested.Digest())
 		if err != nil {
 			return nil, err
diff --git a/distribution/pull_v2_test.go b/distribution/pull_v2_test.go
index 2647911408..87356aee33 100644
--- a/distribution/pull_v2_test.go
+++ b/distribution/pull_v2_test.go
@@ -9,7 +9,7 @@ import (
 
 	"github.com/docker/distribution/digest"
 	"github.com/docker/distribution/manifest/schema1"
-	"github.com/docker/distribution/reference"
+	"github.com/docker/docker/reference"
 )
 
 // TestFixManifestLayers checks that fixManifestLayers removes a duplicate
@@ -104,7 +104,7 @@ func TestFixManifestLayersBadParent(t *testing.T) {
 
 // TestValidateManifest verifies the validateManifest function
 func TestValidateManifest(t *testing.T) {
-	expectedDigest, err := reference.Parse("repo@sha256:02fee8c3220ba806531f606525eceb83f4feb654f62b207191b1c9209188dedd")
+	expectedDigest, err := reference.ParseNamed("repo@sha256:02fee8c3220ba806531f606525eceb83f4feb654f62b207191b1c9209188dedd")
 	if err != nil {
 		t.Fatal("could not parse reference")
 	}
diff --git a/distribution/push.go b/distribution/push.go
index c9aef91375..956532a148 100644
--- a/distribution/push.go
+++ b/distribution/push.go
@@ -8,7 +8,6 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/daemon/events"
 	"github.com/docker/docker/distribution/metadata"
@@ -16,8 +15,8 @@ import (
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/progress"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
-	"github.com/docker/docker/tag"
 	"github.com/docker/libtrust"
 	"golang.org/x/net/context"
 )
@@ -45,8 +44,8 @@ type ImagePushConfig struct {
 	LayerStore layer.Store
 	// ImageStore manages images.
 	ImageStore image.Store
-	// TagStore manages tags.
-	TagStore tag.Store
+	// ReferenceStore manages tags.
+	ReferenceStore reference.Store
 	// TrustKey is the private key for legacy signatures. This is typically
 	// an ephemeral key, since these signatures are no longer verified.
 	TrustKey libtrust.PrivateKey
@@ -112,7 +111,7 @@ func Push(ctx context.Context, ref reference.Named, imagePushConfig *ImagePushCo
 
 	progress.Messagef(imagePushConfig.ProgressOutput, "", "The push refers to a repository [%s]", repoInfo.CanonicalName.String())
 
-	associations := imagePushConfig.TagStore.ReferencesByName(repoInfo.LocalName)
+	associations := imagePushConfig.ReferenceStore.ReferencesByName(repoInfo.LocalName)
 	if len(associations) == 0 {
 		return fmt.Errorf("Repository does not exist: %s", repoInfo.LocalName)
 	}
diff --git a/distribution/push_v1.go b/distribution/push_v1.go
index 155bbc8647..012216a68e 100644
--- a/distribution/push_v1.go
+++ b/distribution/push_v1.go
@@ -6,7 +6,6 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/distribution/registry/client/transport"
 	"github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/image"
@@ -15,6 +14,7 @@ import (
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"golang.org/x/net/context"
 )
@@ -141,16 +141,15 @@ func (p *v1Pusher) getImageList() (imageList []v1Image, tagsByImage map[image.ID
 	tagsByImage = make(map[image.ID][]string)
 
 	// Ignore digest references
-	_, isDigested := p.ref.(reference.Digested)
-	if isDigested {
+	if _, isCanonical := p.ref.(reference.Canonical); isCanonical {
 		return
 	}
 
-	tagged, isTagged := p.ref.(reference.Tagged)
+	tagged, isTagged := p.ref.(reference.NamedTagged)
 	if isTagged {
 		// Push a specific tag
 		var imgID image.ID
-		imgID, err = p.config.TagStore.Get(p.ref)
+		imgID, err = p.config.ReferenceStore.Get(p.ref)
 		if err != nil {
 			return
 		}
@@ -168,9 +167,9 @@ func (p *v1Pusher) getImageList() (imageList []v1Image, tagsByImage map[image.ID
 	imagesSeen := make(map[image.ID]struct{})
 	dependenciesSeen := make(map[layer.ChainID]*v1DependencyImage)
 
-	associations := p.config.TagStore.ReferencesByName(p.ref)
+	associations := p.config.ReferenceStore.ReferencesByName(p.ref)
 	for _, association := range associations {
-		if tagged, isTagged = association.Ref.(reference.Tagged); !isTagged {
+		if tagged, isTagged = association.Ref.(reference.NamedTagged); !isTagged {
 			// Ignore digest references.
 			continue
 		}
diff --git a/distribution/push_v2.go b/distribution/push_v2.go
index 4f725eb60a..f687518fd1 100644
--- a/distribution/push_v2.go
+++ b/distribution/push_v2.go
@@ -13,7 +13,6 @@ import (
 	"github.com/docker/distribution/digest"
 	"github.com/docker/distribution/manifest"
 	"github.com/docker/distribution/manifest/schema1"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/distribution/xfer"
 	"github.com/docker/docker/image"
@@ -22,8 +21,8 @@ import (
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/progress"
 	"github.com/docker/docker/pkg/stringid"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
-	"github.com/docker/docker/tag"
 	"golang.org/x/net/context"
 )
 
@@ -55,14 +54,14 @@ func (p *v2Pusher) Push(ctx context.Context) (fallback bool, err error) {
 
 	localName := p.repoInfo.LocalName.Name()
 
-	var associations []tag.Association
-	if _, isTagged := p.ref.(reference.Tagged); isTagged {
-		imageID, err := p.config.TagStore.Get(p.ref)
+	var associations []reference.Association
+	if _, isTagged := p.ref.(reference.NamedTagged); isTagged {
+		imageID, err := p.config.ReferenceStore.Get(p.ref)
 		if err != nil {
 			return false, fmt.Errorf("tag does not exist: %s", p.ref.String())
 		}
 
-		associations = []tag.Association{
+		associations = []reference.Association{
 			{
 				Ref:     p.ref,
 				ImageID: imageID,
@@ -70,7 +69,7 @@ func (p *v2Pusher) Push(ctx context.Context) (fallback bool, err error) {
 		}
 	} else {
 		// Pull all tags
-		associations = p.config.TagStore.ReferencesByName(p.ref)
+		associations = p.config.ReferenceStore.ReferencesByName(p.ref)
 	}
 	if err != nil {
 		return false, fmt.Errorf("error getting tags for %s: %s", localName, err)
@@ -88,7 +87,7 @@ func (p *v2Pusher) Push(ctx context.Context) (fallback bool, err error) {
 	return false, nil
 }
 
-func (p *v2Pusher) pushV2Tag(ctx context.Context, association tag.Association) error {
+func (p *v2Pusher) pushV2Tag(ctx context.Context, association reference.Association) error {
 	ref := association.Ref
 	logrus.Debugf("Pushing repository: %s", ref.String())
 
@@ -146,7 +145,7 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, association tag.Association) e
 	}
 
 	var tag string
-	if tagged, isTagged := ref.(reference.Tagged); isTagged {
+	if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
 		tag = tagged.Tag()
 	}
 	m, err := CreateV2Manifest(p.repo.Name(), tag, img, fsLayers)
@@ -165,7 +164,7 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, association tag.Association) e
 		return err
 	}
 	if manifestDigest != "" {
-		if tagged, isTagged := ref.(reference.Tagged); isTagged {
+		if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
 			// NOTE: do not change this format without first changing the trust client
 			// code. This information is used to determine what was pushed and should be signed.
 			progress.Messagef(p.config.ProgressOutput, "", "%s: digest: %s size: %d", tagged.Tag(), manifestDigest, manifestSize)
diff --git a/distribution/registry_unit_test.go b/distribution/registry_unit_test.go
index 45e4840112..f6543bf837 100644
--- a/distribution/registry_unit_test.go
+++ b/distribution/registry_unit_test.go
@@ -8,10 +8,10 @@ import (
 	"testing"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/distribution/registry/client/auth"
 	"github.com/docker/docker/api/types"
 	registrytypes "github.com/docker/docker/api/types/registry"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/utils"
 	"golang.org/x/net/context"
diff --git a/image/tarexport/load.go b/image/tarexport/load.go
index 695ddba3ee..a32b9863c9 100644
--- a/image/tarexport/load.go
+++ b/image/tarexport/load.go
@@ -9,13 +9,13 @@ import (
 	"path/filepath"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/image/v1"
 	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/chrootarchive"
 	"github.com/docker/docker/pkg/symlink"
+	"github.com/docker/docker/reference"
 )
 
 func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer) error {
@@ -124,11 +124,11 @@ func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS) (layer.Lay
 }
 
 func (l *tarexporter) setLoadedTag(ref reference.NamedTagged, imgID image.ID, outStream io.Writer) error {
-	if prevID, err := l.ts.Get(ref); err == nil && prevID != imgID {
+	if prevID, err := l.rs.Get(ref); err == nil && prevID != imgID {
 		fmt.Fprintf(outStream, "The image %s already exists, renaming the old one with ID %s to empty string\n", ref.String(), string(prevID)) // todo: this message is wrong in case of multiple tags
 	}
 
-	if err := l.ts.AddTag(ref, imgID, true); err != nil {
+	if err := l.rs.AddTag(ref, imgID, true); err != nil {
 		return err
 	}
 	return nil
diff --git a/image/tarexport/save.go b/image/tarexport/save.go
index f16a149c06..8626e95523 100644
--- a/image/tarexport/save.go
+++ b/image/tarexport/save.go
@@ -10,13 +10,12 @@ import (
 	"time"
 
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/image/v1"
 	"github.com/docker/docker/layer"
 	"github.com/docker/docker/pkg/archive"
+	"github.com/docker/docker/reference"
 	"github.com/docker/docker/registry"
-	"github.com/docker/docker/tag"
 )
 
 type imageDescriptor struct {
@@ -50,13 +49,13 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
 
 		if ref != nil {
 			var tagged reference.NamedTagged
-			if _, ok := ref.(reference.Digested); ok {
+			if _, ok := ref.(reference.Canonical); ok {
 				return
 			}
 			var ok bool
 			if tagged, ok = ref.(reference.NamedTagged); !ok {
 				var err error
-				if tagged, err = reference.WithTag(ref, tag.DefaultTag); err != nil {
+				if tagged, err = reference.WithTag(ref, reference.DefaultTag); err != nil {
 					return
 				}
 			}
@@ -84,9 +83,9 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
 			addAssoc(imgID, nil)
 			continue
 		}
-		if _, ok := ref.(reference.Digested); !ok {
+		if _, ok := ref.(reference.Canonical); !ok {
 			if _, ok := ref.(reference.NamedTagged); !ok {
-				assocs := l.ts.ReferencesByName(ref)
+				assocs := l.rs.ReferencesByName(ref)
 				for _, assoc := range assocs {
 					addAssoc(assoc.ImageID, assoc.Ref)
 				}
@@ -101,7 +100,7 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
 			}
 		}
 		var imgID image.ID
-		if imgID, err = l.ts.Get(ref); err != nil {
+		if imgID, err = l.rs.Get(ref); err != nil {
 			return nil, err
 		}
 		addAssoc(imgID, ref)
diff --git a/image/tarexport/tarexport.go b/image/tarexport/tarexport.go
index 3369d665c9..cc8cdc8533 100644
--- a/image/tarexport/tarexport.go
+++ b/image/tarexport/tarexport.go
@@ -3,7 +3,7 @@ package tarexport
 import (
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
-	"github.com/docker/docker/tag"
+	"github.com/docker/docker/reference"
 )
 
 const (
@@ -23,14 +23,14 @@ type manifestItem struct {
 type tarexporter struct {
 	is image.Store
 	ls layer.Store
-	ts tag.Store
+	rs reference.Store
 }
 
 // NewTarExporter returns new ImageExporter for tar packages
-func NewTarExporter(is image.Store, ls layer.Store, ts tag.Store) image.Exporter {
+func NewTarExporter(is image.Store, ls layer.Store, rs reference.Store) image.Exporter {
 	return &tarexporter{
 		is: is,
 		ls: ls,
-		ts: ts,
+		rs: rs,
 	}
 }
diff --git a/migrate/v1/migratev1.go b/migrate/v1/migratev1.go
index 14f6ce4ba5..a9110bca9c 100644
--- a/migrate/v1/migratev1.go
+++ b/migrate/v1/migratev1.go
@@ -11,12 +11,11 @@ import (
 
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/image"
 	imagev1 "github.com/docker/docker/image/v1"
 	"github.com/docker/docker/layer"
-	"github.com/docker/docker/tag"
+	"github.com/docker/docker/reference"
 )
 
 type graphIDRegistrar interface {
@@ -46,7 +45,7 @@ var (
 
 // Migrate takes an old graph directory and transforms the metadata into the
 // new format.
-func Migrate(root, driverName string, ls layer.Store, is image.Store, ts tag.Store, ms metadata.Store) error {
+func Migrate(root, driverName string, ls layer.Store, is image.Store, rs reference.Store, ms metadata.Store) error {
 	mappings := make(map[string]image.ID)
 
 	if registrar, ok := ls.(graphIDRegistrar); !ok {
@@ -61,7 +60,7 @@ func Migrate(root, driverName string, ls layer.Store, is image.Store, ts tag.Sto
 		return err
 	}
 
-	if err := migrateTags(root, driverName, ts, mappings); err != nil {
+	if err := migrateRefs(root, driverName, rs, mappings); err != nil {
 		return err
 	}
 
@@ -189,12 +188,12 @@ func migrateContainers(root string, ls graphIDMounter, is image.Store, imageMapp
 	return nil
 }
 
-type tagAdder interface {
+type refAdder interface {
 	AddTag(ref reference.Named, id image.ID, force bool) error
 	AddDigest(ref reference.Canonical, id image.ID, force bool) error
 }
 
-func migrateTags(root, driverName string, ts tagAdder, mappings map[string]image.ID) error {
+func migrateRefs(root, driverName string, rs refAdder, mappings map[string]image.ID) error {
 	migrationFile := filepath.Join(root, migrationTagsFileName)
 	if _, err := os.Lstat(migrationFile); !os.IsNotExist(err) {
 		return err
@@ -232,7 +231,7 @@ func migrateTags(root, driverName string, ts tagAdder, mappings map[string]image
 						logrus.Errorf("migrate tags: invalid digest %q, %q", dgst, err)
 						continue
 					}
-					if err := ts.AddDigest(canonical, strongID, false); err != nil {
+					if err := rs.AddDigest(canonical, strongID, false); err != nil {
 						logrus.Errorf("can't migrate digest %q for %q, err: %q", ref.String(), strongID, err)
 					}
 				} else {
@@ -241,7 +240,7 @@ func migrateTags(root, driverName string, ts tagAdder, mappings map[string]image
 						logrus.Errorf("migrate tags: invalid tag %q, %q", tag, err)
 						continue
 					}
-					if err := ts.AddTag(tagRef, strongID, false); err != nil {
+					if err := rs.AddTag(tagRef, strongID, false); err != nil {
 						logrus.Errorf("can't migrate tag %q for %q, err: %q", ref.String(), strongID, err)
 					}
 				}
diff --git a/migrate/v1/migratev1_test.go b/migrate/v1/migratev1_test.go
index ef5c1a951b..067d04c382 100644
--- a/migrate/v1/migratev1_test.go
+++ b/migrate/v1/migratev1_test.go
@@ -13,13 +13,13 @@ import (
 	"testing"
 
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/distribution/metadata"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
+	"github.com/docker/docker/reference"
 )
 
-func TestMigrateTags(t *testing.T) {
+func TestMigrateRefs(t *testing.T) {
 	tmpdir, err := ioutil.TempDir("", "migrate-tags")
 	if err != nil {
 		t.Fatal(err)
@@ -29,7 +29,7 @@ func TestMigrateTags(t *testing.T) {
 	ioutil.WriteFile(filepath.Join(tmpdir, "repositories-generic"), []byte(`{"Repositories":{"busybox":{"latest":"b3ca410aa2c115c05969a7b2c8cf8a9fcf62c1340ed6a601c9ee50df337ec108","sha256:16a2a52884c2a9481ed267c2d46483eac7693b813a63132368ab098a71303f8a":"b3ca410aa2c115c05969a7b2c8cf8a9fcf62c1340ed6a601c9ee50df337ec108"},"registry":{"2":"5d165b8e4b203685301c815e95663231691d383fd5e3d3185d1ce3f8dddead3d","latest":"8d5547a9f329b1d3f93198cd661fb5117e5a96b721c5cf9a2c389e7dd4877128"}}}`), 0600)
 
 	ta := &mockTagAdder{}
-	err = migrateTags(tmpdir, "generic", ta, map[string]image.ID{
+	err = migrateRefs(tmpdir, "generic", ta, map[string]image.ID{
 		"5d165b8e4b203685301c815e95663231691d383fd5e3d3185d1ce3f8dddead3d": image.ID("sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"),
 		"b3ca410aa2c115c05969a7b2c8cf8a9fcf62c1340ed6a601c9ee50df337ec108": image.ID("sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9"),
 		"abcdef3434c115c05969a7b2c8cf8a9fcf62c1340ed6a601c9ee50df337ec108": image.ID("sha256:56434342345ae68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"),
@@ -50,7 +50,7 @@ func TestMigrateTags(t *testing.T) {
 
 	// second migration is no-op
 	ioutil.WriteFile(filepath.Join(tmpdir, "repositories-generic"), []byte(`{"Repositories":{"busybox":{"latest":"b3ca410aa2c115c05969a7b2c8cf8a9fcf62c1340ed6a601c9ee50df337ec108"`), 0600)
-	err = migrateTags(tmpdir, "generic", ta, map[string]image.ID{
+	err = migrateRefs(tmpdir, "generic", ta, map[string]image.ID{
 		"b3ca410aa2c115c05969a7b2c8cf8a9fcf62c1340ed6a601c9ee50df337ec108": image.ID("sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9"),
 	})
 	if err != nil {
diff --git a/reference/reference.go b/reference/reference.go
new file mode 100644
index 0000000000..70196a14d2
--- /dev/null
+++ b/reference/reference.go
@@ -0,0 +1,60 @@
+package reference
+
+import (
+	"github.com/docker/distribution/digest"
+	distreference "github.com/docker/distribution/reference"
+)
+
+// Reference is an opaque object reference identifier that may include
+// modifiers such as a hostname, name, tag, and digest.
+type Reference interface {
+	// String returns the full reference
+	String() string
+}
+
+// Named is an object with a full name
+type Named interface {
+	Reference
+	Name() string
+}
+
+// NamedTagged is an object including a name and tag.
+type NamedTagged interface {
+	Named
+	Tag() string
+}
+
+// Canonical reference is an object with a fully unique
+// name including a name with hostname and digest
+type Canonical interface {
+	Named
+	Digest() digest.Digest
+}
+
+// ParseNamed parses s and returns a syntactically valid reference implementing
+// the Named interface. The reference must have a name, otherwise an error is
+// returned.
+// If an error was encountered it is returned, along with a nil Reference.
+// NOTE: ParseNamed will not handle short digests.
+func ParseNamed(s string) (Named, error) {
+	// todo: docker specific validation
+	return distreference.ParseNamed(s)
+}
+
+// WithName returns a named object representing the given string. If the input
+// is invalid ErrReferenceInvalidFormat will be returned.
+func WithName(name string) (Named, error) {
+	return distreference.WithName(name)
+}
+
+// WithTag combines the name from "name" and the tag from "tag" to form a
+// reference incorporating both the name and the tag.
+func WithTag(name Named, tag string) (NamedTagged, error) {
+	return distreference.WithTag(name, tag)
+}
+
+// WithDigest combines the name from "name" and the digest from "digest" to form
+// a reference incorporating both the name and the digest.
+func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
+	return distreference.WithDigest(name, digest)
+}
diff --git a/tag/store.go b/reference/store.go
similarity index 76%
rename from tag/store.go
rename to reference/store.go
index f09db74b53..660c9e2019 100644
--- a/tag/store.go
+++ b/reference/store.go
@@ -1,4 +1,4 @@
-package tag
+package reference
 
 import (
 	"encoding/json"
@@ -11,7 +11,6 @@ import (
 	"sync"
 
 	"github.com/docker/distribution/digest"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/image"
 )
 
@@ -26,18 +25,18 @@ var (
 
 // An Association is a tuple associating a reference with an image ID.
 type Association struct {
-	Ref     reference.Named
+	Ref     Named
 	ImageID image.ID
 }
 
 // Store provides the set of methods which can operate on a tag store.
 type Store interface {
-	References(id image.ID) []reference.Named
-	ReferencesByName(ref reference.Named) []Association
-	AddTag(ref reference.Named, id image.ID, force bool) error
-	AddDigest(ref reference.Canonical, id image.ID, force bool) error
-	Delete(ref reference.Named) (bool, error)
-	Get(ref reference.Named) (image.ID, error)
+	References(id image.ID) []Named
+	ReferencesByName(ref Named) []Association
+	AddTag(ref Named, id image.ID, force bool) error
+	AddDigest(ref Canonical, id image.ID, force bool) error
+	Delete(ref Named) (bool, error)
+	Get(ref Named) (image.ID, error)
 }
 
 type store struct {
@@ -49,14 +48,14 @@ type store struct {
 	Repositories map[string]repository
 	// referencesByIDCache is a cache of references indexed by ID, to speed
 	// up References.
-	referencesByIDCache map[image.ID]map[string]reference.Named
+	referencesByIDCache map[image.ID]map[string]Named
 }
 
 // Repository maps tags to image IDs. The key is a a stringified Reference,
 // including the repository name.
 type repository map[string]image.ID
 
-type lexicalRefs []reference.Named
+type lexicalRefs []Named
 
 func (a lexicalRefs) Len() int           { return len(a) }
 func (a lexicalRefs) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
@@ -68,22 +67,22 @@ func (a lexicalAssociations) Len() int           { return len(a) }
 func (a lexicalAssociations) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
 func (a lexicalAssociations) Less(i, j int) bool { return a[i].Ref.String() < a[j].Ref.String() }
 
-func defaultTagIfNameOnly(ref reference.Named) reference.Named {
+func defaultTagIfNameOnly(ref Named) Named {
 	switch ref.(type) {
-	case reference.Tagged:
+	case NamedTagged:
 		return ref
-	case reference.Digested:
+	case Canonical:
 		return ref
 	default:
 		// Should never fail
-		ref, _ = reference.WithTag(ref, DefaultTag)
+		ref, _ = WithTag(ref, DefaultTag)
 		return ref
 	}
 }
 
-// NewTagStore creates a new tag store, tied to a file path where the set of
-// tags is serialized in JSON format.
-func NewTagStore(jsonPath string) (Store, error) {
+// NewReferenceStore creates a new reference store, tied to a file path where
+// the set of references are serialized in JSON format.
+func NewReferenceStore(jsonPath string) (Store, error) {
 	abspath, err := filepath.Abs(jsonPath)
 	if err != nil {
 		return nil, err
@@ -92,7 +91,7 @@ func NewTagStore(jsonPath string) (Store, error) {
 	store := &store{
 		jsonPath:            abspath,
 		Repositories:        make(map[string]repository),
-		referencesByIDCache: make(map[image.ID]map[string]reference.Named),
+		referencesByIDCache: make(map[image.ID]map[string]Named),
 	}
 	// Load the json file if it exists, otherwise create it.
 	if err := store.reload(); os.IsNotExist(err) {
@@ -105,21 +104,21 @@ func NewTagStore(jsonPath string) (Store, error) {
 	return store, nil
 }
 
-// Add adds a tag to the store. If force is set to true, existing
+// AddTag adds a tag reference to the store. If force is set to true, existing
 // references can be overwritten. This only works for tags, not digests.
-func (store *store) AddTag(ref reference.Named, id image.ID, force bool) error {
-	if _, isDigested := ref.(reference.Digested); isDigested {
+func (store *store) AddTag(ref Named, id image.ID, force bool) error {
+	if _, isCanonical := ref.(Canonical); isCanonical {
 		return errors.New("refusing to create a tag with a digest reference")
 	}
 	return store.addReference(defaultTagIfNameOnly(ref), id, force)
 }
 
-// Add adds a digest reference to the store.
-func (store *store) AddDigest(ref reference.Canonical, id image.ID, force bool) error {
+// AddDigest adds a digest reference to the store.
+func (store *store) AddDigest(ref Canonical, id image.ID, force bool) error {
 	return store.addReference(ref, id, force)
 }
 
-func (store *store) addReference(ref reference.Named, id image.ID, force bool) error {
+func (store *store) addReference(ref Named, id image.ID, force bool) error {
 	if ref.Name() == string(digest.Canonical) {
 		return errors.New("refusing to create an ambiguous tag using digest algorithm as name")
 	}
@@ -138,7 +137,7 @@ func (store *store) addReference(ref reference.Named, id image.ID, force bool) e
 
 	if exists {
 		// force only works for tags
-		if digested, isDigest := ref.(reference.Digested); isDigest {
+		if digested, isDigest := ref.(Canonical); isDigest {
 			return fmt.Errorf("Cannot overwrite digest %s", digested.Digest().String())
 		}
 
@@ -156,7 +155,7 @@ func (store *store) addReference(ref reference.Named, id image.ID, force bool) e
 
 	repository[refStr] = id
 	if store.referencesByIDCache[id] == nil {
-		store.referencesByIDCache[id] = make(map[string]reference.Named)
+		store.referencesByIDCache[id] = make(map[string]Named)
 	}
 	store.referencesByIDCache[id][refStr] = ref
 
@@ -165,7 +164,7 @@ func (store *store) addReference(ref reference.Named, id image.ID, force bool) e
 
 // Delete deletes a reference from the store. It returns true if a deletion
 // happened, or false otherwise.
-func (store *store) Delete(ref reference.Named) (bool, error) {
+func (store *store) Delete(ref Named) (bool, error) {
 	ref = defaultTagIfNameOnly(ref)
 
 	store.mu.Lock()
@@ -196,8 +195,8 @@ func (store *store) Delete(ref reference.Named) (bool, error) {
 	return false, ErrDoesNotExist
 }
 
-// Get retrieves an item from the store by reference.
-func (store *store) Get(ref reference.Named) (image.ID, error) {
+// Get retrieves an item from the store by
+func (store *store) Get(ref Named) (image.ID, error) {
 	ref = defaultTagIfNameOnly(ref)
 
 	store.mu.RLock()
@@ -218,15 +217,15 @@ func (store *store) Get(ref reference.Named) (image.ID, error) {
 
 // References returns a slice of references to the given image ID. The slice
 // will be nil if there are no references to this image ID.
-func (store *store) References(id image.ID) []reference.Named {
+func (store *store) References(id image.ID) []Named {
 	store.mu.RLock()
 	defer store.mu.RUnlock()
 
 	// Convert the internal map to an array for two reasons:
-	// 1) We must not return a mutable reference.
+	// 1) We must not return a mutable
 	// 2) It would be ugly to expose the extraneous map keys to callers.
 
-	var references []reference.Named
+	var references []Named
 	for _, ref := range store.referencesByIDCache[id] {
 		references = append(references, ref)
 	}
@@ -239,7 +238,7 @@ func (store *store) References(id image.ID) []reference.Named {
 // ReferencesByName returns the references for a given repository name.
 // If there are no references known for this repository name,
 // ReferencesByName returns nil.
-func (store *store) ReferencesByName(ref reference.Named) []Association {
+func (store *store) ReferencesByName(ref Named) []Association {
 	store.mu.RLock()
 	defer store.mu.RUnlock()
 
@@ -250,7 +249,7 @@ func (store *store) ReferencesByName(ref reference.Named) []Association {
 
 	var associations []Association
 	for refStr, refID := range repository {
-		ref, err := reference.ParseNamed(refStr)
+		ref, err := ParseNamed(refStr)
 		if err != nil {
 			// Should never happen
 			return nil
@@ -299,13 +298,13 @@ func (store *store) reload() error {
 
 	for _, repository := range store.Repositories {
 		for refStr, refID := range repository {
-			ref, err := reference.ParseNamed(refStr)
+			ref, err := ParseNamed(refStr)
 			if err != nil {
 				// Should never happen
 				continue
 			}
 			if store.referencesByIDCache[refID] == nil {
-				store.referencesByIDCache[refID] = make(map[string]reference.Named)
+				store.referencesByIDCache[refID] = make(map[string]Named)
 			}
 			store.referencesByIDCache[refID][refStr] = ref
 		}
diff --git a/tag/store_test.go b/reference/store_test.go
similarity index 89%
rename from tag/store_test.go
rename to reference/store_test.go
index 80a36bf84c..a877c55f58 100644
--- a/tag/store_test.go
+++ b/reference/store_test.go
@@ -1,4 +1,4 @@
-package tag
+package reference
 
 import (
 	"bytes"
@@ -8,7 +8,6 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/image"
 )
 
@@ -40,13 +39,13 @@ func TestLoad(t *testing.T) {
 	}
 	jsonFile.Close()
 
-	store, err := NewTagStore(jsonFile.Name())
+	store, err := NewReferenceStore(jsonFile.Name())
 	if err != nil {
 		t.Fatalf("error creating tag store: %v", err)
 	}
 
 	for refStr, expectedID := range saveLoadTestCases {
-		ref, err := reference.ParseNamed(refStr)
+		ref, err := ParseNamed(refStr)
 		if err != nil {
 			t.Fatalf("failed to parse reference: %v", err)
 		}
@@ -69,17 +68,17 @@ func TestSave(t *testing.T) {
 	jsonFile.Close()
 	defer os.RemoveAll(jsonFile.Name())
 
-	store, err := NewTagStore(jsonFile.Name())
+	store, err := NewReferenceStore(jsonFile.Name())
 	if err != nil {
 		t.Fatalf("error creating tag store: %v", err)
 	}
 
 	for refStr, id := range saveLoadTestCases {
-		ref, err := reference.ParseNamed(refStr)
+		ref, err := ParseNamed(refStr)
 		if err != nil {
 			t.Fatalf("failed to parse reference: %v", err)
 		}
-		if canonical, ok := ref.(reference.Canonical); ok {
+		if canonical, ok := ref.(Canonical); ok {
 			err = store.AddDigest(canonical, id, false)
 			if err != nil {
 				t.Fatalf("could not add digest reference %s: %v", refStr, err)
@@ -111,7 +110,7 @@ func TestAddDeleteGet(t *testing.T) {
 	jsonFile.Close()
 	defer os.RemoveAll(jsonFile.Name())
 
-	store, err := NewTagStore(jsonFile.Name())
+	store, err := NewReferenceStore(jsonFile.Name())
 	if err != nil {
 		t.Fatalf("error creating tag store: %v", err)
 	}
@@ -121,7 +120,7 @@ func TestAddDeleteGet(t *testing.T) {
 	testImageID3 := image.ID("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9e")
 
 	// Try adding a reference with no tag or digest
-	nameOnly, err := reference.WithName("username/repo")
+	nameOnly, err := WithName("username/repo")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
@@ -130,7 +129,7 @@ func TestAddDeleteGet(t *testing.T) {
 	}
 
 	// Add a few references
-	ref1, err := reference.ParseNamed("username/repo1:latest")
+	ref1, err := ParseNamed("username/repo1:latest")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
@@ -138,7 +137,7 @@ func TestAddDeleteGet(t *testing.T) {
 		t.Fatalf("error adding to store: %v", err)
 	}
 
-	ref2, err := reference.ParseNamed("username/repo1:old")
+	ref2, err := ParseNamed("username/repo1:old")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
@@ -146,7 +145,7 @@ func TestAddDeleteGet(t *testing.T) {
 		t.Fatalf("error adding to store: %v", err)
 	}
 
-	ref3, err := reference.ParseNamed("username/repo1:alias")
+	ref3, err := ParseNamed("username/repo1:alias")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
@@ -154,7 +153,7 @@ func TestAddDeleteGet(t *testing.T) {
 		t.Fatalf("error adding to store: %v", err)
 	}
 
-	ref4, err := reference.ParseNamed("username/repo2:latest")
+	ref4, err := ParseNamed("username/repo2:latest")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
@@ -162,11 +161,11 @@ func TestAddDeleteGet(t *testing.T) {
 		t.Fatalf("error adding to store: %v", err)
 	}
 
-	ref5, err := reference.ParseNamed("username/repo3@sha256:58153dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c")
+	ref5, err := ParseNamed("username/repo3@sha256:58153dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
-	if err = store.AddDigest(ref5.(reference.Canonical), testImageID2, false); err != nil {
+	if err = store.AddDigest(ref5.(Canonical), testImageID2, false); err != nil {
 		t.Fatalf("error adding to store: %v", err)
 	}
 
@@ -229,7 +228,7 @@ func TestAddDeleteGet(t *testing.T) {
 	}
 
 	// Get should return ErrDoesNotExist for a nonexistent repo
-	nonExistRepo, err := reference.ParseNamed("username/nonexistrepo:latest")
+	nonExistRepo, err := ParseNamed("username/nonexistrepo:latest")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
@@ -238,7 +237,7 @@ func TestAddDeleteGet(t *testing.T) {
 	}
 
 	// Get should return ErrDoesNotExist for a nonexistent tag
-	nonExistTag, err := reference.ParseNamed("username/repo1:nonexist")
+	nonExistTag, err := ParseNamed("username/repo1:nonexist")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
@@ -264,7 +263,7 @@ func TestAddDeleteGet(t *testing.T) {
 	}
 
 	// Check ReferencesByName
-	repoName, err := reference.WithName("username/repo1")
+	repoName, err := WithName("username/repo1")
 	if err != nil {
 		t.Fatalf("could not parse reference: %v", err)
 	}
@@ -328,14 +327,14 @@ func TestInvalidTags(t *testing.T) {
 	tmpDir, err := ioutil.TempDir("", "tag-store-test")
 	defer os.RemoveAll(tmpDir)
 
-	store, err := NewTagStore(filepath.Join(tmpDir, "repositories.json"))
+	store, err := NewReferenceStore(filepath.Join(tmpDir, "repositories.json"))
 	if err != nil {
 		t.Fatalf("error creating tag store: %v", err)
 	}
 	id := image.ID("sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6")
 
 	// sha256 as repo name
-	ref, err := reference.ParseNamed("sha256:abc")
+	ref, err := ParseNamed("sha256:abc")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -345,7 +344,7 @@ func TestInvalidTags(t *testing.T) {
 	}
 
 	// setting digest as a tag
-	ref, err = reference.ParseNamed("registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6")
+	ref, err = ParseNamed("registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6")
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/registry/config.go b/registry/config.go
index 2eeba140e4..45caf57891 100644
--- a/registry/config.go
+++ b/registry/config.go
@@ -7,11 +7,12 @@ import (
 	"net/url"
 	"strings"
 
-	"github.com/docker/distribution/reference"
+	distreference "github.com/docker/distribution/reference"
 	registrytypes "github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/image/v1"
 	"github.com/docker/docker/opts"
 	flag "github.com/docker/docker/pkg/mflag"
+	"github.com/docker/docker/reference"
 )
 
 // Options holds command line options.
@@ -269,7 +270,7 @@ func GetAuthConfigKey(index *registrytypes.IndexInfo) string {
 // splitReposName breaks a reposName into an index name and remote name
 func splitReposName(reposName reference.Named) (indexName string, remoteName reference.Named, err error) {
 	var remoteNameStr string
-	indexName, remoteNameStr = reference.SplitHostname(reposName)
+	indexName, remoteNameStr = distreference.SplitHostname(reposName)
 	if indexName == "" || (!strings.Contains(indexName, ".") &&
 		!strings.Contains(indexName, ":") && indexName != "localhost") {
 		// This is a Docker Index repos (ex: samalba/hipache or ubuntu)
@@ -405,13 +406,13 @@ func localNameFromRemote(indexName string, remoteName reference.Named) (referenc
 // error.
 func NormalizeLocalReference(ref reference.Named) reference.Named {
 	localName := NormalizeLocalName(ref)
-	if tagged, isTagged := ref.(reference.Tagged); isTagged {
+	if tagged, isTagged := ref.(reference.NamedTagged); isTagged {
 		newRef, err := reference.WithTag(localName, tagged.Tag())
 		if err != nil {
 			return ref
 		}
 		return newRef
-	} else if digested, isDigested := ref.(reference.Digested); isDigested {
+	} else if digested, isCanonical := ref.(reference.Canonical); isCanonical {
 		newRef, err := reference.WithDigest(localName, digested.Digest())
 		if err != nil {
 			return ref
diff --git a/registry/registry_mock_test.go b/registry/registry_mock_test.go
index f45de5c89c..017d08bbe5 100644
--- a/registry/registry_mock_test.go
+++ b/registry/registry_mock_test.go
@@ -15,9 +15,9 @@ import (
 	"testing"
 	"time"
 
-	"github.com/docker/distribution/reference"
 	registrytypes "github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/opts"
+	"github.com/docker/docker/reference"
 	"github.com/gorilla/mux"
 
 	"github.com/Sirupsen/logrus"
diff --git a/registry/registry_test.go b/registry/registry_test.go
index 7e35244165..31ae2d5fbb 100644
--- a/registry/registry_test.go
+++ b/registry/registry_test.go
@@ -8,10 +8,10 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/distribution/registry/client/transport"
 	"github.com/docker/docker/api/types"
 	registrytypes "github.com/docker/docker/api/types/registry"
+	"github.com/docker/docker/reference"
 )
 
 var (
diff --git a/registry/service.go b/registry/service.go
index b826f11731..eb5cd6bfdd 100644
--- a/registry/service.go
+++ b/registry/service.go
@@ -6,10 +6,10 @@ import (
 	"net/url"
 	"strings"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/distribution/registry/client/auth"
 	"github.com/docker/docker/api/types"
 	registrytypes "github.com/docker/docker/api/types/registry"
+	"github.com/docker/docker/reference"
 )
 
 // Service is a registry service. It tracks configuration data such as a list
diff --git a/registry/service_v1.go b/registry/service_v1.go
index 5fdc1ececf..3b3cc780f3 100644
--- a/registry/service_v1.go
+++ b/registry/service_v1.go
@@ -4,8 +4,8 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/pkg/tlsconfig"
+	"github.com/docker/docker/reference"
 )
 
 func (s *Service) lookupV1Endpoints(repoName reference.Named) (endpoints []APIEndpoint, err error) {
diff --git a/registry/service_v2.go b/registry/service_v2.go
index 56a3d2eeed..3a2c32a5d9 100644
--- a/registry/service_v2.go
+++ b/registry/service_v2.go
@@ -4,9 +4,9 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/docker/distribution/reference"
 	"github.com/docker/distribution/registry/client/auth"
 	"github.com/docker/docker/pkg/tlsconfig"
+	"github.com/docker/docker/reference"
 )
 
 func (s *Service) lookupV2Endpoints(repoName reference.Named) (endpoints []APIEndpoint, err error) {
diff --git a/registry/session.go b/registry/session.go
index d09babd403..a1206206f6 100644
--- a/registry/session.go
+++ b/registry/session.go
@@ -19,13 +19,13 @@ import (
 	"strings"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
 	registrytypes "github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/pkg/httputils"
 	"github.com/docker/docker/pkg/ioutils"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/tarsum"
+	"github.com/docker/docker/reference"
 )
 
 var (
diff --git a/registry/types.go b/registry/types.go
index 03657820e5..939f44b14c 100644
--- a/registry/types.go
+++ b/registry/types.go
@@ -1,8 +1,8 @@
 package registry
 
 import (
-	"github.com/docker/distribution/reference"
 	registrytypes "github.com/docker/docker/api/types/registry"
+	"github.com/docker/docker/reference"
 )
 
 // RepositoryData tracks the image list, list of endpoints, and list of tokens