From eb23ec18553c5e1f80a58f5abe459e806fbce0c2 Mon Sep 17 00:00:00 2001 From: Alexandre Melard Date: Wed, 14 Nov 2012 22:22:49 +0100 Subject: [PATCH] mirror with obsolete files removal in target dir I added a "delete" option to the mirror function. If set to TRUE, then files present in target dir and not in origin dir will be removed --- Filesystem.php | 24 +++++++++++++++++++++--- Tests/FilesystemTest.php | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Filesystem.php b/Filesystem.php index 34b0a9ba67..e573ea4492 100644 --- a/Filesystem.php +++ b/Filesystem.php @@ -336,11 +336,32 @@ public function makePathRelative($endPath, $startPath) * Valid options are: * - $options['override'] Whether to override an existing file on copy or not (see copy()) * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink()) + * - $options['delete'] Default FALSE Whether to delete files that are not in the source directory * * @throws IOException When file type is unknown */ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array()) { + $targetDir = rtrim($targetDir, '/\\'); + $originDir = rtrim($originDir, '/\\'); + + // Iterate in destination folder to remove obsolete entries + if ($this->exists($targetDir)) { + if (isset($options['delete']) and $options['delete']) { + $l_iterator = $iterator; + if (null === $l_iterator) { + $flags = \FilesystemIterator::SKIP_DOTS; + $l_iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST ); + } + foreach ($l_iterator as $file) { + $origin = str_replace($targetDir, $originDir, $file->getPathname()); + if (!$this->exists($origin)) { + $this->remove($file); + } + } + } + } + $copyOnWindows = false; if (isset($options['copy_on_windows']) && !function_exists('symlink')) { $copyOnWindows = $options['copy_on_windows']; @@ -351,9 +372,6 @@ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $o $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST); } - $targetDir = rtrim($targetDir, '/\\'); - $originDir = rtrim($originDir, '/\\'); - foreach ($iterator as $file) { $target = str_replace($originDir, $targetDir, $file->getPathname()); diff --git a/Tests/FilesystemTest.php b/Tests/FilesystemTest.php index c4c5fcae0f..261add85eb 100644 --- a/Tests/FilesystemTest.php +++ b/Tests/FilesystemTest.php @@ -798,6 +798,25 @@ public function testMirrorCopiesFilesAndDirectoriesRecursively() $this->assertTrue(is_dir($targetPath.'directory')); $this->assertFileEquals($file1, $targetPath.'directory'.DIRECTORY_SEPARATOR.'file1'); $this->assertFileEquals($file2, $targetPath.'file2'); + + $this->filesystem->remove($file1); + + $this->filesystem->mirror($sourcePath, $targetPath, null, array("delete" => FALSE)); + $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1')); + + $this->filesystem->mirror($sourcePath, $targetPath, null, array("delete" => TRUE)); + $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1')); + + file_put_contents($file1, 'FILE1'); + + $this->filesystem->mirror($sourcePath, $targetPath, null, array("delete" => TRUE)); + $this->assertTrue($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1')); + + $this->filesystem->remove($directory); + $this->filesystem->mirror($sourcePath, $targetPath, null, array("delete" => TRUE)); + $this->assertFalse($this->filesystem->exists($targetPath.'directory')); + $this->assertFalse($this->filesystem->exists($targetPath.'directory'.DIRECTORY_SEPARATOR.'file1')); + } public function testMirrorCopiesLinks()