3434// walkFunc is a function type that gets called for each file or directory visited by the Walker.
3535type walkFunc func (path string , _ os.FileInfo , _ io.Reader ) error
3636
37+ type findFunc func (path string , r io.Reader ) error
38+
3739// walker is the interface that defines how to access a given archival format
3840type walker interface {
3941
@@ -43,6 +45,9 @@ type walker interface {
4345 // get will copy an arbitrary blob, defined by desc, in to dst. returns
4446 // the number of bytes copied on success.
4547 get (desc v1.Descriptor , dst io.Writer ) (int64 , error )
48+
49+ // find calls findFunc for handling content of path
50+ find (path string , ff findFunc ) error
4651}
4752
4853// tarWalker exposes access to image layouts in a tar file.
@@ -120,6 +125,34 @@ func (w *tarWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
120125 return bytes , nil
121126}
122127
128+ func (w * tarWalker ) find (path string , ff findFunc ) error {
129+ done := false
130+
131+ f := func (relpath string , info os.FileInfo , rdr io.Reader ) error {
132+ var err error
133+ if done {
134+ return nil
135+ }
136+
137+ if filepath .Clean (relpath ) == path && ! info .IsDir () {
138+ if err = ff (relpath , rdr ); err != nil {
139+ return err
140+ }
141+ done = true
142+ }
143+ return nil
144+ }
145+
146+ if err := w .walk (f ); err != nil {
147+ return errors .Wrapf (err , "find failed: unable to walk" )
148+ }
149+ if ! done {
150+ return os .ErrNotExist
151+ }
152+
153+ return nil
154+ }
155+
123156type eofReader struct {}
124157
125158func (eofReader ) Read (_ []byte ) (int , error ) {
@@ -188,6 +221,27 @@ func (w *pathWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
188221 return nbytes , nil
189222}
190223
224+ func (w * pathWalker ) find (path string , ff findFunc ) error {
225+ name := filepath .Join (w .root , path )
226+
227+ info , err := os .Stat (name )
228+ if err != nil {
229+ return err
230+ }
231+
232+ if info .IsDir () {
233+ return fmt .Errorf ("object is dir" )
234+ }
235+
236+ file , err := os .Open (name )
237+ if err != nil {
238+ return errors .Wrap (err , "unable to open file" ) // os.Open includes the path
239+ }
240+ defer file .Close ()
241+
242+ return ff (name , file )
243+ }
244+
191245type zipWalker struct {
192246 fileName string
193247}
@@ -249,3 +303,31 @@ func (w *zipWalker) get(desc v1.Descriptor, dst io.Writer) (int64, error) {
249303
250304 return bytes , nil
251305}
306+
307+ func (w * zipWalker ) find (path string , ff findFunc ) error {
308+ done := false
309+
310+ f := func (relpath string , info os.FileInfo , rdr io.Reader ) error {
311+ var err error
312+ if done {
313+ return nil
314+ }
315+
316+ if filepath .Clean (relpath ) == path && ! info .IsDir () {
317+ if err = ff (relpath , rdr ); err != nil {
318+ return err
319+ }
320+ done = true
321+ }
322+ return nil
323+ }
324+
325+ if err := w .walk (f ); err != nil {
326+ return errors .Wrapf (err , "find failed: unable to walk" )
327+ }
328+ if ! done {
329+ return os .ErrNotExist
330+ }
331+
332+ return nil
333+ }
0 commit comments