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