
# Protokoli

Pitmaster podpira več omrežnih prenosnih protokolov za komunikacijo s strežniki git. Primarni prenos je pametni protokol HTTP. Na voljo so tudi dodatni protokoli za širšo združljivost.

## Pametni HTTP (primarni)

Priporočeni prenos. Deluje prek HTTPS in je najpogosteje uporabljen protokol. Za glave po meri ali poverilnice ni na voljo API; poverilnice je mogoče posredovati le v URL (`https://user:token@host/repo.git`), ki jih PHP pošlje kot osnovno preverjanje pristnosti. `clone()` shrani URL, vključno s poverilnicami, kot `remote.origin.url` v `.git/config`. Zahteve uporabljajo ovojnike tokov PHP, zato mora biti omogočen `allow_url_fopen`.

```php
use Pitmaster\Protocol\SmartHttpClient;

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

Za vse podrobnosti glejte [Pametni HTTP](https://pitmaster.inline0.dev/sl/docs/network/smart-http).

### Protokol v1

Tradicionalni pametni protokol HTTP. Med odkrivanjem se pošljejo vse reference, dogovarjanje pa uporablja vrstice want/have/done.

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

### Protokol v2

Novejši protokol s strukturiranimi ukazi (`ls-refs`, `fetch`). Učinkovitejši je za repozitorije z veliko referencami, saj lahko odjemalec filtrira seznam referenc.

`clone()` in `fetch()` vedno uporabljata protokol v1. Protokol v2 je na voljo izrecno prek pametnega protokola HTTP prek `SmartHttpClient::discoverRefsV2()` in `UploadPackClient::fetchV2()`.

## Preprosti HTTP

Nadomestna možnost za strežnike, ki ne podpirajo pametnega protokola HTTP. Preprosti protokol pridobiva objekte in pakete posamično z navadnimi zahtevami GET prek HTTP.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Omejitve preprostega HTTP:
- Brez dogovarjanja (odjemalec mora prenesti vse)
- Med prenosom ni stiskanja delt
- Precej počasnejši od pametnega protokola HTTP
- Nekateri strežniki (GitHub, GitLab) ga ne podpirajo

Preprosti protokol pridobi:
1. `GET /info/refs` (navadno besedilo, brez pkt-line)
2. `GET /HEAD` (privzeta veja)
3. `GET /objects/info/packs` (seznam razpoložljivih paketov)
4. `GET /objects/pack/pack-<hash>.pack` in `.idx` (vsak navedeni paket in njegov indeks)
5. `GET /objects/<xx>/<rest>` (posamezne proste objekte, ki jih poišče od vrhov referenc naprej)

5. korak se izvede samo, kadar strežnik ne navede nobenega paketa. Če navede pakete, se objekti, ki na strežniku obstajajo samo kot ohlapne datoteke, ne prenesejo ([#18](https://github.com/inline0/pitmaster/issues/18)). Preprost odjemalec sprejema samo 40-mestne ID-je objektov (SHA-1). `clone()` in `fetch()` preklopita na preprost HTTP, kadar izmenjava s pametnim HTTP ne uspe.

## SSH

Prenos SSH uporablja razširitev `ssh2` PHP, če je naložena. Sicer zažene sistemski odjemalec `ssh` prek `proc_open()`. V obeh primerih na oddaljenem gostitelju zažene `git-upload-pack` ali `git-receive-pack`.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

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

Razširitev ni potrebna. Obe poti delujeta različno:

**Sistemski odjemalec `ssh`** (uporabi se, kadar `ssh2` ni naložen). Pitmaster zažene `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>`, zato preverjanje pristnosti in gostiteljskega ključa sledita konfiguraciji SSH in agentu. Te spremenljivke okolja prilagodijo ukaz:

| Spremenljivka | Učinek |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | Izvedljiva datoteka, ki se zažene namesto `ssh` |
| `PITMASTER_SSH_IDENTITY_FILE` | Posredovana kot `-i <file>` |
| `PITMASTER_SSH_KNOWN_HOSTS` | Posredovana kot `-o UserKnownHostsFile=<file>` |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | Posredovana kot `-o StrictHostKeyChecking=<value>` |

Ta pot zažene proces, zato ni na voljo pri povezavah, odprtih z `['processes' => false]`.

**Razširitev `ssh2`** (vedno ima prednost, kadar je naložena). Pitmaster se najprej preveri pristnost z `~/.ssh/id_rsa`, nato z `~/.ssh/id_ed25519`, če je ključ RSA na voljo, vendar zavrnjen, sicer pa z agentom SSH. Spremenljivke `PITMASTER_SSH_*` se prezrejo, gostiteljski ključ strežnika pa se na tej poti ne preveri ([#22](https://github.com/inline0/pitmaster/issues/22)).

Prenos SSH izvede `git-upload-pack` ali `git-receive-pack` kot oddaljeni ukaz in komunicira prek kanala SSH z istim protokolom pkt-line kot pametni protokol HTTP.

## Protokol Git (TCP)

Izvorni protokol git komunicira prek vrat TCP 9418 z uporabo vtičnic PHP. `GitProtocolClient` implementira odkrivanje referenc in `upload-pack` (pridobivanje); pošiljanje ni mogoče. `clone()` in `fetch()` URL-jev `git://` ne usmerjata nanj, zato uporabite odjemalca neposredno.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

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

