func execCmd(gopath, curPath string, args ...string) error { oldGopath := os.Getenv("GOPATH") log.Info("Setting GOPATH to %s", gopath) sep := ":" if runtime.GOOS == "windows" { sep = ";" } if err := os.Setenv("GOPATH", gopath+sep+oldGopath); err != nil { if setting.LibraryMode { return fmt.Errorf("Fail to setting GOPATH: %v", err) } log.Error("", "Fail to setting GOPATH:") log.Fatal("", "\t"+err.Error()) } if setting.HasGOPATHSetting { defer func() { log.Info("Setting GOPATH back to %s", oldGopath) os.Setenv("GOPATH", oldGopath) }() } cmd := exec.Command(args[0], args[1:]...) cmd.Dir = curPath cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr log.Info("===== application outputs start =====\n") err := cmd.Run() log.Info("====== application outputs end ======") return err }
func runTest(ctx *cli.Context) { if err := setup(ctx); err != nil { errors.SetError(err) return } if err := linkVendors(ctx, ""); err != nil { errors.SetError(err) return } log.Info("Testing...") cmdArgs := []string{"go", "test"} if len(ctx.String("tags")) > 0 { cmdArgs = append(cmdArgs, "-tags") cmdArgs = append(cmdArgs, ctx.String("tags")) } cmdArgs = append(cmdArgs, ctx.Args()...) if err := execCmd(setting.DefaultVendor, setting.WorkDir, cmdArgs...); err != nil { errors.SetError(fmt.Errorf("fail to run program: %v", err)) return } log.Info("Command executed successfully!") }
// Download downloads remote package without version control. func (n *Node) Download(ctx *cli.Context) ([]string, error) { for _, s := range services { if !strings.HasPrefix(n.DownloadURL, s.prefix) { continue } m := s.pattern.FindStringSubmatch(n.DownloadURL) if m == nil { if s.prefix != "" { return nil, errors.New("Cannot match package service prefix by given path") } continue } match := map[string]string{"downloadURL": n.DownloadURL} for i, n := range s.pattern.SubexpNames() { if n != "" { match[n] = m[i] } } return s.get(HttpClient, match, n, ctx) } if n.ImportPath != n.DownloadURL { return nil, errors.New("Didn't find any match service") } log.Info("Cannot match any service, getting dynamic...") return n.getDynamic(HttpClient, ctx) }
func runBuild(ctx *cli.Context) { if err := setup(ctx); err != nil { errors.SetError(err) return } if err := buildBinary(ctx, ctx.Args()...); err != nil { errors.SetError(err) return } log.Info("Command executed successfully!") }
// ParseTarget guesses import path of current package // if target is empty. func ParseTarget(target string) string { if len(target) > 0 { return target } for _, gopath := range base.GetGOPATHs() { if strings.HasPrefix(setting.WorkDir, gopath) { target = strings.TrimPrefix(setting.WorkDir, path.Join(gopath, "src")+"/") log.Info("Guess import path: %s", target) return target } } return "." }
func runInstall(ctx *cli.Context) { if err := setup(ctx); err != nil { errors.SetError(err) return } if err := linkVendors(ctx, ""); err != nil { errors.SetError(err) return } // Get target name. gfPath := path.Join(setting.WorkDir, setting.GOPMFILE) _, target, err := parseGopmfile(gfPath) if err != nil { errors.SetError(fmt.Errorf("fail to parse gopmfile: %v", err)) return } log.Info("Installing...") cmdArgs := []string{"go", "install"} if ctx.Bool("verbose") { cmdArgs = append(cmdArgs, "-v") } if len(ctx.String("tags")) > 0 { cmdArgs = append(cmdArgs, "-tags") cmdArgs = append(cmdArgs, ctx.String("tags")) } cmdArgs = append(cmdArgs, target) if err := execCmd(setting.DefaultVendor, setting.WorkDir, cmdArgs...); err != nil { errors.SetError(fmt.Errorf("fail to run program: %v", err)) return } log.Info("Command executed successfully!") }
func (n *Node) CopyToGopath() error { if n.HasVcs() { log.Warn("Package in GOPATH has version control: %s", n.RootPath) return nil } os.RemoveAll(n.InstallGopath) if err := base.CopyDir(n.InstallPath, n.InstallGopath); err != nil { if setting.LibraryMode { return fmt.Errorf("Fail to copy to GOPATH: %v", err) } log.Error("", "Fail to copy to GOPATH:") log.Fatal("", "\t"+err.Error()) } log.Info("Package copied to GOPATH: %s", n.RootPath) return nil }
func buildBinary(ctx *cli.Context, args ...string) error { _, target, err := parseGopmfile(setting.GOPMFILE) if err != nil { return err } if err := linkVendors(ctx, ""); err != nil { return err } log.Info("Building...") cmdArgs := []string{"go", "build"} cmdArgs = append(cmdArgs, args...) if len(ctx.String("o")) > 0 { cmdArgs = append(cmdArgs, "-o") cmdArgs = append(cmdArgs, ctx.String("o")) } if len(ctx.String("tags")) > 0 { cmdArgs = append(cmdArgs, "-tags") cmdArgs = append(cmdArgs, ctx.String("tags")) } if err := execCmd(setting.DefaultVendor, setting.WorkDir, cmdArgs...); err != nil { return fmt.Errorf("fail to build program: %v", err) } if setting.IsWindowsXP { fName := path.Base(target) binName := fName + ".exe" os.Remove(binName) exePath := path.Join(setting.DefaultVendorSrc, target, binName) if base.IsFile(exePath) { if err := os.Rename(exePath, path.Join(setting.WorkDir, binName)); err != nil { return fmt.Errorf("fail to move binary: %v", err) } } else { log.Warn("No binary generated") } } return nil }
// DownloadGopm downloads remote package from gopm registry. func (n *Node) DownloadGopm(ctx *cli.Context) error { // Custom DownloadURL if u, _ := CustomDownloadURL(n.DownloadURL); u != nil { switch u.Scheme { case "git+ssh", "git+https", "git+http": return n.DownloadByGit(ctx, u) case "go+get": return n.DownloadByGoGet(ctx, u) } } // Localsize repository for _, localize := range setting.Localizes { if strings.HasPrefix(n.RootPath, localize.Domain) { return n.DownloadLocalRepository(ctx, localize) } } // Fetch latest version, check if package has been changed. if n.Type == BRANCH && n.IsEmptyVal() { resp, err := http.Get(fmt.Sprintf("%s%s?pkgname=%s", setting.RegistryUrl, setting.URL_API_REVISION, n.RootPath)) if err != nil { return fmt.Errorf("fail to make request: %v", err) } if resp.StatusCode != 200 { var apiErr ApiError if err = json.NewDecoder(resp.Body).Decode(&apiErr); err != nil { return fmt.Errorf("fail to decode response JSON: %v", err) } return errors.New(apiErr.Error) } var apiResp ApiResponse if err = json.NewDecoder(resp.Body).Decode(&apiResp); err != nil { return fmt.Errorf("fail to decode response JSON: %v", err) } if n.Revision == apiResp.Sha { log.Info("Package(%s) hasn't been changed", n.RootPath) return nil } n.Revision = apiResp.Sha } resp, err := http.Get(fmt.Sprintf("%s%s?pkgname=%s&revision=%s", setting.RegistryUrl, setting.URL_API_DOWNLOAD, n.RootPath, n.Value)) if err != nil { return fmt.Errorf("fail to make request: %v", err) } if resp.StatusCode != 200 { var apiErr ApiError if err = json.NewDecoder(resp.Body).Decode(&apiErr); err != nil { return fmt.Errorf("fail to decode response JSON: %v", err) } return errors.New(apiErr.Error) } tmpPath := path.Join(setting.HomeDir, ".gopm/temp/archive", n.RootPath+"-"+base.ToStr(time.Now().Nanosecond())+".zip") defer os.Remove(tmpPath) if setting.Debug { log.Debug("Temp archive path: %s", tmpPath) } os.MkdirAll(path.Dir(tmpPath), os.ModePerm) fw, err := os.Create(tmpPath) if err != nil { return err } if _, err = io.Copy(fw, resp.Body); err != nil { return fmt.Errorf("fail to save archive: %v", err) } fw.Close() // Remove old files. os.RemoveAll(n.InstallPath) os.MkdirAll(path.Dir(n.InstallPath), os.ModePerm) var rootDir string var extractFn = func(fullName string, fi os.FileInfo) error { if len(rootDir) == 0 { rootDir = strings.Split(fullName, "/")[0] } return nil } if err := zip.ExtractToFunc(tmpPath, path.Dir(n.InstallPath), extractFn); err != nil { return fmt.Errorf("fail to extract archive: %v", err) } else if err = os.Rename(path.Join(path.Dir(n.InstallPath), rootDir), n.InstallPath); err != nil { return fmt.Errorf("fail to rename directory: %v", err) } return nil }
func runBin(ctx *cli.Context) { if err := setup(ctx); err != nil { errors.SetError(err) return } if len(ctx.Args()) != 1 { errors.SetError(fmt.Errorf("Incorrect number of arguments for command: should have 1")) return } // Check if given directory exists if specified. if ctx.IsSet("dir") && !base.IsDir(ctx.String("dir")) { errors.SetError(fmt.Errorf("Indicated path does not exist or not a directory")) return } // Backup exsited .vendor. if base.IsExist(setting.VENDOR) { os.Rename(setting.VENDOR, setting.VENDOR+".bak") defer func() { os.Rename(setting.VENDOR+".bak", setting.VENDOR) }() } // Parse package version. info := ctx.Args().First() pkgPath := info n := doc.NewNode(pkgPath, doc.BRANCH, "", "", true) if i := strings.Index(info, "@"); i > -1 { pkgPath = info[:i] var err error tp, val, dwn, err := validPkgInfo(info[i+1:]) if err != nil { errors.SetError(err) return } n = doc.NewNode(pkgPath, tp, val, dwn, !ctx.Bool("download")) } // Check package name. if !strings.Contains(pkgPath, "/") { tmpPath, err := setting.GetPkgFullPath(pkgPath) if err != nil { errors.SetError(err) return } if tmpPath != pkgPath { n = doc.NewNode(tmpPath, n.Type, n.Value, n.DownloadURL, n.IsGetDeps) } } if err := downloadPackages(".", ctx, []*doc.Node{n}); err != nil { errors.SetError(err) return } // Check if previous steps were successful. if !n.IsExist() { errors.SetError(fmt.Errorf("Download steps weren't successful")) return } tmpVendor := path.Join("vendor", path.Base(n.RootPath)) os.RemoveAll(tmpVendor) os.RemoveAll(setting.VENDOR) defer func() { os.RemoveAll(tmpVendor) os.RemoveAll(setting.VENDOR) }() // FIXME: should use .gopm/temp path. if err := autoLink(n.InstallPath, tmpVendor); err != nil { errors.SetError(fmt.Errorf("Fail to link slef: %v", err)) return } os.Chdir(tmpVendor) oldWorkDir := setting.WorkDir setting.WorkDir = path.Join(setting.WorkDir, tmpVendor) if !setting.Debug { defer func() { os.Chdir(oldWorkDir) os.RemoveAll("vendor") os.RemoveAll(setting.VENDOR) }() } // if err := buildBinary(ctx); err != nil { // errors.SetError(err) // return // } if err := linkVendors(ctx, n.ImportPath); err != nil { errors.SetError(err) return } log.Info("Installing...") cmdArgs := []string{"go", "install"} if ctx.Bool("verbose") { cmdArgs = append(cmdArgs, "-v") } if len(ctx.String("tags")) > 0 { cmdArgs = append(cmdArgs, "-tags") cmdArgs = append(cmdArgs, ctx.String("tags")) } cmdArgs = append(cmdArgs, n.ImportPath) if err := execCmd(setting.DefaultVendor, setting.WorkDir, cmdArgs...); err != nil { errors.SetError(fmt.Errorf("fail to run program: %v", err)) return } gf, _, err := parseGopmfile(setting.GOPMFILE) if err != nil { errors.SetError(err) return } // Because build command moved binary to root path. binName := path.Base(n.ImportPath) binPath := path.Join(setting.DefaultVendor, "bin", path.Base(n.ImportPath)) if runtime.GOOS == "windows" { binName += ".exe" } // Move binary to given directory. movePath := oldWorkDir if ctx.IsSet("dir") { movePath = ctx.String("dir") } else if base.IsGoTool(n.ImportPath) { movePath = path.Join(runtime.GOROOT(), "pkg/tool", runtime.GOOS+"_"+runtime.GOARCH) if !base.IsExist(binPath) { log.Info("Command executed successfully!") fmt.Println("Binary has been built into: " + movePath) return } } if !base.IsFile(binPath) { errors.SetError(fmt.Errorf("Previous steps weren't successful or the project does not contain main package")) return } if base.IsExist(path.Join(movePath, binName)) { if err := os.Remove(path.Join(movePath, binName)); err != nil { log.Warn("Cannot remove binary in work directory: %v", err) } } if err := os.Rename(binPath, movePath+"/"+binName); err != nil { errors.SetError(fmt.Errorf("Fail to move binary: %v", err)) return } os.Chmod(movePath+"/"+binName, os.ModePerm) includes := strings.Split(gf.MustValue("res", "include"), "|") if len(includes) > 0 { log.Info("Copying resources to %s", movePath) for _, include := range includes { if base.IsDir(include) { os.RemoveAll(path.Join(movePath, include)) if err := base.CopyDir(include, filepath.Join(movePath, include)); err != nil { errors.AppendError(errors.NewErrCopyResource(include)) } } } } log.Info("Command executed successfully!") fmt.Println("Binary has been built into: " + movePath) }
// setup initializes and checks common environment variables. func setup(ctx *cli.Context) (err error) { setting.Debug = ctx.GlobalBool("debug") log.NonColor = ctx.GlobalBool("noterm") log.Verbose = ctx.Bool("verbose") log.Info("App Version: %s", ctx.App.Version) setting.HomeDir, err = base.HomeDir() if err != nil { return fmt.Errorf("Fail to get home directory: %v", err) } setting.HomeDir = strings.Replace(setting.HomeDir, "\\", "/", -1) setting.InstallRepoPath = path.Join(setting.HomeDir, ".gopm/repos") if runtime.GOOS == "windows" { setting.IsWindows = true } os.MkdirAll(setting.InstallRepoPath, os.ModePerm) log.Info("Local repository path: %s", setting.InstallRepoPath) if !setting.LibraryMode || len(setting.WorkDir) == 0 { setting.WorkDir, err = os.Getwd() if err != nil { return fmt.Errorf("Fail to get work directory: %v", err) } setting.WorkDir = strings.Replace(setting.WorkDir, "\\", "/", -1) } setting.DefaultGopmfile = path.Join(setting.WorkDir, setting.GOPMFILE) setting.DefaultVendor = path.Join(setting.WorkDir, setting.VENDOR) setting.DefaultVendorSrc = path.Join(setting.DefaultVendor, "src") if !ctx.Bool("remote") { if ctx.Bool("local") { // gf, _, _, err := genGopmfile(ctx) // if err != nil { // return err // } // setting.InstallGopath = gf.MustValue("project", "local_gopath") // if ctx.Command.Name != "gen" { // if com.IsDir(setting.InstallGopath) { // log.Log("Indicated local GOPATH: %s", setting.InstallGopath) // setting.InstallGopath += "/src" // } else { // if setting.LibraryMode { // return fmt.Errorf("Local GOPATH does not exist or is not a directory: %s", // setting.InstallGopath) // } // log.Error("", "Invalid local GOPATH path") // log.Error("", "Local GOPATH does not exist or is not a directory:") // log.Error("", "\t"+setting.InstallGopath) // log.Help("Try 'go help gopath' to get more information") // } // } } else { // Get GOPATH. setting.InstallGopath = base.GetGOPATHs()[0] if base.IsDir(setting.InstallGopath) { log.Info("Indicated GOPATH: %s", setting.InstallGopath) setting.InstallGopath += "/src" setting.HasGOPATHSetting = true } else { if ctx.Bool("gopath") { return fmt.Errorf("Local GOPATH does not exist or is not a directory: %s", setting.InstallGopath) } else { // It's OK that no GOPATH setting // when user does not specify to use. log.Warn("No GOPATH setting available") } } } } setting.ConfigFile = path.Join(setting.HomeDir, ".gopm/data/gopm.ini") if err = setting.LoadConfig(); err != nil { return err } setting.PkgNameListFile = path.Join(setting.HomeDir, ".gopm/data/pkgname.list") if err = setting.LoadPkgNameList(); err != nil { return err } setting.LocalNodesFile = path.Join(setting.HomeDir, ".gopm/data/localnodes.list") if err = setting.LoadLocalNodes(); err != nil { return err } setting.LocalizeConfigFile = path.Join(setting.HomeDir, ".gopm/data/localize.ini") if err = setting.LoadLocalize(); err != nil { return err } return nil }