108 lines
2.5 KiB
PHP
108 lines
2.5 KiB
PHP
<?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), ''];
|
|
}
|
|
}
|