
# Protokollok

Az Pitmaster több hálózati átviteli protokollt támogat a git-szerverekkel való kommunikációhoz. Az intelligens HTTP az elsődleges átviteli mód. A szélesebb kompatibilitás érdekében további protokollok is rendelkezésre állnak.

## Intelligens HTTP (elsődleges)

Az ajánlott átviteli mód. HTTPS-on keresztül működik, és ez a legszélesebb körben használt protokoll. Egyéni fejlécekhez vagy hitelesítő adatokhoz nincs API; hitelesítő adatok csak az URL-ben adhatók át (`https://user:token@host/repo.git`), amelyet az PHP Basic hitelesítésként küld el. Az `clone()` a URL tartalmát, a hitelesítő adatokat is beleértve, `remote.origin.url` formában tárolja az `.git/config` helyen. A kérések az PHP adatfolyam-burkolóit használják, ezért engedélyezni kell az `allow_url_fopen` beállítást.

```php
use Pitmaster\Protocol\SmartHttpClient;

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

A teljes részletekért lásd: [Intelligens HTTP](https://pitmaster.inline0.dev/hu/docs/network/smart-http).

### v1 protokoll

A hagyományos intelligens HTTP protokoll. A felderítés során az összes ref elküldésre kerül, az egyeztetés pedig want/have/done sorokkal történik.

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

### v2 protokoll

Az újabb protokoll strukturált parancsokkal (`ls-refs`, `fetch`). Sok refet tartalmazó tárolóknál hatékonyabb, mert a kliens szűrheti a refek listáját.

Az `clone()` és az `fetch()` mindig a v1 protokollt használja. A v2 protokoll kifejezetten, intelligens HTTP felett, az `SmartHttpClient::discoverRefsV2()` és az `UploadPackClient::fetchV2()` segítségével érhető el.

## Egyszerű HTTP

Tartalék megoldás azokhoz a szerverekhez, amelyek nem támogatják az intelligens HTTP protokollt. Az egyszerű protokoll az objektumokat és packokat külön-külön, egyszerű HTTP GET-kérésekkel tölti le.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Az egyszerű HTTP korlátai:
- Nincs egyeztetés (a kliensnek mindent le kell töltenie)
- Átvitel közben nincs delta-tömörítés
- Jelentősen lassabb az intelligens HTTP protokollnál
- Egyes szerverek (GitHub, GitLab) nem támogatják

Az egyszerű protokoll az alábbiakat tölti le:
1. `GET /info/refs` (egyszerű szöveg, pkt-line nélkül)
2. `GET /HEAD` (alapértelmezett ág)
3. `GET /objects/info/packs` (az elérhető packok listája)
4. `GET /objects/pack/pack-<hash>.pack` és `.idx` (minden felsorolt pack és annak indexe)
5. `GET /objects/<xx>/<rest>` (egyedi laza objektumok, a refek csúcsaitól bejárva)

Az 5. lépés csak akkor fut le, ha a szerver nem sorol fel packokat. Ha packokat sorol fel, a szerveren csak laza fájlként létező objektumok nem töltődnek le ([#18](https://github.com/inline0/pitmaster/issues/18)). Az egyszerű kliens csak 40 karakteres (SHA-1) objektumazonosítókat fogad el. Az `clone()` és az `fetch()` egyszerű HTTP módra vált, ha az intelligens HTTP egyeztetés sikertelen.

## SSH

Az SSH átviteli mód betöltött állapotban az `ssh2` PHP kiterjesztést használja. Ellenkező esetben az `proc_open()` segítségével elindítja a rendszer `ssh` kliensét. Mindkét esetben az `git-upload-pack` vagy az `git-receive-pack` parancsot futtatja a távoli gépen.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

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

Nincs szükség kiterjesztésre. A két módszer eltérően működik:

**Rendszer-`ssh` kliens** (ha az `ssh2` nincs betöltve). Az Pitmaster az `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>` parancsot futtatja, ezért a hitelesítés és a gazdagép-kulcs ellenőrzése az Ön SSH konfigurációját és ügynökét követi. Ezek a környezeti változók módosítják a parancsot:

| Változó | Hatás |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | Az `ssh` helyett futtatandó végrehajtható fájl |
| `PITMASTER_SSH_IDENTITY_FILE` | `-i <file>` formában kerül átadásra |
| `PITMASTER_SSH_KNOWN_HOSTS` | `-o UserKnownHostsFile=<file>` formában kerül átadásra |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | `-o StrictHostKeyChecking=<value>` formában kerül átadásra |

Ez a módszer folyamatot indít, ezért nem érhető el az `['processes' => false]` használatával megnyitott fogantyúkon.

**`ssh2` kiterjesztés** (betöltés esetén mindig ezt részesíti előnyben). Az Pitmaster az `~/.ssh/id_rsa` használatával hitelesít, majd `~/.ssh/id_ed25519`-mal próbálkozik, ha az RSA-kulcs létezik, de elutasításra kerül, végül pedig az SSH ügynököt használja. Az `PITMASTER_SSH_*` változókat figyelmen kívül hagyja, a szerver gazdagép-kulcsát pedig ezen az útvonalon nem ellenőrzi ([#22](https://github.com/inline0/pitmaster/issues/22)).

Az SSH átviteli mód távoli parancsként futtatja az `git-upload-pack` vagy az `git-receive-pack` parancsot, és az SSH csatornán kommunikál, az intelligens HTTP protokollal megegyező pkt-line protokollt használva.

## Git protokoll (TCP)

A natív git protokoll TCP 9418 porton, PHP socketek használatával kommunikál. Az `GitProtocolClient` megvalósítja a refek felderítését és az `upload-pack` műveletet (letöltés); pushra nem képes. Az `clone()` és az `fetch()` nem irányítja ide az `git://` URL-eket, ezért használja közvetlenül a klienst.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

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

