diff --git a/src/Illuminate/Filesystem/Filesystem.php b/src/Illuminate/Filesystem/Filesystem.php index b458500e81ae..4c4af8deaae6 100644 --- a/src/Illuminate/Filesystem/Filesystem.php +++ b/src/Illuminate/Filesystem/Filesystem.php @@ -2,6 +2,7 @@ namespace Illuminate\Filesystem; +use Exception; use ErrorException; use FilesystemIterator; use Symfony\Component\Finder\Finder; @@ -122,6 +123,36 @@ public function put($path, $contents, $lock = false) return file_put_contents($path, $contents, $lock ? LOCK_EX : 0); } + /** + * Write the contents of a file, replacing it atomically if it already exists. + * + * This will also replace the target file permissions. + * + * @param string $path + * @param string $content + * @throws Exception + */ + public function replace($path, $content) + { + // Just in case path already exists and is a symlink, we want to make sure we get the real path. + clearstatcache(true, $path); + $realPath = realpath($path); + if ($realPath) { + $path = $realPath; + } + + $dirName = dirname($path); + if (! is_writable($dirName)) { + throw new Exception("Replacing $path requires it's parent directory to be writable."); + } + + // Write out the contents to a temp file, so we then can rename the file atomically. + $tempPath = tempnam($dirName, basename($path)); + file_put_contents($tempPath, $content); + + rename($tempPath, $path); + } + /** * Prepend to a file. * diff --git a/src/Illuminate/Foundation/PackageManifest.php b/src/Illuminate/Foundation/PackageManifest.php index 5a86e5925e37..8c263278c830 100644 --- a/src/Illuminate/Foundation/PackageManifest.php +++ b/src/Illuminate/Foundation/PackageManifest.php @@ -2,7 +2,6 @@ namespace Illuminate\Foundation; -use Exception; use Illuminate\Filesystem\Filesystem; class PackageManifest @@ -97,7 +96,7 @@ protected function getManifest() $this->build(); } - $this->files->get($this->manifestPath, true); + $this->files->get($this->manifestPath); return $this->manifest = file_exists($this->manifestPath) ? $this->files->getRequire($this->manifestPath) : []; @@ -164,13 +163,6 @@ protected function packagesToIgnore() */ protected function write(array $manifest) { - if (! is_writable(dirname($this->manifestPath))) { - throw new Exception('The '.dirname($this->manifestPath).' directory must be present and writable.'); - } - - $this->files->put( - $this->manifestPath, 'files->replace($this->manifestPath, 'assertStringEqualsFile($this->tempDir.'/file.txt', 'Hello World'); } + public function testReplaceStoresFiles() + { + $files = new Filesystem; + $files->replace($this->tempDir.'/file.txt', 'Hello World'); + $this->assertStringEqualsFile($this->tempDir.'/file.txt', 'Hello World'); + + $files->replace($this->tempDir.'/file.txt', 'Something Else'); + $this->assertStringEqualsFile($this->tempDir.'/file.txt', 'Something Else'); + } + public function testSetChmod() { file_put_contents($this->tempDir.'/file.txt', 'Hello World');