Merge pull request #699 from sdboyer/preserve-vsubmod
Try to preserve vendor/.git, if it exists
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2acae4d..668b25d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# Release 0.13.0 (unreleased)
-- Nothing yet
+- #697: Preserve vendor/.git, if it exists.
# Release 0.12.3 (2016-10-03)
diff --git a/repo/installer.go b/repo/installer.go
index 8f02cc3..72e49cd 100644
--- a/repo/installer.go
+++ b/repo/installer.go
@@ -354,42 +354,66 @@
}
msg.Info("Replacing existing vendor dependencies")
+
+ // Check if a .git directory exists under the old vendor dir. If it does,
+ // move it over to the newly-generated vendor dir - the user is probably
+ // submoduling, and it's easy enough not to break their setup.
+ ivg := filepath.Join(i.VendorPath(), ".git")
+ _, err = os.Stat(ivg)
+ if err == nil {
+ msg.Info("Preserving existing vendor/.git directory")
+ vpg := filepath.Join(vp, ".git")
+ err = os.Rename(ivg, vpg)
+
+ if terr, ok := err.(*os.LinkError); ok {
+ err = fixcle(ivg, vpg, terr)
+ if err != nil {
+ msg.Warn("Failed to preserve existing vendor/.git directory")
+ }
+ }
+ }
+
err = os.RemoveAll(i.VendorPath())
if err != nil {
return err
}
err = os.Rename(vp, i.VendorPath())
-
- if err != nil {
- // When there are different physical devices we cannot rename cross device.
- // Instead we copy.
- switch terr := err.(type) {
- case *os.LinkError:
- // syscall.EXDEV is the common name for the cross device link error
- // which has varying output text across different operating systems.
- if terr.Err == syscall.EXDEV {
- msg.Debug("Cross link err, trying manual copy: %s", err)
- return gpath.CopyDir(vp, i.VendorPath())
- } else if runtime.GOOS == "windows" {
- // In windows it can drop down to an operating system call that
- // returns an operating system error with a different number and
- // message. Checking for that as a fall back.
- noerr, ok := terr.Err.(syscall.Errno)
- // 0x11 (ERROR_NOT_SAME_DEVICE) is the windows error.
- // See https://msdn.microsoft.com/en-us/library/cc231199.aspx
- if ok && noerr == 0x11 {
- msg.Debug("Cross link err on Windows, trying manual copy: %s", err)
- return gpath.CopyDir(vp, i.VendorPath())
- }
- }
- }
+ if terr, ok := err.(*os.LinkError); ok {
+ return fixcle(vp, i.VendorPath(), terr)
}
return err
}
+// fixcle is a helper function that tries to recover from cross-device rename
+// errors by falling back to copying.
+func fixcle(from, to string, terr *os.LinkError) error {
+ // When there are different physical devices we cannot rename cross device.
+ // Instead we copy.
+
+ // syscall.EXDEV is the common name for the cross device link error
+ // which has varying output text across different operating systems.
+ if terr.Err == syscall.EXDEV {
+ msg.Debug("Cross link err, trying manual copy: %s", terr)
+ return gpath.CopyDir(from, to)
+ } else if runtime.GOOS == "windows" {
+ // In windows it can drop down to an operating system call that
+ // returns an operating system error with a different number and
+ // message. Checking for that as a fall back.
+ noerr, ok := terr.Err.(syscall.Errno)
+ // 0x11 (ERROR_NOT_SAME_DEVICE) is the windows error.
+ // See https://msdn.microsoft.com/en-us/library/cc231199.aspx
+ if ok && noerr == 0x11 {
+ msg.Debug("Cross link err on Windows, trying manual copy: %s", terr)
+ return gpath.CopyDir(from, to)
+ }
+ }
+
+ return terr
+}
+
// List resolves the complete dependency tree and returns a list of dependencies.
func (i *Installer) List(conf *cfg.Config) []*cfg.Dependency {
base := "."