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 }
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 }
// 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") }
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 }
// 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 }
// 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 }
// 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 }
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 }
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 }