İçeriğe geç

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):

  • 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).

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).

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).

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:

Kod
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:

Kod
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'