@@ -11,7 +11,6 @@ import (
11
11
12
12
"github.com/deislabs/cnab-go/bundle"
13
13
"github.com/docker/distribution/reference"
14
- "github.com/opencontainers/go-digest"
15
14
"github.com/pkg/errors"
16
15
)
17
16
@@ -22,12 +21,27 @@ type BundleStore interface {
22
21
Read (ref reference.Reference ) (* bundle.Bundle , error )
23
22
List () ([]reference.Reference , error )
24
23
Remove (ref reference.Reference ) error
24
+ LookUp (refOrID string ) (reference.Reference , error )
25
25
}
26
26
27
27
var _ BundleStore = & bundleStore {}
28
28
29
29
type bundleStore struct {
30
- path string
30
+ path string
31
+ referenceMap map [ID ][]reference.Reference
32
+ }
33
+
34
+ func NewBundleStore (path string ) (BundleStore , error ) {
35
+ bundleStore := & bundleStore {
36
+ path : path ,
37
+ referenceMap : make (map [ID ][]reference.Reference ),
38
+ }
39
+ err := bundleStore .scanAllBundles ()
40
+ if err != nil {
41
+ return nil , err
42
+ }
43
+ fmt .Println (bundleStore .referenceMap )
44
+ return bundleStore , nil
31
45
}
32
46
33
47
// We store bundles either by image:tags, image:digest or by unique ID (actually, bundle's sha256).
@@ -72,56 +86,27 @@ func (b *bundleStore) Store(ref reference.Reference, bndle *bundle.Bundle) (refe
72
86
}
73
87
74
88
func (b * bundleStore ) Read (ref reference.Reference ) (* bundle.Bundle , error ) {
75
- path , err := b .storePath (ref )
89
+ paths , err := b .storePaths (ref )
90
+ fmt .Println (paths )
76
91
if err != nil {
77
92
return nil , errors .Wrapf (err , "failed to read bundle %q" , ref )
78
93
}
79
94
80
- data , err := ioutil . ReadFile (filepath .Join (path , "bundle.json" ))
95
+ bndl , err := b . fetchBundleJSON (filepath .Join (paths [ 0 ] , "bundle.json" ))
81
96
if err != nil {
82
97
return nil , errors .Wrapf (err , "failed to read bundle %q" , ref )
83
98
}
84
- var bndle bundle.Bundle
85
- if err := json .Unmarshal (data , & bndle ); err != nil {
86
- return nil , errors .Wrapf (err , "failed to read bundle %q" , ref )
87
- }
88
- return & bndle , nil
99
+ return bndl , nil
89
100
}
90
101
91
102
// Returns the list of all bundles present in the bundle store
92
103
func (b * bundleStore ) List () ([]reference.Reference , error ) {
93
104
var references []reference.Reference
94
- digests := filepath .Join (b .path , "_ids" )
95
- if err := filepath .Walk (b .path , func (path string , info os.FileInfo , err error ) error {
96
- if err != nil {
97
- return err
98
- }
99
-
100
- if info .IsDir () {
101
- return nil
102
- }
103
-
104
- if ! strings .HasSuffix (info .Name (), ".json" ) {
105
- return nil
106
- }
107
-
108
- if strings .HasPrefix (path , digests ) {
109
- rel := path [len (digests )+ 1 :]
110
- dg := strings .Split (filepath .ToSlash (rel ), "/" )[0 ]
111
- references = append (references , ID {digest .NewDigestFromEncoded (digest .SHA256 , dg )})
112
- return nil
113
- }
114
105
115
- ref , err := b . pathToReference ( path )
116
- if err != nil {
117
- return err
106
+ for _ , refAliases := range b . referenceMap {
107
+ for _ , ref := range refAliases {
108
+ references = append ( references , ref )
118
109
}
119
-
120
- references = append (references , ref )
121
-
122
- return nil
123
- }); err != nil {
124
- return nil , err
125
110
}
126
111
127
112
sort .Slice (references , func (i , j int ) bool {
@@ -143,6 +128,75 @@ func (b *bundleStore) Remove(ref reference.Reference) error {
143
128
return os .RemoveAll (path )
144
129
}
145
130
131
+ func (b * bundleStore ) LookUp (refOrID string ) (reference.Reference , error ) {
132
+ ref , err := FromString (refOrID )
133
+ if err == nil {
134
+ return ref , nil
135
+ }
136
+ if isShortID (refOrID ) {
137
+ ref , err := b .matchShortID (refOrID )
138
+ if err == nil {
139
+ return ref , nil
140
+ }
141
+ }
142
+ return reference .ParseNormalizedNamed (refOrID )
143
+ }
144
+
145
+ func (b * bundleStore ) matchShortID (shortID string ) (reference.Reference , error ) {
146
+ var found reference.Reference
147
+ for id := range b .referenceMap {
148
+ if strings .HasPrefix (id .String (), shortID ) {
149
+ if found != nil && found != id {
150
+ return nil , fmt .Errorf ("Ambiguous reference found" )
151
+ }
152
+ found = id
153
+ }
154
+ }
155
+ if found == nil {
156
+ return nil , fmt .Errorf ("Could not find reference" )
157
+ }
158
+ fmt .Printf ("found = %s\n " , found )
159
+ return found , nil
160
+ }
161
+
162
+ func (b * bundleStore ) referenceToID (ref reference.Reference ) (ID , error ) {
163
+ if id , ok := ref .(ID ); ok {
164
+ return id , nil
165
+ }
166
+ for id , refs := range b .referenceMap {
167
+ for _ , r := range refs {
168
+ if r == ref {
169
+ return id , nil
170
+ }
171
+ }
172
+ }
173
+ return ID {}, fmt .Errorf ("%s: reference not found" , ref .String ())
174
+ }
175
+
176
+ func (b * bundleStore ) storePaths (ref reference.Reference ) ([]string , error ) {
177
+ var paths []string
178
+
179
+ id , err := b .referenceToID (ref )
180
+ if err != nil {
181
+ return nil , err
182
+ }
183
+
184
+ if refs , exist := b .referenceMap [id ]; exist {
185
+ for _ , rf := range refs {
186
+ path , err := b .storePath (rf )
187
+ if err != nil {
188
+ continue
189
+ }
190
+ paths = append (paths , path )
191
+ }
192
+ }
193
+
194
+ if len (paths ) == 0 {
195
+ return nil , fmt .Errorf ("%s: reference not found" , ref .String ())
196
+ }
197
+ return paths , nil
198
+ }
199
+
146
200
func (b * bundleStore ) storePath (ref reference.Reference ) (string , error ) {
147
201
named , ok := ref .(reference.Named )
148
202
if ! ok {
@@ -175,6 +229,72 @@ func (b *bundleStore) storePath(ref reference.Reference) (string, error) {
175
229
return storeDir , nil
176
230
}
177
231
232
+ // Returns the list of all bundles present in the bundle store
233
+ func (b * bundleStore ) scanAllBundles () error {
234
+ digests := filepath .Join (b .path , "_ids" )
235
+ if err := filepath .Walk (b .path , func (path string , info os.FileInfo , err error ) error {
236
+ if err != nil {
237
+ return err
238
+ }
239
+
240
+ if info .IsDir () {
241
+ return nil
242
+ }
243
+
244
+ if ! strings .HasSuffix (info .Name (), ".json" ) {
245
+ return nil
246
+ }
247
+
248
+ if strings .HasPrefix (path , digests ) {
249
+ rel := path [len (digests )+ 1 :]
250
+ dg := strings .Split (filepath .ToSlash (rel ), "/" )[0 ]
251
+ //references = append(references, ID{dg})
252
+ id := ID {dg }
253
+ if _ , ok := b .referenceMap [id ]; ! ok {
254
+ b .referenceMap [id ] = []reference.Reference {id }
255
+ } else {
256
+ b .referenceMap [id ] = append (b .referenceMap [id ], id )
257
+ }
258
+ return nil
259
+ }
260
+
261
+ ref , err := b .pathToReference (path )
262
+ if err != nil {
263
+ return err
264
+ }
265
+ bndl , err := b .fetchBundleJSON (path )
266
+ if err != nil {
267
+ return err
268
+ }
269
+ id , err := FromBundle (bndl )
270
+ if err != nil {
271
+ return err
272
+ }
273
+ if _ , ok := b .referenceMap [id ]; ! ok {
274
+ b .referenceMap [id ] = []reference.Reference {ref }
275
+ } else {
276
+ b .referenceMap [id ] = append (b .referenceMap [id ], ref )
277
+ }
278
+
279
+ return nil
280
+ }); err != nil {
281
+ return err
282
+ }
283
+ return nil
284
+ }
285
+
286
+ func (b * bundleStore ) fetchBundleJSON (bundlePath string ) (* bundle.Bundle , error ) {
287
+ data , err := ioutil .ReadFile (bundlePath )
288
+ if err != nil {
289
+ return nil , errors .Wrapf (err , "failed to read file %s" , bundlePath )
290
+ }
291
+ var bndle bundle.Bundle
292
+ if err := json .Unmarshal (data , & bndle ); err != nil {
293
+ return nil , errors .Wrapf (err , "failed to read file %s" , bundlePath )
294
+ }
295
+ return & bndle , nil
296
+ }
297
+
178
298
func (b * bundleStore ) pathToReference (path string ) (reference.Named , error ) {
179
299
// Clean the path and remove the local bundle store path
180
300
cleanpath := filepath .ToSlash (path )
0 commit comments