Fixed #273: Glide fails when multiple packages in same directory

Go does not allow multiple packages in the same directory. But,
some use build tags to ignore example files. We need to look at
dependencies for all OS which is why we ignore build tags by
default. When ignoring build tags if we run into an error
of multiple packages we iterate over all possible combinations
to generate the list.
diff --git a/dependency/resolver.go b/dependency/resolver.go
index 6d59ad3..394c15b 100644
--- a/dependency/resolver.go
+++ b/dependency/resolver.go
@@ -241,16 +241,29 @@
 
 		// Scan for dependencies, and anything that's not part of the local
 		// package gets added to the scan list.
+		var imps []string
 		p, err := r.BuildContext.ImportDir(path, 0)
 		if err != nil {
 			if strings.HasPrefix(err.Error(), "no buildable Go source") {
 				return nil
+			} else if strings.HasPrefix(err.Error(), "found packages ") {
+				// If we got here it's because a package and multiple packages
+				// 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)
+				if err != nil {
+					return err
+				}
+			} else {
+				return err
 			}
-			return err
+		} else {
+			imps = p.Imports
 		}
 
 		// We are only looking for dependencies in vendor. No root, cgo, etc.
-		for _, imp := range p.Imports {
+		for _, imp := range imps {
 			if alreadySeen[imp] {
 				continue
 			}
@@ -372,8 +385,20 @@
 
 		// Here, we want to import the package and see what imports it has.
 		msg.Debug("Trying to open %s", vdep)
+		var imps []string
 		pkg, err := r.BuildContext.ImportDir(vdep, 0)
-		if err != nil {
+		if err != nil && strings.HasPrefix(err.Error(), "found packages ") {
+			// If we got here it's because a package and multiple packages
+			// 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.
+			msg.Debug("Using Iterative Scanning for %s", dep)
+			imps, err = IterativeScan(vdep)
+			if err != nil {
+				msg.Err("Error scanning %s: %s", dep, err)
+				continue
+			}
+		} else if err != nil {
 			msg.Debug("ImportDir error on %s: %s", vdep, err)
 			if strings.HasPrefix(err.Error(), "no buildable Go source") {
 				msg.Debug("No subpackages declared. Skipping %s.", dep)
@@ -407,11 +432,13 @@
 				msg.Err("Error scanning %s: %s", dep, err)
 			}
 			continue
+		} else {
+			imps = pkg.Imports
 		}
 
 		// Range over all of the identified imports and see which ones we
 		// can locate.
-		for _, imp := range pkg.Imports {
+		for _, imp := range imps {
 			pi := r.FindPkg(imp)
 			if pi.Loc != LocCgo && pi.Loc != LocGoroot && pi.Loc != LocAppengine {
 				msg.Debug("Package %s imports %s", dep, imp)
@@ -618,9 +645,21 @@
 
 	// FIXME: On error this should try to NotFound to the dependency, and then import
 	// it again.
+	var imps []string
 	p, err := r.BuildContext.ImportDir(pkg, 0)
-	if err != nil {
+	if err != nil && strings.HasPrefix(err.Error(), "found packages ") {
+		// If we got here it's because a package and multiple packages
+		// 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 err != nil {
+			return []string{}, err
+		}
+	} else if err != nil {
 		return []string{}, err
+	} else {
+		imps = p.Imports
 	}
 
 	// It is okay to scan a package more than once. In some cases, this is
@@ -636,7 +675,7 @@
 
 	// We are only looking for dependencies in vendor. No root, cgo, etc.
 	buf := []string{}
-	for _, imp := range p.Imports {
+	for _, imp := range imps {
 		if r.Config.HasIgnore(imp) {
 			msg.Debug("Ignoring %s", imp)
 			continue
diff --git a/dependency/scan.go b/dependency/scan.go
new file mode 100644
index 0000000..5b99858
--- /dev/null
+++ b/dependency/scan.go
@@ -0,0 +1,71 @@
+package dependency
+
+import (
+	"strings"
+
+	"github.com/Masterminds/glide/msg"
+	"github.com/Masterminds/glide/util"
+)
+
+var osList []string
+var archList []string
+
+func init() {
+	// The supported systems are listed in
+	// https://github.com/golang/go/blob/master/src/go/build/syslist.go
+	// The lists are not exported so we need to duplicate them here.
+	osListString := "android darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris windows"
+	osList = strings.Split(osListString, " ")
+
+	archListString := "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc s390 s390x sparc sparc64"
+	archList = strings.Split(archListString, " ")
+}
+
+// IterativeScan attempts to obtain a list of imported dependencies from a
+// package. This scanning is different from ImportDir as part of the go/build
+// package. It looks over different permutations of the supported OS/Arch to
+// try and find all imports. This is different from setting UseAllFiles to
+// true on the build Context. It scopes down to just the supported OS/Arch.
+//
+// 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) {
+
+	var pkgs []string
+	for _, o := range osList {
+		for _, a := range archList {
+			b, err := util.GetBuildContext()
+			if err != nil {
+				return []string{}, err
+			}
+
+			// Make sure use all files is off
+			b.UseAllFiles = false
+
+			// Set the OS and Arch for this pass
+			b.GOARCH = a
+			b.GOOS = o
+
+			pk, err := b.ImportDir(path, 0)
+			if err != nil {
+				msg.Debug("Problem parsing package at %s for %s %s", path, o, a)
+				return []string{}, err
+			}
+
+			for _, dep := range pk.Imports {
+				found := false
+				for _, p := range pkgs {
+					if p == dep {
+						found = true
+					}
+				}
+				if !found {
+					pkgs = append(pkgs, dep)
+				}
+			}
+		}
+	}
+
+	return pkgs, nil
+}
diff --git a/tree/tree.go b/tree/tree.go
index 1be49a5..8f0a0b5 100644
--- a/tree/tree.go
+++ b/tree/tree.go
@@ -52,20 +52,33 @@
 			return nil
 		}
 
+		var imps []string
 		pkg, err := b.ImportDir(path, 0)
-		if err != nil {
+		if err != nil && strings.HasPrefix(err.Error(), "found packages ") {
+			// If we got here it's because a package and multiple packages
+			// 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)
+			if err != nil {
+				msg.Err("Error walking dependencies for %s: %s", path, err)
+				return err
+			}
+		} else if err != nil {
 			if !strings.HasPrefix(err.Error(), "no buildable Go source") {
 				msg.Warn("Error: %s (%s)", err, path)
 				// Not sure if we should return here.
 				//return err
 			}
+		} else {
+			imps = pkg.Imports
 		}
 
 		if pkg.Goroot {
 			return nil
 		}
 
-		for _, imp := range pkg.Imports {
+		for _, imp := range imps {
 			//if strings.HasPrefix(imp, myName) {
 			////Info("Skipping %s because it is a subpackage of %s", imp, myName)
 			//continue