Merge pull request #535 from Fugiman/resolve_vendor_dir_symlinks

Resolve vendor directory symlinks
diff --git a/path/path.go b/path/path.go
index 0b19442..0c3cee1 100644
--- a/path/path.go
+++ b/path/path.go
@@ -80,6 +80,29 @@
 
 	gopath := filepath.Join(yamldir, VendorDir)
 
+	// Resolve symlinks
+	info, err := os.Lstat(gopath)
+	if err != nil {
+		return gopath, nil
+	}
+	for i := 0; IsLink(info) && i < 255; i++ {
+		p, err := os.Readlink(gopath)
+		if err != nil {
+			return gopath, nil
+		}
+
+		if filepath.IsAbs(p) {
+			gopath = p
+		} else {
+			gopath = filepath.Join(filepath.Dir(gopath), p)
+		}
+
+		info, err = os.Lstat(gopath)
+		if err != nil {
+			return gopath, nil
+		}
+	}
+
 	return gopath, nil
 }
 
diff --git a/path/path_test.go b/path/path_test.go
index 0c8a221..77a0276 100644
--- a/path/path_test.go
+++ b/path/path_test.go
@@ -34,6 +34,7 @@
 		t.Fatal(err)
 	}
 	wd, _ := os.Getwd()
+
 	os.Chdir(filepath.Join(td, "a/b/c"))
 	res, err := Vendor()
 	if err != nil {
@@ -43,6 +44,17 @@
 	if res != expect {
 		t.Errorf("Failed to find vendor: expected %s got %s", expect, res)
 	}
+
+	os.Chdir(filepath.Join(td, "x/y/z"))
+	res, err = Vendor()
+	if err != nil {
+		t.Errorf("Failed to resolve vendor directory: %s", err)
+	}
+	expect = filepath.Join(td, "x", "symlinked_vendor")
+	if res != expect {
+		t.Errorf("Failed to find vendor: expected %s got %s", expect, res)
+	}
+
 	os.Chdir(wd)
 }
 func TestGlide(t *testing.T) {
diff --git a/path/strip.go b/path/strip.go
index 1162f38..be00be9 100644
--- a/path/strip.go
+++ b/path/strip.go
@@ -11,36 +11,36 @@
 // StripVcs removes VCS metadata (.git, .hg, .bzr, .svn) from the vendor/
 // directory.
 func StripVcs() error {
-	if _, err := os.Stat(VendorDir); err != nil {
+	searchPath, _ := Vendor()
+	if _, err := os.Stat(searchPath); err != nil {
 		if os.IsNotExist(err) {
 			msg.Debug("Vendor directory does not exist.")
 		}
 
 		return err
 	}
-	return filepath.Walk(VendorDir, stripHandler)
-}
 
-func stripHandler(path string, info os.FileInfo, err error) error {
+	return filepath.Walk(searchPath, func(path string, info os.FileInfo, err error) error {
+		name := info.Name()
+		if name == ".git" || name == ".bzr" || name == ".svn" || name == ".hg" {
+			if _, err := os.Stat(path); err == nil {
+				if info.IsDir() {
+					msg.Info("Removing: %s", path)
+					return os.RemoveAll(path)
+				}
 
-	name := info.Name()
-	if name == ".git" || name == ".bzr" || name == ".svn" || name == ".hg" {
-		if _, err := os.Stat(path); err == nil {
-			if info.IsDir() {
-				msg.Info("Removing: %s", path)
-				return os.RemoveAll(path)
+				msg.Debug("%s is not a directory. Skipping removal", path)
+				return nil
 			}
-
-			msg.Debug("%s is not a directory. Skipping removal", path)
-			return nil
 		}
-	}
-	return nil
+		return nil
+	})
 }
 
 // StripVendor removes nested vendor and Godeps/_workspace/ directories.
 func StripVendor() error {
-	if _, err := os.Stat(VendorDir); err != nil {
+	searchPath, _ := Vendor()
+	if _, err := os.Stat(searchPath); err != nil {
 		if os.IsNotExist(err) {
 			msg.Debug("Vendor directory does not exist.")
 		}
@@ -48,33 +48,29 @@
 		return err
 	}
 
-	err := filepath.Walk(VendorDir, stripVendorHandler)
+	err := filepath.Walk(searchPath, func(path string, info os.FileInfo, err error) error {
+		// Skip the base vendor directory
+		if path == searchPath {
+			return nil
+		}
+
+		name := info.Name()
+		if name == "vendor" {
+			if _, err := os.Stat(path); err == nil {
+				if info.IsDir() {
+					msg.Info("Removing: %s", path)
+					return os.RemoveAll(path)
+				}
+
+				msg.Debug("%s is not a directory. Skipping removal", path)
+				return nil
+			}
+		}
+		return nil
+	})
 	if err != nil {
 		return err
 	}
 
-	err = strip.GodepWorkspace(VendorDir)
-
-	return err
-}
-
-func stripVendorHandler(path string, info os.FileInfo, err error) error {
-	// Skip the base vendor directory
-	if path == VendorDir {
-		return nil
-	}
-
-	name := info.Name()
-	if name == "vendor" {
-		if _, err := os.Stat(path); err == nil {
-			if info.IsDir() {
-				msg.Info("Removing: %s", path)
-				return os.RemoveAll(path)
-			}
-
-			msg.Debug("%s is not a directory. Skipping removal", path)
-			return nil
-		}
-	}
-	return nil
+	return strip.GodepWorkspace(searchPath)
 }
diff --git a/path/strip_test.go b/path/strip_test.go
index 6c11194..23e9d94 100644
--- a/path/strip_test.go
+++ b/path/strip_test.go
@@ -21,36 +21,44 @@
 	}()
 
 	// Make VCS directories.
-	gp := filepath.Join(tempDir, ".git")
+	v := filepath.Join(tempDir, VendorDir)
+	err = os.Mkdir(v, 0755)
+	if err != nil {
+		t.Error(err)
+	}
+
+	gp := filepath.Join(tempDir, VendorDir, ".git")
 	err = os.Mkdir(gp, 0755)
 	if err != nil {
 		t.Error(err)
 	}
 
-	bp := filepath.Join(tempDir, ".bzr")
+	bp := filepath.Join(tempDir, VendorDir, ".bzr")
 	err = os.Mkdir(bp, 0755)
 	if err != nil {
 		t.Error(err)
 	}
 
-	hp := filepath.Join(tempDir, ".hg")
+	hp := filepath.Join(tempDir, VendorDir, ".hg")
 	err = os.Mkdir(hp, 0755)
 	if err != nil {
 		t.Error(err)
 	}
 
-	sp := filepath.Join(tempDir, ".svn")
+	sp := filepath.Join(tempDir, VendorDir, ".svn")
 	err = os.Mkdir(sp, 0755)
 	if err != nil {
 		t.Error(err)
 	}
 
-	ov := VendorDir
-	VendorDir = tempDir
+	wd, _ := os.Getwd()
+	os.Chdir(tempDir)
 
-	StripVcs()
+	if err := StripVcs(); err != nil {
+		t.Errorf("Failed to strip vcs: %s", err)
+	}
 
-	VendorDir = ov
+	os.Chdir(wd)
 
 	if _, err := os.Stat(gp); !os.IsNotExist(err) {
 		t.Error(".git directory not deleted")
diff --git a/testdata/path/x/glide.yaml b/testdata/path/x/glide.yaml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testdata/path/x/glide.yaml
diff --git a/testdata/path/x/vendor b/testdata/path/x/vendor
new file mode 120000
index 0000000..5b13353
--- /dev/null
+++ b/testdata/path/x/vendor
@@ -0,0 +1 @@
+symlinked_vendor
\ No newline at end of file
diff --git a/testdata/path/x/y/z/placeholder.empty b/testdata/path/x/y/z/placeholder.empty
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testdata/path/x/y/z/placeholder.empty