
# Protokoller

Pitmaster understøtter flere netværkstransportprotokoller til kommunikation med git-servere. Smart HTTP er den primære transport. Yderligere protokoller er tilgængelige for bredere kompatibilitet.

## Smart HTTP (primær)

Den anbefalede transport. Fungerer over HTTPS og er den mest udbredte protokol. Der findes ingen API til brugerdefinerede headere eller legitimationsoplysninger; legitimationsoplysninger kan kun sendes i URL (`https://user:token@host/repo.git`), som PHP sender som Basic-godkendelse. `clone()` gemmer URL, inklusive legitimationsoplysninger, som `remote.origin.url` i `.git/config`. Anmodninger bruger PHPs stream-wrappere, så `allow_url_fopen` skal være aktiveret.

```php
use Pitmaster\Protocol\SmartHttpClient;

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

Se [Smart HTTP](https://pitmaster.inline0.dev/da/docs/network/smart-http) for alle detaljer.

### Protokol v1

Den traditionelle smart HTTP-protokol. Alle referencer sendes under opdagelsen, og forhandlingen bruger want/have/done-linjer.

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

### Protokol v2

Den nyere protokol med strukturerede kommandoer (`ls-refs`, `fetch`). Mere effektiv til arkiver med mange referencer, fordi klienten kan filtrere referencelisten.

`clone()` og `fetch()` bruger altid protokol v1. Protokol v2 er eksplicit tilgængelig over smart HTTP via `SmartHttpClient::discoverRefsV2()` og `UploadPackClient::fetchV2()`.

## Dumb HTTP

Fallback til servere, der ikke understøtter smart HTTP-protokollen. Dumb-protokollen henter objekter og pakker enkeltvis via almindelige HTTP GET-anmodninger.

```php
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();
```

Begrænsninger ved dumb HTTP:
- Ingen forhandling (klienten skal hente alt)
- Ingen deltakomprimering under overførsel
- Betydeligt langsommere end smart HTTP
- Nogle servere (GitHub, GitLab) understøtter det ikke

Dumb-protokollen henter:
1. `GET /info/refs` (ren tekst, ingen pkt-line)
2. `GET /HEAD` (standardgren)
3. `GET /objects/info/packs` (liste over tilgængelige pakker)
4. `GET /objects/pack/pack-<hash>.pack` og `.idx` (hver angivet pakke og dens indeks)
5. `GET /objects/<xx>/<rest>` (individuelle løse objekter, gennemgået fra referencernes spidser)

Trin 5 køres kun, når serveren ikke angiver nogen pakker. Når den angiver pakker, hentes objekter, der kun findes som løse filer på serveren, ikke ([#18](https://github.com/inline0/pitmaster/issues/18)). Dumb-klienten accepterer kun objekt-id'er på 40 tegn (SHA-1). `clone()` og `fetch()` falder tilbage til dumb HTTP, hvis udvekslingen via smart HTTP mislykkes.

## SSH

SSH-transporten bruger udvidelsen `ssh2` PHP, når den er indlæst. Ellers starter den systemets `ssh`-klient via `proc_open()`. I begge tilfælde køres `git-upload-pack` eller `git-receive-pack` på fjernlageret.

```php
use Pitmaster\Protocol\SshClient;

