Състояние
Pitmaster изчислява състоянието на работното дърво, като сравнява три състояния: дървото на commit-а HEAD, индекса (зоната за подготовка) и работното дърво (реалните файлове на диска). CLI отпечатва обобщение в стил git status, а statusPorcelainV2() отпечатва формата porcelain v2 на git.
Основна употреба
$entries = $repo->status();
foreach ($entries as $entry) {
echo $entry->shortFormat() . "\n";
}
shortFormat() отпечатва краткия формат на 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
Състоянието на всеки файл е представено с 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"
Перечисление 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() не отчита игнорираните файлове, затова Ignored не се появява в резултата му.
Изход във формат Porcelain v2
За машинночетим изход за състоянието, съответстващ на git status --porcelain=v2:
echo $repo->statusPorcelainV2();
Изход:
1 .M N... 100644 100644 100644 ce013625030ba8dba906f756967f9e9ca394464a ce013625030ba8dba906f756967f9e9ca394464a modified-file.txt
? untracked-file.txt
Първо се показват проследяваните записи, а след тях — непроследяваните. Преименуванията използват редове 2, а конфликтите — редове u. Заглавията # branch на git status --porcelain=v2 --branch не се отпечатват и игнорираните файлове не се показват.
Как се изчислява състоянието
Класът WorkingTreeStatus извършва тристранното сравнение:
use Pitmaster\Status\WorkingTreeStatus;
$status = new WorkingTreeStatus($repo->objectDatabase(), $repo->workDir(), $repo->gitDir());
$entries = $status->compute($repo->index(), $repo->resolve('HEAD'));
Стъпка 1: Създаване на карта на дървото HEAD
Дървото на commit-а HEAD се преобразува в карта на path => blob hash. Тя представя последното записано състояние.
Стъпка 2: Сравняване на HEAD с индекса
За всеки файл в дървото HEAD и индекса:
- В HEAD, но не и в индекса:
Deletedв колоната за индекса - В индекса, но не и в HEAD:
Addedв колоната за индекса - И в двете, но с различен хеш:
Modifiedв колоната за индекса - И в двете с еднакъв хеш:
Unmodifiedв колоната за индекса
Стъпка 3: Сравняване на индекса с работното дърво
За всеки файл в индекса и работното дърво:
- В индекса, но не и на диска:
Deletedв колоната за работното дърво - И в двете, но съдържанието се различава:
Modifiedв колоната за работното дърво - И в двете с еднакво съдържание:
Unmodifiedв колоната за работното дърво
Стъпка 4: Откриване на непроследявани файлове
Обхожда директорията на работното дърво, пропуска .git/ и игнорираните пътища и отчита като Untracked и в двете колони файловете, които не присъстват в индекса.
Поддръжка на .gitignore
Pitmaster анализира файловете .gitignore, за да определи кои непроследявани файлове трябва да се отчетат като игнорирани и кои като непроследявани.
use Pitmaster\Status\GitIgnore;
Класът GitIgnore анализира шаблоните gitignore от:
.gitignoreв основната директория на хранилището.gitignoreв поддиректориите.git/info/exclude
Поддържан синтаксис на шаблоните:
- Шаблони glob (
*.log,build/) - Отрицание (
!important.log) - Шаблони само за директории (завършващи с
/) - Начално
/за шаблони спрямо основната директория **за рекурсивно съвпадение
Категоризиране на записите за състоянието
Често срещан шаблон за показване на 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;
}
}
Употреба на CLI
./vendor/bin/pitmaster status
Изход:
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
Наблюдение на файловата система
Pitmaster включва помощен компонент за протокола fsmonitor на git:
use Pitmaster\Status\Fsmonitor;
Класът Fsmonitor може да прави заявки към hook-а core.fsmonitor (като преминава към сканиране по време на последна промяна при неуспех), за да разбере кои файлове са се променили след даден токен. Изключва се автоматично при манипулатори, отворени с ['processes' => false]. В момента status() не го извиква; вместо това сравнява данните от stat и съдържанието директно.