Saltar al contenido

Protocolos

Pitmaster admite varios protocolos de transporte de red para comunicarse con servidores git. HTTP inteligente es el transporte principal. Hay protocolos adicionales para ofrecer mayor compatibilidad.

HTTP inteligente (principal)

Es el transporte recomendado. Funciona sobre HTTPS y es el protocolo más extendido. No hay API para encabezados personalizados o credenciales; estas solo se pueden pasar en URL (https://user:token@host/repo.git), que PHP envía como autenticación básica. clone() almacena URL, incluidas las credenciales, como remote.origin.url en .git/config. Las solicitudes usan los contenedores de flujo de PHP, por lo que debe estar habilitado allow_url_fopen.

PHP
use Pitmaster\Protocol\SmartHttpClient;

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

Consulte HTTP inteligente para obtener todos los detalles.

Protocolo v1

El protocolo tradicional HTTP inteligente. Todas las referencias se envían durante el descubrimiento y la negociación usa líneas want/have/done.

PHP
use Pitmaster\Protocol\ProtocolV1;

Protocolo v2

El protocolo más reciente, con comandos estructurados (ls-refs, fetch). Es más eficiente para repositorios con muchas referencias porque el cliente puede filtrar la lista.

clone() y fetch() siempre usan el protocolo v1. El protocolo v2 está disponible explícitamente sobre HTTP inteligente a través de SmartHttpClient::discoverRefsV2() y UploadPackClient::fetchV2().

HTTP simple

Alternativa para servidores que no admiten el protocolo HTTP inteligente. El protocolo simple obtiene objetos y paquetes individualmente mediante solicitudes GET de HTTP sin formato.

PHP
use Pitmaster\Protocol\DumbHttpClient;

$client = new DumbHttpClient();

Limitaciones de HTTP simple:

  • Sin negociación (el cliente debe descargarlo todo)
  • Sin compresión delta durante la transferencia
  • Mucho más lento que HTTP inteligente
  • Algunos servidores (GitHub, GitLab) no lo admiten

El protocolo simple obtiene:

  1. GET /info/refs (texto sin formato, sin pkt-line)
  2. GET /HEAD (rama predeterminada)
  3. GET /objects/info/packs (lista de paquetes disponibles)
  4. GET /objects/pack/pack-<hash>.pack y .idx (cada paquete enumerado y su índice)
  5. GET /objects/<xx>/<rest> (objetos sueltos individuales, recorridos desde las puntas de las referencias)

El paso 5 solo se ejecuta cuando el servidor no enumera paquetes. Si enumera paquetes, no se descargan los objetos que solo existen como archivos sueltos en el servidor (#18). El cliente simple solo admite ID de objeto de 40 caracteres (SHA-1). clone() y fetch() recurren a HTTP simple cuando falla el intercambio HTTP inteligente.

SSH

El transporte SSH usa la extensión ssh2 PHP cuando está cargada. De lo contrario, inicia el cliente ssh del sistema mediante proc_open(). En ambos casos ejecuta git-upload-pack o git-receive-pack en el remoto.

PHP
use Pitmaster\Protocol\SshClient;

$client = new SshClient();

URL SSH:

Código
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git

No se requiere ninguna extensión. Las dos vías funcionan de manera diferente:

Cliente ssh del sistema (se usa cuando ssh2 no está cargado). Pitmaster ejecuta ssh -o BatchMode=yes -o ConnectTimeout=30 -p <port> <user>@<host> <command>, por lo que la autenticación y la comprobación de la clave del host siguen la configuración de SSH y su agente. Estas variables de entorno ajustan el comando:

Variable Efecto
PITMASTER_SSH_COMMAND Ejecutable que se ejecutará en lugar de ssh
PITMASTER_SSH_IDENTITY_FILE Se pasa como -i <file>
PITMASTER_SSH_KNOWN_HOSTS Se pasa como -o UserKnownHostsFile=<file>
PITMASTER_SSH_STRICT_HOST_KEY_CHECKING Se pasa como -o StrictHostKeyChecking=<value>

Esta vía inicia un proceso, así que no está disponible en identificadores abiertos con ['processes' => false].

Extensión ssh2 (siempre se prefiere cuando está cargada). Pitmaster se autentica con ~/.ssh/id_rsa y, si la clave RSA está presente pero se rechaza, con ~/.ssh/id_ed25519; en los demás casos, usa el agente SSH. Se ignoran las variables PITMASTER_SSH_* y, por esta vía, no se verifica la clave del host del servidor (#22).

El transporte SSH ejecuta git-upload-pack o git-receive-pack como comando remoto y se comunica por el canal SSH mediante el mismo protocolo pkt-line que HTTP inteligente.

Protocolo Git (TCP)

El protocolo nativo de git se comunica por el puerto TCP 9418 mediante sockets PHP. GitProtocolClient implementa el descubrimiento de referencias y upload-pack (obtención); no puede enviar cambios. clone() y fetch() no dirigen las URL git:// hacia este protocolo, así que use el cliente directamente.

PHP
use Pitmaster\Protocol\GitProtocolClient;

$client = new GitProtocolClient();

URL Git:

Código
git://github.com/user/repo.git

Características:

  • Sin autenticación (en la práctica, solo lectura)
  • Sin cifrado
  • La mayoría de los proveedores de alojamiento lo han desaprobado
  • Usa el mismo encuadre pkt-line que HTTP inteligente

El protocolo git envía el nombre del servicio y la ruta del repositorio como solicitud inicial; luego continúa con el descubrimiento de referencias pkt-line estándar y la negociación del paquete.

Paquetes de transferencia

Los paquetes de transferencia Git son archivos de paquete sin conexión que contienen información de referencias. Permiten transferir datos del repositorio sin conexión de red.

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 lee encabezados de paquetes de transferencia v2 y v3. No hay ningún método Repository para importar un paquete de transferencia: escriba packData() en .git/objects/pack/, cree su índice con PackIndexer::writeIndex() y actualice las referencias por su cuenta.

Formato de los paquetes de transferencia:

Código
# v2 git bundle\n
-<prerequisite hash>\n    (zero or more)
<hash> <refname>\n        (one or more)
\n
<pack data>               (standard pack file format)

Los paquetes de transferencia son útiles para:

  • Transferencias mediante dispositivos físicos (unidades USB)
  • Copias de seguridad incrementales
  • Preparar clones en entornos aislados de la red

Clones superficiales

Pitmaster admite clones superficiales, que solo obtienen una parte limitada del historial de confirmaciones.

PHP
use Pitmaster\Protocol\ShallowClone;

Pase una profundidad a Pitmaster::clone($url, $path, $depth) o $repo->fetch($remote, $depth). La solicitud añade la capacidad shallow y una línea deepen:

Código
want <hash>
deepen <depth>

El servidor responde con shallow <hash> líneas que indican dónde se truncó el historial. Pitmaster calcula el límite superficial a partir de la profundidad y usa las líneas shallow del servidor cuando el cálculo no encuentra ninguna; el resultado se almacena en .git/shallow. ShallowClone::readShallow(), writeShallow() y isShallow() trabajan directamente con ese archivo.

Comparación de protocolos

Protocolo Autenticación Cifrado Envío Uso habitual
Smart HTTP Credenciales en URL HTTPS Sí Transporte principal
Dumb HTTP Credenciales en URL HTTPS No Alternativa heredada
SSH Claves SSH o agente SSH Sí Repositorios privados, CI
Git (TCP) Ninguna Ninguno No Réplicas de solo lectura
Bundle N/A N/A N/A Transferencia sin conexión

Selección del transporte

Pitmaster::clone(), $repo->fetch() y $repo->push() seleccionan el transporte a partir de URL:

Patrón URL Transporte
ssh://... SSH
user@host:path SSH
Cualquier otro (https://..., http://...) Smart HTTP; clone y fetch recurren a dumb HTTP

git:// no admite URL ni rutas locales con estos métodos: se envían al cliente smart HTTP y fallan. Usa GitProtocolClient directamente para git://. Actualmente, un HTTPS URL que contiene tanto un usuario como un puerto (https://user@host:8443/repo.git) se confunde con un SSH URL (#17).