SYNOPSIS

<over-the-wire-protocol>

DESCRIPTION

このドキュメントは、Gitの通信(wire)プロトコルのバージョン2の仕様を示しています。プロトコルv2は、以下の方法でv1を改善します:

  • 複数のサービス名の代わりに、単一のサービスで複数のコマンドがサポートされます

  • 機能(capability)がプロトコルの独自のセクションに移動され、NULバイトの後ろに隠されたり、pkt行のサイズによって制限されたりすることがないため、簡単に拡張できます。

  • NULバイトの後ろに隠されている他の情報を分離します(たとえば、機能(capability)としてのエージェント文字列とsymrefsは ls-refs を使用して要求できます)

  • 明示的に要求されない限り、 参照広告(reference advertisement)は省略されます

  • 一部の参照を明示的に要求する ls-refs コマンド

  • http と stateless-rpc を念頭に置いて設計されています。明確なフラッシュセマンティクス(flush semantics)を使用すると、httpリモートヘルパーは単にプロキシとして機能できます

プロトコルv2では、 通信はコマンド指向です。 サーバーに最初に連絡するときに、 機能(capability)のリストが広告(advertise)されます。 これらの機能の一部は、 クライアントが実行を要求(request)できるコマンドになります。 コマンドが完了すると、 クライアントは接続を再利用して、 他のコマンドの実行を要求できます。

Packet-Line Framing

すべての通信は、v1と同様に、パケットラインフレーミングを使用して行われます。 詳細については、 gitprotocol-pack(5)gitprotocol-common(5) を参照してください。

プロトコルv2での、 特別なパケットの意味は以下のとおりです:

  • 0000 フラッシュパケット (flush-pkt) - メッセージの終わりを示します

  • 0001 区切りパケット (delim-pkt) - メッセージのセクションを区切ります

  • 0002 応答終了パケット (response-end-pkt) - ステートレス接続の応答の終了を示します

Initial Client Request

In general a client can request to speak protocol v2 by sending version=2 through the respective side-channel for the transport being used which inevitably sets GIT_PROTOCOL. More information can be found in gitprotocol-pack(5) and gitprotocol-http(5), as well as the GIT_PROTOCOL definition in git(1). In all cases the response from the server is the capability advertisement.

Git Transport

git:// 転送(transport)を使用する場合、 追加のパラメーターとして "version=2" を送信することにより、 プロトコルv2の使用を要求できます:

003egit-upload-pack /project.git\0host=myserver.com\0\0version=2\0

SSH and File Transport

ssh:// 転送または file:// 転送のどちらかを使用する場合、 GIT_PROTOCOL 環境変数を明示的に設定して version=2 を含める必要があります。 この環境変数が渡されるようにサーバーを構成する必要がある場合があります。

HTTP Transport

http:// 転送または https:// 転送を使用する場合、 クライアントは gitprotocol-http(5) で説明されているように「smart」な info/refs リクエストを作成し、 Git-Protocol ヘッダー内で「version=2」を指定してv2を使用するように要求します。

C: GET $GIT_URL/info/refs?service=git-upload-pack HTTP/1.0
C: Git-Protocol: version=2

v2サーバーは以下のように応答します:

S: 200 OK
S: <Some headers>
S: ...
S:
S: 000eversion 2\n
S: <capability-advertisement>

その後の要求は、サービス $GIT_URL/git-upload-pack に対して直接行われます。(これはgit-receive-packでも同じように機能します)。

--http-backend-info-refs オプションを使用して git-upload-pack(1) を実行します。

The server may need to be configured to pass this header’s contents via the GIT_PROTOCOL variable. See the discussion in git-http-backend(1).

Capability Advertisement(機能の広告)

(クライアントからの要求に基づいて)プロトコルバージョン2を使用して通信することを決定したサーバーは、初期応答でバージョン文字列を送信し、続いてその機能(capabilities)を広告(advertisement)することによってクライアントに通知します。各機能は、オプションの値を持つキーです。クライアントは、不明なキーをすべて無視する必要があります。未知の値の意味は、各キーの定義に任されています。一部の機能では、クライアントによる実行を要求できるコマンドについて説明します。

capability-advertisement = protocol-version
                           capability-list
                           flush-pkt
protocol-version = PKT-LINE("version 2" LF)
capability-list = *capability
capability = PKT-LINE(key[=value] LF)
key = 1*(ALPHA | DIGIT | "-_")
value = 1*(ALPHA | DIGIT | " -_.,?\/{}[]()<>!@#$%^&*+=:;")

