
# البروتوكولات

يدعم Pitmaster بروتوكولات نقل متعددة للاتصال بخوادم git. يُعد HTTP الذكي وسيلة النقل الأساسية، وتتوفر بروتوكولات إضافية لضمان توافق أوسع.

## HTTP الذكي (أساسي)

وسيلة النقل الموصى بها. تعمل عبر HTTPS وهي البروتوكول الأكثر انتشارًا. لا يتوفر API للعناوين المخصصة أو بيانات الاعتماد؛ ولا يمكن تمرير بيانات الاعتماد إلا في URL (`https://user:token@host/repo.git`)، التي يرسلها PHP على هيئة مصادقة Basic. يخزّن `clone()` قيمة URL، بما فيها بيانات الاعتماد، بوصفها `remote.origin.url` في `.git/config`. تستخدم الطلبات أغلفة تدفق PHP، لذا يجب تفعيل `allow_url_fopen`.

```php
use Pitmaster\Protocol\SmartHttpClient;

$http = new SmartHttpClient(timeout: 30);
$discovery = $http->discoverRefs('https://github.com/user/repo.git');
```

راجع [HTTP الذكي](https://pitmaster.inline0.dev/ar/docs/network/smart-http) للاطلاع على التفاصيل كاملة.

### البروتوكول v1

بروتوكول HTTP الذكي التقليدي. تُرسل كل المراجع أثناء الاكتشاف، ويستخدم التفاوض أسطر المطلوب والمتاح والانتهاء.

```php
use Pitmaster\Protocol\ProtocolV1;
```

### البروتوكول v2

بروتوكول أحدث بأوامر منظمة (`ls-refs`، `fetch`). أكثر كفاءة للمستودعات التي تضم مراجع كثيرة، إذ يمكن للعميل تصفية قائمة المراجع.

يستخدم `clone()` و`fetch()` البروتوكول v1 دائمًا. يتوفر البروتوكول v2 صراحةً عبر HTTP الذكي من خلال `SmartHttpClient::discoverRefsV2()` و`UploadPackClient::fetchV2()`.

## HTTP غير الذكي

خيار احتياطي للخوادم التي لا تدعم بروتوكول HTTP الذكي. يجلب البروتوكول غير الذكي الكائنات والحزم كلًا على حدة عبر طلبات GET عادية باستخدام HTTP.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

قيود HTTP غير الذكي:
- لا يوجد تفاوض (على العميل تنزيل كل شيء)
- لا يوجد ضغط دلتا أثناء النقل
- أبطأ بكثير من HTTP الذكي
- بعض الخوادم (GitHub وGitLab) لا تدعمه

يجلب البروتوكول غير الذكي ما يلي:
1. `GET /info/refs` (نص عادي، بلا pkt-line)
2. `GET /HEAD` (الفرع الافتراضي)
3. `GET /objects/info/packs` (قائمة بالحزم المتاحة)
4. `GET /objects/pack/pack-<hash>.pack` و`.idx` (كل حزمة مدرجة وفهرسها)
5. `GET /objects/<xx>/<rest>` (الكائنات المنفردة غير المعبأة، بدءًا من رؤوس المراجع)

تُنفّذ الخطوة 5 فقط عندما لا يسرد الخادم أي حزم. وعند إدراج حزم، لا تُنزّل الكائنات الموجودة كملفات منفردة على الخادم ([#18](https://github.com/inline0/pitmaster/issues/18)). يقبل العميل غير الذكي معرّفات الكائنات ذات 40 محرفًا (SHA-1) فقط. يعود `clone()` و`fetch()` إلى HTTP غير الذكي إذا فشل التبادل عبر HTTP الذكي.

## SSH

يستخدم نقل SSH الامتداد `ssh2` PHP عند تحميله. وإلا فيبدأ عميل `ssh` النظام عبر `proc_open()`. وفي الحالتين يشغّل `git-upload-pack` أو `git-receive-pack` على المستودع البعيد.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

عناوين SSH:
```
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git
```

لا يلزم أي امتداد. يختلف سلوك المسارين:

**عميل `ssh` النظام** (يُستخدم عند عدم تحميل `ssh2`). يشغّل Pitmaster الأمر `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>`، لذا تتبع المصادقة والتحقق من مفتاح المضيف إعدادات SSH والوكيل لديك. تضبط متغيرات البيئة التالية الأمر:

| المتغير | التأثير |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | الملف التنفيذي الذي سيُشغّل بدلًا من `ssh` |
| `PITMASTER_SSH_IDENTITY_FILE` | يُمرّر بوصفه `-i <file>` |
| `PITMASTER_SSH_KNOWN_HOSTS` | يُمرّر بوصفه `-o UserKnownHostsFile=<file>` |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | يُمرّر بوصفه `-o StrictHostKeyChecking=<value>` |

يبدأ هذا المسار عملية، لذا فهو غير متاح للمقابض المفتوحة باستخدام `['processes' => false]`.

**امتداد `ssh2`** (يُفضّل دائمًا عند تحميله). يصادق Pitmaster باستخدام `~/.ssh/id_rsa`، ثم `~/.ssh/id_ed25519` إذا كان مفتاح RSA موجودًا لكن رُفض، وإلا فيستخدم وكيل SSH. تُتجاهل متغيرات `PITMASTER_SSH_*`، ولا يُتحقق من مفتاح مضيف الخادم في هذا المسار ([#22](https://github.com/inline0/pitmaster/issues/22)).

يشغّل نقل SSH الأمر `git-upload-pack` أو `git-receive-pack` على المستودع البعيد، ويتواصل عبر قناة SSH باستخدام بروتوكول pkt-line نفسه الذي يستخدمه HTTP الذكي.

## بروتوكول Git (TCP)

يتواصل بروتوكول git الأصلي عبر منافذ TCP رقم 9418 باستخدام مقابس PHP. ينفّذ `GitProtocolClient` اكتشاف المراجع و`upload-pack` (الجلب)، لكنه لا يدعم الدفع. لا يوجّه `clone()` و`fetch()` عناوين `git://` إليه، لذا استخدم العميل مباشرةً.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

عناوين Git:
```
git://github.com/user/repo.git
```

الخصائص:
- لا توجد مصادقة (للقراءة فقط عمليًا)
- لا يوجد تشفير
- أوقف معظم مزودي الاستضافة استخدامه
- يستخدم تأطير pkt-line نفسه الذي يستخدمه HTTP الذكي

يرسل بروتوكول git اسم الخدمة ومسار المستودع في الطلب الأولي، ثم يتابع باكتشاف المراجع والتفاوض على الحزم باستخدام pkt-line القياسي.

## الحزم المجمّعة

حزم Git المجمّعة ملفات حزم للاستخدام دون اتصال، تتضمن معلومات المراجع. وتتيح نقل بيانات المستودع دون اتصال بالشبكة.

```php
use Pitmaster\Protocol\Bundle;

// Read a bundle file
$bundle = Bundle::open('/path/to/repo.bundle');
$refs = $bundle->refs();
$packData = $bundle->packData();
$prerequisites = $bundle->prerequisites();

// Create one
$bundle = Bundle::create(['refs/heads/main' => $commitId], $packData);
$bundle->writeTo('/path/to/out.bundle');
```

يقرأ Pitmaster ترويسات الحزم المجمّعة v2 وv3. لا توجد طريقة `Repository` لاستيراد حزمة مجمّعة: اكتب `packData()` إلى `.git/objects/pack/`، وأنشئ فهرسها باستخدام `PackIndexer::writeIndex()`، ثم حدّث المراجع بنفسك.

تنسيق الحزم المجمّعة:
```
# v2 git bundle\n
-<prerequisite hash>\n    (zero or more)
<hash> <refname>\n        (one or more)
\n
<pack data>               (standard pack file format)
```

تفيد الحزم المجمّعة في:
- النقل دون شبكة (محركات USB)
- النسخ الاحتياطية التدريجية
- تهيئة نسخ المستودعات في بيئات معزولة عن الشبكة

## الاستنساخ السطحي

يدعم Pitmaster الاستنساخ السطحي، حيث لا يُجلب سوى عمق محدود من سجل الالتزامات.

```php
use Pitmaster\Protocol\ShallowClone;
```

مرّر عمقًا إلى `Pitmaster::clone($url, $path, $depth)` أو `$repo->fetch($remote, $depth)`. يضيف الطلب إمكانية `shallow` وسطر `deepen`:
```
want <hash>
deepen <depth>
```

يرد الخادم بأسطر `shallow <hash>` تشير إلى الموضع الذي اقتُطع عنده السجل. يحسب Pitmaster الحد السطحي من العمق نفسه، ويستخدم أسطر `shallow` من الخادم إذا لم يُفضِ هذا الحساب إلى نتيجة؛ وتُخزّن النتيجة في `.git/shallow`. يتعامل كل من `ShallowClone::readShallow()` و`writeShallow()` و`isShallow()` مع هذا الملف مباشرةً.

## مقارنة البروتوكولات

| البروتوكول | المصادقة | التشفير | الدفع | الاستخدام المعتاد |
|----------|------|-----------|------|-------------|
| HTTP الذكي | بيانات اعتماد في URL | HTTPS | نعم | وسيلة النقل الأساسية |
| HTTP غير الذكي | بيانات اعتماد في URL | HTTPS | لا | خيار احتياطي قديم |
| SSH | مفاتيح SSH أو وكيل | SSH | نعم | المستودعات الخاصة وCI |
| Git (TCP) | لا شيء | لا شيء | لا | نسخ مطابقة للقراءة فقط |
| حزمة مجمّعة | لا ينطبق | لا ينطبق | لا ينطبق | النقل دون اتصال |

## اختيار وسيلة النقل

يختار كل من `Pitmaster::clone()` و`$repo->fetch()` و`$repo->push()` وسيلة النقل من URL:

| نمط URL | وسيلة النقل |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| أي شيء آخر (`https://...`، `http://...`) | HTTP ذكي؛ يعود الاستنساخ والجلب إلى HTTP غير الذكي |

لا تدعم هذه الأساليب عناوين `git://` والمسارات المحلية؛ إذ تُرسل إلى عميل HTTP الذكي وتفشل. استخدم `GitProtocolClient` مباشرةً من أجل `git://`. ويُخلط حاليًا بين HTTPS URL الذي يحتوي على مستخدم ومنفذ (`https://user@host:8443/repo.git`) وبين URL SSH ([#17](https://github.com/inline0/pitmaster/issues/17)).
