Merge pull request #461 from Masterminds/feat/resolve-test-imports
Resolve Test Imports
diff --git a/action/config_wizard.go b/action/config_wizard.go
index 2d774f8..1257980 100644
--- a/action/config_wizard.go
+++ b/action/config_wizard.go
@@ -51,6 +51,11 @@
deps = append(deps, dep)
}
}
+ for _, dep := range conf.DevImports {
+ if wizardLookInto(dep) {
+ deps = append(deps, dep)
+ }
+ }
msg.Info("Gathering information on each dependency")
msg.Info("--> This may take a moment. Especially on a codebase with many dependencies")
diff --git a/action/create.go b/action/create.go
index 4d1c0bb..5d42199 100644
--- a/action/create.go
+++ b/action/create.go
@@ -108,15 +108,19 @@
msg.Die("Error creating a dependency resolver: %s", err)
}
+ // When creating resolve the test dependencies as well as the application ones.
+ r.ResolveTest = true
+
h := &dependency.DefaultMissingPackageHandler{Missing: []string{}, Gopath: []string{}}
r.Handler = h
- sortable, err := r.ResolveLocal(false)
+ sortable, testSortable, err := r.ResolveLocal(false)
if err != nil {
msg.Die("Error resolving local dependencies: %s", err)
}
sort.Strings(sortable)
+ sort.Strings(testSortable)
vpath := r.VendorDir
if !strings.HasSuffix(vpath, "/") {
@@ -127,7 +131,7 @@
n := strings.TrimPrefix(pa, vpath)
root, subpkg := util.NormalizeName(n)
- if !config.HasDependency(root) && root != config.Name {
+ if !config.Imports.Has(root) && root != config.Name {
msg.Info("--> Found reference to %s\n", n)
d := &cfg.Dependency{
Name: root,
@@ -136,7 +140,7 @@
d.Subpackages = []string{subpkg}
}
config.Imports = append(config.Imports, d)
- } else if config.HasDependency(root) {
+ } else if config.Imports.Has(root) {
if len(subpkg) > 0 {
subpkg = strings.TrimPrefix(subpkg, "/")
d := config.Imports.Get(root)
@@ -148,6 +152,33 @@
}
}
+ for _, pa := range testSortable {
+ n := strings.TrimPrefix(pa, vpath)
+ root, subpkg := util.NormalizeName(n)
+
+ if config.Imports.Has(root) && root != config.Name {
+ msg.Debug("--> Found test reference to %s already listed as an import", n)
+ } else if !config.DevImports.Has(root) && root != config.Name {
+ msg.Info("--> Found test reference to %s", n)
+ d := &cfg.Dependency{
+ Name: root,
+ }
+ if len(subpkg) > 0 {
+ d.Subpackages = []string{subpkg}
+ }
+ config.DevImports = append(config.DevImports, d)
+ } else if config.DevImports.Has(root) {
+ if len(subpkg) > 0 {
+ subpkg = strings.TrimPrefix(subpkg, "/")
+ d := config.DevImports.Get(root)
+ if !d.HasSubpackage(subpkg) {
+ msg.Info("--> Adding test sub-package %s to %s\n", subpkg, root)
+ d.Subpackages = append(d.Subpackages, subpkg)
+ }
+ }
+ }
+ }
+
if len(config.Imports) == importLen && importLen != 0 {
msg.Info("--> Code scanning found no additional imports")
}
diff --git a/action/get.go b/action/get.go
index 5d4e143..5b0b72e 100644
--- a/action/get.go
+++ b/action/get.go
@@ -18,7 +18,7 @@
// Get fetches one or more dependencies and installs.
//
// This includes resolving dependency resolution and re-generating the lock file.
-func Get(names []string, installer *repo.Installer, insecure, skipRecursive, strip, stripVendor, nonInteract bool) {
+func Get(names []string, installer *repo.Installer, insecure, skipRecursive, strip, stripVendor, nonInteract, testDeps bool) {
if installer.UseCache {
cache.SystemLock()
}
@@ -33,7 +33,7 @@
}
// Add the packages to the config.
- if count, err2 := addPkgsToConfig(conf, names, insecure, nonInteract); err2 != nil {
+ if count, err2 := addPkgsToConfig(conf, names, insecure, nonInteract, testDeps); err2 != nil {
msg.Die("Failed to get new packages: %s", err2)
} else if count == 0 {
msg.Warn("Nothing to do")
@@ -43,7 +43,7 @@
// Fetch the new packages. Can't resolve versions via installer.Update if
// get is called while the vendor/ directory is empty so we checkout
// everything.
- err = installer.Checkout(conf, false)
+ err = installer.Checkout(conf)
if err != nil {
msg.Die("Failed to checkout packages: %s", err)
}
@@ -68,7 +68,7 @@
}
// Set Reference
- if err := repo.SetReference(confcopy); err != nil {
+ if err := repo.SetReference(confcopy, installer.ResolveTest); err != nil {
msg.Err("Failed to set references: %s", err)
}
@@ -112,7 +112,7 @@
if err != nil {
msg.Die("Failed to generate config hash. Unable to generate lock file.")
}
- lock := cfg.NewLockfile(confcopy.Imports, hash)
+ lock := cfg.NewLockfile(confcopy.Imports, confcopy.DevImports, hash)
if err := lock.WriteFile(filepath.Join(base, gpath.LockFile)); err != nil {
msg.Die("Failed to write glide lock file: %s", err)
}
@@ -127,7 +127,7 @@
// - separates repo from packages
// - sets up insecure repo URLs where necessary
// - generates a list of subpackages
-func addPkgsToConfig(conf *cfg.Config, names []string, insecure, nonInteract bool) (int, error) {
+func addPkgsToConfig(conf *cfg.Config, names []string, insecure, nonInteract, testDeps bool) (int, error) {
if len(names) == 1 {
msg.Info("Preparing to install %d package.", len(names))
@@ -152,17 +152,38 @@
if conf.HasDependency(root) {
+ var moved bool
+ var dep *cfg.Dependency
+ // Move from DevImports to Imports
+ if !testDeps && !conf.Imports.Has(root) && conf.DevImports.Has(root) {
+ dep = conf.DevImports.Get(root)
+ conf.Imports = append(conf.Imports, dep)
+ conf.DevImports = conf.DevImports.Remove(root)
+ moved = true
+ numAdded++
+ msg.Info("--> Moving %s from testImport to import", root)
+ } else if testDeps && conf.Imports.Has(root) {
+ msg.Warn("--> Test dependency %s already listed as import", root)
+ }
+
// Check if the subpackage is present.
if subpkg != "" {
- dep := conf.Imports.Get(root)
+ if dep == nil {
+ dep = conf.Imports.Get(root)
+ if dep == nil && testDeps {
+ dep = conf.DevImports.Get(root)
+ }
+ }
if dep.HasSubpackage(subpkg) {
- msg.Warn("--> Package %q is already in glide.yaml. Skipping", name)
+ if !moved {
+ msg.Warn("--> Package %q is already in glide.yaml. Skipping", name)
+ }
} else {
dep.Subpackages = append(dep.Subpackages, subpkg)
msg.Info("--> Adding sub-package %s to existing import %s", subpkg, root)
numAdded++
}
- } else {
+ } else if !moved {
msg.Warn("--> Package %q is already in glide.yaml. Skipping", root)
}
continue
@@ -196,10 +217,14 @@
if dep.Reference != "" {
msg.Info("--> Adding %s to your configuration with the version %s", dep.Name, dep.Reference)
} else {
- msg.Info("--> Adding %s to your configuration %s", dep.Name)
+ msg.Info("--> Adding %s to your configuration", dep.Name)
}
- conf.Imports = append(conf.Imports, dep)
+ if testDeps {
+ conf.DevImports = append(conf.DevImports, dep)
+ } else {
+ conf.Imports = append(conf.Imports, dep)
+ }
numAdded++
}
return numAdded, nil
diff --git a/action/get_test.go b/action/get_test.go
index b61490d..07dba0f 100644
--- a/action/get_test.go
+++ b/action/get_test.go
@@ -24,7 +24,7 @@
"github.com/Masterminds/semver",
}
- addPkgsToConfig(conf, names, false, true)
+ addPkgsToConfig(conf, names, false, true, false)
if !conf.HasDependency("github.com/Masterminds/semver") {
t.Error("addPkgsToConfig failed to add github.com/Masterminds/semver")
diff --git a/action/install.go b/action/install.go
index 25a5f08..3deb9d2 100644
--- a/action/install.go
+++ b/action/install.go
@@ -53,7 +53,7 @@
msg.Info("Setting references.")
// Set reference
- if err := repo.SetReference(newConf); err != nil {
+ if err := repo.SetReference(newConf, installer.ResolveTest); err != nil {
msg.Err("Failed to set references: %s (Skip to cleanup)", err)
}
diff --git a/action/list.go b/action/list.go
index 8ff6c69..f4b3379 100644
--- a/action/list.go
+++ b/action/list.go
@@ -28,7 +28,7 @@
h := &dependency.DefaultMissingPackageHandler{Missing: []string{}, Gopath: []string{}}
r.Handler = h
- localPkgs, err := r.ResolveLocal(deep)
+ localPkgs, _, err := r.ResolveLocal(deep)
if err != nil {
msg.Die("Error listing dependencies: %s", err)
}
diff --git a/action/remove.go b/action/remove.go
index bdf831b..fc305f5 100644
--- a/action/remove.go
+++ b/action/remove.go
@@ -27,7 +27,7 @@
confcopy.Imports = inst.List(confcopy)
- if err := repo.SetReference(confcopy); err != nil {
+ if err := repo.SetReference(confcopy, inst.ResolveTest); err != nil {
msg.Err("Failed to set references: %s", err)
}
diff --git a/action/update.go b/action/update.go
index 23d3f4f..cb33e63 100644
--- a/action/update.go
+++ b/action/update.go
@@ -30,13 +30,13 @@
}
// Try to check out the initial dependencies.
- if err := installer.Checkout(conf, false); err != nil {
+ if err := installer.Checkout(conf); err != nil {
msg.Die("Failed to do initial checkout of config: %s", err)
}
// Set the versions for the initial dependencies so that resolved dependencies
// are rooted in the correct version of the base.
- if err := repo.SetReference(conf); err != nil {
+ if err := repo.SetReference(conf, installer.ResolveTest); err != nil {
msg.Die("Failed to set initial config references: %s", err)
}
@@ -51,15 +51,11 @@
msg.Die("Could not update packages: %s", err)
}
- // TODO: There is no support here for importing Godeps, GPM, and GB files.
- // I think that all we really need to do now is hunt for these files, and then
- // roll their version numbers into the config file.
-
// Set references. There may be no remaining references to set since the
// installer set them as it went to make sure it parsed the right imports
// from the right version of the package.
msg.Info("Setting references for remaining imports")
- if err := repo.SetReference(confcopy); err != nil {
+ if err := repo.SetReference(confcopy, installer.ResolveTest); err != nil {
msg.Err("Failed to set references: %s (Skip to cleanup)", err)
}
}
@@ -90,7 +86,7 @@
if err != nil {
msg.Die("Failed to generate config hash. Unable to generate lock file.")
}
- lock := cfg.NewLockfile(confcopy.Imports, hash)
+ lock := cfg.NewLockfile(confcopy.Imports, confcopy.DevImports, hash)
wl := true
if gpath.HasLock(base) {
yml, err := ioutil.ReadFile(filepath.Join(base, gpath.LockFile))
diff --git a/cfg/config.go b/cfg/config.go
index afeed9a..4b24fca 100644
--- a/cfg/config.go
+++ b/cfg/config.go
@@ -51,7 +51,7 @@
// DevImports contains the test or other development imports for a project.
// See the Dependency type for more details on how this is recorded.
- DevImports Dependencies `yaml:"devimport,omitempty"`
+ DevImports Dependencies `yaml:"testImport,omitempty"`
}
// A transitive representation of a dependency for importing and exporting to yaml.
@@ -64,7 +64,7 @@
Ignore []string `yaml:"ignore,omitempty"`
Exclude []string `yaml:"excludeDirs,omitempty"`
Imports Dependencies `yaml:"import"`
- DevImports Dependencies `yaml:"devimport,omitempty"`
+ DevImports Dependencies `yaml:"testImport,omitempty"`
}
// ConfigFromYaml returns an instance of Config from YAML
@@ -298,6 +298,33 @@
return nil
}
+// Has checks if a dependency is on a list of dependencies such as import or devimport
+func (d Dependencies) Has(name string) bool {
+ for _, dep := range d {
+ if dep.Name == name {
+ return true
+ }
+ }
+ return false
+}
+
+// Remove removes a dependency from a list of dependencies
+func (d Dependencies) Remove(name string) Dependencies {
+ found := -1
+ for i, dep := range d {
+ if dep.Name == name {
+ found = i
+ }
+ }
+
+ if found >= 0 {
+ copy(d[found:], d[found+1:])
+ d[len(d)-1] = nil
+ return d[:len(d)-1]
+ }
+ return d
+}
+
// Clone performs a deep clone of Dependencies
func (d Dependencies) Clone() Dependencies {
n := make(Dependencies, 0, len(d))
diff --git a/cfg/lock.go b/cfg/lock.go
index 517d3ba..2b2c4c8 100644
--- a/cfg/lock.go
+++ b/cfg/lock.go
@@ -15,7 +15,7 @@
Hash string `yaml:"hash"`
Updated time.Time `yaml:"updated"`
Imports Locks `yaml:"imports"`
- DevImports Locks `yaml:"devImports"`
+ DevImports Locks `yaml:"testImports"`
}
// LockfileFromYaml returns an instance of Lockfile from YAML
@@ -131,11 +131,12 @@
}
// NewLockfile is used to create an instance of Lockfile.
-func NewLockfile(ds Dependencies, hash string) *Lockfile {
+func NewLockfile(ds, tds Dependencies, hash string) *Lockfile {
lf := &Lockfile{
- Hash: hash,
- Updated: time.Now(),
- Imports: make([]*Lock, len(ds)),
+ Hash: hash,
+ Updated: time.Now(),
+ Imports: make([]*Lock, len(ds)),
+ DevImports: make([]*Lock, len(tds)),
}
for i := 0; i < len(ds); i++ {
@@ -152,6 +153,20 @@
sort.Sort(lf.Imports)
+ for i := 0; i < len(tds); i++ {
+ lf.DevImports[i] = &Lock{
+ Name: tds[i].Name,
+ Version: tds[i].Pin,
+ Repository: tds[i].Repository,
+ VcsType: tds[i].VcsType,
+ Subpackages: tds[i].Subpackages,
+ Arch: tds[i].Arch,
+ Os: tds[i].Os,
+ }
+ }
+
+ sort.Sort(lf.DevImports)
+
return lf
}
diff --git a/dependency/resolver.go b/dependency/resolver.go
index 473209a..06dd2dc 100644
--- a/dependency/resolver.go
+++ b/dependency/resolver.go
@@ -31,7 +31,7 @@
// When it returns false with no error, this indicates that the handler did
// its job, but the resolver should not do any additional work on the
// package.
- NotFound(pkg string) (bool, error)
+ NotFound(pkg string, addTest bool) (bool, error)
// OnGopath is called when the Resolver finds a dependency, but it's only on GOPATH.
//
@@ -45,12 +45,12 @@
//
// An error indicates that OnGopath cannot complete its intended operation.
// Not all false results are errors.
- OnGopath(pkg string) (bool, error)
+ OnGopath(pkg string, addTest bool) (bool, error)
// InVendor is called when the Resolver finds a dependency in the vendor/ directory.
//
// This can be used update a project found in the vendor/ folder.
- InVendor(pkg string) error
+ InVendor(pkg string, addTest bool) error
}
// DefaultMissingPackageHandler is the default handler for missing packages.
@@ -65,21 +65,21 @@
// NotFound prints a warning and then stores the package name in Missing.
//
// It never returns an error, and it always returns false.
-func (d *DefaultMissingPackageHandler) NotFound(pkg string) (bool, error) {
+func (d *DefaultMissingPackageHandler) NotFound(pkg string, addTest bool) (bool, error) {
msg.Warn("Package %s is not installed", pkg)
d.Missing = append(d.Missing, pkg)
return false, nil
}
// OnGopath is run when a package is missing from vendor/ but found in the GOPATH
-func (d *DefaultMissingPackageHandler) OnGopath(pkg string) (bool, error) {
+func (d *DefaultMissingPackageHandler) OnGopath(pkg string, addTest bool) (bool, error) {
msg.Warn("Package %s is only on GOPATH.", pkg)
d.Gopath = append(d.Gopath, pkg)
return false, nil
}
// InVendor is run when a package is found in the vendor/ folder
-func (d *DefaultMissingPackageHandler) InVendor(pkg string) error {
+func (d *DefaultMissingPackageHandler) InVendor(pkg string, addTest bool) error {
msg.Info("Package %s found in vendor/ folder", pkg)
return nil
}
@@ -96,7 +96,7 @@
// SetVersion sets the version for a package. An error is returned if there
// was a problem setting the version.
- SetVersion(pkg string) error
+ SetVersion(pkg string, testDep bool) error
}
// DefaultVersionHandler is the default handler for setting the version.
@@ -113,7 +113,7 @@
// SetVersion here sends a message when a package is found noting that it
// did not set the version.
-func (d *DefaultVersionHandler) SetVersion(pkg string) error {
+func (d *DefaultVersionHandler) SetVersion(pkg string, testDep bool) error {
msg.Warn("Version not set for package %s", pkg)
return nil
}
@@ -139,6 +139,9 @@
// import tree.
ResolveAllFiles bool
+ // ResolveTest sets if test dependencies should be resolved.
+ ResolveTest bool
+
// Items already in the queue.
alreadyQ map[string]bool
@@ -220,9 +223,9 @@
// In this mode, walk the entire tree.
if r.ResolveAllFiles {
- return r.resolveList(l)
+ return r.resolveList(l, false, false)
}
- return r.resolveImports(l)
+ return r.resolveImports(l, false, false)
}
// dirHasPrefix tests whether the directory dir begins with prefix.
@@ -240,12 +243,14 @@
// If the deep flag is set to true, this will then resolve all of the dependencies
// of the dependencies it has found. If not, it will return just the packages that
// the base project relies upon.
-func (r *Resolver) ResolveLocal(deep bool) ([]string, error) {
+func (r *Resolver) ResolveLocal(deep bool) ([]string, []string, error) {
// We build a list of local source to walk, then send this list
// to resolveList.
msg.Debug("Resolving local dependencies")
l := list.New()
+ tl := list.New()
alreadySeen := map[string]bool{}
+ talreadySeen := map[string]bool{}
err := filepath.Walk(r.basedir, func(path string, fi os.FileInfo, err error) error {
if err != nil && err != filepath.SkipDir {
return err
@@ -266,6 +271,7 @@
// Scan for dependencies, and anything that's not part of the local
// package gets added to the scan list.
var imps []string
+ var testImps []string
p, err := r.BuildContext.ImportDir(path, 0)
if err != nil {
if strings.HasPrefix(err.Error(), "no buildable Go source") {
@@ -275,7 +281,7 @@
// declared. This is often because of an example with a package
// or main but +build ignore as a build tag. In that case we
// try to brute force the packages with a slower scan.
- imps, err = IterativeScan(path)
+ imps, testImps, err = IterativeScan(path)
if err != nil {
return err
}
@@ -284,6 +290,7 @@
}
} else {
imps = p.Imports
+ testImps = p.TestImports
}
// We are only looking for dependencies in vendor. No root, cgo, etc.
@@ -314,19 +321,55 @@
}
}
+ if r.ResolveTest {
+ for _, imp := range testImps {
+ if talreadySeen[imp] {
+ continue
+ }
+ talreadySeen[imp] = true
+ info := r.FindPkg(imp)
+ switch info.Loc {
+ case LocUnknown, LocVendor:
+ tl.PushBack(filepath.Join(r.VendorDir, filepath.FromSlash(imp))) // Do we need a path on this?
+ case LocGopath:
+ if !dirHasPrefix(info.Path, r.basedir) {
+ // FIXME: This is a package outside of the project we're
+ // scanning. It should really be on vendor. But we don't
+ // want it to reference GOPATH. We want it to be detected
+ // and moved.
+ tl.PushBack(filepath.Join(r.VendorDir, filepath.FromSlash(imp)))
+ }
+ case LocRelative:
+ if strings.HasPrefix(imp, "./"+gpath.VendorDir) {
+ msg.Warn("Go package resolving will resolve %s without the ./%s/ prefix", imp, gpath.VendorDir)
+ }
+ }
+ }
+ }
+
return nil
})
if err != nil {
msg.Err("Failed to build an initial list of packages to scan: %s", err)
- return []string{}, err
+ return []string{}, []string{}, err
}
if deep {
if r.ResolveAllFiles {
- return r.resolveList(l)
+ re, err := r.resolveList(l, false, false)
+ if err != nil {
+ return []string{}, []string{}, err
+ }
+ tre, err := r.resolveList(l, false, true)
+ return re, tre, err
}
- return r.resolveImports(l)
+ re, err := r.resolveImports(l, false, false)
+ if err != nil {
+ return []string{}, []string{}, err
+ }
+ tre, err := r.resolveImports(tl, true, true)
+ return re, tre, err
}
// If we're not doing a deep scan, we just convert the list into an
@@ -335,7 +378,14 @@
for e := l.Front(); e != nil; e = e.Next() {
res = append(res, e.Value.(string))
}
- return res, nil
+ tres := make([]string, 0, l.Len())
+ if r.ResolveTest {
+ for e := tl.Front(); e != nil; e = e.Next() {
+ tres = append(tres, e.Value.(string))
+ }
+ }
+
+ return res, tres, nil
}
// ResolveAll takes a list of packages and returns an inclusive list of all
@@ -350,31 +400,18 @@
//
// If one of the passed in packages does not exist in the vendor directory,
// an error is returned.
-func (r *Resolver) ResolveAll(deps []*cfg.Dependency) ([]string, error) {
- var queue *list.List
- if r.ResolveAllFiles {
- queue = sliceToQueue(deps, r.VendorDir)
- } else {
- queue = list.New()
- }
+func (r *Resolver) ResolveAll(deps []*cfg.Dependency, addTest bool) ([]string, error) {
- loc, err := r.ResolveLocal(false)
- if err != nil {
- return []string{}, err
- }
- for _, l := range loc {
- msg.Debug("Adding local Import %s to queue", l)
- queue.PushBack(l)
- }
+ queue := sliceToQueue(deps, r.VendorDir)
if r.ResolveAllFiles {
- return r.resolveList(queue)
+ return r.resolveList(queue, false, addTest)
}
- return r.resolveImports(queue)
+ return r.resolveImports(queue, false, addTest)
}
-// stripv strips the vendor/ prefix from vendored packages.
-func (r *Resolver) stripv(str string) string {
+// Stripv strips the vendor/ prefix from vendored packages.
+func (r *Resolver) Stripv(str string) string {
return strings.TrimPrefix(str, r.VendorDir+string(os.PathSeparator))
}
@@ -395,14 +432,25 @@
//
// The resolver's handler is used in the cases where a package cannot be
// located.
-func (r *Resolver) resolveImports(queue *list.List) ([]string, error) {
+//
+// testDeps specifies if the test dependencies should be resolved and addTest
+// specifies if the dependencies should be added to the Config.DevImports. This
+// is important because we may resolve normal dependencies of test deps and add
+// them to the DevImports list.
+func (r *Resolver) resolveImports(queue *list.List, testDeps, addTest bool) ([]string, error) {
msg.Debug("Resolving import path")
+
+ // When test deps passed in but not resolving return empty.
+ if (testDeps || addTest) && !r.ResolveTest {
+ return []string{}, nil
+ }
+
for e := queue.Front(); e != nil; e = e.Next() {
vdep := e.Value.(string)
- dep := r.stripv(vdep)
-
+ dep := r.Stripv(vdep)
// Check if marked in the Q and then explicitly mark it. We want to know
// if it had previously been marked and ensure it for the future.
+
_, foundQ := r.alreadyQ[dep]
r.alreadyQ[dep] = true
@@ -419,7 +467,6 @@
continue
}
r.VersionHandler.Process(dep)
-
// Here, we want to import the package and see what imports it has.
msg.Debug("Trying to open %s", vdep)
var imps []string
@@ -430,7 +477,12 @@
// or main but +build ignore as a build tag. In that case we
// try to brute force the packages with a slower scan.
msg.Debug("Using Iterative Scanning for %s", dep)
- imps, err = IterativeScan(vdep)
+ if testDeps {
+ _, imps, err = IterativeScan(vdep)
+ } else {
+ imps, _, err = IterativeScan(vdep)
+ }
+
if err != nil {
msg.Err("Iterative scanning error %s: %s", dep, err)
continue
@@ -448,13 +500,13 @@
// not to get stuck in a recursion.
// If the location doesn't exist try to fetch it.
- if ok, err2 := r.Handler.NotFound(dep); ok {
+ if ok, err2 := r.Handler.NotFound(dep, addTest); ok {
r.alreadyQ[dep] = true
// By adding to the queue it will get reprocessed now that
// it exists.
queue.PushBack(r.vpath(dep))
- r.VersionHandler.SetVersion(dep)
+ r.VersionHandler.SetVersion(dep, addTest)
} else if err2 != nil {
r.hadError[dep] = true
msg.Err("Error looking for %s: %s", dep, err2)
@@ -470,7 +522,12 @@
}
continue
} else {
- imps = pkg.Imports
+ if testDeps {
+ imps = pkg.TestImports
+ } else {
+ imps = pkg.Imports
+ }
+
}
// Range over all of the identified imports and see which ones we
@@ -489,20 +546,20 @@
msg.Debug("In vendor: %s", imp)
if _, ok := r.alreadyQ[imp]; !ok {
msg.Debug("Marking %s to be scanned.", imp)
- r.alreadyQ[imp] = true
+ r.alreadyQ[dep] = true
queue.PushBack(r.vpath(imp))
- if err := r.Handler.InVendor(imp); err == nil {
- r.VersionHandler.SetVersion(imp)
+ if err := r.Handler.InVendor(imp, addTest); err == nil {
+ r.VersionHandler.SetVersion(imp, addTest)
} else {
msg.Warn("Error updating %s: %s", imp, err)
}
}
case LocUnknown:
msg.Debug("Missing %s. Trying to resolve.", imp)
- if ok, err := r.Handler.NotFound(imp); ok {
- r.alreadyQ[imp] = true
+ if ok, err := r.Handler.NotFound(imp, addTest); ok {
+ r.alreadyQ[dep] = true
queue.PushBack(r.vpath(imp))
- r.VersionHandler.SetVersion(imp)
+ r.VersionHandler.SetVersion(imp, addTest)
} else if err != nil {
r.hadError[dep] = true
msg.Warn("Error looking for %s: %s", imp, err)
@@ -514,10 +571,10 @@
msg.Debug("Found on GOPATH, not vendor: %s", imp)
if _, ok := r.alreadyQ[imp]; !ok {
// Only scan it if it gets moved into vendor/
- if ok, _ := r.Handler.OnGopath(imp); ok {
- r.alreadyQ[imp] = true
+ if ok, _ := r.Handler.OnGopath(imp, addTest); ok {
+ r.alreadyQ[dep] = true
queue.PushBack(r.vpath(imp))
- r.VersionHandler.SetVersion(imp)
+ r.VersionHandler.SetVersion(imp, addTest)
}
}
}
@@ -530,7 +587,7 @@
// In addition to generating a list
for e := queue.Front(); e != nil; e = e.Next() {
- t := r.stripv(e.Value.(string))
+ t := r.Stripv(e.Value.(string))
root, sp := util.NormalizeName(t)
// Skip ignored packages
@@ -541,6 +598,9 @@
// TODO(mattfarina): Need to eventually support devImport
existing := r.Config.Imports.Get(root)
+ if existing == nil && addTest {
+ existing = r.Config.DevImports.Get(root)
+ }
if existing != nil {
if sp != "" && !existing.HasSubpackage(sp) {
existing.Subpackages = append(existing.Subpackages, sp)
@@ -553,7 +613,11 @@
newDep.Subpackages = []string{sp}
}
- r.Config.Imports = append(r.Config.Imports, newDep)
+ if addTest {
+ r.Config.DevImports = append(r.Config.DevImports, newDep)
+ } else {
+ r.Config.Imports = append(r.Config.Imports, newDep)
+ }
}
res = append(res, t)
}
@@ -566,7 +630,11 @@
// This walks the entire file tree for the given dependencies, not just the
// parts that are imported directly. Using this will discover dependencies
// regardless of OS, and arch.
-func (r *Resolver) resolveList(queue *list.List) ([]string, error) {
+func (r *Resolver) resolveList(queue *list.List, testDeps, addTest bool) ([]string, error) {
+ // When test deps passed in but not resolving return empty.
+ if testDeps && !r.ResolveTest {
+ return []string{}, nil
+ }
var failedDep string
for e := queue.Front(); e != nil; e = e.Next() {
@@ -599,7 +667,7 @@
// Anything that comes through here has already been through
// the queue.
r.alreadyQ[path] = true
- e := r.queueUnseen(path, queue)
+ e := r.queueUnseen(path, queue, testDeps, addTest)
if err != nil {
failedDep = path
//msg.Err("Failed to fetch dependency %s: %s", path, err)
@@ -619,8 +687,11 @@
t := strings.TrimPrefix(e.Value.(string), r.VendorDir+string(os.PathSeparator))
root, sp := util.NormalizeName(t)
- // TODO(mattfarina): Need to eventually support devImport
existing := r.Config.Imports.Get(root)
+ if existing == nil && addTest {
+ existing = r.Config.DevImports.Get(root)
+ }
+
if existing != nil {
if sp != "" && !existing.HasSubpackage(sp) {
existing.Subpackages = append(existing.Subpackages, sp)
@@ -633,7 +704,11 @@
newDep.Subpackages = []string{sp}
}
- r.Config.Imports = append(r.Config.Imports, newDep)
+ if addTest {
+ r.Config.DevImports = append(r.Config.DevImports, newDep)
+ } else {
+ r.Config.Imports = append(r.Config.Imports, newDep)
+ }
}
res = append(res, e.Value.(string))
}
@@ -643,7 +718,7 @@
// queueUnseenImports scans a package's imports and adds any new ones to the
// processing queue.
-func (r *Resolver) queueUnseen(pkg string, queue *list.List) error {
+func (r *Resolver) queueUnseen(pkg string, queue *list.List, testDeps, addTest bool) error {
// A pkg is marked "seen" as soon as we have inspected it the first time.
// Seen means that we have added all of its imports to the list.
@@ -651,7 +726,7 @@
// or intentionally not put it in the queue for fatal reasons (e.g. no
// buildable source).
- deps, err := r.imports(pkg)
+ deps, err := r.imports(pkg, testDeps, addTest)
if err != nil && !strings.HasPrefix(err.Error(), "no buildable Go source") {
msg.Err("Could not find %s: %s", pkg, err)
return err
@@ -676,7 +751,7 @@
// If the package is in GOROOT, this will return an empty list (but not
// an error).
// If it cannot resolve the pkg, it will return an error.
-func (r *Resolver) imports(pkg string) ([]string, error) {
+func (r *Resolver) imports(pkg string, testDeps, addTest bool) ([]string, error) {
if r.Config.HasIgnore(pkg) {
msg.Debug("Ignoring %s", pkg)
@@ -698,14 +773,23 @@
// declared. This is often because of an example with a package
// or main but +build ignore as a build tag. In that case we
// try to brute force the packages with a slower scan.
- imps, err = IterativeScan(pkg)
+ if testDeps {
+ _, imps, err = IterativeScan(pkg)
+ } else {
+ imps, _, err = IterativeScan(pkg)
+ }
+
if err != nil {
return []string{}, err
}
} else if err != nil {
return []string{}, err
} else {
- imps = p.Imports
+ if testDeps {
+ imps = p.TestImports
+ } else {
+ imps = p.Imports
+ }
}
// It is okay to scan a package more than once. In some cases, this is
@@ -730,26 +814,26 @@
switch info.Loc {
case LocUnknown:
// Do we resolve here?
- found, err := r.Handler.NotFound(imp)
+ found, err := r.Handler.NotFound(imp, addTest)
if err != nil {
msg.Err("Failed to fetch %s: %s", imp, err)
}
if found {
buf = append(buf, filepath.Join(r.VendorDir, filepath.FromSlash(imp)))
- r.VersionHandler.SetVersion(imp)
+ r.VersionHandler.SetVersion(imp, addTest)
continue
}
r.seen[info.Path] = true
case LocVendor:
//msg.Debug("Vendored: %s", imp)
buf = append(buf, info.Path)
- if err := r.Handler.InVendor(imp); err == nil {
- r.VersionHandler.SetVersion(imp)
+ if err := r.Handler.InVendor(imp, addTest); err == nil {
+ r.VersionHandler.SetVersion(imp, addTest)
} else {
msg.Warn("Error updating %s: %s", imp, err)
}
case LocGopath:
- found, err := r.Handler.OnGopath(imp)
+ found, err := r.Handler.OnGopath(imp, addTest)
if err != nil {
msg.Err("Failed to fetch %s: %s", imp, err)
}
@@ -758,7 +842,7 @@
// in a less-than-perfect, but functional, situation.
if found {
buf = append(buf, filepath.Join(r.VendorDir, filepath.FromSlash(imp)))
- r.VersionHandler.SetVersion(imp)
+ r.VersionHandler.SetVersion(imp, addTest)
continue
}
msg.Warn("Package %s is on GOPATH, but not vendored. Ignoring.", imp)
@@ -777,7 +861,20 @@
func sliceToQueue(deps []*cfg.Dependency, basepath string) *list.List {
l := list.New()
for _, e := range deps {
- l.PushBack(filepath.Join(basepath, filepath.FromSlash(e.Name)))
+ if len(e.Subpackages) > 0 {
+ for _, v := range e.Subpackages {
+ ip := e.Name
+ if v != "." && v != "" {
+ ip = ip + "/" + v
+ }
+ msg.Debug("Adding local Import %s to queue", ip)
+ l.PushBack(filepath.Join(basepath, filepath.FromSlash(ip)))
+ }
+ } else {
+ msg.Debug("Adding local Import %s to queue", e.Name)
+ l.PushBack(filepath.Join(basepath, filepath.FromSlash(e.Name)))
+ }
+
}
return l
}
diff --git a/dependency/resolver_test.go b/dependency/resolver_test.go
index bb455c2..1867cee 100644
--- a/dependency/resolver_test.go
+++ b/dependency/resolver_test.go
@@ -15,7 +15,7 @@
t.Fatal(err)
}
- l, err := r.ResolveLocal(false)
+ l, _, err := r.ResolveLocal(false)
if err != nil {
t.Fatalf("Failed to resolve: %s", err)
}
@@ -47,7 +47,7 @@
t.Fatal(err)
}
- l, err := r.ResolveLocal(true)
+ l, _, err := r.ResolveLocal(true)
if err != nil {
t.Fatalf("Failed to resolve: %s", err)
}
@@ -91,7 +91,7 @@
if err != nil {
t.Fatalf("No new resolver: %s", err)
}
- l, err := r.ResolveAll(deps)
+ l, err := r.ResolveAll(deps, false)
if err != nil {
t.Fatalf("Failed to resolve: %s", err)
}
diff --git a/dependency/scan.go b/dependency/scan.go
index c1bad5c..71f4865 100644
--- a/dependency/scan.go
+++ b/dependency/scan.go
@@ -35,7 +35,7 @@
// Note, there are cases where multiple packages are in the same directory. This
// usually happens with an example that has a main package and a +build tag
// of ignore. This is a bit of a hack. It causes UseAllFiles to have errors.
-func IterativeScan(path string) ([]string, error) {
+func IterativeScan(path string) ([]string, []string, error) {
// TODO(mattfarina): Add support for release tags.
@@ -44,6 +44,7 @@
tgs = append(tgs, "")
var pkgs []string
+ var testPkgs []string
for _, tt := range tgs {
// split the tag combination to look at permutations.
@@ -84,7 +85,7 @@
b, err := util.GetBuildContext()
if err != nil {
- return []string{}, err
+ return []string{}, []string{}, err
}
// Make sure use all files is off
@@ -110,7 +111,7 @@
continue
} else if err != nil {
msg.Debug("Problem parsing package at %s for %s %s", path, ops, arch)
- return []string{}, err
+ return []string{}, []string{}, err
}
for _, dep := range pk.Imports {
@@ -124,9 +125,21 @@
pkgs = append(pkgs, dep)
}
}
+
+ for _, dep := range pk.TestImports {
+ found := false
+ for _, p := range pkgs {
+ if p == dep {
+ found = true
+ }
+ }
+ if !found {
+ testPkgs = append(testPkgs, dep)
+ }
+ }
}
- return pkgs, nil
+ return pkgs, testPkgs, nil
}
func readBuildTags(p string) ([]string, error) {
diff --git a/docs/glide.yaml.md b/docs/glide.yaml.md
index 3aba801..1b87990 100644
--- a/docs/glide.yaml.md
+++ b/docs/glide.yaml.md
@@ -44,4 +44,4 @@
- `subpackages`: A record of packages being used within a repository. This does not include all packages within a repository but rather those being used.
- `os`: A list of operating systems used for filtering. If set it will compare the current runtime OS to the one specified and only fetch the dependency if there is a match. If not set filtering is skipped. The names are the same used in build flags and `GOOS` environment variable.
- `arch`: A list of architectures used for filtering. If set it will compare the current runtime architecture to the one specified and only fetch the dependency if there is a match. If not set filtering is skipped. The names are the same used in build flags and `GOARCH` environment variable.
-- `devImport`: A list of development packages. Each package has the same details as those listed under import.
+- `testImport`: A list of packages used in tests that are not already listed in `import`. Each package has the same details as those listed under import.
diff --git a/glide.go b/glide.go
index 61b6e2b..1190885 100644
--- a/glide.go
+++ b/glide.go
@@ -203,6 +203,10 @@
folder.`,
Flags: []cli.Flag{
cli.BoolFlag{
+ Name: "test",
+ Usage: "Add test dependencies.",
+ },
+ cli.BoolFlag{
Name: "insecure",
Usage: "Use http:// rather than https:// to retrieve pacakges.",
},
@@ -250,6 +254,10 @@
Name: "non-interactive",
Usage: "Disable interactive prompts.",
},
+ cli.BoolFlag{
+ Name: "skip-test",
+ Usage: "Resolve dependencies in test files.",
+ },
},
Action: func(c *cli.Context) {
if c.Bool("strip-vendor") && !c.Bool("strip-vcs") {
@@ -273,9 +281,10 @@
inst.UseCacheGopath = c.Bool("cache-gopath")
inst.UpdateVendored = c.Bool("update-vendored")
inst.ResolveAllFiles = c.Bool("all-dependencies")
+ inst.ResolveTest = !c.Bool("skip-test")
packages := []string(c.Args())
insecure := c.Bool("insecure")
- action.Get(packages, inst, insecure, c.Bool("no-recursive"), c.Bool("strip-vcs"), c.Bool("strip-vendor"), c.Bool("non-interactive"))
+ action.Get(packages, inst, insecure, c.Bool("no-recursive"), c.Bool("strip-vcs"), c.Bool("strip-vendor"), c.Bool("non-interactive"), c.Bool("test"))
},
},
{
@@ -456,6 +465,10 @@
Name: "strip-vendor, v",
Usage: "Removes nested vendor and Godeps/_workspace directories. Requires --strip-vcs.",
},
+ cli.BoolFlag{
+ Name: "skip-test",
+ Usage: "Resolve dependencies in test files.",
+ },
},
Action: func(c *cli.Context) {
if c.Bool("strip-vendor") && !c.Bool("strip-vcs") {
@@ -470,6 +483,7 @@
installer.UpdateVendored = c.Bool("update-vendored")
installer.Home = c.GlobalString("home")
installer.DeleteUnused = c.Bool("delete")
+ installer.ResolveTest = !c.Bool("skip-test")
action.Install(installer, c.Bool("strip-vcs"), c.Bool("strip-vendor"))
},
@@ -563,6 +577,10 @@
Name: "strip-vendor, v",
Usage: "Removes nested vendor and Godeps/_workspace directories. Requires --strip-vcs.",
},
+ cli.BoolFlag{
+ Name: "skip-test",
+ Usage: "Resolve dependencies in test files.",
+ },
},
Action: func(c *cli.Context) {
if c.Bool("strip-vendor") && !c.Bool("strip-vcs") {
@@ -583,6 +601,7 @@
installer.ResolveAllFiles = c.Bool("all-dependencies")
installer.Home = c.GlobalString("home")
installer.DeleteUnused = c.Bool("delete")
+ installer.ResolveTest = !c.Bool("skip-test")
action.Update(installer, c.Bool("no-recursive"), c.Bool("strip-vcs"), c.Bool("strip-vendor"))
},
diff --git a/glide.lock b/glide.lock
index 8bb73d6..572094a 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,5 +1,5 @@
hash: ebc39e5b2036ba2235316f2897fb9f2e696c6a7d5389416812722cc8ed3dfa21
-updated: 2016-05-05T09:44:44.751721442-04:00
+updated: 2016-06-10T16:27:29.24243625-04:00
imports:
- name: github.com/codegangsta/cli
version: 71f57d300dd6a780ac1856c005c4b518cfd498ec
@@ -9,4 +9,4 @@
version: 7af28b64c5ec41b1558f5514fd938379822c237c
- name: gopkg.in/yaml.v2
version: a83829b6f1293c91addabc89d0571c246397bbf4
-devImports: []
+testImports: []
diff --git a/repo/installer.go b/repo/installer.go
index 1469042..6f4b2d0 100644
--- a/repo/installer.go
+++ b/repo/installer.go
@@ -51,6 +51,9 @@
// packages.
ResolveAllFiles bool
+ // ResolveTest sets if test dependencies should be resolved.
+ ResolveTest bool
+
// Updated tracks the packages that have been remotely fetched.
Updated *UpdateTracker
}
@@ -121,6 +124,8 @@
return newConf, nil
}
+ msg.Info("Downloading dependencies. Please wait...")
+
ConcurrentUpdate(newConf.Imports, cwd, i, newConf)
ConcurrentUpdate(newConf.DevImports, cwd, i, newConf)
return newConf, nil
@@ -130,15 +135,17 @@
//
// This is used when initializing an empty vendor directory, or when updating a
// vendor directory based on changed config.
-func (i *Installer) Checkout(conf *cfg.Config, useDev bool) error {
+func (i *Installer) Checkout(conf *cfg.Config) error {
dest := i.VendorPath()
+ msg.Info("Downloading dependencies. Please wait...")
+
if err := ConcurrentUpdate(conf.Imports, dest, i, conf); err != nil {
return err
}
- if useDev {
+ if i.ResolveTest {
return ConcurrentUpdate(conf.DevImports, dest, i, conf)
}
@@ -182,6 +189,7 @@
// Update imports
res, err := dependency.NewResolver(base)
+ res.ResolveTest = i.ResolveTest
if err != nil {
msg.Die("Failed to create a resolver: %s", err)
}
@@ -190,18 +198,81 @@
res.VersionHandler = v
res.ResolveAllFiles = i.ResolveAllFiles
msg.Info("Resolving imports")
- _, err = allPackages(conf.Imports, res)
+
+ imps, timps, err := res.ResolveLocal(false)
+ if err != nil {
+ msg.Die("Failed to resolve local packages: %s", err)
+ }
+ var deps cfg.Dependencies
+ var tdeps cfg.Dependencies
+ for _, v := range imps {
+ n := res.Stripv(v)
+ rt, sub := util.NormalizeName(n)
+ if sub == "" {
+ sub = "."
+ }
+ d := deps.Get(rt)
+ if d == nil {
+ nd := &cfg.Dependency{
+ Name: rt,
+ Subpackages: []string{sub},
+ }
+ deps = append(deps, nd)
+ } else if !d.HasSubpackage(sub) {
+ d.Subpackages = append(d.Subpackages, sub)
+ }
+ }
+ if i.ResolveTest {
+ for _, v := range timps {
+ n := res.Stripv(v)
+ rt, sub := util.NormalizeName(n)
+ if sub == "" {
+ sub = "."
+ }
+ d := deps.Get(rt)
+ if d == nil {
+ d = tdeps.Get(rt)
+ }
+ if d == nil {
+ nd := &cfg.Dependency{
+ Name: rt,
+ Subpackages: []string{sub},
+ }
+ tdeps = append(tdeps, nd)
+ } else if !d.HasSubpackage(sub) {
+ d.Subpackages = append(d.Subpackages, sub)
+ }
+ }
+ }
+
+ _, err = allPackages(deps, res, false)
if err != nil {
msg.Die("Failed to retrieve a list of dependencies: %s", err)
}
- if len(conf.DevImports) > 0 {
- msg.Warn("dev imports not resolved.")
+ if i.ResolveTest {
+ msg.Debug("Resolving test dependencies")
+ _, err = allPackages(tdeps, res, true)
+ if err != nil {
+ msg.Die("Failed to retrieve a list of test dependencies: %s", err)
+ }
}
- err = ConcurrentUpdate(conf.Imports, vpath, i, conf)
+ msg.Info("Downloading dependencies. Please wait...")
- return err
+ err = ConcurrentUpdate(conf.Imports, vpath, i, conf)
+ if err != nil {
+ return err
+ }
+
+ if i.ResolveTest {
+ err = ConcurrentUpdate(conf.DevImports, vpath, i, conf)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
}
// List resolves the complete dependency tree and returns a list of dependencies.
@@ -229,7 +300,12 @@
res.ResolveAllFiles = i.ResolveAllFiles
msg.Info("Resolving imports")
- _, err = allPackages(conf.Imports, res)
+ _, _, err = res.ResolveLocal(false)
+ if err != nil {
+ msg.Die("Failed to resolve local packages: %s", err)
+ }
+
+ _, err = allPackages(conf.Imports, res, false)
if err != nil {
msg.Die("Failed to retrieve a list of dependencies: %s", err)
}
@@ -249,8 +325,6 @@
var lock sync.Mutex
var returnErr error
- msg.Info("Downloading dependencies. Please wait...")
-
for ii := 0; ii < concurrentWorkers; ii++ {
go func(ch <-chan *cfg.Dependency) {
for {
@@ -307,7 +381,7 @@
}
// allPackages gets a list of all packages required to satisfy the given deps.
-func allPackages(deps []*cfg.Dependency, res *dependency.Resolver) ([]string, error) {
+func allPackages(deps []*cfg.Dependency, res *dependency.Resolver, addTest bool) ([]string, error) {
if len(deps) == 0 {
return []string{}, nil
}
@@ -317,7 +391,7 @@
return []string{}, err
}
vdir += string(os.PathSeparator)
- ll, err := res.ResolveAll(deps)
+ ll, err := res.ResolveAll(deps, addTest)
if err != nil {
return []string{}, err
}
@@ -344,9 +418,8 @@
// NotFound attempts to retrieve a package when not found in the local vendor/
// folder. It will attempt to get it from the remote location info.
-func (m *MissingPackageHandler) NotFound(pkg string) (bool, error) {
+func (m *MissingPackageHandler) NotFound(pkg string, addTest bool) (bool, error) {
root := util.GetRootFromPackage(pkg)
-
// Skip any references to the root package.
if root == m.Config.Name {
return false, nil
@@ -379,6 +452,10 @@
msg.Info("Fetching %s into %s", pkg, m.destination)
d := m.Config.Imports.Get(root)
+ if d == nil && addTest {
+ d = m.Config.DevImports.Get(root)
+ }
+
// If the dependency is nil it means the Config doesn't yet know about it.
if d == nil {
d, _ = m.Use.Get(root)
@@ -386,8 +463,11 @@
if d == nil {
d = &cfg.Dependency{Name: root}
}
-
- m.Config.Imports = append(m.Config.Imports, d)
+ if addTest {
+ m.Config.DevImports = append(m.Config.DevImports, d)
+ } else {
+ m.Config.Imports = append(m.Config.Imports, d)
+ }
}
if err := VcsGet(d, dest, m.home, m.cache, m.cacheGopath, m.useGopath); err != nil {
return false, err
@@ -398,11 +478,11 @@
// OnGopath will either copy a package, already found in the GOPATH, to the
// vendor/ directory or download it from the internet. This is dependent if
// useGopath on the installer is set to true to copy from the GOPATH.
-func (m *MissingPackageHandler) OnGopath(pkg string) (bool, error) {
+func (m *MissingPackageHandler) OnGopath(pkg string, addTest bool) (bool, error) {
// If useGopath is false, we fall back to the strategy of fetching from
// remote.
if !m.useGopath {
- return m.NotFound(pkg)
+ return m.NotFound(pkg, addTest)
}
root := util.GetRootFromPackage(pkg)
@@ -435,9 +515,8 @@
// InVendor updates a package in the vendor/ directory to make sure the latest
// is available.
-func (m *MissingPackageHandler) InVendor(pkg string) error {
+func (m *MissingPackageHandler) InVendor(pkg string, addTest bool) error {
root := util.GetRootFromPackage(pkg)
-
// Skip any references to the root package.
if root == m.Config.Name {
return nil
@@ -446,6 +525,10 @@
dest := filepath.Join(m.destination, root)
d := m.Config.Imports.Get(root)
+ if d == nil && addTest {
+ d = m.Config.DevImports.Get(root)
+ }
+
// If the dependency is nil it means the Config doesn't yet know about it.
if d == nil {
d, _ = m.Use.Get(root)
@@ -454,7 +537,11 @@
d = &cfg.Dependency{Name: root}
}
- m.Config.Imports = append(m.Config.Imports, d)
+ if addTest {
+ m.Config.DevImports = append(m.Config.DevImports, d)
+ } else {
+ m.Config.Imports = append(m.Config.Imports, d)
+ }
}
if err := VcsUpdate(d, dest, m.home, m.cache, m.cacheGopath, m.useGopath, m.force, m.updateVendored, m.updated); err != nil {
@@ -524,7 +611,7 @@
// - keeping the already set version
// - proviting messaging about the version conflict
// TODO(mattfarina): The way version setting happens can be improved. Currently not optimal.
-func (d *VersionHandler) SetVersion(pkg string) (e error) {
+func (d *VersionHandler) SetVersion(pkg string, addTest bool) (e error) {
root := util.GetRootFromPackage(pkg)
// Skip any references to the root package.
@@ -533,6 +620,20 @@
}
v := d.Config.Imports.Get(root)
+ if addTest {
+ if v == nil {
+ v = d.Config.DevImports.Get(root)
+ } else if d.Config.DevImports.Has(root) {
+ // Both imports and test imports lists the same dependency.
+ // There are import chains (because the import tree is resolved
+ // before the test tree) that can cause this.
+ tempD := d.Config.DevImports.Get(root)
+ if tempD.Reference != v.Reference {
+ msg.Warn("Using import %s (version %s) for test instead of testImport (version %s).", v.Name, v.Reference, tempD.Reference)
+ }
+ // TODO(mattfarina): Note repo difference in a warning.
+ }
+ }
dep, req := d.Use.Get(root)
if dep != nil && v != nil {
@@ -553,7 +654,11 @@
} else if dep != nil {
// We've got an imported dependency to use and don't already have a
// record of it. Append it to the Imports.
- d.Config.Imports = append(d.Config.Imports, dep)
+ if addTest {
+ d.Config.DevImports = append(d.Config.DevImports, dep)
+ } else {
+ d.Config.Imports = append(d.Config.Imports, dep)
+ }
} else {
// If we've gotten here we don't have any depenency objects.
r, sp := util.NormalizeName(pkg)
@@ -563,7 +668,11 @@
if sp != "" {
dep.Subpackages = []string{sp}
}
- d.Config.Imports = append(d.Config.Imports, dep)
+ if addTest {
+ d.Config.DevImports = append(d.Config.DevImports, dep)
+ } else {
+ d.Config.Imports = append(d.Config.Imports, dep)
+ }
}
err := VcsVersion(dep, d.Destination)
diff --git a/repo/set_reference.go b/repo/set_reference.go
index 2856b89..4363459 100644
--- a/repo/set_reference.go
+++ b/repo/set_reference.go
@@ -10,14 +10,14 @@
// SetReference is a command to set the VCS reference (commit id, tag, etc) for
// a project.
-func SetReference(conf *cfg.Config) error {
+func SetReference(conf *cfg.Config, resolveTest bool) error {
cwd, err := gpath.Vendor()
if err != nil {
return err
}
- if len(conf.Imports) == 0 {
+ if len(conf.Imports) == 0 && len(conf.DevImports) == 0 {
msg.Info("No references set.\n")
return nil
}
@@ -49,6 +49,15 @@
}
}
+ if resolveTest {
+ for _, dep := range conf.DevImports {
+ if !conf.HasIgnore(dep.Name) {
+ wg.Add(1)
+ in <- dep
+ }
+ }
+ }
+
wg.Wait()
// Close goroutines setting the version
for i := 0; i < concurrentWorkers; i++ {
diff --git a/repo/vcs.go b/repo/vcs.go
index b2d471f..31bed50 100644
--- a/repo/vcs.go
+++ b/repo/vcs.go
@@ -36,7 +36,7 @@
}
updated.Add(dep.Name)
- msg.Info("Fetching updates for %s.\n", dep.Name)
+ msg.Info("--> Fetching updates for %s.", dep.Name)
if filterArchOs(dep) {
msg.Info("%s is not used for %s/%s.\n", dep.Name, runtime.GOOS, runtime.GOARCH)
@@ -207,7 +207,7 @@
// If there is a ^ prefix we assume it's a semver constraint rather than
// part of the git/VCS commit id.
if repo.IsReference(ver) && !strings.HasPrefix(ver, "^") {
- msg.Info("Setting version for %s to %s.\n", dep.Name, ver)
+ msg.Info("--> Setting version for %s to %s.\n", dep.Name, ver)
} else {
// Create the constraing first to make sure it's valid before
@@ -242,9 +242,9 @@
}
}
if found {
- msg.Info("Detected semantic version. Setting version for %s to %s.\n", dep.Name, ver)
+ msg.Info("--> Detected semantic version. Setting version for %s to %s.", dep.Name, ver)
} else {
- msg.Warn("Unable to find semantic version for constraint %s %s\n", dep.Name, ver)
+ msg.Warn("--> Unable to find semantic version for constraint %s %s", dep.Name, ver)
}
}
if err := repo.UpdateVersion(ver); err != nil {
diff --git a/tree/tree.go b/tree/tree.go
index 5b19336..0dc3df7 100644
--- a/tree/tree.go
+++ b/tree/tree.go
@@ -59,7 +59,7 @@
// declared. This is often because of an example with a package
// or main but +build ignore as a build tag. In that case we
// try to brute force the packages with a slower scan.
- imps, err = dependency.IterativeScan(path)
+ imps, _, err = dependency.IterativeScan(path)
if err != nil {
msg.Err("Error walking dependencies for %s: %s", path, err)
return err