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,107 @@
<?php
namespace Toolbox;
/**
* Caché clonada del toolbox. Mantiene historial completo (no superficial) para
* poder resolver cualquier commit registrado en un lock.
*/
final class ToolboxRepo
{
public function __construct(
private readonly string $dir,
private readonly string $url,
) {
}
public function dir(): string
{
return $this->dir;
}
public function isCloned(): bool
{
return is_dir($this->dir . '/.git');
}
public function ensure(): void
{
if (!$this->isCloned()) {
$parent = dirname($this->dir);
if (!is_dir($parent)) {
mkdir($parent, 0777, true);
}
$this->git(['clone', '--tags', $this->url, $this->dir]);
return;
}
$this->ensureFull();
$this->fetch();
}
public function fetch(): void
{
$this->git(['fetch', '--tags', '--force', 'origin']);
}
/**
* Si la caché es superficial, la completa.
*/
public function ensureFull(): void
{
if (is_file($this->dir . '/.git/shallow')) {
$this->git(['fetch', '--unshallow', '--tags']);
}
}
/**
* @return list<string>
*/
public function tags(?string $prefix = null): array
{
$tags = array_filter(explode("\n", trim($this->git(['tag', '-l'])[1])));
if ($prefix === null) {
return array_values($tags);
}
return array_values(array_filter($tags, fn ($tag) => str_starts_with($tag, $prefix)));
}
public function commitOfTag(string $tag): ?string
{
$result = $this->git(['rev-list', '-n', '1', $tag]);
return $result[0] === 0 && trim($result[1]) !== '' ? trim($result[1]) : null;
}
public function hasCommit(string $commit): bool
{
$result = $this->git(['cat-file', '-e', $commit . '^{commit}']);
return $result[0] === 0;
}
public function fileAt(string $ref, string $path): ?string
{
$result = $this->git(['show', $ref . ':' . $path]);
return $result[0] === 0 ? $result[1] : null;
}
/**
* @param list<string> $args
* @return array{0:int, 1:string, 2:string}
*/
public function git(array $args): array
{
$command = 'git -C ' . escapeshellarg($this->dir) . ' ' . implode(' ', array_map('escapeshellarg', $args)) . ' 2>&1';
$output = [];
$code = 0;
exec($command, $output, $code);
return [$code, implode("\n", $output), ''];
}
}