...

Source file src/github.com/docker/distribution/registry/storage/driver/walk.go

Documentation: github.com/docker/distribution/registry/storage/driver

     1  package driver
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"sort"
     7  
     8  	"github.com/sirupsen/logrus"
     9  )
    10  
    11  // ErrSkipDir is used as a return value from onFileFunc to indicate that
    12  // the directory named in the call is to be skipped. It is not returned
    13  // as an error by any function.
    14  var ErrSkipDir = errors.New("skip this directory")
    15  
    16  // WalkFn is called once per file by Walk
    17  type WalkFn func(fileInfo FileInfo) error
    18  
    19  // WalkFallback traverses a filesystem defined within driver, starting
    20  // from the given path, calling f on each file. It uses the List method and Stat to drive itself.
    21  // If the returned error from the WalkFn is ErrSkipDir and fileInfo refers
    22  // to a directory, the directory will not be entered and Walk
    23  // will continue the traversal.  If fileInfo refers to a normal file, processing stops
    24  func WalkFallback(ctx context.Context, driver StorageDriver, from string, f WalkFn) error {
    25  	children, err := driver.List(ctx, from)
    26  	if err != nil {
    27  		return err
    28  	}
    29  	sort.Stable(sort.StringSlice(children))
    30  	for _, child := range children {
    31  		// TODO(stevvooe): Calling driver.Stat for every entry is quite
    32  		// expensive when running against backends with a slow Stat
    33  		// implementation, such as s3. This is very likely a serious
    34  		// performance bottleneck.
    35  		fileInfo, err := driver.Stat(ctx, child)
    36  		if err != nil {
    37  			switch err.(type) {
    38  			case PathNotFoundError:
    39  				// repository was removed in between listing and enumeration. Ignore it.
    40  				logrus.WithField("path", child).Infof("ignoring deleted path")
    41  				continue
    42  			default:
    43  				return err
    44  			}
    45  		}
    46  		err = f(fileInfo)
    47  		if err == nil && fileInfo.IsDir() {
    48  			if err := WalkFallback(ctx, driver, child, f); err != nil {
    49  				return err
    50  			}
    51  		} else if err == ErrSkipDir {
    52  			// Stop iteration if it's a file, otherwise noop if it's a directory
    53  			if !fileInfo.IsDir() {
    54  				return nil
    55  			}
    56  		} else if err != nil {
    57  			return err
    58  		}
    59  	}
    60  	return nil
    61  }
    62  

View as plain text