Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6041462

Browse files
[Filesystem] remove dirs atomically if possible
1 parent 5dbc7db commit 6041462

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ public function remove($files)
167167
} elseif (!\is_array($files)) {
168168
$files = [$files];
169169
}
170+
171+
self::doRemove($files, false);
172+
}
173+
174+
private static function doRemove(array $files, bool $isRecursive): void
175+
{
170176
$files = array_reverse($files);
171177
foreach ($files as $file) {
172178
if (is_link($file)) {
@@ -175,10 +181,35 @@ public function remove($files)
175181
throw new IOException(sprintf('Failed to remove symlink "%s": ', $file).self::$lastError);
176182
}
177183
} elseif (is_dir($file)) {
178-
$this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
184+
if (!$isRecursive) {
185+
$tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-.'));
186+
187+
if (file_exists($tmpName)) {
188+
try {
189+
self::doRemove([$tmpName], true);
190+
} catch (IOException $e) {
191+
}
192+
}
193+
194+
if (!file_exists($tmpName) && self::box('rename', $file, $tmpName)) {
195+
$origFile = $file;
196+
$file = $tmpName;
197+
} else {
198+
$origFile = null;
199+
}
200+
}
201+
202+
$files = new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS);
203+
self::doRemove(iterator_to_array($files, true), true);
204+
205+
if (!self::box('rmdir', $file) && file_exists($file) && !$isRecursive) {
206+
$lastError = self::$lastError;
207+
208+
if (null !== $origFile && self::box('rename', $file, $origFile)) {
209+
$file = $origFile;
210+
}
179211

180-
if (!self::box('rmdir', $file) && file_exists($file)) {
181-
throw new IOException(sprintf('Failed to remove directory "%s": ', $file).self::$lastError);
212+
throw new IOException(sprintf('Failed to remove directory "%s": ', $file).$lastError);
182213
}
183214
} elseif (!self::box('unlink', $file) && (false !== strpos(self::$lastError, 'Permission denied') || file_exists($file))) {
184215
throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError);

src/Symfony/Component/HttpKernel/Tests/KernelTest.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1717
use Symfony\Component\DependencyInjection\ContainerBuilder;
1818
use Symfony\Component\DependencyInjection\ContainerInterface;
19+
use Symfony\Component\Filesystem\Exception\IOException;
1920
use Symfony\Component\Filesystem\Filesystem;
2021
use Symfony\Component\HttpFoundation\Request;
2122
use Symfony\Component\HttpFoundation\Response;
@@ -35,8 +36,10 @@ class KernelTest extends TestCase
3536
{
3637
protected function tearDown(): void
3738
{
38-
$fs = new Filesystem();
39-
$fs->remove(__DIR__.'/Fixtures/var');
39+
try {
40+
(new Filesystem())->remove(__DIR__.'/Fixtures/var');
41+
} catch (IOException $e) {
42+
}
4043
}
4144

4245
public function testConstructor()

0 commit comments

Comments
 (0)