
# Protokoły

Pitmaster obsługuje wiele protokołów transportowych do komunikacji sieciowej z serwerami gita. Inteligentny HTTP to podstawowy transport. Dostępne są też dodatkowe protokoły zapewniające szerszą zgodność.

## Inteligentny HTTP (podstawowy)

Zalecany transport. Działa przez HTTPS i jest najpowszechniej stosowanym protokołem. Nie ma API dla własnych nagłówków ani danych uwierzytelniających; można je przekazać tylko w URL (`https://user:token@host/repo.git`), które PHP wysyła jako uwierzytelnianie Basic. `clone()` zapisuje URL, łącznie z danymi uwierzytelniającymi, jako `remote.origin.url` w `.git/config`. Żądania korzystają z opakowań strumieni PHP, dlatego `allow_url_fopen` musi być włączone.

```php
use Pitmaster\Protocol\SmartHttpClient;

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

Pełne informacje znajdziesz w sekcji [Inteligentny HTTP](https://pitmaster.inline0.dev/pl/docs/network/smart-http).

### Protokół v1

Tradycyjny inteligentny protokół HTTP. Podczas wyszukiwania przesyłane są wszystkie referencje, a negocjacja wykorzystuje linie want/have/done.

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

### Protokół v2

Nowszy protokół z uporządkowanymi poleceniami (`ls-refs`, `fetch`). Jest wydajniejszy w repozytoriach z wieloma referencjami, ponieważ klient może filtrować ich listę.

`clone()` i `fetch()` zawsze korzystają z protokołu v1. Protokół v2 jest dostępny jawnie przez inteligentny HTTP za pośrednictwem `SmartHttpClient::discoverRefsV2()` i `UploadPackClient::fetchV2()`.

## Prosty HTTP

Zapasowy protokół dla serwerów, które nie obsługują inteligentnego protokołu HTTP. Prosty protokół pobiera pojedynczo obiekty i pakiety za pomocą zwykłych żądań HTTP GET.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Ograniczenia prostego HTTP:
- Brak negocjacji (klient musi pobrać wszystko)
- Brak kompresji delt podczas przesyłania
- Znacznie wolniejszy niż inteligentny HTTP
- Niektóre serwery (GitHub, GitLab) go nie obsługują

Prosty protokół pobiera:
1. `GET /info/refs` (zwykły tekst, bez pkt-line)
2. `GET /HEAD` (domyślna gałąź)
3. `GET /objects/info/packs` (lista dostępnych pakietów)
4. `GET /objects/pack/pack-<hash>.pack` i `.idx` (każdy wymieniony pakiet i jego indeks)
5. `GET /objects/<xx>/<rest>` (pojedyncze luźne obiekty, przechodząc od końcówek referencji)

Krok 5 jest wykonywany tylko wtedy, gdy serwer nie wymienia żadnych pakietów. Jeśli wymienia pakiety, obiekty istniejące na serwerze wyłącznie jako luźne pliki nie są pobierane ([#18](https://github.com/inline0/pitmaster/issues/18)). Prosty klient akceptuje tylko identyfikatory obiektów o długości 40 znaków (SHA-1). `clone()` i `fetch()` przechodzą na prosty HTTP, jeśli inteligentna wymiana HTTP zakończy się niepowodzeniem.

## SSH

Transport SSH korzysta z rozszerzenia `ssh2` PHP, jeśli jest załadowane. W przeciwnym razie uruchamia systemowego klienta `ssh` za pośrednictwem `proc_open()`. W obu przypadkach na zdalnym serwerze uruchamia `git-upload-pack` lub `git-receive-pack`.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

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

Nie jest wymagane żadne rozszerzenie. Te dwie ścieżki działają inaczej:

**Systemowy klient `ssh`** (używany, gdy `ssh2` nie jest załadowane). Pitmaster uruchamia `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>`, więc uwierzytelnianie i sprawdzanie klucza hosta odbywają się zgodnie z konfiguracją SSH i agentem. Te zmienne środowiskowe modyfikują polecenie:

| Zmienna | Działanie |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | Plik wykonywalny uruchamiany zamiast `ssh` |
| `PITMASTER_SSH_IDENTITY_FILE` | Przekazywana jako `-i <file>` |
| `PITMASTER_SSH_KNOWN_HOSTS` | Przekazywana jako `-o UserKnownHostsFile=<file>` |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | Przekazywana jako `-o StrictHostKeyChecking=<value>` |

Ta ścieżka uruchamia proces, więc nie jest dostępna dla uchwytów otwartych z `['processes' => false]`.

**Rozszerzenie `ssh2`** (zawsze używane w pierwszej kolejności, gdy jest załadowane). Pitmaster uwierzytelnia się za pomocą `~/.ssh/id_rsa`, a następnie `~/.ssh/id_ed25519`, jeśli klucz RSA jest obecny, ale odrzucony, a w pozostałych przypadkach za pomocą agenta SSH. Zmienne `PITMASTER_SSH_*` są ignorowane, a klucz hosta serwera nie jest weryfikowany tą ścieżką ([#22](https://github.com/inline0/pitmaster/issues/22)).

Transport SSH uruchamia `git-upload-pack` lub `git-receive-pack` jako zdalne polecenie i komunikuje się przez kanał SSH, używając tego samego protokołu pkt-line co inteligentny HTTP.

## Protokół Git (TCP)

Natywny protokół gita komunikuje się przez port TCP 9418 za pomocą gniazd PHP. `GitProtocolClient` obsługuje wyszukiwanie referencji i `upload-pack` (pobieranie); nie obsługuje wysyłania. `clone()` i `fetch()` nie kierują do niego adresów URL `git://`, dlatego użyj klienta bezpośrednio.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

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

