...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package ocimem
18
19 import (
20 "fmt"
21 "sync"
22
23 "cuelabs.dev/go/oci/ociregistry"
24 "github.com/opencontainers/go-digest"
25 )
26
27 var _ ociregistry.Interface = (*Registry)(nil)
28
29 type Registry struct {
30 *ociregistry.Funcs
31 cfg Config
32 mu sync.Mutex
33 repos map[string]*repository
34 }
35
36 type repository struct {
37 tags map[string]ociregistry.Descriptor
38 manifests map[ociregistry.Digest]*blob
39 blobs map[ociregistry.Digest]*blob
40 uploads map[string]*Buffer
41 }
42
43 type blob struct {
44 mediaType string
45 data []byte
46 subject digest.Digest
47 }
48
49 func (b *blob) descriptor() ociregistry.Descriptor {
50 return ociregistry.Descriptor{
51 MediaType: b.mediaType,
52 Size: int64(len(b.data)),
53 Digest: digest.FromBytes(b.data),
54 }
55 }
56
57
58
59
60
61 func New() *Registry {
62 return NewWithConfig(nil)
63 }
64
65
66
67
68 func NewWithConfig(cfg0 *Config) *Registry {
69 var cfg Config
70 if cfg0 != nil {
71 cfg = *cfg0
72 }
73 return &Registry{
74 cfg: cfg,
75 }
76 }
77
78
79 type Config struct {
80
81
82
83
84
85
86
87
88 ImmutableTags bool
89 }
90
91 func (r *Registry) repo(repoName string) (*repository, error) {
92 if repo, ok := r.repos[repoName]; ok {
93 return repo, nil
94 }
95 return nil, ociregistry.ErrNameUnknown
96 }
97
98 func (r *Registry) manifestForDigest(repoName string, dig ociregistry.Digest) (*blob, error) {
99 repo, err := r.repo(repoName)
100 if err != nil {
101 return nil, err
102 }
103 b := repo.manifests[dig]
104 if b == nil {
105 return nil, ociregistry.ErrManifestUnknown
106 }
107 return b, nil
108 }
109
110 func (r *Registry) blobForDigest(repoName string, dig ociregistry.Digest) (*blob, error) {
111 repo, err := r.repo(repoName)
112 if err != nil {
113 return nil, err
114 }
115 b := repo.blobs[dig]
116 if b == nil {
117 return nil, ociregistry.ErrBlobUnknown
118 }
119 return b, nil
120 }
121
122 func (r *Registry) makeRepo(repoName string) (*repository, error) {
123 if !ociregistry.IsValidRepoName(repoName) {
124 return nil, ociregistry.ErrNameInvalid
125 }
126 if r.repos == nil {
127 r.repos = make(map[string]*repository)
128 }
129 if repo := r.repos[repoName]; repo != nil {
130 return repo, nil
131 }
132 repo := &repository{
133 tags: make(map[string]ociregistry.Descriptor),
134 manifests: make(map[digest.Digest]*blob),
135 blobs: make(map[digest.Digest]*blob),
136 uploads: make(map[string]*Buffer),
137 }
138 r.repos[repoName] = repo
139 return repo, nil
140 }
141
142
143 const emptyHash = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
144
145
146
147 func CheckDescriptor(desc ociregistry.Descriptor, data []byte) error {
148 if err := desc.Digest.Validate(); err != nil {
149 return fmt.Errorf("invalid digest: %v", err)
150 }
151 if data != nil {
152 if digest.FromBytes(data) != desc.Digest {
153 return fmt.Errorf("digest mismatch")
154 }
155 if desc.Size != int64(len(data)) {
156 return fmt.Errorf("size mismatch")
157 }
158 } else {
159 if desc.Size == 0 && desc.Digest != emptyHash {
160 return fmt.Errorf("zero sized content with mismatching digest")
161 }
162 }
163 if desc.MediaType == "" {
164 return fmt.Errorf("no media type in descriptor")
165 }
166 return nil
167 }
168
View as plain text