@@ -11,7 +11,6 @@ import (
1111
1212 "github.com/deislabs/cnab-go/bundle"
1313 "github.com/docker/distribution/reference"
14- "github.com/opencontainers/go-digest"
1514 "github.com/pkg/errors"
1615)
1716
@@ -22,12 +21,27 @@ type BundleStore interface {
2221 Read (ref reference.Reference ) (* bundle.Bundle , error )
2322 List () ([]reference.Reference , error )
2423 Remove (ref reference.Reference ) error
24+ LookUp (refOrID string ) (reference.Reference , error )
2525}
2626
2727var _ BundleStore = & bundleStore {}
2828
2929type 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
3145}
3246
3347// 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
7286}
7387
7488func (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 )
7691 if err != nil {
7792 return nil , errors .Wrapf (err , "failed to read bundle %q" , ref )
7893 }
7994
80- data , err := ioutil . ReadFile (filepath .Join (path , "bundle.json" ))
95+ bndl , err := b . fetchBundleJSON (filepath .Join (paths [ 0 ] , "bundle.json" ))
8196 if err != nil {
8297 return nil , errors .Wrapf (err , "failed to read bundle %q" , ref )
8398 }
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
89100}
90101
91102// Returns the list of all bundles present in the bundle store
92103func (b * bundleStore ) List () ([]reference.Reference , error ) {
93104 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- }
114105
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 )
118109 }
119-
120- references = append (references , ref )
121-
122- return nil
123- }); err != nil {
124- return nil , err
125110 }
126111
127112 sort .Slice (references , func (i , j int ) bool {
@@ -143,6 +128,75 @@ func (b *bundleStore) Remove(ref reference.Reference) error {
143128 return os .RemoveAll (path )
144129}
145130
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+
146200func (b * bundleStore ) storePath (ref reference.Reference ) (string , error ) {
147201 named , ok := ref .(reference.Named )
148202 if ! ok {
@@ -175,6 +229,72 @@ func (b *bundleStore) storePath(ref reference.Reference) (string, error) {
175229 return storeDir , nil
176230}
177231
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+
178298func (b * bundleStore ) pathToReference (path string ) (reference.Named , error ) {
179299 // Clean the path and remove the local bundle store path
180300 cleanpath := filepath .ToSlash (path )
0 commit comments