Diff
Pitmaster berekent verschillen in het uniforme formaat van git. De diff-engine ondersteunt meerdere algoritmen, uniforme diff-opmaak, detectie van binaire bestanden en recursieve vergelijking op boomniveau.
Voor een gewijzigd tekstbestand met modus 100644 produceert format() dezelfde bytes als git diff. Andere gevallen worden momenteel anders opgemaakt (#3):
- Nieuwe en verwijderde bestanden hebben geen regel
new file mode/deleted file mode, geen regelindexen geen/dev/null: beide zijden krijgen de aanduidinga/<path>enb/<path>, en het hunk-bereik van de lege zijde wordt geschreven als-1,0of+1,0, terwijl git-0,0of+0,0schrijft. - De regel
indexeindigt altijd op100644, ongeacht de bestandsmodus. - Wijzigingen in alleen de modus (bijvoorbeeld
chmod +x) leveren geen resultaat op. - Binaire bestanden tonen
Binary files differzonder een regelindex, terwijl gitBinary files a/<path> and b/<path> differtoont. - Hernoemingen worden weergegeven als één
diff --git a/<old> b/<new>-item met een inhoudsverschil, zonder regelssimilarity index,rename fromofrename to.
Diff-bewerkingen
Niet-gefaseerde wijzigingen (werkboom versus index)
$diffs = $repo->diff();
foreach ($diffs as $diff) {
echo $diff->format();
}
Vergelijkt elk bestand in de index met de huidige staat ervan in de werkboom. Detecteert wijzigingen, verwijderingen en binaire bestanden.
Gefaseerde wijzigingen (index versus HEAD)
$diffs = $repo->diffStaged();
foreach ($diffs as $diff) {
echo $diff->format();
}
Vergelijkt de huidige index met de tree van de HEAD-commit. Toont wat in de volgende commit wordt opgenomen. Verwijderde en toegevoegde bestanden met vergelijkbare inhoud worden als één hernoemd item gerapporteerd. Vóór de eerste commit bestaat er geen HEAD en is het resultaat leeg (#5).
Koppeling van hernoemde bestanden matcht momenteel ook niet-gerelateerde bestanden van één regel, omdat de afsluitende lege regel als gedeelde inhoud telt (#4).
Diff tussen trees
$a = $repo->readObject($repo->resolve('HEAD~1')->hex)->tree;
$b = $repo->head()->tree;
$diffs = $repo->diffTree($a, $b);
Vergelijkt twee trees recursief. Geef tree-ID's door: commit-ID's worden niet herleid tot hun trees en leveren een leeg resultaat op. Dezelfde engine TreeDiff ligt ten grondslag aan diffStaged(), show() en logPath().
Filteren op pad
$diffs = $repo->diff('src/specific-file.php');
De pathspec is één exact bestandspad. diffStaged() accepteert hetzelfde argument, maar negeert het momenteel en retourneert daarom altijd elk gefaseerd bestand (#5).
Een algoritme kiezen
$diffs = $repo->diff(null, 'patience');
$diffs = $repo->diffStaged(null, 'histogram');
$diffs = $repo->diffTree($a, $b, 'minimal');
Geldige namen zijn myers (standaard), patience, histogram en minimal. Elke andere naam gooit InvalidArgumentException.
Structuur van DiffResult
Elk DiffResult vertegenwoordigt de diff voor één bestand.
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'
}
}
}
Opgemaakte uitvoer
echo $diff->format();
Produceert unified diff-uitvoer. Voor een gewijzigd tekstbestand komt deze overeen met 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()
{
Controleren op wijzigingen
if ($diff->hasChanges()) {
// File was modified (or is binary with changes)
}
Hunk-structuur
Elk Hunk vertegenwoordigt een aaneengesloten gebied met wijzigingen en contextregels.
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-algoritmen
Pitmaster implementeert vier diff-algoritmen. Myers is de standaard.
Myers-diff
Het standaardalgoritme O(ND), hetzelfde als de standaardinstelling van git. Levert minimale bewerkingsscripts op.
use Pitmaster\Diff\MyersDiff;
$hunks = MyersDiff::diff($oldContent, $newContent);
De methode diff() neemt twee tekenreeksen en retourneert een array met Hunk-objecten. De invoer wordt opgesplitst bij regeleinden, het kortste bewerkingsscript wordt berekend en wijzigingen worden gegroepeerd in hunks met 3 contextregels (zoals de standaardinstelling van git).
Patience-diff
Zorgt voor betere structurele diffs van code. Matcht eerst unieke regels en vult daarna de tussenliggende stukken op.
use Pitmaster\Diff\PatienceDiff;
$hunks = PatienceDiff::diff($oldContent, $newContent);
Histogram-diff
Een variant van de patience-diff die beter omgaat met herhaalde regels. Wordt gebruikt door JGit en Eclipse.
use Pitmaster\Diff\HistogramDiff;
$hunks = HistogramDiff::diff($oldContent, $newContent);
Minimale diff
Produceert de kleinst mogelijke diff (met zo min mogelijk gewijzigde regels), ten koste van meer rekenwerk.
use Pitmaster\Diff\MinimalDiff;
$hunks = MinimalDiff::diff($oldContent, $newContent);
Binaire detectie
Pitmaster behandelt inhoud als binair wanneer deze een NUL-byte bevat in de eerste 8192 bytes (git controleert de eerste 8000).
if (MyersDiff::isBinary($content)) {
// Binary file, skip line-level diff
}
Binaire bestanden produceren een DiffResult met $binary = true en een lege array $hunks. De opgemaakte uitvoer is:
diff --git a/image.png b/image.png
Binary files differ
Uitvoer met kleuren
De CLI gebruikt ColorDiff voor terminaluitvoer met ANSI-kleuren.
use Pitmaster\Diff\ColorDiff;
$colorized = ColorDiff::colorize($diff->format());
echo $colorized;
- Toegevoegde regels (
+) worden groen weergegeven - Verwijderde regels (
-) worden rood weergegeven - Hunk-headers (
@@) worden cyaan weergegeven - Bestandsheaders (
diff --git,index,---,+++) worden vet weergegeven
pitmaster diff kleurt altijd, ook wanneer de uitvoer wordt doorgevoerd. pitmaster show kleurt alleen wanneer stdout een terminal is.
Tree-diff (intern)
De klasse TreeDiff vergelijkt twee tree-objecten recursief en produceert een DiffResult voor elk gewijzigd bestand.
use Pitmaster\Diff\TreeDiff;
$treeDiff = new TreeDiff($repo->objectDatabase());
$diffs = $treeDiff->diff($oldTreeId, $newTreeId);
Tree-diff behandelt:
- Toegevoegde bestanden (alleen aanwezig in de nieuwe tree)
- Verwijderde bestanden (alleen aanwezig in de oude tree)
- Gewijzigde bestanden (zelfde pad, andere blob-hash)
- Recursieve vergelijking van submappen
- Koppeling van hernoemingen tussen verwijderde en toegevoegde bestanden (exacte hash-match of minstens 50% gedeelde regels)
Items met een ongewijzigde hash worden overgeslagen, dus een wijziging van alleen de modus levert geen resultaat op.
Word-diff
Voor wijzigingen op woordniveau binnen regels.
use Pitmaster\Diff\WordDiff;
$result = WordDiff::diff('the quick fox', 'the slow fox');
// 'the [-quick-]{+slow+} fox'