Hoppa till innehåll

Diff

Pitmaster beräknar diffar i gits enhetliga format. Diffmotorn stöder flera algoritmer, formatering av enhetliga diffar, identifiering av binärfiler och rekursiv jämförelse på trädnivå.

För en ändrad textfil med läget 100644 producerar format() samma byte som git diff. Andra fall formateras annorlunda i dag (#3):

  • Nya och borttagna filer saknar rad för new file mode / deleted file mode, rad för index och /dev/null: båda sidorna etiketteras a/<path> och b/<path>, och den tomma sidans hunk-intervall skrivs som -1,0 eller +1,0 där git skriver -0,0 eller +0,0.
  • Raden index slutar alltid med 100644, oavsett filläge.
  • Ändringar av enbart läge (till exempel chmod +x) ger inget resultat.
  • Binärfiler skriver ut Binary files differ utan en rad för index, medan git skriver ut Binary files a/<path> and b/<path> differ.
  • Namnbyten visas som en enda diff --git a/<old> b/<new>-post med en innehållsdiff, utan rader för similarity index, rename from eller rename to.

Diffåtgärder

Ej mellanlagrade ändringar (arbetsträd jämfört med index)

PHP
$diffs = $repo->diff();

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

Jämför varje fil i indexet med dess aktuella tillstånd i arbetsträdet. Upptäcker ändringar, borttagningar och binärfiler.

Mellanlagrade ändringar (index jämfört med HEAD)

PHP
$diffs = $repo->diffStaged();

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

Jämför det aktuella indexet med HEAD-incheckningens träd. Visar vad som kommer att ingå i nästa incheckning. Borttagna och tillagda filer med liknande innehåll rapporteras som en post med nytt namn. Före den första incheckningen finns inget HEAD och resultatet är tomt (#5).

Parning av namnbyten matchar för närvarande även orelaterade filer med en enda rad, eftersom den avslutande tomma raden räknas som delat innehåll (#4).

Träd-till-träd-diff

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

Jämför två träd rekursivt. Skicka med träd-ID:n: inchecknings-ID:n omvandlas inte till sina träd och ger ett tomt resultat. Samma TreeDiff-motor används av diffStaged(), show() och logPath().

Filtrera efter sökväg

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

Sökvägsspecifikationen är en exakt filsökväg. diffStaged() accepterar samma argument men ignorerar det för tillfället, så den returnerar alltid alla mellanlagrade filer (#5).

Välj en algoritm

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

Giltiga namn är myers (standard), patience, histogram och minimal. Alla andra namn orsakar InvalidArgumentException.

DiffResult-struktur

Varje DiffResult representerar diffen för en enskild fil.

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

Formaterad utdata

PHP
echo $diff->format();

Producerar utdata med enhetlig diff. För en ändrad textfil matchar den git diff:

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()
     {

Kontrollera om det finns ändringar

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

Hunk-struktur

Varje Hunk representerar ett sammanhängande ändringsområde med kontextrader.

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

Pitmaster implementerar fyra diff-algoritmer. Standardalgoritmen är Myers.

Myers-diff

Standardalgoritmen O(ND), samma som standardalgoritmen i git. Producerar minimala redigeringsskript.

PHP
use Pitmaster\Diff\MyersDiff;

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

Metoden diff() tar två strängar och returnerar en array med Hunk-objekt. Den delar upp indata vid radbrytningar, beräknar det kortaste redigeringsskriptet och grupperar ändringarna i hunkar med 3 kontextrader (i enlighet med standardvärdet i git).

Patience-diff

Bättre strukturella diffar för kod. Matchar först unika rader och fyller sedan i mellanrummen.

PHP
use Pitmaster\Diff\PatienceDiff;

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

Histogram-diff

En variant av patience-diff som hanterar upprepade rader bättre. Används av JGit och Eclipse.

PHP
use Pitmaster\Diff\HistogramDiff;

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

Minimal diff

Producerar minsta möjliga diff (minst antal ändrade rader), till priset av mer beräkning.

PHP
use Pitmaster\Diff\MinimalDiff;

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

Binärdetektering

Pitmaster behandlar innehåll som binärt om det innehåller en NUL-byte bland de första 8192 byten (git kontrollerar de första 8000).

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

Binärfiler ger en DiffResult med $binary = true och en tom $hunks-array. Den formaterade utdata är:

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

Färgmarkerad utdata

CLI använder ColorDiff för terminalutdata med ANSI-färger.

PHP
use Pitmaster\Diff\ColorDiff;

$colorized = ColorDiff::colorize($diff->format());
echo $colorized;
  • Tillagda rader (+) visas i grönt
  • Borttagna rader (-) visas i rött
  • Hunk-rubriker (@@) visas i cyan
  • Filrubriker (diff --git, index, ---, +++) visas i fetstil

pitmaster diff färglägger alltid utdata, även när den skickas vidare. pitmaster show färglägger bara när stdout är en terminal.

Träddiff (internt)

Klassen TreeDiff jämför två trädobjekt rekursivt och skapar en DiffResult för varje ändrad fil.

PHP
use Pitmaster\Diff\TreeDiff;

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

Träddiff hanterar:

  • Tillagda filer (finns bara i det nya trädet)
  • Borttagna filer (finns bara i det gamla trädet)
  • Ändrade filer (samma sökväg, annan blob-hash)
  • Rekursiv jämförelse av underkataloger
  • Parning av namnbyten mellan borttagna och tillagda filer (exakt hashmatchning eller minst 50 % gemensamma rader)

Poster med oförändrad hash hoppas över, så en ändring av enbart läge ger inget resultat.

Orddiff

För ändringar på ordnivå inom rader.

PHP
use Pitmaster\Diff\WordDiff;

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