Indeksi vorming
Indeksifail (.git/index) on lavastusala. See salvestab järgmisse kinnistusse lisatavad failid koos metaandmetega, mis kiirendavad oleku arvutamist. Pitmaster loeb indeksiversioone 2, 3 ja 4 ning kirjutab versioone 2 ja 3. Versioonina 4 loetud indeksi kirjutamisel tekib fail, mida git ei suuda lugeda (#15), seega teisenda sellised hoidlad käsuga git update-index --index-version 2 enne, kui kirjutad käsuga Pitmaster.
Indeksi lugemine
use Pitmaster\Index\Index;
$index = Index::open('/path/to/.git/index'); // pass 32 as the second argument for SHA-256
// Or through the repository
$index = $repo->index();
// Entry count (all stages)
echo $index->count();
// Iterate stage 0 entries, keyed by path
foreach ($index->entries() as $path => $entry) {
echo "{$entry->path} {$entry->hash->hex}\n";
}
// Look up a specific entry
$entry = $index->entry('src/File.php');
Index::open() tagastab tühja indeksi, kui faili pole. entries() tagastab ainult 0. etapi kirjed; allEntries() kaasab konflikti etapid ja paths() loetleb jälgitavad rajad.
IndexEntry
Iga indeksikirje on kirjutuskaitstud väärtusobjekt:
use Pitmaster\Index\IndexEntry;
$entry->path; // File path relative to repo root
$entry->hash; // ObjectId of the blob
$entry->mode; // File mode as an int (0100644, 0100755, 0120000, 0160000)
$entry->fileSize; // File size in bytes
$entry->ctimeSec; // Metadata change time (seconds)
$entry->ctimeNsec; // Metadata change time nanoseconds
$entry->mtimeSec; // Modification time (seconds)
$entry->mtimeNsec; // Modification time nanoseconds
$entry->dev; // Device number
$entry->ino; // Inode number
$entry->uid; // User ID
$entry->gid; // Group ID
$entry->flags; // Raw flags field
$entry->extendedFlags; // v3 extended flags (skip-worktree, intent-to-add)
$entry->stage(); // Conflict stage (0 = normal, 1 = base, 2 = ours, 3 = theirs)
$entry->assumeValid(); // Assume-valid bit
$entry->skipWorktree(); // Skip-worktree bit
Kirjete loomine
// From file stat
$entry = IndexEntry::fromStat('src/File.php', $blobId, '/full/path/to/src/File.php');
// Minimal (no stat info)
$entry = IndexEntry::create('src/File.php', $blobId);
// With explicit mode
$entry = IndexEntry::create('deploy.sh', $blobId, 0100755);
Indeksi muutmine
// Add or replace an entry
$index->addEntry($entry);
// Remove an entry
$index->removeEntry('src/OldFile.php');
// Replace all stages of a conflicted path with one resolved entry
$index->resolveConflict('src/File.php', $entry);
addEntries() ja removeEntries() töötlevad ühe läbimisega mitu kirjet või rada. Kirjete mis tahes muudatus eemaldab salvestatud laiendused (vt allpool).
Indeksi kirjutamine
use Pitmaster\Index\IndexWriter;
IndexWriter::write($index, '/path/to/.git/index');
Või hoidla kaudu (mis teeb seda automaatselt):
$repo->add('src/File.php'); // Reads file, creates blob, updates index, writes
$repo->remove('--cached', 'old-file.txt'); // Removes from index only, writes
Binaarvorming
Päis
Signature: DIRC (4 bytes, ASCII)
Version: 4 bytes, big-endian (2, 3, or 4)
Entry count: 4 bytes, big-endian
Kirje vorming (v2)
Iga kirje koosneb järgmisest:
ctime seconds: 4 bytes, big-endian
ctime nanoseconds: 4 bytes, big-endian
mtime seconds: 4 bytes, big-endian
mtime nanoseconds: 4 bytes, big-endian
dev: 4 bytes, big-endian
ino: 4 bytes, big-endian
mode: 4 bytes, big-endian
uid: 4 bytes, big-endian
gid: 4 bytes, big-endian
file size: 4 bytes, big-endian
object hash: 20 bytes SHA-1 or 32 bytes SHA-256 (raw binary)
flags: 2 bytes, big-endian
path: variable length, NUL-terminated
padding: 1-8 NUL bytes to align to 8-byte boundary
Lippude väli:
- Bitt 15: eeldatavalt kehtiva oleku lipp
- Bitid 13–12: liitmise etapp (0–3)
- Bitid 11–0: raja nime pikkus või 0xFFF, kui raja pikkus on vähemalt 4095 baiti (sel juhul otsib lugeja NUL-i)
Versioonide erinevused
Versioon 2: eespool kirjeldatud põhivorming. Kõige levinum.
Versioon 3: lisab laiendatud lipud (tavaliste lippude järel 2 lisabaiti). Toetab bitte skip-worktree ja intent-to-add. Kasutusel, kui mõni kirje vajab laiendatud lippe.
Versioon 4: lisab radade eesliidete tihendamise. Täielike radade salvestamise asemel salvestatakse igas kirjes eelmisest rajast eemaldatavate baitide arv ja seejärel uus lõpp. Vähendab oluliselt indeksi suurust sügavalt pesastatud puude korral.
Konfliktietapid
Liitmis konflikti ajal võib ühel rajal olla mitu eri etappi indeksikirjet:
| Etapp | Tähendus |
|---|---|
| 0 | Tavaline (konflikt puudub) |
| 1 | Baasversioon (ühine eellane) |
| 2 | Meie oma (praegune haru) |
| 3 | Nende oma (liidetav haru) |
// During a conflict, entries have non-zero stages
foreach ($index->allEntries() as $entry) {
if ($entry->stage() > 0) {
echo "Conflict: {$entry->path} (stage {$entry->stage()})\n";
}
}
$index->hasUnmerged(); // true while conflicts remain
$index->unmergedPaths(); // conflicted paths
$index->stageEntries('a.txt'); // [1 => base, 2 => ours, 3 => theirs]
Indeksi laiendused
Laiendused lisatakse pärast kirjeid ja enne kontrollsummat. Igal laiendusel on 4-baidine signatuur, 4-baidine suurus ja muutuva pikkusega andmed.
Pitmaster säilitab laiendusplokid töötlemata baitidena ($index->extensions() tagastab paare signature ja data) ning kirjutab need muutmata kujul tagasi, kui kirjeid pole muudetud. See ei tõlgenda ega loo laiendusi ning kirjete muutmisel eemaldab need kõik; git aktsepteerib seda ja loob vajaduse korral laiendused uuesti. Allpool kirjeldatakse viiteks git-i kasutatavaid laiendusi.
TREE-laiendus
Salvestab kataloogide jaoks eelnevalt arvutatud puuobjektid vahemällu. Kiirendab käske git status ja git commit, vältides puude uuesti arvutamist, kui muutus ainult indeks.
Signatuur: TREE (0x54524545)
REUC-laiendus
Salvestab konflikti lahendamise tagasivõtmise teabe. Pärast konflikti lahendamist tõstetakse algsed 1/2/3 etapi kirjed siia, et need saaks käsuga git checkout -m taastada.
Signatuur: REUC (0x52455543)
Muud laiendused
git kirjutab ka:
EOIE(indeksikirje lõpp): märgib, kus kirjed lõpevad ja laiendused algavadIEOT(indeksikirje nihete tabel): võimaldab indeksi paralleelset laadimistlink(tükeldatud indeks): väga suurte hoidlade jaoks, kus kasutatakse tükeldatud indeksit
git-i vormingus on suurtähega algava signatuuriga laiendused valikulised ja väiketähega algavad kohustuslikud. Pitmaster aktsepteerib mõlemat tüüpi kontrollimata. Tükeldatud indeksit (link) ei laadita, seega ei toetata seda kasutavaid hoidlaid.
Kontrollsumma
Indeksifail lõpeb kõigi eelnevate baitide kontrollsummaga, mis arvutatakse hoidla räsialgoritmiga (20 baiti SHA-1, 32 baiti SHA-256). Pitmaster kirjutab selle salvestamisel, kuid ei kontrolli lugemisel.
Index::open() ja Index::parse() tekitavad IndexParseException, kui signatuur DIRC puudub või versiooni ei toetata.
Indeks ja olek
Indeks on oleku arvutamisel keskse tähtsusega. WorkingTreeStatus võrdleb:
- HEAD-i puud ja indeksit: tuvastab lisatud muudatused
- Indeksit ja tööpuud: tuvastab lisamata muudatused
Statistikaväljad (ctime, mtime, dev, ino, size, mode, uid, gid) võimaldavad kiiresti kontrollida, kas fail on muutunud, ilma faili sisu lugemata. Kui statistikaväljad kattuvad ja faili muudeti enne oleku skannimise algust, eeldatakse, et fail pole muutunud. Erinev suurus märgib faili kohe muudetuks. Vastasel juhul loeb Pitmaster faili ja arvutab selle räsi, et kontrollida, kas sisu on tegelikult muutunud.
Kehtivaks eeldamise lipp
if ($entry->assumeValid()) {
// Entry has assume-valid set (flags & 0x8000)
}
See lipp käsib git-il oleku kontrollimisel faili vahele jätta, isegi kui statistikaväljad on muutunud (git update-index --assume-unchanged). Pitmaster säilitab biti kirjete ümberkirjutamisel, kuid selle olekukontroll seda ei arvesta ja võrdleb faili siiski.