glide init can now construct packages and subpackages using the new resolver.
diff --git a/cmd/guess_deps.go b/cmd/guess_deps.go index 7ced3c6..3bc26ac 100644 --- a/cmd/guess_deps.go +++ b/cmd/guess_deps.go
@@ -1,13 +1,14 @@ package cmd import ( - "go/build" "os" - "path/filepath" + "sort" "strings" "github.com/Masterminds/cookoo" "github.com/Masterminds/glide/cfg" + "github.com/Masterminds/glide/dependency" + "github.com/Masterminds/glide/util" ) // GuessDeps tries to get the dependencies for the current directory. @@ -20,72 +21,46 @@ return nil, err } base := p.Get("dirname", ".").(string) - deps := make(map[string]bool) - err = findDeps(buildContext, deps, base, "") name := guessPackageName(buildContext, base) - // If there error is that no go source files were found try looking one - // level deeper. Some Go projects don't have go source files at the top - // level. - switch err.(type) { - case *build.NoGoError: - filepath.Walk(base, func(path string, fi os.FileInfo, err error) error { - if excludeSubtree(path, fi) { - top := filepath.Base(path) - if fi.IsDir() && (top == "vendor" || top == "testdata") { - return filepath.SkipDir - } - return nil - } - - pkg, err := buildContext.ImportDir(path, 0) - if err != nil { - // When there is an error we skip it and keep going. - return nil - } - - if pkg.Goroot { - return nil - } - - for _, imp := range pkg.Imports { - - // Skip subpackages of the project we're in. - if strings.HasPrefix(imp, name) { - continue - } - if imp == name { - continue - } - - found := findPkg(buildContext, imp, base) - switch found.PType { - case ptypeGoroot, ptypeCgo: - break - default: - deps[imp] = true - } - } - - return nil - }) + r, err := dependency.NewResolver(base) + if err != nil { + return nil, err } - deps = compactDeps(deps) - delete(deps, base) + h := &dependency.DefaultMissingPackageHandler{Missing: []string{}, Gopath: []string{}} + r.Handler = h + + sortable, err := r.ResolveLocal(false) + if err != nil { + return nil, err + } + + sort.Strings(sortable) Info("Generating a YAML configuration file and guessing the dependencies") config := new(cfg.Config) + vpath := r.VendorDir + if !strings.HasSuffix(vpath, "/") { + vpath = vpath + string(os.PathSeparator) + } // Get the name of the top level package config.Name = name - config.Imports = make([]*cfg.Dependency, len(deps)) + config.Imports = make([]*cfg.Dependency, len(sortable)) i := 0 - for pa := range deps { - Info("Found reference to %s\n", pa) + for _, pa := range sortable { + n := strings.TrimPrefix(pa, vpath) + Info("Found reference to %s\n", n) + root := util.GetRootFromPackage(n) + d := &cfg.Dependency{ - Name: pa, + Name: root, + } + subpkg := strings.TrimPrefix(n, root) + if len(subpkg) > 0 && subpkg != "/" { + d.Subpackages = []string{subpkg} } config.Imports[i] = d i++ @@ -94,76 +69,6 @@ return config, nil } -// findDeps finds all of the dependenices. -// https://golang.org/src/cmd/go/pkg.go#485 -// -// As of Go 1.5 the go command knows about the vendor directory but the go/build -// package does not. It only knows about the GOPATH and GOROOT. In order to look -// for packages in the vendor/ directory we need to fake it for now. -func findDeps(b *BuildCtxt, soFar map[string]bool, name, vpath string) error { - cwd, err := os.Getwd() - if err != nil { - return err - } - - // Skip cgo pseudo-package. - if name == "C" { - return nil - } - - pkg, err := b.Import(name, cwd, 0) - if err != nil { - return err - } - - if pkg.Goroot { - return nil - } - - if vpath == "" { - vpath = pkg.ImportPath - } - - // When the vendor/ directory is present make sure we strip it out before - // registering it as a guess. - realName := strings.TrimPrefix(pkg.ImportPath, vpath+"/vendor/") - - // Before adding a name to the list make sure it's not the name of the - // top level package. - lookupName, _ := NormalizeName(realName) - if vpath != lookupName { - soFar[realName] = true - } - for _, imp := range pkg.Imports { - if !soFar[imp] { - - // Try looking for a dependency as a vendor. If it's not there then - // fall back to a way where it will be found in the GOPATH or GOROOT. - if err := findDeps(b, soFar, vpath+"/vendor/"+imp, vpath); err != nil { - if err := findDeps(b, soFar, imp, vpath); err != nil { - return err - } - } - } - } - return nil -} - -// compactDeps registers only top level packages. -// -// Minimize the package imports. For example, importing github.com/Masterminds/cookoo -// and github.com/Masterminds/cookoo/io should not import two packages. Only one -// package needs to be referenced. -func compactDeps(soFar map[string]bool) map[string]bool { - basePackages := make(map[string]bool, len(soFar)) - for k := range soFar { - base, _ := NormalizeName(k) - basePackages[base] = true - } - - return basePackages -} - // Attempt to guess at the package name at the top level. When unable to detect // a name goes to default of "main". func guessPackageName(b *BuildCtxt, base string) string {