mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
7.1 KiB
292 lines
7.1 KiB
// Copyright 2013-2014 gopm authors. |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may |
|
// not use this file except in compliance with the License. You may obtain |
|
// a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
|
// License for the specific language governing permissions and limitations |
|
// under the License. |
|
|
|
package cmd |
|
|
|
import ( |
|
"errors" |
|
"go/build" |
|
"os" |
|
"os/exec" |
|
"path/filepath" |
|
"runtime" |
|
"strings" |
|
|
|
"github.com/Unknwon/com" |
|
"github.com/codegangsta/cli" |
|
|
|
"github.com/gpmgo/gopm/doc" |
|
"github.com/gpmgo/gopm/log" |
|
) |
|
|
|
var isWindowsXP = false |
|
|
|
func getGopmPkgs(dirPath string, isTest bool) (pkgs map[string]*doc.Pkg, err error) { |
|
absPath, err := filepath.Abs(dirPath) |
|
if err != nil { |
|
log.Error("", "Fail to get absolute path of work directory:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
|
|
var builds map[string]string |
|
|
|
if com.IsFile(absPath + "/" + doc.GOPM_FILE_NAME) { |
|
gf := doc.NewGopmfile(absPath) |
|
|
|
if builds, err = gf.GetSection("deps"); err != nil { |
|
builds = nil |
|
} |
|
} |
|
|
|
imports := doc.GetAllImports([]string{dirPath}, ".", false, false) |
|
pkgs = make(map[string]*doc.Pkg) |
|
for _, name := range imports { |
|
if name == "C" { |
|
continue |
|
} |
|
if !doc.IsGoRepoPath(name) { |
|
if builds != nil { |
|
if info, ok := builds[name]; ok { |
|
// Check version. there should chek |
|
// local first because d:\ contains : |
|
if com.IsDir(info) { |
|
pkgs[name] = &doc.Pkg{ |
|
ImportPath: name, |
|
Type: doc.LOCAL, |
|
Value: info, |
|
} |
|
continue |
|
} else if i := strings.Index(info, ":"); i > -1 { |
|
pkgs[name] = &doc.Pkg{ |
|
ImportPath: name, |
|
Type: info[:i], |
|
Value: info[i+1:], |
|
} |
|
continue |
|
} |
|
} |
|
} |
|
pkgs[name] = doc.NewDefaultPkg(name) |
|
} |
|
} |
|
return pkgs, nil |
|
} |
|
|
|
func pkgInCache(name string, cachePkgs map[string]*doc.Pkg) bool { |
|
_, ok := cachePkgs[name] |
|
return ok |
|
} |
|
|
|
func autoLink(oldPath, newPath string) error { |
|
newPPath, _ := filepath.Split(newPath) |
|
os.MkdirAll(newPPath, os.ModePerm) |
|
return makeLink(oldPath, newPath) |
|
} |
|
|
|
func getChildPkgs(ctx *cli.Context, cpath string, ppkg *doc.Pkg, cachePkgs map[string]*doc.Pkg, isTest bool) error { |
|
pkgs, err := getGopmPkgs(cpath, isTest) |
|
if err != nil { |
|
return errors.New("Fail to get gopmfile deps: " + err.Error()) |
|
} |
|
for name, pkg := range pkgs { |
|
pkg.RootPath = doc.GetProjectPath(pkg.ImportPath) |
|
if !pkgInCache(pkg.RootPath, cachePkgs) { |
|
var newPath string |
|
if !build.IsLocalImport(name) && pkg.Type != doc.LOCAL { |
|
suf := versionSuffix(pkg.Value) |
|
pkgPath := strings.Replace( |
|
pkg.ImportPath, pkg.RootPath, pkg.RootPath+suf, 1) |
|
newPath = filepath.Join(installRepoPath, pkgPath) |
|
if len(suf) == 0 && !ctx.Bool("remote") && |
|
com.IsDir(filepath.Join(installGopath, pkgPath)) { |
|
newPath = filepath.Join(installGopath, pkgPath) |
|
} |
|
if pkgName != "" && strings.HasPrefix(pkg.ImportPath, pkgName) { |
|
newPath = filepath.Join(curPath, strings.TrimPrefix(pkg.ImportPath, pkgName)) |
|
} else { |
|
if !com.IsExist(newPath) || ctx.Bool("update") { |
|
node := doc.NewNode(pkg.ImportPath, pkg.ImportPath, |
|
pkg.Type, pkg.Value, true) |
|
nodes := []*doc.Node{node} |
|
downloadPackages(ctx, nodes) |
|
// TODO: Should handler download failed |
|
} |
|
} |
|
} else { |
|
if pkg.Type == doc.LOCAL { |
|
newPath, err = filepath.Abs(pkg.Value) |
|
} else { |
|
newPath, err = filepath.Abs(name) |
|
} |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
cachePkgs[pkg.RootPath] = pkg |
|
err = getChildPkgs(ctx, newPath, pkg, cachePkgs, false) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
} |
|
return nil |
|
} |
|
|
|
var pkgName string |
|
var curPath string |
|
var newCurPath string |
|
var newGoPath string |
|
var oldGoPath string |
|
|
|
func execCmd(gopath, curPath string, args ...string) error { |
|
cwd, err := os.Getwd() |
|
if err != nil { |
|
log.Error("", "Fail to get work directory:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
|
|
log.Log("Changing work directory to %s", curPath) |
|
err = os.Chdir(curPath) |
|
if err != nil { |
|
log.Error("", "Fail to change work directory:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
defer func() { |
|
log.Log("Changing work directory back to %s", cwd) |
|
os.Chdir(cwd) |
|
}() |
|
|
|
err = os.Chdir(curPath) |
|
if err != nil { |
|
log.Error("", "Fail to change work directory:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
|
|
oldGoPath = os.Getenv("GOPATH") |
|
log.Log("Setting GOPATH to %s", gopath) |
|
|
|
sep := ":" |
|
if runtime.GOOS == "windows" { |
|
sep = ";" |
|
} |
|
err = os.Setenv("GOPATH", gopath+sep+oldGoPath) |
|
if err != nil { |
|
log.Error("", "Fail to setting GOPATH:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
defer func() { |
|
log.Log("Setting GOPATH back to %s", oldGoPath) |
|
os.Setenv("GOPATH", oldGoPath) |
|
}() |
|
|
|
cmd := exec.Command(args[0], args[1:]...) |
|
cmd.Stdout = os.Stdout |
|
cmd.Stderr = os.Stderr |
|
|
|
log.Log("===== application outputs start =====\n") |
|
|
|
err = cmd.Run() |
|
|
|
log.Log("====== application outputs end ======") |
|
return err |
|
} |
|
|
|
func genNewGoPath(ctx *cli.Context, isTest bool) { |
|
var err error |
|
curPath, err = os.Getwd() |
|
if err != nil { |
|
log.Error("", "Fail to get work directory:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
|
|
installRepoPath = doc.HomeDir + "/repos" |
|
|
|
if com.IsFile(curPath + "/" + doc.GOPM_FILE_NAME) { |
|
log.Trace("Loading gopmfile...") |
|
gf := doc.NewGopmfile(curPath) |
|
|
|
var err error |
|
pkgName, err = gf.GetValue("target", "path") |
|
if err == nil { |
|
log.Log("Target name: %s", pkgName) |
|
} |
|
} |
|
|
|
if len(pkgName) == 0 { |
|
_, pkgName = filepath.Split(curPath) |
|
} |
|
|
|
cachePkgs := make(map[string]*doc.Pkg) |
|
err = getChildPkgs(ctx, curPath, nil, cachePkgs, isTest) |
|
if err != nil { |
|
log.Error("", "Fail to get child pakcages:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
|
|
newGoPath = filepath.Join(curPath, doc.VENDOR) |
|
newGoPathSrc := filepath.Join(newGoPath, "src") |
|
os.RemoveAll(newGoPathSrc) |
|
os.MkdirAll(newGoPathSrc, os.ModePerm) |
|
|
|
for name, pkg := range cachePkgs { |
|
suf := versionSuffix(pkg.Value) |
|
|
|
var oldPath string |
|
if pkg.Type == doc.LOCAL { |
|
oldPath, _ = filepath.Abs(pkg.Value) |
|
} else { |
|
oldPath = filepath.Join(installRepoPath, name) + suf |
|
} |
|
|
|
newPath := filepath.Join(newGoPathSrc, name) |
|
paths := strings.Split(name, "/") |
|
var isExistP, isCurChild bool |
|
if name == pkgName { |
|
continue |
|
} |
|
|
|
for i := 0; i < len(paths)-1; i++ { |
|
pName := strings.Join(paths[:len(paths)-1-i], "/") |
|
if _, ok := cachePkgs[pName]; ok { |
|
isExistP = true |
|
break |
|
} |
|
if pkgName == pName { |
|
isCurChild = true |
|
break |
|
} |
|
} |
|
if isCurChild { |
|
continue |
|
} |
|
|
|
if !isExistP && (len(pkg.Value) > 0 || ctx.Bool("remote") || |
|
!com.IsDir(filepath.Join(installGopath, pkg.ImportPath))) { |
|
log.Log("Linking %s", name+suf) |
|
err = autoLink(oldPath, newPath) |
|
if err != nil { |
|
log.Error("", "Fail to make link:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
} |
|
} |
|
|
|
newCurPath = filepath.Join(newGoPathSrc, pkgName) |
|
log.Log("Linking %s", pkgName) |
|
err = autoLink(curPath, newCurPath) |
|
if err != nil { |
|
log.Error("", "Fail to make link:") |
|
log.Fatal("", "\t"+err.Error()) |
|
} |
|
}
|
|
|