...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package name
16
17 import (
18 "fmt"
19 "strings"
20 )
21
22 const (
23 defaultNamespace = "library"
24 repositoryChars = "abcdefghijklmnopqrstuvwxyz0123456789_-./"
25 regRepoDelimiter = "/"
26 )
27
28
29 type Repository struct {
30 Registry
31 repository string
32 }
33
34
35 func hasImplicitNamespace(repo string, reg Registry) bool {
36 return !strings.ContainsRune(repo, '/') && reg.RegistryStr() == DefaultRegistry
37 }
38
39
40 func (r Repository) RepositoryStr() string {
41 if hasImplicitNamespace(r.repository, r.Registry) {
42 return fmt.Sprintf("%s/%s", defaultNamespace, r.repository)
43 }
44 return r.repository
45 }
46
47
48 func (r Repository) Name() string {
49 regName := r.Registry.Name()
50 if regName != "" {
51 return regName + regRepoDelimiter + r.RepositoryStr()
52 }
53
54 return r.RepositoryStr()
55 }
56
57 func (r Repository) String() string {
58 return r.Name()
59 }
60
61
62
63 func (r Repository) Scope(action string) string {
64 return fmt.Sprintf("repository:%s:%s", r.RepositoryStr(), action)
65 }
66
67 func checkRepository(repository string) error {
68 return checkElement("repository", repository, repositoryChars, 2, 255)
69 }
70
71
72 func NewRepository(name string, opts ...Option) (Repository, error) {
73 opt := makeOptions(opts...)
74 if len(name) == 0 {
75 return Repository{}, newErrBadName("a repository name must be specified")
76 }
77
78 var registry string
79 repo := name
80 parts := strings.SplitN(name, regRepoDelimiter, 2)
81 if len(parts) == 2 && (strings.ContainsRune(parts[0], '.') || strings.ContainsRune(parts[0], ':')) {
82
83
84
85 registry = parts[0]
86 repo = parts[1]
87 }
88
89 if err := checkRepository(repo); err != nil {
90 return Repository{}, err
91 }
92
93 reg, err := NewRegistry(registry, opts...)
94 if err != nil {
95 return Repository{}, err
96 }
97 if hasImplicitNamespace(repo, reg) && opt.strict {
98 return Repository{}, newErrBadName("strict validation requires the full repository path (missing 'library')")
99 }
100 return Repository{reg, repo}, nil
101 }
102
103
104 func (r Repository) Tag(identifier string) Tag {
105 t := Tag{
106 tag: identifier,
107 Repository: r,
108 }
109 t.original = t.Name()
110 return t
111 }
112
113
114 func (r Repository) Digest(identifier string) Digest {
115 d := Digest{
116 digest: identifier,
117 Repository: r,
118 }
119 d.original = d.Name()
120 return d
121 }
122
View as plain text