Command Request

機能広告を受信した後、クライアントは、特定の機能または引数を使用して、必要なコマンドを選択する要求を発行できます。その次に、クライアントがコマンド固有のパラメータまたはクエリを提供できるオプションのセクションがあります。 一度に要求できるコマンドは1つだけです。

request = empty-request | command-request
empty-request = flush-pkt
command-request = command
                  capability-list
                  delim-pkt
                  command-args
                  flush-pkt
command = PKT-LINE("command=" key LF)
command-args = *command-specific-arg
command-specific-argsは、個々のコマンドによって定義される
パケットラインフレームの引数です。

次に、 サーバーは、 クライアントの要求が、 広告された有効な機能だけでなく、 有効なコマンドで構成されていることを確認します。 要求が有効な場合、 サーバーはコマンドを実行します。 サーバーは、 応答を発行する前に、 クライアントの要求全体を受信するまで待機する必要があります。 応答の形式は実行中のコマンドによって決まりますが、 すべての場合で、 flush-pkt は応答の終了を示します。

コマンドが終了し、クライアントがサーバーからの応答全体を受信すると、クライアントは別のコマンドの実行を要求するか、接続を終了することができます。 クライアントは、オプションで、flush-pktのみで構成される空の要求を送信して、これ以上要求が行われないことを示すことができます。

Capabilities(機能)

機能には異なる2つのタイプがあります。情報を伝達したり要求の動作を変更したりするために使用できる通常の機能と、クライアントが実行したいコアアクション(フェッチ、プッシュなど)であるコマンドです。

プロトコルバージョン2は、デフォルトではステートレスです。 つまり、クライアントがサーバーで状態を維持する必要があることを指示する機能を要求しない限り、すべてのコマンドは1ラウンドだけ持続し、サーバー側の観点からステートレスである必要があります。クライアントは、正しく機能するためにサーバー側に状態管理を要求してはいけません(MUST NOT)。これにより、サーバー側では状態管理について心配することなく、単純なラウンドロビン負荷分散が可能になります。

agent

The server can advertise the agent capability with a value X (in the form agent=X) to notify the client that the server is running version X. The client may optionally send its own agent string by including the agent capability with a value Y (in the form agent=Y) in its request to the server (but it MUST NOT do so if the server did not advertise the agent capability). The X and Y strings may contain any printable ASCII characters except space (i.e., the byte range 33 ⇐ x ⇐ 126), and are typically of the form "package/version-os" (e.g., "git/1.8.3.1-Linux") where os is the operating system name (e.g., "Linux"). X and Y can be configured using the GIT_USER_AGENT environment variable and it takes priority. The os is retrieved using the sysname field of the uname(2) system call or its equivalent. The agent strings are purely informative for statistics and debugging purposes, and MUST NOT be used to programmatically assume the presence or absence of particular features.

ls-refs

ls-refs は、v2で参照広告を要求するために使用されるコマンドです。現在の参照広告とは異なり、ls-refsは、サーバーから送信される参照を制限するために使用できる引数を取ります。

基本コマンドでサポートされていない追加の機能は、 機能広告のコマンドの値として、 スペースで区切られた機能のリストの形式で広告されます: "<command>=<feature-1> <feature-2>"

ls-refsは以下の引数を取ります:

symrefs

それが指すオブジェクトに加えて、シンボリック参照を表示するときに、それが指す基になる参照を表示します。

peel

剥いたタグ(peeled tags)を表示します。

ref-prefix <prefix>

指定すると、 指定された接頭辞のいずれかに一致する接頭辞を持つ参照のみが表示されます。 複数のインスタンスを指定できます。 その場合、プレフィックスに一致する参照が表示されます。 注意: これは純粋に最適化のためであることに注意してください。 サーバーは、 選択した場合、 プレフィックスに一致しない参照を表示する場合があり、 クライアントは結果を自分でフィルターする必要があります。

「unborn」機能が広告される場合、以下の引数をクライアントの要求に含めることができます。

unborn

サーバーは、 unborn HEAD symref-target:<target> の形式で、unbornブランチを指すsymrefであっても、HEADに関する情報を送信します。

ls-refsの出力は以下のとおりです:

output = *ref
         flush-pkt
obj-id-or-unborn = (obj-id | "unborn")
ref = PKT-LINE(obj-id-or-unborn SP refname *(SP ref-attribute) LF)
ref-attribute = (symref | peeled)
symref = "symref-target:" symref-target
peeled = "peeled:" obj-id

fetch

