Skip to content

Commit c38f174

Browse files
committed
Forward-port #978
1 parent 9903c22 commit c38f174

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

src/StaticPHP/Artifact/ArtifactExtractor.php

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -571,18 +571,30 @@ protected function unzipWithStrip(string $zip_file, string $extract_path): void
571571
}
572572

573573
/**
574-
* Move file or directory to destination.
574+
* Move file or directory, handling cross-device scenarios
575+
* Uses rename() if possible, falls back to copy+delete for cross-device moves
576+
*
577+
* @param string $source Source path
578+
* @param string $dest Destination path
575579
*/
576-
protected function moveFileOrDir(string $source, string $dest): void
580+
private static function moveFileOrDir(string $source, string $dest): void
577581
{
578582
$source = FileSystem::convertPath($source);
579583
$dest = FileSystem::convertPath($dest);
580584

581-
// Try rename first (fast, atomic)
582-
if (@rename($source, $dest)) {
583-
return;
585+
// Check if source and dest are on the same device to avoid cross-device rename errors
586+
$source_stat = @stat($source);
587+
$dest_parent = dirname($dest);
588+
$dest_stat = @stat($dest_parent);
589+
590+
// Only use rename if on same device
591+
if ($source_stat !== false && $dest_stat !== false && $source_stat['dev'] === $dest_stat['dev']) {
592+
if (@rename($source, $dest)) {
593+
return;
594+
}
584595
}
585596

597+
// Fall back to copy + delete for cross-device moves or if rename failed
586598
if (is_dir($source)) {
587599
FileSystem::copyDir($source, $dest);
588600
FileSystem::removeDir($source);

0 commit comments

Comments
 (0)