Indeksin muoto
Indeksitiedosto (.git/index) toimii välialueena. Se tallentaa seuraavaan committiin sisällytettävät tiedostot sekä metatiedot tilan tehokasta laskentaa varten. Pitmaster lukee indeksiversiot 2, 3 ja 4 sekä kirjoittaa versioita 2 ja 3. Versiona 4 luetun indeksin kirjoittaminen tuottaa tiedoston, jota git ei pysty lukemaan (#15), joten muunna tällaiset tietovarastot komennolla git update-index --index-version 2 ennen kirjoittamista komennon Pitmaster kautta.
Indeksin lukeminen
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() palauttaa tyhjän indeksin, jos tiedostoa ei ole. entries() palauttaa vain vaiheen 0 merkinnät; allEntries() sisältää ristiriitojen vaiheet, ja paths() luettelee seuratut polut.
IndexEntry
Jokainen indeksimerkintä on vain luku -arvo-olio:
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
Merkintöjen luominen
// 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);
Indeksin muokkaaminen
// 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() käsittelevät useita merkintöjä tai polkuja yhdellä kertaa. Merkintöjen muuttaminen poistaa tallennetut laajennukset (katso alla).
Indeksin kirjoittaminen
use Pitmaster\Index\IndexWriter;
IndexWriter::write($index, '/path/to/.git/index');
Tai tietovaraston kautta (joka hoitaa tämän automaattisesti):
$repo->add('src/File.php'); // Reads file, creates blob, updates index, writes
$repo->remove('--cached', 'old-file.txt'); // Removes from index only, writes
Binäärimuoto
Otsake
Signature: DIRC (4 bytes, ASCII)
Version: 4 bytes, big-endian (2, 3, or 4)
Entry count: 4 bytes, big-endian
Merkinnän muoto (v2)
Jokainen merkintä on seuraavanlainen:
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
Lipputietue:
- Bitti 15: assume-valid-lippu
- Bitit 13–12: yhdistämisvaihe (0–3)
- Bitit 11–0: polun nimen pituus tai 0xFFF, jos polku on vähintään 4095 tavua pitkä (lukija etsii tällöin NUL-tavua)
Versioiden erot
Versio 2: yllä kuvattu perusmuoto. Yleisin.
Versio 3: lisää laajennetut liput (2 lisätavua tavallisten lippujen jälkeen). Tukee bittejä skip-worktree ja intent-to-add. Käytössä, kun jokin merkintä tarvitsee laajennettuja lippuja.
Versio 4: lisää polkujen etuliitteiden pakkauksen. Täysien polkujen tallentamisen sijaan kukin merkintä tallentaa edellisen merkinnän polusta poistettavien tavujen määrän ja sen jälkeen uuden loppuosan. Pienentää huomattavasti syvälle sisäkkäisten puiden indeksin kokoa.
Ristiriitojen vaiheet
Yhdistämisristiriidan aikana yhdellä polulla voi olla useita indeksimerkintöjä eri vaiheissa:
| Vaihe | Merkitys |
|---|---|
| 0 | Tavallinen (ei ristiriitaa) |
| 1 | Perusversio (yhteinen kantaisä) |
| 2 | Meidän versiomme (nykyinen haara) |
| 3 | Heidän versionsa (yhdistettävä haara) |
// 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]
Indeksin laajennukset
Laajennukset lisätään merkintöjen jälkeen ja ennen tarkistussummaa. Kussakin laajennuksessa on 4 tavun tunniste, 4 tavun koko ja vaihtelevan pituista dataa.
Pitmaster säilyttää laajennuslohkot raak tavuina ($index->extensions() palauttaa signature- ja data-pareja) ja kirjoittaa ne takaisin muuttamattomina, kun merkintöjä ei ole muokattu. Se ei tulkitse tai luo laajennuksia, ja merkintöjen muuttaminen poistaa ne kaikki. Tämän git hyväksyy ja rakentaa tarvittaessa uudelleen. Alla kuvataan viitteeksi git-laajennukset.
TREE-laajennus
Tallentaa hakemistojen valmiiksi lasketut puuobjektit välimuistiin. Nopeuttaa komentoja git status ja git commit välttämällä puiden uudelleenlaskennan, kun vain indeksi on muuttunut.
Tunniste: TREE (0x54524545)
REUC-laajennus
Tallentaa ristiriitojen ratkaisemisen kumoamiseen tarvittavat tiedot. Kun ristiriita on ratkaistu, alkuperäiset vaiheiden 1/2/3 merkinnät siirretään tänne, jotta ne voi palauttaa komennolla git checkout -m.
Tunniste: REUC (0x52455543)
Muut laajennukset
git kirjoittaa myös seuraavat:
EOIE(indeksimerkinnän loppu): ilmaisee, mihin merkinnät päättyvät ja laajennukset alkavatIEOT(indeksimerkintöjen siirtymätaulukko): mahdollistaa indeksin rinnakkaisen lataamisenlink(jaettu indeksi): hyvin suurille tietovarastoille, joissa käytetään jaettua indeksiä
git-muodossa isolla kirjaimella alkavan allekirjoituksen laajennukset ovat valinnaisia ja pienellä alkavat pakollisia. Pitmaster hyväksyy molemmat tyypit tarkistamatta niitä. Jaetun indeksin (link) tietoja ei ladata, joten sitä käyttävät repositoriot eivät ole tuettuja.
Tarkistussumma
Indeksitiedoston lopussa on tarkistussumma kaikista sitä edeltävistä tavuista tietovaraston tiivistealgoritmilla (20 tavua SHA-1-algoritmilla, 32 tavua SHA-256-algoritmilla). Pitmaster kirjoittaa sen tallennuksen yhteydessä, mutta ei tarkista sitä luettaessa.
Index::open() ja Index::parse() heittävät IndexParseException-poikkeuksen, jos DIRC-tunniste puuttuu tai versio ei ole tuettu.
Indeksi ja tila
Indeksi on keskeinen osa tilan laskentaa. WorkingTreeStatus vertaa:
- HEAD-puuta indeksiin: havaitsee indeksiin lisätyt muutokset
- Indeksiä työpuuhun: havaitsee indeksiin lisäämättömät muutokset
Tilakentät (ctime, mtime, dev, ino, size, mode, uid, gid) mahdollistavat nopeat tarkistukset ilman tiedoston sisällön lukemista. Jos tilakentät täsmäävät ja tiedoston viimeisin muokkaus on ennen tilan tarkistuksen alkua, tiedoston oletetaan olevan muuttumaton. Eri koko merkitsee tiedoston heti muokatuksi. Muussa tapauksessa Pitmaster lukee tiedoston ja laskee sen tiivisteen sisällön muutosten tarkistamiseksi.
Oleta kelvolliseksi -lippu
if ($entry->assumeValid()) {
// Entry has assume-valid set (flags & 0x8000)
}
Tämä lippu käskee gitiä ohittamaan tiedoston tarkistuksen tilatietoja laskettaessa, vaikka tilakentät olisivat muuttuneet (git update-index --assume-unchanged). Pitmaster säilyttää bitin kirjoittaessaan merkinnät uudelleen, mutta sen tilatarkistus ei huomioi sitä, vaan vertaa tiedostoa silti.