Liigu sisu juurde

Nutikas HTTP

Pitmaster suhtleb git-serveritega HTTPS kaudu, kasutades nutikat HTTP-protokolli. See on peamine võrguedastusviis. See kasutab PHP natiivseid voo-funktsioone (fopen voo kontekstiga) HTTP päringute jaoks, seega peab allow_url_fopen olema lubatud.

SmartHttpClient

PHP
use Pitmaster\Protocol\SmartHttpClient;

$http = new SmartHttpClient();
// Or with custom timeout:
$http = new SmartHttpClient(timeout: 60);

Vaikimisi on ajalõpp konstant PITMASTER_HTTP_TIMEOUT (täisarv) või 30 sekundit, kui see pole määratud.

Viidete tuvastamine

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();

discoverReceivePackRefs() teeb sama git-receive-pack puhul. Viidete tuvastamise päring saadetakse aadressile:

Kood
GET <url>/info/refs?service=git-upload-pack

Vastus on pkt-line-kodeeringus viidete loend, mille esimesel real on võimalused.

Paketi üleslaadimine (toomine)

PHP
$response = $http->uploadPack($url, $requestBody);

Saadab aadressile <url>/git-upload-pack POST-päringu, mille sisuks on want/have läbirääkimisandmed. Tagastab toore vastusekeha (pkt-read, NAK ja side-band-andmed). UploadPackClient koostab päringu ja eraldab paketi:

PHP
use Pitmaster\Protocol\UploadPackClient;

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

Paketi vastuvõtmine (tõukamine)

PHP
$response = $http->receivePack($url, $requestBody);

Saadab aadressile <url>/git-receive-pack POST-päringu koos viidete uuenduskäskude ja paketiandmetega.

PktLine'i kodeering

git-protokoll kasutab kogu side jaoks pkt-line-raamistust. Iga rea ees on selle kogupikkus (koos 4-baidise pikkuse eesliitega), mis on kodeeritud 4 kuueteistkümnendnumbrina.

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)

Pikkusreeglid

  • Andmerea minimaalne pikkus: 0005 (1 baidi kasulik koormus)
  • Andmerea maksimaalne pikkus: fff0 (65516 baidi kasulik koormus)
  • Tühjenduspakett: 0000
  • Eraldajapakett: 0001
  • Vastuse lõpp: 0002 (protokolli v2; seda käsitleb ProtocolV2::decode(), PktLine::decode() lükkab selle tagasi)
PHP
PktLine::MAX_PAYLOAD;  // 65516 (65520 - 4)

Viidete tuvastamine

RefDiscovery klass parsib serveri viiteteate.

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

Viiteteate vorming

Teate esimene rida sisaldab võimalusi:

Kood
<hash> HEAD\0<capability list>\n
<hash> refs/heads/main\n
<hash> refs/tags/v1.0\n
0000

Võimalused

Capability klass parsib ja haldab protokolli võimalusi.

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']

Levinud võimalused

Võimalus Tähendus
multi_ack Server toetab mitme ACK-ga läbirääkimist
thin-pack Server saadab õhukesi pakette (baasobjektid võivad puududa). Pitmaster küsib seda, kuid ei suuda veel õhukesi pakette indekseerida (#16)
side-band Server kasutab paketiandmete jaoks side-band'i (piirang 1000 baidile)
side-band-64k Server kasutab paketiandmete jaoks 64K side-band'i
ofs-delta Pakett võib kasutada OFS_DELTA-objekte
shallow Server toetab madalat kloonimist
no-done Server ei nõua rida "done"
symref=HEAD:refs/heads/main HEAD-i sümboolne sihtmärk
agent=git/2.45.0 Serveri git-versioon

Side-band-kanalite eraldamine

Kui server kasutab side-band'i, multipleksitakse paketiandmed edenemis- ja veateadetega. Iga pkt-line'i kasuliku koormuse esimene bait näitab kanalit:

Kanal Tähendus
1 Paketiandmed
2 Edenemisteated (stderr)
3 Saatuslikud veateated

Pitmaster UploadPackClient eemaldab kanali baidid ja paneb paketiandmed uuesti kokku.

Protokolli versioonid

v1 (vaikimisi)

Traditsiooniline protokoll. Viidete tuvastamisel saadetakse kõik viited korraga. Pitmaster peab läbirääkimisi ühes voorus: saadab oma soovid, iga kohaliku viite tipu kui have ning done.

v2

Lihtsam ja parema jõudlusega protokoll.

Peamised erinevused võrreldes protokolliga v1:

  • Viidete tuvastamine on eraldi käsk ls-refs (viiteid saab filtreerida)
  • Toomine on üks käsk fetch struktureeritud parameetritega
  • Sektsioonide eraldamiseks kasutatakse eraldajapakette (0001)

clone() ja fetch() kasutavad alati v1. v2 on saadaval, kui kutsute selle selgesõnaliselt:

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

HTTP päringuvoog

Kloonimine/toomine

Kood
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)

Tõukamine

Kood
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

Vigade käsitlemine

Võrguvead põhjustavad ProtocolException. Kui nutikas HTTP-vahetus clone() või fetch() korral nurjub, proovib Pitmaster uuesti rumala HTTP kaudu ja viskab ebaõnnestumise korral algse vea uuesti. Muud tõrked (tundmatu kaugserver, protsessita käepide, indekseerimatu pakett) põhjustavad teist tüüpi erindeid:

PHP
use Pitmaster\Exceptions\ProtocolException;

try {
    $repo->fetch();
} catch (ProtocolException $e) {
    echo "Network error: {$e->getMessage()}\n";
}

Levinud vead:

  • Server pole kättesaadav (ajalõpp)
  • Nõutakse autentimist või repositooriumi ei leitud (teatatuna kui Unexpected HTTP status 401, 403 või 404)
  • Ootamatu Content-Type vastuses
  • Vigased pkt-line-andmed
  • Side-band'i veakanali teade