Git LFS開発ガイドライン

このPagesには、GitLabチームメンバーのための開発者中心の情報が含まれています。ユーザー向けのドキュメントはGit Large File Storage をご覧ください。

コントローラーとサービス

リポジトリ::GitHttpClientController

ここで定義した認証用のメソッドは、他のすべての LFS コントローラに継承されます。

リポジトリ::LfsApiController

#batch

認証後のbatch アクションは、Git LFS クライアントがダウンロードやアップロード (pull や push、clone など) を行う際に最初にコールするアクションです。

リポジトリ::LfsStorageController

#upload_authorize

Workhorse にファイルを保存するパスを含むペイロードを提供します。リモートオブジェクトストレージの可能性もあります。

#upload_finalize

Workhorseがすでにアップロードしたファイル(このミドルウェアを参照)の情報を含むWorkhorseからのリクエストを処理し、gitlab

  • LfsObject を作成します。
  • 既存のLfsObjectLfsObjectsProject でプロジェクトに接続。

LfsObject と LfsObjectsProject

  • oid (ファイルのSHA256チェックサム)とファイルサイズが指定されたファイルに対して、LfsObject が1つだけ作成されます。
  • LfsObjectsProject LfsObject s とProjects を関連付けます。これらは、プロジェクトを通じてファイルにアクセスできるかどうかを決定します。
  • これらのオブジェクトは、プロジェクトが使用している LFS ストレージの量を計算するためにも使用されます。詳細については、ProjectStatistics#update_lfs_objects_sizeを参照してください。

リポジトリ::LfsLocksApiController

LFS のロック API を処理します。主に対応するサービスに委譲します:

  • Lfs::LockFileService
  • Lfs::UnlockFileService
  • Lfs::LocksFinderService

これらのサービスはLfsFileLock を作成および削除します。

#verify

  • このエンドポイントはペイロードで応答し、プッシュされているファイルに他のユーザーのロックがあるかどうかをクライアントがチェックできるようにします。
  • クライアントサイドのlfs.locksverify 設定は、他のユーザーに属するロックが存在する場合、クライアントがプッシュを中止するように設定することができます。
  • 他のユーザーに属するロックの存在は、サーバー側でも検証されます。

認証の例

