|
@@ -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
|
|
|
}
|