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