fetch は、v2でパックファイルをフェッチするために使用されるコマンドです。 これは、v1 fetch の修正バージョンと見なすことができ、(ls-refs コマンドがその役割を果たしているため、)参照広告(ref-advertisement)が削除され、メッセージ形式が調整されて冗長性が排除され、将来の拡張機能を簡単に追加できるようになっています。

基本コマンドでサポートされていない追加の機能は、 機能広告のコマンドの値として、 スペースで区切られた機能のリストの形式で広告されます: "<command>=<feature-1> <feature-2>"

fetch リクエストは、以下の引数を取ることができます:

want <oid>

クライアントが取得したいオブジェクトをサーバーに提示します。欲しいものは何でもかまいません。広告されているオブジェクトに限定されません。

have <oid>

クライアントがローカルに持っているオブジェクトをサーバーに提示します。 これにより、サーバーは、クライアントが必要とするオブジェクトのみを含むパックファイルを作成できます。 複数の「have」行を指定できます。

done

ネゴシエーションを終了する必要があること(またはクローンを実行する場合は開始しないこと)、およびサーバーが要求で提供された情報を使用してパックファイルを作成する必要があることをサーバーに提示します。

thin-pack

シンパック(thin pack)の送信を要求します。これは、パック内に含まれていない(ただし、受信側に存在することがわかっている)ベースオブジェクトを参照するデルタを含むパックです。これにより、ネットワークトラフィックを大幅に削減できますが、受信側は、シンパックに不足しているベースを追加して、これらのパックを「厚く」(thicken)する方法を知っている必要があります。

no-progress

パックファイル転送中にサイドバンドチャネル2で通常送信される進行状況情報を送信しないように要求します。 ただし、サイドバンドチャネル3は引き続きエラー応答に使用されます。

include-tag

注釈付きタグ(annotated tags)が指すオブジェクトが送信されている場合は、注釈付きタグ(annotated tags)を送信するように要求します。

ofs-delta

クライアントが PACKv2を理解していることを提示します。デルタは、OIDではなくパック内の位置によってベースを参照しています。 つまり、パックファイル内の OBJ_OFS_DELTA (別名タイプ 6)を読み取ることができます。

「shallow」機能が広告される場合、以下で説明するように、以下の引数をクライアント要求に含めることができ、サーバーの応答に「shallow-info」セクションを追加する可能性があります。

shallow <oid>

クライアントは、サーバーがクライアントの履歴の制限を認識できるように、そのようなオブジェクトごとに「shallow <oid>」行を指定することにより、shallowコピーしかない(つまり、そのコミットの親がないことを意味する、)すべてのコミットをサーバーに通知する必要があります。 これは、クライアントがそのようなコミットから到達可能なすべてのオブジェクトを持っていない可能性があることをサーバーが認識できるようにするためです。

deepen <depth>

フェッチ/クローンを浅くし(shallow)、リモート側に対してコミットの深さが<depth>であることを要求します。

deepen-relative

「deepen」コマンドのセマンティクスを変更して、要求された深さが、要求されたコミットではなく、クライアントの現在のshallow境界に関連していることを示すように要求します。

deepen-since <timestamp>

shallow クローン/フェッチ を深さではなく特定の日付時刻でカットするように要求します。 内部的には、「git rev-list --max-age=<timestamp>」を実行するのと同じです。 「deepen」との併用はできません。

deepen-not <rev>

shallow クローン/フェッチを、深さではなく、 <rev> で指定された特定のリビジョンでカットするように要求します。 内部的には、「git rev-list --not <rev>」を実行するのと同じです。 「deepen」では使用できませんが、「deepen-since」では使用できます。

filter 機能が広告される場合、以下の引数をクライアントの要求に含めることができます:

filter <filter-spec>

いくつかのフィルタリング手法のいずれかを使用して、パックファイルのさまざまなオブジェクトを省略するように要求します。これらは、部分クローン(partial clone)および部分フェッチ(partial fetch)操作での使用を目的としています。 可能な「filter-spec」値については、rev-list を参照してください。他のプロセスと通信する場合、送信者はスケーリングされた整数(「1k」など)を完全に拡張された形式(「1024」など)に変換して、新発想のスケーリングサフィックスを理解できない古い受信者との相互運用性を支援する必要があります。しかしながら、受信者は次のサフィックスを受け入れる必要があります:「k」、「m」、「g」で、それぞれ、1024、1048576、1073741824 を現します。

「ref-in-want」機能が広告される場合、以下で説明するように、以下の引数をクライアントの要求に含めることができ、サーバーの応答に「wanted-refs」セクションを追加する可能性があります。

