Älykäs HTTP
Pitmaster viestii git-palvelinten kanssa HTTPS-yhteyden kautta käyttäen älykästä HTTP-protokollaa. Tämä on ensisijainen verkkosiirtotapa. Siinä käytetään PHP-järjestelmän natiiveja virtatoimintoja (fopen ja virtakonteksti) HTTP-pyyntöihin, joten allow_url_fopen on otettava käyttöön.
SmartHttpClient
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient();
// Or with custom timeout:
$http = new SmartHttpClient(timeout: 60);
Aikakatkaisun oletusarvo on vakio PITMASTER_HTTP_TIMEOUT (kokonaisluku) tai 30 sekuntia, jos sitä ei ole määritelty.
Selvitä viitteet
$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() tekee saman kohteelle git-receive-pack. Viitteiden selvityspyyntö lähetetään osoitteeseen:
GET <url>/info/refs?service=git-upload-pack
Vastaus on pkt-line-muotoon koodattu viiteluettelo, jonka ensimmäisellä rivillä ovat ominaisuudet.
Lähetyspaketti (nouto)
$response = $http->uploadPack($url, $requestBody);
Lähettää POST-pyynnön osoitteeseen <url>/git-upload-pack, jonka runko sisältää haluttujen ja olemassa olevien objektien neuvottelun. Palauttaa raakavastausrungon (pkt-line-rivit, NAK ja side-band-tiedot). UploadPackClient muodostaa pyynnön ja poimii paketin:
use Pitmaster\Protocol\UploadPackClient;
$client = new UploadPackClient($http);
$packData = $client->fetch($url, $wants, $haves); // ObjectId[] wants and haves
Vastaanottopaketti (lähetys)
$response = $http->receivePack($url, $requestBody);
Lähettää POST-pyynnön osoitteeseen <url>/git-receive-pack, jonka runko sisältää viitepäivityskomennot ja pakettitiedot.
PktLine-koodaus
git-protokolla käyttää pkt-line-kehystystä kaikessa tiedonsiirrossa. Jokaisen rivin eteen lisätään rivin kokonaispituus (mukaan lukien 4 tavun pituusetuliite), joka koodataan neljänä heksadesimaalinumerona.
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)
Pituussäännöt
- Tietorivin vähimmäispituus:
0005(hyötykuorma 1 tavu) - Tietorivin enimmäispituus:
fff0(65516 tavun hyötykuorma) - Tyhjennyspaketti:
0000 - Erotinpaketti:
0001 - Vastauksen loppu:
0002(protokolla v2;ProtocolV2::decode()käsittelee sen, muttaPktLine::decode()hylkää sen)
PktLine::MAX_PAYLOAD; // 65516 (65520 - 4)
Viitteiden selvitys
Luokka RefDiscovery jäsentää palvelimen viiteilmoituksen.
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
Viiteilmoituksen muoto
Ilmoituksen ensimmäinen rivi sisältää ominaisuudet:
<hash> HEAD\0<capability list>\n
<hash> refs/heads/main\n
<hash> refs/tags/v1.0\n
0000
Ominaisuudet
Luokka Capability jäsentää protokollan ominaisuudet ja hallinnoi niitä.
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']
Yleiset ominaisuudet
| Ominaisuus | Merkitys |
|---|---|
multi_ack |
Palvelin tukee usean kuittauksen neuvottelua |
thin-pack |
Palvelin lähettää ohuita paketteja (perusobjekteja voidaan jättää pois). Pitmaster pyytää niitä, mutta ei vielä osaa indeksoida ohuita paketteja (#16) |
side-band |
Palvelin käyttää side-bandia pakettitiedoille (enintään 1000 tavua) |
side-band-64k |
Palvelin käyttää 64K side-bandia pakettitiedoille |
ofs-delta |
Paketti voi käyttää OFS_DELTA-objekteja |
shallow |
Palvelin tukee vajaata kloonausta |
no-done |
Palvelin ei vaadi "done"-riviä |
symref=HEAD:refs/heads/main |
HEADin symbolinen kohde |
agent=git/2.45.0 |
Palvelimen git-versio |
Side-band-kanavien erottelu
Kun palvelin käyttää side-bandia, pakettitiedot lomitetaan edistymis- ja virheilmoitusten kanssa. Jokaisen pkt-line-hyötykuorman ensimmäinen tavu ilmaisee kanavan:
| Kanava | Merkitys |
|---|---|
| 1 | Pakettitiedot |
| 2 | Edistymisilmoitukset (stderr) |
| 3 | Vakavat virheilmoitukset |
Pitmaster-luokan UploadPackClient poistaa kanavatavut ja kokoaa pakettitiedot uudelleen.
Protokollaversiot
v1 (oletus)
Perinteinen protokolla. Viitteiden selvityksessä lähetetään kaikki viitteet kerralla. Pitmaster neuvottelee yhdellä kierroksella: se lähettää haluamansa objektit, jokaisen paikallisen viitteen kärjen muodossa have sekä done.
v2
Yksinkertaisempi ja suorituskykyisempi protokolla.
Tärkeimmät erot protokollaan v1 verrattuna:
- Viitteiden selvitys on erillinen
ls-refs-komento (viitteitä voi suodattaa) - Nouto tehdään yhdellä
fetch-komennolla, jolla on rakenteiset parametrit - Osioiden erottamiseen käytetään erotinpaketteja (
0001)
clone() ja fetch() käyttävät aina v1-protokollaa. v2 on käytettävissä, kun kutsut sitä erikseen:
$discovery = $http->discoverRefsV2($url); // ls-refs
$packData = (new UploadPackClient($http))->fetchV2($url, $wants, $haves);
HTTP-pyynnön kulku
Kloonaus/nouto
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)
Lähetys
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
Virheenkäsittely
Verkkovirheet aiheuttavat poikkeuksen ProtocolException. Jos älykäs HTTP-pyyntö kohteelle clone() tai fetch() epäonnistuu, Pitmaster yrittää uudelleen tavallisella HTTP-pyynnöllä ja heittää alkuperäisen virheen uudelleen, jos sekin epäonnistuu. Muunlaiset virheet (tuntematon etärepositorio, prosessiton käsittelijä tai indeksoimaton paketti) aiheuttavat muuntyyppisiä poikkeuksia:
use Pitmaster\Exceptions\ProtocolException;
try {
$repo->fetch();
} catch (ProtocolException $e) {
echo "Network error: {$e->getMessage()}\n";
}
Yleisiä virheitä:
- Palvelimeen ei saada yhteyttä (aikakatkaisu)
- Todennus vaaditaan tai repositoriota ei löydy (ilmoitetaan muodossa
Unexpected HTTP status 401,403tai404) - Vastauksessa on odottamaton
Content-Type - Virheellistä pkt-line-dataa
- Side-band-virhekanavan viesti