
# Protokol

Pitmaster mendukung beberapa protokol transport jaringan untuk berkomunikasi dengan server git. Smart HTTP adalah transport utama. Protokol tambahan tersedia untuk kompatibilitas yang lebih luas.

## Smart HTTP (utama)

Transport yang direkomendasikan. Berfungsi melalui HTTPS dan merupakan protokol yang paling banyak digunakan. Tidak ada API untuk header atau kredensial kustom; kredensial hanya dapat dikirim di URL (`https://user:token@host/repo.git`), yang dikirim PHP sebagai autentikasi Basic. `clone()` menyimpan URL, termasuk kredensial, sebagai `remote.origin.url` di `.git/config`. Permintaan menggunakan pembungkus stream milik PHP, jadi `allow_url_fopen` harus diaktifkan.

```php
use Pitmaster\Protocol\SmartHttpClient;

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

Lihat [Smart HTTP](https://pitmaster.inline0.dev/id/docs/network/smart-http) untuk detail lengkap.

### Protokol v1

Protokol smart HTTP tradisional. Semua ref dikirim saat discovery, dan negosiasi menggunakan baris want/have/done.

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

### Protokol v2

Protokol yang lebih baru dengan perintah terstruktur (`ls-refs`, `fetch`). Lebih efisien untuk repositori dengan banyak ref karena klien dapat memfilter daftar ref.

`clone()` dan `fetch()` selalu menggunakan protokol v1. Protokol v2 tersedia secara eksplisit melalui smart HTTP menggunakan `SmartHttpClient::discoverRefsV2()` dan `UploadPackClient::fetchV2()`.

## Dumb HTTP

Fallback untuk server yang tidak mendukung protokol smart HTTP. Protokol dumb mengambil objek dan pack satu per satu melalui permintaan GET HTTP biasa.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Keterbatasan dumb HTTP:
- Tidak ada negosiasi (klien harus mengunduh semuanya)
- Tidak ada kompresi delta selama transfer
- Jauh lebih lambat daripada smart HTTP
- Beberapa server (GitHub, GitLab) tidak mendukungnya

Protokol dumb mengambil:
1. `GET /info/refs` (teks biasa, tanpa pkt-line)
2. `GET /HEAD` (cabang default)
3. `GET /objects/info/packs` (daftar pack yang tersedia)
4. `GET /objects/pack/pack-<hash>.pack` dan `.idx` (setiap pack yang tercantum dan indeksnya)
5. `GET /objects/<xx>/<rest>` (objek lepas satu per satu, ditelusuri dari tip ref)

Langkah 5 hanya dijalankan jika server tidak mencantumkan pack. Jika server mencantumkan pack, objek yang hanya tersedia sebagai file lepas di server tidak diunduh ([#18](https://github.com/inline0/pitmaster/issues/18)). Klien dumb hanya menerima ID objek 40 karakter (SHA-1). `clone()` dan `fetch()` beralih ke dumb HTTP jika pertukaran smart HTTP gagal.

## SSH

Transport SSH menggunakan ekstensi `ssh2` PHP jika ekstensi tersebut dimuat. Jika tidak, transport ini menjalankan klien `ssh` sistem melalui `proc_open()`. Keduanya menjalankan `git-upload-pack` atau `git-receive-pack` pada remote.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

URL SSH:
```
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git
```

Tidak diperlukan ekstensi. Kedua jalur bekerja secara berbeda:

**Klien `ssh` sistem** (digunakan saat `ssh2` tidak dimuat). Pitmaster menjalankan `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>`, sehingga autentikasi dan pemeriksaan kunci host mengikuti konfigurasi SSH dan agent Anda. Variabel lingkungan ini menyesuaikan perintah:

| Variabel | Efek |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | Executable yang dijalankan sebagai pengganti `ssh` |
| `PITMASTER_SSH_IDENTITY_FILE` | Dikirim sebagai `-i <file>` |
| `PITMASTER_SSH_KNOWN_HOSTS` | Dikirim sebagai `-o UserKnownHostsFile=<file>` |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | Dikirim sebagai `-o StrictHostKeyChecking=<value>` |

Jalur ini memulai proses, jadi tidak tersedia pada handle yang dibuka dengan `['processes' => false]`.

**Ekstensi `ssh2`** (selalu diprioritaskan jika dimuat). Pitmaster melakukan autentikasi dengan `~/.ssh/id_rsa`, lalu `~/.ssh/id_ed25519` jika kunci RSA tersedia tetapi ditolak, dan jika tidak, menggunakan agent SSH. Variabel `PITMASTER_SSH_*` diabaikan, dan kunci host server tidak diverifikasi pada jalur ini ([#22](https://github.com/inline0/pitmaster/issues/22)).

Transport SSH menjalankan `git-upload-pack` atau `git-receive-pack` sebagai perintah remote dan berkomunikasi melalui kanal SSH menggunakan protokol pkt-line yang sama dengan smart HTTP.

## Protokol Git (TCP)

Protokol git native berkomunikasi melalui port TCP 9418 menggunakan socket PHP. `GitProtocolClient` menerapkan discovery ref dan `upload-pack` (pengambilan); protokol ini tidak dapat melakukan push. `clone()` dan `fetch()` tidak mengarahkan URL `git://` ke protokol ini, jadi gunakan kliennya secara langsung.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

URL Git:
```
git://github.com/user/repo.git
```

Karakteristik:
- Tidak ada autentikasi (dalam praktiknya hanya baca)
- Tidak ada enkripsi
- Tidak digunakan lagi oleh sebagian besar penyedia hosting
- Menggunakan framing pkt-line yang sama dengan smart HTTP

Protokol git mengirim nama layanan dan jalur repositori sebagai permintaan awal, lalu melanjutkan dengan discovery ref pkt-line standar dan negosiasi pack.

## Bundle

Bundle Git adalah file pack offline yang berisi informasi ref. Bundle memungkinkan transfer data repositori tanpa koneksi jaringan.

```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 membaca header bundle v2 dan v3. Tidak ada metode `Repository` untuk mengimpor bundle: tulis `packData()` ke `.git/objects/pack/`, buat indeksnya dengan `PackIndexer::writeIndex()`, lalu perbarui ref sendiri.

Format bundle:
```
# v2 git bundle\n
-<prerequisite hash>\n    (zero or more)
<hash> <refname>\n        (one or more)
\n
<pack data>               (standard pack file format)
```

Bundle berguna untuk:
- Transfer sneakernet (drive USB)
- Cadangan inkremental
- Menyiapkan clone di lingkungan terisolasi dari jaringan

## Clone dangkal

Pitmaster mendukung clone dangkal, yaitu hanya mengambil riwayat commit hingga kedalaman tertentu.

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

Berikan kedalaman ke `Pitmaster::clone($url, $path, $depth)` atau `$repo->fetch($remote, $depth)`. Permintaan menambahkan kapabilitas `shallow` dan baris `deepen`:
```
want <hash>
deepen <depth>
```

Server merespons dengan baris `shallow <hash>` yang menunjukkan di mana riwayat dipotong. Pitmaster menghitung batas kedalaman dari kedalaman itu sendiri dan menggunakan baris `shallow` server jika perhitungan tersebut tidak menemukan apa pun; hasilnya disimpan di `.git/shallow`. `ShallowClone::readShallow()`, `writeShallow()`, dan `isShallow()` bekerja langsung dengan file itu.

## Perbandingan protokol

| Protokol | Autentikasi | Enkripsi | Push | Penggunaan umum |
|----------|------|-----------|------|-------------|
| Smart HTTP | Kredensial di URL | HTTPS | Ya | Transport utama |
| Dumb HTTP | Kredensial di URL | HTTPS | Tidak | Fallback lama |
| SSH | Kunci atau agent SSH | SSH | Ya | Repo privat, CI |
| Git (TCP) | Tidak ada | Tidak ada | Tidak | Mirror hanya-baca |
| Bundle | N/A | N/A | N/A | Transfer offline |

## Pemilihan transport

`Pitmaster::clone()`, `$repo->fetch()`, dan `$repo->push()` memilih transport dari URL:

| Pola URL | Transport |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Apa pun lainnya (`https://...`, `http://...`) | Smart HTTP; clone dan fetch beralih ke dumb HTTP |

URL `git://` dan jalur lokal tidak didukung oleh metode ini: keduanya dikirim ke klien smart HTTP dan gagal. Gunakan `GitProtocolClient` secara langsung untuk `git://`. HTTPS URL yang berisi pengguna dan port (`https://user@host:8443/repo.git`) saat ini keliru dianggap sebagai SSH URL ([#17](https://github.com/inline0/pitmaster/issues/17)).
