github.com/devcamcar/cli@v0.0.0-20181107134215-706a05759d18/common/walker.go (about)

     1  package common
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  )
     9  
    10  // WalkFuncsFunc good name huh?
    11  type walkFuncsFunc func(path string, ff *FuncFile, err error) error
    12  type walkFuncsFuncV20180708 func(path string, ff *FuncFileV20180708, err error) error
    13  
    14  // WalkFuncs is similar to filepath.Walk except only returns func.yaml's (so on per function)
    15  func WalkFuncs(root string, walkFn walkFuncsFunc) error {
    16  	return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
    17  		if err != nil {
    18  			// logging this so we can figure out any common issues
    19  			fmt.Println("error walking filesystem:", err)
    20  			return err
    21  		}
    22  		// was `path != wd` necessary?
    23  		if info.IsDir() {
    24  			return nil
    25  		}
    26  
    27  		if !IsFuncFile(path, info) {
    28  			return nil
    29  		}
    30  
    31  		// TODO: test/try this again to speed up deploys.
    32  		if false && !isstale(path) {
    33  			return nil
    34  		}
    35  		// Then we found a func file, so let's deploy it:
    36  		ff, err := ParseFuncfile(path)
    37  		// if err != nil {
    38  		// return err
    39  		// }
    40  		return walkFn(path, ff, err)
    41  	})
    42  }
    43  
    44  // WalkFuncs is similar to filepath.Walk except only returns func.yaml's (so on per function)
    45  func WalkFuncsV20180708(root string, walkFn walkFuncsFuncV20180708) error {
    46  	return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
    47  		if err != nil {
    48  			// logging this so we can figure out any common issues
    49  			fmt.Println("error walking filesystem:", err)
    50  			return err
    51  		}
    52  		// was `path != wd` necessary?
    53  		if info.IsDir() {
    54  			return nil
    55  		}
    56  
    57  		if !IsFuncFile(path, info) {
    58  			return nil
    59  		}
    60  
    61  		// TODO: test/try this again to speed up deploys.
    62  		if false && !isstale(path) {
    63  			return nil
    64  		}
    65  		// Then we found a func file, so let's deploy it:
    66  		ff, err := ParseFuncFileV20180708(path)
    67  		// if err != nil {
    68  		// return err
    69  		// }
    70  		return walkFn(path, ff, err)
    71  	})
    72  }
    73  
    74  // Theory of operation: this takes an optimistic approach to detect whether a
    75  // package must be rebuild/bump/deployed. It loads for all files mtime's and
    76  // compare with functions.json own mtime. If any file is younger than
    77  // functions.json, it triggers a rebuild.
    78  // The problem with this approach is that depending on the OS running it, the
    79  // time granularity of these timestamps might lead to false negatives - that is
    80  // a package that is stale but it is not recompiled. A more elegant solution
    81  // could be applied here, like https://golang.org/src/cmd/go/pkg.go#L1111
    82  func isstale(path string) bool {
    83  	fi, err := os.Stat(path)
    84  	if err != nil {
    85  		return true
    86  	}
    87  
    88  	fnmtime := fi.ModTime()
    89  	dir := filepath.Dir(path)
    90  	err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
    91  		if info.IsDir() {
    92  			return nil
    93  		}
    94  		if info.ModTime().After(fnmtime) {
    95  			return errors.New("found stale package")
    96  		}
    97  		return nil
    98  	})
    99  
   100  	return err != nil
   101  }