github.com/n0needt0/glide@v0.0.0-20160325160517-844a77136d85/path/path.go (about) 1 // Package path contains path and environment utilities for Glide. 2 // 3 // This includes tools to find and manipulate Go path variables, as well as 4 // tools for copying from one path to another. 5 package path 6 7 import ( 8 "fmt" 9 "io" 10 "os" 11 "path/filepath" 12 "strings" 13 ) 14 15 // DefaultGlideFile is the default name for the glide.yaml file. 16 const DefaultGlideFile = "glide.yaml" 17 18 // VendorDir is the name of the directory that holds vendored dependencies. 19 // 20 // As of Go 1.5, this is always vendor. 21 var VendorDir = "vendor" 22 23 // HomeDir is the home directory for Glide. 24 // 25 // HomeDir is where cache files and other configuration data are stored. 26 var HomeDir = "$HOME/.glide" 27 28 // GlideFile is the name of the Glide file. 29 // 30 // Setting this is not concurrency safe. For consistency, it should really 31 // only be set once, at startup, or not at all. 32 var GlideFile = DefaultGlideFile 33 34 // LockFile is the default name for the lock file. 35 const LockFile = "glide.lock" 36 37 // Home returns the Glide home directory ($GLIDE_HOME or ~/.glide, typically). 38 // 39 // This normalizes to an absolute path, and passes through os.ExpandEnv. 40 func Home() string { 41 h := os.ExpandEnv(HomeDir) 42 var err error 43 if h, err = filepath.Abs(HomeDir); err != nil { 44 return HomeDir 45 } 46 return h 47 } 48 49 // Vendor calculates the path to the vendor directory. 50 // 51 // Based on working directory, VendorDir and GlideFile, this attempts to 52 // guess the location of the vendor directory. 53 func Vendor() (string, error) { 54 cwd, err := os.Getwd() 55 if err != nil { 56 return "", err 57 } 58 59 // Find the directory that contains glide.yaml 60 yamldir, err := GlideWD(cwd) 61 if err != nil { 62 return cwd, err 63 } 64 65 gopath := filepath.Join(yamldir, VendorDir) 66 67 return gopath, nil 68 } 69 70 // Glide gets the path to the closest glide file. 71 func Glide() (string, error) { 72 cwd, err := os.Getwd() 73 if err != nil { 74 return "", err 75 } 76 77 // Find the directory that contains glide.yaml 78 yamldir, err := GlideWD(cwd) 79 if err != nil { 80 return cwd, err 81 } 82 83 gf := filepath.Join(yamldir, GlideFile) 84 return gf, nil 85 } 86 87 // GlideWD finds the working directory of the glide.yaml file, starting at dir. 88 // 89 // If the glide file is not found in the current directory, it recurses up 90 // a directory. 91 func GlideWD(dir string) (string, error) { 92 fullpath := filepath.Join(dir, GlideFile) 93 94 if _, err := os.Stat(fullpath); err == nil { 95 return dir, nil 96 } 97 98 base := filepath.Dir(dir) 99 if base == dir { 100 return "", fmt.Errorf("Cannot resolve parent of %s", base) 101 } 102 103 return GlideWD(base) 104 } 105 106 // Gopath gets GOPATH from environment and return the most relevant path. 107 // 108 // A GOPATH can contain a colon-separated list of paths. This retrieves the 109 // GOPATH and returns only the FIRST ("most relevant") path. 110 // 111 // This should be used carefully. If, for example, you are looking for a package, 112 // you may be better off using Gopaths. 113 func Gopath() string { 114 gopaths := Gopaths() 115 if len(gopaths) == 0 { 116 return "" 117 } 118 return gopaths[0] 119 } 120 121 // Gopaths retrieves the Gopath as a list when there is more than one path 122 // listed in the Gopath. 123 func Gopaths() []string { 124 p := os.Getenv("GOPATH") 125 p = strings.Trim(p, string(filepath.ListSeparator)) 126 return filepath.SplitList(p) 127 } 128 129 // Basepath returns the current working directory. 130 // 131 // If there is an error getting the working directory, this returns ".", which 132 // should function in cases where the directory is unlinked... Then again, 133 // maybe not. 134 func Basepath() string { 135 base, err := os.Getwd() 136 if err != nil { 137 return "." 138 } 139 return base 140 } 141 142 // StripBasepath removes the base directory from a passed in path. 143 func StripBasepath(p string) string { 144 bp := Basepath() 145 return strings.TrimPrefix(p, bp+string(os.PathSeparator)) 146 } 147 148 // IsLink returns true if the given FileInfo references a link. 149 func IsLink(fi os.FileInfo) bool { 150 return fi.Mode()&os.ModeSymlink == os.ModeSymlink 151 } 152 153 // HasLock returns true if this can stat a lockfile at the givin location. 154 func HasLock(basepath string) bool { 155 _, err := os.Stat(filepath.Join(basepath, LockFile)) 156 return err == nil 157 } 158 159 // IsDirectoryEmpty checks if a directory is empty. 160 func IsDirectoryEmpty(dir string) (bool, error) { 161 f, err := os.Open(dir) 162 if err != nil { 163 return false, err 164 } 165 defer f.Close() 166 167 _, err = f.Readdir(1) 168 169 if err == io.EOF { 170 return true, nil 171 } 172 173 return false, err 174 } 175 176 // CopyDir copies an entire source directory to the dest directory. 177 // 178 // This is akin to `cp -a src/* dest/` 179 // 180 // We copy the directory here rather than jumping out to a shell so we can 181 // support multiple operating systems. 182 func CopyDir(source string, dest string) error { 183 184 // get properties of source dir 185 si, err := os.Stat(source) 186 if err != nil { 187 return err 188 } 189 190 err = os.MkdirAll(dest, si.Mode()) 191 if err != nil { 192 return err 193 } 194 195 d, _ := os.Open(source) 196 197 objects, err := d.Readdir(-1) 198 199 for _, obj := range objects { 200 201 sp := filepath.Join(source, "/", obj.Name()) 202 203 dp := filepath.Join(dest, "/", obj.Name()) 204 205 if obj.IsDir() { 206 err = CopyDir(sp, dp) 207 if err != nil { 208 return err 209 } 210 } else { 211 // perform copy 212 err = CopyFile(sp, dp) 213 if err != nil { 214 return err 215 } 216 } 217 218 } 219 return nil 220 } 221 222 // CopyFile copies a source file to a destination. 223 // 224 // It follows symbolic links and retains modes. 225 func CopyFile(source string, dest string) error { 226 ln, err := os.Readlink(source) 227 if err == nil { 228 return os.Symlink(ln, dest) 229 } 230 s, err := os.Open(source) 231 if err != nil { 232 return err 233 } 234 235 defer s.Close() 236 237 d, err := os.Create(dest) 238 if err != nil { 239 return err 240 } 241 242 defer d.Close() 243 244 _, err = io.Copy(d, s) 245 if err != nil { 246 return err 247 } 248 249 si, err := os.Stat(source) 250 if err != nil { 251 return err 252 } 253 err = os.Chmod(dest, si.Mode()) 254 255 return err 256 }