Διαφορές
Το Pitmaster υπολογίζει διαφορές στη συνενωμένη μορφή του git. Η μηχανή διαφορών υποστηρίζει πολλούς αλγορίθμους, μορφοποίηση συνενωμένων διαφορών, εντοπισμό δυαδικών αρχείων και αναδρομική σύγκριση σε επίπεδο δέντρου.
Για τροποποιημένο αρχείο κειμένου με λειτουργία 100644, το format() παράγει τα ίδια byte με το git diff. Άλλες περιπτώσεις μορφοποιούνται διαφορετικά προς το παρόν (#3):
- Τα νέα και τα διαγραμμένα αρχεία δεν έχουν γραμμή
new file mode/deleted file mode, γραμμήindexή/dev/null: και οι δύο πλευρές επισημαίνονται ωςa/<path>καιb/<path>, ενώ το εύρος hunk της κενής πλευράς γράφεται ως-1,0ή+1,0εκεί όπου το git γράφει-0,0ή+0,0. - Η γραμμή
indexτελειώνει πάντα σε100644, ανεξάρτητα από τη λειτουργία του αρχείου. - Οι αλλαγές μόνο στη λειτουργία (για παράδειγμα
chmod +x) δεν παράγουν αποτέλεσμα. - Τα δυαδικά αρχεία εμφανίζουν
Binary files differχωρίς γραμμήindex, ενώ το git εμφανίζειBinary files a/<path> and b/<path> differ. - Οι μετονομασίες εμφανίζονται ως μία καταχώριση
diff --git a/<old> b/<new>με διαφορά περιεχομένου, χωρίς γραμμέςsimilarity index,rename fromήrename to.
Λειτουργίες διαφορών
Μη καταχωρισμένες αλλαγές (δέντρο εργασίας έναντι ευρετηρίου)
$diffs = $repo->diff();
foreach ($diffs as $diff) {
echo $diff->format();
}
Συγκρίνει κάθε αρχείο στο ευρετήριο με την τρέχουσα κατάστασή του στο δέντρο εργασίας. Εντοπίζει τροποποιήσεις, διαγραφές και δυαδικά αρχεία.
Καταχωρισμένες αλλαγές (ευρετήριο έναντι HEAD)
$diffs = $repo->diffStaged();
foreach ($diffs as $diff) {
echo $diff->format();
}
Συγκρίνει το τρέχον ευρετήριο με το δέντρο της καταχώρισης HEAD. Εμφανίζει όσα θα συμπεριληφθούν στην επόμενη καταχώριση. Τα διαγραμμένα και τα προστιθέμενα αρχεία με παρόμοιο περιεχόμενο αναφέρονται ως μία καταχώριση μετονομασίας. Πριν από την πρώτη καταχώριση δεν υπάρχει HEAD και το αποτέλεσμα είναι κενό (#5).
Η αντιστοίχιση μετονομασιών ταιριάζει προς το παρόν και άσχετα αρχεία μίας γραμμής, επειδή η κενή γραμμή στο τέλος μετρά ως κοινό περιεχόμενο (#4).
Διαφορά μεταξύ δέντρων
$a = $repo->readObject($repo->resolve('HEAD~1')->hex)->tree;
$b = $repo->head()->tree;
$diffs = $repo->diffTree($a, $b);
Συγκρίνει αναδρομικά δύο δέντρα. Δώστε ID δέντρων: τα ID καταχωρίσεων δεν αναλύονται στα αντίστοιχα δέντρα τους και επιστρέφουν κενό αποτέλεσμα. Η ίδια μηχανή TreeDiff υποστηρίζει τα diffStaged(), show() και logPath().
Φιλτράρισμα κατά διαδρομή
$diffs = $repo->diff('src/specific-file.php');
Το pathspec είναι μία ακριβής διαδρομή αρχείου. Το diffStaged() δέχεται το ίδιο όρισμα, αλλά προς το παρόν το αγνοεί και έτσι επιστρέφει πάντα κάθε καταχωρισμένο αρχείο (#5).
Επιλογή αλγορίθμου
$diffs = $repo->diff(null, 'patience');
$diffs = $repo->diffStaged(null, 'histogram');
$diffs = $repo->diffTree($a, $b, 'minimal');
Έγκυρα ονόματα είναι τα myers (προεπιλογή), patience, histogram και minimal. Οποιοδήποτε άλλο όνομα προκαλεί InvalidArgumentException.
Δομή DiffResult
Κάθε DiffResult αναπαριστά τη διαφορά ενός αρχείου.
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'
}
}
}
Μορφοποιημένη έξοδος
echo $diff->format();
Παράγει έξοδο συνενωμένης διαφοράς. Για τροποποιημένο αρχείο κειμένου αντιστοιχεί στο 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()
{
Έλεγχος για αλλαγές
if ($diff->hasChanges()) {
// File was modified (or is binary with changes)
}
Δομή Hunk
Κάθε Hunk αναπαριστά μια συνεχόμενη περιοχή αλλαγών με γραμμές περιβάλλοντος.
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 @@"
Αλγόριθμοι διαφορών
Το Pitmaster υλοποιεί τέσσερις αλγορίθμους διαφορών. Προεπιλογή είναι ο Myers.
Διαφορά Myers
Ο τυπικός αλγόριθμος O(ND), ίδιος με την προεπιλογή του git. Παράγει ελάχιστα σενάρια επεξεργασίας.
use Pitmaster\Diff\MyersDiff;
$hunks = MyersDiff::diff($oldContent, $newContent);
Η μέθοδος diff() δέχεται δύο συμβολοσειρές και επιστρέφει έναν πίνακα αντικειμένων Hunk. Χωρίζει την είσοδο στις αλλαγές γραμμής, υπολογίζει το συντομότερο σενάριο επεξεργασίας και ομαδοποιεί τις αλλαγές σε hunks με 3 γραμμές περιβάλλοντος (σύμφωνα με την προεπιλογή του git).
Διαφορά Patience
Παράγει καλύτερες δομικές διαφορές για κώδικα. Αντιστοιχίζει πρώτα τις μοναδικές γραμμές και στη συνέχεια συμπληρώνει τα κενά ανάμεσά τους.
use Pitmaster\Diff\PatienceDiff;
$hunks = PatienceDiff::diff($oldContent, $newContent);
Διαφορά Histogram
Παραλλαγή της διαφοράς Patience που χειρίζεται καλύτερα τις επαναλαμβανόμενες γραμμές. Χρησιμοποιείται από τα JGit και Eclipse.
use Pitmaster\Diff\HistogramDiff;
$hunks = HistogramDiff::diff($oldContent, $newContent);
Ελάχιστη διαφορά
Παράγει τη μικρότερη δυνατή διαφορά (με τις λιγότερες αλλαγμένες γραμμές), με αντάλλαγμα περισσότερους υπολογισμούς.
use Pitmaster\Diff\MinimalDiff;
$hunks = MinimalDiff::diff($oldContent, $newContent);
Εντοπισμός δυαδικών αρχείων
Το Pitmaster αντιμετωπίζει το περιεχόμενο ως δυαδικό αν περιέχει byte NUL στα πρώτα 8192 byte του (το git ελέγχει τα πρώτα 8000).
if (MyersDiff::isBinary($content)) {
// Binary file, skip line-level diff
}
Τα δυαδικά αρχεία παράγουν ένα DiffResult με $binary = true και κενό πίνακα $hunks. Η μορφοποιημένη έξοδος είναι:
diff --git a/image.png b/image.png
Binary files differ
Έξοδος με χρώματα
Το CLI χρησιμοποιεί το ColorDiff για έξοδο τερματικού με χρώματα ANSI.
use Pitmaster\Diff\ColorDiff;
$colorized = ColorDiff::colorize($diff->format());
echo $colorized;
- Οι γραμμές που προστέθηκαν (
+) εμφανίζονται με πράσινο - Οι γραμμές που αφαιρέθηκαν (
-) εμφανίζονται με κόκκινο - Οι κεφαλίδες hunk (
@@) εμφανίζονται με κυανό - Οι κεφαλίδες αρχείων (
diff --git,index,---,+++) εμφανίζονται με έντονη γραφή
Το pitmaster diff εφαρμόζει πάντα χρωματισμό, ακόμη κι όταν η έξοδός του διοχετεύεται. Το pitmaster show εφαρμόζει χρωματισμό μόνο όταν το stdout είναι τερματικό.
Διαφορά δέντρων (εσωτερική)
Η κλάση TreeDiff συγκρίνει αναδρομικά δύο αντικείμενα δέντρου και παράγει ένα DiffResult για κάθε αρχείο που έχει αλλάξει.
use Pitmaster\Diff\TreeDiff;
$treeDiff = new TreeDiff($repo->objectDatabase());
$diffs = $treeDiff->diff($oldTreeId, $newTreeId);
Η διαφορά δέντρων χειρίζεται:
- Προστιθέμενα αρχεία (υπάρχουν μόνο στο νέο δέντρο)
- Διαγραμμένα αρχεία (υπάρχουν μόνο στο παλιό δέντρο)
- Τροποποιημένα αρχεία (ίδια διαδρομή, διαφορετικό hash blob)
- Αναδρομική σύγκριση υποκαταλόγων
- Αντιστοίχιση μετονομασιών μεταξύ διαγραμμένων και προστιθέμενων αρχείων (ακριβής αντιστοιχία hash ή τουλάχιστον 50% κοινών γραμμών)
Οι καταχωρίσεις με αμετάβλητο hash παραλείπονται, επομένως μια αλλαγή λειτουργίας από μόνη της δεν παράγει αποτέλεσμα.
Διαφορά λέξεων
Για ενσωματωμένες αλλαγές σε επίπεδο λέξης μέσα στις γραμμές.
use Pitmaster\Diff\WordDiff;
$result = WordDiff::diff('the quick fox', 'the slow fox');
// 'the [-quick-]{+slow+} fox'