Merge pull request #557 from Masterminds/fix/550
Fixed #550: There was opportunity for nil pointers in lock
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6b80ea1..7e757f7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
others are deprecated and no longer needed.
## Fixed
+- #553: Export was failing with different physical devices
- #542: Glide failed to detect some test dependencies (thanks @sdboyer)
- #517: Fixed failure to install testImport from lock when no imports present
or when same dependency on both import and testImport
diff --git a/glide.go b/glide.go
index ce39ede..77c39a7 100644
--- a/glide.go
+++ b/glide.go
@@ -105,6 +105,12 @@
Usage: "The location of Glide files",
EnvVar: "GLIDE_HOME",
},
+ cli.StringFlag{
+ Name: "tmp",
+ Value: "",
+ Usage: "The temp directory to use. Defaults to systems temp",
+ EnvVar: "GLIDE_TMP",
+ },
cli.BoolFlag{
Name: "no-color",
Usage: "Turn off colored output for log messages",
@@ -858,6 +864,7 @@
action.Quiet(c.Bool("quiet"))
action.Init(c.String("yaml"), c.String("home"))
action.EnsureGoVendor()
+ gpath.Tmp = c.String("tmp")
return nil
}
diff --git a/path/path.go b/path/path.go
index ecc8a10..48e95fb 100644
--- a/path/path.go
+++ b/path/path.go
@@ -21,6 +21,10 @@
// As of Go 1.5, this is always vendor.
var VendorDir = "vendor"
+// Tmp is the temporary directory Glide should use. Defaults to "" which
+// signals using the system default.
+var Tmp = ""
+
// Cache the location of the homedirectory.
var homeDir = ""
@@ -211,3 +215,85 @@
return false, err
}
+
+// CopyDir copies an entire source directory to the dest directory.
+//
+// This is akin to `cp -a src/* dest/`
+//
+// We copy the directory here rather than jumping out to a shell so we can
+// support multiple operating systems.
+func CopyDir(source string, dest string) error {
+
+ // get properties of source dir
+ si, err := os.Stat(source)
+ if err != nil {
+ return err
+ }
+
+ err = os.MkdirAll(dest, si.Mode())
+ if err != nil {
+ return err
+ }
+
+ d, _ := os.Open(source)
+
+ objects, err := d.Readdir(-1)
+
+ for _, obj := range objects {
+
+ sp := filepath.Join(source, "/", obj.Name())
+
+ dp := filepath.Join(dest, "/", obj.Name())
+
+ if obj.IsDir() {
+ err = CopyDir(sp, dp)
+ if err != nil {
+ return err
+ }
+ } else {
+ // perform copy
+ err = CopyFile(sp, dp)
+ if err != nil {
+ return err
+ }
+ }
+
+ }
+ return nil
+}
+
+// CopyFile copies a source file to a destination.
+//
+// It follows symbolic links and retains modes.
+func CopyFile(source string, dest string) error {
+ ln, err := os.Readlink(source)
+ if err == nil {
+ return os.Symlink(ln, dest)
+ }
+ s, err := os.Open(source)
+ if err != nil {
+ return err
+ }
+
+ defer s.Close()
+
+ d, err := os.Create(dest)
+ if err != nil {
+ return err
+ }
+
+ defer d.Close()
+
+ _, err = io.Copy(d, s)
+ if err != nil {
+ return err
+ }
+
+ si, err := os.Stat(source)
+ if err != nil {
+ return err
+ }
+ err = os.Chmod(dest, si.Mode())
+
+ return err
+}
diff --git a/repo/installer.go b/repo/installer.go
index a5d6aee..018f8fc 100644
--- a/repo/installer.go
+++ b/repo/installer.go
@@ -244,7 +244,7 @@
// Export from the cache to the vendor directory
func (i *Installer) Export(conf *cfg.Config) error {
- tempDir, err := ioutil.TempDir("", "glide-vendor")
+ tempDir, err := ioutil.TempDir(gpath.Tmp, "glide-vendor")
if err != nil {
return err
}
@@ -358,6 +358,15 @@
}
err = os.Rename(vp, i.VendorPath())
+
+ // When there are different physical devices we cannot rename cross device.
+ // Fall back to manual copy.
+ if err != nil && strings.Contains(err.Error(), "invalid cross-device link") {
+ msg.Debug("Cross link err, trying manual copy: %s", err)
+
+ err = gpath.CopyDir(vp, i.VendorPath())
+ }
+
return err
}