github.com/tooploox/oya@v0.0.21-0.20230524103240-1cda1861aad6/pkg/project/list.go (about) 1 package project 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 8 "github.com/pkg/errors" 9 "github.com/tooploox/oya/pkg/oyafile" 10 "k8s.io/helm/pkg/ignore" 11 ) 12 13 func (p *Project) Oyafiles() ([]*oyafile.Oyafile, error) { 14 return p.List(p.RootDir) 15 } 16 17 func (p *Project) List(startDir string) ([]*oyafile.Oyafile, error) { 18 skip := p.makeSkipFunc(startDir) 19 ignore, err := p.makeIgnoreFunc() 20 if err != nil { 21 return nil, errors.Wrapf(err, "error setting up ignores in %v", startDir) 22 } 23 var oyafiles []*oyafile.Oyafile 24 return oyafiles, filepath.Walk(startDir, func(path string, info os.FileInfo, err error) error { 25 if err != nil { 26 return err 27 } 28 if !info.IsDir() { 29 return nil 30 } 31 doSkip, err := skip(path) 32 if err != nil { 33 return errors.Wrapf(err, "error trying to determine if %v should be skipped", path) 34 } 35 if doSkip { 36 return filepath.SkipDir 37 } 38 oyafile, ok, err := p.oyafileIn(path) 39 if err != nil { 40 return errors.Wrapf(err, "error loading Oyafile from %v", path) 41 } 42 if !ok { 43 return nil 44 } 45 doIgnore, err := ignore(oyafile) 46 if err != nil { 47 return errors.Wrapf(err, "error trying to determine if %v should be ignored", oyafile.Path) 48 } 49 if doIgnore { 50 return filepath.SkipDir 51 } 52 oyafiles = append(oyafiles, oyafile) 53 return nil 54 }) 55 } 56 57 // makeSkipFunc returns a function that given a path, returns 58 // true if the entire subdirectory should be ignored. 59 // Similar to makeIgnoreFunc but does not parse Oyafile, thus allowing 60 // for broken Oyafile projects nested under the current project. 61 func (p *Project) makeSkipFunc(startDir string) func(path string) (bool, error) { 62 return func(path string) (bool, error) { 63 // Exclude projects nested under the current project. 64 65 raw, found, err := p.rawOyafileIn(path) 66 if err != nil { 67 return false, err 68 } 69 if !found { 70 return false, nil 71 } 72 73 isRoot, err := raw.IsRoot() 74 if err != nil { 75 return false, err 76 } 77 78 // BUG(bilus): Clean up this magic string & logic duplication everywhere. 79 _, isProject, err := raw.Project() 80 if err != nil { 81 return false, err 82 } 83 84 return isProject && !isRoot, nil 85 } 86 } 87 88 // makeIgnoreFunc returns a function that given an oyafile returns true if its containing directory tree should be recursively ignored. 89 // It uses an array of relative paths under "Ignore:" key in the project's root Oyafile. 90 // BUG(bilus): We should probably make it more intuitive by supporting Ignore: directives in nested dirs as well as the root dir. 91 func (p *Project) makeIgnoreFunc() (func(*oyafile.Oyafile) (bool, error), error) { 92 o, ok, err := p.oyafileIn(p.RootDir) 93 if err != nil { 94 return nil, errors.Wrapf(err, "error looking for Ignore: directive") 95 } 96 if !ok { 97 return nil, errors.Errorf("No oyafile found at %v", p.RootDir) 98 } 99 ignore, err := ignore.Parse(strings.NewReader(o.Ignores())) 100 if err != nil { 101 return nil, errors.Wrapf(err, "Ignore: in %v contains invalid entries", o.Path) 102 } 103 return func(o *oyafile.Oyafile) (bool, error) { 104 fi, err := os.Stat(o.Path) 105 if err != nil { 106 return true, err 107 } 108 109 return ignore.Ignore(o.RelPath(), fi), nil 110 }, nil 111 }