الفروق
تحسب Pitmaster الفروق بتنسيق git الموحد. يدعم محرك الفروق خوارزميات متعددة، وتنسيق الفروق الموحد، واكتشاف الملفات الثنائية، والمقارنة التكرارية على مستوى الشجرة.
بالنسبة إلى ملف نصي معدّل بنمط 100644، تنتج format() البايتات نفسها التي تنتجها git diff. تُنسّق الحالات الأخرى بطريقة مختلفة حاليًا (#3):
- لا تحتوي الملفات الجديدة والمحذوفة على سطر
new file mode/deleted file modeأو سطرindexأو/dev/null: يُشار إلى كلا الجانبين باسمa/<path>وb/<path>، ويُكتب نطاق مقطع التغيير للجانب الفارغ على هيئة-1,0أو+1,0حيث يكتب git-0,0أو+0,0. - ينتهي سطر
indexدائمًا بـ100644، مهما كان نمط الملف. - لا تنتج تغييرات النمط وحدها (مثل
chmod +x) أي نتيجة. - تطبع الملفات الثنائية
Binary files differدون سطرindex، بينما يطبع gitBinary 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);
تقارن شجرتين بشكل تكراري. مرّر معرّفات الأشجار: لا تُحوّل معرّفات الالتزام إلى أشجارها، وتنتج نتيجة فارغة. يستخدم المحرك نفسه TreeDiff كل من diffStaged() وshow() وlogPath().
التصفية حسب المسار
$diffs = $repo->diff('src/specific-file.php');
مواصفة المسار هي مسار ملف محدد. تقبل 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 منطقة متصلة من التغييرات مع أسطر السياق.
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. تقسم المدخلات عند الأسطر الجديدة، وتحسب أقصر تسلسل للتعديلات، ثم تجمع التغييرات في مقاطع مع 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 مع المحتوى باعتباره ثنائيًا إذا احتوى على بايت NUL ضمن أول 8192 بايتًا (يفحص 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;
- تظهر الأسطر المضافة (
+) باللون الأخضر - تظهر الأسطر المحذوفة (
-) باللون الأحمر - تظهر عناوين مقاطع التغيير (
@@) باللون السماوي - تظهر عناوين الملفات (
diff --gitوindexو---و+++) بخط عريض
تضيف pitmaster diff الألوان دائمًا، حتى عند توجيه مخرجاتها إلى مسار آخر. ولا تضيف pitmaster show الألوان إلا عندما يكون stdout طرفية.
فروق الأشجار (داخلي)
تقارن الفئة TreeDiff كائني شجرة بشكل تكراري، وتنتج DiffResult لكل ملف تغيّر.
use Pitmaster\Diff\TreeDiff;
$treeDiff = new TreeDiff($repo->objectDatabase());
$diffs = $treeDiff->diff($oldTreeId, $newTreeId);
تتعامل فروق الأشجار مع:
- الملفات المضافة (موجودة في الشجرة الجديدة فقط)
- الملفات المحذوفة (موجودة في الشجرة القديمة فقط)
- الملفات المعدّلة (المسار نفسه مع تجزئة blob مختلفة)
- المقارنة التكرارية للأدلة الفرعية
- إقران الملفات المحذوفة والمضافة عند إعادة التسمية (تطابق التجزئة تمامًا أو اشتراك في 50% على الأقل من الأسطر)
يتم تخطي المدخلات التي لم تتغير تجزئتها، لذا لا ينتج عن تغيير النمط وحده أي نتيجة.
فروق الكلمات
للتغييرات المضمنة على مستوى الكلمات داخل الأسطر.
use Pitmaster\Diff\WordDiff;
$result = WordDiff::diff('the quick fox', 'the slow fox');
// 'the [-quick-]{+slow+} fox'