Pāriet uz saturu

Git objekti

Katrs objekts git repozitorijā tiek glabāts kā atsevišķs objekts. Ir četri veidi: blob (faila saturs), koki (direktoriju saraksti), komiti (momentuzņēmumi ar metadatiem) un tagi (anotētas atsauces). Katru objektu identificē tā satura SHA-1 jaucējvērtība.

Objektu veidi

Blob

Blob satur neapstrādātu faila saturu bez metadatiem (bez faila nosaukuma un atļaujām).

PHP
use Pitmaster\Object\Blob;

// Create from content
$blob = Blob::fromContent('Hello, world!');
echo $blob->content;    // 'Hello, world!'
echo $blob->size();     // 13
echo $blob->id->hex;    // SHA-1 hash
echo $blob->type->value; // 'blob' (the property is ObjectType::Blob)

Koks

Koks ir direktorijas saraksts. Katram ierakstam ir režīms, nosaukums un jaucējvērtība, kas norāda uz blob vai apakškoku.

PHP
use Pitmaster\Object\Tree;
use Pitmaster\Object\TreeEntry;

// Read a tree
$tree = $repo->readObject($treeHash);

foreach ($tree->entries as $entry) {
    echo "{$entry->mode} {$entry->name} {$entry->hash->hex}\n";
}

// Look up a specific entry
$entry = $tree->entry('README.md');

// Create a tree (entries already in git's sort order)
$entries = [
    new TreeEntry('100644', 'README.md', $blobId),
    new TreeEntry('100755', 'deploy.sh', $execBlobId),
    new TreeEntry('40000', 'src', $subtreeId),
];

$tree = Tree::fromEntries($entries);

Tree::fromEntries() ieraksta vienumus norādītajā secībā un režīmu virknes tieši tādas, kā norādīts, tāpēc vispirms tās sakārtojiet un direktoriju režīmus norādiet kā 40000. Koks, kas ierakstīts ar 040000 vai citā secībā, iegūst citādu jaucējvērtību nekā git, un git fsck --strict izvada režīmu ar nullēm sākumā.

TreeEntry

TreeEntry ir tikai lasāms vērtības objekts:

PHP
use Pitmaster\Object\TreeEntry;

$entry->mode;   // '100644', '100755', '40000', '120000', '160000'
$entry->name;   // Filename
$entry->hash;   // ObjectId

// Type checks
$entry->isBlob();        // regular or executable file (mode 10xxxx)
$entry->isExecutable();  // mode 100755
$entry->isTree();        // mode 40000 (also accepts 040000)
$entry->isSymlink();     // mode 120000
$entry->isGitlink();     // mode 160000 (submodule)

Režīmu vērtības:

Režīms Nozīme
100644 Parasts fails
100755 Izpildāms fails
40000 Direktorija (koks); git ls-tree to rāda kā 040000
120000 Simboliskā saite
160000 Gitlink (apakšmodulis)

Koka ieraksti tiek sakārtoti pēc nosaukuma, salīdzināšanas nolūkos pieņemot, ka direktoriju nosaukumu beigās ir /.

Komits

Komits sasaista koku ar tā vēsturi un metadatiem.

PHP
use Pitmaster\Object\Commit;

$commit = $repo->head();

$commit->id;         // ObjectId
$commit->tree;       // ObjectId of the tree
$commit->parents;    // array of ObjectId (zero for root, one for normal, two+ for merge)
$commit->author;     // 'Name <email> timestamp timezone'
$commit->committer;  // 'Name <email> timestamp timezone'
$commit->message;    // Full commit message

$commit->isMerge();  // true if two or more parents

Komita satura veidošana

PHP
$content = Commit::buildContent(
    tree: $treeId,
    parents: [$parentId],
    author: 'Jane <jane@example.com> 1700000000 +0000',
    committer: 'Jane <jane@example.com> 1700000000 +0000',
    message: "Add feature\n",
);

Neapstrādāta komita formāts:

Kods
tree <hex hash>\n
parent <hex hash>\n       (zero or more)
author <name> <<email>> <timestamp> <tz>\n
committer <name> <<email>> <timestamp> <tz>\n
\n
<message>

Tags

Anotēti tagi ir objekti ar metadatiem.

PHP
use Pitmaster\Object\Tag;

$tag = $repo->readObject($tagHash);

$tag->object;        // ObjectId of the target
$tag->objectType;    // ObjectType enum (ObjectType::Commit, ...)
$tag->name;          // Tag name
$tag->tagger;        // 'Name <email> timestamp timezone'
$tag->message;       // Tag message

Neapstrādāts taga formāts:

Kods
object <hex hash>\n
type commit\n
tag <name>\n
tagger <name> <<email>> <timestamp> <tz>\n
\n
<message>

ObjectId

ObjectId ir tikai lasāms vērtības objekts, kas attēlo SHA-1 (vai SHA-256) jaucējvērtību.

PHP
use Pitmaster\Object\ObjectId;
use Pitmaster\Object\ObjectType;

// From hex string
$id = ObjectId::fromHex('a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2');

// From binary (20 bytes for SHA-1, 32 for SHA-256)
$id = ObjectId::fromBinary($rawBytes);

// Compute from content
$id = ObjectId::compute(ObjectType::Blob, 'Hello, world!');
$id = ObjectId::compute(ObjectType::Blob, 'Hello, world!', 'sha256');

// Zero hash
$id = ObjectId::zero();
$id = ObjectId::zero('sha256');

