Browse code

Merge pull request #26616 from tonistiigi/id-digest

Generalize content addressable and reference storage

Brian Goff authored on 2016/09/18 22:40:16
Showing 21 changed files
... ...
@@ -27,18 +27,18 @@ func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) {
27 27
 		return "", err
28 28
 	}
29 29
 	if id != "" {
30
-		if _, err := daemon.imageStore.Get(image.ID(id)); err != nil {
30
+		if _, err := daemon.imageStore.Get(image.IDFromDigest(id)); err != nil {
31 31
 			return "", ErrImageDoesNotExist{refOrID}
32 32
 		}
33
-		return image.ID(id), nil
33
+		return image.IDFromDigest(id), nil
34 34
 	}
35 35
 
36 36
 	if id, err := daemon.referenceStore.Get(ref); err == nil {
37
-		return id, nil
37
+		return image.IDFromDigest(id), nil
38 38
 	}
39 39
 	if tagged, ok := ref.(reference.NamedTagged); ok {
40 40
 		if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil {
41
-			for _, namedRef := range daemon.referenceStore.References(id) {
41
+			for _, namedRef := range daemon.referenceStore.References(id.Digest()) {
42 42
 				if namedRef.Name() == ref.Name() {
43 43
 					return id, nil
44 44
 				}
... ...
@@ -68,7 +68,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
68 68
 		return nil, daemon.imageNotExistToErrcode(err)
69 69
 	}
70 70
 
71
-	repoRefs := daemon.referenceStore.References(imgID)
71
+	repoRefs := daemon.referenceStore.References(imgID.Digest())
72 72
 
73 73
 	var removedRepositoryRef bool
74 74
 	if !isImageIDPrefix(imgID.String(), imageRef) {
... ...
@@ -102,7 +102,7 @@ func (daemon *Daemon) ImageDelete(imageRef string, force, prune bool) ([]types.I
102 102
 		daemon.LogImageEvent(imgID.String(), imgID.String(), "untag")
103 103
 		records = append(records, untaggedRecord)
104 104
 
105
-		repoRefs = daemon.referenceStore.References(imgID)
105
+		repoRefs = daemon.referenceStore.References(imgID.Digest())
106 106
 
107 107
 		// If a tag reference was removed and the only remaining
108 108
 		// references to the same repository are digest references,
... ...
@@ -239,7 +239,7 @@ func (daemon *Daemon) removeImageRef(ref reference.Named) (reference.Named, erro
239 239
 // daemon's event service. An "Untagged" types.ImageDelete is added to the
240 240
 // given list of records.
241 241
 func (daemon *Daemon) removeAllReferencesToImageID(imgID image.ID, records *[]types.ImageDelete) error {
242
-	imageRefs := daemon.referenceStore.References(imgID)
242
+	imageRefs := daemon.referenceStore.References(imgID.Digest())
243 243
 
244 244
 	for _, imageRef := range imageRefs {
245 245
 		parsedRef, err := daemon.removeImageRef(imageRef)
... ...
@@ -372,7 +372,7 @@ func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, mask conflictType
372 372
 	}
373 373
 
374 374
 	// Check if any repository tags/digest reference this image.
375
-	if mask&conflictActiveReference != 0 && len(daemon.referenceStore.References(imgID)) > 0 {
375
+	if mask&conflictActiveReference != 0 && len(daemon.referenceStore.References(imgID.Digest())) > 0 {
376 376
 		return &imageDeleteConflict{
377 377
 			imgID:   imgID,
378 378
 			message: "image is referenced in multiple repositories",
... ...
@@ -400,5 +400,5 @@ func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, mask conflictType
400 400
 // that there are no repository references to the given image and it has no
401 401
 // child images.
402 402
 func (daemon *Daemon) imageIsDangling(imgID image.ID) bool {
403
-	return !(len(daemon.referenceStore.References(imgID)) > 0 || len(daemon.imageStore.Children(imgID)) > 0)
403
+	return !(len(daemon.referenceStore.References(imgID.Digest())) > 0 || len(daemon.imageStore.Children(imgID)) > 0)
404 404
 }
... ...
@@ -60,7 +60,7 @@ func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) {
60 60
 		h.ID = id.String()
61 61
 
62 62
 		var tags []string
63
-		for _, r := range daemon.referenceStore.References(id) {
63
+		for _, r := range daemon.referenceStore.References(id.Digest()) {
64 64
 			if _, ok := r.(reference.NamedTagged); ok {
65 65
 				tags = append(tags, r.String())
66 66
 			}
... ...
@@ -17,7 +17,7 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
17 17
 		return nil, fmt.Errorf("No such image: %s", name)
18 18
 	}
19 19
 
20
-	refs := daemon.referenceStore.References(img.ID())
20
+	refs := daemon.referenceStore.References(img.ID().Digest())
21 21
 	repoTags := []string{}
22 22
 	repoDigests := []string{}
23 23
 	for _, ref := range refs {
... ...
@@ -28,7 +28,7 @@ func (daemon *Daemon) TagImage(imageName, repository, tag string) error {
28 28
 
29 29
 // TagImageWithReference adds the given reference to the image ID provided.
30 30
 func (daemon *Daemon) TagImageWithReference(imageID image.ID, newTag reference.Named) error {
31
-	if err := daemon.referenceStore.AddTag(newTag, imageID, true); err != nil {
31
+	if err := daemon.referenceStore.AddTag(newTag, imageID.Digest(), true); err != nil {
32 32
 		return err
33 33
 	}
34 34
 
... ...
@@ -135,7 +135,7 @@ func (daemon *Daemon) Images(filterArgs, filter string, all bool) ([]*types.Imag
135 135
 
136 136
 		newImage := newImage(img, size)
137 137
 
138
-		for _, ref := range daemon.referenceStore.References(id) {
138
+		for _, ref := range daemon.referenceStore.References(id.Digest()) {
139 139
 			if filter != "" { // filter by tag/repo name
140 140
 				if filterTagged { // filter by tag, require full ref match
141 141
 					if ref.String() != filter {
... ...
@@ -205,21 +205,21 @@ func ValidateRepoName(name string) error {
205 205
 	return nil
206 206
 }
207 207
 
208
-func addDigestReference(store reference.Store, ref reference.Named, dgst digest.Digest, imageID image.ID) error {
208
+func addDigestReference(store reference.Store, ref reference.Named, dgst digest.Digest, id digest.Digest) error {
209 209
 	dgstRef, err := reference.WithDigest(ref, dgst)
210 210
 	if err != nil {
211 211
 		return err
212 212
 	}
213 213
 
214
-	if oldTagImageID, err := store.Get(dgstRef); err == nil {
215
-		if oldTagImageID != imageID {
214
+	if oldTagID, err := store.Get(dgstRef); err == nil {
215
+		if oldTagID != id {
216 216
 			// Updating digests not supported by reference store
217
-			logrus.Errorf("Image ID for digest %s changed from %s to %s, cannot update", dgst.String(), oldTagImageID, imageID)
217
+			logrus.Errorf("Image ID for digest %s changed from %s to %s, cannot update", dgst.String(), oldTagID, id)
218 218
 		}
219 219
 		return nil
220 220
 	} else if err != reference.ErrDoesNotExist {
221 221
 		return err
222 222
 	}
223 223
 
224
-	return store.AddDigest(dgstRef, imageID, true)
224
+	return store.AddDigest(dgstRef, id, true)
225 225
 }
... ...
@@ -248,7 +248,7 @@ func (p *v1Puller) pullImage(ctx context.Context, v1ID, endpoint string, localNa
248 248
 		return err
249 249
 	}
250 250
 
251
-	if err := p.config.ReferenceStore.AddTag(localNameRef, imageID, true); err != nil {
251
+	if err := p.config.ReferenceStore.AddTag(localNameRef, imageID.Digest(), true); err != nil {
252 252
 		return err
253 253
 	}
254 254
 
... ...
@@ -374,23 +374,23 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
374 374
 	progress.Message(p.config.ProgressOutput, tagOrDigest, "Pulling from "+p.repo.Named().Name())
375 375
 
376 376
 	var (
377
-		imageID        image.ID
377
+		id             digest.Digest
378 378
 		manifestDigest digest.Digest
379 379
 	)
380 380
 
381 381
 	switch v := manifest.(type) {
382 382
 	case *schema1.SignedManifest:
383
-		imageID, manifestDigest, err = p.pullSchema1(ctx, ref, v)
383
+		id, manifestDigest, err = p.pullSchema1(ctx, ref, v)
384 384
 		if err != nil {
385 385
 			return false, err
386 386
 		}
387 387
 	case *schema2.DeserializedManifest:
388
-		imageID, manifestDigest, err = p.pullSchema2(ctx, ref, v)
388
+		id, manifestDigest, err = p.pullSchema2(ctx, ref, v)
389 389
 		if err != nil {
390 390
 			return false, err
391 391
 		}
392 392
 	case *manifestlist.DeserializedManifestList:
393
-		imageID, manifestDigest, err = p.pullManifestList(ctx, ref, v)
393
+		id, manifestDigest, err = p.pullManifestList(ctx, ref, v)
394 394
 		if err != nil {
395 395
 			return false, err
396 396
 		}
... ...
@@ -400,31 +400,31 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
400 400
 
401 401
 	progress.Message(p.config.ProgressOutput, "", "Digest: "+manifestDigest.String())
402 402
 
403
-	oldTagImageID, err := p.config.ReferenceStore.Get(ref)
403
+	oldTagID, err := p.config.ReferenceStore.Get(ref)
404 404
 	if err == nil {
405
-		if oldTagImageID == imageID {
406
-			return false, addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID)
405
+		if oldTagID == id {
406
+			return false, addDigestReference(p.config.ReferenceStore, ref, manifestDigest, id)
407 407
 		}
408 408
 	} else if err != reference.ErrDoesNotExist {
409 409
 		return false, err
410 410
 	}
411 411
 
412 412
 	if canonical, ok := ref.(reference.Canonical); ok {
413
-		if err = p.config.ReferenceStore.AddDigest(canonical, imageID, true); err != nil {
413
+		if err = p.config.ReferenceStore.AddDigest(canonical, id, true); err != nil {
414 414
 			return false, err
415 415
 		}
416 416
 	} else {
417
-		if err = addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID); err != nil {
417
+		if err = addDigestReference(p.config.ReferenceStore, ref, manifestDigest, id); err != nil {
418 418
 			return false, err
419 419
 		}
420
-		if err = p.config.ReferenceStore.AddTag(ref, imageID, true); err != nil {
420
+		if err = p.config.ReferenceStore.AddTag(ref, id, true); err != nil {
421 421
 			return false, err
422 422
 		}
423 423
 	}
424 424
 	return true, nil
425 425
 }
426 426
 
427
-func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Named, unverifiedManifest *schema1.SignedManifest) (imageID image.ID, manifestDigest digest.Digest, err error) {
427
+func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Named, unverifiedManifest *schema1.SignedManifest) (id digest.Digest, manifestDigest digest.Digest, err error) {
428 428
 	var verifiedManifest *schema1.Manifest
429 429
 	verifiedManifest, err = verifySchema1Manifest(unverifiedManifest, ref)
430 430
 	if err != nil {
... ...
@@ -487,28 +487,27 @@ func (p *v2Puller) pullSchema1(ctx context.Context, ref reference.Named, unverif
487 487
 		return "", "", err
488 488
 	}
489 489
 
490
-	imageID, err = p.config.ImageStore.Create(config)
490
+	imageID, err := p.config.ImageStore.Create(config)
491 491
 	if err != nil {
492 492
 		return "", "", err
493 493
 	}
494 494
 
495 495
 	manifestDigest = digest.FromBytes(unverifiedManifest.Canonical)
496 496
 
497
-	return imageID, manifestDigest, nil
497
+	return imageID.Digest(), manifestDigest, nil
498 498
 }
499 499
 
500
-func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *schema2.DeserializedManifest) (imageID image.ID, manifestDigest digest.Digest, err error) {
500
+func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *schema2.DeserializedManifest) (id digest.Digest, manifestDigest digest.Digest, err error) {
501 501
 	manifestDigest, err = schema2ManifestDigest(ref, mfst)
502 502
 	if err != nil {
503 503
 		return "", "", err
504 504
 	}
505 505
 
506 506
 	target := mfst.Target()
507
-	imageID = image.ID(target.Digest)
508
-	if _, err := p.config.ImageStore.Get(imageID); err == nil {
507
+	if _, err := p.config.ImageStore.Get(image.IDFromDigest(target.Digest)); err == nil {
509 508
 		// If the image already exists locally, no need to pull
510 509
 		// anything.
511
-		return imageID, manifestDigest, nil
510
+		return target.Digest, manifestDigest, nil
512 511
 	}
513 512
 
514 513
 	var descriptors []xfer.DownloadDescriptor
... ...
@@ -534,7 +533,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
534 534
 
535 535
 	// Pull the image config
536 536
 	go func() {
537
-		configJSON, err := p.pullSchema2ImageConfig(ctx, target.Digest)
537
+		configJSON, err := p.pullSchema2Config(ctx, target.Digest)
538 538
 		if err != nil {
539 539
 			errChan <- ImageConfigPullError{Err: err}
540 540
 			cancel()
... ...
@@ -618,12 +617,12 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
618 618
 		}
619 619
 	}
620 620
 
621
-	imageID, err = p.config.ImageStore.Create(configJSON)
621
+	imageID, err := p.config.ImageStore.Create(configJSON)
622 622
 	if err != nil {
623 623
 		return "", "", err
624 624
 	}
625 625
 
626
-	return imageID, manifestDigest, nil
626
+	return imageID.Digest(), manifestDigest, nil
627 627
 }
628 628
 
629 629
 func receiveConfig(configChan <-chan []byte, errChan <-chan error) ([]byte, image.Image, error) {
... ...
@@ -643,7 +642,7 @@ func receiveConfig(configChan <-chan []byte, errChan <-chan error) ([]byte, imag
643 643
 
644 644
 // pullManifestList handles "manifest lists" which point to various
645 645
 // platform-specifc manifests.
646
-func (p *v2Puller) pullManifestList(ctx context.Context, ref reference.Named, mfstList *manifestlist.DeserializedManifestList) (imageID image.ID, manifestListDigest digest.Digest, err error) {
646
+func (p *v2Puller) pullManifestList(ctx context.Context, ref reference.Named, mfstList *manifestlist.DeserializedManifestList) (id digest.Digest, manifestListDigest digest.Digest, err error) {
647 647
 	manifestListDigest, err = schema2ManifestDigest(ref, mfstList)
648 648
 	if err != nil {
649 649
 		return "", "", err
... ...
@@ -681,12 +680,12 @@ func (p *v2Puller) pullManifestList(ctx context.Context, ref reference.Named, mf
681 681
 
682 682
 	switch v := manifest.(type) {
683 683
 	case *schema1.SignedManifest:
684
-		imageID, _, err = p.pullSchema1(ctx, manifestRef, v)
684
+		id, _, err = p.pullSchema1(ctx, manifestRef, v)
685 685
 		if err != nil {
686 686
 			return "", "", err
687 687
 		}
688 688
 	case *schema2.DeserializedManifest:
689
-		imageID, _, err = p.pullSchema2(ctx, manifestRef, v)
689
+		id, _, err = p.pullSchema2(ctx, manifestRef, v)
690 690
 		if err != nil {
691 691
 			return "", "", err
692 692
 		}
... ...
@@ -694,10 +693,10 @@ func (p *v2Puller) pullManifestList(ctx context.Context, ref reference.Named, mf
694 694
 		return "", "", errors.New("unsupported manifest format")
695 695
 	}
696 696
 
697
-	return imageID, manifestListDigest, err
697
+	return id, manifestListDigest, err
698 698
 }
699 699
 
700
-func (p *v2Puller) pullSchema2ImageConfig(ctx context.Context, dgst digest.Digest) (configJSON []byte, err error) {
700
+func (p *v2Puller) pullSchema2Config(ctx context.Context, dgst digest.Digest) (configJSON []byte, err error) {
701 701
 	blobs := p.repo.Blobs(ctx)
702 702
 	configJSON, err = blobs.Get(ctx, dgst)
703 703
 	if err != nil {
... ...
@@ -92,7 +92,7 @@ type v1TopImage struct {
92 92
 }
93 93
 
94 94
 func newV1TopImage(imageID image.ID, img *image.Image, l layer.Layer, parent *v1DependencyImage) (*v1TopImage, error) {
95
-	v1ID := digest.Digest(imageID).Hex()
95
+	v1ID := imageID.Digest().Hex()
96 96
 	parentV1ID := ""
97 97
 	if parent != nil {
98 98
 		parentV1ID = parent.V1ID()
... ...
@@ -149,10 +149,12 @@ func (p *v1Pusher) getImageList() (imageList []v1Image, tagsByImage map[image.ID
149 149
 	if isTagged {
150 150
 		// Push a specific tag
151 151
 		var imgID image.ID
152
-		imgID, err = p.config.ReferenceStore.Get(p.ref)
152
+		var dgst digest.Digest
153
+		dgst, err = p.config.ReferenceStore.Get(p.ref)
153 154
 		if err != nil {
154 155
 			return
155 156
 		}
157
+		imgID = image.IDFromDigest(dgst)
156 158
 
157 159
 		imageList, err = p.imageListForTag(imgID, nil, &referencedLayers)
158 160
 		if err != nil {
... ...
@@ -164,7 +166,7 @@ func (p *v1Pusher) getImageList() (imageList []v1Image, tagsByImage map[image.ID
164 164
 		return
165 165
 	}
166 166
 
167
-	imagesSeen := make(map[image.ID]struct{})
167
+	imagesSeen := make(map[digest.Digest]struct{})
168 168
 	dependenciesSeen := make(map[layer.ChainID]*v1DependencyImage)
169 169
 
170 170
 	associations := p.config.ReferenceStore.ReferencesByName(p.ref)
... ...
@@ -174,15 +176,16 @@ func (p *v1Pusher) getImageList() (imageList []v1Image, tagsByImage map[image.ID
174 174
 			continue
175 175
 		}
176 176
 
177
-		tagsByImage[association.ImageID] = append(tagsByImage[association.ImageID], tagged.Tag())
177
+		imgID := image.IDFromDigest(association.ID)
178
+		tagsByImage[imgID] = append(tagsByImage[imgID], tagged.Tag())
178 179
 
179
-		if _, present := imagesSeen[association.ImageID]; present {
180
+		if _, present := imagesSeen[association.ID]; present {
180 181
 			// Skip generating image list for already-seen image
181 182
 			continue
182 183
 		}
183
-		imagesSeen[association.ImageID] = struct{}{}
184
+		imagesSeen[association.ID] = struct{}{}
184 185
 
185
-		imageListForThisTag, err := p.imageListForTag(association.ImageID, dependenciesSeen, &referencedLayers)
186
+		imageListForThisTag, err := p.imageListForTag(imgID, dependenciesSeen, &referencedLayers)
186 187
 		if err != nil {
187 188
 			return nil, nil, nil, err
188 189
 		}
... ...
@@ -99,7 +99,7 @@ func (p *v2Pusher) pushV2Repository(ctx context.Context) (err error) {
99 99
 	for _, association := range p.config.ReferenceStore.ReferencesByName(p.ref) {
100 100
 		if namedTagged, isNamedTagged := association.Ref.(reference.NamedTagged); isNamedTagged {
101 101
 			pushed++
102
-			if err := p.pushV2Tag(ctx, namedTagged, association.ImageID); err != nil {
102
+			if err := p.pushV2Tag(ctx, namedTagged, association.ID); err != nil {
103 103
 				return err
104 104
 			}
105 105
 		}
... ...
@@ -112,10 +112,10 @@ func (p *v2Pusher) pushV2Repository(ctx context.Context) (err error) {
112 112
 	return nil
113 113
 }
114 114
 
115
-func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, imageID image.ID) error {
115
+func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, id digest.Digest) error {
116 116
 	logrus.Debugf("Pushing repository: %s", ref.String())
117 117
 
118
-	img, err := p.config.ImageStore.Get(imageID)
118
+	img, err := p.config.ImageStore.Get(image.IDFromDigest(id))
119 119
 	if err != nil {
120 120
 		return fmt.Errorf("could not find image from tag %s: %v", ref.String(), err)
121 121
 	}
... ...
@@ -207,7 +207,7 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, ima
207 207
 	manifestDigest := digest.FromBytes(canonicalManifest)
208 208
 	progress.Messagef(p.config.ProgressOutput, "", "%s: digest: %s size: %d", ref.Tag(), manifestDigest, len(canonicalManifest))
209 209
 
210
-	if err := addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID); err != nil {
210
+	if err := addDigestReference(p.config.ReferenceStore, ref, manifestDigest, id); err != nil {
211 211
 		return err
212 212
 	}
213 213
 
... ...
@@ -12,18 +12,18 @@ import (
12 12
 	"github.com/docker/docker/pkg/ioutils"
13 13
 )
14 14
 
15
-// IDWalkFunc is function called by StoreBackend.Walk
16
-type IDWalkFunc func(id ID) error
15
+// DigestWalkFunc is function called by StoreBackend.Walk
16
+type DigestWalkFunc func(id digest.Digest) error
17 17
 
18 18
 // StoreBackend provides interface for image.Store persistence
19 19
 type StoreBackend interface {
20
-	Walk(f IDWalkFunc) error
21
-	Get(id ID) ([]byte, error)
22
-	Set(data []byte) (ID, error)
23
-	Delete(id ID) error
24
-	SetMetadata(id ID, key string, data []byte) error
25
-	GetMetadata(id ID, key string) ([]byte, error)
26
-	DeleteMetadata(id ID, key string) error
20
+	Walk(f DigestWalkFunc) error
21
+	Get(id digest.Digest) ([]byte, error)
22
+	Set(data []byte) (digest.Digest, error)
23
+	Delete(id digest.Digest) error
24
+	SetMetadata(id digest.Digest, key string, data []byte) error
25
+	GetMetadata(id digest.Digest, key string) ([]byte, error)
26
+	DeleteMetadata(id digest.Digest, key string) error
27 27
 }
28 28
 
29 29
 // fs implements StoreBackend using the filesystem.
... ...
@@ -55,18 +55,16 @@ func newFSStore(root string) (*fs, error) {
55 55
 	return s, nil
56 56
 }
57 57
 
58
-func (s *fs) contentFile(id ID) string {
59
-	dgst := digest.Digest(id)
58
+func (s *fs) contentFile(dgst digest.Digest) string {
60 59
 	return filepath.Join(s.root, contentDirName, string(dgst.Algorithm()), dgst.Hex())
61 60
 }
62 61
 
63
-func (s *fs) metadataDir(id ID) string {
64
-	dgst := digest.Digest(id)
62
+func (s *fs) metadataDir(dgst digest.Digest) string {
65 63
 	return filepath.Join(s.root, metadataDirName, string(dgst.Algorithm()), dgst.Hex())
66 64
 }
67 65
 
68 66
 // Walk calls the supplied callback for each image ID in the storage backend.
69
-func (s *fs) Walk(f IDWalkFunc) error {
67
+func (s *fs) Walk(f DigestWalkFunc) error {
70 68
 	// Only Canonical digest (sha256) is currently supported
71 69
 	s.RLock()
72 70
 	dir, err := ioutil.ReadDir(filepath.Join(s.root, contentDirName, string(digest.Canonical)))
... ...
@@ -80,37 +78,37 @@ func (s *fs) Walk(f IDWalkFunc) error {
80 80
 			logrus.Debugf("Skipping invalid digest %s: %s", dgst, err)
81 81
 			continue
82 82
 		}
83
-		if err := f(ID(dgst)); err != nil {
83
+		if err := f(dgst); err != nil {
84 84
 			return err
85 85
 		}
86 86
 	}
87 87
 	return nil
88 88
 }
89 89
 
90
-// Get returns the content stored under a given ID.
91
-func (s *fs) Get(id ID) ([]byte, error) {
90
+// Get returns the content stored under a given digest.
91
+func (s *fs) Get(dgst digest.Digest) ([]byte, error) {
92 92
 	s.RLock()
93 93
 	defer s.RUnlock()
94 94
 
95
-	return s.get(id)
95
+	return s.get(dgst)
96 96
 }
97 97
 
98
-func (s *fs) get(id ID) ([]byte, error) {
99
-	content, err := ioutil.ReadFile(s.contentFile(id))
98
+func (s *fs) get(dgst digest.Digest) ([]byte, error) {
99
+	content, err := ioutil.ReadFile(s.contentFile(dgst))
100 100
 	if err != nil {
101 101
 		return nil, err
102 102
 	}
103 103
 
104 104
 	// todo: maybe optional
105
-	if ID(digest.FromBytes(content)) != id {
106
-		return nil, fmt.Errorf("failed to verify image: %v", id)
105
+	if digest.FromBytes(content) != dgst {
106
+		return nil, fmt.Errorf("failed to verify: %v", dgst)
107 107
 	}
108 108
 
109 109
 	return content, nil
110 110
 }
111 111
 
112
-// Set stores content under a given ID.
113
-func (s *fs) Set(data []byte) (ID, error) {
112
+// Set stores content by checksum.
113
+func (s *fs) Set(data []byte) (digest.Digest, error) {
114 114
 	s.Lock()
115 115
 	defer s.Unlock()
116 116
 
... ...
@@ -118,58 +116,58 @@ func (s *fs) Set(data []byte) (ID, error) {
118 118
 		return "", fmt.Errorf("Invalid empty data")
119 119
 	}
120 120
 
121
-	id := ID(digest.FromBytes(data))
122
-	if err := ioutils.AtomicWriteFile(s.contentFile(id), data, 0600); err != nil {
121
+	dgst := digest.FromBytes(data)
122
+	if err := ioutils.AtomicWriteFile(s.contentFile(dgst), data, 0600); err != nil {
123 123
 		return "", err
124 124
 	}
125 125
 
126
-	return id, nil
126
+	return dgst, nil
127 127
 }
128 128
 
129
-// Delete removes content and metadata files associated with the ID.
130
-func (s *fs) Delete(id ID) error {
129
+// Delete removes content and metadata files associated with the digest.
130
+func (s *fs) Delete(dgst digest.Digest) error {
131 131
 	s.Lock()
132 132
 	defer s.Unlock()
133 133
 
134
-	if err := os.RemoveAll(s.metadataDir(id)); err != nil {
134
+	if err := os.RemoveAll(s.metadataDir(dgst)); err != nil {
135 135
 		return err
136 136
 	}
137
-	if err := os.Remove(s.contentFile(id)); err != nil {
137
+	if err := os.Remove(s.contentFile(dgst)); err != nil {
138 138
 		return err
139 139
 	}
140 140
 	return nil
141 141
 }
142 142
 
143 143
 // SetMetadata sets metadata for a given ID. It fails if there's no base file.
144
-func (s *fs) SetMetadata(id ID, key string, data []byte) error {
144
+func (s *fs) SetMetadata(dgst digest.Digest, key string, data []byte) error {
145 145
 	s.Lock()
146 146
 	defer s.Unlock()
147
-	if _, err := s.get(id); err != nil {
147
+	if _, err := s.get(dgst); err != nil {
148 148
 		return err
149 149
 	}
150 150
 
151
-	baseDir := filepath.Join(s.metadataDir(id))
151
+	baseDir := filepath.Join(s.metadataDir(dgst))
152 152
 	if err := os.MkdirAll(baseDir, 0700); err != nil {
153 153
 		return err
154 154
 	}
155
-	return ioutils.AtomicWriteFile(filepath.Join(s.metadataDir(id), key), data, 0600)
155
+	return ioutils.AtomicWriteFile(filepath.Join(s.metadataDir(dgst), key), data, 0600)
156 156
 }
157 157
 
158
-// GetMetadata returns metadata for a given ID.
159
-func (s *fs) GetMetadata(id ID, key string) ([]byte, error) {
158
+// GetMetadata returns metadata for a given digest.
159
+func (s *fs) GetMetadata(dgst digest.Digest, key string) ([]byte, error) {
160 160
 	s.RLock()
161 161
 	defer s.RUnlock()
162 162
 
163
-	if _, err := s.get(id); err != nil {
163
+	if _, err := s.get(dgst); err != nil {
164 164
 		return nil, err
165 165
 	}
166
-	return ioutil.ReadFile(filepath.Join(s.metadataDir(id), key))
166
+	return ioutil.ReadFile(filepath.Join(s.metadataDir(dgst), key))
167 167
 }
168 168
 
169
-// DeleteMetadata removes the metadata associated with an ID.
170
-func (s *fs) DeleteMetadata(id ID, key string) error {
169
+// DeleteMetadata removes the metadata associated with a digest.
170
+func (s *fs) DeleteMetadata(dgst digest.Digest, key string) error {
171 171
 	s.Lock()
172 172
 	defer s.Unlock()
173 173
 
174
-	return os.RemoveAll(filepath.Join(s.metadataDir(id), key))
174
+	return os.RemoveAll(filepath.Join(s.metadataDir(dgst), key))
175 175
 }
... ...
@@ -128,7 +128,7 @@ func testMetadataGetSet(t *testing.T, store StoreBackend) {
128 128
 	}
129 129
 
130 130
 	tcases := []struct {
131
-		id    ID
131
+		id    digest.Digest
132 132
 		key   string
133 133
 		value []byte
134 134
 	}{
... ...
@@ -158,12 +158,12 @@ func testMetadataGetSet(t *testing.T, store StoreBackend) {
158 158
 	}
159 159
 
160 160
 	id3 := digest.FromBytes([]byte("baz"))
161
-	err = store.SetMetadata(ID(id3), "tkey", []byte("tval"))
161
+	err = store.SetMetadata(id3, "tkey", []byte("tval"))
162 162
 	if err == nil {
163 163
 		t.Fatal("Expected error for setting metadata for unknown ID.")
164 164
 	}
165 165
 
166
-	_, err = store.GetMetadata(ID(id3), "tkey")
166
+	_, err = store.GetMetadata(id3, "tkey")
167 167
 	if err == nil {
168 168
 		t.Fatal("Expected error for getting metadata for unknown ID.")
169 169
 	}
... ...
@@ -232,7 +232,7 @@ func TestFSInvalidWalker(t *testing.T) {
232 232
 	}
233 233
 
234 234
 	n := 0
235
-	err = fs.Walk(func(id ID) error {
235
+	err = fs.Walk(func(id digest.Digest) error {
236 236
 		if id != fooID {
237 237
 			t.Fatalf("Invalid walker ID %q, expected %q", id, fooID)
238 238
 		}
... ...
@@ -250,10 +250,10 @@ func TestFSInvalidWalker(t *testing.T) {
250 250
 func testGetSet(t *testing.T, store StoreBackend) {
251 251
 	type tcase struct {
252 252
 		input    []byte
253
-		expected ID
253
+		expected digest.Digest
254 254
 	}
255 255
 	tcases := []tcase{
256
-		{[]byte("foobar"), ID("sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2")},
256
+		{[]byte("foobar"), digest.Digest("sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2")},
257 257
 	}
258 258
 
259 259
 	randomInput := make([]byte, 8*1024)
... ...
@@ -269,7 +269,7 @@ func testGetSet(t *testing.T, store StoreBackend) {
269 269
 	}
270 270
 	tcases = append(tcases, tcase{
271 271
 		input:    randomInput,
272
-		expected: ID("sha256:" + hex.EncodeToString(h.Sum(nil))),
272
+		expected: digest.Digest("sha256:" + hex.EncodeToString(h.Sum(nil))),
273 273
 	})
274 274
 
275 275
 	for _, tc := range tcases {
... ...
@@ -299,7 +299,7 @@ func testGetSet(t *testing.T, store StoreBackend) {
299 299
 		}
300 300
 	}
301 301
 
302
-	for _, key := range []ID{"foobar:abc", "sha256:abc", "sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2a"} {
302
+	for _, key := range []digest.Digest{"foobar:abc", "sha256:abc", "sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2a"} {
303 303
 		_, err := store.Get(key)
304 304
 		if err == nil {
305 305
 			t.Fatalf("Expected error for ID %q.", key)
... ...
@@ -352,11 +352,11 @@ func testWalker(t *testing.T, store StoreBackend) {
352 352
 		t.Fatal(err)
353 353
 	}
354 354
 
355
-	tcases := make(map[ID]struct{})
355
+	tcases := make(map[digest.Digest]struct{})
356 356
 	tcases[id] = struct{}{}
357 357
 	tcases[id2] = struct{}{}
358 358
 	n := 0
359
-	err = store.Walk(func(id ID) error {
359
+	err = store.Walk(func(id digest.Digest) error {
360 360
 		delete(tcases, id)
361 361
 		n++
362 362
 		return nil
... ...
@@ -373,9 +373,9 @@ func testWalker(t *testing.T, store StoreBackend) {
373 373
 	}
374 374
 
375 375
 	// stop on error
376
-	tcases = make(map[ID]struct{})
376
+	tcases = make(map[digest.Digest]struct{})
377 377
 	tcases[id] = struct{}{}
378
-	err = store.Walk(func(id ID) error {
378
+	err = store.Walk(func(id digest.Digest) error {
379 379
 		return errors.New("")
380 380
 	})
381 381
 	if err == nil {
... ...
@@ -14,7 +14,17 @@ import (
14 14
 type ID digest.Digest
15 15
 
16 16
 func (id ID) String() string {
17
-	return digest.Digest(id).String()
17
+	return id.Digest().String()
18
+}
19
+
20
+// Digest converts ID into a digest
21
+func (id ID) Digest() digest.Digest {
22
+	return digest.Digest(id)
23
+}
24
+
25
+// IDFromDigest creates an ID from a digest
26
+func IDFromDigest(digest digest.Digest) ID {
27
+	return ID(digest)
18 28
 }
19 29
 
20 30
 // V1Image stores the V1 image configuration.
... ...
@@ -72,9 +82,9 @@ func (img *Image) ID() ID {
72 72
 	return img.computedID
73 73
 }
74 74
 
75
-// ImageID stringizes ID.
75
+// ImageID stringifies ID.
76 76
 func (img *Image) ImageID() string {
77
-	return string(img.ID())
77
+	return img.ID().String()
78 78
 }
79 79
 
80 80
 // RunConfig returns the image's container config.
... ...
@@ -61,10 +61,10 @@ func NewImageStore(fs StoreBackend, ls LayerGetReleaser) (Store, error) {
61 61
 }
62 62
 
63 63
 func (is *store) restore() error {
64
-	err := is.fs.Walk(func(id ID) error {
65
-		img, err := is.Get(id)
64
+	err := is.fs.Walk(func(dgst digest.Digest) error {
65
+		img, err := is.Get(IDFromDigest(dgst))
66 66
 		if err != nil {
67
-			logrus.Errorf("invalid image %v, %v", id, err)
67
+			logrus.Errorf("invalid image %v, %v", dgst, err)
68 68
 			return nil
69 69
 		}
70 70
 		var l layer.Layer
... ...
@@ -74,7 +74,7 @@ func (is *store) restore() error {
74 74
 				return err
75 75
 			}
76 76
 		}
77
-		if err := is.digestSet.Add(digest.Digest(id)); err != nil {
77
+		if err := is.digestSet.Add(dgst); err != nil {
78 78
 			return err
79 79
 		}
80 80
 
... ...
@@ -83,7 +83,7 @@ func (is *store) restore() error {
83 83
 			children: make(map[ID]struct{}),
84 84
 		}
85 85
 
86
-		is.images[ID(id)] = imageMeta
86
+		is.images[IDFromDigest(dgst)] = imageMeta
87 87
 
88 88
 		return nil
89 89
 	})
... ...
@@ -131,7 +131,7 @@ func (is *store) Create(config []byte) (ID, error) {
131 131
 	if err != nil {
132 132
 		return "", err
133 133
 	}
134
-	imageID := ID(dgst)
134
+	imageID := IDFromDigest(dgst)
135 135
 
136 136
 	is.Lock()
137 137
 	defer is.Unlock()
... ...
@@ -156,7 +156,7 @@ func (is *store) Create(config []byte) (ID, error) {
156 156
 	}
157 157
 
158 158
 	is.images[imageID] = imageMeta
159
-	if err := is.digestSet.Add(digest.Digest(imageID)); err != nil {
159
+	if err := is.digestSet.Add(imageID.Digest()); err != nil {
160 160
 		delete(is.images, imageID)
161 161
 		return "", err
162 162
 	}
... ...
@@ -175,13 +175,13 @@ func (is *store) Search(term string) (ID, error) {
175 175
 		}
176 176
 		return "", err
177 177
 	}
178
-	return ID(dgst), nil
178
+	return IDFromDigest(dgst), nil
179 179
 }
180 180
 
181 181
 func (is *store) Get(id ID) (*Image, error) {
182 182
 	// todo: Check if image is in images
183 183
 	// todo: Detect manual insertions and start using them
184
-	config, err := is.fs.Get(id)
184
+	config, err := is.fs.Get(id.Digest())
185 185
 	if err != nil {
186 186
 		return nil, err
187 187
 	}
... ...
@@ -209,17 +209,17 @@ func (is *store) Delete(id ID) ([]layer.Metadata, error) {
209 209
 		return nil, fmt.Errorf("unrecognized image ID %s", id.String())
210 210
 	}
211 211
 	for id := range imageMeta.children {
212
-		is.fs.DeleteMetadata(id, "parent")
212
+		is.fs.DeleteMetadata(id.Digest(), "parent")
213 213
 	}
214 214
 	if parent, err := is.GetParent(id); err == nil && is.images[parent] != nil {
215 215
 		delete(is.images[parent].children, id)
216 216
 	}
217 217
 
218
-	if err := is.digestSet.Remove(digest.Digest(id)); err != nil {
218
+	if err := is.digestSet.Remove(id.Digest()); err != nil {
219 219
 		logrus.Errorf("error removing %s from digest set: %q", id, err)
220 220
 	}
221 221
 	delete(is.images, id)
222
-	is.fs.Delete(id)
222
+	is.fs.Delete(id.Digest())
223 223
 
224 224
 	if imageMeta.layer != nil {
225 225
 		return is.ls.Release(imageMeta.layer)
... ...
@@ -238,11 +238,11 @@ func (is *store) SetParent(id, parent ID) error {
238 238
 		delete(is.images[parent].children, id)
239 239
 	}
240 240
 	parentMeta.children[id] = struct{}{}
241
-	return is.fs.SetMetadata(id, "parent", []byte(parent))
241
+	return is.fs.SetMetadata(id.Digest(), "parent", []byte(parent))
242 242
 }
243 243
 
244 244
 func (is *store) GetParent(id ID) (ID, error) {
245
-	d, err := is.fs.GetMetadata(id, "parent")
245
+	d, err := is.fs.GetMetadata(id.Digest(), "parent")
246 246
 	if err != nil {
247 247
 		return "", err
248 248
 	}
... ...
@@ -11,6 +11,7 @@ import (
11 11
 
12 12
 	"github.com/Sirupsen/logrus"
13 13
 	"github.com/docker/distribution"
14
+	"github.com/docker/distribution/digest"
14 15
 	"github.com/docker/docker/image"
15 16
 	"github.com/docker/docker/image/v1"
16 17
 	"github.com/docker/docker/layer"
... ...
@@ -123,7 +124,7 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool)
123 123
 			if !ok {
124 124
 				return fmt.Errorf("invalid tag %q", repoTag)
125 125
 			}
126
-			l.setLoadedTag(ref, imgID, outStream)
126
+			l.setLoadedTag(ref, imgID.Digest(), outStream)
127 127
 			outStream.Write([]byte(fmt.Sprintf("Loaded image: %s\n", ref)))
128 128
 			imageRefCount++
129 129
 		}
... ...
@@ -195,7 +196,7 @@ func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string,
195 195
 	return l.ls.Register(inflatedLayerData, rootFS.ChainID())
196 196
 }
197 197
 
198
-func (l *tarexporter) setLoadedTag(ref reference.NamedTagged, imgID image.ID, outStream io.Writer) error {
198
+func (l *tarexporter) setLoadedTag(ref reference.NamedTagged, imgID digest.Digest, outStream io.Writer) error {
199 199
 	if prevID, err := l.rs.Get(ref); err == nil && prevID != imgID {
200 200
 		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
201 201
 	}
... ...
@@ -253,7 +254,7 @@ func (l *tarexporter) legacyLoad(tmpDir string, outStream io.Writer, progressOut
253 253
 			if err != nil {
254 254
 				return err
255 255
 			}
256
-			l.setLoadedTag(ref, imgID, outStream)
256
+			l.setLoadedTag(ref, imgID.Digest(), outStream)
257 257
 		}
258 258
 	}
259 259
 
... ...
@@ -77,11 +77,11 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
77 77
 			return nil, err
78 78
 		}
79 79
 		if id != "" {
80
-			_, err := l.is.Get(image.ID(id))
80
+			_, err := l.is.Get(image.IDFromDigest(id))
81 81
 			if err != nil {
82 82
 				return nil, err
83 83
 			}
84
-			addAssoc(image.ID(id), nil)
84
+			addAssoc(image.IDFromDigest(id), nil)
85 85
 			continue
86 86
 		}
87 87
 		if ref.Name() == string(digest.Canonical) {
... ...
@@ -95,7 +95,7 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
95 95
 		if reference.IsNameOnly(ref) {
96 96
 			assocs := l.rs.ReferencesByName(ref)
97 97
 			for _, assoc := range assocs {
98
-				addAssoc(assoc.ImageID, assoc.Ref)
98
+				addAssoc(image.IDFromDigest(assoc.ID), assoc.Ref)
99 99
 			}
100 100
 			if len(assocs) == 0 {
101 101
 				imgID, err := l.is.Search(name)
... ...
@@ -106,11 +106,11 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
106 106
 			}
107 107
 			continue
108 108
 		}
109
-		var imgID image.ID
110
-		if imgID, err = l.rs.Get(ref); err != nil {
109
+		id, err = l.rs.Get(ref)
110
+		if err != nil {
111 111
 			return nil, err
112 112
 		}
113
-		addAssoc(imgID, ref)
113
+		addAssoc(image.IDFromDigest(id), ref)
114 114
 
115 115
 	}
116 116
 	return imgDescr, nil
... ...
@@ -155,7 +155,7 @@ func (s *saveSession) save(outStream io.Writer) error {
155 155
 		}
156 156
 
157 157
 		manifest = append(manifest, manifestItem{
158
-			Config:       digest.Digest(id).Hex() + ".json",
158
+			Config:       id.Digest().Hex() + ".json",
159 159
 			RepoTags:     repoTags,
160 160
 			Layers:       layers,
161 161
 			LayerSources: foreignSrcs,
... ...
@@ -264,7 +264,7 @@ func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]distribution.Desc
264 264
 		}
265 265
 	}
266 266
 
267
-	configFile := filepath.Join(s.outDir, digest.Digest(id).Hex()+".json")
267
+	configFile := filepath.Join(s.outDir, id.Digest().Hex()+".json")
268 268
 	if err := ioutil.WriteFile(configFile, img.RawJSON(), 0644); err != nil {
269 269
 		return nil, err
270 270
 	}
... ...
@@ -294,8 +294,8 @@ func migrateContainers(root string, ls graphIDMounter, is image.Store, imageMapp
294 294
 }
295 295
 
296 296
 type refAdder interface {
297
-	AddTag(ref reference.Named, id image.ID, force bool) error
298
-	AddDigest(ref reference.Canonical, id image.ID, force bool) error
297
+	AddTag(ref reference.Named, id digest.Digest, force bool) error
298
+	AddDigest(ref reference.Canonical, id digest.Digest, force bool) error
299 299
 }
300 300
 
301 301
 func migrateRefs(root, driverName string, rs refAdder, mappings map[string]image.ID) error {
... ...
@@ -336,7 +336,7 @@ func migrateRefs(root, driverName string, rs refAdder, mappings map[string]image
336 336
 						logrus.Errorf("migrate tags: invalid digest %q, %q", dgst, err)
337 337
 						continue
338 338
 					}
339
-					if err := rs.AddDigest(canonical, strongID, false); err != nil {
339
+					if err := rs.AddDigest(canonical, strongID.Digest(), false); err != nil {
340 340
 						logrus.Errorf("can't migrate digest %q for %q, err: %q", ref.String(), strongID, err)
341 341
 					}
342 342
 				} else {
... ...
@@ -345,7 +345,7 @@ func migrateRefs(root, driverName string, rs refAdder, mappings map[string]image
345 345
 						logrus.Errorf("migrate tags: invalid tag %q, %q", tag, err)
346 346
 						continue
347 347
 					}
348
-					if err := rs.AddTag(tagRef, strongID, false); err != nil {
348
+					if err := rs.AddTag(tagRef, strongID.Digest(), false); err != nil {
349 349
 						logrus.Errorf("can't migrate tag %q for %q, err: %q", ref.String(), strongID, err)
350 350
 					}
351 351
 				}
... ...
@@ -333,14 +333,14 @@ type mockTagAdder struct {
333 333
 	refs map[string]string
334 334
 }
335 335
 
336
-func (t *mockTagAdder) AddTag(ref reference.Named, id image.ID, force bool) error {
336
+func (t *mockTagAdder) AddTag(ref reference.Named, id digest.Digest, force bool) error {
337 337
 	if t.refs == nil {
338 338
 		t.refs = make(map[string]string)
339 339
 	}
340 340
 	t.refs[ref.String()] = id.String()
341 341
 	return nil
342 342
 }
343
-func (t *mockTagAdder) AddDigest(ref reference.Canonical, id image.ID, force bool) error {
343
+func (t *mockTagAdder) AddDigest(ref reference.Canonical, id digest.Digest, force bool) error {
344 344
 	return t.AddTag(ref, id, force)
345 345
 }
346 346
 
... ...
@@ -10,7 +10,6 @@ import (
10 10
 	"sync"
11 11
 
12 12
 	"github.com/docker/distribution/digest"
13
-	"github.com/docker/docker/image"
14 13
 	"github.com/docker/docker/pkg/ioutils"
15 14
 )
16 15
 
... ...
@@ -22,18 +21,18 @@ var (
22 22
 
23 23
 // An Association is a tuple associating a reference with an image ID.
24 24
 type Association struct {
25
-	Ref     Named
26
-	ImageID image.ID
25
+	Ref Named
26
+	ID  digest.Digest
27 27
 }
28 28
 
29 29
 // Store provides the set of methods which can operate on a tag store.
30 30
 type Store interface {
31
-	References(id image.ID) []Named
31
+	References(id digest.Digest) []Named
32 32
 	ReferencesByName(ref Named) []Association
33
-	AddTag(ref Named, id image.ID, force bool) error
34
-	AddDigest(ref Canonical, id image.ID, force bool) error
33
+	AddTag(ref Named, id digest.Digest, force bool) error
34
+	AddDigest(ref Canonical, id digest.Digest, force bool) error
35 35
 	Delete(ref Named) (bool, error)
36
-	Get(ref Named) (image.ID, error)
36
+	Get(ref Named) (digest.Digest, error)
37 37
 }
38 38
 
39 39
 type store struct {
... ...
@@ -45,12 +44,12 @@ type store struct {
45 45
 	Repositories map[string]repository
46 46
 	// referencesByIDCache is a cache of references indexed by ID, to speed
47 47
 	// up References.
48
-	referencesByIDCache map[image.ID]map[string]Named
48
+	referencesByIDCache map[digest.Digest]map[string]Named
49 49
 }
50 50
 
51
-// Repository maps tags to image IDs. The key is a stringified Reference,
51
+// Repository maps tags to digests. The key is a stringified Reference,
52 52
 // including the repository name.
53
-type repository map[string]image.ID
53
+type repository map[string]digest.Digest
54 54
 
55 55
 type lexicalRefs []Named
56 56
 
... ...
@@ -75,7 +74,7 @@ func NewReferenceStore(jsonPath string) (Store, error) {
75 75
 	store := &store{
76 76
 		jsonPath:            abspath,
77 77
 		Repositories:        make(map[string]repository),
78
-		referencesByIDCache: make(map[image.ID]map[string]Named),
78
+		referencesByIDCache: make(map[digest.Digest]map[string]Named),
79 79
 	}
80 80
 	// Load the json file if it exists, otherwise create it.
81 81
 	if err := store.reload(); os.IsNotExist(err) {
... ...
@@ -90,7 +89,7 @@ func NewReferenceStore(jsonPath string) (Store, error) {
90 90
 
91 91
 // AddTag adds a tag reference to the store. If force is set to true, existing
92 92
 // references can be overwritten. This only works for tags, not digests.
93
-func (store *store) AddTag(ref Named, id image.ID, force bool) error {
93
+func (store *store) AddTag(ref Named, id digest.Digest, force bool) error {
94 94
 	if _, isCanonical := ref.(Canonical); isCanonical {
95 95
 		return errors.New("refusing to create a tag with a digest reference")
96 96
 	}
... ...
@@ -98,11 +97,11 @@ func (store *store) AddTag(ref Named, id image.ID, force bool) error {
98 98
 }
99 99
 
100 100
 // AddDigest adds a digest reference to the store.
101
-func (store *store) AddDigest(ref Canonical, id image.ID, force bool) error {
101
+func (store *store) AddDigest(ref Canonical, id digest.Digest, force bool) error {
102 102
 	return store.addReference(ref, id, force)
103 103
 }
104 104
 
105
-func (store *store) addReference(ref Named, id image.ID, force bool) error {
105
+func (store *store) addReference(ref Named, id digest.Digest, force bool) error {
106 106
 	if ref.Name() == string(digest.Canonical) {
107 107
 		return errors.New("refusing to create an ambiguous tag using digest algorithm as name")
108 108
 	}
... ...
@@ -112,7 +111,7 @@ func (store *store) addReference(ref Named, id image.ID, force bool) error {
112 112
 
113 113
 	repository, exists := store.Repositories[ref.Name()]
114 114
 	if !exists || repository == nil {
115
-		repository = make(map[string]image.ID)
115
+		repository = make(map[string]digest.Digest)
116 116
 		store.Repositories[ref.Name()] = repository
117 117
 	}
118 118
 
... ...
@@ -179,8 +178,8 @@ func (store *store) Delete(ref Named) (bool, error) {
179 179
 	return false, ErrDoesNotExist
180 180
 }
181 181
 
182
-// Get retrieves an item from the store by
183
-func (store *store) Get(ref Named) (image.ID, error) {
182
+// Get retrieves an item from the store by reference
183
+func (store *store) Get(ref Named) (digest.Digest, error) {
184 184
 	ref = WithDefaultTag(ref)
185 185
 
186 186
 	store.mu.RLock()
... ...
@@ -199,9 +198,9 @@ func (store *store) Get(ref Named) (image.ID, error) {
199 199
 	return id, nil
200 200
 }
201 201
 
202
-// References returns a slice of references to the given image ID. The slice
203
-// will be nil if there are no references to this image ID.
204
-func (store *store) References(id image.ID) []Named {
202
+// References returns a slice of references to the given ID. The slice
203
+// will be nil if there are no references to this ID.
204
+func (store *store) References(id digest.Digest) []Named {
205 205
 	store.mu.RLock()
206 206
 	defer store.mu.RUnlock()
207 207
 
... ...
@@ -240,8 +239,8 @@ func (store *store) ReferencesByName(ref Named) []Association {
240 240
 		}
241 241
 		associations = append(associations,
242 242
 			Association{
243
-				Ref:     ref,
244
-				ImageID: refID,
243
+				Ref: ref,
244
+				ID:  refID,
245 245
 			})
246 246
 	}
247 247
 
... ...
@@ -8,11 +8,11 @@ import (
8 8
 	"strings"
9 9
 	"testing"
10 10
 
11
-	"github.com/docker/docker/image"
11
+	"github.com/docker/distribution/digest"
12 12
 )
13 13
 
14 14
 var (
15
-	saveLoadTestCases = map[string]image.ID{
15
+	saveLoadTestCases = map[string]digest.Digest{
16 16
 		"registry:5000/foobar:HEAD":                                                        "sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6",
17 17
 		"registry:5000/foobar:alternate":                                                   "sha256:ae300ebc4a4f00693702cfb0a5e0b7bc527b353828dc86ad09fb95c8a681b793",
18 18
 		"registry:5000/foobar:latest":                                                      "sha256:6153498b9ac00968d71b66cca4eac37e990b5f9eb50c26877eb8799c8847451b",
... ...
@@ -115,9 +115,9 @@ func TestAddDeleteGet(t *testing.T) {
115 115
 		t.Fatalf("error creating tag store: %v", err)
116 116
 	}
117 117
 
118
-	testImageID1 := image.ID("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9c")
119
-	testImageID2 := image.ID("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9d")
120
-	testImageID3 := image.ID("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9e")
118
+	testImageID1 := digest.Digest("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9c")
119
+	testImageID2 := digest.Digest("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9d")
120
+	testImageID3 := digest.Digest("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9e")
121 121
 
122 122
 	// Try adding a reference with no tag or digest
123 123
 	nameOnly, err := WithName("username/repo")
... ...
@@ -276,19 +276,19 @@ func TestAddDeleteGet(t *testing.T) {
276 276
 	if associations[0].Ref.String() != ref3.String() {
277 277
 		t.Fatalf("unexpected reference: %v", associations[0].Ref.String())
278 278
 	}
279
-	if associations[0].ImageID != testImageID1 {
279
+	if associations[0].ID != testImageID1 {
280 280
 		t.Fatalf("unexpected reference: %v", associations[0].Ref.String())
281 281
 	}
282 282
 	if associations[1].Ref.String() != ref1.String() {
283 283
 		t.Fatalf("unexpected reference: %v", associations[1].Ref.String())
284 284
 	}
285
-	if associations[1].ImageID != testImageID1 {
285
+	if associations[1].ID != testImageID1 {
286 286
 		t.Fatalf("unexpected reference: %v", associations[1].Ref.String())
287 287
 	}
288 288
 	if associations[2].Ref.String() != ref2.String() {
289 289
 		t.Fatalf("unexpected reference: %v", associations[2].Ref.String())
290 290
 	}
291
-	if associations[2].ImageID != testImageID2 {
291
+	if associations[2].ID != testImageID2 {
292 292
 		t.Fatalf("unexpected reference: %v", associations[2].Ref.String())
293 293
 	}
294 294
 
... ...
@@ -331,7 +331,7 @@ func TestInvalidTags(t *testing.T) {
331 331
 	if err != nil {
332 332
 		t.Fatalf("error creating tag store: %v", err)
333 333
 	}
334
-	id := image.ID("sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6")
334
+	id := digest.Digest("sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6")
335 335
 
336 336
 	// sha256 as repo name
337 337
 	ref, err := ParseNamed("sha256:abc")