Charakterystyka:
- Brak uwierzytelniania (w praktyce tylko do odczytu)
- Brak szyfrowania
- Większość dostawców hostingu wycofała obsługę
- Używa takiego samego formatowania pkt-line jak inteligentny HTTP

Protokół gita wysyła nazwę usługi i ścieżkę repozytorium jako początkowe żądanie, a następnie przechodzi do standardowego wyszukiwania referencji pkt-line i negocjacji pakietu.

## Pakiety archiwalne

Pakiety archiwalne Git to pliki pakietów offline zawierające informacje o referencjach. Umożliwiają przesyłanie danych repozytorium bez połączenia sieciowego.

```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 odczytuje nagłówki pakietów archiwalnych v2 i v3. Nie ma metody `Repository` importowania pakietu archiwalnego: zapisz `packData()` w `.git/objects/pack/`, utwórz jego indeks za pomocą `PackIndexer::writeIndex()` i samodzielnie zaktualizuj referencje.

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

Pakiety archiwalne przydają się do:
- Przesyłania danych bez sieci (na dyskach USB)
- Przyrostowych kopii zapasowych
- Przygotowywania klonów w środowiskach odizolowanych od sieci

## Płytkie klonowanie

Pitmaster obsługuje płytkie klonowanie, w którym pobierana jest tylko ograniczona część historii zatwierdzeń.

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

Podaj głębokość w `Pitmaster::clone($url, $path, $depth)` lub `$repo->fetch($remote, $depth)`. Żądanie dodaje możliwość `shallow` i linię `deepen`:
```
want <hash>
deepen <depth>
```

Serwer odpowiada wierszami `shallow <hash>` wskazującymi miejsce, w którym historia została obcięta. Pitmaster oblicza płytką granicę na podstawie samej głębokości i używa wierszy `shallow` serwera, gdy obliczenia niczego nie znajdą; wynik jest zapisywany w `.git/shallow`. `ShallowClone::readShallow()`, `writeShallow()` i `isShallow()` bezpośrednio korzystają z tego pliku.

## Porównanie protokołów

| Protokół | Uwierzytelnianie | Szyfrowanie | Wysyłanie zmian | Typowe zastosowanie |
|----------|----------------|-----------|------|-------------|
| Smart HTTP | Dane uwierzytelniające w URL | HTTPS | Tak | Podstawowy transport |
| Dumb HTTP | Dane uwierzytelniające w URL | HTTPS | Nie | Zgodność ze starszymi wersjami |
| SSH | Klucze SSH lub agent | SSH | Tak | Prywatne repozytoria, CI |
| Git (TCP) | Brak | Brak | Nie | Lustra tylko do odczytu |
| Bundle | Nie dotyczy | Nie dotyczy | Nie dotyczy | Transfer offline |

## Wybór transportu

`Pitmaster::clone()`, `$repo->fetch()` i `$repo->push()` wybierają transport na podstawie URL:

| Wzorzec URL | Transport |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Wszystko inne (`https://...`, `http://...`) | Smart HTTP; clone i fetch przechodzą w tryb dumb HTTP |

`git://` URL-e i ścieżki lokalne nie są obsługiwane przez te metody: są przekazywane do klienta smart HTTP i kończą się błędem. W przypadku `git://` użyj bezpośrednio `GitProtocolClient`. Obecnie HTTPS URL zawierający zarówno użytkownika, jak i port (`https://user@host:8443/repo.git`) jest błędnie rozpoznawany jako SSH URL ([#17](https://github.com/inline0/pitmaster/issues/17)).
