Intelligens HTTP
Az Pitmaster intelligens HTTP protokollt használva kommunikál a git-szerverekkel HTTPS felett. Ez az elsődleges hálózati átviteli mód. Az HTTP kérésekhez az PHP natív adatfolyam-függvényeit használja (fopen adatfolyam-kontextussal), ezért engedélyezni kell az allow_url_fopen beállítást.
SmartHttpClient
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient();
// Or with custom timeout:
$http = new SmartHttpClient(timeout: 60);
Az időkorlát alapértelmezés szerint az PITMASTER_HTTP_TIMEOUT konstans értékét használja (egész számként), ennek hiányában pedig 30 másodperc.
Refek felderítése
$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();
Az discoverReceivePackRefs() ugyanezt teszi az git-receive-pack esetében. A ref-felderítési kérés ide kerül:
GET <url>/info/refs?service=git-upload-pack
A válasz egy pkt-line kódolású reflista, amelynek első sora tartalmazza a képességeket.
Pack feltöltése (fetch)
$response = $http->uploadPack($url, $requestBody);
POST-kérést küld az <url>/git-upload-pack címre, benne a want/have egyeztetés törzsével. A nyers válaszüzenettörzset adja vissza (pkt-line sorok, NAK és side-band adatok). Az UploadPackClient állítja össze a kérést, és nyeri ki a packet:
use Pitmaster\Protocol\UploadPackClient;
$client = new UploadPackClient($http);
$packData = $client->fetch($url, $wants, $haves); // ObjectId[] wants and haves
Pack fogadása (push)
$response = $http->receivePack($url, $requestBody);
POST-kérést küld az <url>/git-receive-pack címre, benne a reffrissítési parancsokkal és a pack-adatokkal.
PktLine-kódolás
A git protokoll minden kommunikációhoz pkt-line keretezést használ. Minden sort a teljes hossza előz meg, beleértve a 4 bájtos hosszprefixet is, 4 hexadecimális számjeggyel kódolva.
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)
Hosszra vonatkozó szabályok
- Minimális adatsor:
0005(1 bájtos hasznos adat) - Maximális adatsor:
fff0(65516 bájtos hasznos adat) - Ürítőcsomag:
0000 - Elválasztócsomag:
0001 - Válasz vége:
0002(v2 protokoll; azProtocolV2::decode()kezeli, azPktLine::decode()viszont elutasítja)
PktLine::MAX_PAYLOAD; // 65516 (65520 - 4)
Refek felderítése
Az RefDiscovery osztály feldolgozza a szerver refhirdetését.
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
A refhirdetés formátuma
A hirdetés első sora képességeket tartalmaz:
<hash> HEAD\0<capability list>\n
<hash> refs/heads/main\n
<hash> refs/tags/v1.0\n
0000
Képességek
Az Capability osztály feldolgozza és kezeli a protokollképességeket.
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']
Gyakori képességek
| Képesség | Jelentés |
|---|---|
multi_ack |
A szerver támogatja a többes nyugtázású egyeztetést |
thin-pack |
A szerver vékony packokat küldhet (az alapobjektumok kimaradhatnak). Az Pitmaster kéri ezt, de egyelőre nem tudja indexelni a vékony packokat (#16) |
side-band |
A szerver side-band csatornát használ a pack-adatokhoz (legfeljebb 1000 bájtot) |
side-band-64k |
A szerver 64K side-band csatornát használ a pack-adatokhoz |
ofs-delta |
A pack használhat OFS_DELTA objektumokat |
shallow |
A szerver támogatja a sekély klónozást |
no-done |
A szerver nem követel meg „done” sort |
symref=HEAD:refs/heads/main |
A HEAD szimbolikus célja |
agent=git/2.45.0 |
A szerver git-verziója |
A side-band szétválasztása
Ha a szerver side-band módot használ, a pack-adatok az állapotjelentésekkel és hibaüzenetekkel együtt kerülnek továbbításra. Minden pkt-line hasznos adatának első bájtja jelzi a csatornát:
| Csatorna | Jelentés |
|---|---|
| 1 | Pack-adatok |
| 2 | Folyamatjelzések (stderr) |
| 3 | Végzetes hibaüzenetek |
Az Pitmaster UploadPackClient eltávolítja a csatornabájtokat, és újra összeállítja a pack-adatokat.
Protokollverziók
v1 (alapértelmezett)
A hagyományos protokoll. A ref-felderítés egyszerre küldi el az összes refet. Az Pitmaster egyetlen körben egyeztet: elküldi a kéréseit, minden helyi ref csúcsát have-ként, valamint a done értéket.
v2
Egyszerűbb protokoll, jobb teljesítménnyel.
Főbb eltérések az v1 verziótól:
- A ref-felderítés külön
ls-refsparancs; a refek szűrhetők - A fetch egyetlen
fetchparancs strukturált paraméterekkel - Elválasztócsomagokat (
0001) használ a szakaszok elkülönítésére
Az clone() és az fetch() mindig az v1 protokollt használja. Az v2 kifejezett meghívással érhető el:
$discovery = $http->discoverRefsV2($url); // ls-refs
$packData = (new UploadPackClient($http))->fetchV2($url, $wants, $haves);
HTTP kérésfolyamat
Klónozás/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
Hibakezelés
A hálózati hibák ProtocolException kivételt dobnak. Ha az clone() vagy az fetch() intelligens HTTP egyeztetése sikertelen, az Pitmaster újrapróbálkozik egyszerű HTTP módon, és ismét sikertelenség esetén újra dobja az eredeti hibát. Más hibák (ismeretlen távoli tároló, folyamat nélküli fogantyú, nem indexelhető pack) más kivételtípusokat dobnak:
use Pitmaster\Exceptions\ProtocolException;
try {
$repo->fetch();
} catch (ProtocolException $e) {
echo "Network error: {$e->getMessage()}\n";
}
Gyakori hibák:
- A szerver nem érhető el (időtúllépés)
- Hitelesítés szükséges, vagy a tároló nem található (
Unexpected HTTP status 401,403vagy404jelzi) - Váratlan
Content-Typea válaszban - Érvénytelen pkt-line-adat
- Üzenet a side-band hiba csatornáján