
# Dizin Biçimi

Dizin dosyası (`.git/index`) hazırlama alanıdır. Sonraki commit'e eklenecek dosyaları, verimli durum hesaplaması için gerekli meta verilerle birlikte kaydeder. Pitmaster, 2, 3 ve 4 dizin sürümlerini okur; 2 ve 3 sürümlerini yazar. 4. sürüm olarak okunan bir dizinin yazılması, git tarafından okunamayan bir dosya üretir ([#15](https://github.com/inline0/pitmaster/issues/15)); bu nedenle Pitmaster üzerinden yazmadan önce bu depoları `git update-index --index-version 2` ile dönüştürün.

## Dizini okuma

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

Dosya yoksa `Index::open()` boş bir dizin döndürür. `entries()` yalnızca 0. aşama girdilerini döndürür; `allEntries()` çakışma aşamalarını içerir ve `paths()` izlenen yolları listeler.

## IndexEntry

Dizindeki her girdi salt okunur bir değer nesnesidir:

```php
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
```

### Girdi oluşturma

```php
// 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);
```

## Dizini değiştirme

```php
// 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()` ve `removeEntries()`, tek seferde birden fazla girdi veya yol alır. Girdilerdeki herhangi bir değişiklik, saklanan uzantıları kaldırır (aşağıya bakın).

## Dizini yazma

```php
use Pitmaster\Index\IndexWriter;

IndexWriter::write($index, '/path/to/.git/index');
```

Ya da bunu otomatik olarak yöneten depo üzerinden:

```php
$repo->add('src/File.php');    // Reads file, creates blob, updates index, writes
$repo->remove('--cached', 'old-file.txt'); // Removes from index only, writes
```

## İkili biçim

### Başlık

```
Signature:   DIRC (4 bytes, ASCII)
Version:     4 bytes, big-endian (2, 3, or 4)
Entry count: 4 bytes, big-endian
```

### Girdi biçimi (v2)

Her girdi şöyledir:

```
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
```

Bayraklar alanı:
- Bit 15: geçerli kabul et bayrağı
- Bit 13-12: birleştirme aşaması (0-3)
- Bit 11-0: yol adı uzunluğu; yol 4095 bayt veya daha uzunsa 0xFFF kullanılır (okuyucu bu durumda NUL karakterini arar)

### Sürümler arasındaki farklar

**Sürüm 2**: yukarıda açıklanan temel biçim. En yaygın sürüm.

**Sürüm 3**: genişletilmiş bayraklar ekler (normal bayraklardan sonra 2 ek bayt). `skip-worktree` ve `intent-to-add` bitlerini destekler. Herhangi bir girdi genişletilmiş bayrak gerektirdiğinde kullanılır.

**Sürüm 4**: yol öneki sıkıştırması ekler. Tam yolları saklamak yerine her girdi, önceki girdinin yolundan çıkarılacak bayt sayısını ve ardından yeni son eki saklar. İç içe dizinlerin derin olduğu ağaçlarda dizin boyutunu önemli ölçüde azaltır.

## Çakışma aşamaları

Birleştirme çakışması sırasında tek bir yol, farklı aşamalarda birden fazla dizin girdisine sahip olabilir:

| Aşama | Anlam |
|-------|---------|
| 0 | Normal (çakışma yok) |
| 1 | Taban sürümü (ortak ata) |
| 2 | Bizimki (geçerli dal) |
| 3 | Onlarınki (birleştirilen dal) |

```php
// 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]
```

## Dizin uzantıları

Uzantılar, girdilerden sonra ve sağlama toplamından önce eklenir. Her uzantıda 4 baytlık imza, 4 baytlık boyut ve değişken uzunlukta veri bulunur.

Pitmaster uzantı bloklarını ham baytlar olarak tutar (`$index->extensions()`, `signature` ve `data` çiftlerini döndürür) ve girdiler değiştirilmemişse bunları olduğu gibi geri yazar. Hiçbir uzantıyı yorumlamaz veya oluşturmaz; girdilerdeki herhangi bir değişiklik tüm uzantıları kaldırır. git bunları kabul eder ve gerektiğinde yeniden oluşturur. Başvuru amacıyla git tarafından kullanılan uzantılar aşağıda açıklanmıştır.

### TREE uzantısı

Dizinler için önceden hesaplanmış ağaç nesnelerini önbelleğe alır. Yalnızca dizin değiştiğinde ağaçların yeniden hesaplanmasını önleyerek `git status` ve `git commit` işlemlerini hızlandırır.

İmza: `TREE` (0x54524545)

### REUC uzantısı

Çakışmayı çözme geri alma bilgilerini kaydeder. Bir çakışma çözüldükten sonra, özgün 1/2/3. aşama girdileri buraya taşınır; böylece `git checkout -m` ile geri yüklenebilirler.

İmza: `REUC` (0x52455543)

### Diğer uzantılar

git ayrıca şunları yazar:
- `EOIE` (dizin girdisinin sonu): girdilerin nerede bitip uzantıların nerede başladığını işaretler
- `IEOT` (dizin girdisi ofset tablosu): dizinin paralel yüklenmesini sağlar
- `link` (bölünmüş dizin): bölünmüş dizin kullanan çok büyük depolar için

git biçiminde, imzası büyük harfle başlayan uzantılar isteğe bağlı, küçük harfle başlayanlar ise zorunludur. Pitmaster her iki türü de denetlemeden kabul eder. Bölünmüş dizin (`link`) yüklenmez; bu nedenle bunu kullanan depolar desteklenmez.

## Sağlama toplamı

Dizin dosyası, depoda kullanılan karma algoritmasıyla hesaplanmış ve önceki tüm baytları kapsayan bir sağlama toplamıyla biter (SHA-1 için 20 bayt, SHA-256 için 32 bayt). Pitmaster, kaydederken bunu yazar ancak okurken doğrulamaz.

`Index::open()` ve `Index::parse()`, `DIRC` imzası eksikse veya sürüm desteklenmiyorsa `IndexParseException` hatası verir.

## Dizin ve durum

Dizin, durum hesaplamasının merkezindedir. `WorkingTreeStatus` şunları karşılaştırır:
1. HEAD ağacı ile dizin: hazırlanmış değişiklikleri algılar
2. Dizin ile çalışma ağacı: hazırlanmamış değişiklikleri algılar

stat alanları (ctime, mtime, dev, ino, size, mode, uid, gid), dosya içeriğini okumadan "bu dosya değişti mi?" denetimlerinin hızlı yapılmasını sağlar. stat alanları eşleşiyorsa ve dosya durum taraması başlamadan önce en son değiştirilmişse, dosyanın değişmediği varsayılır. Farklı bir boyut dosyayı hemen değiştirilmiş olarak işaretler. Aksi takdirde Pitmaster dosyayı okur ve gerçek içerik değişikliklerini denetlemek için karmasını hesaplar.

## Geçerli kabul et bayrağı

```php
if ($entry->assumeValid()) {
    // Entry has assume-valid set (flags & 0x8000)
}
```

Bu bayrak, `git update-index --assume-unchanged` durumunda bile git öğesine durum denetimi sırasında dosyayı atlamasını söyler. Pitmaster, girdileri yeniden yazarken bu biti korur; ancak durum denetimi bunu dikkate almaz ve dosyayı karşılaştırmaya devam eder.