want-ref <ref>

クライアントが特定の参照を取得したいとサーバーに通知します。 ここで、 <ref> はサーバー上の参照のフルネームです。 同一参照のために Want-Ref を複数回送信するとプロトコル・エラーになります。

sideband-all 機能が広告される場合、以下の引数をクライアントの要求に含めることができます:

sideband-all

packfileセクションだけでなく、応答全体を多重化して送信するようにサーバーに指示します。(packfileセクションだけでなく、)応答内のすべての非フラッシュ(non-flush)および non-delim PKT-LINEは、そのサイドバンド(1または2または3)を示すバイトで始まります。サーバーは、キープアライブパケットとして「0005\2」(ペイロードのないサイドバンド2のPKT-LINE)を送信する場合があります。

「packfile-uris」機能が広告される場合、 以下で説明するように、 以下の引数をクライアントの要求に含めることができ、 サーバーの応答に「packfile-uris」セクションを追加する可能性があります。 注意: サーバーに送信可能な「Packfile-uris」行は 1 行だけであることに注意してください。

packfile-uris <comma-separated-list-of-protocols>

クライアントが、送信されたパックファイル内のオブジェクトの代わりに、指定されたプロトコルのいずれかのURIを受信する用意があることをサーバーに提示します。 接続チェックを実行する前に、クライアントは指定されたすべてのURIからダウンロードする必要があります。 現在、サポートされているプロトコルは「http」と「https」です。

wait-for-done 機能が広告される場合、以下の引数をクライアントの要求に含めることができます。

wait-for-done

サーバは決して "ready" を送らず、クライアントが "done" と言うまで待ってからパックファイルを送信するように指示します。

fetch の応答は、区切り文字パケット(0001)で区切られたいくつかのセクションに分割され、各セクションはセクションヘッダーで始まります。ほとんどのセクションは、パックファイルが送信されたときにのみ送信されます。

output = acknowledgements flush-pkt |
         [acknowledgments delim-pkt] [shallow-info delim-pkt]
         [wanted-refs delim-pkt] [packfile-uris delim-pkt]
         packfile flush-pkt
acknowledgments = PKT-LINE("acknowledgments" LF)
                  (nak | *ack)
                  (ready)
ready = PKT-LINE("ready" LF)
nak = PKT-LINE("NAK" LF)
ack = PKT-LINE("ACK" SP obj-id LF)
shallow-info = PKT-LINE("shallow-info" LF)
               *PKT-LINE((shallow | unshallow) LF)
shallow = "shallow" SP obj-id
unshallow = "unshallow" SP obj-id
wanted-refs = PKT-LINE("wanted-refs" LF)
              *PKT-LINE(wanted-ref LF)
wanted-ref = obj-id SP refname
packfile-uris = PKT-LINE("packfile-uris" LF) *packfile-uri
packfile-uri = PKT-LINE(40*(HEXDIGIT) SP *%x20-ff LF)
packfile = PKT-LINE("packfile" LF)
           *PKT-LINE(%x01-03 *%x00-ff)
acknowledgments section
  • クライアントが「done」行を送信してネゴシエーションが終了したと判断した場合(したがって、サーバーにパックファイルを送信する必要があります)、サーバーの応答からacknowledgmentsセクションを省略しなければなりません(MUST)。

  • 常にセクションヘッダー「acknowledgements」で始まります

  • have行として送信されたオブジェクトIDがどれも共通していない場合、サーバーは「NAK」で応答します。

  • サーバーは、共通のhave行として送信されたすべてのオブジェクトIDに対して「ACK obj-id」で応答します。

  • 応答に「ACK」行と「NAK」行の両方を含めることはできません。

  • サーバーは、サーバーが許容可能な共通ベースを検出し、packfile(同じ応答のpackfileセクションにあります)を作成して、送信する準備ができていることを示す「ready」行で応答します。

  • サーバーが適切な切断点(cut point)を見つけて「ready」行を送信することを決定した場合、サーバーは(最適化として)応答中に送信した「ACK」行を省略することを決定できます。これは、サーバーがクライアントに送信する予定のオブジェクトをすでに決定しており、それ以上のネゴシエーションが必要ないためです。

