Gå til indhold

Diff

Pitmaster beregner forskelle i gits samlede format. Diff-motoren understøtter flere algoritmer, formatering af samlede forskelle, registrering af binære filer og rekursiv sammenligning på træniveau.

For en ændret tekstfil med tilstanden 100644 producerer format() de samme bytes som git diff. Andre tilfælde formateres i øjeblikket anderledes (#3):

  • Nye og slettede filer har ingen new file mode / deleted file mode-linje, ingen index-linje og intet /dev/null: begge sider mærkes a/<path> og b/<path>, og den tomme sides hunk-interval skrives som -1,0 eller +1,0, hvor git skriver -0,0 eller +0,0.
  • index-linjen slutter altid med 100644, uanset filtilstanden.
  • Ændringer kun af tilstanden (f.eks. chmod +x) giver intet resultat.
  • Binære filer viser Binary files differ uden en index-linje, hvor git viser Binary files a/<path> and b/<path> differ.
  • Omdøbninger vises som én diff --git a/<old> b/<new>-post med en indholdsdiff uden linjerne similarity index, rename from eller rename to.

Diff-handlinger

Ikke-indekserede ændringer (arbejdsmappe vs. indeks)

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

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

Sammenligner hver fil i indekset med dens aktuelle tilstand i arbejdsområdet. Registrerer ændringer, sletninger og binære filer.

Indekserede ændringer (indeks vs. HEAD)

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

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

Sammenligner det aktuelle indeks med træet i HEAD-committen. Viser, hvad der kommer med i den næste commit. Slettede og tilføjede filer med lignende indhold rapporteres som én post for en omdøbt fil. Før den første commit findes der ingen HEAD, og resultatet er tomt (#5).

Parringen af omdøbninger matcher i øjeblikket også ikke-relaterede filer på én linje, fordi den afsluttende tomme linje tæller som fælles indhold (#4).

Træ-til-træ-diff

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

Sammenligner to træer rekursivt. Angiv træ-id'er: commit-id'er foldes ikke ud til deres træer og giver et tomt resultat. Den samme TreeDiff-motor ligger til grund for diffStaged(), show() og logPath().

Filtrér efter sti

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

Stispecifikationen er én præcis filsti. diffStaged() accepterer det samme argument, men ignorerer det i øjeblikket, så den altid returnerer alle indekserede filer (#5).

Vælg en algoritme

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

Gyldige navne er myers (standard), patience, histogram og minimal. Ethvert andet navn kaster InvalidArgumentException.

DiffResult-struktur

Hver DiffResult repræsenterer forskellen for én enkelt 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'
        }
    }
}

Formateret output

PHP
echo $diff->format();

Producerer output med forenede forskelle. For en ændret tekstfil svarer det til git diff:

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

Kontrollér for ændringer

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

Hunk-struktur

Hver Hunk repræsenterer et sammenhængende ændringsområde med kontekstlinjer.

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 implementerer fire diff-algoritmer. Standardalgoritmen er Myers.

Myers-diff

Standardalgoritmen O(ND), den samme som gits standardalgoritme. Giver minimale redigeringsscripts.

PHP
use Pitmaster\Diff\MyersDiff;

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

Metoden diff() tager to strenge og returnerer et array af Hunk-objekter. Den opdeler inputtet ved linjeskift, beregner det korteste redigeringsscript og grupperer ændringer i hunks med 3 kontekstlinjer (som git gør som standard).

Tålmodig diff

Bedre strukturelle diff'er for kode. Matcher først unikke linjer og udfylder derefter mellemrummene.

PHP
use Pitmaster\Diff\PatienceDiff;

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

Histogram-diff

En variant af tålmodig diff, der håndterer gentagne linjer bedre. Bruges af JGit og Eclipse.

PHP
use Pitmaster\Diff\HistogramDiff;

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

Minimal diff

Producerer den mindst mulige diff (færrest ændrede linjer) på bekostning af mere beregning.

PHP
use Pitmaster\Diff\MinimalDiff;

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

Registrering af binærfiler

Pitmaster behandler indhold som binært, hvis det indeholder en NUL-byte blandt de første 8192 bytes (git kontrollerer de første 8000).

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

Binære filer giver en DiffResult med $binary = true og et tomt $hunks-array. Det formaterede output er:

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

Farvelagt output

CLI bruger ColorDiff til terminaloutput med ANSI-farver.

PHP
use Pitmaster\Diff\ColorDiff;

$colorized = ColorDiff::colorize($diff->format());
echo $colorized;
  • Tilføjede linjer (+) vises med grønt
  • Fjernede linjer (-) vises med rødt
  • Hunk-headere (@@) vises med cyan
  • Filheadere (diff --git, index, ---, +++) vises med fed skrift

pitmaster diff farvelægger altid output, også når det sendes gennem en pipe. pitmaster show farvelægger kun, når stdout er en terminal.

Tree-diff (intern)

Klassen TreeDiff sammenligner to tree-objekter rekursivt og producerer en DiffResult for hver ændret fil.

PHP
use Pitmaster\Diff\TreeDiff;

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

Tree-diff håndterer:

  • Tilføjede filer (findes kun i det nye tree)
  • Slettede filer (findes kun i det gamle tree)
  • Ændrede filer (samme sti, forskellig blob-hash)
  • Rekursiv sammenligning af undermapper
  • Parring af omdøbninger mellem slettede og tilføjede filer (præcist hash-match eller mindst 50 % fælles linjer)

Poster med uændret hash springes over, så en ændring af tilstanden alene ikke giver et resultat.

Orddiff

Til ændringer på ordniveau inde i linjer.

PHP
use Pitmaster\Diff\WordDiff;

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