Treci la conținut

Citirea depozitelor

Pitmaster citește depozitele git analizând direct formatele de pe disc: obiecte loose (fișiere comprimate cu zlib în .git/objects/), fișiere pack (.git/objects/pack/), referințe (fișiere în .git/refs/ și packed-refs) și indexul (.git/index).

Deschiderea unui depozit

PHP
use Pitmaster\Pitmaster;

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

Pitmaster acceptă trei structuri de depozit:

  1. Depozite obișnuite: .git este un director în rădăcina proiectului.
  2. Worktree-uri conectate: .git este un fișier care conține gitdir: <path> ce indică spre .git/worktrees/<name>/.
  3. Depozite fără director de lucru: calea însăși conține HEAD, objects/ etc.
PHP
// Detection helpers
Pitmaster::isRepository('/path');  // true for any of the above
Pitmaster::isWorktree('/path');    // true only for linked worktrees

Citirea obiectelor

Fiecare fragment de date dintr-un depozit git este stocat ca obiect identificat prin hash: SHA-1 (40 de caractere hexazecimale) în mod implicit sau SHA-256 (64 de caractere hexazecimale) în depozitele create cu Pitmaster::init($path, 'sha256'). Există patru tipuri de obiecte: blob, arbore, commit și tag.

Metodele bazate pe hash de mai jos primesc hash-ul hexazecimal complet; hash-urile abreviate nu sunt acceptate.

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),
};

Obiectele sunt căutate mai întâi în stocarea loose, apoi în fișierele pack. Căutările în fișierele pack folosesc tabelul de dispersie .idx pentru căutarea binară O(log n).

catFile

Pentru preluarea simplă a conținutului fără verificarea tipului:

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...', ...]

Returnează hash-urile hexazecimale pentru toate obiectele (loose și împachetate).

Lucrul cu bloburi

Un blob conține conținutul brut al unui fișier.

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

Lucrul cu arbori

Un arbore este o listare de directoare. Fiecare intrare are un mod, un nume și un hash.

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)
    }
}

Lucrul cu commiturile

Un commit leagă un instantaneu al arborelui de părinții și metadatele sale.

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
}

Lucrul cu etichetele

Etichetele adnotate sunt obiecte cu o țintă, un tip, un nume, un autor al etichetei și un mesaj.

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

Citirea referințelor

HEAD curent

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

Rezolvă HEAD (urmând referințe simbolice precum HEAD -> refs/heads/main -> commit hash) și returnează obiectul commit.

Ramura curentă

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

Listarea ramurilor și etichetelor

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

Toate referințele

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

Rezolvarea reviziilor

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');

Parserul de revizii acceptă operatorii ~N (strămoș) și ^N (părinte), care pot fi înlănțuiți arbitrar. Hashurile trebuie furnizate integral.

Parcurgerea istoricului commiturilor

log

Commiturile sunt returnate de la cel mai nou la cel mai vechi, în ordinea marcajului temporal al autorului commitului.

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 pornind de la un anumit commit

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

log filtrat după calea fișierului

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

Returnează numai commiturile în care fișierul specificat a fost modificat (adăugat, modificat, șters sau redenumit) în comparație cu primul părinte. Calea trebuie să fie calea exactă a unui fișier; directoarele nu se potrivesc. Sunt examinate numai cele mai noi 5 * $limit commituri, așa că este posibil să lipsească potriviri mai vechi (#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();
}

Detectarea ramurii implicite

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

Când remote.origin.url este setat și procesele sunt activate, prima verificare trimite o cerere inteligentă HTTP către serverul la distanță. Erorile de rețea sunt ignorate, apoi urmează verificările locale.

Strămoșii de merge

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'),
);