
# Protocoale

Pitmaster acceptă mai multe protocoale de transport de rețea pentru comunicarea cu serverele git. Smart HTTP este transportul principal. Sunt disponibile protocoale suplimentare pentru compatibilitate extinsă.

## Smart HTTP (principal)

Transportul recomandat. Funcționează prin HTTPS și este protocolul cel mai răspândit. Nu există API pentru antete sau acreditări personalizate; acreditările pot fi transmise numai în URL (`https://user:token@host/repo.git`), pe care PHP îl trimite ca autentificare Basic. `clone()` stochează URL, inclusiv acreditările, ca `remote.origin.url` în `.git/config`. Cererile folosesc fluxurile PHP, așadar `allow_url_fopen` trebuie să fie activată.

```php
use Pitmaster\Protocol\SmartHttpClient;

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

Consultați [Smart HTTP](https://pitmaster.inline0.dev/ro/docs/network/smart-http) pentru detalii complete.

### v1 protocol

Protocolul smart HTTP tradițional. Toate referințele sunt trimise în timpul descoperirii, iar negocierea folosește liniile want/have/done.

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

### v2 protocol

Protocolul mai nou, cu comenzi structurate (`ls-refs`, `fetch`). Este mai eficient pentru depozitele cu multe referințe, deoarece clientul poate filtra lista acestora.

`clone()` și `fetch()` folosesc întotdeauna protocolul v1. Protocolul v2 este disponibil explicit prin smart HTTP, prin intermediul `SmartHttpClient::discoverRefsV2()` și `UploadPackClient::fetchV2()`.

## Dumb HTTP

Opțiune de rezervă pentru serverele care nu acceptă protocolul smart HTTP. Protocolul dumb preia obiectele și fișierele pack individual, prin cereri GET simple HTTP.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Limitările protocolului dumb HTTP:
- Fără negociere (clientul trebuie să descarce totul)
- Fără comprimare delta în timpul transferului
- Semnificativ mai lent decât smart HTTP
- Unele servere (GitHub, GitLab) nu îl acceptă

Protocolul dumb preia:
1. `GET /info/refs` (text simplu, fără pkt-line)
2. `GET /HEAD` (ramura implicită)
3. `GET /objects/info/packs` (lista fișierelor pack disponibile)
4. `GET /objects/pack/pack-<hash>.pack` și `.idx` (fiecare fișier pack listat și indexul său)
5. `GET /objects/<xx>/<rest>` (obiecte libere individuale, parcurse pornind de la vârfurile referințelor)

Pasul 5 rulează numai când serverul nu listează niciun fișier pack. Dacă listează fișiere pack, obiectele care există doar ca fișiere libere pe server nu sunt descărcate ([#18](https://github.com/inline0/pitmaster/issues/18)). Clientul dumb acceptă numai ID-uri de obiecte cu 40 de caractere (SHA-1). `clone()` și `fetch()` revin la dumb HTTP dacă schimbul smart HTTP eșuează.

## SSH

Transportul SSH folosește extensia `ssh2` PHP când aceasta este încărcată. În caz contrar, pornește clientul de sistem `ssh` prin `proc_open()`. În ambele cazuri rulează `git-upload-pack` sau `git-receive-pack` pe serverul la distanță.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

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

Nu este necesară nicio extensie. Cele două căi se comportă diferit:

**Clientul `ssh` de sistem** (folosit când `ssh2` nu este încărcat). Pitmaster rulează `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>`, așadar autentificarea și verificarea cheii gazdei urmează configurația SSH și agentul dvs. Aceste variabile de mediu modifică comanda:

| Variabilă | Efect |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | Executabilul rulat în locul lui `ssh` |
| `PITMASTER_SSH_IDENTITY_FILE` | Transmis ca `-i <file>` |
| `PITMASTER_SSH_KNOWN_HOSTS` | Transmis ca `-o UserKnownHostsFile=<file>` |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | Transmis ca `-o StrictHostKeyChecking=<value>` |

Această cale pornește un proces, așadar nu este disponibilă pentru instanțele deschise cu `['processes' => false]`.

**Extensia `ssh2`** (este întotdeauna preferată când este încărcată). Pitmaster se autentifică folosind `~/.ssh/id_rsa`, apoi `~/.ssh/id_ed25519` dacă cheia RSA există, dar este respinsă; în caz contrar, folosește agentul SSH. Variabilele `PITMASTER_SSH_*` sunt ignorate, iar pe această cale cheia gazdei serverului nu este verificată ([#22](https://github.com/inline0/pitmaster/issues/22)).

Transportul SSH rulează `git-upload-pack` sau `git-receive-pack` ca o comandă la distanță și comunică prin canalul SSH, folosind același protocol pkt-line ca smart HTTP.

## Protocolul Git (TCP)

Protocolul nativ git comunică prin portul TCP 9418, folosind socket-uri PHP. `GitProtocolClient` implementează descoperirea referințelor și `upload-pack` (preluarea); nu poate trimite modificări. `clone()` și `fetch()` nu direcționează URL-uri `git://` către acesta, așadar folosiți direct clientul.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

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