Značilnosti:
- Brez preverjanja pristnosti (v praksi samo za branje)
- Brez šifriranja
- Večina ponudnikov gostovanja protokol opušča
- Uporablja enako uokvirjanje pkt-line kot pametni protokol HTTP

Protokol git v začetni zahtevi pošlje ime storitve in pot do repozitorija, nato pa nadaljuje s standardnim odkrivanjem referenc pkt-line in dogovarjanjem o paketih.

## Paketi

Paketi Git so datoteke paketov za uporabo brez povezave, ki vsebujejo podatke o referencah. Omogočajo prenos podatkov repozitorija brez omrežne povezave.

```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 bere glavi paketov v2 in v3. Za uvoz paketa ni na voljo metode `Repository`: zapišite `packData()` v `.git/objects/pack/`, ustvarite njegov indeks z `PackIndexer::writeIndex()` in sami posodobite reference.

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

Paketi so uporabni za:
- Prenose s fizičnimi mediji (pogon USB)
- Postopne varnostne kopije
- Pripravo klonov v okoljih brez omrežne povezave

## Plitvi kloni

Pitmaster podpira plitve klone, pri katerih se prenese le omejena globina zgodovine objav.

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

Podajte globino za `Pitmaster::clone($url, $path, $depth)` ali `$repo->fetch($remote, $depth)`. Zahteva doda zmožnost `shallow` in vrstico `deepen`:
```
want <hash>
deepen <depth>
```

Strežnik odgovori z vrsticami `shallow <hash>`, ki kažejo, kje je bila zgodovina skrajšana. Pitmaster izračuna plitvo mejo na podlagi same globine in uporabi strežniške vrstice `shallow`, kadar izračun ne vrne ničesar; rezultat shrani v `.git/shallow`. `ShallowClone::readShallow()`, `writeShallow()` in `isShallow()` neposredno delajo s to datoteko.

## Primerjava protokolov

| Protokol | Preverjanje pristnosti | Šifriranje | Potiskanje | Običajna uporaba |
|----------|------|-----------|------|-------------|
| Smart HTTP | Poverilnice v URL | HTTPS | Da | Primarni prenos |
| Dumb HTTP | Poverilnice v URL | HTTPS | Ne | Združljivostna možnost za starejše sisteme |
| SSH | Ključi SSH ali posrednik | SSH | Da | Zasebni repozitoriji, CI |
| Git (TCP) | Brez | Brez | Ne | Zrcalni strežniki samo za branje |
| Paket | Ni na voljo | Ni na voljo | Ni na voljo | Prenos brez povezave |

## Izbira prenosa

`Pitmaster::clone()`, `$repo->fetch()` in `$repo->push()` izberejo način prenosa iz URL:

| Vzorec URL | Prenos |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Vse drugo (`https://...`, `http://...`) | Smart HTTP; pri kloniranju in pridobivanju se uporabi Dumb HTTP kot nadomestna možnost |

Metode `git://` ne podpirajo URL-jev in lokalnih poti: poslane so odjemalcu smart HTTP, kjer ne delujejo. Za `git://` uporabite neposredno `GitProtocolClient`. HTTPS URL, ki vsebuje uporabnika in vrata (`https://user@host:8443/repo.git`), je trenutno napačno prepoznan kot SSH URL ([#17](https://github.com/inline0/pitmaster/issues/17)).
