github.com/Xenoex/gopm@v0.6.5/cmd/gopath.go (about) 1 // Copyright 2013-2014 gopm authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package cmd 16 17 import ( 18 "errors" 19 "go/build" 20 "os" 21 "os/exec" 22 "path/filepath" 23 "runtime" 24 "strings" 25 26 "github.com/Unknwon/com" 27 "github.com/codegangsta/cli" 28 29 "github.com/gpmgo/gopm/doc" 30 "github.com/gpmgo/gopm/log" 31 ) 32 33 var isWindowsXP = false 34 35 func getGopmPkgs(dirPath string, isTest bool) (pkgs map[string]*doc.Pkg, err error) { 36 absPath, err := filepath.Abs(dirPath) 37 if err != nil { 38 log.Error("", "Fail to get absolute path of work directory:") 39 log.Fatal("", "\t"+err.Error()) 40 } 41 42 var builds map[string]string 43 44 if com.IsFile(absPath + "/" + doc.GOPM_FILE_NAME) { 45 gf := doc.NewGopmfile(absPath) 46 47 if builds, err = gf.GetSection("deps"); err != nil { 48 builds = nil 49 } 50 } 51 52 imports := doc.GetAllImports([]string{dirPath}, ".", false, false) 53 pkgs = make(map[string]*doc.Pkg) 54 for _, name := range imports { 55 if name == "C" { 56 continue 57 } 58 if !doc.IsGoRepoPath(name) { 59 if builds != nil { 60 if info, ok := builds[name]; ok { 61 // Check version. there should chek 62 // local first because d:\ contains : 63 if com.IsDir(info) { 64 pkgs[name] = &doc.Pkg{ 65 ImportPath: name, 66 Type: doc.LOCAL, 67 Value: info, 68 } 69 continue 70 } else if i := strings.Index(info, ":"); i > -1 { 71 pkgs[name] = &doc.Pkg{ 72 ImportPath: name, 73 Type: info[:i], 74 Value: info[i+1:], 75 } 76 continue 77 } 78 } 79 } 80 pkgs[name] = doc.NewDefaultPkg(name) 81 } 82 } 83 return pkgs, nil 84 } 85 86 func pkgInCache(name string, cachePkgs map[string]*doc.Pkg) bool { 87 _, ok := cachePkgs[name] 88 return ok 89 } 90 91 func autoLink(oldPath, newPath string) error { 92 newPPath, _ := filepath.Split(newPath) 93 os.MkdirAll(newPPath, os.ModePerm) 94 return makeLink(oldPath, newPath) 95 } 96 97 func getChildPkgs(ctx *cli.Context, cpath string, ppkg *doc.Pkg, cachePkgs map[string]*doc.Pkg, isTest bool) error { 98 log.Trace("Current Path: 1 %s", cpath) 99 pkgs, err := getGopmPkgs(cpath, isTest) 100 if err != nil { 101 return errors.New("Fail to get gopmfile deps: " + err.Error()) 102 } 103 for name, pkg := range pkgs { 104 pkg.RootPath = doc.GetProjectPath(pkg.ImportPath) 105 if !pkgInCache(pkg.RootPath, cachePkgs) { 106 var newPath string 107 if !build.IsLocalImport(name) && pkg.Type != doc.LOCAL { 108 suf := versionSuffix(pkg.Value) 109 pkgPath := strings.Replace( 110 pkg.ImportPath, pkg.RootPath, pkg.RootPath+suf, 1) 111 newPath = filepath.Join(installRepoPath, pkgPath) 112 if len(suf) == 0 && !ctx.Bool("remote") && 113 com.IsDir(filepath.Join(installGopath, pkgPath)) { 114 newPath = filepath.Join(installGopath, pkgPath) 115 } 116 if pkgName != "" && strings.HasPrefix(pkg.ImportPath, pkgName) { 117 newPath = filepath.Join(curPath, strings.TrimPrefix(pkg.ImportPath, pkgName)) 118 } else { 119 if !com.IsExist(newPath) || ctx.Bool("update") { 120 node := doc.NewNode(pkg.ImportPath, pkg.ImportPath, 121 pkg.Type, pkg.Value, true) 122 nodes := []*doc.Node{node} 123 downloadPackages(ctx, nodes) 124 // TODO: Should handler download failed 125 } 126 } 127 } else { 128 if pkg.Type == doc.LOCAL { 129 newPath, err = filepath.Abs(pkg.Value) 130 } else { 131 newPath, err = filepath.Abs(name) 132 } 133 if err != nil { 134 return err 135 } 136 } 137 cachePkgs[pkg.RootPath] = pkg 138 err = getChildPkgs(ctx, newPath, pkg, cachePkgs, false) 139 if err != nil { 140 return err 141 } 142 } 143 } 144 return nil 145 } 146 147 var pkgName string 148 var curPath string 149 var newCurPath string 150 var newGoPath string 151 var oldGoPath string 152 153 func execCmd(gopath, curPath string, args ...string) error { 154 cwd, err := os.Getwd() 155 if err != nil { 156 log.Error("", "Fail to get work directory:") 157 log.Fatal("", "\t"+err.Error()) 158 } 159 160 log.Log("Changing work directory to %s", curPath) 161 err = os.Chdir(curPath) 162 if err != nil { 163 log.Error("", "Fail to change work directory:") 164 log.Fatal("", "\t"+err.Error()) 165 } 166 defer func() { 167 log.Log("Changing work directory back to %s", cwd) 168 os.Chdir(cwd) 169 }() 170 171 err = os.Chdir(curPath) 172 if err != nil { 173 log.Error("", "Fail to change work directory:") 174 log.Fatal("", "\t"+err.Error()) 175 } 176 177 oldGoPath = os.Getenv("GOPATH") 178 log.Log("Setting GOPATH to %s", gopath) 179 180 sep := ":" 181 if runtime.GOOS == "windows" { 182 sep = ";" 183 } 184 err = os.Setenv("GOPATH", gopath+sep+oldGoPath) 185 if err != nil { 186 log.Error("", "Fail to setting GOPATH:") 187 log.Fatal("", "\t"+err.Error()) 188 } 189 defer func() { 190 log.Log("Setting GOPATH back to %s", oldGoPath) 191 os.Setenv("GOPATH", oldGoPath) 192 }() 193 194 cmd := exec.Command(args[0], args[1:]...) 195 cmd.Stdout = os.Stdout 196 cmd.Stderr = os.Stderr 197 198 log.Log("===== application outputs start =====\n") 199 200 err = cmd.Run() 201 202 log.Log("====== application outputs end ======") 203 return err 204 } 205 206 func genNewGoPath(ctx *cli.Context, isTest bool) { 207 var err error 208 curPath, err = os.Getwd() 209 if err != nil { 210 log.Error("", "Fail to get work directory:") 211 log.Fatal("", "\t"+err.Error()) 212 } 213 log.Trace("Current Path: 0 %s", curPath) 214 215 installRepoPath = doc.HomeDir + "/repos" 216 217 if com.IsFile(curPath + "/" + doc.GOPM_FILE_NAME) { 218 log.Trace("Loading gopmfile...") 219 gf := doc.NewGopmfile(curPath) 220 221 var err error 222 pkgName, err = gf.GetValue("target", "path") 223 if err == nil { 224 log.Log("Target name: %s", pkgName) 225 } 226 } 227 228 if len(pkgName) == 0 { 229 _, pkgName = filepath.Split(curPath) 230 } 231 232 cachePkgs := make(map[string]*doc.Pkg) 233 if err = getChildPkgs(ctx, curPath, nil, cachePkgs, isTest); err != nil { 234 log.Error("", "Fail to get child pakcages:") 235 log.Fatal("", "\t"+err.Error()) 236 } 237 238 newGoPath = filepath.Join(curPath, doc.VENDOR) 239 newGoPathSrc := filepath.Join(newGoPath, "src") 240 os.RemoveAll(newGoPathSrc) 241 os.MkdirAll(newGoPathSrc, os.ModePerm) 242 243 for name, pkg := range cachePkgs { 244 suf := versionSuffix(pkg.Value) 245 246 var oldPath string 247 if pkg.Type == doc.LOCAL { 248 oldPath, _ = filepath.Abs(pkg.Value) 249 } else { 250 oldPath = filepath.Join(installRepoPath, name) + suf 251 } 252 253 newPath := filepath.Join(newGoPathSrc, name) 254 paths := strings.Split(name, "/") 255 var isExistP, isCurChild bool 256 if name == pkgName { 257 continue 258 } 259 260 for i := 0; i < len(paths)-1; i++ { 261 pName := strings.Join(paths[:len(paths)-1-i], "/") 262 if _, ok := cachePkgs[pName]; ok { 263 isExistP = true 264 break 265 } 266 if pkgName == pName { 267 isCurChild = true 268 break 269 } 270 } 271 if isCurChild { 272 continue 273 } 274 275 if !isExistP && (len(pkg.Value) > 0 || ctx.Bool("remote") || 276 !com.IsDir(filepath.Join(installGopath, pkg.ImportPath))) { 277 log.Log("Linking %s", name+suf) 278 err = autoLink(oldPath, newPath) 279 if err != nil { 280 log.Error("", "Fail to make link:") 281 log.Fatal("", "\t"+err.Error()) 282 } 283 } 284 } 285 286 newCurPath = filepath.Join(newGoPathSrc, pkgName) 287 log.Log("Linking %s", pkgName) 288 err = autoLink(curPath, newCurPath) 289 if err != nil { 290 log.Error("", "Fail to make link:") 291 log.Fatal("", "\t"+err.Error()) 292 } 293 }