/
collection.go
147 lines (115 loc) · 3.17 KB
/
collection.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Package collection provides a "container" structure to store Docker
// registry query results in a well organized and easily accessible form.
package collection
import (
"fmt"
"github.com/ivanilves/lstags/repository"
"github.com/ivanilves/lstags/tag"
)
func refHasTags(ref string, tags map[string][]*tag.Tag) bool {
for r := range tags {
if r == ref {
return true
}
}
return false
}
func contains(slice []string, str string) bool {
for _, s := range slice {
if s == str {
return true
}
}
return false
}
// New creates a collection of API resources from passed repository references and tags
func New(refs []string, tags map[string][]*tag.Tag) (*Collection, error) {
repos := make(map[string]*repository.Repository)
for _, ref := range refs {
repo, err := repository.ParseRef(ref)
if err != nil {
return nil, err
}
repos[ref] = repo
if !refHasTags(ref, tags) {
return nil, fmt.Errorf("repository reference has no tags: %s", ref)
}
}
for ref := range tags {
if !contains(refs, ref) {
return nil, fmt.Errorf("repository has tags, but not referenced: %s", ref)
}
}
return &Collection{refs: refs, repos: repos, tags: tags}, nil
}
// Collection of API resources received from a registry or Docker daemon query
type Collection struct {
refs []string
repos map[string]*repository.Repository
tags map[string][]*tag.Tag
}
// Refs returns all repository references from collection
func (cn *Collection) Refs() []string {
return cn.refs
}
// Repos returns all repository structures from collection
func (cn *Collection) Repos() []*repository.Repository {
repos := make([]*repository.Repository, cn.RepoCount())
for i, ref := range cn.Refs() {
repos[i] = cn.repos[ref]
}
return repos
}
// Repo returns repo structure, if it is present in collection (nil if not)
func (cn *Collection) Repo(ref string) *repository.Repository {
for _, r := range cn.Refs() {
if r == ref {
return cn.repos[ref]
}
}
return nil
}
// Tags returns slice of tag structures, if it is present in collection (nil if not)
func (cn *Collection) Tags(ref string) []*tag.Tag {
repo := cn.Repo(ref)
if repo == nil {
return nil
}
return cn.tags[ref]
}
// TagMap returns [name]*Tag map of tag structures, if it is present in collection (nil if not)
func (cn *Collection) TagMap(ref string) map[string]*tag.Tag {
tags := cn.Tags(ref)
if tags == nil {
return nil
}
tagMap := make(map[string]*tag.Tag)
for _, tg := range tags {
tagMap[tg.Name()] = tg
}
return tagMap
}
// RepoCount counts total repo number inside the collection
func (cn *Collection) RepoCount() int {
return len(cn.refs)
}
// TagCount counts total tag number inside the collection
func (cn *Collection) TagCount() int {
i := 0
for _, v := range cn.tags {
i += len(v)
}
return i
}
// TaggedRefs returns a slice of [REGISTRY/]REPOSITORY:TAG references for all tags present in collection
func (cn *Collection) TaggedRefs() []string {
taggedRefs := make([]string, 0)
for _, ref := range cn.Refs() {
repo := cn.Repo(ref)
for _, tg := range cn.Tags(ref) {
taggedRef := fmt.Sprintf("%s:%s", repo.Name(), tg.Name())
taggedRefs = append(taggedRefs, taggedRef)
}
}
return taggedRefs
}