Към съдържанието

Протоколи

Pitmaster поддържа няколко мрежови транспортни протокола за комуникация със сървъри на git. Smart HTTP е основният транспорт. Налични са и допълнителни протоколи за по-широка съвместимост.

Smart HTTP (основен)

Препоръчителният транспорт. Работи през HTTPS и е най-широко разпространеният протокол. Няма API за персонализирани заглавки или идентификационни данни; те могат да се подават само в URL (https://user:token@host/repo.git), което PHP изпраща с Basic удостоверяване. clone() съхранява URL, включително идентификационните данни, като remote.origin.url в .git/config. Заявките използват поточните обвивки на PHP, затова allow_url_fopen трябва да е активирано.

PHP
use Pitmaster\Protocol\SmartHttpClient;

$http = new SmartHttpClient(timeout: 30);
$discovery = $http->discoverRefs('https://github.com/user/repo.git');

Вижте Smart HTTP за пълни подробности.

Протокол v1

Традиционният протокол smart HTTP. При откриването се изпращат всички препратки, а договарянето използва редове want/have/done.

PHP
use Pitmaster\Protocol\ProtocolV1;

Протокол v2

По-новият протокол със структурирани команди (ls-refs, fetch). По-ефективен е за хранилища с много препратки, защото клиентът може да филтрира списъка с препратки.

clone() и fetch() винаги използват протокол v1. Протокол v2 е наличен изрично през smart HTTP чрез SmartHttpClient::discoverRefsV2() и UploadPackClient::fetchV2().

Тъп HTTP

Резервен вариант за сървъри, които не поддържат протокола smart HTTP. Dumb протоколът извлича обекти и пакети поотделно чрез обикновени HTTP GET заявки.

PHP
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();

Ограничения на Dumb HTTP:

  • Няма договаряне (клиентът трябва да изтегли всичко)
  • Няма делта компресия по време на прехвърлянето
  • Значително по-бавен е от smart HTTP
  • Някои сървъри (GitHub, GitLab) не го поддържат

Dumb протоколът извлича:

  1. GET /info/refs (обикновен текст, без pkt-line)
  2. GET /HEAD (клонът по подразбиране)
  3. GET /objects/info/packs (списък с наличните пакети)
  4. GET /objects/pack/pack-<hash>.pack и .idx (всеки посочен пакет и неговият индекс)
  5. GET /objects/<xx>/<rest> (отделни свободни обекти, обходени от върховете на препратките)

Стъпка 5 се изпълнява само когато сървърът не посочва пакети. Когато посочи пакети, обектите, които съществуват на сървъра само като отделни свободни файлове, не се изтеглят (#18). Dumb клиентът приема само идентификатори на обекти с дължина 40 знака (SHA-1). clone() и fetch() преминават към dumb HTTP, ако обменът по smart HTTP е неуспешен.

SSH

Транспортът SSH използва разширението ssh2 PHP, когато то е заредено. В противен случай стартира системния клиент ssh чрез proc_open(). И в двата случая изпълнява git-upload-pack или git-receive-pack на отдалечената машина.

PHP
use Pitmaster\Protocol\SshClient;

$client = new SshClient();

URL адреси на SSH:

Код
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git

Не е необходимо разширение. Двата начина работят различно:

Системен клиент ssh (използва се, когато ssh2 не е заредено). Pitmaster изпълнява ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>, така че удостоверяването и проверката на ключа на хоста следват конфигурацията и агента на вашето SSH. Тези променливи на средата настройват командата:

Променлива Действие
PITMASTER_SSH_COMMAND Изпълним файл, който да се стартира вместо ssh
PITMASTER_SSH_IDENTITY_FILE Подавана като -i <file>
PITMASTER_SSH_KNOWN_HOSTS Подавана като -o UserKnownHostsFile=<file>
PITMASTER_SSH_STRICT_HOST_KEY_CHECKING Подавана като -o StrictHostKeyChecking=<value>

Този начин стартира процес и затова не е наличен за манипулатори, отворени с ['processes' => false].

Разширение ssh2 (винаги с предимство, когато е заредено). Pitmaster се удостоверява с ~/.ssh/id_rsa, след това с ~/.ssh/id_ed25519, ако RSA ключът съществува, но е отхвърлен, и в противен случай с агента SSH. Променливите PITMASTER_SSH_* се игнорират, а ключът на хоста на сървъра не се проверява при този начин (#22).

Транспортът SSH изпълнява git-upload-pack или git-receive-pack като отдалечена команда и комуникира през канала SSH, като използва същия протокол pkt-line като smart HTTP.

Протокол Git (TCP)

Родният протокол на git комуникира през TCP порт 9418, използвайки сокети PHP. GitProtocolClient реализира откриването на препратки и upload-pack (извличане); не може да изпраща промени. clone() и fetch() не насочват URL адреси git:// към него, затова използвайте клиента директно.

PHP
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();

URL адреси на Git:

Код
git://github.com/user/repo.git

Характеристики:

  • Няма удостоверяване (на практика е само за четене)
  • Няма криптиране
  • Повечето доставчици на хостинг вече не го поддържат
  • Използва същото рамкиране pkt-line като smart HTTP

Протоколът git изпраща името на услугата и пътя до хранилището като първоначална заявка, след което продължава със стандартното откриване на препратки и договаряне на пакети чрез pkt-line.

Пакети

Пакетите Git са офлайн пакетни файлове с информация за препратките. Те позволяват прехвърляне на данни за хранилище без мрежова връзка.

PHP
use Pitmaster\Protocol\Bundle;

// Read a bundle file
$bundle = Bundle::open('/path/to/repo.bundle');
$refs = $bundle->refs();
$packData = $bundle->packData();
$prerequisites = $bundle->prerequisites();

// Create one
$bundle = Bundle::create(['refs/heads/main' => $commitId], $packData);
$bundle->writeTo('/path/to/out.bundle');

Pitmaster чете заглавките на пакети v2 и v3. Няма метод Repository за импортиране на пакет: запишете packData() в .git/objects/pack/, изградете индекса му с PackIndexer::writeIndex() и актуализирайте препратките сами.

Формат на пакетите:

Код
# v2 git bundle\n
-<prerequisite hash>\n    (zero or more)
<hash> <refname>\n        (one or more)
\n
<pack data>               (standard pack file format)

Пакетите са полезни за:

  • Прехвърляне на данни чрез физически носител (USB устройства)
  • Инкрементални резервни копия
  • Подготвяне на клонинги в изолирани от мрежата среди

Плитки клонинги

Pitmaster поддържа плитки клонинги, при които се извлича само ограничен брой комити от историята.

PHP
use Pitmaster\Protocol\ShallowClone;

Подайте дълбочина на Pitmaster::clone($url, $path, $depth) или $repo->fetch($remote, $depth). Заявката добавя възможността shallow и ред deepen:

Код
want <hash>
deepen <depth>

Сървърът връща редове shallow <hash>, които указват къде е прекъсната историята. Pitmaster изчислява плитката граница въз основа на самата дълбочина и използва редовете shallow на сървъра, когато това изчисление не намира такава; резултатът се съхранява в .git/shallow. ShallowClone::readShallow(), writeShallow() и isShallow() работят директно с този файл.

Сравнение на протоколите

Протокол Удостоверяване Криптиране Изпращане Типична употреба
Smart HTTP Идентификационни данни в URL HTTPS Да Основен транспорт
Dumb HTTP Идентификационни данни в URL HTTPS Не Резервен вариант за стари системи
SSH Ключове или агент SSH SSH Да Частни хранилища, CI
Git (TCP) Няма Няма Не Огледални копия само за четене
Bundle Не се прилага Не се прилага Не се прилага Офлайн прехвърляне

Избор на транспорт

Pitmaster::clone(), $repo->fetch() и $repo->push() избират транспорта според URL:

Шаблон URL Транспорт
ssh://... SSH
user@host:path SSH
Всичко останало (https://..., http://...) Smart HTTP; clone и fetch преминават към dumb HTTP

URL адресите git:// и локалните пътища не се поддържат от тези методи: изпращат се към клиента smart HTTP и операцията се проваля. За git:// използвайте директно GitProtocolClient. HTTPS URL, който съдържа едновременно потребител и порт (https://user@host:8443/repo.git), в момента погрешно се приема за SSH URL (#17).