first commit.
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Toolbox;
|
||||
|
||||
/**
|
||||
* Copia (o enlaza) los archivos de un componente al proyecto respetando la
|
||||
* regla de destino, el modo y el drift.
|
||||
*/
|
||||
final class Copier
|
||||
{
|
||||
public function __construct(private readonly FileSync $sync = new FileSync())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $files rutas relativas al paquete
|
||||
* @param array<string, string> $expectedFiles rel -> hash previo (lock)
|
||||
* @param array<string, string>|null $destinations
|
||||
* @param array{force?:bool, backup?:bool, keepLocal?:bool, dryRun?:bool} $options
|
||||
* @return array{files: array<string,string>, actions: array<string,string>, aborted: list<string>}
|
||||
*/
|
||||
public function install(
|
||||
array $files,
|
||||
string $sourceDir,
|
||||
string $rootDir,
|
||||
string $rootCore,
|
||||
?array $destinations,
|
||||
string $mode,
|
||||
array $options = [],
|
||||
array $expectedFiles = []
|
||||
): array {
|
||||
$installed = [];
|
||||
$actions = [];
|
||||
$aborted = [];
|
||||
|
||||
foreach ($files as $file) {
|
||||
$relative = Destination::relative($file, $rootDir, $rootCore, $destinations);
|
||||
$source = rtrim($sourceDir, '/') . '/' . ltrim($file, '/');
|
||||
$target = rtrim($rootDir, '/') . '/' . $relative;
|
||||
$expected = $expectedFiles[$relative] ?? null;
|
||||
|
||||
if (($options['dryRun'] ?? false)) {
|
||||
$actions[$relative] = 'planned';
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($mode === 'link') {
|
||||
$action = $this->link($source, $target, $options);
|
||||
} else {
|
||||
$contents = file_get_contents($source);
|
||||
if ($contents === false) {
|
||||
throw new ToolboxException("No se pudo leer el archivo de origen: {$source}");
|
||||
}
|
||||
$action = $this->sync->write($target, $contents, $expected, $options);
|
||||
}
|
||||
|
||||
$actions[$relative] = $action;
|
||||
|
||||
if ($action === FileSync::ABORTED) {
|
||||
$aborted[] = $relative;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$installed[$relative] = is_file($source) ? Drift::hash($source) : '';
|
||||
}
|
||||
|
||||
return ['files' => $installed, 'actions' => $actions, 'aborted' => $aborted];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{force?:bool, keepLocal?:bool} $options
|
||||
*/
|
||||
private function link(string $source, string $target, array $options): string
|
||||
{
|
||||
if (is_link($target)) {
|
||||
if (readlink($target) === $source) {
|
||||
return FileSync::WRITTEN;
|
||||
}
|
||||
unlink($target);
|
||||
} elseif (is_file($target)) {
|
||||
if ($options['keepLocal'] ?? false) {
|
||||
return FileSync::SKIPPED;
|
||||
}
|
||||
if (!($options['force'] ?? false)) {
|
||||
return FileSync::ABORTED;
|
||||
}
|
||||
unlink($target);
|
||||
}
|
||||
|
||||
if (!is_dir(dirname($target))) {
|
||||
mkdir(dirname($target), 0777, true);
|
||||
}
|
||||
|
||||
if (!symlink($source, $target)) {
|
||||
throw new ToolboxException("No se pudo enlazar {$target} -> {$source}");
|
||||
}
|
||||
|
||||
return FileSync::WRITTEN;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user