Przejdź do treści

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.

PHP
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.

PHP
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.

PHP
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:

  1. GET /info/refs (zwykły tekst, bez pkt-line)
  2. GET /HEAD (domyślna gałąź)
  3. GET /objects/info/packs (lista dostępnych pakietów)
  4. GET /objects/pack/pack-<hash>.pack i .idx (każdy wymieniony pakiet i jego indeks)
  5. 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.

PHP
use Pitmaster\Protocol\SshClient;

$client = new SshClient();

Adresy URL SSH:

Kod
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.

PHP
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();

Adresy URL Git:

Kod
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.

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 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:

Kod
# 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ń.

PHP
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:

Kod
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).