shallow-info section
  • クライアントが shallow フェッチ/クローン を要求した場合、shallowクライアントがフェッチを要求するか、サーバーがshallowの場合、サーバーの応答に shallow-info セクションが含まれる場合があります。(上記の条件のいずれかにより、サーバーがクライアントにshallow 境界(shallow boundaries)を通知する必要がある場合、または既存の浅い境界をクライアントと調整する必要がある場合は、 shallow-info セクションが含まれます。

  • 常にセクションヘッダー「shallow-info」で始まります

  • 正数の深さが要求された場合、サーバーは指定の深さよりも深くないコミットのセットを計算します。

  • サーバーは、続くパックファイルで親が送信されないコミットごとに「shallow obj-id」行を送信します。

  • サーバーは、クライアントがshallowを指示したコミットごとに「unshallow obj-id」行を送信しますが、(その親が次のパックファイルで送信されるため、)フェッチの結果としてはshallowにはなりません。

  • サーバーは、クライアントが要求の一部としてshallowを指示していないものに対して、「unshallow」行を送信しては「いけません」。

wanted-refs section
  • このセクションは、クライアントが「want-ref」行を使用して参照を要求し、packfileセクションも応答に含まれている場合にのみ含まれます。

  • 常にセクションヘッダー「wanted-refs」で始まります。

  • サーバーは、「want-ref」行を使用して要求された参照ごとに、参照リスト("<oid> <refname>")を送信します。

  • サーバーは、「want-ref」行を使用して要求されなかった参照を送信しては「いけません」。

packfile-uris section
  • このセクションは、クライアントが「packfile-uris」を送信し、サーバーに送信するそのようなURIが少なくとも1つある場合にのみ含まれます。

  • 常にセクションヘッダー「packfile-uris」で始まります。

  • サーバーが送信するURIごとに、パックの内容のハッシュ(git index-packによって出力される)と、それに続くURIを送信します。

  • ハッシュの長さは40文字です。 Gitが新しいハッシュアルゴリズムにアップグレードするとき、これを更新する必要があるかもしれません。 (「pack\t」または「keep\t」の後に出力されるインデックスパックと一致する必要があります)。

packfile section
  • このセクションは、クライアントがリクエストで「want」行を送信し、「done」を送信してこれ以上ネゴシエーションを行わないように要求した場合、または、サーバーがパックファイルを生成するのに十分なカットポイントを見つけたと判断した場合、のいずれかにのみ含まれます。

  • 常にセクションヘッダー「packfile」で始まります

  • パックファイルの送信は、セクションヘッダーの直後に開始されます

  • パックファイルのデータ転送は、プロトコルバージョン1の「side-band-64k」機能と同じセマンティクスを使用して、常に多重化されます。つまり、packfileデータストリーム中の各パケットは、先頭の4バイトの pkt-line長(通常はpkt-line形式)、1バイトのストリームコード、実際のデータで構成されます。

    ストリーム・コードは以下のいずれかです:

    1. パックデータ

    2. 進行状況メッセージ

    3. ストリームが中止(abort)される直前の致命的なエラーメッセージ

server-option

広告されている場合は、サーバー固有のオプションをいくつでもリクエストに含めることができることを示します。これは、リクエストの機能リストセクションで「server-option=<option>」機能行として各オプションを送信することによって行われます。

提供されるオプションには、NULまたはLF文字を含めることはできません。

object-format

サーバーは、値 X (object-format=X 形式)を使用して object-format 機能を広告し、サーバーがハッシュアルゴリズムXを使用してオブジェクトを処理できることをクライアントに通知できます。 指定しない場合、サーバーはSHA-1のみを処理すると見なされます。 クライアントがSHA-1以外のハッシュアルゴリズムを使用する場合は、object-formatの文字列を指定する必要があります。

session-id=<session-id>

サーバーは、複数のリクエストにわたってこのプロセスを識別するために使用できるセッションIDを広告する場合があります。 クライアントは、自身のセッションIDをサーバーに広告することもできます。

セッションIDは、特定のプロセスに固有である必要があります。それらはパケット行内に収まる必要があり、印刷不可能な文字や空白文字を含めることはできません。 現在の実装ではtrace2セッションID(詳細は api-trace2 参照)を使用していますが、これは変更される可能性があるため、セッションIDのユーザーはこの事実に依存しないでください。

object-info

object-info は、1つまたは複数のオブジェクトに関する情報を取得するためのコマンドです。 その主な目的は、クライアントがオブジェクトを完全にフェッチすることなく、この情報に基づいて決定を下せるようにすることです。 現在サポートされている情報はオブジェクトサイズのみです。

object-info リクエストは以下の引数を取ります:

size

リストされたオブジェクトIDごとに返されるサイズ情報を要求します。

oid <oid>

クライアントが情報を取得したいオブジェクトをサーバーに指示します。

object-info の応答は、要求されたオブジェクトIDと関連する要求された情報のリストであり、それぞれが1つのスペースで区切られています。

output = info flush-pkt
info = PKT-LINE(attrs) LF)
        *PKT-LINE(obj-info LF)
