예제 #1
0
파일: resolve.go 프로젝트: fabxc/govendor
func (ctx *Context) addSingleImport(pkgInDir, imp string) error {
	if _, found := ctx.Package[imp]; found {
		return nil
	}
	// Also need to check for vendor paths that won't use the local path in import path.
	for _, pkg := range ctx.Package {
		if pkg.Canonical == imp && pkg.Status == StatusVendor {
			return nil
		}
	}
	dir, gopath, err := ctx.findImportDir(pkgInDir, imp)
	if err != nil {
		if _, is := err.(ErrNotInGOPATH); is {
			ctx.setPackage("", imp, imp, "", StatusMissing)
			return nil
		}
		return err
	}
	if pathos.FileStringEquals(gopath, ctx.Goroot) {
		ctx.setPackage(dir, imp, imp, ctx.Goroot, StatusStandard)
		return nil
	}
	df, err := os.Open(dir)
	if err != nil {
		return err
	}
	info, err := df.Readdir(-1)
	df.Close()
	if err != nil {
		return err
	}
	for _, fi := range info {
		if fi.IsDir() {
			continue
		}
		switch fi.Name()[0] {
		case '.', '_':
			continue
		}
		if pathos.FileStringEquals(dir, pkgInDir) {
			continue
		}
		path := filepath.Join(dir, fi.Name())
		err = ctx.addFileImports(path, gopath)
		if err != nil {
			return err
		}
	}
	return nil
}
예제 #2
0
파일: context.go 프로젝트: kouhin/govendor
func (ctx *Context) modifyAdd(pkg *Package) error {
	var err error
	src := pkg.Dir
	if pkg.Status == StatusVendor {
		src, _, err = ctx.findImportDir("", pkg.Canonical)
		if err != nil {
			return err
		}
	}
	dest := filepath.Join(ctx.RootDir, ctx.VendorFolder, pathos.SlashToFilepath(pkg.Canonical))
	// TODO: This might cause other issues or might be hiding the underlying issues. Examine in depth later.
	if pathos.FileStringEquals(src, dest) {
		return nil
	}
	ctx.Operation = append(ctx.Operation, &Operation{
		Pkg:  pkg,
		Src:  src,
		Dest: dest,
	})

	// Update vendor file with correct Local field.
	vp := ctx.VendorFilePackageCanonical(pkg.Canonical)
	if vp == nil {
		vp = &vendorfile.Package{
			Add:       true,
			Canonical: pkg.Canonical,
			Local:     path.Join(ctx.VendorFileToFolder, pkg.Canonical),
		}
		ctx.VendorFile.Package = append(ctx.VendorFile.Package, vp)
	}

	// Find the VCS information.
	system, err := vcs.FindVcs(pkg.Gopath, src)
	if err != nil {
		return err
	}
	if system != nil {
		if system.Dirty {
			return ErrDirtyPackage{pkg.Canonical}
		}
		vp.Revision = system.Revision
		if system.RevisionTime != nil {
			vp.RevisionTime = system.RevisionTime.Format(time.RFC3339)
		}
	}

	mvSet := make(map[*Package]struct{}, 3)
	ctx.makeSet(pkg, mvSet)

	for r := range mvSet {
		to := path.Join(ctx.RootImportPath, ctx.VendorFolder, r.Canonical)
		dprintf("RULE: %s -> %s\n", r.Local, to)
		ctx.RewriteRule[r.Local] = to
	}

	return nil
}
예제 #3
0
파일: path.go 프로젝트: fabxc/govendor
// RemovePackage removes the specified folder files. If folder is empty when
// done (no nested folders, remove the folder and any empty parent folders.
func RemovePackage(path, root string) error {
	// Ensure the path is empty of files.
	dir, err := os.Open(path)
	if err != nil {
		return err
	}

	fl, err := dir.Readdir(-1)
	dir.Close()
	if err != nil {
		return err
	}
	for _, fi := range fl {
		if fi.IsDir() {
			continue
		}
		err = os.Remove(filepath.Join(path, fi.Name()))
		if err != nil {
			return err
		}
	}

	// Ignore errors here.
	for i := 0; i <= looplimit; i++ {
		if pathos.FileStringEquals(path, root) {
			return nil
		}
		dir, err := os.Open(path)
		if err != nil {
			// fmt.Fprintf(os.Stderr, "Failedd to open directory %q: %v\n", path, err)
			return nil
		}

		fl, err := dir.Readdir(1)
		dir.Close()
		if err != nil && err != io.EOF {
			// fmt.Fprintf(os.Stderr, "Failedd to list directory %q: %v\n", path, err)
			return nil
		}
		if len(fl) > 0 {
			return nil
		}
		err = os.Remove(path)
		if err != nil {
			// fmt.Fprintf(os.Stderr, "Failedd to remove empty directory %q: %v\n", path, err)
			return nil
		}
		nextPath := filepath.Clean(filepath.Join(path, ".."))
		// Check for root.
		if nextPath == path {
			return nil
		}
		path = nextPath
	}
	panic("removePackage() remove parent folders")
}
예제 #4
0
파일: context.go 프로젝트: fabxc/govendor
func (ctx *Context) copy() error {
	// Ensure there are no conflicts at this time.
	buf := &bytes.Buffer{}
	for _, conflict := range ctx.Check() {
		buf.WriteString(fmt.Sprintf("Different Canonical Packages for %s\n", conflict.Canonical))
		for _, op := range conflict.Operation {
			buf.WriteString(fmt.Sprintf("\t%s\n", op.Pkg.Local))
		}
	}
	if buf.Len() != 0 {
		return errors.New(buf.String())
	}

	// Move and possibly rewrite packages.
	var err error
	for _, op := range ctx.Operation {
		if op.State != OpReady {
			continue
		}
		pkg := op.Pkg

		if pathos.FileStringEquals(op.Dest, op.Src) {
			panic("For package " + pkg.Local + " attempt to copy to same location: " + op.Src)
		}
		dprintf("MV: %s (%q -> %q)\n", pkg.Local, op.Src, op.Dest)
		// Copy the package or remove.
		if len(op.Dest) == 0 {
			err = RemovePackage(op.Src, filepath.Join(ctx.RootDir, ctx.VendorFolder))
		} else {
			err = CopyPackage(op.Dest, op.Src, op.IgnoreFile)
		}
		if err != nil {
			return fmt.Errorf("Failed to copy package %q -> %q: %v", op.Src, op.Dest, err)
		}
		op.State = OpDone
		ctx.dirty = true
	}
	return nil
}
예제 #5
0
// addFileImports is called from loadPackage and resolveUnknown.
func (ctx *Context) addFileImports(pathname, gopath string) error {
	dir, filenameExt := filepath.Split(pathname)
	importPath := pathos.FileTrimPrefix(dir, gopath)
	importPath = pathos.SlashToImportPath(importPath)
	importPath = strings.TrimPrefix(importPath, "/")
	importPath = strings.TrimSuffix(importPath, "/")

	if strings.HasSuffix(pathname, ".go") == false {
		return nil
	}
	// No need to add the same file more then once.
	for _, pkg := range ctx.Package {
		if pathos.FileStringEquals(pkg.Dir, dir) == false {
			continue
		}
		for _, f := range pkg.Files {
			if pathos.FileStringEquals(f.Path, pathname) {
				return nil
			}
		}
		for _, f := range pkg.ignoreFile {
			if pathos.FileStringEquals(f, filenameExt) {
				return nil
			}
		}
	}
	f, err := parser.ParseFile(token.NewFileSet(), pathname, nil, parser.ImportsOnly|parser.ParseComments)
	if err != nil {
		return err
	}

	tags, err := ctx.getFileTags(pathname, f)
	if err != nil {
		return err
	}

	pkg, found := ctx.Package[importPath]
	if !found {
		status := StatusUnknown
		if f.Name.Name == "main" {
			status = StatusProgram
		}
		pkg = ctx.setPackage(dir, importPath, importPath, gopath, status)
		ctx.Package[importPath] = pkg
	}
	if pkg.Status != StatusLocal && pkg.Status != StatusProgram {
		for _, tag := range tags {
			for _, ignore := range ctx.ignoreTag {
				if tag == ignore {
					pkg.ignoreFile = append(pkg.ignoreFile, filenameExt)
					return nil
				}
			}
		}
	}
	pf := &File{
		Package: pkg,
		Path:    pathname,
		Imports: make([]string, len(f.Imports)),
	}
	pkg.Files = append(pkg.Files, pf)
	for i := range f.Imports {
		imp := f.Imports[i].Path.Value
		imp, err = strconv.Unquote(imp)
		if err != nil {
			return err
		}
		if strings.HasPrefix(imp, "./") {
			imp = path.Join(importPath, imp)
		}
		pf.Imports[i] = imp
		err = ctx.addSingleImport(pkg.Dir, imp)
		if err != nil {
			return err
		}
	}

	// Record any import comment for file.
	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 {
			q := strings.TrimSpace(ic.Text[index+len(" import "):])
			pf.ImportComment, err = strconv.Unquote(q)
			if err != nil {
				pf.ImportComment = q
			}
		}
	}

	return nil
}
예제 #6
0
파일: copy.go 프로젝트: kouhin/govendor
// CopyPackage copies the files from the srcPath to the destPath, destPath
// folder and parents are are created if they don't already exist.
func CopyPackage(destPath, srcPath string, ignoreFiles []string) error {
	if pathos.FileStringEquals(destPath, srcPath) {
		return fmt.Errorf("Attempting to copy package to same location %q.", destPath)
	}
	err := os.MkdirAll(destPath, 0777)
	if err != nil {
		return err
	}

	// Ensure the dest is empty of files.
	destDir, err := os.Open(destPath)
	if err != nil {
		return err
	}

	fl, err := destDir.Readdir(-1)
	destDir.Close()
	if err != nil {
		return err
	}
	for _, fi := range fl {
		if fi.IsDir() {
			continue
		}
		err = os.Remove(filepath.Join(destPath, fi.Name()))
		if err != nil {
			return err
		}
	}

	// Copy files into dest.
	srcDir, err := os.Open(srcPath)
	if err != nil {
		return err
	}

	fl, err = srcDir.Readdir(-1)
	srcDir.Close()
	if err != nil {
		return err
	}
fileLoop:
	for _, fi := range fl {
		if fi.IsDir() {
			continue
		}
		if fi.Name()[0] == '.' {
			continue
		}
		for _, ignore := range ignoreFiles {
			if pathos.FileStringEquals(fi.Name(), ignore) {
				continue fileLoop
			}
		}
		err = copyFile(
			filepath.Join(destPath, fi.Name()),
			filepath.Join(srcPath, fi.Name()),
		)
		if err != nil {
			return err
		}
	}
	return nil
}
예제 #7
0
파일: copy.go 프로젝트: jpillora/govendor
// CopyPackage copies the files from the srcPath to the destPath, destPath
// folder and parents are are created if they don't already exist.
func (ctx *Context) CopyPackage(destPath, srcPath string, ignoreFiles []string, tree bool) error {
	if pathos.FileStringEquals(destPath, srcPath) {
		return fmt.Errorf("Attempting to copy package to same location %q.", destPath)
	}
	err := os.MkdirAll(destPath, 0777)
	if err != nil {
		return err
	}

	// Ensure the dest is empty of files.
	destDir, err := os.Open(destPath)
	if err != nil {
		return err
	}
	ignoreTest := false
	if tree {
		for _, ignore := range ctx.ignoreTag {
			if ignore == "test" {
				ignoreTest = true
				break
			}
		}
	}

	fl, err := destDir.Readdir(-1)
	destDir.Close()
	if err != nil {
		return err
	}
	for _, fi := range fl {
		if fi.IsDir() {
			if tree {
				err = os.RemoveAll(filepath.Join(destPath, fi.Name()))
				if err != nil {
					return err
				}
			}
			continue
		}
		err = os.Remove(filepath.Join(destPath, fi.Name()))
		if err != nil {
			return err
		}
	}

	// Copy files into dest.
	srcDir, err := os.Open(srcPath)
	if err != nil {
		return err
	}

	fl, err = srcDir.Readdir(-1)
	srcDir.Close()
	if err != nil {
		return err
	}
fileLoop:
	for _, fi := range fl {
		name := fi.Name()
		if name[0] == '.' {
			continue
		}
		if fi.IsDir() {
			if !tree {
				continue
			}
			if name[0] == '_' {
				continue
			}
			if ignoreTest {
				if strings.HasSuffix(name, "_test") || name == "testdata" {
					continue
				}
			}
			nextDestPath := filepath.Join(destPath, name)
			nextSrcPath := filepath.Join(srcPath, name)
			nextIgnoreFiles, err := ctx.getIngoreFiles(nextSrcPath)
			if err != nil {
				return err
			}

			err = ctx.CopyPackage(nextDestPath, nextSrcPath, nextIgnoreFiles, true)
			if err != nil {
				return err
			}
			continue
		}
		for _, ignore := range ignoreFiles {
			if pathos.FileStringEquals(name, ignore) {
				continue fileLoop
			}
		}
		err = copyFile(
			filepath.Join(destPath, name),
			filepath.Join(srcPath, name),
		)
		if err != nil {
			return err
		}
	}
	return nil
}
예제 #8
0
파일: context.go 프로젝트: fabxc/govendor
func (ctx *Context) modifyAdd(pkg *Package) error {
	var err error
	src := pkg.Dir
	if pkg.Status == StatusVendor {
		src, _, err = ctx.findImportDir("", pkg.Canonical)
		if err != nil {
			return err
		}
	}
	// If the canonical package is also the local package, then the package
	// isn't copied locally already and has already been checked for tags.
	// If it has been vendored the source still needs to be examined.
	// Examine here and add to the operations list.
	var ignoreFile []string
	if cpkg, found := ctx.Package[pkg.Canonical]; found {
		ignoreFile = cpkg.ignoreFile
	} else {
		srcDir, err := os.Open(src)
		if err != nil {
			return err
		}
		fl, err := srcDir.Readdir(-1)
		srcDir.Close()
		if err != nil {
			return err
		}
		for _, fi := range fl {
			if fi.IsDir() {
				continue
			}
			if fi.Name()[0] == '.' {
				continue
			}
			tags, err := ctx.getFileTags(filepath.Join(src, fi.Name()), nil)
			if err != nil {
				return err
			}

			for _, tag := range tags {
				for _, ignore := range ctx.ignoreTag {
					if tag == ignore {
						ignoreFile = append(ignoreFile, fi.Name())
					}
				}
			}
		}
	}
	dest := filepath.Join(ctx.RootDir, ctx.VendorFolder, pathos.SlashToFilepath(pkg.Canonical))
	// TODO: This might cause other issues or might be hiding the underlying issues. Examine in depth later.
	if pathos.FileStringEquals(src, dest) {
		return nil
	}
	ctx.Operation = append(ctx.Operation, &Operation{
		Pkg:        pkg,
		Src:        src,
		Dest:       dest,
		IgnoreFile: ignoreFile,
	})

	// Update vendor file with correct Local field.
	vp := ctx.VendorFilePackagePath(pkg.Canonical)
	if vp == nil {
		vp = &vendorfile.Package{
			Add:  true,
			Path: pkg.Canonical,
		}
		ctx.VendorFile.Package = append(ctx.VendorFile.Package, vp)
	}

	// Find the VCS information.
	system, err := vcs.FindVcs(pkg.Gopath, src)
	if err != nil {
		return err
	}
	if system != nil {
		if system.Dirty {
			return ErrDirtyPackage{pkg.Canonical}
		}
		vp.Revision = system.Revision
		if system.RevisionTime != nil {
			vp.RevisionTime = system.RevisionTime.Format(time.RFC3339)
		}
	}

	mvSet := make(map[*Package]struct{}, 3)
	ctx.makeSet(pkg, mvSet)

	for r := range mvSet {
		to := path.Join(ctx.RootImportPath, ctx.VendorFolder, r.Canonical)
		dprintf("RULE: %s -> %s\n", r.Local, to)
		ctx.RewriteRule[r.Canonical] = to
		ctx.RewriteRule[r.Local] = to
	}

	return nil
}
예제 #9
0
func (ctx *Context) modifyAdd(pkg *Package) error {
	var err error
	src := pkg.OriginDir
	dprintf("found import: %q\n", src)
	// If the canonical package is also the local package, then the package
	// isn't copied locally already and has already been checked for tags.
	// If it has been vendored the source still needs to be examined.
	// Examine here and add to the operations list.
	var ignoreFile []string
	if cpkg, found := ctx.Package[pkg.Canonical]; found {
		ignoreFile = cpkg.ignoreFile
	} else {
		var err error
		ignoreFile, err = ctx.getIngoreFiles(src)
		if err != nil {
			return err
		}
	}
	dest := filepath.Join(ctx.RootDir, ctx.VendorFolder, pathos.SlashToFilepath(pkg.Canonical))
	// TODO: This might cause other issues or might be hiding the underlying issues. Examine in depth later.
	if pathos.FileStringEquals(src, dest) {
		return nil
	}
	dprintf("add op: %q\n", src)
	ctx.Operation = append(ctx.Operation, &Operation{
		Pkg:        pkg,
		Src:        src,
		Dest:       dest,
		IgnoreFile: ignoreFile,
	})

	// Update vendor file with correct Local field.
	vp := ctx.VendorFilePackagePath(pkg.Canonical)
	if vp == nil {
		vp = &vendorfile.Package{
			Add:  true,
			Path: pkg.Canonical,
		}
		ctx.VendorFile.Package = append(ctx.VendorFile.Package, vp)

		if pkg.Local != pkg.Canonical && pkg.inVendor {
			vp.Origin = pkg.Local
		}
	}
	vp.Tree = pkg.Tree

	// Find the VCS information.
	system, err := vcs.FindVcs(pkg.Gopath, src)
	if err != nil {
		return err
	}
	if system != nil {
		if system.Dirty {
			return ErrDirtyPackage{pkg.Canonical}
		}
		vp.Revision = system.Revision
		if system.RevisionTime != nil {
			vp.RevisionTime = system.RevisionTime.Format(time.RFC3339)
		}
	}

	mvSet := make(map[*Package]struct{}, 3)
	ctx.makeSet(pkg, mvSet)

	for r := range mvSet {
		to := path.Join(ctx.RootImportPath, ctx.VendorFolder, r.Canonical)
		dprintf("RULE: %s -> %s\n", r.Local, to)
		ctx.RewriteRule[r.Canonical] = to
		ctx.RewriteRule[r.Local] = to
	}

	return nil
}