Aller au contenu

Lecture des dépôts

Pitmaster lit les dépôts git en analysant directement les formats sur disque : objets libres (fichiers compressés avec zlib dans .git/objects/), fichiers pack (.git/objects/pack/), refs (fichiers dans .git/refs/ et packed-refs) et index (.git/index).

Ouvrir un dépôt

PHP
use Pitmaster\Pitmaster;

$repo = Pitmaster::open('/path/to/project');

Pitmaster prend en charge trois organisations de dépôt :

  1. Dépôts classiques : .git est un répertoire à la racine du projet.
  2. Arbres de travail liés : .git est un fichier contenant gitdir: <path> pointant vers .git/worktrees/<name>/.
  3. Dépôts nus : le chemin lui-même contient HEAD, objects/, etc.
PHP
// Detection helpers
Pitmaster::isRepository('/path');  // true for any of the above
Pitmaster::isWorktree('/path');    // true only for linked worktrees

Lire les objets

Chaque donnée d’un dépôt git est stockée sous forme d’objet identifié par son hash : SHA-1 (40 caractères hexadécimaux) par défaut, ou SHA-256 (64 caractères hexadécimaux) dans les dépôts créés avec Pitmaster::init($path, 'sha256'). Il existe quatre types d’objets : blob, tree, commit et tag.

Les méthodes ci-dessous basées sur le hash attendent le hash hexadécimal complet ; les hash abrégés ne sont pas acceptés.

readObject

PHP
use Pitmaster\Object\Blob;
use Pitmaster\Object\Tree;
use Pitmaster\Object\Commit;
use Pitmaster\Object\Tag;

$object = $repo->readObject('a1b2c3d4e5f6...');

match (true) {
    $object instanceof Blob   => handleBlob($object),
    $object instanceof Tree   => handleTree($object),
    $object instanceof Commit => handleCommit($object),
    $object instanceof Tag    => handleTag($object),
};

Les objets sont d’abord recherchés dans le stockage libre, puis dans les fichiers pack. Les recherches dans les fichiers pack utilisent la table de dispersion .idx pour une recherche binaire O(log n).

catFile

Pour récupérer simplement le contenu sans vérifier son type :

PHP
$content = $repo->catFile('a1b2c3d4e5f6...');
echo $content;

objectExists

PHP
if ($repo->objectExists('a1b2c3d4e5f6...')) {
    // Object is in the repository
}

listObjects

PHP
$hashes = $repo->listObjects();
// ['a1b2c3d4...', 'f6e5d4c3...', ...]

Renvoie les hash hexadécimaux de tous les objets (libres et empaquetés).

Utiliser des blobs

Un blob contient le contenu brut d’un fichier.

PHP
$blob = $repo->readObject($hash);
echo $blob->content;     // Raw file bytes
echo $blob->size();      // Content length
echo $blob->id->hex;     // Object hash

Utiliser des arbres

Un arbre est une liste de répertoires. Chaque entrée comprend un mode, un nom et un hachage.

PHP
$tree = $repo->readObject($hash);

foreach ($tree->entries as $entry) {
    echo "{$entry->mode} {$entry->name} {$entry->hash->hex}\n";
    // 100644 README.md abc123...
    // 40000 src def456...
    // 100755 deploy.sh 789012...

    if ($entry->isTree()) {
        // Recurse into subdirectory (mode 40000)
    } elseif ($entry->isExecutable()) {
        // Executable file (mode 100755)
    } elseif ($entry->isBlob()) {
        // Regular file (any 10xxxx mode, so executables match too)
    } elseif ($entry->isSymlink()) {
        // Symbolic link (mode 120000)
    } elseif ($entry->isGitlink()) {
        // Submodule (mode 160000)
    }
}

Travailler avec les commits

Un commit relie un instantané d’arbre à ses parents et à ses métadonnées.

PHP
$commit = $repo->head();

