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
use Pitmaster\Pitmaster;
$repo = Pitmaster::open('/path/to/project');
Pitmaster acceptă trei structuri de depozit:
- Depozite obișnuite:
.giteste un director în rădăcina proiectului. - Worktree-uri conectate:
.giteste un fișier care conținegitdir: <path>ce indică spre.git/worktrees/<name>/. - Depozite fără director de lucru: calea însăși conține
HEAD,objects/etc.
// 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
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:
$content = $repo->catFile('a1b2c3d4e5f6...');
echo $content;
objectExists
if ($repo->objectExists('a1b2c3d4e5f6...')) {
// Object is in the repository
}
listObjects
$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.
$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.
$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.
$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.
$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
$commit = $repo->head();
Rezolvă HEAD (urmând referințe simbolice precum HEAD -> refs/heads/main -> commit hash) și returnează obiectul commit.
Ramura curentă
$branch = $repo->branch(); // 'main' or null if detached
Listarea ramurilor și etichetelor
$branches = $repo->branches(); // ['bugfix/typo', 'feature/login', 'main']
$tags = $repo->tags(); // ['v1.0.0', 'v1.1.0']
Toate referințele
$refs = $repo->allRefs();
// [
// 'refs/heads/main' => 'abc123...',
// 'refs/heads/feature' => 'def456...',
// 'refs/tags/v1.0.0' => '789012...',
// 'refs/remotes/origin/main' => 'abc123...',
// ]
Rezolvarea reviziilor
$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.
// 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
$from = $repo->resolve('feature/login');
$commits = $repo->log(10, $from);
log filtrat după calea fișierului
$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
$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
$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
// 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'),
);