diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 34b0a9ba671a..0e250b3669f4 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -336,11 +336,30 @@ 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) && isset($options['delete']) && $options['delete']) { + $deleteIterator = $iterator; + if (null === $deleteIterator) { + $flags = \FilesystemIterator::SKIP_DOTS; + $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); + } + foreach ($deleteIterator 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 +370,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/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index c4c5fcae0f6b..261add85eb91 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/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()