sequenceDiagram autonumber alt Over HTTPS Git client-->>Git client: user-supplied credentials else Over SSH Git client->>gitlab-shell: git-lfs-authenticate activate gitlab-shell activate GitLab Rails gitlab-shell->>GitLab Rails: POST /api/v4/internal/lfs_authenticate GitLab Rails-->>gitlab-shell: token with expiry deactivate gitlab-shell deactivate GitLab Rails end
  1. クライアントは、いくつかの方法で認証情報を保存するように設定することができます。認証については Git LFS のドキュメント を参照ください。
  2. gitlab-shellgitlab-lfs-authenticate を実行します。gitlab-lfs-authenticate](https://github.com/git-lfs/git-lfs/blob/bea0287cdd3acbc0aa9cdf67ae09b6843d3ffcf0/docs/api/server-discovery.md#ssh)に関する[Git LFS のドキュメントを参照ください。
  3. gitlab-shellGitLab API へのリクエストを行います。
  4. その後のリクエストで使用されるトークンでShellに応答します。認証に関する Git LFS ドキュメント を参照。

クローンの例

sequenceDiagram Note right of Git client: Typical Git clone things happen first Note right of Git client: Authentication for LFS comes next activate GitLab Rails autonumber Git client->>GitLab Rails: POST project/namespace/info/lfs/objects/batch GitLab Rails-->>Git client: payload with objects deactivate GitLab Rails loop each object in payload Git client->>GitLab Rails: GET project/namespace/gitlab-lfs/objects/:oid/ (<- This URL is from the payload) GitLab Rails->>Workhorse: SendfileUpload Workhorse-->> Git client: Binary data end
  1. Git LFS は、authorization ヘッダを持つファイルをダウンロードする機能を作成者に要求します。
  2. gitlab はオブジェクトの一覧とその場所を応答します。LfsApiController#batch を参照ください。
  3. Git LFS は、前のレスポンスにあるhref の各ファイルに対してリクエストを行います。基本転送モードでのダウンロードの処理方法を参照。
  4. gitlab リモートオブジェクトストレージが有効になっている場合は、リモートの URL にリダイレクトします。SendFileUpload を参照ください。

プッシュの例

sequenceDiagram Note right of Git client: Typical Git push things happen first. Note right of Git client: Suthentication for LFS comes next. autonumber activate GitLab Rails Git client ->> GitLab Rails: POST project/namespace/info/lfs/objects/batch GitLab Rails-->>Git client: payload with objects deactivate GitLab Rails loop each object in payload Git client->>Workhorse: PUT project/namespace/gitlab-lfs/objects/:oid/:size (URL is from payload) Workhorse->>GitLab Rails: PUT project/namespace/gitlab-lfs/objects/:oid/:size/authorize GitLab Rails-->>Workhorse: response with where path to upload Workhorse->>Workhorse: Upload Workhorse->>GitLab Rails: PUT project/namespace/gitlab-lfs/objects/:oid/:size/finalize end
  1. Git LFS は、ファイルをアップロードする機能を要求します。
  2. gitlab は、オブジェクトのリストとアップロード先を指定して応答します。LfsApiController#batch を参照ください。
  3. Git LFS は、前のレスポンスでhref の各ファイルに対してリクエストを行います。基本転送モードでのアップロードの処理方法を参照ください。
  4. gitlab は、Workhorse がファイルを保存するパスを含むペイロードで応答します。リモートオブジェクトストレージの可能性があります。LfsStorageController#upload_authorize を参照してください。
  5. Workhorse はファイルの保存を行います。
  6. Workhorse はgitlab アップロードされたファイルの gitlab情報をリクエストし、LfsObject を作成します。LfsStorageController#upload_finalizeを参照してください。

ディープダイブ

2019年4月、Francisco Javier LópezがGitLabのGit LFS実装に関するDeep Dive(GitLabチームメンバー限定:https://gitlab.com/gitlab-org/create-stage/-/issues/1 )を開催し、将来コードベースのこの部分で働く可能性のある人とドメイン固有の知識を共有しました。詳しくは 録画はYouTubeで、スライドはGoogleスライドと PDFでどうぞ。このディープダイブはGitLab 11.10時点のもので、具体的な詳細は変更されているかもしれませんが、それでも良い入門書として役立つはずです。

プロジェクトアーカイブに LFS blob を含める

GitLab 13.5 で導入されました

次の図は、GitLabがプロジェクトアーカイブのLFSファイルをどのように解決するかを示しています:

sequenceDiagram autonumber Client->>+Workhorse: GET /group/project/-/archive/master.zip Workhorse->>+Rails: GET /group/project/-/archive/master.zip Rails->>+Workhorse: Gitlab-Workhorse-Send-Data git-archive Workhorse->>Gitaly: SendArchiveRequest Gitaly->>Git: git archive master Git->>Smudge: OID 12345 Smudge->>+Workhorse: GET /internal/api/v4/lfs?oid=12345&gl_repository=project-1234 Workhorse->>+Rails: GET /internal/api/v4/lfs?oid=12345&gl_repository=project-1234 Rails->>+Workhorse: Gitlab-Workhorse-Send-Data send-url Workhorse->>Smudge: <LFS data> Smudge->>Git: <LFS data> Git->>Gitaly: <streamed data> Gitaly->>Workhorse: <streamed data> Workhorse->>Client: master.zip
  1. ユーザーはUIからプロジェクトアーカイブを要求します。
  2. WorkhorseはこのリクエストをRailsに転送します。
  3. ユーザーがアーカイブのダウンロードを作成者として許可されている場合、RailsはHTTPヘッダGitlab-Workhorse-Send-Data 、base64エンコードされたJSONペイロードを先頭にgit-archive 。このペイロードにはSendArchiveRequest のバイナリメッセージが含まれ、再びbase64でエンコードされます。
  4. Workhorse はGitlab-Workhorse-Send-Data ペイロードをデコードします。アーカイブが既にアーカイブキャッシュに存在する場合、Workhorseはそのファイルを送信します。そうでない場合、WorkhorseはSendArchiveRequest を適切なGitalyサーバに送信します。
  5. Gitalyサーバーはgit archive <ref> を呼び出し、Gitアーカイブをオンザフライで生成し始めます。include_lfs_blobs フラグが有効になっている場合、Gitalyは-c filter.lfs.smudge=/path/to/gitaly-lfs-smudge Gitオプションを介してカスタムLFSスマッジフィルターを有効にします。
  6. git.gitattributes ファイルを使用して LFS ポインタの可能性を特定すると、gitgitaly-lfs-smudge を呼び出し、標準入力を介して LFS ポインタを提供します。Gitalyは、GL_PROJECT_PATHGL_INTERNAL_CONFIG を環境変数として提供し、LFSオブジェクトの検索を可能にします。
  7. 有効なLFSポインタがデコードされた場合、gitaly-lfs-smudge 、Workhorseに内部APIコールを行い、GitLabからLFSオブジェクトをダウンロードします。
  8. Workhorse はこのリクエストを Rails に転送します。LFS オブジェクトが存在し、プロジェクトに関連付けられている場合、Rails はArchivePath に LFS オブジェクトが存在するパス (ローカルディスクの場合) または署名済みの URL (オブジェクトストレージが有効な場合) を、Gitlab-Workhorse-Send-Data HTTP ヘッダーのペイロードの先頭にsend-url を付けて送信します。
  9. Workhorseはそのファイルを取得し、gitaly-lfs-smudge プロセスに送信します。 プロセスはその内容を標準出力に書き込みます。
  10. git はこの出力を読み取り、Gitalyプロセスに送り返します。
  11. GitalyはデータをRailsに送り返します。
  12. アーカイブデータはクライアントに送り返されます。

ステップ 7 では、gitaly-lfs-smudge フィルタは Rails ではなく Workhorse と話をする必要があります。そうしないと、無効な LFS blob が保存されます。これをサポートするために、GitLab 13.5ではOmnibusのデフォルト設定を変更し、GitalyがRailsではなくWorkhorseと話すようにしました。

この変更の副作用として、Gitaly (またはgitaly-lfs-smudge) による内部 API リクエスト (ステップ 8 で行ったようなもの) では、元のリクエストの相関 ID が保持されません。これらのAPIリクエストの相関IDは、このWorkhorseのイシューが解決されるまでランダムな値になります。