私自身の質問に答えます。私は受け入れられる(ほとんど文書化されていませんが)答えを見つけました。私はこれを理解するためにたくさんのCコードを掘り下げなければなりませんでした。
まず第一に、上記の要件はgit-upload-packfile
、プログラムが実行するように設計されたものではないため、を使用して達成することはできません。私が疑った正解はですgit-upload-archive
。残念ながら、プロトコルはほとんど文書化されていません。それで、他の誰かが同様の要件を持っている場合に備えて、これについての私のメモがあります。
基本的に、ここで(scalaで)シミュレートしようとしているのは、次のコマンドです。
git archive --format=tar --remote=ssh://dave@ssh.mycompany.com/cornballer.git \
> master plans/documents/cornballer-blueprint.pdf | tar -x
ソフトウェアを除いて、うまくいけばJGitを使用します。残念ながら、JGitは(まだ)gitアーカイブコマンドをサポートしていません。したがって、サポートを追加する方法の非常に高レベルの概要を次に示します(JGitをフォークして、後で追加する場合があります)。
プロトコルを見てみましょう(Documentation / technology / pack-protocol.txtから):
git-proto-request = request-command SP pathname NUL [ host-parameter NUL ]
request-command = "git-upload-pack" / "git-receive-pack" /
"git-upload-archive" ; case sensitive
pathname = *( %x01-ff ) ; exclude NUL
host-parameter = "host=" hostname [ ":" port ]
したがって、プロトコルのパート1は次のようになります。
- リモートでトランスポートを確立します(sshを実行
git-upload-archive
してから、匿名gitプロトコルを実行または使用します)
- 送信
git-upload-archive /cornballer.git\0host=ssh.mycompany.com\0
(パケットラインとして)
この時点で接続が確立されます。Gコマンドがサポートされていない場合、または何らかの問題が発生した場合は、エラーが返されることがあります。これを確認する方法はまだわかりません。
次は、文書化されていない部分です。基本的に、コマンドライン引数をネットワーク経由で送信しますgit-archive
。git-archive
これらは、1つの例外を除いて、コマンドとまったく同じです。すべてのプレフィックスに。が付いていargument[SPACE]
ます。各引数は(少なくともリファレンス実装では)個別のパケットラインとして記述されます。したがって、上記の例では、次のようになります。
- 送信
argument --format=tar
(パケットラインとして)
- 送信
argument master
(パケットラインとして)
- 送信
argument plans/documents/cornballer-blueprint.pdf
(パケットラインとして)
- フラッシュパケットを送信する(
0000
)
この時点で、リモートgit-archiveプロセスにコマンド全体を与えました。次に、応答を読みます。サーバーから1つのパケット行を読み取ります。これは、次のいずれかの応答になります。
ACK
(成功を意味します-アーカイブを送信する準備ができています)
NACK [message]
-ある種のエラー、その使用のインスタンスが1つだけ見つかりました-「サブプロセスを生成できません」
ERR [message]
- エラーが発生しました
がACK
送信されると、その後にフラッシュパケット(0000
)が続き、次に生のtarデータが続きます。この時点で、側波帯#1(メインデータチャネル)に着信するパケットラインを繰り返し読み取ります。フラッシュパケットに到達すると、読み取りを停止します。ものすごく単純。
これでリモートファイルができましたが、ある種の巧妙なキャッシュを実行したい場合はどうでしょうか。私が非常に熱心に使用していた理由の1つgit-upload-packfile
は、コミットIDを記録してローカルにキャッシュし、必要な場合にのみ更新できるようにするためです。tarファイルはその情報を教えてくれませんか?間違い!
git-archiveのmanページから:
さらに、tar形式が使用されている場合、コミットIDはグローバル拡張paxヘッダーに格納されます。gitget-tar-commit-idを使用して抽出できます。ZIPファイルでは、ファイルコメントとして保存されます。
それは素晴らしいニュースです!それは文字通り私が欲しかったすべてです。ヘッダーがどのように見えるか疑問に思われる場合は、サンプルを次に示します(paxヘッダーを分析するつもりはありません)。
pax_global_header00006660000000000000000000000064121002672560014513gustar00rootroot0000000000000052 comment=326756f834865880c9832b64238e7665632e9b67
したがって、私の観点からは、上記のステップを自動的に実行するパイプラインを設定し、untarステップを(プログラムで)実行して、目的の「gitから単一ファイルをフェッチする」機能を実行する必要があります。