Saltar al contenido

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

PHP
$entries = $repo->status();

foreach ($entries as $entry) {
    echo $entry->shortFormat() . "\n";
}

shortFormat() imprime el formato breve de git:

Código
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:

PHP
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

PHP
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:

PHP
echo $repo->statusPorcelainV2();

Salida:

Código
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:

PHP
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: Deleted en la columna del índice
  • En el índice, pero no en HEAD: Added en la columna del índice
  • En ambos, pero con hashes distintos: Modified en la columna del índice
  • En ambos y con el mismo hash: Unmodified en 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: Deleted en la columna del árbol de trabajo
  • En ambos, pero con contenido distinto: Modified en la columna del árbol de trabajo
  • En ambos y con contenido coincidente: Unmodified en 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.

PHP
use Pitmaster\Status\GitIgnore;

La clase GitIgnore analiza los patrones de gitignore de:

  • .gitignore en la raíz del repositorio
  • .gitignore en 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:

PHP
$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

Shell
./vendor/bin/pitmaster status

Salida:

Código
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:

PHP
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.