Merge pull request #200 from jrick/subpackages

Fix example glide.yaml in README.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 64b86e1..60de65d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # Release 0.8.3 (xxxx-xx-xx)
 
+- Issue #198: Instead of stopping `glide install` for a hash failures providing
+  a warning. Failed hash check is currently too aggressive.
+- Fixed #199: `glide up` on Windows unable to detect dependencies when GOPATH
+  and GOROOT on a different drive or when GOROOT ends in a path separator.
+- Fixed #194: `glide up` stalling on Windows due to POSIX path separators and
+  path list separators being used.
 - Fixed #185 and #187: Inaccurate hash being generated for lock file with nested
   version ranges.
 - Fixed #182 and #183: Caching on go-import lookups mishandled some prefixes.
diff --git a/cmd/delete.go b/cmd/delete.go
index 709dafd..202377a 100644
--- a/cmd/delete.go
+++ b/cmd/delete.go
@@ -90,7 +90,7 @@
 	}
 
 	// Walk vendor directory
-	searchPath = vpath + "/"
+	searchPath = vpath + string(os.PathSeparator)
 	err = filepath.Walk(searchPath, fn)
 	if err != nil {
 		return false, err
diff --git a/cmd/flatten.go b/cmd/flatten.go
index a8788c3..9ae94f7 100644
--- a/cmd/flatten.go
+++ b/cmd/flatten.go
@@ -4,6 +4,7 @@
 	"io/ioutil"
 	"os"
 	"path"
+	"path/filepath"
 	"strings"
 
 	"github.com/Masterminds/cookoo"
@@ -126,7 +127,7 @@
 	Debug("---> Inspecting %s for changes (%d packages).\n", f.curr, len(f.scan))
 	for _, imp := range f.scan {
 		Debug("----> Scanning %s", imp)
-		base := path.Join(f.top, imp)
+		base := filepath.Join(f.top, filepath.FromSlash(imp))
 		mod := []string{}
 		if m, ok := mergeGlide(base, imp, f); ok {
 			mod = m
@@ -169,7 +170,7 @@
 		if imp.Name == f.conf.Name {
 			continue
 		}
-		wd := path.Join(f.top, imp.Name)
+		wd := filepath.Join(f.top, filepath.FromSlash(imp.Name))
 
 		if updateCache[imp.Name] {
 			Debug("----> Already updated %s", imp.Name)
@@ -365,7 +366,7 @@
 		} else if dd.Reference != "" && existing.Reference != "" && dd.Reference != existing.Reference {
 			// Check if one is a version and the other is a constraint. If the
 			// version is in the constraint use that.
-			dest := path.Join(vend, dd.Name)
+			dest := filepath.Join(vend, filepath.FromSlash(dd.Name))
 			repo, err := existing.GetRepo(dest)
 			if err != nil {
 				Warn("Unable to access repo for %s\n", existing.Name)
diff --git a/cmd/gb.go b/cmd/gb.go
index 35245d3..e74e6b6 100644
--- a/cmd/gb.go
+++ b/cmd/gb.go
@@ -12,7 +12,7 @@
 
 func HasGbManifest(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
 	dir := cookoo.GetString("dir", "", p)
-	path := filepath.Join(dir, "vendor/manifest")
+	path := filepath.Join(dir, "vendor", "manifest")
 	_, err := os.Stat(path)
 	return err == nil, nil
 }
@@ -29,7 +29,7 @@
 }
 
 func parseGbManifest(dir string) ([]*cfg.Dependency, error) {
-	path := filepath.Join(dir, "vendor/manifest")
+	path := filepath.Join(dir, "vendor", "manifest")
 	if fi, err := os.Stat(path); err != nil || fi.IsDir() {
 		return []*cfg.Dependency{}, nil
 	}
diff --git a/cmd/get_imports.go b/cmd/get_imports.go
index 3e70f29..8613914 100644
--- a/cmd/get_imports.go
+++ b/cmd/get_imports.go
@@ -13,7 +13,6 @@
 	//"log"
 
 	"os"
-	"path"
 	"runtime"
 	"strings"
 
@@ -145,7 +144,7 @@
 
 			// Even though skipping check if the package exists and has VCS info
 			// needed for other operations.
-			dest := path.Join(cwd, dep.Name)
+			dest := filepath.Join(cwd, filepath.FromSlash(dep.Name))
 			if _, err := os.Stat(dest); os.IsNotExist(err) {
 				Warn("Package %s not checked out to vendor/ folder", dep.Name)
 				Error("Unable to generate accurate glide.lock because %s is missing", dep.Name)
@@ -285,7 +284,7 @@
 		// Check if the $GOPATH has a viable version to use and if so copy to vendor
 		gps := Gopaths()
 		for _, p := range gps {
-			d := filepath.Join(p, "src", dep.Name)
+			d := filepath.Join(p, "src", filepath.FromSlash(dep.Name))
 			if _, err := os.Stat(d); err == nil {
 				empty, err := isDirectoryEmpty(d)
 				if empty || err != nil {
@@ -342,7 +341,7 @@
 		// Since we didn't find an existing copy in the GOPATHs try to clone there.
 		gp := Gopath()
 		if gp != "" {
-			d := filepath.Join(gp, "src", dep.Name)
+			d := filepath.Join(gp, "src", filepath.FromSlash(dep.Name))
 			if _, err := os.Stat(d); os.IsNotExist(err) {
 				// Empty directory so we checkout out the code here.
 				Debug("Retrieving %s to %s before copying to vendor", dep.Name, d)
@@ -492,7 +491,7 @@
 		return nil
 	}
 
-	dest := path.Join(vend, dep.Name)
+	dest := filepath.Join(vend, filepath.FromSlash(dep.Name))
 	// If destination doesn't exist we need to perform an initial checkout.
 	if _, err := os.Stat(dest); os.IsNotExist(err) {
 		if err = VcsGet(dep, dest, home, cache, cacheGopath, useGopath); err != nil {
@@ -599,7 +598,7 @@
 
 // VcsVersion set the VCS version for a checkout.
 func VcsVersion(dep *cfg.Dependency, vend string) error {
-	cwd := path.Join(vend, dep.Name)
+	cwd := filepath.Join(vend, filepath.FromSlash(dep.Name))
 
 	// If there is no refernece configured there is nothing to set.
 	if dep.Reference == "" {
@@ -690,7 +689,7 @@
 
 // VcsLastCommit gets the last commit ID from the given dependency.
 func VcsLastCommit(dep *cfg.Dependency, vend string) (string, error) {
-	cwd := path.Join(vend, dep.Name)
+	cwd := filepath.Join(vend, filepath.FromSlash(dep.Name))
 	repo, err := dep.GetRepo(cwd)
 	if err != nil {
 		return "", err
diff --git a/cmd/godeps.go b/cmd/godeps.go
index fc62dd7..ac12292 100644
--- a/cmd/godeps.go
+++ b/cmd/godeps.go
@@ -38,7 +38,7 @@
 // HasGodepGodeps is a command to detect if a package contains a Godeps.json file.
 func HasGodepGodeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
 	dir := cookoo.GetString("dir", "", p)
-	path := filepath.Join(dir, "Godeps/Godeps.json")
+	path := filepath.Join(dir, "Godeps", "Godeps.json")
 	_, err := os.Stat(path)
 	return err == nil, nil
 }
@@ -54,7 +54,7 @@
 	return parseGodepGodeps(dir)
 }
 func parseGodepGodeps(dir string) ([]*cfg.Dependency, error) {
-	path := filepath.Join(dir, "Godeps/Godeps.json")
+	path := filepath.Join(dir, "Godeps", "Godeps.json")
 	if _, err := os.Stat(path); err != nil {
 		return []*cfg.Dependency{}, nil
 	}
diff --git a/cmd/install.go b/cmd/install.go
index 3f58edd..ea4b86a 100644
--- a/cmd/install.go
+++ b/cmd/install.go
@@ -1,7 +1,6 @@
 package cmd
 
 import (
-	"errors"
 	"io/ioutil"
 	"os"
 	"sync"
@@ -43,7 +42,7 @@
 	}
 
 	if hash != lock.Hash {
-		return nil, errors.New("Lock file does not match YAML configuration. Consider running 'update'")
+		Warn("Lock file may be out of date. Hash check of YAML failed. You may need to run 'update'")
 	}
 
 	return lock, nil
diff --git a/cmd/rebuild.go b/cmd/rebuild.go
index a781503..07a1449 100644
--- a/cmd/rebuild.go
+++ b/cmd/rebuild.go
@@ -62,11 +62,11 @@
 
 func resolvePackages(vpath, pkg, subpkg string) ([]string, error) {
 	sdir, _ := os.Getwd()
-	if err := os.Chdir(filepath.Join(vpath, pkg, subpkg)); err != nil {
+	if err := os.Chdir(filepath.Join(vpath, filepath.FromSlash(pkg), filepath.FromSlash(subpkg))); err != nil {
 		return []string{}, err
 	}
 	defer os.Chdir(sdir)
-	p, err := filepath.Glob(path.Join(vpath, pkg, subpkg))
+	p, err := filepath.Glob(filepath.Join(vpath, filepath.FromSlash(pkg), filepath.FromSlash(subpkg)))
 	if err != nil {
 		return []string{}, err
 	}
@@ -90,7 +90,7 @@
 func buildPath(c cookoo.Context, path string) error {
 	Info("Running go build %s\n", path)
 	// . in a filepath.Join is removed so it needs to be prepended separately.
-	p := "." + string(filepath.Separator) + filepath.Join("vendor", path)
+	p := "." + string(filepath.Separator) + filepath.Join("vendor", filepath.FromSlash(path))
 	out, err := exec.Command("go", "install", p).CombinedOutput()
 	if err != nil {
 		Warn("Failed to run 'go install' for %s: %s", path, string(out))
diff --git a/cmd/tree.go b/cmd/tree.go
index 4df1205..252405e 100644
--- a/cmd/tree.go
+++ b/cmd/tree.go
@@ -195,13 +195,24 @@
 		abs = cwd
 	}
 	if abs != "." {
-		for wd := abs; wd != "/"; wd = filepath.Dir(wd) {
+
+		// Previously there was a check on the loop that wd := "/". The path
+		// "/" is a POSIX path so this fails on Windows. Now the check is to
+		// make sure the same wd isn't seen twice. When the same wd happens
+		// more than once it's the beginning of looping on the same location
+		// which is the top level.
+		pwd := ""
+		for wd := abs; wd != pwd; wd = filepath.Dir(wd) {
+			pwd = wd
 
 			// Don't look for packages outside the GOPATH
-			if wd == b.GOPATH {
+			// Note, the GOPATH may or may not end with the path separator.
+			// The output of filepath.Dir does not the the path separator on the
+			// end so we need to test both.
+			if wd == b.GOPATH || wd+string(os.PathSeparator) == b.GOPATH {
 				break
 			}
-			p = filepath.Join(wd, "vendor", name)
+			p = filepath.Join(wd, "vendor", filepath.FromSlash(name))
 			if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
 				info.Path = p
 				info.PType = ptypeVendor
@@ -211,8 +222,8 @@
 		}
 	}
 	// Check $GOPATH
-	for _, r := range strings.Split(b.GOPATH, ":") {
-		p = filepath.Join(r, "src", name)
+	for _, r := range filepath.SplitList(b.GOPATH) {
+		p = filepath.Join(r, "src", filepath.FromSlash(name))
 		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
 			info.Path = p
 			info.PType = ptypeGopath
@@ -221,8 +232,8 @@
 	}
 
 	// Check $GOROOT
-	for _, r := range strings.Split(b.GOROOT, ":") {
-		p = filepath.Join(r, "src", name)
+	for _, r := range filepath.SplitList(b.GOROOT) {
+		p = filepath.Join(r, "src", filepath.FromSlash(name))
 		if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
 			info.Path = p
 			info.PType = ptypeGoroot
diff --git a/cmd/util.go b/cmd/util.go
index 0ae85dc..6744173 100644
--- a/cmd/util.go
+++ b/cmd/util.go
@@ -5,7 +5,6 @@
 	"io"
 	"os"
 	"os/exec"
-	"path"
 	"path/filepath"
 	"strings"
 
@@ -79,7 +78,7 @@
 		return false, fmt.Errorf("No GOPATH is set.\n")
 	}
 
-	_, err := os.Stat(path.Join(gopath, "src"))
+	_, err := os.Stat(filepath.Join(gopath, "src"))
 	if err != nil {
 		Error("Could not find %s/src. The GOPATH does not appear to be properly setup.\n", gopath)
 		Info("As of Glide 0.5/Go 1.5, this is required.\n")
@@ -161,9 +160,9 @@
 
 	for _, obj := range objects {
 
-		sp := filepath.Join(source, "/", obj.Name())
+		sp := filepath.Join(source, obj.Name())
 
-		dp := filepath.Join(dest, "/", obj.Name())
+		dp := filepath.Join(dest, obj.Name())
 
 		if obj.IsDir() {
 			err = copyDir(sp, dp)
diff --git a/cmd/vendored.go b/cmd/vendored.go
index 5f1f87e..6dfbda0 100644
--- a/cmd/vendored.go
+++ b/cmd/vendored.go
@@ -2,7 +2,7 @@
 
 import (
 	"os"
-	"path"
+	"path/filepath"
 
 	"github.com/Masterminds/cookoo"
 	"github.com/Masterminds/glide/cfg"
@@ -46,7 +46,7 @@
 			Info("Cleaning up vendored package %s\n", dep.Name)
 
 			// Remove the VCS directory
-			cwd := path.Join(vend, dep.Name)
+			cwd := filepath.Join(vend, filepath.FromSlash(dep.Name))
 			repo, err := dep.GetRepo(cwd)
 			if err != nil {
 				Error("Error cleaning up %s:%s", dep.Name, err)
diff --git a/cmd/yaml.go b/cmd/yaml.go
index 33563db..f05a1e9 100644
--- a/cmd/yaml.go
+++ b/cmd/yaml.go
@@ -167,7 +167,7 @@
 	// expects remote names.
 	b, err := util.GetBuildContext()
 	if err == nil {
-		p := filepath.Join(b.GOROOT, "src", name)
+		p := filepath.Join(b.GOROOT, "src", filepath.FromSlash(name))
 		if _, err := os.Stat(p); err == nil {
 			return name, ""
 		}
diff --git a/dependency/resolver.go b/dependency/resolver.go
index 516f689..fcd4ddd 100644
--- a/dependency/resolver.go
+++ b/dependency/resolver.go
@@ -141,7 +141,7 @@
 // If basepath is set to a project's vendor path, the scanning will begin from
 // there.
 func (r *Resolver) Resolve(pkg, basepath string) ([]string, error) {
-	target := filepath.Join(basepath, pkg)
+	target := filepath.Join(basepath, filepath.FromSlash(pkg))
 	//msg.Debug("Scanning %s", target)
 	l := list.New()
 	l.PushBack(target)
@@ -190,14 +190,14 @@
 			info := r.FindPkg(imp)
 			switch info.Loc {
 			case LocUnknown, LocVendor:
-				l.PushBack(filepath.Join(r.VendorDir, imp)) // Do we need a path on this?
+				l.PushBack(filepath.Join(r.VendorDir, filepath.FromSlash(imp))) // Do we need a path on this?
 			case LocGopath:
 				if !strings.HasPrefix(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.
-					l.PushBack(filepath.Join(r.VendorDir, imp))
+					l.PushBack(filepath.Join(r.VendorDir, filepath.FromSlash(imp)))
 				}
 			}
 		}
@@ -362,7 +362,7 @@
 				msg.Error("Failed to fetch %s: %s", imp, err)
 			}
 			if found {
-				buf = append(buf, filepath.Join(r.VendorDir, imp))
+				buf = append(buf, filepath.Join(r.VendorDir, filepath.FromSlash(imp)))
 				continue
 			}
 			r.seen[info.Path] = true
@@ -378,7 +378,7 @@
 			// for subsequent processing. Otherwise, we assume that we're
 			// in a less-than-perfect, but functional, situation.
 			if found {
-				buf = append(buf, filepath.Join(r.VendorDir, imp))
+				buf = append(buf, filepath.Join(r.VendorDir, filepath.FromSlash(imp)))
 				continue
 			}
 			msg.Warn("Package %s is on GOPATH, but not vendored. Ignoring.", imp)
@@ -397,7 +397,7 @@
 func sliceToQueue(deps []*cfg.Dependency, basepath string) *list.List {
 	l := list.New()
 	for _, e := range deps {
-		l.PushBack(filepath.Join(basepath, e.Name))
+		l.PushBack(filepath.Join(basepath, filepath.FromSlash(e.Name)))
 	}
 	return l
 }
@@ -454,7 +454,7 @@
 	}
 
 	// Check _only_ if this dep is in the current vendor directory.
-	p = filepath.Join(r.VendorDir, name)
+	p = filepath.Join(r.VendorDir, filepath.FromSlash(name))
 	if pkgExists(p) {
 		info.Path = p
 		info.Loc = LocVendor
@@ -466,7 +466,7 @@
 	// TODO: Do we need this if we always flatten?
 	// Recurse backward to scan other vendor/ directories
 	//for wd := cwd; wd != "/"; wd = filepath.Dir(wd) {
-	//p = filepath.Join(wd, "vendor", name)
+	//p = filepath.Join(wd, "vendor", filepath.FromSlash(name))
 	//if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
 	//info.Path = p
 	//info.PType = ptypeVendor
@@ -476,8 +476,8 @@
 	//}
 
 	// Check $GOPATH
-	for _, rr := range strings.Split(r.BuildContext.GOPATH, ":") {
-		p = filepath.Join(rr, "src", name)
+	for _, rr := range filepath.SplitList(r.BuildContext.GOPATH) {
+		p = filepath.Join(rr, "src", filepath.FromSlash(name))
 		if pkgExists(p) {
 			info.Path = p
 			info.Loc = LocGopath
@@ -487,8 +487,8 @@
 	}
 
 	// Check $GOROOT
-	for _, rr := range strings.Split(r.BuildContext.GOROOT, ":") {
-		p = filepath.Join(rr, "src", name)
+	for _, rr := range filepath.SplitList(r.BuildContext.GOROOT) {
+		p = filepath.Join(rr, "src", filepath.FromSlash(name))
 		if pkgExists(p) {
 			info.Path = p
 			info.Loc = LocGoroot
diff --git a/glide.lock b/glide.lock
index c69198e..cd88888 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,4 +1,4 @@
-hash: 1fdfb16656a1b4a1664afdc9e2a5fc8040165bc5b6e85812df2affceacb7fbc8
+hash: foo
 updated: 2015-12-21T09:29:33.170992254-05:00
 imports:
 - name: github.com/codegangsta/cli