attrs = attr | attrs SP attrs
attr = "size"
obj-info = obj-id SP obj-size

bundle-uri

bundle-uri 機能が広告されている場合、サーバーは bundle-uri コマンドをサポートします。

現在、この機能は値なし(つまり、 bundle-uri=ほげほげ 形式ではありません)で広告されていますが、コマンド全体の拡張機能をサポートするために、将来値が追加される可能性があります。クライアントは不明な機能値を無視し、サポートする bundle-uri 対話を続行しなければなりません。

bundle-uri コマンドは、種(seed)にするためのバンドル・ファイルの URI を取得し、 後続の fetch コマンドに通知するために、 fetch の前に発行されることを目的としています。

クライアントは、他の有効なコマンドの前後に bundle-uri を発行できます。クライアントにとって役立つように、 ls-refs の後でかつ fetch の前に発行されることが期待されますが、対話内のいつでも発行できます。

DISCUSSION of bundle-uri

この機能の目的は、 git-clone(1) 処理中に非常に大きなパックを取得する一般的なケースを、 より小さな増分フェッチに変更することで、 一般的なケースでのサーバー・リソースの消費を最適化することです。

また、 サーバーは uploadpack.packObjectsHook と組み合わせてより優れたキャッシュを実現できます (git-config(1) 参照)。

新しいクローンやフェッチを、 最近生成された *.bundle ファイルの先端(tips)に対して、より予測可能で一般的なネゴシエーションを行うようにする。 サーバーは、新しいプッシュが来ると uploadpack.packObjectsHook のために、そのようなネゴシエーションの結果を事前に生成するかもしれません。

サーバーがこれらのバンドルを利用する方法の一つは、新しいクローンが既知のバンドルをダウンロードし、その後にそのバンドルにある 参照 先端(tips) を使ってリポジトリの現在の状態に追いつくことをサーバーが予測することである。

PROTOCOL for bundle-uri

bundle-uri 要求は引数無しで、上記の通り、現時点では機能値(capability value)を広告しません。いずれも将来追加される可能性はあります。

クライアントが command=bundle-uri 要求を発行すると、その応答は値 <key>=<value> を持つパケット行として提供される、キーと値のペアのリストです。 各 <key> は、バンドルのリストを作成するための bundle.* 名前空間の設定キーとして解釈される必要があります。これらのキーは bundle.<id>. サブセクションによってグループ化されており、指定された <id> に対応する各キーは、その <id> によって定義されたバンドルに属性を提供します。これらのキーの具体的な詳細と、Git クライアントがそれらの値をどのように解釈するかについては、git-config(1) を参照してください。

クライアントは上記の形式に従って行をパースしなければいけません(MUST)、形式に従わない行は破棄されるべきです(SHOULD)。そののような場合、ユーザーに警告が表示されることがあります。

bundle-uri CLIENT AND SERVER EXPECTATIONS(bundle-uriクライアントとサーバが期待する事)

URI CONTENTS

広告された URI の内容は、以下の 2 つのタイプのいずれかでなければなりません。

広告された URI には、 git bundle verify が受け入れる事ができるバンドル・ファイルが含まれている場合があります。つまり、それらには、クライアントが使用するための 1 つ以上の参照先端(reference tips)が含まれていなければなりません(MUST)。標準の - プレフィックスを使用して(いずれかの)前提条件を示さなければなりません(MUST)。また、該当する場合は object-format(オブジェクト形式)を示さなければなりません。

広告された URI には、 git config --list が受け入れられるプレーンテキスト・ファイルが含まれる場合もあります(--file オプションを使用)。このリストのキーと値のペアは、 bundle.* 名前空間内にあります (git-config(1) 参照)。

bundle-uri CLIENT ERROR RECOVERY

そのエラーが、 バンドルURIの欠落やデータの誤りによるものであれ、クライアントがバンドルヘッダとその前提関係を理解せず解析しきれないほど間抜けであるためであれ、あるいは他の何かによるものであれ、クライアントは何よりもまず、素直に機能縮退しなければなりません(MUST)。

