Files
duckbrain-toolbox/packages/commands/src/Toolbox/FileSync.php
T
2026-10-05 15:08:39 -03:00

93 lines
2.5 KiB
PHP

<?php
namespace Toolbox;
/**
* Escribe archivos respetando el drift: sin edición local escribe; con edición
* decide según `--force`, `--backup`, `--keep-local` o aborta.
*/
final class FileSync
{
public const WRITTEN = 'written';
public const OVERWRITTEN = 'overwritten';
public const BACKED_UP = 'backed_up';
public const SKIPPED = 'skipped';
public const ABORTED = 'aborted';
/**
* @param array{force?:bool, backup?:bool, keepLocal?:bool} $options
*/
public function write(string $path, string $contents, ?string $expected, array $options = []): string
{
if (!is_dir(dirname($path))) {
mkdir(dirname($path), 0777, true);
}
$existed = is_file($path);
$drifted = $existed && Drift::isDrifted($path, $expected);
if (!$drifted) {
// Sin hash previo (p. ej. primera canonicalización de un proyecto
// heredado) un archivo existente también puede respaldarse.
$changed = $existed && (string) file_get_contents($path) !== $contents;
if ($changed && ($options['backup'] ?? false)) {
copy($path, $path . '.bak');
file_put_contents($path, $contents);
return self::BACKED_UP;
}
file_put_contents($path, $contents);
return $existed ? self::OVERWRITTEN : self::WRITTEN;
}
if ($options['force'] ?? false) {
file_put_contents($path, $contents);
return self::OVERWRITTEN;
}
if ($options['backup'] ?? false) {
copy($path, $path . '.bak');
file_put_contents($path, $contents);
return self::BACKED_UP;
}
if ($options['keepLocal'] ?? false) {
return self::SKIPPED;
}
return self::ABORTED;
}
/**
* @param array{force?:bool, backup?:bool, keepLocal?:bool} $options
*/
public function remove(string $path, ?string $expected, array $options = []): string
{
if (!is_file($path)) {
return self::SKIPPED;
}
$drifted = Drift::isDrifted($path, $expected);
if ($drifted && !($options['force'] ?? false)) {
if ($options['keepLocal'] ?? false) {
return self::SKIPPED;
}
if ($options['backup'] ?? false) {
copy($path, $path . '.bak');
} else {
return self::ABORTED;
}
}
unlink($path);
return self::OVERWRITTEN;
}
}