Estado
Pitmaster calcula el estado del árbol de trabajo comparando tres estados: el árbol del commit HEAD, el índice (área de preparación) y el árbol de trabajo (los archivos reales en el disco). CLI imprime un resumen al estilo de git status a partir de ello, y statusPorcelainV2() imprime el formato porcelain v2 de git.
Uso básico
$entries = $repo->status();
foreach ($entries as $entry) {
echo $entry->shortFormat() . "\n";
}
shortFormat() imprime el formato breve de git:
M src/Modified.php (staged modification)
M src/WorktreeModified.php (unstaged modification)
A src/NewFile.php (staged new file)
D src/Deleted.php (deleted in worktree)
?? untracked.txt (untracked file)
StatusEntry
El estado de cada archivo se representa con un StatusEntry:
use Pitmaster\Status\StatusEntry;
$entry->path; // File path relative to repo root
$entry->index; // FileStatus: HEAD-to-index state
$entry->worktree; // FileStatus: index-to-worktree state
$entry->origPath; // Original path for renamed entries, otherwise null
$entry->renameScore; // Similarity score for renamed entries, otherwise null
$entry->shortFormat(); // "XY path", "?? path", or "R old -> new"
Enumeración FileStatus
use Pitmaster\Status\FileStatus;
FileStatus::Added; // 'A' - new file
FileStatus::Modified; // 'M' - content changed
FileStatus::Deleted; // 'D' - file removed
FileStatus::Renamed; // 'R' - file renamed
FileStatus::Copied; // 'C' - file copied
FileStatus::Unmerged; // 'U' - unresolved merge conflict
FileStatus::Untracked; // '?' - not in index
FileStatus::Ignored; // '!' - matched by .gitignore
FileStatus::Unmodified; // ' ' - no change
status() no informa sobre archivos ignorados, por lo que Ignored no aparece en su resultado.
Salida Porcelain v2
Para obtener una salida de estado legible por máquinas que coincida con git status --porcelain=v2:
echo $repo->statusPorcelainV2();
Salida:
1 .M N... 100644 100644 100644 ce013625030ba8dba906f756967f9e9ca394464a ce013625030ba8dba906f756967f9e9ca394464a modified-file.txt
? untracked-file.txt
Primero aparecen las entradas rastreadas y luego las que no lo están. Los renombrados usan líneas 2 y los conflictos, líneas u. No se imprimen los encabezados # branch de git status --porcelain=v2 --branch y no se enumeran los archivos ignorados.
Cómo se calcula el estado
La clase WorkingTreeStatus realiza la comparación de tres vías:
use Pitmaster\Status\WorkingTreeStatus;
$status = new WorkingTreeStatus($repo->objectDatabase(), $repo->workDir(), $repo->gitDir());
$entries = $status->compute($repo->index(), $repo->resolve('HEAD'));
Paso 1: Crear el mapa del árbol HEAD
Aplanar el árbol del commit HEAD en un mapa de path => blob hash. Esto representa el último estado confirmado.
Paso 2: Comparar HEAD con el índice
Para cada archivo del árbol HEAD y del índice:
- En HEAD, pero no en el índice:
Deleteden la columna del índice - En el índice, pero no en HEAD:
Addeden la columna del índice - En ambos, pero con hashes distintos:
Modifieden la columna del índice - En ambos y con el mismo hash:
Unmodifieden la columna del índice
Paso 3: Comparar el índice con el árbol de trabajo
Para cada archivo del índice y del árbol de trabajo:
- En el índice, pero no en el disco:
Deleteden la columna del árbol de trabajo - En ambos, pero con contenido distinto:
Modifieden la columna del árbol de trabajo - En ambos y con contenido coincidente:
Unmodifieden la columna del árbol de trabajo
Paso 4: Detectar archivos sin seguimiento
Recorre el directorio del árbol de trabajo, omite .git/ y las rutas ignoradas, e informa como Untracked en ambas columnas los archivos que no están en el índice.
Compatibilidad con .gitignore
Pitmaster analiza archivos .gitignore para determinar qué archivos sin seguimiento deben informarse como ignorados y cuáles como no rastreados.
use Pitmaster\Status\GitIgnore;
La clase GitIgnore analiza los patrones de gitignore de:
.gitignoreen la raíz del repositorio.gitignoreen los subdirectorios.git/info/exclude
Sintaxis de patrones admitida:
- Patrones glob (
*.log,build/) - Negación (
!important.log) - Patrones solo para directorios (
/al final) /inicial para patrones relativos a la raíz**para coincidencias recursivas
Categorización de entradas de estado
Un patrón habitual para mostrar UI:
$staged = [];
$unstaged = [];
$untracked = [];
foreach ($repo->status() as $entry) {
if ($entry->index === FileStatus::Untracked) {
$untracked[] = $entry;
} elseif ($entry->index !== FileStatus::Unmodified) {
$staged[] = $entry;
}
if ($entry->worktree !== FileStatus::Unmodified
&& $entry->index !== FileStatus::Untracked
) {
$unstaged[] = $entry;
}
}
Uso de CLI
./vendor/bin/pitmaster status
Salida:
On branch main
Changes to be committed:
new file: src/Feature.php
Changes not staged for commit:
modified: src/Existing.php
Untracked files:
notes.txt
Fsmonitor
Pitmaster incluye un ayudante para el protocolo fsmonitor de git:
use Pitmaster\Status\Fsmonitor;
La clase Fsmonitor puede consultar el hook core.fsmonitor (y recurrir a un análisis de marcas de tiempo de modificación) para saber qué archivos cambiaron desde un token. Se desactiva con los manejadores abiertos con ['processes' => false]. status() no lo llama por ahora; compara directamente los datos de stat y el contenido.