サーバー管理者は、「bundle-uri」機能をオンにすることで、例えばCDNがダウンした場合でも、クローンやフェッチが重大な失敗することを心配する必要がなくなります。サーバーのバンドルが不完全であったり、何らかの形で不良であったりしても、クライアントは、このプロトコル拡張を使用しないことを選択した場合と同じように、機能するリポジトリを手にすることができます。

クライアントとサーバーの相互作用に関する以降のすべての議論は、これを念頭に置く必要があります。

bundle-uri SERVER TO CLIENT

返されるバンドル URI の順序は重要ではありません。クライアントは、ヘッダーを解析して、含まれる OID と前提条件を検出する必要があります。クライアントは、バンドル自体のコンテンツとそのヘッダーを最も信頼できる情報源と見なす必要があります。

サーバーは(事故または意図的な「賢い」構成によって)、クローン作成されるリポジトリと直接関係のないバンドルを返してもよく、クライアントがそのバンドルからどのようなデータを取得したいかえり分けることを期待します。

bundle-uri CLIENT TO SERVER

クライアントは、バンドル・ヘッダーで見つかった参照先端(reference tips)を、後続の「fetch」要求の「have」行として提供する必要があります。 クライアントは、何らかの理由、バンドルがダウンロードできない場合、見つけた先端(tips)が気に入らない場合など、 バンドル処理するほうがより悪いとみなされる場合、バンドルを完全に無視してもよいです。

WHEN ADVERTISED BUNDLE(S) REQUIRE NO FURTHER NEGOTIATION(宣伝されたバンドルにそれ以上ネゴが必要ない場合)

bundle-urils-refs を発行し、バンドルのヘッダーを取得後、クライアントが必要なすべての 参照 先端(tips)を広告されたバンドルから取得できることがわかった場合、クライアントはGit サーバーから切断してもよいです。このような「clone」または「fetch」の結果は、 bundle-uri を使用せずに得られた状態と区別できないものであるべきです。

EARLY CLIENT DISCONNECTIONS AND ERROR RECOVERY(クライアントの早期切断とエラーリカバリ)

クライアントは、バンドルのダウンロード中(ヘッダーの転送・パース後)、早期切断を実行してもよい。 このような場合、クライアントは、バンドルのダウンロード終了と検証に関連するエラーから適切に回復しなければなりません。

つまり、クライアントは再接続して「fetch」コマンドを発行する必要がある場合があり、場合によっては「bundle-uri」をまったく使用しないようにフォールバックする可能性があります。

この、 (「しなければならない」(SHOULD)ではなく、)「してもよい」(MAY)という振る舞いは、バンドルURIを広告するサーバーが比較的大きなリポジトリを提供している可能性が高く、かつ、正常である可能性が高いURIを指しているという仮定に基づいています。 クライアントは、例えば、ヒューリスティックとしてバンドルのペイロ ード・サイズを確認して、早期に切断する価値があるかどうか、完全な「fetch」対話にフォールバックする必要があるかどうかを確認「してもよい」です。

WHEN ADVERTISED BUNDLE(S) REQUIRE FURTHER NEGOTIATION(宣伝されているバンドルにさらなるネゴが必要な場合)

クライアントは、たとえバンドルをダウンロード途中であっても、広告されたバンドルで見つかった OID 先端(tips)を使用して、「fetch」コマンドを介してサーバーから PACK のネゴシエーションを開始する必要があります。

これにより、対話的なサーバーとの対話からの積極的な早期切断が可能になります。 クライアントは、広告された OID 先端(tips)が自分に関連していることを盲目的に信頼し、それらを「have」行として発行し、その後(通常は「ls-refs」広告から、)「want」行を介して必要な先端(tips)を要求します。次にサーバーは、バンドルからの先端(tips)と要求されたデータの間の期待される差分を使用して、(できれば小さい) PACK を計算します。

クライアントがアクティブに保っておく必要がある唯一の接続は、並列にダウンロードしている静的バンドルへの接続であり、そして、それらと増分 PACK が取得されるときに、解凍して検証する必要があります。 この時点でエラーが発生した場合は、正常に回復する必要があります(上記参照)。

bundle-uri PROTOCOL FEATURES

クライアントは、 サーバーから提供された <key>=<value> ペア達からバンドル・リストを構築します。 これらのペア達は、 git-config(1) に記載されている bundle.* 名前空間の一部です。 このセクションでは、 これらのキーのいくつかについて説明し、 この情報に応じてクライアントが実行するアクションについて説明します。

特に、 bundle.version キーは整数値を指定します。 現時点で受け入れられる唯一の値は 1 ですが、クライアントがここで予期しない値を見た場合、クライアントはバンドルリストを無視しなければなりません(MUST)。

