func runRun(ctx *cli.Context) { setup(ctx) // Get GOPATH. installGopath = com.GetGOPATHs()[0] if com.IsDir(installGopath) { isHasGopath = true log.Log("Indicated GOPATH: %s", installGopath) installGopath += "/src" } genNewGoPath(ctx, false) log.Trace("Running...") cmdArgs := []string{"go", "run"} cmdArgs = append(cmdArgs, ctx.Args()...) err := execCmd(newGoPath, newCurPath, cmdArgs...) if err != nil { log.Error("run", "Fail to run program:") log.Fatal("", "\t"+err.Error()) } log.Success("SUCC", "run", "Command executed successfully!") }
func getByPath(ctx *cli.Context) { nodes := make([]*doc.Node, 0, len(ctx.Args())) for _, info := range ctx.Args() { pkgPath := info node := doc.NewNode(pkgPath, pkgPath, doc.BRANCH, "", true) if i := strings.Index(info, "@"); i > -1 { pkgPath = info[:i] tp, ver := validPath(info[i+1:]) node = doc.NewNode(pkgPath, pkgPath, tp, ver, true) } // Check package name. if !strings.Contains(pkgPath, "/") { pkgPath = doc.GetPkgFullPath(pkgPath) } nodes = append(nodes, node) } downloadPackages(ctx, nodes) doc.SaveLocalNodes() log.Log("%d package(s) downloaded, %d failed", downloadCount, failConut) }
func getByGopmfile(ctx *cli.Context) { // Check if gopmfile exists and generate one if not. if !com.IsFile(".gopmfile") { runGen(ctx) } gf := doc.NewGopmfile(".") targetPath := parseTarget(gf.MustValue("target", "path")) // Get dependencies. imports := doc.GetAllImports([]string{workDir}, targetPath, ctx.Bool("example")) nodes := make([]*doc.Node, 0, len(imports)) for _, p := range imports { p = doc.GetProjectPath(p) // Skip subpackage(s) of current project. if isSubpackage(p, targetPath) { continue } node := doc.NewNode(p, p, doc.BRANCH, "", true) // Check if user specified the version. if v, err := gf.GetValue("deps", p); err == nil && len(v) > 0 { node.Type, node.Value = validPath(v) } nodes = append(nodes, node) } downloadPackages(ctx, nodes) doc.SaveLocalNodes() log.Log("%d package(s) downloaded, %d failed", downloadCount, failConut) }
func runGet(ctx *cli.Context) { setup(ctx) // Check conflicts. if ctx.Bool("gopath") && ctx.Bool("remote") { log.Error("get", "Command options have conflicts") log.Error("", "Following options are not supposed to use at same time:") log.Error("", "\t'--gopath, -g' '--remote, -r'") log.Help("Try 'gopm help get' to get more information") } if !ctx.Bool("remote") { // Get GOPATH. installGopath = com.GetGOPATHs()[0] if com.IsDir(installGopath) { isHasGopath = true log.Log("Indicated GOPATH: %s", installGopath) installGopath += "/src" } else { if ctx.Bool("gopath") { log.Error("get", "Invalid GOPATH path") log.Error("", "GOPATH does not exist or is not a directory:") log.Error("", "\t"+installGopath) log.Help("Try 'go help gopath' to get more information") } else { // It's OK that no GOPATH setting // when user does not specify to use. log.Warn("No GOPATH setting available") } } } // The gopm local repository. installRepoPath = doc.HomeDir + "/repos" log.Log("Local repository path: %s", installRepoPath) // Check number of arguments to decide which function to call. switch len(ctx.Args()) { case 0: getByGopmfile(ctx) default: getByPath(ctx) } }
func runBuild(ctx *cli.Context) { setup(ctx) // Get GOPATH. installGopath = com.GetGOPATHs()[0] if com.IsDir(installGopath) { isHasGopath = true log.Log("Indicated GOPATH: %s", installGopath) installGopath += "/src" } buildBinary(ctx, ctx.Args()...) log.Success("SUCC", "build", "Command executed successfully!") }
func copyToGopath(srcPath, destPath string) { importPath := strings.TrimPrefix(destPath, installGopath+"/") if len(getVcsName(destPath)) > 0 { log.Warn("Package in GOPATH has version control: %s", importPath) return } os.RemoveAll(destPath) err := com.CopyDir(srcPath, destPath) if err != nil { log.Error("download", "Fail to copy to GOPATH:") log.Fatal("", "\t"+err.Error()) } log.Log("Package copied to GOPATH: %s", importPath) }
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 }
// PureDownload downloads package without version control. func PureDownload(nod *Node, installRepoPath string, ctx *cli.Context) ([]string, error) { for _, s := range services { if s.get == nil || !strings.HasPrefix(nod.DownloadURL, s.prefix) { continue } m := s.pattern.FindStringSubmatch(nod.DownloadURL) if m == nil { if s.prefix != "" { return nil, errors.New("Cannot match package service prefix by given path") } continue } match := map[string]string{"importPath": nod.DownloadURL} for i, n := range s.pattern.SubexpNames() { if n != "" { match[n] = m[i] } } return s.get(HttpClient, match, installRepoPath, nod, ctx) } log.Log("Cannot match any service, getting dynamic...") return getDynamic(HttpClient, nod, installRepoPath, ctx) }
func runInstall(ctx *cli.Context) { setup(ctx) var target string switch len(ctx.Args()) { case 0: if !com.IsFile(".gopmfile") { break } gf := doc.NewGopmfile(".") target = gf.MustValue("target", "path") case 1: target = ctx.Args()[0] default: log.Fatal("install", "Too many arguments") } // Get GOPATH. installGopath = com.GetGOPATHs()[0] if com.IsDir(installGopath) { isHasGopath = true log.Log("Indicated GOPATH: %s", installGopath) installGopath += "/src" } else { if ctx.Bool("gopath") { log.Error("get", "Invalid GOPATH path") log.Error("", "GOPATH does not exist or is not a directory:") log.Error("", "\t"+installGopath) log.Help("Try 'go help gopath' to get more information") } else { // It's OK that no GOPATH setting // when user does not specify to use. log.Warn("No GOPATH setting available") } } genNewGoPath(ctx, false) var installRepos []string if ctx.Bool("pkg") { curPath, _ := filepath.Abs(".") installRepos = doc.GetAllImports([]string{curPath}, ".", ctx.Bool("example")) } else { if len(target) == 0 { target = pkgName } installRepos = []string{target} } log.Trace("Installing...") for _, repo := range installRepos { cmdArgs := []string{"go", "install"} if ctx.Bool("verbose") { cmdArgs = append(cmdArgs, "-v") } cmdArgs = append(cmdArgs, repo) err := execCmd(newGoPath, newCurPath, cmdArgs...) if err != nil { log.Error("install", "Fail to install program:") log.Fatal("", "\t"+err.Error()) } } log.Success("SUCC", "install", "Command executed successfully!") }
// getGoogleDoc downloads raw files from code.google.com. func getGoogleDoc(client *http.Client, match map[string]string, installRepoPath string, nod *Node, ctx *cli.Context) ([]string, error) { setupGoogleMatch(match) // Check version control. if err := getGoogleVCS(client, match); err != nil { return nil, errors.New("fail to get vcs " + nod.ImportPath + " : " + err.Error()) } switch nod.Type { case BRANCH: if len(nod.Value) == 0 { match["tag"] = defaultTags[match["vcs"]] // Only get and check revision with the latest version. p, err := com.HttpGetBytes(client, com.Expand("http://{subrepo}{dot}{repo}.googlecode.com/{vcs}{dir}/?r={tag}", match), nil) if err != nil { log.Error("GET", "Fail to get revision") log.Error("", err.Error()) break } if m := googleRevisionRe.FindSubmatch(p); m == nil { log.Error("GET", "Fail to get revision") log.Error("", err.Error()) } else { etag := string(m[1]) if etag == nod.Revision { log.Log("GET Package hasn't changed: %s", nod.ImportPath) return nil, nil } nod.Revision = etag } } else { match["tag"] = nod.Value } case TAG, COMMIT: match["tag"] = nod.Value default: return nil, errors.New("Unknown node type: " + nod.Type) } var installPath string projectPath := GetProjectPath(nod.ImportPath) if nod.ImportPath == nod.DownloadURL { suf := "." + nod.Value if len(suf) == 1 { suf = "" } installPath = installRepoPath + "/" + projectPath + suf } else { installPath = installRepoPath + "/" + projectPath } // Remove old files. os.RemoveAll(installPath + "/") os.MkdirAll(installPath+"/", os.ModePerm) if match["vcs"] == "svn" { com.ColorLog("[WARN] SVN detected, may take very long time.\n") rootPath := com.Expand("http://{subrepo}{dot}{repo}.googlecode.com/{vcs}", match) d, f := path.Split(rootPath) err := downloadFiles(client, match, d, installPath+"/", match["tag"], []string{f + "/"}) if err != nil { return nil, errors.New("Fail to download " + nod.ImportPath + " : " + err.Error()) } } p, err := com.HttpGetBytes(client, com.Expand("http://{subrepo}{dot}{repo}.googlecode.com/archive/{tag}.zip", match), nil) if err != nil { return nil, errors.New("Fail to download " + nod.ImportPath + " : " + err.Error()) } r, err := zip.NewReader(bytes.NewReader(p), int64(len(p))) if err != nil { return nil, errors.New(nod.ImportPath + " -> new zip: " + err.Error()) } nameLen := strings.Index(r.File[0].Name, "/") dirPrefix := match["dir"] if len(dirPrefix) != 0 { dirPrefix = dirPrefix[1:] + "/" } dirs := make([]string, 0, 5) for _, f := range r.File { absPath := strings.Replace(f.Name, f.Name[:nameLen], installPath, 1) // Create diretory before create file. dir := path.Dir(absPath) if !checkDir(dir, dirs) && !(!ctx.Bool("example") && strings.Contains(absPath, "example")) { dirs = append(dirs, dir+"/") os.MkdirAll(dir+"/", os.ModePerm) } // Get file from archive. r, err := f.Open() if err != nil { return nil, err } fbytes := make([]byte, f.FileInfo().Size()) _, err = io.ReadFull(r, fbytes) if err != nil { return nil, err } _, err = com.SaveFile(absPath, fbytes) if err != nil { return nil, err } } var imports []string // Check if need to check imports. if nod.IsGetDeps { for _, d := range dirs { importPkgs, err := CheckImports(d, match["importPath"], nod) if err != nil { return nil, err } imports = append(imports, importPkgs...) } } return imports, err }
func runExec(ctx *cli.Context) { setup(ctx) if len(ctx.Args()) == 0 { log.Error("exec", "Cannot start command:") log.Fatal("", "\tNo package specified") } installRepoPath = doc.HomeDir + "/repos" log.Log("Local repository path: %s", installRepoPath) // Parse package version. info := ctx.Args()[0] pkgPath := info node := doc.NewNode(pkgPath, pkgPath, doc.BRANCH, "", true) if i := strings.Index(info, "@"); i > -1 { // Specify version by argument. pkgPath = info[:i] node.Type, node.Value = validPath(info[i+1:]) } // Check package name. if !strings.Contains(pkgPath, "/") { pkgPath = doc.GetPkgFullPath(pkgPath) } node.ImportPath = pkgPath node.DownloadURL = pkgPath if len(node.Value) == 0 && com.IsFile(".gopmfile") { // Specify version by gopmfile. gf := doc.NewGopmfile(".") info, err := gf.GetValue("exec", pkgPath) if err == nil && len(info) > 0 { node.Type, node.Value = validPath(info) } } // Check if binary exists. binPath := path.Join(doc.HomeDir, "bins", node.ImportPath, path.Base(node.ImportPath)+versionSuffix(node.Value)) log.Log("Binary path: %s", binPath) if !com.IsFile(binPath) { // Calling bin command. args := []string{"bin", "-d"} if ctx.Bool("verbose") { args = append(args, "-v") } if ctx.Bool("update") { args = append(args, "-u") } args = append(args, node.ImportPath+"@"+node.Type+":"+node.Value) args = append(args, path.Dir(binPath)) stdout, stderr, err := com.ExecCmd("gopm", args...) if err != nil { log.Error("exec", "Building binary failed:") log.Fatal("", "\t"+err.Error()) } if len(stderr) > 0 { fmt.Print(stderr) } if len(stdout) > 0 { fmt.Print(stdout) } } fmt.Printf("%+v\n", node) return stdout, stderr, err := com.ExecCmd(binPath, ctx.Args()[1:]...) if err != nil { log.Error("exec", "Calling binary failed:") log.Fatal("", "\t"+err.Error()) } if len(stderr) > 0 { fmt.Print(stderr) } if len(stdout) > 0 { fmt.Print(stdout) } }
func runRun(ctx *cli.Context) { setup(ctx) //support unix only if ctx.Bool("local") { var localPath string var err error var wd string var gf *goconfig.ConfigFile wd, _ = os.Getwd() for wd != "/" { gf, _ = goconfig.LoadConfigFile(".gopmfile") if gf != nil { localPath = gf.MustValue("project", "localPath") } if localPath != "" { break } os.Chdir("..") wd, _ = os.Getwd() } if wd == "/" { log.Fatal("run", "no gopmfile in the directory or parent directory") } argss := gf.MustValue("run", "cmd") if localPath == "" { log.Fatal("run", "No localPath set") } args := strings.Split(argss, " ") argsLen := len(args) for i := 0; i < argsLen; i++ { strings.Trim(args[i], " ") } if len(args) < 2 { log.Fatal("run", "cmd arguments less than 2") } err = execCmd(localPath, localPath, args...) if err != nil { log.Error("run", "Fail to run program:") log.Fatal("", "\t"+err.Error()) } return } // Get GOPATH. installGopath = com.GetGOPATHs()[0] if com.IsDir(installGopath) { isHasGopath = true log.Log("Indicated GOPATH: %s", installGopath) installGopath += "/src" } // run command with gopm repos context // need version control , auto link to GOPATH/src repos genNewGoPath(ctx, false) defer os.RemoveAll(doc.VENDOR) log.Trace("Running...") cmdArgs := []string{"go", "run"} cmdArgs = append(cmdArgs, ctx.Args()...) err := execCmd(newGoPath, newCurPath, cmdArgs...) if err != nil { log.Error("run", "Fail to run program:") log.Fatal("", "\t"+err.Error()) } log.Success("SUCC", "run", "Command executed successfully!") }
// downloadPackages downloads packages with certain commit, // if the commit is empty string, then it downloads all dependencies, // otherwise, it only downloada package with specific commit only. func downloadPackages(ctx *cli.Context, nodes []*doc.Node) { // Check all packages, they may be raw packages path. for _, n := range nodes { // Check if local reference if n.Type == doc.LOCAL { continue } // Check if it is a valid remote path or C. if n.ImportPath == "C" { continue } else if !doc.IsValidRemotePath(n.ImportPath) { // Invalid import path. log.Error("download", "Skipped invalid package: "+fmt.Sprintf("%s@%s:%s", n.ImportPath, n.Type, doc.CheckNodeValue(n.Value))) failConut++ continue } // Valid import path. gopathDir := path.Join(installGopath, n.ImportPath) n.RootPath = doc.GetProjectPath(n.ImportPath) installPath := path.Join(installRepoPath, n.RootPath) + versionSuffix(n.Value) if isSubpackage(n.RootPath, ".") { continue } // Indicates whether need to download package again. if n.IsFixed() && com.IsExist(installPath) { n.IsGetDepsOnly = true } if !ctx.Bool("update") { // Check if package has been downloaded. if (len(n.Value) == 0 && !ctx.Bool("remote") && com.IsExist(gopathDir)) || com.IsExist(installPath) { log.Trace("Skipped installed package: %s@%s:%s", n.ImportPath, n.Type, doc.CheckNodeValue(n.Value)) // Only copy when no version control. if ctx.Bool("gopath") && com.IsExist(installPath) || len(getVcsName(gopathDir)) == 0 { copyToGopath(installPath, gopathDir) } continue } else { doc.LocalNodes.SetValue(n.RootPath, "value", "") } } if downloadCache[n.RootPath] { log.Trace("Skipped downloaded package: %s@%s:%s", n.ImportPath, n.Type, doc.CheckNodeValue(n.Value)) continue } // Download package. nod, imports := downloadPackage(ctx, n) if len(imports) > 0 { var gf *goconfig.ConfigFile // Check if has gopmfile. if com.IsFile(installPath + "/" + doc.GOPM_FILE_NAME) { log.Log("Found gopmfile: %s@%s:%s", n.ImportPath, n.Type, doc.CheckNodeValue(n.Value)) gf = doc.NewGopmfile(installPath) } // Need to download dependencies. // Generate temporary nodes. nodes := make([]*doc.Node, len(imports)) for i := range nodes { nodes[i] = doc.NewNode(imports[i], imports[i], doc.BRANCH, "", true) if gf == nil { continue } // Check if user specified the version. if v, err := gf.GetValue("deps", imports[i]); err == nil && len(v) > 0 { nodes[i].Type, nodes[i].Value = validPath(v) } } downloadPackages(ctx, nodes) } // Only save package information with specific commit. if nod == nil { continue } // Save record in local nodes. log.Success("SUCC", "GET", fmt.Sprintf("%s@%s:%s", n.ImportPath, n.Type, doc.CheckNodeValue(n.Value))) downloadCount++ // Only save non-commit node. if len(nod.Value) == 0 && len(nod.Revision) > 0 { doc.LocalNodes.SetValue(nod.RootPath, "value", nod.Revision) } if ctx.Bool("gopath") && com.IsExist(installPath) && !ctx.Bool("update") && len(getVcsName(path.Join(installGopath, nod.RootPath))) == 0 { copyToGopath(installPath, gopathDir) } } }
func runUpdate(ctx *cli.Context) { doc.LoadPkgNameList(doc.HomeDir + "/data/pkgname.list") installRepoPath = doc.HomeDir + "/repos" // Check arguments. num := 0 if len(ctx.Args()) != num { log.Error("Update", "Fail to start command") log.Fatal("", "Invalid argument number") } // Parse package version. info := "github.com/gpmgo/gopm" pkgPath := info ver := "" var err error if i := strings.Index(info, "@"); i > -1 { pkgPath = info[:i] _, ver = validPath(info[i+1:]) } // Check package name. if !strings.Contains(pkgPath, "/") { name, ok := doc.PackageNameList[pkgPath] if !ok { log.Error("Update", "Invalid package name: "+pkgPath) log.Fatal("", "No match in the package name list") } pkgPath = name } // Get code. stdout, _, _ := com.ExecCmd("gopm", "get", info) if len(stdout) > 0 { fmt.Print(stdout) } // Check if previous steps were successful. repoPath := installRepoPath + "/" + pkgPath if len(ver) > 0 { repoPath += "." + ver } if !com.IsDir(repoPath) { log.Error("Bin", "Fail to continue command") log.Fatal("", "Previous steps weren't successful") } wd, err := os.Getwd() if err != nil { log.Error("Bin", "Fail to get work directory") log.Fatal("", err.Error()) } // Change to repository path. log.Log("Changing work directory to %s", repoPath) err = os.Chdir(repoPath) if err != nil { log.Error("Bin", "Fail to change work directory") log.Fatal("", err.Error()) } // Build application. stdout, _, _ = com.ExecCmd("gopm", "build") if len(stdout) > 0 { fmt.Print(stdout) } defer func() { // Clean files. os.RemoveAll(path.Join(repoPath, doc.VENDOR)) }() // Check if previous steps were successful. if com.IsFile(doc.GOPM_FILE_NAME) { log.Trace("Loading gopmfile...") gf := doc.NewGopmfile(".") 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(pkgPath) } binName := path.Base(pkgName) if runtime.GOOS == "windows" { binName += ".exe" } binPath := path.Join(doc.VENDOR, "src", pkgPath, binName) if !com.IsFile(binPath) { log.Error("Update", "Fail to continue command") log.Fatal("", "Previous steps weren't successful or the project does not contain main package") } movePath := exePath() fmt.Print(movePath) // Move binary to given directory. if runtime.GOOS != "windows" { err = os.Rename(binPath, movePath) if err != nil { log.Error("Update", "Fail to move binary") log.Fatal("", err.Error()) } os.Chmod(movePath+"/"+binName, os.ModePerm) } else { batPath := filepath.Join(wd, "a.bat") f, err := os.Create(batPath) if err != nil { log.Error("Update", "Fail to generate bat file") log.Fatal("", err.Error()) } f.WriteString(fmt.Sprintf(`ping -n 1 127.0.0.1>nul\ncopy "%v" "%v"\ndel "%v"\ndel "%v"`, binPath, movePath, binPath, batPath)) f.Close() attr := &os.ProcAttr{ Dir: wd, Env: os.Environ(), //Files: []*os.File{nil, nil, nil}, Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, } _, err = os.StartProcess(batPath, []string{"a.bat"}, attr) if err != nil { log.Error("Update", "Fail to start bat process") log.Fatal("", err.Error()) } } log.Log("Changing work directory back to %s", wd) os.Chdir(wd) log.Success("SUCC", "Update", "Command execute successfully!") }
func runUpdate(ctx *cli.Context) { setup(ctx) isAnythingUpdated := false // Load local version info. localVerInfo := loadLocalVerInfo() // Get remote version info. var remoteVerInfo version if err := com.HttpGetJSON(http.DefaultClient, "http://gopm.io/VERSION.json", &remoteVerInfo); err != nil { log.Error("Update", "Fail to fetch VERSION.json") log.Fatal("", err.Error()) } // Package name list. if remoteVerInfo.PackageNameList > localVerInfo.PackageNameList { log.Log("Updating pkgname.list...%v > %v", localVerInfo.PackageNameList, remoteVerInfo.PackageNameList) data, err := com.HttpGetBytes(http.DefaultClient, "https://raw2.github.com/gpmgo/docs/master/pkgname.list", nil) if err != nil { log.Error("Update", "Fail to update pkgname.list") log.Fatal("", err.Error()) } if err = com.WriteFile(path.Join(doc.HomeDir, doc.PKG_NAME_LIST_PATH), data); err != nil { log.Error("Update", "Fail to save pkgname.list") log.Fatal("", err.Error()) } log.Log("Update pkgname.list to %v succeed!", remoteVerInfo.PackageNameList) isAnythingUpdated = true } // Gopm. if remoteVerInfo.Gopm > localVerInfo.Gopm { log.Log("Updating gopm...%v > %v", localVerInfo.Gopm, remoteVerInfo.Gopm) installRepoPath = doc.HomeDir + "/repos" tmpDirPath := filepath.Join(doc.HomeDir, "temp") tmpBinPath := filepath.Join(tmpDirPath, "gopm") if runtime.GOOS == "windows" { tmpBinPath += ".exe" } os.MkdirAll(tmpDirPath, os.ModePerm) os.Remove(tmpBinPath) // Fetch code. args := []string{"bin", "-u", "-d"} if ctx.Bool("verbose") { args = append(args, "-v") } args = append(args, []string{"github.com/gpmgo/gopm", tmpDirPath}...) stdout, stderr, err := com.ExecCmd("gopm", args...) if err != nil { log.Error("Update", "Fail to execute 'gopm bin -u -d github.com/gpmgo/gopm "+tmpDirPath+"'") log.Fatal("", err.Error()) } if len(stderr) > 0 { fmt.Print(stderr) } if len(stdout) > 0 { fmt.Print(stdout) } // Check if previous steps were successful. if !com.IsExist(tmpBinPath) { log.Error("Update", "Fail to continue command") log.Fatal("", "Previous steps weren't successful, no binary produced") } movePath := exePath() log.Log("New binary will be replaced for %s", movePath) // Move binary to given directory. if runtime.GOOS != "windows" { err := os.Rename(tmpBinPath, movePath) if err != nil { log.Error("Update", "Fail to move binary") log.Fatal("", err.Error()) } os.Chmod(movePath+"/"+path.Base(tmpBinPath), os.ModePerm) } else { batPath := filepath.Join(tmpDirPath, "update.bat") f, err := os.Create(batPath) if err != nil { log.Error("Update", "Fail to generate bat file") log.Fatal("", err.Error()) } f.WriteString("@echo off\r\n") f.WriteString(fmt.Sprintf("ping -n 1 127.0.0.1>nul\r\ncopy \"%v\" \"%v\" >nul\r\ndel \"%v\" >nul\r\n\r\n", tmpBinPath, movePath, tmpBinPath)) //f.WriteString(fmt.Sprintf("del \"%v\"\r\n", batPath)) f.Close() attr := &os.ProcAttr{ Dir: workDir, Env: os.Environ(), Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, } _, err = os.StartProcess(batPath, []string{batPath}, attr) if err != nil { log.Error("Update", "Fail to start bat process") log.Fatal("", err.Error()) } } log.Success("SUCC", "Update", "Command execute successfully!") isAnythingUpdated = true } // Save JSON. f, err := os.Create(path.Join(doc.HomeDir, doc.VER_PATH)) if err != nil { log.Error("Update", "Fail to create VERSION.json") log.Fatal("", err.Error()) } if err := json.NewEncoder(f).Encode(&remoteVerInfo); err != nil { log.Error("Update", "Fail to encode VERSION.json") log.Fatal("", err.Error()) } if !isAnythingUpdated { log.Log("Nothing need to be updated") } log.Log("Exit old gopm") }
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()) } log.Trace("Current Path: 0 %s", curPath) 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) if err = getChildPkgs(ctx, curPath, nil, cachePkgs, isTest); 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()) } }
func runBin(ctx *cli.Context) { setup(ctx) if len(ctx.Args()) == 0 { log.Error("bin", "Cannot start command:") log.Fatal("", "\tNo package specified") } installRepoPath = doc.HomeDir + "/repos" log.Log("Local repository path: %s", installRepoPath) // Check arguments. num := 1 if ctx.Bool("dir") { num = 2 } if len(ctx.Args()) != num { log.Error("bin", "Cannot start command:") log.Fatal("", "\tMissing indicated path to build binary") } // Check if given directory exists. if ctx.Bool("dir") && !com.IsDir(ctx.Args()[1]) { log.Error("bin", "Cannot start command:") log.Fatal("", "\tIndicated path does not exist or is not a directory") } // Parse package version. info := ctx.Args()[0] pkgPath := info node := doc.NewNode(pkgPath, pkgPath, doc.BRANCH, "", true) var err error if i := strings.Index(info, "@"); i > -1 { pkgPath = info[:i] node.ImportPath = pkgPath node.DownloadURL = pkgPath node.Type, node.Value = validPath(info[i+1:]) } // Check package name. if !strings.Contains(pkgPath, "/") { pkgPath = doc.GetPkgFullPath(pkgPath) } // Get code. downloadPackages(ctx, []*doc.Node{node}) // Check if previous steps were successful. repoPath := installRepoPath + "/" + pkgPath + versionSuffix(node.Value) if !com.IsDir(repoPath) { log.Error("bin", "Cannot continue command:") log.Fatal("", "\tPrevious steps weren't successful") } wd, err := os.Getwd() if err != nil { log.Error("bin", "Cannot get work directory:") log.Fatal("", "\t"+err.Error()) } // Change to repository path. log.Log("Changing work directory to %s", repoPath) if err = os.Chdir(repoPath); err != nil { log.Error("bin", "Fail to change work directory:") log.Fatal("", "\t"+err.Error()) } // Build application. buildBinary(ctx) defer func() { // Clean files. os.RemoveAll(path.Join(repoPath, doc.VENDOR)) }() includes := make([]string, 0, 3) // Check if previous steps were successful. if com.IsFile(doc.GOPM_FILE_NAME) { log.Trace("Loading gopmfile...") gf := doc.NewGopmfile(".") var err error pkgName, err = gf.GetValue("target", "path") if err == nil { log.Log("Target name: %s", pkgName) } includes = strings.Split(gf.MustValue("res", "include"), "|") } if len(pkgName) == 0 { _, pkgName = filepath.Split(pkgPath) } // Because build command moved binary to root path. binName := path.Base(pkgName) if runtime.GOOS == "windows" { binName += ".exe" } if !com.IsFile(binName) { log.Error("bin", "Binary does not exist:") log.Error("", "\t"+binName) log.Fatal("", "\tPrevious steps weren't successful or the project does not contain main package") } // Move binary to given directory. movePath := wd if ctx.Bool("dir") { movePath = ctx.Args()[1] } if com.IsExist(movePath + "/" + binName) { if err = os.Remove(movePath + "/" + binName); err != nil { log.Warn("Cannot remove binary in work directory:") log.Warn("\t %s", err) } } if err = os.Rename(binName, movePath+"/"+binName); err != nil { log.Error("bin", "Fail to move binary:") log.Fatal("", "\t"+err.Error()) } os.Chmod(movePath+"/"+binName, os.ModePerm) if len(includes) > 0 { log.Log("Copying resources to %s", movePath) for _, include := range includes { if com.IsDir(include) { if err = com.CopyDir(include, filepath.Join(movePath, include)); err != nil { log.Error("bin", "Fail to copy following resource:") log.Error("", "\t"+include) } } } } log.Log("Changing work directory back to %s", wd) os.Chdir(wd) log.Success("SUCC", "bin", "Command executed successfully!") fmt.Println("Binary has been built into: " + movePath) }
// getGithubDoc downloads tarball from github.com. func getGithubDoc(client *http.Client, match map[string]string, installRepoPath string, nod *Node, ctx *cli.Context) ([]string, error) { match["cred"] = GetGithubCredentials() // Check downlaod type. switch nod.Type { case BRANCH: if len(nod.Value) == 0 { match["sha"] = MASTER // Only get and check revision with the latest version. var refs []*struct { Ref string Url string Object struct { Sha string Type string Url string } } err := com.HttpGetJSON(client, com.Expand("https://api.github.com/repos/{owner}/{repo}/git/refs?{cred}", match), &refs) if err != nil { if strings.Contains(err.Error(), "403") { break } log.Warn("GET", "Fail to get revision") log.Warn("", err.Error()) break } var etag string COMMIT_LOOP: for _, ref := range refs { switch { case strings.HasPrefix(ref.Ref, "refs/heads/master"): etag = ref.Object.Sha break COMMIT_LOOP } } if etag == nod.Revision { log.Log("GET Package hasn't changed: %s", nod.ImportPath) return nil, nil } nod.Revision = etag } else { match["sha"] = nod.Value } case TAG, COMMIT: match["sha"] = nod.Value default: return nil, errors.New("Unknown node type: " + nod.Type) } // We use .zip here. // zip: https://github.com/{owner}/{repo}/archive/{sha}.zip // tarball: https://github.com/{owner}/{repo}/tarball/{sha} // Downlaod archive. p, err := com.HttpGetBytes(client, com.Expand("https://github.com/{owner}/{repo}/archive/{sha}.zip", match), nil) if err != nil { return nil, errors.New("Fail to donwload Github repo -> " + err.Error()) } shaName := com.Expand("{repo}-{sha}", match) if nod.Type == "tag" { shaName = strings.Replace(shaName, "-v", "-", 1) } var installPath string if nod.ImportPath == nod.DownloadURL { suf := "." + nod.Value if len(suf) == 1 { suf = "" } projectPath := com.Expand("github.com/{owner}/{repo}", match) installPath = installRepoPath + "/" + projectPath + suf nod.ImportPath = projectPath } else { installPath = installRepoPath + "/" + nod.ImportPath } // Remove old files. os.RemoveAll(installPath + "/") os.MkdirAll(installPath+"/", os.ModePerm) r, err := zip.NewReader(bytes.NewReader(p), int64(len(p))) if err != nil { return nil, errors.New(nod.ImportPath + " -> new zip: " + err.Error()) } dirs := make([]string, 0, 5) // Need to add root path because we cannot get from tarball. dirs = append(dirs, installPath+"/") for _, f := range r.File { absPath := strings.Replace(f.Name, shaName, installPath, 1) // Create diretory before create file. os.MkdirAll(path.Dir(absPath)+"/", os.ModePerm) compareDir: switch { case strings.HasSuffix(absPath, "/"): // Directory. // Check if current directory is example. if !(!ctx.Bool("example") && strings.Contains(absPath, "example")) { for _, d := range dirs { if d == absPath { break compareDir } } dirs = append(dirs, absPath) } default: // Get file from archive. r, err := f.Open() if err != nil { return nil, err } fbytes := make([]byte, f.FileInfo().Size()) _, err = io.ReadFull(r, fbytes) if err != nil { return nil, err } if err = com.WriteFile(absPath, fbytes); err != nil { return nil, err } // Set modify time. os.Chtimes(absPath, f.ModTime(), f.ModTime()) } } var imports []string // Check if need to check imports. if nod.IsGetDeps { for _, d := range dirs { importPkgs, err := CheckImports(d, match["importPath"], nod) if err != nil { return nil, err } imports = append(imports, importPkgs...) } } return imports, err }
func runGet(ctx *cli.Context) { setup(ctx) // Check conflicts. if ctx.Bool("gopath") && ctx.Bool("remote") || ctx.Bool("local") && ctx.Bool("remote") || ctx.Bool("gopath") && ctx.Bool("local") { e := " " if ctx.Bool("gopath") { e += "--gopth,-g " } if ctx.Bool("remote") { e += "--remote,-r " } if ctx.Bool("local") { e += "--local,-l " } log.Error("get", "Command options have conflicts") log.Error("", "Following options are not supposed to use at same time:") log.Error("", "\t"+e) log.Help("Try 'gopm help get' to get more information") } if !ctx.Bool("remote") { // Get GOPATH. installGopath = com.GetGOPATHs()[0] if com.IsDir(installGopath) { isHasGopath = true log.Log("Indicated GOPATH: %s", installGopath) installGopath += "/src" } else { if ctx.Bool("gopath") { log.Error("get", "Invalid GOPATH path") log.Error("", "GOPATH does not exist or is not a directory:") log.Error("", "\t"+installGopath) log.Help("Try 'go help gopath' to get more information") } else { // It's OK that no GOPATH setting // when user does not specify to use. log.Warn("No GOPATH setting available") } } // if flag local set use localPath as GOPATH if ctx.Bool("local") { if !com.IsExist(".gopmfile") { runGen(ctx) } gf, err := goconfig.LoadConfigFile(".gopmfile") if err != nil { log.Fatal("get", err.Error()) } else { installGopath = gf.MustValue("project", "localPath") if installGopath == "" { os.Remove(".gopmfile") log.Fatal("get", "unexpected localPath or no localPath exists") } installGopath += "/src" } } } // The gopm local repository. installRepoPath = path.Join(doc.HomeDir, "repos") log.Log("Local repository path: %s", installRepoPath) // Check number of arguments to decide which function to call. switch len(ctx.Args()) { case 0: getByGopmfile(ctx) case 1: getByPath(ctx) default: log.Error("get", "too many arguments") log.Help("Try 'gopm help get' to get more information") } }