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örindexoch/dev/null: båda sidorna etiketterasa/<path>ochb/<path>, och den tomma sidans hunk-intervall skrivs som-1,0eller+1,0där git skriver-0,0eller+0,0. - Raden
indexslutar alltid med100644, oavsett filläge. - Ändringar av enbart läge (till exempel
chmod +x) ger inget resultat. - Binärfiler skriver ut
Binary files differutan en rad förindex, medan git skriver utBinary 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örsimilarity index,rename fromellerrename to.
Diffåtgärder
Ej mellanlagrade ändringar (arbetsträd jämfört med index)
$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)
$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
$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
$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
$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.
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
echo $diff->format();
Producerar utdata med enhetlig diff. För en ändrad textfil matchar den git diff:
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
if ($diff->hasChanges()) {
// File was modified (or is binary with changes)
}
Hunk-struktur
Varje Hunk representerar ett sammanhängande ändringsområde med kontextrader.
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.
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.
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.
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.
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).
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:
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.
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.
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.
use Pitmaster\Diff\WordDiff;
$result = WordDiff::diff('the quick fox', 'the slow fox');
// 'the [-quick-]{+slow+} fox'