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

Skip to content

Commit d97ab18

Browse files
committed
feature #40144 [Filesystem] Remove dirs atomically if possible (nicolas-grekas)
This PR was merged into the 5.3-dev branch. Discussion ---------- [Filesystem] Remove dirs atomically if possible | Q | A | ------------- | --- | Branch? | 5.x | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | Fix #27578 | License | MIT | Doc PR | no need to Commits ------- 17bccca [Filesystem] remove dirs atomically if possible
2 parents 12b9d92 + 17bccca commit d97ab18

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ public function remove($files)
162162
} elseif (!\is_array($files)) {
163163
$files = [$files];
164164
}
165+
166+
self::doRemove($files, false);
167+
}
168+
169+
private static function doRemove(array $files, bool $isRecursive): void
170+
{
165171
$files = array_reverse($files);
166172
foreach ($files as $file) {
167173
if (is_link($file)) {
@@ -170,10 +176,35 @@ public function remove($files)
170176
throw new IOException(sprintf('Failed to remove symlink "%s": ', $file).self::$lastError);
171177
}
172178
} elseif (is_dir($file)) {
173-
$this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
179+
if (!$isRecursive) {
180+
$tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-.'));
181+
182+
if (file_exists($tmpName)) {
183+
try {
184+
self::doRemove([$tmpName], true);
185+
} catch (IOException $e) {
186+
}
187+
}
188+
189+
if (!file_exists($tmpName) && self::box('rename', $file, $tmpName)) {
190+
$origFile = $file;
191+
$file = $tmpName;
192+
} else {
193+
$origFile = null;
194+
}
195+
}
196+
197+
$files = new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS);
198+
self::doRemove(iterator_to_array($files, true), true);
199+
200+
if (!self::box('rmdir', $file) && file_exists($file) && !$isRecursive) {
201+
$lastError = self::$lastError;
202+
203+
if (null !== $origFile && self::box('rename', $file, $origFile)) {
204+
$file = $origFile;
205+
}
174206

175-
if (!self::box('rmdir', $file) && file_exists($file)) {
176-
throw new IOException(sprintf('Failed to remove directory "%s": ', $file).self::$lastError);
207+
throw new IOException(sprintf('Failed to remove directory "%s": ', $file).$lastError);
177208
}
178209
} elseif (!self::box('unlink', $file) && (false !== strpos(self::$lastError, 'Permission denied') || file_exists($file))) {
179210
throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError);

0 commit comments

Comments
 (0)