|  | package cmd | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "go/build" | 
|  | "io" | 
|  | "os" | 
|  | "os/exec" | 
|  | "path" | 
|  | "path/filepath" | 
|  | "strings" | 
|  |  | 
|  | "github.com/Masterminds/cookoo" | 
|  | ) | 
|  |  | 
|  | // Quiet, when set to true, can suppress Info and Debug messages. | 
|  | var Quiet = false | 
|  | var IsDebugging = false | 
|  | var NoColor = false | 
|  |  | 
|  | // BeQuiet supresses Info and Debug messages. | 
|  | func BeQuiet(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { | 
|  | Quiet = p.Get("quiet", false).(bool) | 
|  | IsDebugging = p.Get("debug", false).(bool) | 
|  | return Quiet, nil | 
|  | } | 
|  |  | 
|  | // CheckColor turns off the colored output (and uses plain text output) for | 
|  | // logging depending on the value of the "no-color" flag. | 
|  | func CheckColor(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { | 
|  | NoColor = p.Get("no-color", false).(bool) | 
|  | return NoColor, nil | 
|  | } | 
|  |  | 
|  | // ReadyToGlide fails if the environment is not sufficient for using glide. | 
|  | // | 
|  | // Most importantly, it fails if glide.yaml is not present in the current | 
|  | // working directory. | 
|  | func ReadyToGlide(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { | 
|  | fname := p.Get("filename", "glide.yaml").(string) | 
|  | if _, err := os.Stat(fname); err != nil { | 
|  | cwd, _ := os.Getwd() | 
|  | return false, fmt.Errorf("%s is missing from %s", fname, cwd) | 
|  | } | 
|  | return true, nil | 
|  | } | 
|  |  | 
|  | // VersionGuard ensures that the Go version is correct. | 
|  | func VersionGuard(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { | 
|  | // 6l was removed in 1.5, when vendoring was introduced. | 
|  | cmd := exec.Command("go", "tool", "6l") | 
|  | var out string | 
|  | if _, err := cmd.CombinedOutput(); err == nil { | 
|  | Warn("You must install the Go 1.5 or greater toolchain to work with Glide.\n") | 
|  | } | 
|  | if os.Getenv("GO15VENDOREXPERIMENT") != "1" { | 
|  | Warn("To use Glide, you must set GO15VENDOREXPERIMENT=1\n") | 
|  | } | 
|  |  | 
|  | // Verify the setup isn't for the old version of glide. That is, this is | 
|  | // no longer assuming the _vendor directory as the GOPATH. Inform of | 
|  | // the change. | 
|  | if _, err := os.Stat("_vendor/"); err == nil { | 
|  | Warn(`Your setup appears to be for the previous version of Glide. | 
|  | Previously, vendor packages were stored in _vendor/src/ and | 
|  | _vendor was set as your GOPATH. As of Go 1.5 the go tools | 
|  | recognize the vendor directory as a location for these | 
|  | files. Glide has embraced this. Please remove the _vendor | 
|  | directory or move the _vendor/src/ directory to vendor/.` + "\n") | 
|  | } | 
|  |  | 
|  | return out, nil | 
|  | } | 
|  |  | 
|  | // CowardMode checks that the environment is setup before continuing on. If not | 
|  | // setup and error is returned. | 
|  | func CowardMode(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) { | 
|  | gopath := Gopath() | 
|  | if gopath == "" { | 
|  | return false, fmt.Errorf("No GOPATH is set.\n") | 
|  | } | 
|  |  | 
|  | _, err := os.Stat(path.Join(gopath, "src")) | 
|  | if err != nil { | 
|  | Error("Could not find %s/src.\n", gopath) | 
|  | Info("As of Glide 0.5/Go 1.5, this is required.\n") | 
|  | return false, err | 
|  | } | 
|  |  | 
|  | return true, nil | 
|  | } | 
|  |  | 
|  | // Check if a directory is empty or not. | 
|  | func isDirectoryEmpty(dir string) (bool, error) { | 
|  | f, err := os.Open(dir) | 
|  | if err != nil { | 
|  | return false, err | 
|  | } | 
|  | defer f.Close() | 
|  |  | 
|  | _, err = f.Readdir(1) | 
|  |  | 
|  | if err == io.EOF { | 
|  | return true, nil | 
|  | } | 
|  |  | 
|  | return false, err | 
|  | } | 
|  |  | 
|  | // Gopath gets GOPATH from environment and return the most relevant path. | 
|  | // | 
|  | // A GOPATH can contain a colon-separated list of paths. This retrieves the | 
|  | // GOPATH and returns only the FIRST ("most relevant") path. | 
|  | // | 
|  | // This should be used carefully. If, for example, you are looking for a package, | 
|  | // you may be better off using Gopaths. | 
|  | func Gopath() string { | 
|  | gopaths := Gopaths() | 
|  | if len(gopaths) == 0 { | 
|  | return "" | 
|  | } | 
|  | return gopaths[0] | 
|  | } | 
|  |  | 
|  | // Gopaths retrieves the Gopath as a list when there is more than one path | 
|  | // listed in the Gopath. | 
|  | func Gopaths() []string { | 
|  | p := os.Getenv("GOPATH") | 
|  | p = strings.Trim(p, string(filepath.ListSeparator)) | 
|  | return filepath.SplitList(p) | 
|  | } | 
|  |  | 
|  | // BuildCtxt is a convenience wrapper for not having to import go/build | 
|  | // anywhere else | 
|  | type BuildCtxt struct { | 
|  | build.Context | 
|  | } | 
|  |  | 
|  | // GetBuildContext returns a build context from go/build. When the $GOROOT | 
|  | // variable is not set in the users environment it sets the context's root | 
|  | // path to the path returned by 'go env GOROOT'. | 
|  | func GetBuildContext() (*BuildCtxt, error) { | 
|  | buildContext := &BuildCtxt{build.Default} | 
|  | if goRoot := os.Getenv("GOROOT"); len(goRoot) == 0 { | 
|  | out, err := exec.Command("go", "env", "GOROOT").Output() | 
|  | if goRoot = strings.TrimSpace(string(out)); len(goRoot) == 0 || err != nil { | 
|  | return nil, fmt.Errorf("Please set the $GOROOT environment " + | 
|  | "variable to use this command\n") | 
|  | } | 
|  | buildContext.GOROOT = goRoot | 
|  | } | 
|  | return buildContext, nil | 
|  | } | 
|  |  | 
|  | func fileExist(name string) (bool, error) { | 
|  | _, err := os.Stat(name) | 
|  | if err == nil { | 
|  | return true, nil | 
|  | } | 
|  | if os.IsNotExist(err) { | 
|  | return false, nil | 
|  | } | 
|  | return true, err | 
|  | } | 
|  |  | 
|  | // We copy the directory here rather than jumping out to a shell so we can | 
|  | // support multiple operating systems. | 
|  | func copyDir(source string, dest string) error { | 
|  |  | 
|  | // get properties of source dir | 
|  | si, err := os.Stat(source) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  |  | 
|  | err = os.MkdirAll(dest, si.Mode()) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  |  | 
|  | d, _ := os.Open(source) | 
|  |  | 
|  | objects, err := d.Readdir(-1) | 
|  |  | 
|  | for _, obj := range objects { | 
|  |  | 
|  | sp := filepath.Join(source, "/", obj.Name()) | 
|  |  | 
|  | dp := filepath.Join(dest, "/", obj.Name()) | 
|  |  | 
|  | if obj.IsDir() { | 
|  | err = copyDir(sp, dp) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  | } else { | 
|  | // perform copy | 
|  | err = copyFile(sp, dp) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  | } | 
|  |  | 
|  | } | 
|  | return nil | 
|  | } | 
|  |  | 
|  | func copyFile(source string, dest string) error { | 
|  | ln, err := os.Readlink(source) | 
|  | if err == nil { | 
|  | return os.Symlink(ln, dest) | 
|  | } | 
|  | s, err := os.Open(source) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  |  | 
|  | defer s.Close() | 
|  |  | 
|  | d, err := os.Create(dest) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  |  | 
|  | defer d.Close() | 
|  |  | 
|  | _, err = io.Copy(d, s) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  |  | 
|  | si, err := os.Stat(source) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  | err = os.Chmod(dest, si.Mode()) | 
|  |  | 
|  | return err | 
|  | } |