Caracteristici:
- Fără autentificare (în practică, doar pentru citire)
- Fără criptare
- Învechit pentru majoritatea furnizorilor de găzduire
- Folosește aceeași încadrare pkt-line ca smart HTTP

Protocolul git trimite numele serviciului și calea depozitului în cererea inițială, apoi continuă cu descoperirea standard a referințelor pkt-line și negocierea fișierelor pack.

## Pachete bundle

Pachetele bundle Git sunt fișiere pack offline care conțin informații despre referințe. Acestea permit transferul datelor depozitului fără conexiune la rețea.

```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 citește antetele pachetelor bundle v2 și v3. Nu există nicio metodă `Repository` pentru a importa un pachet bundle: scrieți `packData()` în `.git/objects/pack/`, creați-i indexul cu `PackIndexer::writeIndex()` și actualizați singuri referințele.

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

Pachetele bundle sunt utile pentru:
- Transferuri sneaker-net (unități USB)
- Copii de rezervă incrementale
- Inițializarea clonelor în medii izolate de rețea

## Clone superficiale

Pitmaster acceptă clone superficiale, în care se preia doar o parte limitată din istoricul commit-urilor.

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

Transmiteți o adâncime către `Pitmaster::clone($url, $path, $depth)` sau `$repo->fetch($remote, $depth)`. Cererea adaugă capabilitatea `shallow` și o linie `deepen`:
```
want <hash>
deepen <depth>
```

Serverul răspunde cu linii `shallow <hash>` care indică locul unde istoricul a fost trunchiat. Pitmaster calculează limita superficială pornind de la adâncime și folosește liniile `shallow` ale serverului când calculul nu găsește nimic; rezultatul este stocat în `.git/shallow`. `ShallowClone::readShallow()`, `writeShallow()` și `isShallow()` lucrează direct cu acel fișier.

## Comparație între protocoale

| Protocol | Autentificare | Criptare | Push | Utilizare tipică |
|----------|------|-----------|------|-------------|
| Smart HTTP | Date de autentificare în URL | HTTPS | Da | Transport principal |
| Dumb HTTP | Date de autentificare în URL | HTTPS | Nu | Alternativă pentru compatibilitate veche |
| SSH | Chei SSH sau agent | SSH | Da | Depozite private, CI |
| Git (TCP) | Niciuna | Niciuna | Nu | Oglinzi doar pentru citire |
| Bundle | N/A | N/A | N/A | Transfer offline |

## Selectarea transportului

`Pitmaster::clone()`, `$repo->fetch()` și `$repo->push()` selectează transportul din URL:

| Model URL | Transport |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Orice altceva (`https://...`, `http://...`) | Smart HTTP; clone și fetch folosesc ca alternativă dumb HTTP |

`git://` URL-urile și căile locale nu sunt acceptate de aceste metode: sunt trimise către clientul smart HTTP și eșuează. Folosiți direct `GitProtocolClient` pentru `git://`. Un HTTPS URL care conține atât un utilizator, cât și un port (`https://user@host:8443/repo.git`) este interpretat în prezent greșit ca SSH URL ([#17](https://github.com/inline0/pitmaster/issues/17)).
