Protokoły
Pitmaster obsługuje wiele protokołów transportowych do komunikacji sieciowej z serwerami gita. Inteligentny HTTP to podstawowy transport. Dostępne są też dodatkowe protokoły zapewniające szerszą zgodność.
Inteligentny HTTP (podstawowy)
Zalecany transport. Działa przez HTTPS i jest najpowszechniej stosowanym protokołem. Nie ma API dla własnych nagłówków ani danych uwierzytelniających; można je przekazać tylko w URL (https://user:token@host/repo.git), które PHP wysyła jako uwierzytelnianie Basic. clone() zapisuje URL, łącznie z danymi uwierzytelniającymi, jako remote.origin.url w .git/config. Żądania korzystają z opakowań strumieni PHP, dlatego allow_url_fopen musi być włączone.
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient(timeout: 30);
$discovery = $http->discoverRefs('https://github.com/user/repo.git');
Pełne informacje znajdziesz w sekcji Inteligentny HTTP.
Protokół v1
Tradycyjny inteligentny protokół HTTP. Podczas wyszukiwania przesyłane są wszystkie referencje, a negocjacja wykorzystuje linie want/have/done.
use Pitmaster\Protocol\ProtocolV1;
Protokół v2
Nowszy protokół z uporządkowanymi poleceniami (ls-refs, fetch). Jest wydajniejszy w repozytoriach z wieloma referencjami, ponieważ klient może filtrować ich listę.
clone() i fetch() zawsze korzystają z protokołu v1. Protokół v2 jest dostępny jawnie przez inteligentny HTTP za pośrednictwem SmartHttpClient::discoverRefsV2() i UploadPackClient::fetchV2().
Prosty HTTP
Zapasowy protokół dla serwerów, które nie obsługują inteligentnego protokołu HTTP. Prosty protokół pobiera pojedynczo obiekty i pakiety za pomocą zwykłych żądań HTTP GET.
use Pitmaster\Protocol\DumbHttpClient;
$client = new DumbHttpClient();
Ograniczenia prostego HTTP:
- Brak negocjacji (klient musi pobrać wszystko)
- Brak kompresji delt podczas przesyłania
- Znacznie wolniejszy niż inteligentny HTTP
- Niektóre serwery (GitHub, GitLab) go nie obsługują
Prosty protokół pobiera:
GET /info/refs(zwykły tekst, bez pkt-line)GET /HEAD(domyślna gałąź)GET /objects/info/packs(lista dostępnych pakietów)GET /objects/pack/pack-<hash>.packi.idx(każdy wymieniony pakiet i jego indeks)GET /objects/<xx>/<rest>(pojedyncze luźne obiekty, przechodząc od końcówek referencji)
Krok 5 jest wykonywany tylko wtedy, gdy serwer nie wymienia żadnych pakietów. Jeśli wymienia pakiety, obiekty istniejące na serwerze wyłącznie jako luźne pliki nie są pobierane (#18). Prosty klient akceptuje tylko identyfikatory obiektów o długości 40 znaków (SHA-1). clone() i fetch() przechodzą na prosty HTTP, jeśli inteligentna wymiana HTTP zakończy się niepowodzeniem.
SSH
Transport SSH korzysta z rozszerzenia ssh2 PHP, jeśli jest załadowane. W przeciwnym razie uruchamia systemowego klienta ssh za pośrednictwem proc_open(). W obu przypadkach na zdalnym serwerze uruchamia git-upload-pack lub git-receive-pack.
use Pitmaster\Protocol\SshClient;
$client = new SshClient();
Adresy URL SSH:
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git
Nie jest wymagane żadne rozszerzenie. Te dwie ścieżki działają inaczej:
Systemowy klient ssh (używany, gdy ssh2 nie jest załadowane). Pitmaster uruchamia ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>, więc uwierzytelnianie i sprawdzanie klucza hosta odbywają się zgodnie z konfiguracją SSH i agentem. Te zmienne środowiskowe modyfikują polecenie:
| Zmienna | Działanie |
|---|---|
PITMASTER_SSH_COMMAND |
Plik wykonywalny uruchamiany zamiast ssh |
PITMASTER_SSH_IDENTITY_FILE |
Przekazywana jako -i <file> |
PITMASTER_SSH_KNOWN_HOSTS |
Przekazywana jako -o UserKnownHostsFile=<file> |
PITMASTER_SSH_STRICT_HOST_KEY_CHECKING |
Przekazywana jako -o StrictHostKeyChecking=<value> |
Ta ścieżka uruchamia proces, więc nie jest dostępna dla uchwytów otwartych z ['processes' => false].
Rozszerzenie ssh2 (zawsze używane w pierwszej kolejności, gdy jest załadowane). Pitmaster uwierzytelnia się za pomocą ~/.ssh/id_rsa, a następnie ~/.ssh/id_ed25519, jeśli klucz RSA jest obecny, ale odrzucony, a w pozostałych przypadkach za pomocą agenta SSH. Zmienne PITMASTER_SSH_* są ignorowane, a klucz hosta serwera nie jest weryfikowany tą ścieżką (#22).
Transport SSH uruchamia git-upload-pack lub git-receive-pack jako zdalne polecenie i komunikuje się przez kanał SSH, używając tego samego protokołu pkt-line co inteligentny HTTP.
Protokół Git (TCP)
Natywny protokół gita komunikuje się przez port TCP 9418 za pomocą gniazd PHP. GitProtocolClient obsługuje wyszukiwanie referencji i upload-pack (pobieranie); nie obsługuje wysyłania. clone() i fetch() nie kierują do niego adresów URL git://, dlatego użyj klienta bezpośrednio.
use Pitmaster\Protocol\GitProtocolClient;
$client = new GitProtocolClient();
Adresy URL Git:
git://github.com/user/repo.git
Charakterystyka:
- Brak uwierzytelniania (w praktyce tylko do odczytu)
- Brak szyfrowania
- Większość dostawców hostingu wycofała obsługę
- Używa takiego samego formatowania pkt-line jak inteligentny HTTP
Protokół gita wysyła nazwę usługi i ścieżkę repozytorium jako początkowe żądanie, a następnie przechodzi do standardowego wyszukiwania referencji pkt-line i negocjacji pakietu.
Pakiety archiwalne
Pakiety archiwalne Git to pliki pakietów offline zawierające informacje o referencjach. Umożliwiają przesyłanie danych repozytorium bez połączenia sieciowego.
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 odczytuje nagłówki pakietów archiwalnych v2 i v3. Nie ma metody Repository importowania pakietu archiwalnego: zapisz packData() w .git/objects/pack/, utwórz jego indeks za pomocą PackIndexer::writeIndex() i samodzielnie zaktualizuj referencje.
Format pakietu archiwalnego:
# v2 git bundle\n
-<prerequisite hash>\n (zero or more)
<hash> <refname>\n (one or more)
\n
<pack data> (standard pack file format)
Pakiety archiwalne przydają się do:
- Przesyłania danych bez sieci (na dyskach USB)
- Przyrostowych kopii zapasowych
- Przygotowywania klonów w środowiskach odizolowanych od sieci
Płytkie klonowanie
Pitmaster obsługuje płytkie klonowanie, w którym pobierana jest tylko ograniczona część historii zatwierdzeń.
use Pitmaster\Protocol\ShallowClone;
Podaj głębokość w Pitmaster::clone($url, $path, $depth) lub $repo->fetch($remote, $depth). Żądanie dodaje możliwość shallow i linię deepen:
want <hash>
deepen <depth>
Serwer odpowiada wierszami shallow <hash> wskazującymi miejsce, w którym historia została obcięta. Pitmaster oblicza płytką granicę na podstawie samej głębokości i używa wierszy shallow serwera, gdy obliczenia niczego nie znajdą; wynik jest zapisywany w .git/shallow. ShallowClone::readShallow(), writeShallow() i isShallow() bezpośrednio korzystają z tego pliku.
Porównanie protokołów
| Protokół | Uwierzytelnianie | Szyfrowanie | Wysyłanie zmian | Typowe zastosowanie |
|---|---|---|---|---|
| Smart HTTP | Dane uwierzytelniające w URL | HTTPS | Tak | Podstawowy transport |
| Dumb HTTP | Dane uwierzytelniające w URL | HTTPS | Nie | Zgodność ze starszymi wersjami |
| SSH | Klucze SSH lub agent | SSH | Tak | Prywatne repozytoria, CI |
| Git (TCP) | Brak | Brak | Nie | Lustra tylko do odczytu |
| Bundle | Nie dotyczy | Nie dotyczy | Nie dotyczy | Transfer offline |
Wybór transportu
Pitmaster::clone(), $repo->fetch() i $repo->push() wybierają transport na podstawie URL:
| Wzorzec URL | Transport |
|---|---|
ssh://... |
SSH |
user@host:path |
SSH |
Wszystko inne (https://..., http://...) |
Smart HTTP; clone i fetch przechodzą w tryb dumb HTTP |
git:// URL-e i ścieżki lokalne nie są obsługiwane przez te metody: są przekazywane do klienta smart HTTP i kończą się błędem. W przypadku git:// użyj bezpośrednio GitProtocolClient. Obecnie HTTPS URL zawierający zarówno użytkownika, jak i port (https://user@host:8443/repo.git) jest błędnie rozpoznawany jako SSH URL (#17).