github.com/mattn/gom@v0.0.0-20190726063113-0ebf2b5d812d/gen.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "go/build" 7 "os" 8 "path/filepath" 9 "sort" 10 "strings" 11 ) 12 13 type importPackages []importPackage 14 type importPackage struct { 15 path string 16 isTestFile bool 17 } 18 19 func (slice importPackages) Len() int { 20 return len(slice) 21 } 22 23 func (slice importPackages) Less(i, j int) bool { 24 return slice[i].path < slice[j].path 25 } 26 27 func (slice importPackages) Swap(i, j int) { 28 slice[i], slice[j] = slice[j], slice[i] 29 } 30 31 const travis_yml = ".travis.yml" 32 33 func genTravisYml() error { 34 _, err := os.Stat(travis_yml) 35 if err == nil { 36 return errors.New(".travis.yml already exists") 37 } 38 f, err := os.Create(travis_yml) 39 if err != nil { 40 return err 41 } 42 defer f.Close() 43 f.WriteString(`language: go 44 go: 45 - tip 46 before_install: 47 - go get github.com/mattn/gom 48 script: 49 - $HOME/gopath/bin/gom install 50 - $HOME/gopath/bin/gom test 51 `) 52 return nil 53 } 54 55 func appendPkg(pkgs []importPackage, pkg string) ([]importPackage, bool) { 56 for _, ele := range pkgs { 57 if ele.path == pkg { 58 return pkgs, false 59 } 60 } 61 return append(pkgs, importPackage{path: pkg}), true 62 } 63 64 func appendPkgs(pkgs, more []importPackage) []importPackage { 65 for _, pkg := range more { 66 pkgs, _ = appendPkg(pkgs, pkg.path) 67 } 68 return pkgs 69 } 70 71 func scanDirectory(path, srcDir string) (ret []importPackage, err error) { 72 pkg, err := build.Import(path, srcDir, build.AllowBinary) 73 if err != nil { 74 return ret, err 75 } 76 for _, imp := range pkg.Imports { 77 if imp == "C" { 78 continue 79 } 80 switch { 81 case pkg.Goroot: 82 // Ignore standard packages 83 case !build.IsLocalImport(imp): 84 // Add the external package 85 ret, _ = appendPkg(ret, imp) 86 fallthrough 87 default: 88 // Does the recursive walk 89 pkgs, err := scanDirectory(imp, pkg.Dir) 90 if err != nil { 91 return ret, err 92 } 93 ret = appendPkgs(ret, pkgs) 94 } 95 } 96 retTests := []importPackage{} 97 isAdd := false 98 for _, imp := range pkg.TestImports { 99 switch { 100 case pkg.Goroot: 101 // Ignore standard packages 102 break 103 case !build.IsLocalImport(imp): 104 // Add the external package 105 retTests, isAdd = appendPkg(retTests, imp) 106 if isAdd { 107 retTests[len(retTests)-1].isTestFile = true 108 } 109 } 110 } 111 ret = append(ret, retTests...) 112 return ret, err 113 } 114 115 func vcsScan(p, target string) (*vcsCmd, string, string) { 116 name := "" 117 for _, elem := range strings.Split(target, "/") { 118 var vcs *vcsCmd 119 p = filepath.Join(p, elem) 120 if name == "" { 121 name = elem 122 } else { 123 name += `/` + elem 124 } 125 if isDir(filepath.Join(p, ".git")) { 126 vcs = git 127 } else if isDir(filepath.Join(p, ".hg")) { 128 vcs = hg 129 } else if isDir(filepath.Join(p, ".bzr")) { 130 vcs = bzr 131 } 132 if vcs != nil { 133 return vcs, name, p 134 } 135 } 136 return nil, "", "" 137 } 138 139 func genGomfile() error { 140 _, err := os.Stat("Gomfile") 141 if err == nil { 142 return errors.New("Gomfile already exists") 143 } 144 dir, err := os.Getwd() 145 if err != nil { 146 return err 147 } 148 all, err := scanDirectory(".", dir) 149 if err != nil { 150 return err 151 } 152 sort.Sort(importPackages(all)) 153 goms := make([]Gom, 0) 154 for _, pkg := range all { 155 for _, p := range filepath.SplitList(os.Getenv("GOPATH")) { 156 var vcs *vcsCmd 157 var n string 158 vcs, n, p = vcsScan(filepath.Join(p, "src"), pkg.path) 159 if vcs != nil { 160 found := false 161 for _, gom := range goms { 162 if gom.name == n { 163 found = true 164 break 165 } 166 } 167 if !found { 168 gom := Gom{name: n, options: make(map[string]interface{})} 169 rev, err := vcs.Revision(p) 170 if err == nil && rev != "" { 171 gom.options["commit"] = rev 172 } 173 if pkg.isTestFile { 174 gom.options["group"] = "test" 175 } 176 goms = append(goms, gom) 177 } 178 } 179 } 180 } 181 182 return writeGomfile("Gomfile", goms) 183 } 184 185 func genGomfileLock() error { 186 allGoms, err := parseGomfile("Gomfile") 187 if err != nil { 188 return err 189 } 190 vendor, err := filepath.Abs(vendorFolder) 191 if err != nil { 192 return err 193 } 194 goms := make([]Gom, 0) 195 for _, gom := range allGoms { 196 if group, ok := gom.options["group"]; ok { 197 if !matchEnv(group) { 198 continue 199 } 200 } 201 if goos, ok := gom.options["goos"]; ok { 202 if !matchOS(goos) { 203 continue 204 } 205 } 206 goms = append(goms, gom) 207 } 208 209 for _, gom := range goms { 210 var vcs *vcsCmd 211 var p string 212 vcs, _, p = vcsScan(vendorSrc(vendor), gom.name) 213 if vcs != nil { 214 rev, err := vcs.Revision(p) 215 if err == nil && rev != "" { 216 gom.options["commit"] = rev 217 } 218 } 219 } 220 err = writeGomfile("Gomfile.lock", goms) 221 if err == nil { 222 fmt.Println("Gomfile.lock is generated") 223 } 224 return err 225 }