echo $commit->id->hex;      // Full object hash
echo $commit->tree->hex;    // Tree object hash
echo $commit->author;       // "Name <email> timestamp tz"
echo $commit->committer;    // "Name <email> timestamp tz"
echo $commit->message;      // Full commit message

// Parent commits
foreach ($commit->parents as $parentId) {
    $parent = $repo->readObject($parentId->hex);
}

// Merge detection
if ($commit->isMerge()) {
    // Two or more parents
}

Travailler avec les tags

Les tags annotés sont des objets comprenant une cible, un type, un nom, un tagueur et un message.

PHP
$tag = $repo->readObject($hash);

echo $tag->object->hex;           // Target object hash
echo $tag->objectType->value;     // 'commit', 'tree', 'blob', or 'tag'
echo $tag->name;            // Tag name
echo $tag->tagger;          // "Name <email> timestamp tz"
echo $tag->message;         // Tag message

Lire les références

HEAD actuel

PHP
$commit = $repo->head();

Résout HEAD (en suivant les références symboliques comme HEAD -> refs/heads/main -> commit hash) et renvoie l’objet commit.

Branche actuelle

PHP
$branch = $repo->branch();  // 'main' or null if detached

Lister les branches et les tags

PHP
$branches = $repo->branches();  // ['bugfix/typo', 'feature/login', 'main']
$tags = $repo->tags();          // ['v1.0.0', 'v1.1.0']

Toutes les références

PHP
$refs = $repo->allRefs();
// [
//     'refs/heads/main' => 'abc123...',
//     'refs/heads/feature' => 'def456...',
//     'refs/tags/v1.0.0' => '789012...',
//     'refs/remotes/origin/main' => 'abc123...',
// ]

Résoudre les révisions

PHP
$id = $repo->resolve('HEAD');
$id = $repo->resolve('main');
$id = $repo->resolve('v1.0.0');
$id = $repo->resolve('HEAD~3');
$id = $repo->resolve('main^2');
$id = $repo->resolve('3f2c1e0b9d6a4f8e7c5b2a1d0e9f8c7b6a5d4e3f');

L’analyseur de révisions prend en charge les opérateurs ~N (ancêtre) et ^N (parent), qui peuvent être chaînés sans limite. Les hachages doivent être fournis en entier.

Parcourir l’historique des commits

log

Les commits sont renvoyés du plus récent au plus ancien, selon l’horodatage du committer.

PHP
// Last 20 commits from HEAD
$commits = $repo->log(20);

foreach ($commits as $commit) {
    $short = substr($commit->id->hex, 0, 7);
    echo "{$short} {$commit->message}\n";
}

log à partir d’un commit spécifique

PHP
$from = $repo->resolve('feature/login');
$commits = $repo->log(10, $from);

log filtré par chemin de fichier

PHP
$commits = $repo->logPath('src/Repository.php', 20);

Renvoie uniquement les commits où le fichier indiqué a été modifié (ajouté, modifié, supprimé ou renommé) par rapport au premier parent. Le chemin doit correspondre exactement à un fichier ; les répertoires ne correspondent pas. Seuls les 5 * $limit commits les plus récents sont examinés : des correspondances plus anciennes peuvent manquer (#7).

show

PHP
$result = $repo->show('HEAD');
$commit = $result['commit'];
$diffs = $result['diff'];

echo "Author: {$commit->author}\n";
echo "Message: {$commit->message}\n\n";

foreach ($diffs as $diff) {
    echo $diff->format();
}

Détection de la branche par défaut

PHP
$default = $repo->defaultBranch();
// Checks: remote HEAD symref -> local HEAD -> main/master fallback

Lorsque remote.origin.url est défini et que les processus sont activés, la première vérification envoie une requête HTTP intelligente au dépôt distant. Les erreurs réseau sont ignorées et les vérifications locales suivent.

Ancêtres de fusion

PHP
// Is feature fully merged into main?
$merged = $repo->isBranchMerged('feature/done', 'main');

// Find the merge base of two commits
$base = $repo->mergeBase(
    $repo->resolve('main'),
    $repo->resolve('feature/login'),
);