プロトコル
Pitmasterはgitサーバーとの通信に複数のネットワークトランスポートプロトコルをサポートします。スマートHTTPが主要なトランスポートです。互換性を広げるため、ほかのプロトコルも利用できます。
スマートHTTP(主要)
推奨トランスポートです。HTTPS経由で動作し、最も広く導入されているプロトコルです。カスタムヘッダーや認証情報用のAPIはありません。認証情報はURL(https://user:token@host/repo.git)でのみ渡すことができ、PHPはそれをBasic認証として送信します。clone()は認証情報を含むURLを.git/config内のremote.origin.urlとして保存します。リクエストではPHPのストリームラッパーを使用するため、allow_url_fopenを有効にする必要があります。
use Pitmaster\Protocol\SmartHttpClient;
$http = new SmartHttpClient(timeout: 30);
$discovery = $http->discoverRefs('https://github.com/user/repo.git');
詳しくはスマートHTTPを参照してください。
プロトコルv1
従来のスマートHTTPプロトコルです。検出時にすべてのrefが送信され、ネゴシエーションではwant/have/done行を使用します。
use Pitmaster\Protocol\ProtocolV1;
プロトコルv2
構造化コマンド(ls-refs、fetch)を備えた新しいプロトコルです。クライアントがref一覧を絞り込めるため、refの多いリポジトリでより効率的です。
clone()とfetch()は常にプロトコルv1を使用します。プロトコルv2は、SmartHttpClient::discoverRefsV2()とUploadPackClient::fetchV2()経由のスマートHTTPで明示的に利用できます。
ダムHTTP
スマートHTTPプロトコルに対応していないサーバー向けのフォールバックです。ダムプロトコルでは、通常のHTTP GETリクエストを使ってオブジェクトやpackを個別に取得します。
use Pitmaster\Protocol\DumbHttpClient;
$client = new DumbHttpClient();
ダムHTTPの制限:
- ネゴシエーションなし(クライアントはすべてをダウンロードする必要があります)
- 転送中のデルタ圧縮なし
- スマートHTTPより大幅に低速
- 一部のサーバー(GitHub、GitLab)は非対応
ダムプロトコルでは次を取得します。
GET /info/refs(プレーンテキスト、pkt-lineなし)GET /HEAD(デフォルトブランチ)GET /objects/info/packs(利用可能なpackの一覧)GET /objects/pack/pack-<hash>.packと.idx(一覧にある各packとそのインデックス)GET /objects/<xx>/<rest>(refの先端からたどった個々のルースオブジェクト)
手順5は、サーバーがpackを1つも提示しない場合にのみ実行されます。packが提示される場合、サーバー上にルースファイルとしてのみ存在するオブジェクトはダウンロードされません(#18)。ダムクライアントが受け付けるオブジェクトIDは40文字(SHA-1)のみです。スマートHTTPの通信に失敗すると、clone()とfetch()はダムHTTPにフォールバックします。
SSH
SSHトランスポートでは、PHP拡張機能が読み込まれている場合はssh2を使用します。そうでない場合は、proc_open()を介してシステムのsshクライアントを起動します。どちらの場合も、リモートでgit-upload-packまたはgit-receive-packを実行します。
use Pitmaster\Protocol\SshClient;
$client = new SshClient();
SSH URL:
git@github.com:user/repo.git
ssh://git@github.com/user/repo.git
拡張機能は不要です。2つの方法では動作が異なります。
システムの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で認証し、RSAキーが存在するものの拒否された場合は~/.ssh/id_ed25519で認証します。それ以外の場合はSSHエージェントを使用します。PITMASTER_SSH_*環境変数は無視され、この方法ではサーバーのホストキーを検証しません(#22)。
SSHトランスポートはリモートコマンドとしてgit-upload-packまたはgit-receive-packを実行し、スマートHTTPと同じpkt-lineプロトコルを使ってSSHチャネル上で通信します。
Gitプロトコル(TCP)
ネイティブのgitプロトコルは、PHPソケットを使用してTCPポート9418で通信します。GitProtocolClientはrefの検出とupload-pack(フェッチ)を実装していますが、プッシュはできません。clone()とfetch()はgit:// URLをこのプロトコルに振り分けないため、クライアントを直接使用してください。
use Pitmaster\Protocol\GitProtocolClient;
$client = new GitProtocolClient();
Git URL:
git://github.com/user/repo.git
特徴:
- 認証なし(実質読み取り専用)
- 暗号化なし
- ほとんどのホスティングプロバイダーで非推奨
- スマートHTTPと同じpkt-line形式を使用
gitプロトコルでは、最初のリクエストとしてサービス名とリポジトリパスを送信し、その後、標準のpkt-line形式によるrefの検出とpackのネゴシエーションを行います。
バンドル
Gitバンドルは、ref情報を含むオフライン用のpackファイルです。ネットワーク接続なしでリポジトリデータを転送できます。
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()でインデックスを作成してから、自分でrefを更新してください。
バンドル形式:
# 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()はこのファイルを直接使用します。
プロトコルの比較
| プロトコル | 認証 | 暗号化 | プッシュ | 主な用途 |
|---|---|---|---|---|
| スマートHTTP | URL内の認証情報 | HTTPS | 可 | 主要トランスポート |
| ダムHTTP | URL内の認証情報 | HTTPS | 不可 | 従来方式のフォールバック |
| SSH | SSHキーまたはエージェント | SSH | 可 | プライベートリポジトリ、CI |
| Git(TCP) | なし | なし | 不可 | 読み取り専用ミラー |
| バンドル | 該当なし | 該当なし | 該当なし | オフライン転送 |
トランスポートの選択
Pitmaster::clone()、$repo->fetch()、$repo->push()はURLからトランスポートを選択します。
| URLパターン | トランスポート |
|---|---|
ssh://... |
SSH |
user@host:path |
SSH |
その他(https://...、http://...) |
スマートHTTP。cloneとfetchはダムHTTPにフォールバック |
git:// URLとローカルパスはこれらのメソッドではサポートされていません。スマートHTTPクライアントに渡され、失敗します。git://にはGitProtocolClientを直接使用してください。ユーザーとポートの両方を含むHTTPSURL(https://user@host:8443/repo.git)は、現在SSHURLと誤認されます(#17)。