マージリクエスト差分開発ガイド
このドキュメントでは、マージリクエストの差分のバックエンドの設計と流れについて説明します。貢献者の助けになるはずです:
- コード設計の理解
- 貢献することによる改善点の特定。
実装の詳細は頻繁に変更される可能性があるため、意図的にあまり詳しく書いていません。これらの詳細については、コードを読んでください。ここで述べられているコンポーネントは、マージリクエストの差分がどのように生成され、保存され、ユーザーに返されるのかについてのアプリケーションの主要な部分です。
データモデル
4つの主要なActiveRecordモデルは、私たちが総称して_diffと_呼ぶものを表しています。これらのデータベースでバックアップされたレコードは、プロジェクトのGitリポジトリに含まれるデータを複製し、Gitalyへの過剰なアクセス要求に対するキャッシュの一部となっています。さらに、これらは論理的な場所を提供します:
- diffの断片に関するメタデータの計算と取得。
- 一般的なクラスおよびインスタンスベースのロジック。
MergeRequestDiff
MergeRequestDiff
はapp/models/merge_request_diff.rb
で定義されています。このクラスは、一連のコミットから得られる diff に関連するメタデータとコンテキストを保持します。このクラスは、diff の内容、個々のコミット、変更を含むファイルを操作するための主な手段となるメソッドを定義します。
#<MergeRequestDiff:0x00007fd1ed63b4d0
id: 28,
state: "collected",
merge_request_id: 28,
created_at: Tue, 06 Sep 2022 18:56:02.509469000 UTC +00:00,
updated_at: Tue, 06 Sep 2022 18:56:02.754201000 UTC +00:00,
base_commit_sha: "ae73cb07c9eeaf35924a10f713b364d32b2dd34f",
real_size: "9",
head_commit_sha: "bb5206fee213d983da88c47f9cf4cc6caf9c66dc",
start_commit_sha: "0b4bc9a49b562e85de7cc9e834518ea6828729b9",
commits_count: 6,
external_diff: "diff-28",
external_diff_store: 1,
stored_externally: nil,
files_count: 9,
patch_id_sha: "d504412d5b6e6739647e752aff8e468dde093f2f",
sorted: true,
diff_type: "regular",
verification_checksum: nil>
diff の内容には、通常このクラスを通してアクセスします。ユーザーに返す前に、diff やファイル、コミットの内容にロジックが適用されることがよくあります。
MergeRequestDiff#commits_count
MergeRequestDiff
が保存されると、関連するMergeRequestDiffCommit
レコードがカウントされ、commits_count
列にキャッシュされます。この数はコミットタブのカウンターとしてマージリクエストページに表示されます。
MergeRequestDiffCommit
レコードが削除された場合、カウンターは更新されません。
MergeRequestDiffCommit
MergeRequestDiffCommit
はapp/models/merge_request_diff_commit.rb
で定義されています。このクラスは対応するMergeRequestDiff
に含まれる単一のコミットに対応し、コミットに関するヘッダ情報を保持します。
#<MergeRequestDiffCommit:0x00007fd1dfc6c4c0
authored_date: Wed, 06 Aug 2022 06:35:52.000000000 UTC +00:00,
committed_date: Wed, 06 Aug 2022 06:35:52.000000000 UTC +00:00,
merge_request_diff_id: 28,
relative_order: 0,
sha: "bb5206fee213d983da88c47f9cf4cc6caf9c66dc",
message: "Feature conflcit added\n\nSigned-off-by: Sample User <sample.user@example.com>\n",
trailers: {},
commit_author_id: 19,
committer_id: 19>
すべてのMergeRequestDiffCommit
には対応するMergeRequest::DiffCommitUser
レコードがあり、ActiveRecord の用語では:belongs_to
です。これらのレコードは:commit_author
と:committer
で、別個の個体である可能性があります。
MergeRequest::DiffCommitUser
MergeRequest::DiffCommitUser
はapp/models/merge_request/diff_commit_user.rb
で定義されます。これは、指定されたコミットのname
とemail
をキャプチャしますが、User
レコードへの接続自体は含まれません。
#<MergeRequest::DiffCommitUser:0x00007fd1dff7c930
id: 19,
name: "Sample User",
email: "sample.user@example.com">
MergeRequestDiffFile
MergeRequestDiffFile
はapp/models/merge_request_diff_file.rb
で定義されています。このクラスのこのレコードは、MergeRequestDiff
に含まれる単一のファイルの差分を表します。メタ情報と、ファイルの変更との関係についての具体的な情報の両方を保持します:
- 追加されたか、名前が変更されたか。
- diffでの順序。
- 生のdiff出力そのもの。
外部diffストレージ
デフォルトでは、MergeRequestDiffFile
の diff データはmerge_request_diff_files
テーブルのdiff
カラムに保存されます。インストールによってはテーブルが大きくなりすぎることがあるため、外部ストレージに diff を保存して容量を節約するように設定されています。設定方法はマージリクエストの diff 保存を参照してください。
外部ストレージを使用するように設定されている場合:
- データベースの
diff
列は、NULL
のままです。 - 関連する
MergeRequestDiff
レコードは、MergeRequestDiff
の作成時にstored_externally
属性をtrue
に設定します。
ScheduleMigrateExternalDiffsWorker
という名前のcronジョブも毎時15分にスケジュールされます。これにより、まだデータベースに保存されているdiff
が内部ストレージにマイグレーションされます。
MergeRequestDiffDetail
MergeRequestDiffDetail
はapp/models/merge_request_diff_detail.rb
で定義されています。このクラスは Geo レプリケーションの検証情報を提供しますが、それ以外はユーザー向けの差分には使用されません。
#<MergeRequestDiffFile:0x00007fd1ef7c9048
merge_request_diff_id: 28,
relative_order: 0,
new_file: true,
renamed_file: false,
deleted_file: false,
too_large: false,
a_mode: "0",
b_mode: "100644",
new_path: "files/ruby/feature.rb",
old_path: "files/ruby/feature.rb",
diff:
"@@ -0,0 +1,4 @@\n+# This file was changed in feature branch\n+# We put different code here to make merge conflict\n+class Conflict\n+end\n",
binary: false,
external_diff_offset: nil,
external_diff_size: nil>
フロー
これらのフローチャートは、コントローラから各機能のモデルまでの流れを説明するのに役立つはずです。このページは、diffへのアクセスやdiffを操作するためのオプションのすべてを文書化することを意図したものではなく、最も一般的なものだけに焦点を当てています。
batch_diffs.json
diff を見るための最も一般的な方法は、GitLab UI のマージリクエストページの一番上にあるChangesタブです。これを選択すると、Projects::MergeRequests::DiffsController#diffs_batch
が提供する/-/merge_requests/:id/batch_diffs.json
へのページ分割リクエストによって diff が読み込まれます: