
# Protokoller

Pitmaster, git sunucularıyla iletişim kurmak için birden fazla ağ aktarım protokolünü destekler. Akıllı HTTP birincil aktarımdır. Daha geniş uyumluluk için ek protokoller de kullanılabilir.

## Akıllı HTTP (birincil)

Önerilen aktarım yöntemidir. HTTPS üzerinden çalışır ve en yaygın kullanılan protokoldür. Özel başlıklar veya kimlik bilgileri için API yoktur; kimlik bilgileri yalnızca URL içinde (`https://user:token@host/repo.git`) geçirilebilir ve PHP bunları Basic kimlik doğrulaması olarak gönderir. `clone()`, kimlik bilgileri dahil URL değerini `.git/config` içinde `remote.origin.url` olarak saklar. İsteklerde PHP'nin akış sarmalayıcıları kullanılır; bu nedenle `allow_url_fopen` etkin olmalıdır.

```php
use Pitmaster\Protocol\SmartHttpClient;

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

Tüm ayrıntılar için [Akıllı HTTP](https://pitmaster.inline0.dev/tr/docs/network/smart-http) bölümüne bakın.

### v1 protokolü

Geleneksel akıllı HTTP protokolüdür. Keşif sırasında tüm ref'ler gönderilir; uzlaşmada istenenler/mevcutlar/tamamlandı satırları kullanılır.

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

### v2 protokolü

Yapılandırılmış komutlara sahip daha yeni protokoldür (`ls-refs`, `fetch`). İstemci ref listesini filtreleyebildiği için çok sayıda ref içeren depolarda daha verimlidir.

`clone()` ve `fetch()` her zaman v1 protokolünü kullanır. v2 protokolü, HTTP akıllı aktarımı üzerinden `SmartHttpClient::discoverRefsV2()` ve `UploadPackClient::fetchV2()` aracılığıyla açıkça kullanılabilir.

## Basit HTTP

Akıllı HTTP protokolünü desteklemeyen sunucular için yedek yöntemdir. Basit protokol, nesneleri ve pack'leri tek tek, düz HTTP GET istekleriyle getirir.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Basit HTTP sınırlamaları:
- Uzlaşma yoktur (istemci her şeyi indirmelidir)
- Aktarım sırasında delta sıkıştırması yapılmaz
- Akıllı HTTP yönteminden çok daha yavaştır
- Bazı sunucular (GitHub, GitLab) bunu desteklemez

Basit protokol şunları getirir:
1. `GET /info/refs` (düz metin, pkt-line yok)
2. `GET /HEAD` (varsayılan dal)
3. `GET /objects/info/packs` (kullanılabilir pack'lerin listesi)
4. `GET /objects/pack/pack-<hash>.pack` ve `.idx` (listelenen her pack ve indeksi)
5. `GET /objects/<xx>/<rest>` (ref uçlarından başlayarak dolaşılan tek tek gevşek nesneler)

5. adım yalnızca sunucu hiçbir pack listelemediğinde çalışır. Pack listelendiğinde, sunucuda yalnızca gevşek dosyalar olarak bulunan nesneler indirilmez ([#18](https://github.com/inline0/pitmaster/issues/18)). Basit istemci yalnızca 40 karakterlik (SHA-1) nesne kimliklerini kabul eder. Akıllı HTTP alışverişi başarısız olursa `clone()` ve `fetch()` basit HTTP yöntemine geçer.

## SSH

SSH aktarımı yüklüyse `ssh2` PHP uzantısını kullanır. Aksi durumda sistemin `ssh` istemcisini `proc_open()` üzerinden başlatır. Her iki durumda da uzak sunucuda uzaktan komut olarak `git-upload-pack` veya `git-receive-pack` çalıştırır.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

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

Uzantı gerekmez. İki yol farklı şekilde çalışır:

**Sistem `ssh` istemcisi** (`ssh2` yüklü olmadığında kullanılır). Pitmaster, `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>` çalıştırır; bu nedenle kimlik doğrulama ve ana makine anahtarı denetimi, SSH yapılandırmanıza ve aracınıza göre yapılır. Bu ortam değişkenleri komutu ayarlar:

| Değişken | Etki |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | `ssh` yerine çalıştırılacak yürütülebilir dosya |
| `PITMASTER_SSH_IDENTITY_FILE` | `-i <file>` olarak geçirilir |
| `PITMASTER_SSH_KNOWN_HOSTS` | `-o UserKnownHostsFile=<file>` olarak geçirilir |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | `-o StrictHostKeyChecking=<value>` olarak geçirilir |

Bu yol bir süreç başlatır; bu nedenle `['processes' => false]` ile açılan tanıtıcılarda kullanılamaz.

**`ssh2` uzantısı** (yüklüyse her zaman tercih edilir). Pitmaster, `~/.ssh/id_rsa` ile kimlik doğrular; RSA anahtarı varsa ancak reddedilmişse `~/.ssh/id_ed25519` ile dener, aksi durumda SSH aracısını kullanır. `PITMASTER_SSH_*` değişkenleri yok sayılır ve bu yolda sunucunun ana makine anahtarı doğrulanmaz ([#22](https://github.com/inline0/pitmaster/issues/22)).

SSH aktarımı, uzak komut olarak `git-upload-pack` veya `git-receive-pack` çalıştırır ve akıllı HTTP ile aynı pkt-line protokolünü kullanarak SSH kanalı üzerinden iletişim kurar.

## Git protokolü (TCP)

Yerel git protokolü, TCP portu 9418 üzerinden PHP soketleri kullanarak iletişim kurar. `GitProtocolClient` ref keşfini ve `upload-pack` (getirme) işlemini uygular; push yapamaz. `clone()` ve `fetch()`, `git://` URL'lerini bu protokole yönlendirmez; bu nedenle istemciyi doğrudan kullanın.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

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

Özellikler:
- Kimlik doğrulama yoktur (uygulamada salt okunur)
- Şifreleme yoktur
- Çoğu barındırma sağlayıcısı tarafından kullanımdan kaldırılmıştır
- Akıllı HTTP ile aynı pkt-line çerçevelemesini kullanır

git protokolü, ilk istekte hizmet adını ve depo yolunu gönderir; ardından standart pkt-line ref keşfi ve pack uzlaşmasıyla devam eder.

## Paketler

Git paketleri, ref bilgisi içeren çevrimdışı pack dosyalarıdır. Depo verilerinin ağ bağlantısı olmadan aktarılmasını sağlar.

```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 ve v3 paket başlıklarını okur. Paketi içe aktarmak için `Repository` yöntemi yoktur: `packData()` dosyasını `.git/objects/pack/` konumuna yazın, `PackIndexer::writeIndex()` ile indeksini oluşturun ve ref'leri kendiniz güncelleyin.

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

Paketler şu durumlarda kullanışlıdır:
- Sneakernet aktarımları (USB sürücüler)
- Artımlı yedeklemeler
- Ağdan yalıtılmış ortamlarda clone'ları başlatma

## Sığ klonlar

Pitmaster, commit geçmişinin yalnızca sınırlı bir derinliğinin getirildiği sığ klonları destekler.

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

`Pitmaster::clone($url, $path, $depth)` veya `$repo->fetch($remote, $depth)` için bir derinlik belirtin. İstek, `shallow` yeteneğini ve bir `deepen` satırını ekler:
```
want <hash>
deepen <depth>
```

Sunucu, geçmişin nerede kesildiğini gösteren `shallow <hash>` satırlarıyla yanıt verir. Pitmaster, sığ sınırı doğrudan derinlikten hesaplar; bu hesaplama sonuç vermezse sunucunun `shallow` satırlarını kullanır. Sonuç `.git/shallow` içinde saklanır. `ShallowClone::readShallow()`, `writeShallow()` ve `isShallow()` bu dosyayla doğrudan çalışır.

## Protokol karşılaştırması

| Protokol | Kimlik doğrulama | Şifreleme | Gönderme | Yaygın kullanım |
|----------|------|-----------|------|-------------|
| Akıllı HTTP | URL içinde kimlik bilgileri | HTTPS | Evet | Birincil aktarım |
| Aptal HTTP | URL içinde kimlik bilgileri | HTTPS | Hayır | Eski sistemler için yedek |
| SSH | SSH anahtarları veya aracı | SSH | Evet | Özel depolar, CI |
| Git (TCP) | Yok | Yok | Hayır | Salt okunur yansılar |
| Paket | Uygulanamaz | Uygulanamaz | Uygulanamaz | Çevrimdışı aktarım |

## Aktarım seçimi

`Pitmaster::clone()`, `$repo->fetch()` ve `$repo->push()` aktarımı URL üzerinden seçer:

| URL deseni | Aktarım |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Diğer her şey (`https://...`, `http://...`) | Akıllı HTTP; clone ve fetch, aptal HTTP yöntemine geri döner |

Bu yöntemler `git://` URL'lerini ve yerel yolları desteklemez: bunlar akıllı HTTP istemcisine gönderilir ve başarısız olur. `git://` için doğrudan `GitProtocolClient` kullanın. Hem kullanıcı hem de bağlantı noktası içeren bir HTTPS URL (`https://user@host:8443/repo.git`), şu anda yanlışlıkla bir SSH URL olarak algılanıyor ([#17](https://github.com/inline0/pitmaster/issues/17)).
