Smart HTTP
Pitmaster kommunikerer med git-servere over HTTPS ved hjælp af smart HTTP-protokollen. Dette er den primære netværkstransport. Den bruger PHPs native stream-funktioner (fopen med en stream-kontekst) til HTTP-anmodninger, så allow_url_fopen skal være aktiveret.
SmartHttpClient
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient();
// Or with custom timeout:
$http = new SmartHttpClient(timeout: 60);
Timeouten er som standard konstanten PITMASTER_HTTP_TIMEOUT (et heltal) eller 30 sekunder, hvis den ikke er defineret.
Find referencer
$discovery = $http->discoverRefs('https://github.com/user/repo.git');
foreach ($discovery->refs() as $name => $id) {
echo "{$id->hex} {$name}\n";
}
// HEAD symref (e.g., 'refs/heads/main')
$defaultBranch = $discovery->headSymref();
// Specific ref
$mainId = $discovery->ref('refs/heads/main');
// Server capabilities (a Capability object, or null)
$caps = $discovery->capabilities();
discoverReceivePackRefs() gør det samme for git-receive-pack. Referenceopdagelsesanmodningen sendes til:
GET <url>/info/refs?service=git-upload-pack
Svaret er en pkt-line-kodet liste over referencer med funktioner på den første linje.
Upload af pakke (fetch)
$response = $http->uploadPack($url, $requestBody);
Sender en POST til <url>/git-upload-pack med kroppen, der indeholder want/have-forhandlingen. Returnerer den rå svarbody (pkt-lines, NAK og side-band-data). UploadPackClient opbygger anmodningen og udtrækker pakken:
use Pitmaster\Protocol\UploadPackClient;
$client = new UploadPackClient($http);
$packData = $client->fetch($url, $wants, $haves); // ObjectId[] wants and haves
Modtagelse af pakke (push)
$response = $http->receivePack($url, $requestBody);
Sender en POST til <url>/git-receive-pack med kommandoerne til referenceopdatering og pakkedataene.
PktLine-kodning
git-protokollen bruger pkt-line-indramning til al kommunikation. Hver linje indledes med dens samlede længde (inklusive det 4-byte lange længdepræfiks), kodet som 4 hexadecimale cifre.
use Pitmaster\Protocol\PktLine;
// Encode a single line
$encoded = PktLine::encode("want abc123def456\n");
// "0016want abc123def456\n"
// Flush packet (end of section)
$flush = PktLine::flush();
// "0000"
// Delimiter packet (protocol v2)
$delim = PktLine::delimiter();
// "0001"
// Decode a stream
$lines = PktLine::decode($rawData);
// Each element is: string (data), null (flush), or false (delimiter)
Regler for længde
- Minimum for datalinje:
0005(1 byte data) - Maksimum for datalinje:
fff0(65516 bytes data) - Flush-pakke:
0000 - Afgrænsningspakke:
0001 - Svarafslutning:
0002(protokol v2; håndteres afProtocolV2::decode(), mensPktLine::decode()afviser den)
PktLine::MAX_PAYLOAD; // 65516 (65520 - 4)
Referenceopdagelse
Klassen RefDiscovery fortolker serverens referenceannoncering.
use Pitmaster\Protocol\RefDiscovery;
$discovery = RefDiscovery::parse($pktLines);
// All refs
$refs = $discovery->refs();
// ['refs/heads/main' => ObjectId, 'refs/tags/v1.0' => ObjectId, ...]
// Single ref
$id = $discovery->ref('refs/heads/main');
// HEAD symbolic ref (from capabilities)
$symref = $discovery->headSymref();
// 'refs/heads/main' or null
// Server capabilities
$caps = $discovery->capabilities();
// Capability object (see below), or null
Format for referenceannoncering
Den første linje i annonceringen indeholder funktioner:
<hash> HEAD\0<capability list>\n
<hash> refs/heads/main\n
<hash> refs/tags/v1.0\n
0000
Funktioner
Klassen Capability fortolker og administrerer protokolfunktioner.
use Pitmaster\Protocol\Capability;
$caps = Capability::parse('thin-pack side-band-64k ofs-delta symref=HEAD:refs/heads/main');
$caps->has('thin-pack'); // true
$caps->get('symref'); // 'HEAD:refs/heads/main'
$caps->all(); // ['thin-pack' => null, ..., 'symref' => 'HEAD:refs/heads/main']
Almindelige funktioner
| Funktion | Betydning |
|---|---|
multi_ack |
Serveren understøtter multi-ack-forhandling |
thin-pack |
Serveren sender tynde pakker (basisobjekter kan være udeladt). Pitmaster anmoder om det, men kan endnu ikke indeksere tynde pakker (#16) |
side-band |
Serveren bruger side-band til pakkedata (begrænset til 1000 bytes) |
side-band-64k |
Serveren bruger 64K side-band til pakkedata |
ofs-delta |
Pakken kan bruge OFS_DELTA-objekter |
shallow |
Serveren understøtter overfladisk kloning |
no-done |
Serveren kræver ikke en "done"-linje |
symref=HEAD:refs/heads/main |
HEADs symbolske mål |
agent=git/2.45.0 |
Serverens Git-version |
Demultipleksning af side-band
Når serveren bruger side-band, multiplexes pakkedata med status- og fejlmeddelelser. Den første byte i hver pkt-line-payload angiver kanalen:
| Kanal | Betydning |
|---|---|
| 1 | Pakkedata |
| 2 | Statusmeddelelser (stderr) |
| 3 | Kritiske fejlmeddelelser |
Pitmasters UploadPackClient fjerner kanalbytes og samler pakkedataene igen.
Protokolversioner
v1 (standard)
Den traditionelle protokol. Referenceopdagelsen sender alle referencer på én gang. Pitmaster forhandler i én runde: den sender sine wants, alle lokale reference-spidser som have samt done.
v2
En enklere protokol med bedre ydeevne.
Vigtige forskelle fra v1:
- Referenceopdagelse er en separat kommando af typen
ls-refs(kan filtrere referencer) - Fetch er én kommando af typen
fetchmed strukturerede parametre - Bruger afgrænsningspakker (
0001) til at adskille sektioner
clone() og fetch() bruger altid v1. v2 er tilgængelig, når du kalder den eksplicit:
$discovery = $http->discoverRefsV2($url); // ls-refs
$packData = (new UploadPackClient($http))->fetchV2($url, $wants, $haves);
Anmodningsforløb for HTTP
Clone/fetch
1. GET /info/refs?service=git-upload-pack
Response: pkt-line encoded ref list
2. POST /git-upload-pack
Request: want <hash>\n ... have <hash>\n ... done\n
Response: NAK\n + pack data (possibly side-band wrapped)
Push
1. GET /info/refs?service=git-receive-pack
Response: pkt-line encoded ref list
2. POST /git-receive-pack
Request: <old-hash> <new-hash> refs/heads/main\0<capabilities>\n
0000
PACK<pack data>
Response: unpack ok\n + ref status lines
Fejlhåndtering
Netværksfejl kaster ProtocolException. Hvis udvekslingen via smart HTTP under clone() eller fetch() mislykkes, forsøger Pitmaster igen via dumb HTTP og kaster den oprindelige fejl igen, hvis det også mislykkes. Andre fejl (ukendt fjernlager, handle uden proces, pakke, der ikke kan indekseres) kaster andre undtagelsestyper:
use Pitmaster\Exceptions\ProtocolException;
try {
$repo->fetch();
} catch (ProtocolException $e) {
echo "Network error: {$e->getMessage()}\n";
}
Almindelige fejl:
- Serveren kan ikke nås (timeout)
- Godkendelse påkrævet, eller arkivet blev ikke fundet (rapporteres som
Unexpected HTTP status 401,403eller404) - Uventet
Content-Typei svaret - Ugyldige pkt-line-data
- Fejlmeddelelse fra side-band-fejlkanalen