gopkg.in/tools/godep.v78@v78.0.0-20170123184621-47355da3e1a3/go.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 ) 11 12 var cmdGo = &Command{ 13 Name: "go", 14 Args: "command [arguments]", 15 Short: "run the go tool with saved dependencies", 16 Long: ` 17 Go runs the go tool with a modified GOPATH giving access to 18 dependencies saved in Godeps. 19 20 Any go tool command can run this way, but "godep go get" 21 is unnecessary and has been disabled. Instead, use 22 "godep go install". 23 `, 24 Run: runGo, 25 OnlyInGOPATH: true, 26 } 27 28 // Find the godep GOPATH for this file tree and run the go tool. 29 func runGo(cmd *Command, args []string) { 30 gopath := prepareGopath() 31 if s := os.Getenv("GOPATH"); s != "" { 32 gopath += string(os.PathListSeparator) + os.Getenv("GOPATH") 33 } 34 if len(args) > 0 && args[0] == "get" { 35 log.Printf("invalid subcommand: %q", "go get") 36 fmt.Fprintln(os.Stderr, "Use 'godep go install' instead.") 37 fmt.Fprintln(os.Stderr, "Run 'godep help go' for usage.") 38 os.Exit(2) 39 } 40 c := exec.Command("go", args...) 41 c.Env = append(envNoGopath(), "GOPATH="+gopath) 42 c.Stdin = os.Stdin 43 c.Stdout = os.Stdout 44 c.Stderr = os.Stderr 45 err := c.Run() 46 if err != nil { 47 log.Fatalln("go", err) 48 } 49 } 50 51 // prepareGopath reads dependency information from the filesystem 52 // entry name, fetches any necessary code, and returns a gopath 53 // causing the specified dependencies to be used. 54 func prepareGopath() (gopath string) { 55 dir, isDir := findGodeps() 56 if dir == "" { 57 log.Fatalln("No Godeps found (or in any parent directory)") 58 } 59 if !isDir { 60 log.Fatalln(strings.TrimSpace(needSource)) 61 } 62 return filepath.Join(dir, "Godeps", "_workspace") 63 } 64 65 // findGodeps looks for a directory entry "Godeps" in the 66 // current directory or any parent, and returns the containing 67 // directory and whether the entry itself is a directory. 68 // If Godeps can't be found, findGodeps returns "". 69 // For any other error, it exits the program. 70 func findGodeps() (dir string, isDir bool) { 71 wd, err := os.Getwd() 72 if err != nil { 73 log.Fatalln(err) 74 } 75 return findInParents(wd, "Godeps") 76 } 77 78 // isRoot returns true iff a path is a root. 79 // On Unix: "/". 80 // On Windows: "C:\", "D:\", ... 81 func isRoot(p string) bool { 82 p = filepath.Clean(p) 83 volume := filepath.VolumeName(p) 84 85 p = strings.TrimPrefix(p, volume) 86 p = filepath.ToSlash(p) 87 88 return p == "/" 89 } 90 91 // findInParents returns the path to the directory containing name 92 // in dir or any ancestor, and whether name itself is a directory. 93 // If name cannot be found, findInParents returns the empty string. 94 func findInParents(dir, name string) (container string, isDir bool) { 95 for { 96 fi, err := os.Stat(filepath.Join(dir, name)) 97 if os.IsNotExist(err) && isRoot(dir) { 98 return "", false 99 } 100 if os.IsNotExist(err) { 101 dir = filepath.Dir(dir) 102 continue 103 } 104 if err != nil { 105 log.Fatalln(err) 106 } 107 return dir, fi.IsDir() 108 } 109 } 110 111 func envNoGopath() (a []string) { 112 for _, s := range os.Environ() { 113 if !strings.HasPrefix(s, "GOPATH=") { 114 a = append(a, s) 115 } 116 } 117 return a 118 } 119 120 const needSource = ` 121 outdated Godeps missing source code 122 123 This dependency list was created with an old version of godep. 124 125 To work around this, you have two options: 126 1. Run 'godep restore', and try again. 127 2. Ask the maintainer to switch to a newer version of godep, 128 then try again with the updated package. 129 `