func (ts *tagStore) Lookup(ctx context.Context, desc distribution.Descriptor) ([]string, error) {
	allTags, err := ts.All(ctx)
	switch err.(type) {
	case distribution.ErrRepositoryUnknown:
		break
	case nil:
		break
	default:
		return nil, err
	}
	var tags []string
	for _, tag := range allTags {
		tagLinkPathSpec := manifestTagCurrentPathSpec{
			name: ts.repository.Named().Name(),
			tag:  tag,
		}
		tagLinkPath, err := pathFor(tagLinkPathSpec)
		tagDigest, err := ts.blobStore.readlink(ctx, tagLinkPath)
		if err != nil {
			return nil, err
		}
		if tagDigest == desc.Digest {
			tags = append(tags, tag)
		}
	}
	return tags, nil
}
Lookup recovers a list of tags which refer to this digest.  When a manifest is deleted by
digest, tag entries which point to it need to be recovered to avoid dangling tags.
package storage
import (
	"path"
	"github.com/docker/distribution"
	"github.com/docker/distribution/context"
	"github.com/docker/distribution/digest"
	storagedriver "github.com/docker/distribution/registry/storage/driver"
)
var _ distribution.TagService = &tagStore{}
type tagStore struct {
	repository *repository
	blobStore  *blobStore
}
func (ts *tagStore) All(ctx context.Context) ([]string, error) {
	var tags []string
	pathSpec, err := pathFor(manifestTagPathSpec{
		name: ts.repository.Named().Name(),
	})
	if err != nil {
		return tags, err
	}
	entries, err := ts.blobStore.driver.List(ctx, pathSpec)
	if err != nil {
		switch err := err.(type) {
		case storagedriver.PathNotFoundError:
			return tags, distribution.ErrRepositoryUnknown{Name: ts.repository.Named().Name()}
		default:
			return tags, err
		}
	}
	for _, entry := range entries {
		_, filename := path.Split(entry)
		tags = append(tags, filename)
	}
	return tags, nil
}
func (ts *tagStore) exists(ctx context.Context, tag string) (bool, error) {
	tagPath, err := pathFor(manifestTagCurrentPathSpec{
		name: ts.repository.Named().Name(),
		tag:  tag,
	})
	if err != nil {
		return false, err
	}
	exists, err := exists(ctx, ts.blobStore.driver, tagPath)
	if err != nil {
		return false, err
	}
	return exists, nil
}
func (ts *tagStore) Tag(ctx context.Context, tag string, desc distribution.Descriptor) error {
	currentPath, err := pathFor(manifestTagCurrentPathSpec{
		name: ts.repository.Named().Name(),
		tag:  tag,
	})
	if err != nil {
		return err
	}
	lbs := ts.linkedBlobStore(ctx, tag)
	if err := lbs.linkBlob(ctx, desc); err != nil {
		return err
	}
	return ts.blobStore.link(ctx, currentPath, desc.Digest)
}
func (ts *tagStore) Get(ctx context.Context, tag string) (distribution.Descriptor, error) {
	currentPath, err := pathFor(manifestTagCurrentPathSpec{
		name: ts.repository.Named().Name(),
		tag:  tag,
	})
	if err != nil {
		return distribution.Descriptor{}, err
	}
	revision, err := ts.blobStore.readlink(ctx, currentPath)
	if err != nil {
		switch err.(type) {
		case storagedriver.PathNotFoundError:
			return distribution.Descriptor{}, distribution.ErrTagUnknown{Tag: tag}
		}
		return distribution.Descriptor{}, err
	}
	return distribution.Descriptor{Digest: revision}, nil
}
func (ts *tagStore) Untag(ctx context.Context, tag string) error {
	tagPath, err := pathFor(manifestTagPathSpec{
		name: ts.repository.Named().Name(),
		tag:  tag,
	})
	switch err.(type) {
	case storagedriver.PathNotFoundError:
		return distribution.ErrTagUnknown{Tag: tag}
	case nil:
		break
	default:
		return err
	}
	return ts.blobStore.driver.Delete(ctx, tagPath)
}
func (ts *tagStore) linkedBlobStore(ctx context.Context, tag string) *linkedBlobStore {
	return &linkedBlobStore{
		blobStore:  ts.blobStore,
		repository: ts.repository,
		ctx:        ctx,
		linkPathFns: []linkPathFunc{func(name string, dgst digest.Digest) (string, error) {
			return pathFor(manifestTagIndexEntryLinkPathSpec{
				name:     name,
				tag:      tag,
				revision: dgst,
			})
		}},
	}
}