87 lines
2.1 KiB
PHP
87 lines
2.1 KiB
PHP
<?php
|
|
|
|
namespace Toolbox;
|
|
|
|
/**
|
|
* Mapa de propiedad: cada ruta instalada pertenece al core o a un componente.
|
|
*/
|
|
final class Ownership
|
|
{
|
|
/** @var array<string, string> path => owner id ('core' o 'pkg:comp') */
|
|
private array $owners = [];
|
|
|
|
/** @var array<string, list<string>> path => owners en conflicto */
|
|
private array $collisions = [];
|
|
|
|
public static function fromLock(Lock $lock): self
|
|
{
|
|
$ownership = new self();
|
|
|
|
$core = $lock->core();
|
|
foreach (($core['files'] ?? []) as $path => $hash) {
|
|
$ownership->claim('core', $path);
|
|
}
|
|
|
|
foreach ($lock->components() as $id => $entry) {
|
|
foreach (($entry['files'] ?? []) as $path => $hash) {
|
|
$ownership->claim($id, $path);
|
|
}
|
|
}
|
|
|
|
return $ownership;
|
|
}
|
|
|
|
private function claim(string $owner, string $path): void
|
|
{
|
|
if (!isset($this->owners[$path])) {
|
|
$this->owners[$path] = $owner;
|
|
|
|
return;
|
|
}
|
|
|
|
if ($this->owners[$path] !== $owner) {
|
|
$this->collisions[$path][] = $this->owners[$path];
|
|
$this->collisions[$path][] = $owner;
|
|
}
|
|
}
|
|
|
|
public function ownerOf(string $path): ?string
|
|
{
|
|
return $this->owners[$path] ?? null;
|
|
}
|
|
|
|
/** @return list<string> */
|
|
public function pathsOf(string $owner): array
|
|
{
|
|
return array_keys(array_filter($this->owners, fn ($o) => $o === $owner));
|
|
}
|
|
|
|
/**
|
|
* @return array<string, list<string>>
|
|
*/
|
|
public function collisions(): array
|
|
{
|
|
$result = [];
|
|
foreach ($this->collisions as $path => $owners) {
|
|
$result[$path] = array_values(array_unique($owners));
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function assertNoCollisions(): void
|
|
{
|
|
$collisions = $this->collisions();
|
|
if ($collisions === []) {
|
|
return;
|
|
}
|
|
|
|
$parts = [];
|
|
foreach ($collisions as $path => $owners) {
|
|
$parts[] = $path . ' (' . implode(', ', $owners) . ')';
|
|
}
|
|
|
|
throw new ToolboxException('Colisión de propiedad: ' . implode('; ', $parts));
|
|
}
|
|
}
|