github.com/influx6/npkg@v0.8.8/ngpkg/pkg.go (about) 1 // Package ngpkg provides a package interfacing API using the go build 2 // libraries to provide high level functions that simplify and running 3 // building processes. 4 // 5 package ngpkg 6 7 import ( 8 "bytes" 9 "fmt" 10 "go/build" 11 "log" 12 "os" 13 "os/exec" 14 "path/filepath" 15 "regexp" 16 "runtime" 17 "strings" 18 ) 19 20 var multispaces = regexp.MustCompile(`\s+`) 21 22 // GoDeps calls go get for specific package 23 func GoDeps(targetdir string) error { 24 defer func() { 25 if err := recover(); err != nil { 26 log.Printf("godeps.Error: %+s", err) 27 } 28 }() 29 30 cmdline := []string{"go", "get"} 31 32 cmdline = append(cmdline, targetdir) 33 34 //setup the executor and use a shard buffer 35 cmd := exec.Command("go", cmdline[1:]...) 36 buf := bytes.NewBuffer([]byte{}) 37 cmd.Stdout = buf 38 cmd.Stderr = buf 39 40 err := cmd.Run() 41 42 if buf.Len() > 0 { 43 return fmt.Errorf("go get failed: %s: %s", buf.String(), err.Error()) 44 } 45 46 return nil 47 } 48 49 // GoRun runs the runs a command 50 func GoRun(cmd string) string { 51 defer func() { 52 if err := recover(); err != nil { 53 log.Printf("gorun.Error: %+s", err) 54 } 55 }() 56 var cmdline []string 57 com := strings.Split(cmd, " ") 58 59 if len(com) < 0 { 60 return "" 61 } 62 63 if len(com) == 1 { 64 cmdline = append(cmdline, com...) 65 } else { 66 cmdline = append(cmdline, com[0]) 67 cmdline = append(cmdline, com[1:]...) 68 } 69 70 //setup the executor and use a shard buffer 71 cmdo := exec.Command(cmdline[0], cmdline[1:]...) 72 buf := bytes.NewBuffer([]byte{}) 73 cmdo.Stdout = buf 74 cmdo.Stderr = buf 75 76 _ = cmdo.Run() 77 78 return buf.String() 79 } 80 81 // GobuildArgs runs the build process against a directory, using the giving 82 // arguments. Returns a non-nil error if it fails. 83 func GobuildArgs(args []string) error { 84 if len(args) <= 0 { 85 return nil 86 } 87 88 defer func() { 89 if err := recover(); err != nil { 90 log.Printf("gobuild.Error: %+s", err) 91 } 92 }() 93 94 cmdline := []string{"go", "build"} 95 96 // target := filepath.Join(dir, name) 97 cmdline = append(cmdline, args...) 98 99 //setup the executor and use a shard buffer 100 cmd := exec.Command("go", cmdline[1:]...) 101 buf := bytes.NewBuffer([]byte{}) 102 103 msg, err := cmd.CombinedOutput() 104 105 if !cmd.ProcessState.Success() { 106 return fmt.Errorf("go.build failed: %s: %s -> Msg: %s", buf.String(), err.Error(), msg) 107 } 108 109 return nil 110 } 111 112 // Gobuild runs the build process against a directory, using a giving name for the 113 // build file. Returns a non-nil error if it fails. 114 func Gobuild(dir, name string, args []string) error { 115 defer func() { 116 if err := recover(); err != nil { 117 log.Printf("gobuild.Error: %+s", err) 118 } 119 }() 120 121 cmdline := []string{"go", "build"} 122 123 if runtime.GOOS == "windows" { 124 name = fmt.Sprintf("%s.exe", name) 125 } 126 127 target := filepath.Join(dir, name) 128 cmdline = append(cmdline, args...) 129 cmdline = append(cmdline, "-o", target) 130 131 //setup the executor and use a shard buffer 132 cmd := exec.Command("go", cmdline[1:]...) 133 buf := bytes.NewBuffer([]byte{}) 134 135 msg, err := cmd.CombinedOutput() 136 137 if !cmd.ProcessState.Success() { 138 return fmt.Errorf("go.build failed: %s: %s -> Msg: %s", buf.String(), err.Error(), msg) 139 } 140 141 return nil 142 } 143 144 // RunCMD runs the a set of commands from a list while skipping any one-length command, panics if it gets an empty lists 145 func RunCMD(cmds []string, done func()) chan bool { 146 if len(cmds) < 0 { 147 panic("commands list cant be empty") 148 } 149 150 var relunch = make(chan bool) 151 152 go func() { 153 defer func() { 154 if err := recover(); err != nil { 155 log.Printf("cmdRun.Error: %+s", err) 156 } 157 }() 158 159 cmdloop: 160 for { 161 select { 162 case do, ok := <-relunch: 163 164 if !ok { 165 break cmdloop 166 } 167 168 if !do { 169 continue 170 } 171 172 for _, cox := range cmds { 173 174 cmd := strings.Split(cox, " ") 175 176 if len(cmd) <= 1 { 177 continue 178 } 179 180 cmdo := exec.Command(cmd[0], cmd[1:]...) 181 cmdo.Stdout = os.Stdout 182 cmdo.Stderr = os.Stderr 183 184 if err := cmdo.Start(); err != nil { 185 fmt.Printf("---> Error executing command: %s -> %s\n", cmd, err) 186 } 187 } 188 189 if done != nil { 190 done() 191 } 192 } 193 } 194 195 }() 196 return relunch 197 } 198 199 // RunGo runs the generated binary file with the arguments expected 200 func RunGo(gofile string, args []string, done, stopped func()) chan bool { 201 var relunch = make(chan bool) 202 203 // if runtime.GOOS == "windows" { 204 gofile = filepath.Clean(gofile) 205 // } 206 207 go func() { 208 209 // var cmdline = fmt.Sprintf("go run %s", gofile) 210 cmdargs := append([]string{"run", gofile}, args...) 211 // cmdline = strings.Joinappend([]string{}, "go run", gofile) 212 213 var proc *os.Process 214 215 for dosig := range relunch { 216 if proc != nil { 217 var err error 218 219 if runtime.GOOS == "windows" { 220 err = proc.Kill() 221 } else { 222 err = proc.Signal(os.Interrupt) 223 } 224 225 if err != nil { 226 fmt.Printf("---> Error in Sending Kill Signal %s\n", err) 227 proc.Kill() 228 } 229 proc.Wait() 230 proc = nil 231 } 232 233 if !dosig { 234 continue 235 } 236 237 cmd := exec.Command("go", cmdargs...) 238 cmd.Stdout = os.Stdout 239 cmd.Stderr = os.Stderr 240 241 if err := cmd.Start(); err != nil { 242 fmt.Printf("---> Error starting process: %s\n", err) 243 } 244 245 proc = cmd.Process 246 if done != nil { 247 done() 248 } 249 } 250 251 if stopped != nil { 252 stopped() 253 } 254 }() 255 return relunch 256 } 257 258 // RunBin runs the generated binary file with the arguments expected 259 func RunBin(binfile string, args []string, done, stopped func()) chan bool { 260 var relunch = make(chan bool) 261 go func() { 262 // binfile := fmt.Sprintf("%s/%s", bindir, bin) 263 // cmdline := append([]string{bin}, args...) 264 var proc *os.Process 265 266 for dosig := range relunch { 267 if proc != nil { 268 var err error 269 270 if runtime.GOOS == "windows" { 271 err = proc.Kill() 272 } else { 273 err = proc.Signal(os.Interrupt) 274 } 275 276 if err != nil { 277 fmt.Printf("---> Error in Sending Kill Signal: %s\n", err) 278 proc.Kill() 279 } 280 proc.Wait() 281 proc = nil 282 } 283 284 if !dosig { 285 continue 286 } 287 288 cmd := exec.Command(binfile, args...) 289 cmd.Stdout = os.Stdout 290 cmd.Stderr = os.Stderr 291 292 if err := cmd.Start(); err != nil { 293 fmt.Printf("---> Error starting process: %s -> %s\n", binfile, err) 294 } 295 296 proc = cmd.Process 297 if done != nil { 298 done() 299 } 300 } 301 302 if stopped != nil { 303 stopped() 304 } 305 }() 306 return relunch 307 } 308 309 //SanitizeDuplicates cleans out all duplicates 310 func SanitizeDuplicates(b []string) []string { 311 sz := len(b) - 1 312 for i := 0; i < sz; i++ { 313 for j := i + 1; j <= sz; j++ { 314 if (b)[i] == ((b)[j]) { 315 (b)[j] = (b)[sz] 316 (b) = (b)[0:sz] 317 sz-- 318 j-- 319 } 320 } 321 } 322 return b 323 } 324 325 // GetPackageDir returns the directory of a package path from the go src dir. 326 func GetPackageDir(pkgname string) (string, error) { 327 pkg, err := build.Import(pkgname, "", 0) 328 329 if err != nil { 330 return "", err 331 } 332 333 return pkg.Dir, nil 334 } 335 336 // GetPackageLists retrieves a packages directory and those of its dependencies 337 func GetPackageLists(pkgname string) ([]string, error) { 338 var paths []string 339 var err error 340 341 if paths, err = getPackageLists(pkgname, paths); err != nil { 342 return nil, err 343 } 344 345 return SanitizeDuplicates(paths), nil 346 } 347 348 // GetAllPackageLists retrieves a set of packages directory and those of its dependencies 349 func GetAllPackageLists(pkgnames []string) ([]string, error) { 350 var packages []string 351 var err error 352 353 for _, pkg := range pkgnames { 354 if packages, err = getPackageLists(pkg, packages); err != nil { 355 return nil, err 356 } 357 } 358 359 // log.Printf("Packages: %s", packages) 360 return SanitizeDuplicates(packages), nil 361 } 362 363 // getPackageLists returns the lists of internal package imports used within 364 // a giving package. 365 func getPackageLists(pkgname string, paths []string) ([]string, error) { 366 pkg, err := build.Import(pkgname, "", 0) 367 368 if err != nil { 369 return nil, err 370 } 371 372 if pkg.Goroot { 373 return paths, nil 374 } 375 376 paths = append(paths, pkg.Dir) 377 378 for _, imp := range pkg.Imports { 379 if p, err := getPackageLists(imp, paths); err == nil { 380 paths = p 381 } else { 382 return nil, err 383 } 384 } 385 386 return paths, nil 387 }