Aller au contenu

État

Pitmaster calcule l’état de l’arbre de travail en comparant trois états : l’arbre du commit HEAD, l’index (zone de préparation) et l’arbre de travail (fichiers présents sur le disque). CLI en affiche un résumé au format git status, et statusPorcelainV2() affiche le format porcelain v2 de git.

Utilisation de base

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

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

shortFormat() affiche le format court de git :

Code
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

L’état de chaque fichier est représenté par 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"

Énumération 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() ne signale pas les fichiers ignorés ; Ignored n’apparaît donc pas dans son résultat.

Sortie porcelain v2

Pour obtenir une sortie d’état lisible par machine correspondant à git status --porcelain=v2 :

PHP
echo $repo->statusPorcelainV2();

Sortie :

Code
1 .M N... 100644 100644 100644 ce013625030ba8dba906f756967f9e9ca394464a ce013625030ba8dba906f756967f9e9ca394464a modified-file.txt
? untracked-file.txt

Les entrées suivies sont affichées en premier, puis les entrées non suivies. Les renommages utilisent des lignes 2 et les conflits, des lignes u. Les en-têtes # branch de git status --porcelain=v2 --branch ne sont pas affichés et les fichiers ignorés ne sont pas répertoriés.

Calcul de l’état

La classe WorkingTreeStatus effectue la comparaison en trois étapes :

PHP
use Pitmaster\Status\WorkingTreeStatus;

$status = new WorkingTreeStatus($repo->objectDatabase(), $repo->workDir(), $repo->gitDir());
$entries = $status->compute($repo->index(), $repo->resolve('HEAD'));

Étape 1 : créer la carte de l’arbre HEAD

Aplatit l’arbre du commit HEAD en une carte de path => blob hash. Elle représente le dernier état validé.

Étape 2 : comparer HEAD à l’index

Pour chaque fichier de l’arbre HEAD et de l’index :

  • Dans HEAD, mais pas dans l’index : Deleted dans la colonne de l’index
  • Dans l’index, mais pas dans HEAD : Added dans la colonne de l’index
  • Dans les deux, mais avec un hachage différent : Modified dans la colonne de l’index
  • Dans les deux, avec le même hachage : Unmodified dans la colonne de l’index

Étape 3 : comparer l’index à l’arbre de travail

Pour chaque fichier de l’index et de l’arbre de travail :

  • Dans l’index, mais absent du disque : Deleted dans la colonne de l’arbre de travail
  • Dans les deux, mais avec un contenu différent : Modified dans la colonne de l’arbre de travail
  • Dans les deux, avec un contenu identique : Unmodified dans la colonne de l’arbre de travail

Étape 4 : détecter les fichiers non suivis

Parcourt le répertoire de l’arbre de travail, ignore .git/ et les chemins ignorés, puis signale comme Untracked dans les deux colonnes les fichiers absents de l’index.

Prise en charge de .gitignore

Pitmaster analyse les fichiers .gitignore pour déterminer quels fichiers non suivis doivent être signalés comme ignorés ou non suivis.

PHP
use Pitmaster\Status\GitIgnore;

La classe GitIgnore analyse les motifs gitignore provenant de :

  • .gitignore à la racine du dépôt
  • .gitignore dans les sous-répertoires
  • .git/info/exclude

Syntaxe des motifs prise en charge :

  • Motifs glob (*.log, build/)
  • Négation (!important.log)
  • Motifs réservés aux répertoires (/ final)
  • / en début de motif pour le rendre relatif à la racine
  • ** pour une correspondance récursive

Catégoriser les entrées d’état

Un modèle courant d’affichage de 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;
    }
}

Utilisation de CLI

Shell
./vendor/bin/pitmaster status

Sortie :

Code
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 inclut un utilitaire pour le protocole fsmonitor de git :

PHP
use Pitmaster\Status\Fsmonitor;

La classe Fsmonitor peut interroger le hook core.fsmonitor (et, à défaut, effectuer un balayage des dates de modification) pour déterminer quels fichiers ont changé depuis un jeton. Elle se désactive pour les handles ouverts avec ['processes' => false]. status() ne l’appelle pas pour le moment : il compare directement les données stat et le contenu.