Smart HTTP
Pitmaster kommunicerar med git-servrar över HTTPS med det smarta HTTP-protokollet. Detta är den primära nätverkstransporten. Den använder PHPs inbyggda strömfunktioner (fopen med en strömkontext) för HTTP-förfrågningar, så allow_url_fopen måste vara aktiverat.
SmartHttpClient
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient();
// Or with custom timeout:
$http = new SmartHttpClient(timeout: 60);
Timeoutvärdet är som standard konstanten PITMASTER_HTTP_TIMEOUT (ett heltal), eller 30 sekunder om den inte är definierad.
Upptäck refs
$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 samma sak för git-receive-pack. Ref-upptäcktsförfrågan skickas till:
GET <url>/info/refs?service=git-upload-pack
Svaret är en pkt-line-kodad lista med refs och funktioner på den första raden.
Ladda upp pack (fetch)
$response = $http->uploadPack($url, $requestBody);
Skickar en POST till <url>/git-upload-pack med förhandlingsinnehållet want/have. Returnerar rådata från svarskroppen (pkt-lines, NAK och side-band-data). UploadPackClient bygger förfrågan och extraherar packen:
use Pitmaster\Protocol\UploadPackClient;
$client = new UploadPackClient($http);
$packData = $client->fetch($url, $wants, $haves); // ObjectId[] wants and haves
Ta emot pack (push)
$response = $http->receivePack($url, $requestBody);
Skickar en POST till <url>/git-receive-pack med ref-uppdateringskommandona och packdata.
PktLine-kodning
Protokollet git använder pkt-line-inramning för all kommunikation. Varje rad föregås av sin totala längd (inklusive det 4 byte långa längdprefixet), kodad som 4 hexadecimala siffror.
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)
Längdregler
- Minsta datarad:
0005(1 byte nyttolast) - Största datarad:
fff0(65516 byte nyttolast) - Flush-paket:
0000 - Avgränsarpaket:
0001 - Svarsslut:
0002(protokollet v2; hanteras avProtocolV2::decode(), medanPktLine::decode()avvisar det)
PktLine::MAX_PAYLOAD; // 65516 (65520 - 4)
Ref-upptäckt
Klassen RefDiscovery tolkar serverns ref-annonsering.
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
Ref-annonsformat
Den första raden i annonseringen innehåller funktioner:
<hash> HEAD\0<capability list>\n
<hash> refs/heads/main\n
<hash> refs/tags/v1.0\n
0000
Funktioner
Klassen Capability tolkar och hanterar protokollfunktioner.
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']
Vanliga funktioner
| Funktion | Betydelse |
|---|---|
multi_ack |
Servern stöder förhandling med multi-ack |
thin-pack |
Servern skickar tunna packar (basobjekt kan utelämnas). Pitmaster begär detta men kan ännu inte indexera tunna packar (#16) |
side-band |
Servern använder side-band för packdata (begränsat till 1000 byte) |
side-band-64k |
Servern använder 64K side-band för packdata |
ofs-delta |
Packen kan använda OFS_DELTA-objekt |
shallow |
Servern stöder ytlig kloning |
no-done |
Servern kräver ingen "done"-rad |
symref=HEAD:refs/heads/main |
HEAD:s symboliska mål |
agent=git/2.45.0 |
Serverns version av git |
Demultiplexering av side-band
När servern använder side-band multiplexeras packdata med förlopps- och felmeddelanden. Den första byten i varje pkt-line-nyttolast anger kanalen:
| Kanal | Betydelse |
|---|---|
| 1 | Packdata |
| 2 | Förloppsmeddelanden (stderr) |
| 3 | Allvarliga felmeddelanden |
Pitmasters UploadPackClient tar bort kanalbyten och sätter ihop packdatan igen.
Protokollversioner
v1 (standard)
Det traditionella protokollet. Ref-upptäckten skickar alla refs på en gång. Pitmaster förhandlar i en enda omgång: det skickar sina wants, varje lokal ref-topp som en have och done.
v2
Ett enklare protokoll med bättre prestanda.
Viktiga skillnader jämfört med v1:
- Ref-upptäckt är ett separat
ls-refs-kommando (kan filtrera refs) - Fetch är ett enda
fetch-kommando med strukturerade parametrar - Använder avgränsarpaket (
0001) för att separera avsnitt
clone() och fetch() använder alltid v1. v2 kan användas när du anropar det uttryckligen:
$discovery = $http->discoverRefsV2($url); // ls-refs
$packData = (new UploadPackClient($http))->fetchV2($url, $wants, $haves);
Förfrågningsflöde för 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
Felhantering
Nätverksfel orsakar ProtocolException. Om det smarta HTTP-utbytet för clone() eller fetch() misslyckas försöker Pitmaster igen via dumb HTTP och kastar det ursprungliga felet på nytt om även det misslyckas. Andra fel (en okänd fjärrserver, ett handtag utan process, en pack som inte kan indexeras) orsakar andra undantagstyper:
use Pitmaster\Exceptions\ProtocolException;
try {
$repo->fetch();
} catch (ProtocolException $e) {
echo "Network error: {$e->getMessage()}\n";
}
Vanliga fel:
- Servern kan inte nås (timeout)
- Autentisering krävs eller så hittades inte repot (rapporteras som
Unexpected HTTP status 401,403eller404) - Oväntad
Content-Typei svaret - Ogiltiga pkt-line-data
- Felmeddelande via side-band-kanalen