Browse Source

Merge pull request #940 from schmittjoh/renameError

fixes rename bug (closes #900)
Jordi Boggiano 12 years ago
parent
commit
730c76ef85
2 changed files with 29 additions and 2 deletions
  1. 2 2
      src/Composer/Downloader/ArchiveDownloader.php
  2. 27 0
      src/Composer/Util/Filesystem.php

+ 2 - 2
src/Composer/Downloader/ArchiveDownloader.php

@@ -50,12 +50,12 @@ abstract class ArchiveDownloader extends FileDownloader
                 // Rename the content directory to avoid error when moving up
                 // a child folder with the same name
                 $temporaryName = md5(time().rand());
-                rename($contentDir, $temporaryName);
+                $this->filesystem->rename($contentDir, $temporaryName);
                 $contentDir = $temporaryName;
 
                 foreach (array_merge(glob($contentDir . '/.*'), glob($contentDir . '/*')) as $file) {
                     if (trim(basename($file), '.')) {
-                        rename($file, $path . '/' . basename($file));
+                        $this->filesystem->rename($file, $path . '/' . basename($file));
                     }
                 }
                 rmdir($contentDir);

+ 27 - 0
src/Composer/Util/Filesystem.php

@@ -14,9 +14,17 @@ namespace Composer\Util;
 
 /**
  * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  */
 class Filesystem
 {
+    private $processExecutor;
+
+    public function __construct(ProcessExecutor $executor = null)
+    {
+        $this->processExecutor = $executor ?: new ProcessExecutor();
+    }
+
     public function removeDirectory($directory)
     {
         if (!is_dir($directory)) {
@@ -53,6 +61,25 @@ class Filesystem
         }
     }
 
+    public function rename($source, $target)
+    {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            rename($source, $target);
+
+            return;
+        }
+
+        // We do not use PHP's "rename" function here since it does not support
+        // the case where $source, and $target are located on different partitions.
+        if (0 !== $this->processExecutor->execute('mv '.escapeshellarg($source).' '.escapeshellarg($target))) {
+            if (true === @rename($source, $target)) {
+                return;
+            }
+
+            throw new \RuntimeException(sprintf('Could not rename "%s" to "%s".', $source, $target));
+        }
+    }
+
     /**
      * Returns the shortest path from $from to $to
      *