mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-07 08:45:40 +08:00
Add moveFileOrDir method to handle cross-device file and directory moves
This commit is contained in:
31
src/Package/Artifact/imagick.php
Normal file
31
src/Package/Artifact/imagick.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Package\Artifact;
|
||||||
|
|
||||||
|
use StaticPHP\Attribute\Artifact\AfterSourceExtract;
|
||||||
|
use StaticPHP\Attribute\PatchDescription;
|
||||||
|
use StaticPHP\Util\SourcePatcher;
|
||||||
|
|
||||||
|
class imagick
|
||||||
|
{
|
||||||
|
#[AfterSourceExtract('ext-imagick')]
|
||||||
|
#[PatchDescription('Patch imagick for PHP 8.4 compatibility (versions < 3.8.0)')]
|
||||||
|
public function patchImagickWith84(): void
|
||||||
|
{
|
||||||
|
// match imagick version id
|
||||||
|
$file = SOURCE_PATH . '/php-src/ext/imagick/php_imagick.h';
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$content = file_get_contents($file);
|
||||||
|
if (preg_match('/#define PHP_IMAGICK_EXTNUM\s+(\d+)/', $content, $match) === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$extnum = intval($match[1]);
|
||||||
|
if ($extnum < 30800) {
|
||||||
|
SourcePatcher::patchFile('imagick_php84_before_30800.patch', SOURCE_PATH . '/php-src/ext/imagick');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -493,6 +493,44 @@ class FileSystem
|
|||||||
return FileSystem::convertPath($path);
|
return FileSystem::convertPath($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move file or directory, handling cross-device scenarios
|
||||||
|
* Uses rename() if possible, falls back to copy+delete for cross-device moves
|
||||||
|
*
|
||||||
|
* @param string $source Source path
|
||||||
|
* @param string $dest Destination path
|
||||||
|
*/
|
||||||
|
public static function moveFileOrDir(string $source, string $dest): void
|
||||||
|
{
|
||||||
|
$source = FileSystem::convertPath($source);
|
||||||
|
$dest = FileSystem::convertPath($dest);
|
||||||
|
|
||||||
|
// Check if source and dest are on the same device to avoid cross-device rename errors
|
||||||
|
$source_stat = @stat($source);
|
||||||
|
$dest_parent = dirname($dest);
|
||||||
|
$dest_stat = @stat($dest_parent);
|
||||||
|
|
||||||
|
// Only use rename if on same device
|
||||||
|
if ($source_stat !== false && $dest_stat !== false && $source_stat['dev'] === $dest_stat['dev']) {
|
||||||
|
if (@rename($source, $dest)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to copy + delete for cross-device moves or if rename failed
|
||||||
|
if (is_dir($source)) {
|
||||||
|
FileSystem::copyDir($source, $dest);
|
||||||
|
FileSystem::removeDir($source);
|
||||||
|
} else {
|
||||||
|
if (!copy($source, $dest)) {
|
||||||
|
throw new FileSystemException("Failed to copy file from {$source} to {$dest}");
|
||||||
|
}
|
||||||
|
if (!unlink($source)) {
|
||||||
|
throw new FileSystemException("Failed to remove source file: {$source}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static function replaceFile(string $filename, int $replace_type = REPLACE_FILE_STR, mixed $callback_or_search = null, mixed $to_replace = null): false|int
|
private static function replaceFile(string $filename, int $replace_type = REPLACE_FILE_STR, mixed $callback_or_search = null, mixed $to_replace = null): false|int
|
||||||
{
|
{
|
||||||
logger()->debug('Replacing file with type[' . $replace_type . ']: ' . $filename);
|
logger()->debug('Replacing file with type[' . $replace_type . ']: ' . $filename);
|
||||||
|
|||||||
Reference in New Issue
Block a user