Jellemzők:
- Nincs hitelesítés (a gyakorlatban csak olvasható)
- Nincs titkosítás
- A legtöbb tárhelyszolgáltató elavultnak minősíti
- Ugyanazt a pkt-line keretezést használja, mint az intelligens HTTP

A git protokoll kezdeti kérésként elküldi a szolgáltatás nevét és a tároló elérési útját, majd a szabványos pkt-line ref-felderítéssel és pack-egyeztetéssel folytatódik.

## Bundle-ok

Az Git bundle-ok offline packfájlok refinformációkkal. Lehetővé teszik a tárolóadatok hálózati kapcsolat nélküli átvitelét.

```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');
```

Az Pitmaster beolvassa az v2 és az v3 bundle-fejléceket. Nincs `Repository` módszer bundle importálására: írja az `packData()` fájlt az `.git/objects/pack/` helyre, készítse el az indexét az `PackIndexer::writeIndex()` segítségével, majd frissítse kézzel a refeket.

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

A bundle-ok hasznosak:
- Hálózat nélküli (USB-meghajtós) átvitelhez
- Növekményes biztonsági mentésekhez
- Klónok előkészítéséhez hálózattól elszigetelt környezetben

## Sekély klónok

Az Pitmaster támogatja a sekély klónokat, amelyek csak korlátozott mélységű commitelőzményt töltenek le.

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

Adjon meg mélységet az `Pitmaster::clone($url, $path, $depth)` vagy az `$repo->fetch($remote, $depth)` számára. A kérés hozzáadja az `shallow` képességet és egy `deepen` sort:
```
want <hash>
deepen <depth>
```

A szerver `shallow <hash>` sorokkal jelzi, hol szakadt meg az előzmény. Az Pitmaster magából a mélységből számítja ki a sekély határt, és a szerver `shallow` sorait használja, ha ez a számítás nem talál eredményt; az eredményt az `.git/shallow` tárolja. Az `ShallowClone::readShallow()`, az `writeShallow()` és az `isShallow()` közvetlenül ezzel a fájllal dolgozik.

## Protokollok összehasonlítása

| Protokoll | Hitelesítés | Titkosítás | Push | Jellemző használat |
|----------|------|-----------|------|-------------|
| Intelligens HTTP | Hitelesítő adatok az URL helyen | HTTPS | Igen | Elsődleges átviteli mód |
| Egyszerű HTTP | Hitelesítő adatok az URL helyen | HTTPS | Nem | Régi rendszerekhez tartalék megoldás |
| SSH | SSH kulcsok vagy ügynök | SSH | Igen | Privát tárolók, CI |
| Git (TCP) | Nincs | Nincs | Nem | Csak olvasható tükrök |
| Bundle | Nem értelmezhető | Nem értelmezhető | Nem értelmezhető | Offline átvitel |

## Átviteli mód kiválasztása

Az `Pitmaster::clone()`, az `$repo->fetch()` és az `$repo->push()` az URL alapján választja ki az átviteli módot:

| URL minta | Átviteli mód |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Minden más (`https://...`, `http://...`) | Intelligens HTTP; a klónozás és a letöltés egyszerű HTTP módra vált |

Az `git://` URL-ek és helyi elérési utak nem támogatottak ezekkel a metódusokkal: az intelligens HTTP klienshez kerülnek, és hibát okoznak. Használja közvetlenül az `GitProtocolClient` parancsot az `git://` esetében. Az a HTTPS URL, amely felhasználót és portot is tartalmaz (`https://user@host:8443/repo.git`), jelenleg SSH URL-ként jelenik meg ([#17](https://github.com/inline0/pitmaster/issues/17)).
