Протоколи
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 трябва да е активирано.
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.
use Pitmaster\Protocol\ProtocolV1;
Протокол v2
По-новият протокол със структурирани команди (ls-refs, fetch). По-ефективен е за хранилища с много препратки, защото клиентът може да филтрира списъка с препратки.
clone() и fetch() винаги използват протокол v1. Протокол v2 е наличен изрично през smart HTTP чрез SmartHttpClient::discoverRefsV2() и UploadPackClient::fetchV2().
Тъп HTTP
Резервен вариант за сървъри, които не поддържат протокола smart HTTP. Dumb протоколът извлича обекти и пакети поотделно чрез обикновени HTTP GET заявки.
use Pitmaster\Protocol\DumbHttpClient;
$client = new DumbHttpClient();
Ограничения на Dumb HTTP:
- Няма договаряне (клиентът трябва да изтегли всичко)
- Няма делта компресия по време на прехвърлянето
- Значително по-бавен е от smart HTTP
- Някои сървъри (GitHub, GitLab) не го поддържат
Dumb протоколът извлича:
GET /info/refs(обикновен текст, без pkt-line)GET /HEAD(клонът по подразбиране)GET /objects/info/packs(списък с наличните пакети)GET /objects/pack/pack-<hash>.packи.idx(всеки посочен пакет и неговият индекс)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 на отдалечената машина.
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:// към него, затова използвайте клиента директно.
use Pitmaster\Protocol\GitProtocolClient;
$client = new GitProtocolClient();
URL адреси на Git:
git://github.com/user/repo.git
Характеристики:
- Няма удостоверяване (на практика е само за четене)
- Няма криптиране
- Повечето доставчици на хостинг вече не го поддържат
- Използва същото рамкиране pkt-line като smart HTTP
Протоколът git изпраща името на услугата и пътя до хранилището като първоначална заявка, след което продължава със стандартното откриване на препратки и договаряне на пакети чрез pkt-line.
Пакети
Пакетите Git са офлайн пакетни файлове с информация за препратките. Те позволяват прехвърляне на данни за хранилище без мрежова връзка.
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 поддържа плитки клонинги, при които се извлича само ограничен брой комити от историята.
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).