
# Diff

Pitmaster, git'in birleşik biçiminde farkları hesaplar. Fark motoru birden fazla algoritmayı, birleşik diff biçimlendirmesini, ikili dosya algılamayı ve ağaç düzeyinde özyinelemeli karşılaştırmayı destekler.

`100644` kipine sahip değiştirilmiş bir metin dosyası için `format()`, `git diff` ile aynı baytları üretir. Diğer durumlar şu anda farklı biçimlendirilir ([#3](https://github.com/inline0/pitmaster/issues/3)):

- Yeni ve silinmiş dosyalarda `new file mode` / `deleted file mode` satırı, `index` satırı ve `/dev/null` bulunmaz: her iki taraf da `a/<path>` ve `b/<path>` olarak etiketlenir; boş tarafın hunk aralığı, git'in `-0,0` veya `+0,0` yazdığı yerde `-1,0` ya da `+1,0` olarak yazılır.
- Dosya kipi ne olursa olsun `index` satırı daima `100644` ile biter.
- Yalnızca kip değişiklikleri (örneğin `chmod +x`) sonuç üretmez.
- İkili dosyalar, git'in `Binary files a/<path> and b/<path> differ` yazdığı yerde `Binary files differ` bilgisini `index` satırı olmadan yazdırır.
- Yeniden adlandırmalar, içerik farkıyla birlikte tek bir `diff --git a/<old> b/<new>` girdisi olarak gösterilir; `similarity index`, `rename from` veya `rename to` satırları bulunmaz.

## Diff işlemleri

### Hazırlanmamış değişiklikler (çalışma ağacı ile dizin karşılaştırması)

```php
$diffs = $repo->diff();

foreach ($diffs as $diff) {
    echo $diff->format();
}
```

Dizindeki her dosyayı çalışma ağacındaki mevcut durumuyla karşılaştırır. Değişiklikleri, silmeleri ve ikili dosyaları algılar.

### Hazırlanmış değişiklikler (dizin ile HEAD karşılaştırması)

```php
$diffs = $repo->diffStaged();

foreach ($diffs as $diff) {
    echo $diff->format();
}
```

Geçerli dizini HEAD kaydının ağacıyla karşılaştırır. Bir sonraki kayda nelerin ekleneceğini gösterir. İçerikleri benzer olan silinmiş ve eklenmiş dosyalar, yeniden adlandırılmış tek bir girdi olarak bildirilir. İlk kayıttan önce HEAD yoktur ve sonuç boştur ([#5](https://github.com/inline0/pitmaster/issues/5)).

Yeniden adlandırma eşleştirme işlemi şu anda ilgisiz tek satırlık dosyaları da eşleştiriyor; çünkü sondaki boş satır ortak içerik olarak sayılıyor ([#4](https://github.com/inline0/pitmaster/issues/4)).

### Ağaçtan ağaca diff

```php
$a = $repo->readObject($repo->resolve('HEAD~1')->hex)->tree;
$b = $repo->head()->tree;
$diffs = $repo->diffTree($a, $b);
```

İki ağacı özyinelemeli olarak karşılaştırır. Ağaç kimlikleri verin: kayıt kimlikleri ağaçlarına dönüştürülmez ve boş sonuç verir. Aynı `TreeDiff` motoru `diffStaged()`, `show()` ve `logPath()` işlemlerini destekler.

### Yola göre filtreleme

```php
$diffs = $repo->diff('src/specific-file.php');
```

Yol belirtimi, tek bir tam dosya yoludur. `diffStaged()` aynı bağımsız değişkeni kabul eder ancak şimdilik yok sayar; bu nedenle hazırlanmış tüm dosyaları döndürür ([#5](https://github.com/inline0/pitmaster/issues/5)).

### Algoritma seçme

```php
$diffs = $repo->diff(null, 'patience');
$diffs = $repo->diffStaged(null, 'histogram');
$diffs = $repo->diffTree($a, $b, 'minimal');
```

Geçerli adlar `myers` (varsayılan), `patience`, `histogram` ve `minimal` şeklindedir. Diğer adlar `InvalidArgumentException` fırlatır.

## DiffResult yapısı

Her `DiffResult`, tek bir dosyanın diff'ini temsil eder.

```php
use Pitmaster\Diff\DiffResult;

foreach ($diffs as $diff) {
    echo $diff->oldPath;    // Path in the old tree
    echo $diff->newPath;    // Path in the new tree
    echo $diff->binary;     // true for binary files
    echo $diff->oldHash;    // Hex hash of the old blob (null for added files)
    echo $diff->newHash;    // Hex hash of the new blob (null for deleted files)

    foreach ($diff->hunks as $hunk) {
        echo $hunk->header();  // @@ -1,5 +1,7 @@
        foreach ($hunk->lines as $line) {
            echo $line . "\n"; // ' context', '+added', '-removed'
        }
    }
}
```

### Biçimlendirilmiş çıktı

```php
echo $diff->format();
```

Birleşik diff çıktısı üretir. Değiştirilmiş bir metin dosyasında `git diff` ile eşleşir:

```
diff --git a/src/File.php b/src/File.php
index abc1234..def5678 100644
--- a/src/File.php
+++ b/src/File.php
@@ -10,6 +10,8 @@ class File
     private string $name;

+    private int $count;
+
     public function __construct()
     {
```

### Değişiklikleri denetleme

```php
if ($diff->hasChanges()) {
    // File was modified (or is binary with changes)
}
```

## Hunk yapısı

Her `Hunk`, bağlam satırlarıyla birlikte bitişik bir değişiklik bölgesini temsil eder.

```php
use Pitmaster\Diff\Hunk;

$hunk->oldStart;   // Starting line in old file
$hunk->oldCount;   // Number of lines from old file
$hunk->newStart;   // Starting line in new file
$hunk->newCount;   // Number of lines in new file
$hunk->lines;      // Array of diff lines (prefixed with ' ', '+', or '-')
$hunk->header();   // "@@ -10,6 +10,8 @@"
```

## Diff algoritmaları

Pitmaster dört diff algoritması uygular. Varsayılan algoritma Myers'tır.

### Myers diff

Standart O(ND) algoritmasıdır ve git'in varsayılanıyla aynıdır. En küçük düzenleme betiklerini üretir.

```php
use Pitmaster\Diff\MyersDiff;

$hunks = MyersDiff::diff($oldContent, $newContent);
```

`diff()` yöntemi iki dize alır ve bir `Hunk` nesne dizisi döndürür. Girdiyi yeni satırlara göre böler, en kısa düzenleme betiğini hesaplar ve değişiklikleri 3 bağlam satırlı hunk'lar halinde gruplandırır (git varsayılanıyla eşleşir).

### Patience diff

Kod için yapısal olarak daha iyi farklar sunar. Önce benzersiz satırları eşleştirir, ardından aradaki bölümleri doldurur.

```php
use Pitmaster\Diff\PatienceDiff;

$hunks = PatienceDiff::diff($oldContent, $newContent);
```

### Histogram diff

Tekrarlanan satırları daha iyi işleyen bir patience diff çeşididir. JGit ve Eclipse tarafından kullanılır.

```php
use Pitmaster\Diff\HistogramDiff;

$hunks = HistogramDiff::diff($oldContent, $newContent);
```

### Minimal diff

Daha fazla hesaplama gerektirmesi karşılığında mümkün olan en küçük diff'i (en az değişen satırı) üretir.

```php
use Pitmaster\Diff\MinimalDiff;

$hunks = MinimalDiff::diff($oldContent, $newContent);
```

## İkili dosya algılama

Pitmaster, ilk 8192 bayt içinde NUL baytı varsa içeriği ikili veri olarak değerlendirir (git ilk 8000 baytı denetler).

```php
if (MyersDiff::isBinary($content)) {
    // Binary file, skip line-level diff
}
```

İkili dosyalar, `$binary = true` ve boş bir `$hunks` dizisi içeren bir `DiffResult` üretir. Biçimlendirilmiş çıktı şöyledir:

```
diff --git a/image.png b/image.png
Binary files differ
```

## Renkli çıktı

CLI, ANSI renkleriyle terminal çıktısı için `ColorDiff` kullanır.

```php
use Pitmaster\Diff\ColorDiff;

$colorized = ColorDiff::colorize($diff->format());
echo $colorized;
```

- Eklenen satırlar (`+`) yeşil gösterilir
- Kaldırılan satırlar (`-`) kırmızı gösterilir
- Hunk başlıkları (`@@`) camgöbeği gösterilir
- Dosya başlıkları (`diff --git`, `index`, `---`, `+++`) kalın gösterilir

`pitmaster diff`, çıktısı bir kanala yönlendirildiğinde bile her zaman renklendirir. `pitmaster show` yalnızca standart çıktı bir terminal olduğunda renklendirir.

## Ağaç diff'i (dahili)

`TreeDiff` sınıfı iki ağaç nesnesini özyinelemeli olarak karşılaştırır ve değiştirilen her dosya için bir `DiffResult` üretir.

```php
use Pitmaster\Diff\TreeDiff;

$treeDiff = new TreeDiff($repo->objectDatabase());
$diffs = $treeDiff->diff($oldTreeId, $newTreeId);
```

Ağaç diff'i şunları işler:
- Eklenen dosyalar (yalnızca yeni ağaçta bulunur)
- Silinen dosyalar (yalnızca eski ağaçta bulunur)
- Değiştirilen dosyalar (aynı yol, farklı blob özeti)
- Alt dizinlerin özyinelemeli karşılaştırması
- Silinen ve eklenen dosyalar arasında yeniden adlandırma eşleştirmesi (tam özet eşleşmesi veya en az %50 ortak satır)

Özeti değişmeyen girdiler atlanır; bu nedenle yalnızca kip değişikliği sonuç üretmez.

## Sözcük diff'i

Satır içindeki sözcük düzeyindeki değişiklikler için.

```php
use Pitmaster\Diff\WordDiff;

$result = WordDiff::diff('the quick fox', 'the slow fox');
// 'the [-quick-]{+slow+} fox'
```
