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 }
func readVendorFile(vendorFilePath string) (*vendorfile.File, error) { vf := &vendorfile.File{} f, err := os.Open(vendorFilePath) if err != nil { return nil, err } defer f.Close() err = vf.Unmarshal(f) if err != nil { return nil, err } // Determine if local field is relative to GOPATH or vendor file. // Change to relative to vendor file as needed. folder, _ := filepath.Split(vendorFilePath) relToFile := 0 relToGOPATH := 0 for _, pkg := range vf.Package { p := filepath.Join(folder, pathos.SlashToFilepath(pkg.Local)) _, err := os.Stat(p) if os.IsNotExist(err) { relToGOPATH++ continue } relToFile++ } if relToFile > relToGOPATH || len(vf.Package) == 0 { return vf, nil } gopathList := strings.Split(os.Getenv("GOPATH"), string(os.PathListSeparator)) gopath := "" for _, gp := range gopathList { if pathos.FileHasPrefix(folder, gp) { gopath = gp break } } if len(gopath) == 0 { return vf, nil } prefix := pathos.SlashToImportPath(pathos.FileTrimPrefix(folder, filepath.Join(gopath, "src"))) prefix = strings.TrimPrefix(prefix, "/") for _, pkg := range vf.Package { pkg.Local = strings.TrimPrefix(pkg.Local, prefix) } return vf, 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 }
// AddImport adds the package to the context. The vendorFolder is where the // package should be added to relative to the project root. func (ctx *Context) ModifyImport(sourcePath string, mod Modify) error { var err error if !ctx.loaded || ctx.dirty { err = ctx.loadPackage() if err != nil { return err } } // Determine canonical and local import paths. sourcePath = pathos.SlashToImportPath(sourcePath) canonicalImportPath, err := ctx.findCanonicalPath(sourcePath) if err != nil { if mod != Remove { return err } if _, is := err.(ErrNotInGOPATH); !is { return err } } // If the import is already vendored, ensure we have the local path and not // the canonical path. localImportPath := sourcePath if vendPkg := ctx.VendorFilePackagePath(localImportPath); vendPkg != nil { localImportPath = path.Join(ctx.RootImportPath, ctx.RootToVendorFile, vendPkg.Path) } dprintf("AI: %s, L: %s, C: %s\n", sourcePath, localImportPath, canonicalImportPath) // Does the local import exist? // If so either update or just return. // If not find the disk path from the canonical path, copy locally and rewrite (if needed). pkg, foundPkg := ctx.Package[localImportPath] if !foundPkg { err = ctx.addSingleImport("", canonicalImportPath) if err != nil { return err } pkg, foundPkg = ctx.Package[canonicalImportPath] // Find by canonical path if stored by different local path. if !foundPkg { for _, p := range ctx.Package { if canonicalImportPath == p.Canonical { foundPkg = true pkg = p break } } } if !foundPkg { panic(fmt.Sprintf("Package %q should be listed internally but is not.", canonicalImportPath)) } } localExists, err := hasGoFileInFolder(filepath.Join(ctx.RootDir, ctx.VendorFolder, pathos.SlashToFilepath(canonicalImportPath))) if err != nil { return err } if mod == Add && localExists { return ErrPackageExists{path.Join(ctx.RootImportPath, ctx.VendorFolder, canonicalImportPath)} } switch mod { case Add: return ctx.modifyAdd(pkg) case AddUpdate: return ctx.modifyAdd(pkg) case Update: return ctx.modifyAdd(pkg) case Remove: return ctx.modifyRemove(pkg) default: panic("mod switch: case not handled") } }
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 }
// AddImport adds the package to the context. The vendorFolder is where the // package should be added to relative to the project root. func (ctx *Context) ModifyImport(sourcePath string, mod Modify) error { var err error if !ctx.loaded || ctx.dirty { err = ctx.loadPackage() if err != nil { return err } } tree := strings.HasSuffix(sourcePath, TreeSuffix) sourcePath = strings.TrimSuffix(sourcePath, TreeSuffix) // Determine canonical and local import paths. sourcePath = pathos.SlashToImportPath(sourcePath) canonicalImportPath, err := ctx.findCanonicalPath(sourcePath) if err != nil { if mod != Remove { return err } if _, is := err.(ErrNotInGOPATH); !is { return err } } // If the import is already vendored, ensure we have the local path and not // the canonical path. localImportPath := sourcePath if vendPkg := ctx.VendorFilePackagePath(localImportPath); vendPkg != nil { localImportPath = path.Join(ctx.RootImportPath, ctx.RootToVendorFile, vendPkg.Path) } dprintf("AI: %s, L: %s, C: %s\n", sourcePath, localImportPath, canonicalImportPath) // Does the local import exist? // If so either update or just return. // If not find the disk path from the canonical path, copy locally and rewrite (if needed). pkg, foundPkg := ctx.Package[localImportPath] if !foundPkg { err = ctx.addSingleImport("", canonicalImportPath) if err != nil { return err } pkg, foundPkg = ctx.Package[canonicalImportPath] // Find by canonical path if stored by different local path. if !foundPkg { for _, p := range ctx.Package { if canonicalImportPath == p.Canonical { foundPkg = true pkg = p break } } } if !foundPkg { panic(fmt.Sprintf("Package %q should be listed internally but is not.", canonicalImportPath)) } } // Do not support setting "tree" on Remove. if tree && mod != Remove { pkg.Tree = true } // A restriction where packages cannot live inside a tree package. if mod != Remove { if pkg.Tree { children := ctx.findPackageChild(pkg) if len(children) > 0 { return ErrTreeChildren{path: pkg.Canonical, children: children} } } treeParents := ctx.findPackageParentTree(pkg) if len(treeParents) > 0 { return ErrTreeParents{path: pkg.Canonical, parents: treeParents} } } // TODO (DT): figure out how to upgrade a non-tree package to a tree package with correct checks. localExists, err := hasGoFileInFolder(filepath.Join(ctx.RootDir, ctx.VendorFolder, pathos.SlashToFilepath(canonicalImportPath))) if err != nil { return err } if mod == Add && localExists { return ErrPackageExists{path.Join(ctx.RootImportPath, ctx.VendorFolder, canonicalImportPath)} } dprintf("stage 2: begin!\n") switch mod { case Add: return ctx.modifyAdd(pkg) case AddUpdate: return ctx.modifyAdd(pkg) case Update: return ctx.modifyAdd(pkg) case Remove: return ctx.modifyRemove(pkg) case Fetch: return ctx.modifyFetch(pkg) default: panic("mod switch: case not handled") } }