Status
Pitmaster berechnet den Status des Arbeitsbaums durch den Vergleich dreier Zustände: des Baums des HEAD-Commits, des Index (Staging-Bereichs) und des Arbeitsbaums (der tatsächlichen Dateien auf dem Datenträger). CLI gibt eine Zusammenfassung im Stil von git status aus, statusPorcelainV2() gibt das Porzellanformat v2 von git aus.
Grundlegende Verwendung
$entries = $repo->status();
foreach ($entries as $entry) {
echo $entry->shortFormat() . "\n";
}
shortFormat() gibt das Kurzformat von git aus:
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
Der Status jeder Datei wird durch ein StatusEntry dargestellt:
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"
FileStatus-Aufzählung
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() meldet keine ignorierten Dateien, daher erscheint Ignored nicht im Ergebnis.
Porcelain-v2-Ausgabe
Für eine maschinenlesbare Statusausgabe, die git status --porcelain=v2 entspricht:
echo $repo->statusPorcelainV2();
Ausgabe:
1 .M N... 100644 100644 100644 ce013625030ba8dba906f756967f9e9ca394464a ce013625030ba8dba906f756967f9e9ca394464a modified-file.txt
? untracked-file.txt
Getrackte Einträge erscheinen zuerst, danach nicht getrackte. Umbenennungen verwenden 2-Zeilen und Konflikte u-Zeilen. Die # branch-Header von git status --porcelain=v2 --branch werden nicht ausgegeben, und ignorierte Dateien werden nicht aufgelistet.
So wird der Status berechnet
Die Klasse WorkingTreeStatus führt den Drei-Wege-Vergleich durch:
use Pitmaster\Status\WorkingTreeStatus;
$status = new WorkingTreeStatus($repo->objectDatabase(), $repo->workDir(), $repo->gitDir());
$entries = $status->compute($repo->index(), $repo->resolve('HEAD'));
Schritt 1: HEAD-Tree-Map erstellen
Den Tree des HEAD-Commits zu einer Map aus path => blob hash abflachen. Diese bildet den zuletzt committeten Zustand ab.
Schritt 2: HEAD mit dem Index vergleichen
Für jede Datei im HEAD-Tree und im Index:
- In HEAD, aber nicht im Index:
Deletedin der Index-Spalte - Im Index, aber nicht in HEAD:
Addedin der Index-Spalte - In beiden, aber mit unterschiedlichem Hash:
Modifiedin der Index-Spalte - In beiden mit demselben Hash:
Unmodifiedin der Index-Spalte
Schritt 3: Index mit Arbeitsbaum vergleichen
Für jede Datei im Index und im Arbeitsbaum:
- Im Index, aber nicht auf dem Datenträger:
Deletedin der Arbeitsbaum-Spalte - In beiden, aber mit unterschiedlichem Inhalt:
Modifiedin der Arbeitsbaum-Spalte - In beiden mit übereinstimmendem Inhalt:
Unmodifiedin der Arbeitsbaum-Spalte
Schritt 4: Nicht versionierte Dateien erkennen
Durchsuche das Arbeitsverzeichnis, überspringe .git/ und ignorierte Pfade und melde Dateien, die nicht im Index stehen, in beiden Spalten als Untracked.
Unterstützung für .gitignore
Pitmaster verarbeitet .gitignore-Dateien, um zu bestimmen, welche nicht versionierten Dateien als ignoriert oder nicht versioniert gemeldet werden sollen.
use Pitmaster\Status\GitIgnore;
Die Klasse GitIgnore verarbeitet gitignore-Muster aus:
.gitignoreim Repository-Stammverzeichnis.gitignorein Unterverzeichnissen.git/info/exclude
Unterstützte Mustersyntax:
- Glob-Muster (
*.log,build/) - Negation (
!important.log) - Nur für Verzeichnisse geltende Muster (abschließendes
/) - Führendes
/für auf das Stammverzeichnis bezogene Muster **für rekursive Übereinstimmungen
Statuseinträge kategorisieren
Ein gängiges Muster zur Anzeige von 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;
}
}
Verwendung von CLI
./vendor/bin/pitmaster status
Ausgabe:
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 enthält eine Hilfsfunktion für das fsmonitor-Protokoll von git:
use Pitmaster\Status\Fsmonitor;
Die Klasse Fsmonitor kann den Hook core.fsmonitor abfragen (und greift ersatzweise auf einen Scan der Änderungszeiten zurück), um festzustellen, welche Dateien sich seit einem Token geändert haben. Bei Handles, die mit ['processes' => false] geöffnet wurden, wird die Funktion deaktiviert. status() ruft sie derzeit nicht auf, sondern vergleicht stat-Daten und Inhalte direkt.