$client = new SshClient();
```

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

Der kræves ingen udvidelse. De to metoder fungerer forskelligt:

**Systemets `ssh`-klient** (bruges, når `ssh2` ikke er indlæst). Pitmaster kører `ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>`, så godkendelse og kontrol af værtsnøgler følger din SSH-konfiguration og agent. Disse miljøvariabler justerer kommandoen:

| Variabel | Effekt |
|----------|--------|
| `PITMASTER_SSH_COMMAND` | Program, der køres i stedet for `ssh` |
| `PITMASTER_SSH_IDENTITY_FILE` | Sendes som `-i <file>` |
| `PITMASTER_SSH_KNOWN_HOSTS` | Sendes som `-o UserKnownHostsFile=<file>` |
| `PITMASTER_SSH_STRICT_HOST_KEY_CHECKING` | Sendes som `-o StrictHostKeyChecking=<value>` |

Denne metode starter en proces, så den er ikke tilgængelig for handles åbnet med `['processes' => false]`.

**Udvidelsen `ssh2`** (altid foretrukket, når den er indlæst). Pitmaster godkender med `~/.ssh/id_rsa`, derefter `~/.ssh/id_ed25519`, hvis RSA-nøglen findes, men afvises, og ellers med SSH-agenten. `PITMASTER_SSH_*`-variablerne ignoreres, og serverens værtsnøgle verificeres ikke med denne metode ([#22](https://github.com/inline0/pitmaster/issues/22)).

SSH-transporten kører `git-upload-pack` eller `git-receive-pack` som en fjernkommando og kommunikerer over kanalen SSH med samme pkt-line-protokol som smart HTTP.

## Git-protokol (TCP)

Den native git-protokol kommunikerer over TCP-port 9418 ved hjælp af PHP-sockets. `GitProtocolClient` implementerer ref-opdagelse og `upload-pack` (hentning); den kan ikke pushe. `clone()` og `fetch()` dirigerer ikke `git://`-URL'er til den, så brug klienten direkte.

```php
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();
```

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

Egenskaber:
- Ingen godkendelse (i praksis skrivebeskyttet)
- Ingen kryptering
- Udfaset af de fleste hostingudbydere
- Bruger samme pkt-line-indramning som smart HTTP

git-protokollen sender tjenestenavnet og arkivstien som den første anmodning og fortsætter derefter med standard pkt-line-ref-opdagelse og pack-forhandling.

## Bundles

Git-bundles er offline-pakkefiler med referenceoplysninger. De gør det muligt at overføre arkivdata uden netværksforbindelse.

```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 læser bundle-headere af typen v2 og v3. Der findes ingen `Repository`-metode til at importere et bundle: skriv `packData()` til `.git/objects/pack/`, opbyg indekset med `PackIndexer::writeIndex()`, og opdatér selv referencerne.

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

Bundles er nyttige til:
- Overførsler med USB-drev
- Trinvise sikkerhedskopier
- Klargøring af kloner i netværksisolerede miljøer

## Overfladiske kloner

Pitmaster understøtter overfladiske kloner, hvor der kun hentes en begrænset dybde af commit-historikken.

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

Angiv en dybde til `Pitmaster::clone($url, $path, $depth)` eller `$repo->fetch($remote, $depth)`. Anmodningen tilføjer funktionen `shallow` og en linje med `deepen`:
```
want <hash>
deepen <depth>
```

Serveren svarer med `shallow <hash>`-linjer, der angiver, hvor historikken blev afkortet. Pitmaster beregner den overfladiske grænse ud fra selve dybden og bruger serverens `shallow`-linjer, hvis beregningen ikke finder nogen; resultatet gemmes i `.git/shallow`. `ShallowClone::readShallow()`, `writeShallow()` og `isShallow()` arbejder direkte med den fil.

## Sammenligning af protokoller

| Protokol | Godkendelse | Kryptering | Push | Typisk brug |
|----------|------|-----------|------|-------------|
| Smart HTTP | Legitimationsoplysninger i URL | HTTPS | Ja | Primær transport |
| Dumb HTTP | Legitimationsoplysninger i URL | HTTPS | Nej | Ældre fallback |
| SSH | SSH-nøgler eller agent | SSH | Ja | Private arkiver, CI |
| Git (TCP) | Ingen | Ingen | Nej | Skrivebeskyttede spejle |
| Bundle | Ikke relevant | Ikke relevant | Ikke relevant | Offlineoverførsel |

## Valg af transport

`Pitmaster::clone()`, `$repo->fetch()` og `$repo->push()` vælger transporten ud fra URL:

| Mønster for URL | Transport |
|------------|-----------|
| `ssh://...` | SSH |
| `user@host:path` | SSH |
| Alt andet (`https://...`, `http://...`) | Smart HTTP; clone og fetch falder tilbage til dumb HTTP |

`git://`-URL'er og lokale stier understøttes ikke af disse metoder: de sendes til smart HTTP-klienten og fejler. Brug `GitProtocolClient` direkte til `git://`. En HTTPS URL, der indeholder både en bruger og en port (`https://user@host:8443/repo.git`), forveksles i øjeblikket med en SSH URL ([#17](https://github.com/inline0/pitmaster/issues/17)).
