
# Protokoli

Pitmaster atbalsta vairākus tīkla transporta protokolus saziņai ar git serveriem. Primārais transports ir viedais HTTP. Plašākai saderībai pieejami arī citi protokoli.

## Viedais HTTP (primārais)

Ieteicamais transports. Darbojas ar HTTPS un ir visplašāk izmantotais protokols. Nav API pielāgotām galvenēm vai akreditācijas datiem; akreditācijas datus var nodot tikai URL (`https://user:token@host/repo.git`), ko PHP nosūta kā Basic autentifikāciju. `clone()` saglabā URL, tostarp akreditācijas datus, kā `remote.origin.url` mapē `.git/config`. Pieprasījumos izmanto PHP plūsmas aptinējus, tāpēc jābūt iespējotam `allow_url_fopen`.

```php
use Pitmaster\Protocol\SmartHttpClient;

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

Pilnu aprakstu skatiet sadaļā [Viedais HTTP](https://pitmaster.inline0.dev/lv/docs/network/smart-http).

### Protokols v1

Tradicionālais viedais HTTP protokols. Atklāšanas laikā tiek nosūtīti visi refi, bet saskaņošanā izmanto want/have/done rindas.

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

### Protokols v2

Jaunāks protokols ar strukturētām komandām (`ls-refs`, `fetch`). Efektīvāks repozitorijiem ar daudziem refiem, jo klients var filtrēt refu sarakstu.

`clone()` un `fetch()` vienmēr izmanto protokolu v1. Protokols v2 ir pieejams tieši, izmantojot viedo HTTP ar `SmartHttpClient::discoverRefsV2()` un `UploadPackClient::fetchV2()`.

## Vienkāršais HTTP

Rezerves variants serveriem, kas neatbalsta viedo HTTP protokolu. Vienkāršais protokols izgūst objektus un pack failus pa vienam, izmantojot parastus HTTP GET pieprasījumus.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Vienkāršā HTTP ierobežojumi:
- Nav saskaņošanas (klientam jālejupielādē viss)
- Pārsūtīšanas laikā nav delta saspiešanas
- Ievērojami lēnāks nekā viedais HTTP
- Daži serveri (GitHub, GitLab) to neatbalsta

Vienkāršais protokols izgūst:
1. `GET /info/refs` (vienkāršs teksts, bez pkt-line)
2. `GET /HEAD` (noklusējuma atzars)
3. `GET /objects/info/packs` (pieejamo pack failu saraksts)
4. `GET /objects/pack/pack-<hash>.pack` un `.idx` (katrs sarakstā norādītais pack fails un tā indekss)
5. `GET /objects/<xx>/<rest>` (atsevišķi brīvie objekti, sākot no refu galapunktiem)

5. darbība tiek veikta tikai tad, ja serveris nenorāda pack failus. Ja pack faili ir norādīti, objekti, kas serverī ir tikai kā brīvi faili, netiek lejupielādēti ([#18](https://github.com/inline0/pitmaster/issues/18)). Vienkāršais klients pieņem tikai objektu ID ar 40 rakstzīmēm (SHA-1). `clone()` un `fetch()` izmanto vienkāršo HTTP kā rezerves variantu, ja viedā HTTP apmaiņa neizdodas.

## SSH

SSH transports izmanto `ssh2` paplašinājumu PHP, ja tas ir ielādēts. Pretējā gadījumā tas palaiž sistēmas `ssh` klientu, izmantojot `proc_open()`. Abos gadījumos attālajā pusē tiek izpildīts `git-upload-pack` vai `git-receive-pack`.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

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

Paplašinājums nav nepieciešams. Abi ceļi darbojas atšķirīgi:

**Sistēmas `ssh` klients** (tiek izmantots, ja `ssh2` nav ielādēts). Pitmaster palaiž `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>`, tāpēc autentifikāciju un resursdatora atslēgas pārbaudi nosaka jūsu SSH konfigurācija un aģents. Šie vides mainīgie pielāgo komandu:

| Mainīgais | Ietekme |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | Izpildāmais fails, ko palaist `ssh` vietā |
| `PITMASTER_SSH_IDENTITY_FILE` | Nodots kā `-i <file>` |
| `PITMASTER_SSH_KNOWN_HOSTS` | Nodots kā `-o UserKnownHostsFile=<file>` |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | Nodots kā `-o StrictHostKeyChecking=<value>` |

Šis ceļš palaiž procesu, tāpēc tas nav pieejams rokturiem, kas atvērti ar `['processes' => false]`.

**`ssh2` paplašinājums** (vienmēr izvēlas, ja tas ir ielādēts). Pitmaster autentificējas ar `~/.ssh/id_rsa`, pēc tam izmanto `~/.ssh/id_ed25519`, ja RSA atslēga ir pieejama, bet tiek noraidīta, un citādi izmanto SSH aģentu. `PITMASTER_SSH_*` mainīgie tiek ignorēti, un šajā ceļā netiek pārbaudīta servera resursdatora atslēga ([#22](https://github.com/inline0/pitmaster/issues/22)).

SSH transports izpilda `git-upload-pack` vai `git-receive-pack` kā attālo komandu un sazinās pa SSH kanālu, izmantojot to pašu pkt-line protokolu kā viedais HTTP.

## Git protokols (TCP)

Vietējais git protokols sazinās, izmantojot TCP portu 9418 un PHP ligzdas. `GitProtocolClient` īsteno refu atklāšanu un `upload-pack` (izgūšanu); tas nevar nosūtīt izmaiņas. `clone()` un `fetch()` nenovirza `git://` URL uz to, tāpēc izmantojiet klientu tieši.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

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

