From 39d8104897ae7966a41c99b60c6b3e45cb92f050 Mon Sep 17 00:00:00 2001 From: Christian Ramelow Date: Thu, 31 Aug 2017 16:52:18 +0200 Subject: [PATCH] Introduces a new method `copy()`. Some packages, e. g. `tm/tooly-composer-script`, are using the composer classes to e. g. create symlinks or perform other file operations. While there's only a `copyThenRemove()` method this commit introduces a new `copy()` method. `copy()` behaves the same as the copy part of `copyThenRemove()` did with one exception: it returns `true` on success and `false` on failure. Copying a directory may lead to a `false`, while the whole directory or some of its files couldn't been copied. To ensure backwards compatibility `copyThenRemove()` calls `copy()` now. This commit also adds the necessary tests. --- src/Composer/Util/Filesystem.php | 22 +++++++++-- tests/Composer/Test/Util/FilesystemTest.php | 42 +++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index 899e342cd..04b767ec3 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -247,27 +247,43 @@ class Filesystem */ public function copyThenRemove($source, $target) { + $this->copy($source, $target); if (!is_dir($source)) { - copy($source, $target); $this->unlink($source); return; } + $this->removeDirectoryPhp($source); + } + + /** + * Copies a file or directory from $source to $target. + * + * @param $source + * @param $target + * @return bool + */ + public function copy($source, $target) { + if (!is_dir($source)) { + return copy($source, $target); + } + $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS); $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST); $this->ensureDirectoryExists($target); + $result=true; foreach ($ri as $file) { $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName(); if ($file->isDir()) { $this->ensureDirectoryExists($targetPath); } else { - copy($file->getPathname(), $targetPath); + $result = $result && copy($file->getPathname(), $targetPath); } } - $this->removeDirectoryPhp($source); + return $result; } public function rename($source, $target) diff --git a/tests/Composer/Test/Util/FilesystemTest.php b/tests/Composer/Test/Util/FilesystemTest.php index 7b54d8762..017cf6e45 100644 --- a/tests/Composer/Test/Util/FilesystemTest.php +++ b/tests/Composer/Test/Util/FilesystemTest.php @@ -311,4 +311,46 @@ class FilesystemTest extends TestCase $this->assertTrue($fs->removeJunction($junction)); $this->assertFalse(is_dir($junction)); } + + public function testCopy() + { + @mkdir($this->workingDir . '/foo/bar', 0777, true); + @mkdir($this->workingDir . '/foo/baz', 0777, true); + file_put_contents($this->workingDir . '/foo/foo.file', 'foo'); + file_put_contents($this->workingDir . '/foo/bar/foobar.file', 'foobar'); + file_put_contents($this->workingDir . '/foo/baz/foobaz.file', 'foobaz'); + file_put_contents($this->testFile, 'testfile'); + $fs = new Filesystem(); + $result1 = $fs->copy($this->workingDir . '/foo', $this->workingDir . '/foop'); + $result2 = $fs->copy($this->testFile, $this->workingDir . '/foop/testfile.file'); + $this->assertTrue($result1); + $this->assertTrue($result2); + $this->assertTrue(is_dir($this->workingDir . '/foop')); + $this->assertTrue(is_dir($this->workingDir . '/foop/bar')); + $this->assertTrue(is_dir($this->workingDir . '/foop/baz')); + $this->assertTrue(is_file($this->workingDir . '/foop/foo.file')); + $this->assertTrue(is_file($this->workingDir . '/foop/bar/foobar.file')); + $this->assertTrue(is_file($this->workingDir . '/foop/baz/foobaz.file')); + $this->assertTrue(is_file($this->workingDir . '/foop/testfile.file')); + } + + public function testCopyTheRemove() + { + @mkdir($this->workingDir . '/foo/bar', 0777, true); + @mkdir($this->workingDir . '/foo/baz', 0777, true); + file_put_contents($this->workingDir . '/foo/foo.file', 'foo'); + file_put_contents($this->workingDir . '/foo/bar/foobar.file', 'foobar'); + file_put_contents($this->workingDir . '/foo/baz/foobaz.file', 'foobaz'); + file_put_contents($this->testFile, 'testfile'); + $fs = new Filesystem(); + $fs->copyThenRemove($this->workingDir . '/foo', $this->workingDir . '/foop'); + $fs->copyThenRemove($this->testFile, $this->workingDir . '/foop/testfile.file'); + $this->assertFalse(is_file($this->workingDir . '/foop/testfile.file')); + $this->assertFalse(is_file($this->workingDir . '/foop/baz/foobaz.file')); + $this->assertFalse(is_file($this->workingDir . '/foop/bar/foobar.file')); + $this->assertFalse(is_file($this->workingDir . '/foop/foo.file')); + $this->assertFalse(is_dir($this->workingDir . '/foop/baz')); + $this->assertFalse(is_dir($this->workingDir . '/foop/bar')); + $this->assertFalse(is_dir($this->workingDir . '/foop')); + } }