Indeksa formāts
Indeksa fails (.git/index) ir sagatavošanas apgabals. Tajā tiek reģistrēti faili, kas tiks iekļauti nākamajā komitā, kā arī metadati efektīvai statusa aprēķināšanai. Pitmaster nolasa indeksa 2., 3. un 4. versiju un raksta 2. un 3. versiju. Ierakstot indeksu, kas nolasīts kā 4. versija, tiek izveidots git nelasāms fails (#15), tāpēc pirms rakstīšanas ar Pitmaster pārveidojiet šādus repozitorijus, izmantojot git update-index --index-version 2.
Indeksa nolasīšana
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() atgriež tukšu indeksu, ja fails neeksistē. entries() atgriež tikai 0. posma ierakstus; allEntries() iekļauj konfliktu posmus, bet paths() uzskaita izsekotos ceļus.
IndexEntry
Katrs indeksa ieraksts ir tikai lasāms vērtības objekts:
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
Ierakstu izveide
// 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);
Indeksa modificēšana
// 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() un removeEntries() vienā reizē apstrādā vairākus ierakstus vai ceļus. Jebkuras izmaiņas ierakstos dzēš saglabātos paplašinājumus (sk. tālāk).
Indeksa ierakstīšana
use Pitmaster\Index\IndexWriter;
IndexWriter::write($index, '/path/to/.git/index');
Vai arī ar repozitorija starpniecību (tas to apstrādā automātiski):
$repo->add('src/File.php'); // Reads file, creates blob, updates index, writes
$repo->remove('--cached', 'old-file.txt'); // Removes from index only, writes
Binārais formāts
Galvene
Signature: DIRC (4 bytes, ASCII)
Version: 4 bytes, big-endian (2, 3, or 4)
Entry count: 4 bytes, big-endian
Ieraksta formāts (v2)
Katrs ieraksts ir šāds:
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
Karodziņu lauks:
- bits: pieņemt kā derīgu karodziņu
- 13.–12. biti: sapludināšanas posms (0–3)
- 11.–0. biti: ceļa nosaukuma garums vai 0xFFF, ja ceļš ir vismaz 4095 baitu garš (tad lasītājs meklē NUL)
Versiju atšķirības
2. versija: iepriekš aprakstītais pamatformāts. Visizplatītākā.
3. versija: pievieno paplašinātos karodziņus (2 papildu baiti pēc parastajiem karodziņiem). Atbalsta bitus skip-worktree un intent-to-add. Tiek izmantota, ja kādam ierakstam nepieciešami paplašinātie karodziņi.
4. versija: pievieno ceļu prefiksu saspiešanu. Pilnu ceļu vietā katrā ierakstā tiek norādīts, cik baitu jānoņem no iepriekšējā ieraksta ceļa, un pēc tam jaunais sufikss. Tas ievērojami samazina indeksa izmēru dziļi ligzdotos kokos.
Konfliktu posmi
Sapludināšanas konflikta laikā vienam ceļam var būt vairāki indeksa ieraksti dažādos posmos:
| Posms | Nozīme |
|---|---|
| 0 | Parasts (bez konflikta) |
| 1 | Bāzes versija (kopīgais priekštecis) |
| 2 | Mūsu versija (pašreizējais zars) |
| 3 | Viņu versija (sapludināmais zars) |
// 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]
Indeksa paplašinājumi
Paplašinājumi tiek pievienoti pēc ierakstiem un pirms kontrolsummas. Katram paplašinājumam ir 4 baitu paraksts, 4 baitu izmērs un mainīga garuma dati.
Pitmaster saglabā paplašinājumu blokus kā neapstrādātus baitus ($index->extensions() atgriež signature un data pārus) un ieraksta tos atpakaļ bez izmaiņām, ja ieraksti nav skarti. Tas nevienu paplašinājumu neinterpretē un neģenerē, un jebkuras izmaiņas ierakstos tos visus dzēš; git vajadzības gadījumā tos pieņem un izveido no jauna. Turpmāk ir aprakstīti git izmantotie paplašinājumi.
TREE paplašinājums
Kešatmiņā saglabā direktoriju iepriekš aprēķinātos koka objektus. Paātrina git status un git commit, jo nav atkārtoti jāaprēķina koki, ja mainījies tikai indekss.
Paraksts: TREE (0x54524545)
REUC paplašinājums
Reģistrē informāciju par konflikta atrisināšanas atsaukšanu. Pēc konflikta atrisināšanas sākotnējie 1./2./3. posma ieraksti tiek pārvietoti šeit, lai tos varētu atjaunot ar git checkout -m.
Paraksts: REUC (0x52455543)
Citi paplašinājumi
git raksta arī:
EOIE(indeksa ieraksta beigas): norāda, kur beidzas ieraksti un sākas paplašinājumiIEOT(indeksa ierakstu nobīžu tabula): nodrošina paralēlu indeksa ielādilink(sadalīts indekss): lieliem repozitorijiem, kuros izmantots sadalīts indekss
git formātā paplašinājumi, kuru paraksts sākas ar lielo burtu, nav obligāti, bet tie, kas sākas ar mazo burtu, ir obligāti. Pitmaster pieņem abus veidus bez pārbaudes. Sadalīts indekss (link) netiek ielādēts, tāpēc repozitoriji, kuros tas tiek izmantots, netiek atbalstīti.
Kontrolsumma
Indeksa faila beigās ir visu iepriekšējo baitu kontrolsumma, kas aprēķināta, izmantojot repozitorija jaucējalgoritmu (20 baiti SHA-1 gadījumā, 32 baiti SHA-256 gadījumā). Pitmaster to ieraksta saglabājot, bet nepārbauda lasīšanas laikā.
Index::open() un Index::parse() izmet IndexParseException, ja trūkst DIRC paraksta vai ir neatbalstīta versija.
Indekss un statuss
Indekss ir būtisks statusa aprēķināšanai. WorkingTreeStatus salīdzina:
- HEAD koku ar indeksu: nosaka indeksētās izmaiņas
- Indeksu ar darba koku: nosaka neindeksētās izmaiņas
Statistikas lauki (ctime, mtime, dev, ino, size, mode, uid, gid) ļauj ātri pārbaudīt, vai fails ir mainījies, nenolasot tā saturu. Ja statistikas lauki sakrīt un fails ir pēdējo reizi mainīts pirms statusa skenēšanas sākuma, tiek pieņemts, ka fails nav mainīts. Atšķirīgs izmērs uzreiz norāda uz izmaiņām. Pretējā gadījumā Pitmaster nolasa failu un aprēķina tā jaucējvērtību, lai pārbaudītu, vai saturs tiešām ir mainījies.
Pieņemt kā derīgu karodziņš
if ($entry->assumeValid()) {
// Entry has assume-valid set (flags & 0x8000)
}
Šis karodziņš liek git statusa pārbaudes laikā izlaist failu, pat ja statistikas lauki ir mainījušies (git update-index --assume-unchanged). Pitmaster saglabā šo bitu, pārrakstot ierakstus, taču tā statusa komanda to neņem vērā un joprojām salīdzina failu.