bundle.version が了解されている限り、他のすべての未知のキーはクライアントによって無視されても構いません(MAY)。サーバーは古いクライアントとの互換性を保証しますが、より新しいクライアントは追加のキーを使用してダウンロードを最小限に抑えることができる場合があります。

pre-URI Key-Value の後方互換性のない追加は 新しい bundle.version 値、または bundle-uri 機能広告自体、 および/または 将来の新しい bundle-uri リクエスト引数によって保護されます。

現在は実装されていないが、将来実装される可能性があるキーと値のペアの例としては、以下のものが挙げられます:

  • hash=<val> または size=<bytes> を追加して、バンドル・ファイルの予想されるハッシュまたはサイズを広告します。

  • 1 つ以上のバンドル・ファイルが同一であることを広告します(たとえば、クライアントにラウンドロビンさせたり、 N 個の可能なファイルから 1 つを選択させるため)。

  • oid=<OID> ショートカットと prerequisite=<OID> ショートカット。 1 つの先端(tip)かつ前提条件(prerequisites)無しのバンドル、 または 1 つの先端と 1 つの前提条件を備えたバンドルの一般的なケースを表現します。

    これにより、「メイン」ブランチ および/または その増分更新のみを含む 1 つの「大きなバンドル」を提供したいサーバーの一般的なケースを最適化できます。

    そのような応答を受信したクライアントは、指定された URI にあるバンドルからヘッダーを取得することをスキップできると想定しても構いません(MAY)。これにより、そのバンドルのヘッダーを検査するために必要なリクエストを自分自身とサーバーが節約することができます。

promisor-remote=<pr-info>

The server may advertise some promisor remotes it is using or knows about to a client which may want to use them as its promisor remotes, instead of this repository. In this case <pr-info> should be of the form:

pr-info = pr-fields | pr-info ";" pr-fields
pr-fields = pr-field | pr-fields "," pr-field
pr-field = field-name "=" field-value

where all the field-name and field-value in a given pr-fields are field names and values related to a single promisor remote. A given field-name MUST NOT appear more than once in given pr-fields.

The server MUST advertise at least the "name" and "url" field names along with the associated field values, which are the name of a valid remote and its URL, in each pr-fields. The "name" and "url" fields MUST appear first in each pr-fields, in that order.

After these mandatory fields, the server MAY advertise the following optional fields in any order:

partialCloneFilter

The filter specification used by the remote. Clients can use this to determine if the remote’s filtering strategy is compatible with their needs (e.g., checking if both use "blob:none"). It corresponds to the "remote.<name>.partialCloneFilter" config setting.

token

An authentication token that clients can use when connecting to the remote. It corresponds to the "remote.<name>.token" config setting.

No other fields are defined by the protocol at this time. Field names are case-sensitive and MUST be transmitted exactly as specified above. Clients MUST ignore fields they don’t recognize to allow for future protocol extensions.

For now, the client can only use information transmitted through these fields to decide if it accepts the advertised promisor remote. In the future that information might be used for other purposes though.

Field values MUST be urlencoded.

If the client decides to use one or more promisor remotes the server advertised, it can reply with "promisor-remote=<pr-names>" where <pr-names> should be of the form:

pr-names = pr-name | pr-names ";" pr-name

where pr-name is the urlencoded name of a promisor remote the server advertised and the client accepts.

Note that, everywhere in this document, the ; and , characters MUST be encoded if they appear in pr-name or field-value.

If the server doesn’t know any promisor remote that could be good for a client to use, or prefers a client not to use any promisor remote it uses or knows about, it shouldn’t advertise the "promisor-remote" capability at all.

In this case, or if the client doesn’t want to use any promisor remote the server advertised, the client shouldn’t advertise the "promisor-remote" capability at all in its reply.

On the server side, the "promisor.advertise" and "promisor.sendFields" configuration options can be used to control what it advertises. On the client side, the "promisor.acceptFromServer" configuration option can be used to control what it accepts. See the documentation of these configuration options for more information.

Note that in the future it would be nice if the "promisor-remote" protocol capability could be used by the server, when responding to git fetch or git clone, to advertise better-connected remotes that the client can use as promisor remotes, instead of this repository, so that the client can lazily fetch objects from these other better-connected remotes. This would require the server to omit in its response the objects available on the better-connected remotes that the client has accepted. This hasn’t been implemented yet though. So for now this "promisor-remote" capability is useful only when the server advertises some promisor remotes it already uses to borrow objects from.

GIT

Part of the git(1) suite