示例#1
0
文件: list.go 项目: Huangsir/gopm
// getDepList get list of dependencies in root path format and nature order.
func getDepList(ctx *cli.Context, target, pkgPath, vendor string) ([]string, error) {
	vendorSrc := path.Join(vendor, "src")
	rootPath := doc.GetRootPath(target)
	// If work directory is not in GOPATH, then need to setup a vendor path.
	if !setting.HasGOPATHSetting || !strings.HasPrefix(pkgPath, setting.InstallGopath) {
		// Make link of self.
		log.Debug("Linking %s...", rootPath)
		from := pkgPath
		to := path.Join(vendorSrc, rootPath)
		if setting.Debug {
			log.Debug("Linking from %s to %s", from, to)
		}
		if err := autoLink(from, to); err != nil {
			return nil, err
		}
	}

	imports, err := doc.ListImports(target, rootPath, vendor, pkgPath, ctx.String("tags"), ctx.Bool("test"))
	if err != nil {
		return nil, err
	}

	list := make([]string, 0, len(imports))
	for _, name := range imports {
		name = doc.GetRootPath(name)
		if !base.IsSliceContainsStr(list, name) {
			list = append(list, name)
		}
	}
	sort.Strings(list)
	return list, nil
}
示例#2
0
文件: utils.go 项目: Huangsir/gopm
// ListImports checks and returns a list of imports of given import path and options.
func ListImports(importPath, rootPath, vendorPath, srcPath, tags string, isTest bool) ([]string, error) {
	oldGOPATH := os.Getenv("GOPATH")
	sep := ":"
	if runtime.GOOS == "windows" {
		sep = ";"
	}

	ctxt := build.Default
	ctxt.BuildTags = strings.Split(tags, " ")
	ctxt.GOPATH = vendorPath + sep + oldGOPATH
	if setting.Debug {
		log.Debug("Import/root path: %s : %s", importPath, rootPath)
		log.Debug("Context GOPATH: %s", ctxt.GOPATH)
		log.Debug("Source path: %s", srcPath)
	}
	pkg, err := ctxt.Import(importPath, srcPath, build.AllowBinary)
	if err != nil {
		if _, ok := err.(*build.NoGoError); !ok && importPath != "C" {
			//import "C" is cgo
			return nil, fmt.Errorf("fail to get imports(%s): %v", importPath, err)
		}
		log.Warn("Getting imports: %v", err)
	}

	rawImports := pkg.Imports
	numImports := len(rawImports)
	if isTest {
		rawImports = append(rawImports, pkg.TestImports...)
		numImports = len(rawImports)
	}
	imports := make([]string, 0, numImports)
	for _, name := range rawImports {
		if IsGoRepoPath(name) {
			continue
		} else if strings.HasPrefix(name, rootPath) {
			moreImports, err := ListImports(name, rootPath, vendorPath, srcPath, tags, isTest)
			if err != nil {
				return nil, err
			}
			imports = append(imports, moreImports...)
			continue
		}
		if setting.Debug {
			log.Debug("Found dependency: %s", name)
		}
		imports = append(imports, name)
	}
	return imports, nil
}
示例#3
0
文件: struct.go 项目: Huangsir/gopm
func (n *Node) DownloadByGoGet(ctx *cli.Context, u *url.URL) error {
	baseDir := path.Join(setting.HomeDir, ".gopm/temp/goget")
	os.MkdirAll(baseDir, os.ModePerm)
	defer func() {
		os.RemoveAll(baseDir)
	}()

	oriGopath := os.Getenv("GOPATH")
	os.Setenv("GOPATH", baseDir)
	fmt.Println(baseDir)
	defer func() {
		os.Setenv("GOPATH", oriGopath)
	}()

	log.Debug("RUN 'go get %s'", n.RootPath)
	_, stderr, err := base.ExecCmdDir(baseDir, "go", "get", n.RootPath)
	if err != nil {
		log.Error("Error occurs when 'go get" + n.RootPath + "'")
		log.Error("\t" + stderr)
		return errors.New(stderr)
	}
	tmpPath := path.Join(baseDir, "src", n.RootPath)
	if !n.IsEmptyVal() {
		base.ExecCmdDir(tmpPath, "git", "checkout", n.Value)
		if err != nil {
			log.Error("Error occurs when 'git checkout" + n.Value + "'")
			log.Error("\t" + stderr)
			return errors.New(stderr)
		}
	}
	os.MkdirAll(path.Dir(n.InstallPath), os.ModePerm)
	os.Rename(tmpPath, n.InstallPath)
	return nil
}
示例#4
0
文件: get.go 项目: Huangsir/gopm
// downloadPackage downloads package either use version control tools or not.
func downloadPackage(ctx *cli.Context, n *doc.Node) (*doc.Node, []string, error) {

	// fmt.Println(n.VerString())
	log.Info("Downloading package: %s", n.VerString())
	downloadCache.Set(n.VerString())

	vendor := base.GetTempDir()
	defer os.RemoveAll(vendor)

	var (
		err     error
		imports []string
		srcPath string
	)

	// Check if only need to use VCS tools.
	vcs := doc.GetVcsName(n.InstallGopath)
	// If update, gopath and VCS tools set then use VCS tools to update the package.
	if ctx.Bool("update") && (ctx.Bool("gopath") || ctx.Bool("local")) && len(vcs) > 0 {
		if err = n.UpdateByVcs(vcs); err != nil {
			return nil, nil, fmt.Errorf("fail to update by VCS(%s): %v", n.ImportPath, err)
		}
		srcPath = n.InstallGopath
	} else {
		if !n.IsGetDepsOnly || !n.IsExist() {
			// Get revision value from local records.
			n.Revision = setting.LocalNodes.MustValue(n.RootPath, "value")
			if err = n.DownloadGopm(ctx); err != nil {
				errors.AppendError(errors.NewErrDownload(n.ImportPath + ": " + err.Error()))
				failConut++
				os.RemoveAll(n.InstallPath)
				return nil, nil, nil
			}
		}
		srcPath = n.InstallPath
	}

	if n.IsGetDeps {
		imports, err = getDepList(ctx, n.ImportPath, srcPath, vendor)
		if err != nil {
			return nil, nil, fmt.Errorf("fail to list imports(%s): %v", n.ImportPath, err)
		}
		if setting.Debug {
			log.Debug("New imports: %v", imports)
		}
	}
	return n, imports, err
}
示例#5
0
文件: get.go 项目: Huangsir/gopm
// 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(target string, ctx *cli.Context, nodes []*doc.Node) (err error) {
	for _, n := range nodes {
		// Check if it is a valid remote path or C.
		if n.ImportPath == "C" {
			continue
		} else if !base.IsValidRemotePath(n.ImportPath) {
			// Invalid import path.
			if setting.LibraryMode {
				errors.AppendError(errors.NewErrInvalidPackage(n.VerString()))
			}
			log.Error("Skipped invalid package: " + n.VerString())
			failConut++
			continue
		}

		// Valid import path.
		if isSubpackage(n.RootPath, target) {
			continue
		}

		// Indicates whether need to download package or update.
		if n.IsFixed() && n.IsExist() {
			n.IsGetDepsOnly = true
		}

		if downloadCache.Get(n.VerString()) {
			if !skipCache.Get(n.VerString()) {
				skipCache.Set(n.VerString())
				log.Debug("Skipped downloaded package: %s", n.VerString())
			}
			continue
		}

		if !ctx.Bool("update") {
			// Check if package has been downloaded.
			if n.IsExist() {
				if !skipCache.Get(n.VerString()) {
					skipCache.Set(n.VerString())
					log.Info("%s", n.InstallPath)
					log.Debug("Skipped installed package: %s", n.VerString())
				}

				// Only copy when no version control.
				if !copyCache.Get(n.VerString()) && (ctx.Bool("gopath") || ctx.Bool("local")) {
					copyCache.Set(n.VerString())
					if err = n.CopyToGopath(); err != nil {
						return err
					}
				}
				continue
			} else {
				setting.LocalNodes.SetValue(n.RootPath, "value", "")
			}
		}
		// Download package.
		nod, imports, err := downloadPackage(ctx, n)
		if err != nil {
			return err
		}
		for _, name := range imports {
			var gf *goconfig.ConfigFile
			gfPath := path.Join(n.InstallPath, setting.GOPMFILE)

			// Check if has gopmfile.
			if base.IsFile(gfPath) {
				log.Info("Found gopmfile: %s", n.VerString())
				var err error
				gf, _, err = parseGopmfile(gfPath)
				if err != nil {
					return fmt.Errorf("fail to parse gopmfile(%s): %v", gfPath, err)
				}
			}

			// Need to download dependencies.
			// Generate temporary nodes.
			nodes := make([]*doc.Node, len(imports))
			for i := range nodes {
				nodes[i] = doc.NewNode(name, doc.BRANCH, "", "", !ctx.Bool("download"))

				if gf == nil {
					continue
				}

				// Check if user specified the version.
				if v := gf.MustValue("deps", imports[i]); len(v) > 0 {
					nodes[i].Type, nodes[i].Value, nodes[i].DownloadURL, err = validPkgInfo(v)
					if err != nil {
						return err
					}
				}
			}
			if err = downloadPackages(target, ctx, nodes); err != nil {
				return err
			}
		}

		// Only save package information with specific commit.
		if nod == nil {
			continue
		}

		// Save record in local nodes.
		log.Info("Got %s", n.VerString())
		downloadCount++

		// Only save non-commit node.
		if nod.IsEmptyVal() && len(nod.Revision) > 0 {
			setting.LocalNodes.SetValue(nod.RootPath, "value", nod.Revision)
		}

		// If update set downloadPackage will use VSC tools to download the package,
		// else just download to local repository and copy to GOPATH.
		if !nod.HasVcs() && !copyCache.Get(n.RootPath) && (ctx.Bool("gopath") || ctx.Bool("local")) {
			copyCache.Set(n.RootPath)
			if err = nod.CopyToGopath(); err != nil {
				return err
			}
		}
	}
	return nil
}
示例#6
0
文件: struct.go 项目: Huangsir/gopm
// 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
}