Protocoles
Pitmaster prend en charge plusieurs protocoles de transport réseau pour communiquer avec les serveurs git. HTTP intelligent est le transport principal. D’autres protocoles sont disponibles pour une meilleure compatibilité.
HTTP intelligent (principal)
Le transport recommandé. Il fonctionne sur HTTPS et constitue le protocole le plus largement déployé. Il n’existe pas de API pour les en-têtes personnalisés ou les identifiants ; ceux-ci ne peuvent être transmis que dans URL (https://user:token@host/repo.git), qu’PHP envoie en authentification Basic. clone() stocke le URL, identifiants compris, comme remote.origin.url dans .git/config. Les requêtes utilisent les wrappers de flux de PHP ; allow_url_fopen doit donc être activé.
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient(timeout: 30);
$discovery = $http->discoverRefs('https://github.com/user/repo.git');
Voir HTTP intelligent pour tous les détails.
Protocole v1
Le protocole intelligent HTTP traditionnel. Toutes les références sont envoyées lors de la découverte, et la négociation utilise les lignes want/have/done.
use Pitmaster\Protocol\ProtocolV1;
Protocole v2
Le protocole plus récent, avec des commandes structurées (ls-refs, fetch). Il est plus efficace pour les dépôts ayant de nombreuses références, car le client peut filtrer la liste.
clone() et fetch() utilisent toujours le protocole v1. Le protocole v2 est disponible explicitement via SmartHttpClient::discoverRefsV2() et UploadPackClient::fetchV2() sur HTTP intelligent.
HTTP simple
Solution de repli pour les serveurs qui ne prennent pas en charge le protocole HTTP intelligent. Le protocole simple récupère les objets et les packs individuellement au moyen de requêtes GET HTTP ordinaires.
use Pitmaster\Protocol\DumbHttpClient;
$client = new DumbHttpClient();
Limites de HTTP simple :
- Aucune négociation (le client doit tout télécharger)
- Aucune compression delta pendant le transfert
- Beaucoup plus lent que HTTP intelligent
- Certains serveurs (GitHub, GitLab) ne le prennent pas en charge
Le protocole simple récupère :
GET /info/refs(texte brut, sans pkt-line)GET /HEAD(branche par défaut)GET /objects/info/packs(liste des packs disponibles)GET /objects/pack/pack-<hash>.packet.idx(chaque pack répertorié et son index)GET /objects/<xx>/<rest>(objets libres individuels, parcourus depuis les pointes des références)
L’étape 5 n’est exécutée que si le serveur ne répertorie aucun pack. S’il en répertorie, les objets qui n’existent que sous forme de fichiers libres sur le serveur ne sont pas téléchargés (#18). Le client simple n’accepte que les ID d’objet de 40 caractères (SHA-1). clone() et fetch() basculent sur HTTP simple lorsque l’échange HTTP intelligent échoue.
SSH
Le transport SSH utilise l’extension ssh2 PHP lorsqu’elle est chargée. Sinon, il lance le client système ssh via proc_open(). Dans les deux cas, il exécute git-upload-pack ou git-receive-pack sur le serveur distant.
use Pitmaster\Protocol\SshClient;
$client = new SshClient();
URL SSH :
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git
Aucune extension n’est nécessaire. Les deux méthodes fonctionnent différemment :
Client système ssh (utilisé lorsque ssh2 n’est pas chargé). Pitmaster exécute ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command> ; l’authentification et la vérification de la clé hôte suivent donc votre configuration SSH et votre agent. Ces variables d’environnement modifient la commande :
| Variable | Effet |
|---|---|
PITMASTER_SSH_COMMAND |
Exécutable à lancer à la place de ssh |
PITMASTER_SSH_IDENTITY_FILE |
Transmis comme -i <file> |
PITMASTER_SSH_KNOWN_HOSTS |
Transmis comme -o UserKnownHostsFile=<file> |
PITMASTER_SSH_STRICT_HOST_KEY_CHECKING |
Transmis comme -o StrictHostKeyChecking=<value> |
Cette méthode lance un processus ; elle n’est donc pas disponible sur les handles ouverts avec ['processes' => false].
Extension ssh2 (toujours privilégiée lorsqu’elle est chargée). Pitmaster s’authentifie avec ~/.ssh/id_rsa, puis avec ~/.ssh/id_ed25519 si la clé RSA est présente mais refusée, et enfin avec l’agent SSH. Les variables PITMASTER_SSH_* sont ignorées, et la clé hôte du serveur n’est pas vérifiée avec cette méthode (#22).
Le transport SSH exécute git-upload-pack ou git-receive-pack comme commande distante et communique sur le canal SSH avec le même protocole pkt-line que HTTP intelligent.
Protocole Git (TCP)
Le protocole git natif communique via le port TCP 9418 au moyen de sockets PHP. GitProtocolClient implémente la découverte des références et upload-pack (récupération) ; il ne peut pas envoyer de modifications. clone() et fetch() ne dirigent pas les URL git:// vers ce protocole ; utilisez donc directement le client.
use Pitmaster\Protocol\GitProtocolClient;
$client = new GitProtocolClient();
URL Git :
git://github.com/user/repo.git
Caractéristiques :
- Aucune authentification (en pratique, lecture seule)
- Aucun chiffrement
- Abandonné par la plupart des fournisseurs d’hébergement
- Utilise le même cadrage pkt-line que HTTP intelligent
Le protocole git envoie le nom du service et le chemin du dépôt dans la requête initiale, puis passe à la découverte des références pkt-line standard et à la négociation du pack.
Bundles
Les bundles Git sont des fichiers pack hors ligne contenant les informations de référence. Ils permettent de transférer les données d’un dépôt sans connexion réseau.
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 lit les en-têtes de bundle v2 et v3. Il n’existe pas de méthode Repository pour importer un bundle : écrivez packData() dans .git/objects/pack/, créez son index avec PackIndexer::writeIndex(), puis mettez vous-même les références à jour.
Format de bundle :
# v2 git bundle\n
-<prerequisite hash>\n (zero or more)
<hash> <refname>\n (one or more)
\n
<pack data> (standard pack file format)
Les bundles sont utiles pour :
- Les transferts par support amovible (clés USB)
- Les sauvegardes incrémentielles
- Préparer des clones dans des environnements isolés du réseau
Clonages superficiels
Pitmaster prend en charge les clonages superficiels, qui ne récupèrent qu’une profondeur limitée de l’historique des commits.
use Pitmaster\Protocol\ShallowClone;
Passez une profondeur à Pitmaster::clone($url, $path, $depth) ou $repo->fetch($remote, $depth). La requête ajoute la capacité shallow et une ligne deepen :
want <hash>
deepen <depth>
Le serveur répond avec des lignes shallow <hash> qui indiquent où l’historique a été tronqué. Pitmaster calcule la limite superficielle à partir de la profondeur elle-même et utilise les lignes shallow du serveur lorsque ce calcul ne trouve rien ; le résultat est stocké dans .git/shallow. ShallowClone::readShallow(), writeShallow() et isShallow() utilisent directement ce fichier.
Comparaison des protocoles
| Protocole | Authentification | Chiffrement | Envoi | Utilisation typique |
|---|---|---|---|---|
| Smart HTTP | Identifiants dans URL | HTTPS | Oui | Transport principal |
| Dumb HTTP | Identifiants dans URL | HTTPS | Non | Solution de repli héritée |
| SSH | Clés SSH ou agent | SSH | Oui | Dépôts privés, CI |
| Git (TCP) | Aucun | Aucun | Non | Miroirs en lecture seule |
| Bundle | S.O. | S.O. | S.O. | Transfert hors ligne |
Sélection du transport
Pitmaster::clone(), $repo->fetch() et $repo->push() sélectionnent le transport à partir de URL :
| Modèle URL | Transport |
|---|---|
ssh://... |
SSH |
user@host:path |
SSH |
Tout autre (https://..., http://...) |
Smart HTTP ; clone et fetch basculent vers dumb HTTP |
Les URL git:// et les chemins locaux ne sont pas pris en charge par ces méthodes : ils sont transmis au client smart HTTP et échouent. Utilisez directement GitProtocolClient pour git://. Un HTTPS URL contenant à la fois un utilisateur et un port (https://user@host:8443/repo.git) est actuellement pris à tort pour un SSH URL (#17).