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 }