Viedais HTTP
Pitmaster sazinās ar git serveriem, izmantojot HTTPS un viedo HTTP protokolu. Tas ir galvenais tīkla transports. Tiek izmantotas PHP iebūvētās plūsmas funkcijas (fopen ar plūsmas kontekstu) HTTP pieprasījumiem, tāpēc jābūt iespējotam allow_url_fopen.
SmartHttpClient
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient();
// Or with custom timeout:
$http = new SmartHttpClient(timeout: 60);
Noildzes noklusējuma vērtība ir konstante PITMASTER_HTTP_TIMEOUT (vesels skaitlis) vai 30 sekundes, ja tā nav definēta.
Refu atklāšana
$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() dara to pašu attiecībā uz git-receive-pack. Refa atklāšanas pieprasījums tiek nosūtīts uz:
GET <url>/info/refs?service=git-upload-pack
Atbilde ir pkt-line kodēts refu saraksts, kura pirmajā rindā ir iespējas.
Upload pack (izgūšana)
$response = $http->uploadPack($url, $requestBody);
Nosūta POST pieprasījumu uz <url>/git-upload-pack ar vajadzīgo un esošo objektu saskaņošanas pamatdaļu. Atgriež neapstrādāto atbildes pamatdaļu (pkt-line, NAK un side-band datus). UploadPackClient izveido pieprasījumu un iegūst pack:
use Pitmaster\Protocol\UploadPackClient;
$client = new UploadPackClient($http);
$packData = $client->fetch($url, $wants, $haves); // ObjectId[] wants and haves
Receive pack (nosūtīšana)
$response = $http->receivePack($url, $requestBody);
Nosūta POST pieprasījumu uz <url>/git-receive-pack ar refu atjaunināšanas komandām un pack datiem.
PktLine kodējums
git protokolā visai saziņai izmanto pkt-line ietvaru. Katras rindas sākumā ir tās kopējais garums, ieskaitot 4 baitu garuma prefiksu, kas kodēts kā 4 heksadecimālcipari.
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)
Garuma noteikumi
- Minimālā datu rinda:
0005(1 baita saturs) - Maksimālā datu rinda:
fff0(65516 baitu saturs) - Iztukšošanas pakete:
0000 - Atdalītāja pakete:
0001 - Atbildes beigu pakete:
0002(protokolā v2; to apstrādāProtocolV2::decode(), betPktLine::decode()to noraida)
PktLine::MAX_PAYLOAD; // 65516 (65520 - 4)
Refa atklāšana
Klase RefDiscovery parsē servera refu paziņojumu.
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
Refa paziņojuma formāts
Paziņojuma pirmajā rindā ir iekļautas iespējas:
<hash> HEAD\0<capability list>\n
<hash> refs/heads/main\n
<hash> refs/tags/v1.0\n
0000
Iespējas
Klase Capability parsē un pārvalda protokola iespējas.
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']
Biežākās iespējas
| Iespēja | Nozīme |
|---|---|
multi_ack |
Serveris atbalsta vairāku apstiprinājumu saskaņošanu |
thin-pack |
Serveris nosūta plānus pack failus (bāzes objekti var nebūt iekļauti). Pitmaster to pieprasa, bet pagaidām nevar indeksēt plānus pack failus (#16) |
side-band |
Serveris pack datiem izmanto side-band (ierobežots līdz 1000 baitu) |
side-band-64k |
Serveris pack datiem izmanto 64K side-band |
ofs-delta |
Pack failā var būt OFS_DELTA objekti |
shallow |
Serveris atbalsta seklus klonus |
no-done |
Serverim nav nepieciešama rinda "done" |
symref=HEAD:refs/heads/main |
HEAD simboliskais mērķis |
agent=git/2.45.0 |
Servera git versija |
Side-band kanālu atdalīšana
Kad serveris izmanto side-band, pack dati tiek multipleksēti ar progresa un kļūdu ziņojumiem. Katras pkt-line lietderīgās slodzes pirmais baits norāda kanālu:
| Kanāls | Nozīme |
|---|---|
| 1 | Pack dati |
| 2 | Progresa ziņojumi (stderr) |
| 3 | Kritiski kļūdu ziņojumi |
Pitmaster UploadPackClient noņem kanālu baitus un atkal apvieno pack datus.
Protokola versijas
v1 (noklusējuma)
Tradicionālais protokols. Refa atklāšanā visi refi tiek nosūtīti uzreiz. Pitmaster veic saskaņošanu vienā kārtā: nosūta nepieciešamos refus, katra lokālā refa galapunkta komitu kā have, kā arī done.
v2
Vienkāršāks protokols ar labāku veiktspēju.
Galvenās atšķirības no v1:
- Refa atklāšana ir atsevišķa
ls-refskomanda (var filtrēt refus) - Izgūšanai izmanto vienu
fetchkomandu ar strukturētiem parametriem - Sadaļu atdalīšanai izmanto atdalītāja paketes (
0001)
clone() un fetch() vienmēr izmanto v1. v2 ir pieejams, ja to izsaucat tieši:
$discovery = $http->discoverRefsV2($url); // ls-refs
$packData = (new UploadPackClient($http))->fetchV2($url, $wants, $haves);
HTTP pieprasījuma darbplūsma
Klonēšana/Iegūšana
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)
Nosūtīšana
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
Kļūdu apstrāde
Tīkla kļūdas izmet ProtocolException. Ja viedā HTTP apmaiņa ar clone() vai fetch() neizdodas, Pitmaster atkārto mēģinājumu, izmantojot vienkāršo HTTP, un, ja arī tas neizdodas, izmet sākotnējo kļūdu. Citas kļūmes (nezināms attālais repozitorijs, rokturis bez procesa, indeksēt neiespējama pakotne) izmet cita veida izņēmumus:
use Pitmaster\Exceptions\ProtocolException;
try {
$repo->fetch();
} catch (ProtocolException $e) {
echo "Network error: {$e->getMessage()}\n";
}
Biežākās kļūdas:
- Serveris nav sasniedzams (iestājies taimauts)
- Nepieciešama autentifikācija vai repozitorijs nav atrasts (ziņots kā
Unexpected HTTP status 401,403vai404) - Negaidīts
Content-Typeatbildē - Nederīgi pkt-line dati
- Sānu joslas kļūdu kanāla ziņojums