first commit.
This commit is contained in:
@@ -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), ''];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user