Pārlūkot izejas kodu

Merge remote-tracking branch 'mheleniak/rename_reliability'

Jordi Boggiano 12 gadi atpakaļ
vecāks
revīzija
c7a13893c7

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

@@ -52,9 +52,9 @@ abstract class ArchiveDownloader extends FileDownloader
                 } else {
                     // Rename the content directory to avoid error when moving up
                     // a child folder with the same name
-                    $temporaryName = md5(time().rand());
-                    $this->filesystem->rename($contentDir, $temporaryName);
-                    $contentDir = $temporaryName;
+                    $temporaryDir = sys_get_temp_dir().'/'.md5(time().rand());
+                    $this->filesystem->rename($contentDir, $temporaryDir);
+                    $contentDir = $temporaryDir;
 
                     foreach (array_merge(glob($contentDir . '/.*'), glob($contentDir . '/*')) as $file) {
                         if (trim(basename($file), '.')) {
@@ -62,7 +62,7 @@ abstract class ArchiveDownloader extends FileDownloader
                         }
                     }
 
-                    rmdir($contentDir);
+                    $this->filesystem->removeDirectory($contentDir);
                 }
             }
         } catch (\Exception $e) {

+ 29 - 9
src/Composer/Util/Filesystem.php

@@ -25,6 +25,19 @@ class Filesystem
         $this->processExecutor = $executor ?: new ProcessExecutor();
     }
 
+    public function remove($file)
+    {
+        if (is_dir($file)) {
+            return $this->removeDirectory($file);
+        }
+
+        if (file_exists($file)) {
+            return unlink($file);
+        }
+
+        return false;
+    }
+
     public function removeDirectory($directory)
     {
         if (!is_dir($directory)) {
@@ -63,21 +76,28 @@ class Filesystem
 
     public function rename($source, $target)
     {
-        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
-            rename($source, $target);
-
+        if (true === @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)) {
+        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
+            // Try to copy & delete - this is a workaround for random "Access denied" errors.
+            $command = sprintf('xcopy %s %s /E /I /Q', escapeshellarg($source), escapeshellarg($target));
+            if (0 === $this->processExecutor->execute($command)) {
+                $this->remove($source);
+
+                return;
+            }
+        } else {
+            // 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.
+            $command = sprintf('mv %s %s', escapeshellarg($source), escapeshellarg($target));
+            if (0 === $this->processExecutor->execute($command)) {
                 return;
             }
-
-            throw new \RuntimeException(sprintf('Could not rename "%s" to "%s".', $source, $target));
         }
+
+        throw new \RuntimeException(sprintf('Could not rename "%s" to "%s".', $source, $target));
     }
 
     /**