first commit.

This commit is contained in:
kj
2026-10-05 15:08:39 -03:00
commit b7799f9fff
93 changed files with 8966 additions and 0 deletions
@@ -0,0 +1,51 @@
<?php
namespace Toolbox;
/**
* Autoactualización del instalador global: descarga el phar, verifica su
* sha256 contra el publicado y reemplaza el binario de forma atómica.
*/
final class SelfUpdater
{
public function __construct(private readonly Console $console)
{
}
public function update(string $from, string $target, string $tempDir): void
{
$source = rtrim($from, '/') . '/duckbrain.phar';
$sumUrl = $source . '.sha256';
$this->console->out(' descargando ' . $source);
$data = @file_get_contents($source);
if ($data === false) {
throw new ToolboxException("No se pudo descargar el instalador: {$source}");
}
$expected = trim((string) @file_get_contents($sumUrl));
if ($expected === '') {
throw new ToolboxException("No se pudo leer el sha256 publicado: {$sumUrl}");
}
$actual = hash('sha256', $data);
if (!hash_equals($expected, $actual)) {
throw new ToolboxException('sha256 inválido; actualización abortada sin tocar el binario');
}
if (!is_dir($tempDir)) {
mkdir($tempDir, 0777, true);
}
$temp = rtrim($tempDir, '/') . '/duckbrain.phar.' . bin2hex(random_bytes(4));
file_put_contents($temp, $data);
chmod($temp, 0755);
if (!rename($temp, $target)) {
@unlink($temp);
throw new ToolboxException("No se pudo reemplazar el instalador: {$target}");
}
$this->console->ok('instalador actualizado (' . $target . ')');
}
}