Browse Source

Avoid overwriting files for more atomic updates

Jordi Boggiano 9 years ago
parent
commit
e33fb2b898
1 changed files with 24 additions and 7 deletions
  1. 24 7
      src/Packagist/WebBundle/Package/SymlinkDumper.php

+ 24 - 7
src/Packagist/WebBundle/Package/SymlinkDumper.php

@@ -389,14 +389,18 @@ class SymlinkDumper
 
     private function switchActiveWebDir($webDir, $buildDir)
     {
-        if (defined('PHP_WINDOWS_VERSION_BUILD')) {
-            @rmdir($webDir.'/p');
-        } else {
-            @unlink($webDir.'/p');
+        $newLink = $webDir.'/p-new';
+        $oldLink = $webDir.'/p';
+
+        if (file_exists($newLink)) {
+            unlink($newLink);
         }
-        if (!symlink($buildDir, $webDir.'/p')) {
+        if (!symlink($buildDir, $newLink)) {
             throw new \RuntimeException('Could not symlink the build dir into the web dir');
         }
+        if (!rename($newLink, $oldLink)) {
+            throw new \RuntimeException('Could not replace the old symlink with the new one in the web dir');
+        }
     }
 
     private function cloneDir($source, $target)
@@ -431,7 +435,6 @@ class SymlinkDumper
 
         // clean up old provider listings
         $finder = Finder::create()->depth(0)->files()->name('provider-*.json')->ignoreVCS(true)->in($buildDir)->date('until 10minutes ago');
-        $providerFiles = array();
         foreach ($finder as $provider) {
             $key = strtr(str_replace($buildDir.DIRECTORY_SEPARATOR, '', $provider), '\\', '/');
             if (!in_array($key, $safeFiles, true)) {
@@ -441,6 +444,15 @@ class SymlinkDumper
                 }
             }
         }
+
+        // clean up old root listings
+        $finder = Finder::create()->depth(0)->files()->name('packages.json-*')->ignoreVCS(true)->in($buildDir)->date('until 10minutes ago');
+        foreach ($finder as $rootFile) {
+            unlink((string) $rootFile);
+            if (file_exists($altDirFile = str_replace($buildDir, $oldBuildDir, (string) $rootFile))) {
+                unlink($altDirFile);
+            }
+        }
     }
 
     private function dumpRootFile($file)
@@ -452,6 +464,9 @@ class SymlinkDumper
             ksort($this->rootFile['packages'][$package]);
         }
 
+        if (file_exists($file)) {
+            rename($file, $file.'-'.time());
+        }
         $this->writeFile($file, json_encode($this->rootFile));
     }
 
@@ -465,7 +480,9 @@ class SymlinkDumper
         $json = json_encode($this->listings[$key]);
         $hash = hash('sha256', $json);
         $path = substr($path, 0, -5) . '$' . $hash . '.json';
-        $this->writeFile($path, $json);
+        if (!file_exists($path)) {
+            $this->writeFile($path, $json);
+        }
 
         return array($path, $hash);
     }