Raksturojums:
- Nav autentifikācijas (praksē tikai lasāms)
- Nav šifrēšanas
- Lielākā daļa mitināšanas pakalpojumu sniedzēju to ir novecojušuši
- Izmanto tādu pašu pkt-line ietvaru kā viedais HTTP

git protokols sākotnējā pieprasījumā nosūta pakalpojuma nosaukumu un repozitorija ceļu, pēc tam turpinās ar standarta pkt-line atsauču izgūšanu un pakotnes saskaņošanu.

## Bundle faili

Git bundle faili ir bezsaistes pack faili ar refu informāciju. Tie ļauj pārsūtīt repozitorija datus bez tīkla savienojuma.

```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 nolasa v2 un v3 bundle galvenes. Bundle failu importēšanai nav `Repository` metodes: ierakstiet `packData()` mapē `.git/objects/pack/`, izveidojiet tā indeksu ar `PackIndexer::writeIndex()` un atjauniniet refus paši.

Bundle faila formāts:
```
# v2 git bundle\n
-<prerequisite hash>\n    (zero or more)
<hash> <refname>\n        (one or more)
\n
<pack data>               (standard pack file format)
```

Bundle faili noder:
- Datu pārsūtīšanai bez tīkla (USB diskdziņi)
- Pakāpeniskām dublējumkopijām
- Klonu sākotnējai sagatavošanai izolētās vidēs

## Seklie kloni

Pitmaster atbalsta seklus klonus, kuros tiek izgūta tikai ierobežota komitu vēsture.

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

Norādiet dziļumu darbībai `Pitmaster::clone($url, $path, $depth)` vai `$repo->fetch($remote, $depth)`. Pieprasījumam tiek pievienota iespēja `shallow` un rinda `deepen`:
```
want <hash>
deepen <depth>
```

Serveris atbild ar `shallow <hash>` rindām, kas norāda, kur vēsture tika saīsināta. Pitmaster aprēķina sekluma robežu, izmantojot pašu dziļumu, un izmanto servera `shallow` rindas, ja šajā aprēķinā nekas netiek atrasts; rezultāts tiek saglabāts mapē `.git/shallow`. `ShallowClone::readShallow()`, `writeShallow()` un `isShallow()` darbojas tieši ar šo failu.

## Protokolu salīdzinājums

| Protokols | Autentifikācija | Šifrēšana | Nosūtīšana | Tipisks lietojums |
|----------|------|-----------|------|-------------|
| Viedais HTTP | Akreditācijas dati URL | HTTPS | Jā | Primārais transports |
| Vienkāršais HTTP | Akreditācijas dati URL | HTTPS | Nē | Mantots rezerves variants |
| SSH | SSH atslēgas vai aģents | SSH | Jā | Privāti repozitoriji, CI |
| Git (TCP) | Nav | Nav | Nē | Tikai lasāmi spoguļserveri |
| Bundle fails | Nav attiecināms | Nav attiecināms | Nav attiecināms | Bezsaistes pārsūtīšana |

## Transporta izvēle

`Pitmaster::clone()`, `$repo->fetch()` un `$repo->push()` izvēlas transportu pēc URL:

| URL paraugs | Transports |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Jebkas cits (`https://...`, `http://...`) | Viedais HTTP; klonēšana un izgūšana izmanto vienkāršo HTTP kā rezerves variantu |

`git://` URL un lokālie ceļi šīm metodēm netiek atbalstīti: tie tiek nosūtīti viedajam HTTP klientam, kur darbība neizdodas. Izmantojiet `GitProtocolClient` tieši, lai piekļūtu `git://`. HTTPS URL, kurā ir gan lietotājs, gan ports (`https://user@host:8443/repo.git`), pašlaik tiek kļūdaini uztverts kā SSH URL ([#17](https://github.com/inline0/pitmaster/issues/17)).