// Properties
$id->hex;      // 40-character hex string (64 for SHA-256)
$id->binary;   // 20-byte raw binary (32 for SHA-256)
$id->algo;     // 'sha1' or 'sha256'
$id->isSha256();
$id->isZero();

// Comparison
$id->equals($otherId);

Jaucējvērtība tiek aprēķināta no nesaspiestajiem datiem: sha1("{type} {size}{content}") vai tādu pašu baitu SHA-256. fromHex() un fromBinary() izvēlas algoritmu pēc garuma.

ObjectType uzskaitījums

PHP
use Pitmaster\Object\ObjectType;

ObjectType::Blob;    // 'blob'
ObjectType::Tree;    // 'tree'
ObjectType::Commit;  // 'commit'
ObjectType::Tag;     // 'tag'

Atsevišķu objektu formāts

Atsevišķi objekti tiek glabāti kā atsevišķi faili mapē .git/objects/, sakārtoti pēc pirmajām divām savas jaucējvērtības heksadecimālajām rakstzīmēm.

Kods
.git/objects/a1/b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2

Faila saturs ir saspiests ar zlib. Nesaspiestais saturs ir šāds:

Kods
<type> <decimal size>\0<raw content>

Piemēram, blob, kas satur “Hello”, tiek saglabāts šādi:

Kods
zlib_encode("blob 5\0Hello")

Atsevišķu objektu nolasīšana

PHP
use Pitmaster\Storage\LooseObjectStore;

$store = new LooseObjectStore('/path/to/.git/objects');
$object = $store->read($objectId);

LooseObjectStore:

  1. Aprēķina faila ceļu pēc jaucējvērtības
  2. Nolasa un atspiež failu ar zlib
  3. Parsē galveni, lai iegūtu veidu un izmēru
  4. Nodod attiecīgajam parsētājam (Blob, Tree, Commit, Tag)

Atsevišķu objektu ierakstīšana

PHP
$store->write($object);

Ierakstīšanas process:

  1. Serializēt: "{type} {size}\0{content}"
  2. Izmantot objekta id, kas aprēķināts objekta izveides laikā (nolasot jaucējvērtība tiek pārbaudīta)
  3. Saspiest: zlib_encode(serialized)
  4. Ierakstīt mapē .git/objects/{hash[0..1]}/{rest of hash}
  5. Veikt atomisku ierakstīšanu (ierakstīt pagaidu failā un pēc tam pārdēvēt)

ObjectSerializer

ObjectSerializer apstrādā objekta vadu formāta kodēšanu un dekodēšanu.

PHP
use Pitmaster\Storage\ObjectSerializer;

// Encode
$raw = ObjectSerializer::encodeRaw($object);
// "blob 5\0Hello"
$compressed = ObjectSerializer::encode($object);
// zlib-compressed form, as stored in a loose object file

// Decode
$object = ObjectSerializer::decodeRaw($raw);
$object = ObjectSerializer::decode($compressed, $expectedHex); // throws CorruptObjectException on a hash mismatch

ObjectDatabase

ObjectDatabase ir kombinēta krātuve, kas vispirms meklē atsevišķos objektus un pēc tam pakotņu failos.

PHP
use Pitmaster\Storage\ObjectDatabase;

$db = new ObjectDatabase('/path/to/.git/objects');

$object = $db->read($objectId);    // Search loose, then packs
$db->write($object);               // Always writes to loose
$exists = $db->exists($objectId);  // Check loose, then packs
$all = $db->listAll();             // All hashes from loose + packs

Rakstīšana tieši atsevišķo objektu krātuvē ir apzināta izvēle. Ļaujiet git gc pārpakot objektus pakotņu failos.

SHA-256 atbalsts

Pitmaster abstrahē jaucējalgoritmu, izmantojot ObjectId. SHA-1 ir noklusējums. SHA-256 tiek izvēlēts katram repozitorijam tā izveides laikā:

PHP
$repo = Pitmaster::init('/path/to/project', 'sha256');
Apvalks
./vendor/bin/pitmaster init --object-format=sha256

Tādējādi konfigurācijā tiek ierakstīts extensions.objectformat = sha256. Vēlāk atvērtie repozitoriji nolasa formātu no šī ieraksta, un visas objektu, koku, indeksa un atsauču darbības pēc tam izmanto 64 rakstzīmju heksadecimālas virknes un 32 baitu bināras jaucējvērtības. Algoritmam nav globāla slēdža vai konstantes.

Veidojot objektus pašiem, objektu klases pieņem algoritmu kā argumentu: Blob::fromContent($content, 'sha256'), Tree::fromEntries($entries, 'sha256'), ObjectId::compute($type, $content, 'sha256'). Pitmaster::clone() izveido SHA-1 repozitorijus.

Koka ieraksta binārais formāts

Koka objekta saturā katrs ieraksts tiek kodēts šādi:

Kods
<octal mode as ASCII> <space> <filename> \0 <binary hash: 20 bytes SHA-1, 32 bytes SHA-256>

Piezīme: jaucējvērtība ir neapstrādāti bināri dati, nevis heksadecimāla virkne, atšķirībā no komita un taga objektu heksadecimālajām jaucējvērtībām.

Ieraksti tiek sakārtoti, salīdzinot nosaukumus tā, it kā direktorijām beigās būtu /. Šai secībai jābūt precīzai, lai koka jaucējvērtība atbilstu git aprēķinātajai.