Μετάβαση στο περιεχόμενο

Διαφορές

Το 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.

Λειτουργίες διαφορών

Μη καταχωρισμένες αλλαγές (δέντρο εργασίας έναντι ευρετηρίου)

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

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

Συγκρίνει κάθε αρχείο στο ευρετήριο με την τρέχουσα κατάστασή του στο δέντρο εργασίας. Εντοπίζει τροποποιήσεις, διαγραφές και δυαδικά αρχεία.

Καταχωρισμένες αλλαγές (ευρετήριο έναντι HEAD)

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

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

Συγκρίνει το τρέχον ευρετήριο με το δέντρο της καταχώρισης HEAD. Εμφανίζει όσα θα συμπεριληφθούν στην επόμενη καταχώριση. Τα διαγραμμένα και τα προστιθέμενα αρχεία με παρόμοιο περιεχόμενο αναφέρονται ως μία καταχώριση μετονομασίας. Πριν από την πρώτη καταχώριση δεν υπάρχει HEAD και το αποτέλεσμα είναι κενό (#5).

Η αντιστοίχιση μετονομασιών ταιριάζει προς το παρόν και άσχετα αρχεία μίας γραμμής, επειδή η κενή γραμμή στο τέλος μετρά ως κοινό περιεχόμενο (#4).

Διαφορά μεταξύ δέντρων

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

Συγκρίνει αναδρομικά δύο δέντρα. Δώστε ID δέντρων: τα ID καταχωρίσεων δεν αναλύονται στα αντίστοιχα δέντρα τους και επιστρέφουν κενό αποτέλεσμα. Η ίδια μηχανή TreeDiff υποστηρίζει τα diffStaged(), show() και logPath().

Φιλτράρισμα κατά διαδρομή

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

Το pathspec είναι μία ακριβής διαδρομή αρχείου. Το diffStaged() δέχεται το ίδιο όρισμα, αλλά προς το παρόν το αγνοεί και έτσι επιστρέφει πάντα κάθε καταχωρισμένο αρχείο (#5).

Επιλογή αλγορίθμου

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

Έγκυρα ονόματα είναι τα myers (προεπιλογή), patience, histogram και minimal. Οποιοδήποτε άλλο όνομα προκαλεί InvalidArgumentException.

Δομή DiffResult

Κάθε DiffResult αναπαριστά τη διαφορά ενός αρχείου.

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

Μορφοποιημένη έξοδος

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

Έλεγχος για αλλαγές

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

Δομή Hunk

Κάθε Hunk αναπαριστά μια συνεχόμενη περιοχή αλλαγών με γραμμές περιβάλλοντος.

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 @@"

Αλγόριθμοι διαφορών

Το Pitmaster υλοποιεί τέσσερις αλγορίθμους διαφορών. Προεπιλογή είναι ο Myers.

Διαφορά Myers

Ο τυπικός αλγόριθμος O(ND), ίδιος με την προεπιλογή του git. Παράγει ελάχιστα σενάρια επεξεργασίας.

PHP
use Pitmaster\Diff\MyersDiff;

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

Η μέθοδος diff() δέχεται δύο συμβολοσειρές και επιστρέφει έναν πίνακα αντικειμένων Hunk. Χωρίζει την είσοδο στις αλλαγές γραμμής, υπολογίζει το συντομότερο σενάριο επεξεργασίας και ομαδοποιεί τις αλλαγές σε hunks με 3 γραμμές περιβάλλοντος (σύμφωνα με την προεπιλογή του git).

Διαφορά Patience

Παράγει καλύτερες δομικές διαφορές για κώδικα. Αντιστοιχίζει πρώτα τις μοναδικές γραμμές και στη συνέχεια συμπληρώνει τα κενά ανάμεσά τους.

PHP
use Pitmaster\Diff\PatienceDiff;

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

Διαφορά Histogram

Παραλλαγή της διαφοράς Patience που χειρίζεται καλύτερα τις επαναλαμβανόμενες γραμμές. Χρησιμοποιείται από τα JGit και Eclipse.

PHP
use Pitmaster\Diff\HistogramDiff;

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

Ελάχιστη διαφορά

Παράγει τη μικρότερη δυνατή διαφορά (με τις λιγότερες αλλαγμένες γραμμές), με αντάλλαγμα περισσότερους υπολογισμούς.

PHP
use Pitmaster\Diff\MinimalDiff;

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

Εντοπισμός δυαδικών αρχείων

Το Pitmaster αντιμετωπίζει το περιεχόμενο ως δυαδικό αν περιέχει byte NUL στα πρώτα 8192 byte του (το git ελέγχει τα πρώτα 8000).

PHP
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.

PHP
use Pitmaster\Diff\ColorDiff;

$colorized = ColorDiff::colorize($diff->format());
echo $colorized;
  • Οι γραμμές που προστέθηκαν (+) εμφανίζονται με πράσινο
  • Οι γραμμές που αφαιρέθηκαν (-) εμφανίζονται με κόκκινο
  • Οι κεφαλίδες hunk (@@) εμφανίζονται με κυανό
  • Οι κεφαλίδες αρχείων (diff --git, index, ---, +++) εμφανίζονται με έντονη γραφή

Το pitmaster diff εφαρμόζει πάντα χρωματισμό, ακόμη κι όταν η έξοδός του διοχετεύεται. Το pitmaster show εφαρμόζει χρωματισμό μόνο όταν το stdout είναι τερματικό.

Διαφορά δέντρων (εσωτερική)

Η κλάση TreeDiff συγκρίνει αναδρομικά δύο αντικείμενα δέντρου και παράγει ένα DiffResult για κάθε αρχείο που έχει αλλάξει.

PHP
use Pitmaster\Diff\TreeDiff;

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

Η διαφορά δέντρων χειρίζεται:

  • Προστιθέμενα αρχεία (υπάρχουν μόνο στο νέο δέντρο)
  • Διαγραμμένα αρχεία (υπάρχουν μόνο στο παλιό δέντρο)
  • Τροποποιημένα αρχεία (ίδια διαδρομή, διαφορετικό hash blob)
  • Αναδρομική σύγκριση υποκαταλόγων
  • Αντιστοίχιση μετονομασιών μεταξύ διαγραμμένων και προστιθέμενων αρχείων (ακριβής αντιστοιχία hash ή τουλάχιστον 50% κοινών γραμμών)

Οι καταχωρίσεις με αμετάβλητο hash παραλείπονται, επομένως μια αλλαγή λειτουργίας από μόνη της δεν παράγει αποτέλεσμα.

Διαφορά λέξεων

Για ενσωματωμένες αλλαγές σε επίπεδο λέξης μέσα στις γραμμές.

PHP
use Pitmaster\Diff\WordDiff;

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