github.com/sc0rp1us/gb@v0.4.1-0.20160319180011-4ba8cf1baa5a/vendor/depset.go (about) 1 package vendor 2 3 import ( 4 "fmt" 5 "go/build" 6 "os" 7 "path/filepath" 8 "strings" 9 ) 10 11 // Pkg describes a Go package. 12 type Pkg struct { 13 *Depset 14 *build.Package 15 } 16 17 // Depset describes a set of related Go packages. 18 type Depset struct { 19 Root string 20 Prefix string 21 Pkgs map[string]*Pkg 22 } 23 24 // LoadPaths returns a map of paths to Depsets. 25 func LoadPaths(paths ...struct{ Root, Prefix string }) (map[string]*Depset, error) { 26 m := make(map[string]*Depset) 27 for _, p := range paths { 28 set, err := LoadTree(p.Root, p.Prefix) 29 if err != nil { 30 return nil, err 31 } 32 m[set.Root] = set 33 } 34 return m, nil 35 } 36 37 // LoadTree parses a tree of source files into a map of *pkgs. 38 func LoadTree(root string, prefix string) (*Depset, error) { 39 d := Depset{ 40 Root: root, 41 Prefix: prefix, 42 Pkgs: make(map[string]*Pkg), 43 } 44 fn := func(dir string, fi os.FileInfo) error { 45 importpath := filepath.Join(prefix, dir[len(root)+1:]) 46 47 // if we're at the root of a tree, skip it 48 if importpath == "" { 49 return nil 50 } 51 52 p, err := loadPackage(&d, dir) 53 if err != nil { 54 if _, ok := err.(*build.NoGoError); ok { 55 return nil 56 } 57 return fmt.Errorf("loadPackage(%q, %q): %v", dir, importpath, err) 58 } 59 p.ImportPath = filepath.ToSlash(importpath) 60 if p != nil { 61 d.Pkgs[p.ImportPath] = p 62 } 63 return nil 64 } 65 66 // handle root of the tree 67 fi, err := os.Stat(root) 68 if err != nil { 69 return nil, err 70 } 71 if err := fn(root+string(filepath.Separator), fi); err != nil { 72 return nil, err 73 } 74 75 // walk sub directories 76 err = eachDir(root, fn) 77 return &d, err 78 } 79 80 func loadPackage(d *Depset, dir string) (*Pkg, error) { 81 p := Pkg{ 82 Depset: d, 83 } 84 var err error 85 86 // expolit local import logic 87 p.Package, err = build.ImportDir(dir, build.ImportComment) 88 return &p, err 89 } 90 91 func eachDir(dir string, fn func(string, os.FileInfo) error) error { 92 f, err := os.Open(dir) 93 if err != nil { 94 return err 95 } 96 defer f.Close() 97 files, err := f.Readdir(-1) 98 for _, fi := range files { 99 if !fi.IsDir() { 100 continue 101 } 102 if strings.HasPrefix(fi.Name(), "_") || strings.HasPrefix(fi.Name(), ".") || fi.Name() == "testdata" { 103 continue 104 } 105 path := filepath.Join(dir, fi.Name()) 106 if err := fn(path, fi); err != nil { 107 return err 108 } 109 if err := eachDir(path, fn); err != nil { 110 return err 111 } 112 } 113 return nil 114 }