Ugrás a tartalomhoz

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

PHP
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

PHP
$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:

Kód
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)

PHP
$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:

PHP
use Pitmaster\Protocol\UploadPackClient;

$client = new UploadPackClient($http);
$packData = $client->fetch($url, $wants, $haves);   // ObjectId[] wants and haves

Pack fogadása (push)

PHP
$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.

PHP
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; az ProtocolV2::decode() kezeli, az PktLine::decode() viszont elutasítja)
PHP
PktLine::MAX_PAYLOAD;  // 65516 (65520 - 4)

Refek felderítése

Az RefDiscovery osztály feldolgozza a szerver refhirdetését.

PHP
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:

Kód
<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.

PHP
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-refs parancs; a refek szűrhetők
  • A fetch egyetlen fetch parancs 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:

PHP
$discovery = $http->discoverRefsV2($url);       // ls-refs
$packData = (new UploadPackClient($http))->fetchV2($url, $wants, $haves);

HTTP kérésfolyamat

Klónozás/Fetch

Kód
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

Kód
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:

PHP
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, 403 vagy 404 jelzi)
  • Váratlan Content-Type a válaszban
  • Érvénytelen pkt-line-adat
  • Üzenet a side-band hiba csatornáján