Μετάβαση στο περιεχόμενο

Ανάγνωση αποθετηρίων

Το Pitmaster διαβάζει αποθετήρια git αναλύοντας απευθείας τις μορφές αρχείων στον δίσκο: χαλαρά αντικείμενα (αρχεία συμπιεσμένα με zlib στο .git/objects/), αρχεία pack (.git/objects/pack/), αναφορές (αρχεία στα .git/refs/ και packed-refs) και το ευρετήριο (.git/index).

Άνοιγμα αποθετηρίου

PHP
use Pitmaster\Pitmaster;

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

Το Pitmaster υποστηρίζει τρεις διατάξεις αποθετηρίων:

  1. Κανονικά αποθετήρια: το .git είναι κατάλογος στη ρίζα του έργου.
  2. Συνδεδεμένα worktrees: το .git είναι αρχείο που περιέχει το gitdir: <path> και δείχνει στο .git/worktrees/<name>/.
  3. Γυμνά αποθετήρια: η ίδια η διαδρομή περιέχει το HEAD, objects/ κ.λπ.
PHP
// Detection helpers
Pitmaster::isRepository('/path');  // true for any of the above
Pitmaster::isWorktree('/path');    // true only for linked worktrees

Ανάγνωση αντικειμένων

Κάθε δεδομένο σε ένα αποθετήριο git αποθηκεύεται ως αντικείμενο που προσδιορίζεται από το hash του: SHA-1 (40 δεκαεξαδικοί χαρακτήρες) από προεπιλογή ή SHA-256 (64 δεκαεξαδικοί χαρακτήρες) σε αποθετήρια που δημιουργούνται με Pitmaster::init($path, 'sha256'). Υπάρχουν τέσσερις τύποι αντικειμένων: blob, tree, commit και tag.

Οι παρακάτω μέθοδοι που βασίζονται σε hash δέχονται ολόκληρο το δεκαεξαδικό hash· δεν γίνονται δεκτά συντομευμένα hash.

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

Τα αντικείμενα αναζητούνται πρώτα στην αποθήκευση loose και μετά στα αρχεία pack. Οι αναζητήσεις σε αρχεία pack χρησιμοποιούν τον πίνακα fanout .idx για δυαδική αναζήτηση O(log n).

catFile

Για απλή ανάκτηση περιεχομένου χωρίς έλεγχο τύπου:

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

Επιστρέφει δεκαεξαδικά hash για όλα τα αντικείμενα (loose και packed).

Εργασία με blobs

Ένα blob περιέχει ακατέργαστο περιεχόμενο αρχείου.

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

Εργασία με δέντρα

Ένα δέντρο είναι μια καταχώριση καταλόγου. Κάθε εγγραφή έχει λειτουργία, όνομα και 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)
    }
}

Εργασία με commits

Ένα commit συνδέει ένα στιγμιότυπο δέντρου με τους γονείς και τα μεταδεδομένα του.

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
}

Εργασία με tags

Τα σχολιασμένα tags είναι αντικείμενα με στόχο, τύπο, όνομα, συντάκτη tag και μήνυμα.

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

Ανάγνωση refs

Τρέχον HEAD

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

Επιλύει το HEAD (ακολουθώντας συμβολικά refs όπως το HEAD -> refs/heads/main -> commit hash) και επιστρέφει το αντικείμενο commit.

Τρέχον branch

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

Καταχώριση branches και tags

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

Όλα τα refs

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

Επίλυση revisions

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

Ο αναλυτής revision υποστηρίζει τους τελεστές ~N (πρόγονος) και ^N (γονέας), με αλυσιδωτή εφαρμογή χωρίς περιορισμό. Τα hash πρέπει να δίνονται ολόκληρα.

Περιήγηση στο ιστορικό commit

καταγραφή

Τα commits επιστρέφονται με πρώτο το νεότερο, ταξινομημένα με βάση τη χρονική σήμανση του 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 από συγκεκριμένο commit

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

log φιλτραρισμένο κατά διαδρομή αρχείου

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

Επιστρέφει μόνο commits όπου το καθορισμένο αρχείο άλλαξε (προστέθηκε, τροποποιήθηκε, διαγράφηκε ή μετονομάστηκε) σε σύγκριση με τον πρώτο γονέα. Η διαδρομή πρέπει να είναι ακριβής διαδρομή αρχείου· οι κατάλογοι δεν αντιστοιχίζονται. Εξετάζονται μόνο τα νεότερα 5 * $limit commits, επομένως παλαιότερες αντιστοιχίες μπορεί να λείπουν (#7).

εμφάνιση

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

Εντοπισμός προεπιλεγμένου branch

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

Όταν έχει οριστεί το remote.origin.url και είναι ενεργοποιημένες οι διεργασίες, ο πρώτος έλεγχος στέλνει ένα έξυπνο αίτημα HTTP στο remote. Τα σφάλματα δικτύου αγνοούνται και ακολουθούν οι τοπικοί έλεγχοι.

Καταγωγή 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'),
);