Skip to content

Commit

Permalink
Revert "Update novendor check (#145)" (#152)
Browse files Browse the repository at this point in the history
This reverts commit 26302f1.
  • Loading branch information
nmiyake committed Jun 20, 2017
1 parent b244adc commit 4380d1f
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 335 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"fmt"
"go/build"
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -122,13 +121,13 @@ func doNovendor(projectDir string, pkgPaths []string, groupPkgsByProject, fullPa
}
}

allProjectPkgs, allVendoredPkgs, err := getPackageInfo(projectDir, pkgsToProcess, groupPkgsByProject)
allProjetPkgs, allVendoredPkgs, err := getPackageInfo(projectDir, pkgsToProcess)
if err != nil {
return errors.Wrapf(err, "Failed to get package information")
}
if printPkgInfo {
projectPkgOutput := []string{fmt.Sprintf("All project packages (%d):", len(allProjectPkgs))}
for pkg := range allProjectPkgs {
projectPkgOutput := []string{fmt.Sprintf("All project packages (%d):", len(allProjetPkgs))}
for pkg := range allProjetPkgs {
projectPkgOutput = append(projectPkgOutput, pkg)
}
sort.Strings(projectPkgOutput)
Expand All @@ -142,7 +141,7 @@ func doNovendor(projectDir string, pkgPaths []string, groupPkgsByProject, fullPa
fmt.Fprintln(w, strings.Join(vendoredPkgOutput, "\n\t"))
}

unusedPkgs, err := getUnusedVendoredPkgs(allProjectPkgs, allVendoredPkgs, groupPkgsByProject, fullPath)
unusedPkgs, err := getUnusedVendoredPkgs(allProjetPkgs, allVendoredPkgs, groupPkgsByProject, fullPath)
if err != nil {
return errors.Wrapf(err, "Failed to determine unused packages")
}
Expand All @@ -154,12 +153,13 @@ func doNovendor(projectDir string, pkgPaths []string, groupPkgsByProject, fullPa
return nil
}

func getPackageInfo(projectDir string, pkgsToProcess []pkgWithSrc, groupByProject bool) (allProjectPkgs map[string]bool, allVendoredPkgs map[string]bool, err error) {
func getPackageInfo(projectDir string, pkgsToProcess []pkgWithSrc) (allProjectPkgs map[string]bool, allVendoredPkgs map[string]bool, err error) {
allProjectPkgs = make(map[string]bool)
for _, currPkg := range pkgsToProcess {
imps, err := getAllImports(currPkg.pkg, currPkg.src, projectDir, make(map[string]bool), true, groupByProject, nil)
examinedImports := make(map[string]bool)
imps, err := getAllImports(currPkg.pkg, currPkg.src, projectDir, examinedImports, true)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to get all imports for %s", currPkg.pkg)
return nil, nil, errors.Wrapf(err, "getAllFailed")
}
for k, v := range imps {
allProjectPkgs[k] = v
Expand Down Expand Up @@ -242,7 +242,7 @@ func getAllVendoredPkgs(projectRoot string) (map[string]bool, error) {
}

// directory is in a vendor directory: attempt to parse as a package
pkg, err := doImport(".", currPath, build.ImportComment, nil)
pkg, err := doImport(".", currPath, build.ImportComment)
// record import path if package could be parsed and import path is not "." (which can
// happen for some directories like testdata which cannot be imported)
if err == nil && pkg.ImportPath != "." {
Expand All @@ -258,79 +258,29 @@ func getAllVendoredPkgs(projectRoot string) (map[string]bool, error) {

// getAllImports takes an import and returns all of the packages that it imports (excluding standard library packages).
// Includes all transitive imports and the package of the import itself. Assumes that the import occurs in a package in
// "srcDir". If the "test" parameter is "true", considers all imports in the test files for the package as well. Any
// files that match the names provided in "ctxIgnoreFiles" in the import directory will be ignored.
func getAllImports(importPkgPath, srcDir, projectRoot string, examinedImports map[string]bool, includeTests, groupByProject bool, ctxIgnoreFiles map[string]struct{}) (map[string]bool, error) {
// "srcDir". If the "test" parameter is "true", considers all imports in the test files for the package as well.
func getAllImports(importPkgPath, srcDir, projectRoot string, examinedImports map[string]bool, includeTests bool) (map[string]bool, error) {
importedPkgs := make(map[string]bool)
if !strings.Contains(importPkgPath, ".") {
// if package is a standard package, return empty
return nil, nil
}

// ignore error because doImport returns partial object even on error. As long as an ImportPath is present,
// proceed with determining imports. Perform the import using the provided ctxIgnoreFiles.
pkg, pkgErr := doImport(importPkgPath, srcDir, build.ImportComment, ctxIgnoreFiles)
// proceed with determining imports.
pkg, _ := doImport(importPkgPath, srcDir, build.ImportComment)
if pkg.ImportPath == "" {
return nil, nil
}

if _, ok := pkgErr.(*build.MultiplePackageError); ok {
// Multiple packages were detected -- this is likely due to including all build constraints.
// Attempt to resolve this by parsing each set of files that form a single package together in isolation.

// create map of invalid Go files
invalidFilesMap := make(map[string]struct{})
for _, currInvalid := range pkg.InvalidGoFiles {
invalidFilesMap[currInvalid] = struct{}{}
}

// create map of Go files that were not considered invalid
validGoFiles := make(map[string]struct{})
for _, currFile := range append(append(pkg.GoFiles, pkg.TestGoFiles...), pkg.XTestGoFiles...) {
if _, ok := invalidFilesMap[currFile]; ok {
continue
}
validGoFiles[currFile] = struct{}{}
}

createIgnoreMap := func(entriesToAdd map[string]struct{}) map[string]struct{} {
allIgnore := make(map[string]struct{})
for k := range ctxIgnoreFiles {
allIgnore[k] = struct{}{}
}
for k := range entriesToAdd {
allIgnore[k] = struct{}{}
}
return allIgnore
}

// context that ignores all "invalid" files (in addition to any files that should already be ignored)
res, err := getAllImports(importPkgPath, srcDir, projectRoot, examinedImports, includeTests, groupByProject, createIgnoreMap(invalidFilesMap))
if err != nil {
return res, err
}
// this is a special case in which the same import path must be examined multiple times (the next call
// will be processing the same import path), so manually remove current import from examined imports.
delete(examinedImports, pkg.ImportPath)

// context that ignores all "valid" files (in addition to any files that should already be ignored)
res2, err := getAllImports(importPkgPath, srcDir, projectRoot, examinedImports, includeTests, groupByProject, createIgnoreMap(validGoFiles))
if err != nil {
return res2, err
}

// combine results
for k, v := range res2 {
res[k] = v
}
return res, nil
}

// skip import if package has already been examined
if examinedImports[pkg.ImportPath] {
return importedPkgs, nil
}

importedPkgs[pkg.ImportPath] = true
examinedImports[pkg.ImportPath] = true

currPkgImports := pkg.Imports
if rel, err := filepath.Rel(projectRoot, pkg.Dir); err == nil && !strings.HasPrefix(rel, "../") {
// if import is internal, update "srcDir" to be pkg.Dir to ensure that resolution is done against the
Expand All @@ -343,70 +293,15 @@ func getAllImports(importPkgPath, srcDir, projectRoot string, examinedImports ma
}
}

// if imports are being grouped by project, then for any given import, assume that all packages in the "project" are also imported
if groupByProject {
uniqueImports := make(map[string]struct{})
for _, currImportPkg := range currPkgImports {
// if import has already been examined, no need to examine again
if examinedImports[currImportPkg] {
continue
}

// perform the import on the package to determine its path on disk
currPkg, _ := doImport(currImportPkg, srcDir, build.ImportComment, nil)
if currPkg.ImportPath == "" {
continue
}

vendorPath, nonVendorFullPath := splitPathOnVendor(currPkg.Dir)
if vendorPath == "" {
// if package is not in the vendor directory, consider the package, but don't do any further expansion
uniqueImports[currPkg.ImportPath] = struct{}{}
continue
}

// determine path to "project" directory for current import in vendor directory
fullPathToCurrImportProject := path.Join(vendorPath, repoOrgProjectPath(nonVendorFullPath))

// walk the project directory and add all directories in it as an import
if err := filepath.Walk(fullPathToCurrImportProject, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
return nil
}

// determine import path to package and add as an import
_, importPath := splitPathOnVendor(path)
uniqueImports[importPath] = struct{}{}
return nil
}); err != nil {
return nil, errors.Wrapf(err, "failed to walk directory structure when grouping packages by project")
}
}

// update current package's imports being considered to be all packages in the "project" of any of the imports
currPkgImports = []string{}
for k := range uniqueImports {
currPkgImports = append(currPkgImports, k)
}
sort.Strings(currPkgImports)
}

// record current package and mark it as examined
importedPkgs[pkg.ImportPath] = true
examinedImports[pkg.ImportPath] = true

// add packages from imports (don't examine transitive test dependencies)
for _, currImport := range currPkgImports {
if examinedImports[currImport] {
continue
}

currImportedPkgs, err := getAllImports(currImport, srcDir, projectRoot, examinedImports, false, groupByProject, nil)
currImportedPkgs, err := getAllImports(currImport, srcDir, projectRoot, examinedImports, false)
if err != nil {
return nil, errors.Wrapf(err, "failed to get all imports for %s", currImport)
return nil, errors.Wrapf(err, "isExternalImport failed for %v", currImport)
}
examinedImports[currImport] = true

Expand Down Expand Up @@ -460,25 +355,6 @@ func getAllContext() build.Context {
return ctx
}

// doImport performs an "Import" operation. If "ignoreFiles" does not have any entries, it uses "allContext" to do the

// the provided map.
func doImport(path, srcDir string, mode build.ImportMode, ignoreFiles map[string]struct{}) (*build.Package, error) {
if len(ignoreFiles) == 0 {
return allContext.Import(path, srcDir, mode)
}

ctx := getAllContext()
ctx.ReadDir = func(dir string) ([]os.FileInfo, error) {
files, err := ioutil.ReadDir(dir)
var filesToReturn []os.FileInfo
for _, curr := range files {
if _, ok := ignoreFiles[curr.Name()]; ok {
continue
}
filesToReturn = append(filesToReturn, curr)
}
return filesToReturn, err
}
return ctx.Import(path, srcDir, mode)
func doImport(path, srcDir string, mode build.ImportMode) (*build.Package, error) {
return allContext.Import(path, srcDir, mode)
}
Loading

0 comments on commit 4380d1f

Please sign in to comment.