github.com/anthonymayer/glide@v0.0.0-20160224162501-bff8b50d232e/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 // IsLink returns true if the given FileInfo references a link. 143 func IsLink(fi os.FileInfo) bool { 144 return fi.Mode()&os.ModeSymlink == os.ModeSymlink 145 } 146 147 // HasLock returns true if this can stat a lockfile at the givin location. 148 func HasLock(basepath string) bool { 149 _, err := os.Stat(filepath.Join(basepath, LockFile)) 150 return err == nil 151 } 152 153 // IsDirectoryEmpty checks if a directory is empty. 154 func IsDirectoryEmpty(dir string) (bool, error) { 155 f, err := os.Open(dir) 156 if err != nil { 157 return false, err 158 } 159 defer f.Close() 160 161 _, err = f.Readdir(1) 162 163 if err == io.EOF { 164 return true, nil 165 } 166 167 return false, err 168 } 169 170 // CopyDir copies an entire source directory to the dest directory. 171 // 172 // This is akin to `cp -a src/* dest/` 173 // 174 // We copy the directory here rather than jumping out to a shell so we can 175 // support multiple operating systems. 176 func CopyDir(source string, dest string) error { 177 178 // get properties of source dir 179 si, err := os.Stat(source) 180 if err != nil { 181 return err 182 } 183 184 err = os.MkdirAll(dest, si.Mode()) 185 if err != nil { 186 return err 187 } 188 189 d, _ := os.Open(source) 190 191 objects, err := d.Readdir(-1) 192 193 for _, obj := range objects { 194 195 sp := filepath.Join(source, "/", obj.Name()) 196 197 dp := filepath.Join(dest, "/", obj.Name()) 198 199 if obj.IsDir() { 200 err = CopyDir(sp, dp) 201 if err != nil { 202 return err 203 } 204 } else { 205 // perform copy 206 err = CopyFile(sp, dp) 207 if err != nil { 208 return err 209 } 210 } 211 212 } 213 return nil 214 } 215 216 // CopyFile copies a source file to a destination. 217 // 218 // It follows symbolic links and retains modes. 219 func CopyFile(source string, dest string) error { 220 ln, err := os.Readlink(source) 221 if err == nil { 222 return os.Symlink(ln, dest) 223 } 224 s, err := os.Open(source) 225 if err != nil { 226 return err 227 } 228 229 defer s.Close() 230 231 d, err := os.Create(dest) 232 if err != nil { 233 return err 234 } 235 236 defer d.Close() 237 238 _, err = io.Copy(d, s) 239 if err != nil { 240 return err 241 } 242 243 si, err := os.Stat(source) 244 if err != nil { 245 return err 246 } 247 err = os.Chmod(dest, si.Mode()) 248 249 return err 250 }