コード例 #1
0
ファイル: path.go プロジェクト: jpillora/govendor
// findImportDir finds the absolute directory. If rel is empty vendor folders
// are not looked in.
func (ctx *Context) findImportDir(relative, importPath string) (dir, gopath string, err error) {
	if importPath == "builtin" || importPath == "unsafe" || importPath == "C" {
		return filepath.Join(ctx.Goroot, importPath), ctx.Goroot, nil
	}
	if len(relative) != 0 {
		rel := relative
		for {
			look := filepath.Join(rel, ctx.VendorDiscoverFolder, importPath)
			nextRel := filepath.Join(rel, "..")
			if rel == nextRel {
				break
			}
			rel = nextRel
			fi, err := os.Stat(look)
			if os.IsNotExist(err) {
				continue
			}
			if err != nil {
				continue
			}
			if fi.IsDir() == false {
				continue
			}
			for _, gopath = range ctx.GopathList {
				if pathos.FileHasPrefix(look, gopath) {
					hasGo, err := hasGoFileInFolder(look)
					if err != nil {
						return "", "", err
					}
					if hasGo {
						return look, gopath, nil
					}
				}
			}
		}

	}
	for _, gopath = range ctx.GopathList {
		dir := filepath.Join(gopath, importPath)
		fi, err := os.Stat(dir)
		if os.IsNotExist(err) {
			continue
		}
		if fi.IsDir() == false {
			continue
		}

		hasGo, err := hasGoFileInFolder(dir)
		if err != nil {
			return "", "", err
		}
		if hasGo {
			return dir, gopath, nil
		}
		return "", "", ErrNotInGOPATH{fmt.Sprintf("Import: %q relative: %q", importPath, relative)}
	}
	return "", "", ErrNotInGOPATH{importPath}
}
コード例 #2
0
ファイル: copy.go プロジェクト: jpillora/govendor
func copyFile(destPath, srcPath string) error {
	ss, err := os.Stat(srcPath)
	if err != nil {
		return err
	}
	src, err := os.Open(srcPath)
	if err != nil {
		return err
	}
	defer src.Close()

	dest, err := os.Create(destPath)
	if err != nil {
		return err
	}

	_, err = io.Copy(dest, src)
	// Close before setting mod and time.
	dest.Close()
	if err != nil {
		return err
	}
	err = os.Chmod(destPath, ss.Mode())
	if err != nil {
		return err
	}
	return os.Chtimes(destPath, ss.ModTime(), ss.ModTime())
}
コード例 #3
0
ファイル: context.go プロジェクト: jpillora/govendor
// NewContextWD creates a new context. It looks for a root folder by finding
// a vendor file.
func NewContextWD(wdIsRoot bool) (*Context, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, err
	}
	pathToVendorFile := filepath.Join("vendor", vendorFilename)
	rootIndicator := "vendor"
	vendorFolder := "vendor"

	root := wd
	if !wdIsRoot {
		root, err = findRoot(wd, rootIndicator)
		if err != nil {
			return nil, err
		}
	}

	// Check for old vendor file location.
	oldLocation := filepath.Join(root, vendorFilename)
	if _, err := os.Stat(oldLocation); err == nil {
		return nil, ErrOldVersion{`Use the "migrate" command to update.`}
	}

	return NewContext(root, pathToVendorFile, vendorFolder, false)
}
コード例 #4
0
ファイル: hg.go プロジェクト: leeprovoost/govendor
func (VcsHg) Find(dir string) (*VcsInfo, error) {
	fi, err := os.Stat(filepath.Join(dir, ".hg"))
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}
	if fi.IsDir() == false {
		return nil, nil
	}

	// Get info.
	info := &VcsInfo{}

	cmd := exec.Command("hg", "identify", "-i")
	cmd.Dir = dir
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, err
	}
	rev := strings.TrimSpace(string(output))
	if strings.HasSuffix(rev, "+") {
		info.Dirty = true
		rev = strings.TrimSuffix(rev, "+")
	}

	cmd = exec.Command("hg", "log", "-r", rev)
	cmd.Dir = dir
	output, err = cmd.CombinedOutput()
	if err != nil {
		return nil, err
	}
	for _, line := range strings.Split(string(output), "\n") {
		if strings.HasPrefix(line, "changeset:") {
			ss := strings.Split(line, ":")
			info.Revision = strings.TrimSpace(ss[len(ss)-1])
		}
		if strings.HasPrefix(line, "date:") {
			line = strings.TrimPrefix(line, "date:")
			tm, err := time.Parse("Mon Jan 02 15:04:05 2006 -0700", strings.TrimSpace(line))
			if err == nil {
				info.RevisionTime = &tm
			}
		}
	}
	return info, nil
}
コード例 #5
0
ファイル: path.go プロジェクト: jpillora/govendor
func findRoot(folder, vendorPath string) (root string, err error) {
	for i := 0; i <= looplimit; i++ {
		test := filepath.Join(folder, vendorPath)
		_, err := os.Stat(test)
		if os.IsNotExist(err) == false {
			return folder, nil
		}
		nextFolder := filepath.Clean(filepath.Join(folder, ".."))

		// Check for root folder.
		if nextFolder == folder {
			return "", ErrMissingVendorFile{vendorPath}
		}
		folder = nextFolder
	}
	panic("findRoot loop limit")
}
コード例 #6
0
ファイル: bzr.go プロジェクト: leeprovoost/govendor
func (VcsBzr) Find(dir string) (*VcsInfo, error) {
	fi, err := os.Stat(filepath.Join(dir, ".bzr"))
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}
	if fi.IsDir() == false {
		return nil, nil
	}

	// Get info.
	info := &VcsInfo{}

	cmd := exec.Command("bzr", "status")
	cmd.Dir = dir
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, err
	}
	if string(output) != "" {
		info.Dirty = true
	}

	cmd = exec.Command("bzr", "log", "-r-1")
	cmd.Dir = dir
	output, err = cmd.CombinedOutput()
	if err != nil {
		return nil, err
	}
	for _, line := range strings.Split(string(output), "\n") {
		if strings.HasPrefix(line, "revno:") {
			info.Revision = strings.Split(strings.TrimSpace(strings.TrimPrefix(line, "revno:")), " ")[0]
		} else if strings.HasPrefix(line, "timestamp:") {
			tm, err := time.Parse("Mon 2006-01-02 15:04:05 -0700", strings.TrimSpace(strings.TrimPrefix(line, "timestamp:")))
			if err != nil {
				return nil, err
			}
			info.RevisionTime = &tm
		}
	}
	return info, nil
}
コード例 #7
0
ファイル: git.go プロジェクト: leeprovoost/govendor
func (VcsGit) Find(dir string) (*VcsInfo, error) {
	fi, err := os.Stat(filepath.Join(dir, ".git"))
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}
	if fi.IsDir() == false {
		return nil, nil
	}

	// Get info.
	info := &VcsInfo{}

	cmd := exec.Command("git", "diff", "--quiet")
	cmd.Dir = dir
	err = cmd.Run()
	if err != nil {
		info.Dirty = true
	}

	cmd = exec.Command("git", "show", "--pretty=format:%H@%ai", "-s")
	cmd.Dir = dir
	output, err := cmd.CombinedOutput()
	if err != nil {
		return nil, err
	}
	line := strings.TrimSpace(string(output))
	ss := strings.Split(line, "@")
	info.Revision = ss[0]
	tm, err := time.Parse("2006-01-02 15:04:05 -0700", ss[1])
	if err != nil {
		return nil, err
	}
	info.RevisionTime = &tm
	return info, nil
}
コード例 #8
0
ファイル: vendorFile.go プロジェクト: leeprovoost/govendor
// WriteVendorFile writes the current vendor file to the context location.
func (ctx *Context) WriteVendorFile() (err error) {
	perm := ros.FileMode(0666)
	fi, err := os.Stat(ctx.VendorFilePath)
	if err == nil {
		perm = fi.Mode()
	}

	buf := &bytes.Buffer{}
	err = ctx.VendorFile.Marshal(buf)
	if err != nil {
		return
	}
	err = buf.WriteByte('\n')
	if err != nil {
		return
	}
	dir, _ := filepath.Split(ctx.VendorFilePath)
	err = os.MkdirAll(dir, 0777)
	if err != nil {
		return
	}
	err = safefile.WriteFile(ctx.VendorFilePath, buf.Bytes(), perm)
	return
}
コード例 #9
0
ファイル: rewrite.go プロジェクト: leeprovoost/govendor
// Rewrite rewrites files to the local path.
func (ctx *Context) rewrite() error {
	if !ctx.rewriteImports {
		return nil
	}
	if ctx.dirty {
		ctx.loadPackage()
	}
	ctx.dirty = true

	fileImports := make(map[string]map[string]*File) // map[ImportPath]map[FilePath]File
	for _, pkg := range ctx.Package {
		for _, f := range pkg.Files {
			for _, imp := range f.Imports {
				fileList := fileImports[imp]
				if fileList == nil {
					fileList = make(map[string]*File, 1)
					fileImports[imp] = fileList
				}
				fileList[f.Path] = f
			}
		}
	}
	filePaths := make(map[string]*File, len(ctx.RewriteRule))
	for from, to := range ctx.RewriteRule {
		// Add files that contain an import path to rewrite.
		for _, f := range fileImports[from] {
			filePaths[f.Path] = f
		}

		// Add files that contain import comments to remove.
		if pkg := ctx.Package[from]; pkg != nil {
			for _, f := range pkg.Files {
				if len(f.ImportComment) != 0 {
					filePaths[f.Path] = f
				}
			}
		}
		if pkg := ctx.Package[to]; pkg != nil {
			for _, f := range pkg.Files {
				if len(f.ImportComment) != 0 {
					filePaths[f.Path] = f
				}
			}
		}
	}

	/*
		RULE: co2/internal/co3/pk3 -> co1/internal/co3/pk3

		i co1/internal/co2/pk2 [co2/pk2] < ["co1/pk1"]
		i co1/internal/co3/pk3 [co3/pk3] < ["co1/pk1"]
		e co2/internal/co3/pk3 [co3/pk3] < ["co1/internal/co2/pk2"]
		l co1/pk1 < []
		s strings < ["co1/internal/co3/pk3" "co2/internal/co3/pk3"]

		Rewrite the package "co1/internal/co2/pk2" because it references a package with a rewrite.from package.
	*/
	ctx.updatePackageReferences()
	for from := range ctx.RewriteRule {
		pkg := ctx.Package[from]
		if pkg == nil {
			continue
		}
		for _, ref := range pkg.referenced {
			for _, f := range ref.Files {
				dprintf("REF RW %s\n", f.Path)
				filePaths[f.Path] = f
			}
		}
	}

	defer func() {
		ctx.RewriteRule = make(map[string]string, 3)
	}()

	if len(ctx.RewriteRule) == 0 {
		return nil
	}
	goprint := &printer.Config{
		Mode:     printer.TabIndent | printer.UseSpaces,
		Tabwidth: 8,
	}
	for _, fileInfo := range filePaths {
		if pathos.FileHasPrefix(fileInfo.Path, ctx.RootDir) == false {
			continue
		}

		// Read the file into AST, modify the AST.
		fileset := token.NewFileSet()
		f, err := parser.ParseFile(fileset, fileInfo.Path, nil, parser.ParseComments)
		if err != nil {
			return err
		}

		dprintf("RW:: File: %s\n", fileInfo.Path)

		for _, impNode := range f.Imports {
			imp, err := strconv.Unquote(impNode.Path.Value)
			if err != nil {
				return err
			}
			for from, to := range ctx.RewriteRule {
				if imp != from {
					continue
				}
				impNode.Path.Value = strconv.Quote(to)
				for i, metaImport := range fileInfo.Imports {
					if from == metaImport {
						dprintf("\tImport: %s -> %s\n", from, to)
						fileInfo.Imports[i] = to
					}
				}
				break
			}
		}

		// Remove import comment.
		st := fileInfo.Package.Status
		if fileInfo.Package.inVendor || st == StatusUnused || st == StatusExternal {
			var ic *ast.Comment
			if f.Name != nil {
				pos := f.Name.Pos()
			big:
				// Find the next comment after the package name.
				for _, cblock := range f.Comments {
					for _, c := range cblock.List {
						if c.Pos() > pos {
							ic = c
							break big
						}
					}
				}
			}
			if ic != nil {
				// If it starts with the import text, assume it is the import comment and remove.
				if index := strings.Index(ic.Text, " import "); index > 0 && index < 5 {
					ic.Text = strings.Repeat(" ", len(ic.Text))
				}
			}
		}

		// Don't sort or modify the imports to minimize diffs.

		// Write the AST back to disk.
		fi, err := os.Stat(fileInfo.Path)
		if err != nil {
			return err
		}
		w, err := safefile.Create(fileInfo.Path, fi.Mode())
		if err != nil {
			return err
		}
		err = goprint.Fprint(w, fileset, f)
		if err != nil {
			w.Close()
			return err
		}
		err = w.Commit()
		if err != nil {
			return err
		}
	}
	return nil
}