병합 요청 차이 개발 가이드

이 문서는 병합 요청 차이의 백엔드 설계 및 흐름에 대해 설명합니다.

기여자들이 다음을 이해하는 데 도움이 되어야 합니다:

  • 코드 설계를 이해합니다.
  • 기여를 통한 개선 영역을 식별합니다.

구현 세부 사항이 너무 많이 포함되지 않은 것은 의도적이며, 변경될 수 있는 부분입니다. 이러한 세부 사항은 코드가 더 잘 설명합니다. 여기 언급된 구성 요소는 병합 요청 차이가 생성, 저장 및 사용자에게 반환되는 방식에서 애플리케이션의 주요 부분입니다.

참고:
이 페이지는 살아있는 문서입니다. 이 문서에서 다루는 코드베이스의 부분이 변경되거나 제거될 때, 또는 새로운 구성 요소가 추가될 때 적절히 업데이트하세요.

데이터 모델

네 개의 주요 ActiveRecord 모델은 우리가 _diffs_라고 통칭하는 것을 나타냅니다. 이 데이터베이스 기반 레코드는 프로젝트의 Git 저장소에 포함된 데이터를 복제하며, Gitaly에 대한 과도한 접근 요청을 방지하는 캐시 역할을 합니다. 또한, 다음에 대한 논리적 위치를 제공합니다:

  • 차이에 대한 메타데이터를 계산하고 검색합니다.
  • 일반적인 클래스 및 인스턴스 기반 논리입니다.
%%{init: { "fontFamily": "GitLab Sans" }}%% erDiagram accTitle: 차이에 대한 데이터 모델 accDescr: 차이에 사용되는 네 개의 ActiveRecord 모델의 데이터 모델 MergeRequest ||--|{ MergeRequestDiff: "" MergeRequestDiff |{--|{ MergeRequestDiffCommit: "" MergeRequestDiff |{--|| MergeRequestDiffDetail: "" MergeRequestDiff |{--|{ MergeRequestDiffFile: "" MergeRequestDiffCommit |{--|| MergeRequestDiffCommitUser: ""

MergeRequestDiff

MergeRequestDiffapp/models/merge_request_diff.rb에 정의되어 있습니다. 이 클래스는 일련의 커밋으로부터 발생한 차이에 대한 메타데이터 및 컨텍스트를 보유합니다. 이는 차이 내용, 개별 커밋, 변경 사항이 포함된 파일과 상호작용하기 위한 주요 수단이 되는 메서드를 정의합니다.

#<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>

차이 내용은 일반적으로 이 클래스를 통해 액세스됩니다. 로직은 사용자가 반환하기 전에 차이, 파일 및 커밋 내용에 적용됩니다.

MergeRequestDiff#commits_count

MergeRequestDiff가 저장될 때, 관련된 MergeRequestDiffCommit 레코드가 계산되어 commits_count 열에 캐시됩니다. 이 숫자는 병합 요청 페이지에서 Commits 탭의 카운터로 표시됩니다.

MergeRequestDiffCommit 레코드가 삭제되면 카운터는 업데이트되지 않습니다.

MergeRequestDiffCommit

MergeRequestDiffCommitapp/models/merge_request_diff_commit.rb에 정의되어 있습니다.

이 클래스는 해당 MergeRequestDiff에 포함된 단일 커밋에 해당하며, 커밋에 대한 헤더 정보를 보유합니다.

#<MergeRequestDiffCommit:0x00007fd1dfc6c4c0
  authored_date: , 2022 8 6 06:35:52 UTC +00:00,
  committed_date: , 2022 8 6 06:35:52 UTC +00:00,
  merge_request_diff_id: 28,
  relative_order: 0,
  sha: "bb5206fee213d983da88c47f9cf4cc6caf9c66dc",
  message: "Feature conflict added\n\nSigned-off-by: Sample User <sample.user@example.com>\n",
  trailers: {},
  commit_author_id: 19,
  committer_id: 19>

모든 MergeRequestDiffCommit는 ActiveRecord 용어에서 :belongs_to로 정의된 해당 MergeRequest::DiffCommitUser 레코드가 있습니다. 이러한 레코드는 :commit_author:committer이며, 서로 다른 개인일 수 있습니다.

MergeRequest::DiffCommitUser

MergeRequest::DiffCommitUserapp/models/merge_request/diff_commit_user.rb에 정의되어 있습니다.

이 클래스는 주어진 커밋의 nameemail을 기록하지만 User 레코드와의 연결은 포함되어 있지 않습니다.

#<MergeRequest::DiffCommitUser:0x00007fd1dff7c930
  id: 19,
  name: "Sample User",
  email: "sample.user@example.com">

MergeRequestDiffFile

MergeRequestDiffFileapp/models/merge_request_diff_file.rb에 정의되어 있습니다.

이 클래스의 레코드는 MergeRequestDiff에 포함된 단일 파일의 diff를 나타냅니다.

이는 변화와의 관계에 대한 메타 및 구체적인 정보를 보유합니다, 예를 들어:

  • 추가되었거나 이름이 변경되었는지 여부.
  • diff에서의 순서.
  • 원시 diff 출력 자체.

외부 diff 저장소

기본적으로, MergeRequestDiffFile의 diff 데이터는 merge_request_diff_files 테이블의 diff 열에 저장됩니다.

일부 설치에서는 테이블이 너무 커질 수 있으므로 공간을 절약하기 위해 외부 저장소에 diffs를 저장하도록 구성할 수 있습니다.

구성 방법은 Merge request diffs storage를 참조하세요.

외부 저장소를 사용하도록 구성된 경우:

  • 데이터베이스의 diff 열은 NULL로 남겨집니다.
  • 연관된 MergeRequestDiff 레코드는 MergeRequestDiff 생성 시 stored_externally 속성을 true로 설정합니다.

ScheduleMigrateExternalDiffsWorker라는 cron 작업은 매시간 15분에 예약되어 있습니다.

이는 여전히 데이터베이스에 저장된 diff를 외부 저장소로 이동합니다.

MergeRequestDiffDetail

MergeRequestDiffDetailapp/models/merge_request_diff_detail.rb에 정의되어 있습니다.

이 클래스는 Geo 복제를 위한 검증 정보를 제공하지만, 사용자에게 표시되는 diff에는 사용되지 않습니다.

#<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+# 이 파일은 기능 브랜치에서 변경되었습니다.\n+# 우리는 병합 충돌을 피하기 위해 서로 다른 코드를 여기에 넣습니다.\n+class Conflict\n+end\n",
  binary: false,
  external_diff_offset: nil,
  external_diff_size: nil>

흐름

이 흐름도는 다양한 기능에 대한 컨트롤러에서 모델로의 흐름을 설명하는 데 도움이 됩니다. 이 페이지는 접근 방법과 diff 작업에 대한 모든 옵션을 문서화하는 것이 아니라 가장 일반적인 것에만 집중합니다.

MergeRequestDiff* 레코드 생성

위에서 설명한 바와 같이, 우리는 병합 요청에서 diffs를 표시할 때 Gitaly의 정보를 캐시하기 위해 데이터베이스 테이블을 사용합니다. 활성화되면 diffs를 저장할 때 오브젝트 스토리지도 사용합니다.

우리는 두 가지 유형의 병합 요청 diff가 있습니다: 기본 diff와 HEAD diff. 각 유형은 다르게 생성됩니다.

기본 diff

병합 요청 브랜치에 푸시할 때마다 새 병합 요청 diff 버전을 생성합니다.

이 흐름도는 이 경우 각 구성 요소가 어떻게 사용되는지에 대한 기본 설명을 보여줍니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart TD accTitle: 새 diff 버전 생성 흐름도 accDescr: 브랜치에 Git 푸시에 기반하여 새 diff 버전을 생성할 때 사용되는 구성 요소의 고급 흐름도 A[PostReceive 워커] --> B[MergeRequests::RefreshService] B --> C[병합 요청의 diff 다시 로드] C --> D[병합 요청 diff 생성] D --> K[(데이터베이스)] D --> E[커밋 SHA 확인] E --> L[Gitaly] E --> F[패치 ID 설정] F --> L[Gitaly] F --> G[커밋 저장] G --> L[Gitaly] G --> K[(데이터베이스)] G --> H[diff 저장] H --> L[Gitaly] H --> K[(데이터베이스)] H --> M[(오브젝트 스토리지)] H --> I[커밋 유지] I --> L[Gitaly] I --> J[하이라이트 및 통계 캐시 지우기] J --> N[(Redis)]

이 시퀀스 다이어그램은 이 흐름에 대한 더 자세한 설명을 보여줍니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: 새 diff 빌딩 데이터 흐름 accDescr: 새 diff 버전을 빌드하는 구성 요소를 통한 데이터 흐름의 상세 모델 PostReceive-->>+MergeRequests_RefreshService: execute() Note over MergeRequests_RefreshService: 병합 요청의 diff 다시 로드 MergeRequests_RefreshService-->>+MergeRequest: reload_diff() Note over MergeRequests_ReloadDiffsService: 병합 요청 diff 생성 MergeRequest-->>+MergeRequests_ReloadDiffsService: execute() MergeRequests_ReloadDiffsService-->>+MergeRequest: create_merge_request_diff() MergeRequest-->>+MergeRequestDiff: create() Note over MergeRequestDiff: 커밋 SHA 확인 MergeRequestDiff-->>+MergeRequest: source_branch_sha() MergeRequest-->>+Repository: commit() Repository-->>+Gitaly: FindCommit RPC Gitaly-->>-Repository: Gitlab::Git::Commit Repository-->>+Commit: new() Commit-->>-Repository: Commit Repository-->>-MergeRequest: Commit MergeRequest-->>-MergeRequestDiff: Commit SHA Note over MergeRequestDiff: 패치 ID 설정 MergeRequestDiff-->>+Repository: get_patch_id() Repository-->>+Gitaly: GetPatchID RPC Gitaly-->>-Repository: Patch ID Repository-->>-MergeRequestDiff: Patch ID Note over MergeRequestDiff: 커밋 저장 MergeRequestDiff-->>+Gitaly: ListCommits RPC Gitaly-->>-MergeRequestDiff: Commits MergeRequestDiff-->>+MergeRequestDiffCommit: create_bulk() Note over MergeRequestDiff: diff 저장 MergeRequestDiff-->>+Gitaly: ListCommits RPC Gitaly-->>-MergeRequestDiff: Commits opt 외부 diffs가 활성화된 경우 MergeRequestDiff-->>+ObjectStorage: upload diffs end MergeRequestDiff-->>+MergeRequestDiffFile: legacy_bulk_insert() Note over MergeRequestDiff: 커밋 유지 MergeRequestDiff-->>+Repository: keep_around() Repository-->>+Gitaly: WriteRef RPC Note over MergeRequests_ReloadDiffsService: 하이라이트 및 통계 캐시 지우기 MergeRequests_ReloadDiffsService->>+Gitlab_Diff_HighlightCache: clear() MergeRequests_ReloadDiffsService->>+Gitlab_Diff_StatsCache: clear() Gitlab_Diff_HighlightCache-->>+Redis: cache Gitlab_Diff_StatsCache-->>+Redis: cache

HEAD diff

병합 요청의 병합 가능성이 확인될 때마다 병합 요청의 merge_status:unchecked, :cannot_be_merged_recheck, :checking, :cannot_be_merged_rechecking 중 하나일 경우,

소스 브랜치에서 대상 브랜치로 변경 사항을 병합하고 참조에 기록하려고 시도합니다.

성공적일 경우(즉, 충돌이 없는 경우),

생성된 커밋을 기반으로 차이를 생성하고 이를 HEAD diff로 표시합니다.

이 흐름은 다른 진입점이 있기 때문에 기본 차이 생성과 다릅니다.

이 순서도는 HEAD diff를 생성할 때 각 구성 요소가 어떻게 사용되는지를 간단히 설명합니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart TD accTitle: HEAD diff 생성 (개요) accDescr: HEAD diff 생성 시 사용되는 구성 요소의 고수준 순서도 A[MergeRequestMergeabilityCheckWorker] --> B[MergeRequests::MergeabilityCheckService] B --> C[변경 사항을 참조로 병합] C --> L[Gitaly] C --> D[병합 요청 HEAD diff 재생성] D --> K[(데이터베이스)] D --> E[커밋 SHA 보장] E --> L[Gitaly] E --> F[패치 ID 설정] F --> L[Gitaly] F --> G[커밋 저장] G --> L[Gitaly] G --> K[(데이터베이스)] G --> H[차이 저장] H --> L[Gitaly] H --> K[(데이터베이스)] H --> M[(객체 저장소)] H --> I[커밋 유지] I --> L[Gitaly]

이 시퀀스 다이어그램은 이 흐름에 대한 보다 상세한 설명을 보여줍니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: HEAD diff 생성 (자세한 보기) accDescr: 새로운 HEAD diff 생성을 위한 상세 시퀀스 다이어그램 MergeRequestMergeabilityCheckWorker-->>+MergeRequests_MergeabilityCheckService: execute() Note over MergeRequests_MergeabilityCheckService: 변경 사항을 참조로 병합 MergeRequests_MergeabilityCheckService-->>+MergeRequests_MergeToRefService: execute() MergeRequests_MergeToRefService-->>+Repository: merge_to_ref() Repository-->>+Gitaly: UserMergeBranch RPC Gitaly-->>-Repository: 커밋 SHA MergeRequests_MergeToRefService-->>+Repository: commit() Repository-->>+Gitaly: FindCommit RPC Gitaly-->>-Repository: Gitlab::Git::Commit Repository-->>+Commit: new() Commit-->>-Repository: Commit Repository-->>-MergeRequests_MergeToRefService: 커밋 Note over MergeRequests_MergeabilityCheckService: 병합 요청 HEAD diff 재생성 MergeRequests_MergeabilityCheckService-->>+MergeRequests_ReloadMergeHeadDiffService: execute() MergeRequests_ReloadMergeHeadDiffService-->>+MergeRequest: create_merge_request_diff() MergeRequest-->>+MergeRequestDiff: create() Note over MergeRequestDiff: 커밋 SHA 보장 MergeRequestDiff-->>+MergeRequest: merge_ref_head() MergeRequest-->>+Repository: commit() Repository-->>+Gitaly: FindCommit RPC Gitaly-->>-Repository: Gitlab::Git::Commit Repository-->>+Commit: new() Commit-->>-Repository: Commit Repository-->>-MergeRequest: 커밋 MergeRequest-->>-MergeRequestDiff: 커밋 SHA Note over MergeRequestDiff: 패치 ID 설정 MergeRequestDiff-->>+Repository: get_patch_id() Repository-->>+Gitaly: GetPatchID RPC Gitaly-->>-Repository: 패치 ID Repository-->>-MergeRequestDiff: 패치 ID Note over MergeRequestDiff: 커밋 저장 MergeRequestDiff-->>+Gitaly: ListCommits RPC Gitaly-->>-MergeRequestDiff: 커밋 MergeRequestDiff-->>+MergeRequestDiffCommit: create_bulk() Note over MergeRequestDiff: 차이 저장 MergeRequestDiff-->>+Gitaly: ListCommits RPC Gitaly-->>-MergeRequestDiff: 커밋 opt 외부 차이가 활성화된 경우 MergeRequestDiff-->>+ObjectStorage: 차이 업로드 end MergeRequestDiff-->>+MergeRequestDiffFile: legacy_bulk_insert() Note over MergeRequestDiff: 커밋 유지 MergeRequestDiff-->>+Repository: keep_around() Repository-->>+Gitaly: WriteRef RPC

diffs_batch.json

가장 일반적인 diffs 뷰 방법은 GitLab UI의 병합 요청 페이지 상단에 있는 Changes 탭입니다. 이 탭을 선택하면 diffs 자체가 /-/merge_requests/:id/diffs_batch.json에 대한 페이지 기반 요청을 통해 로드되며, 이는 Projects::MergeRequests::DiffsController#diffs_batch에서 제공됩니다.

이 플로우차트는 각 구성 요소가 diffs_batch.json 요청에서 어떻게 사용되는지를 기본적으로 설명합니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart TD accTitle: diff 보기 accDescr: 브라우저 표시를 위한 diffs_batch 요청의 고급 플로우차트 A[프론트엔드] --> B[diffs_batch.json] B --> C[diffs 및 ivars 미리 로드] C -->D[Gitaly] C -->E[(데이터베이스)] C --> F[diff 파일 컬렉션 얻기] C --> F[diff 파일 컬렉션 얻기] F --> G[펼칠 수 있는 diff 라인 계산] G --> E G --> H{ETag 헤더가 오래되지 않음} H --> |예| I[304 반환] H --> |아니오| J[diff 직렬화] J --> D J --> E J --> K[(Redis)] J --> L[JSON으로 200 반환]

하지만, diffs를 볼 때는 다양한 경우가 있으며, 각 경우에 따라 플로우가 다릅니다.

HEAD, 최신 또는 특정 diff 버전 보기

HEAD diff는 사용 가능한 경우 기본적으로 표시됩니다. 그렇지 않은 경우 최신 diff 버전으로 대체됩니다. 특정 diff 버전을 보는 것도 가능합니다. 이 경우에는 동일한 플로우가 적용됩니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: 가장 최근 diff 보기 accDescr: HEAD diff, 다음 최신 diff, 그 후 요청된 특정 버전으로 표시되는 순서 다이어그램 Frontend-->>+.#diffs_batch: API 호출 Note over .#diffs_batch: diffs 및 ivars 미리 로드 .#diffs_batch-->>+.#define_diff_vars: before_action .#define_diff_vars-->>+MergeRequest: merge_request_head_diff() 또는 merge_request_diff() MergeRequest-->>+MergeRequestDiff: find() MergeRequestDiff-->>-MergeRequest: MergeRequestDiff MergeRequest-->>-.#define_diff_vars: MergeRequestDiff .#define_diff_vars-->>-.#diffs_batch: @compare Note over .#diffs_batch: diff 파일 컬렉션 얻기 .#diffs_batch-->>+MergeRequestDiff: diffs_in_batch() MergeRequestDiff-->>+Gitlab_Diff_FileCollection_MergeRequestDiffBatch: new() Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>-MergeRequestDiff: diff 파일 컬렉션 MergeRequestDiff-->>-.#diffs_batch: diff 파일 컬렉션 Note over .#diffs_batch: 펼칠 수 있는 diff 라인 계산 .#diffs_batch-->>+MergeRequest: note_positions_for_paths MergeRequest-->>+Gitlab_Diff_PositionCollection: new() then unfoldable() Gitlab_Diff_PositionCollection-->>-MergeRequest: 위치 컬렉션 MergeRequest-->>-.#diffs_batch: unfoldable_positions break when ETag header is present and is not stale .#diffs_batch-->>+Frontend: 304 HTTP 반환 end .#diffs_batch->>+Gitlab_Diff_FileCollection_MergeRequestDiffBatch: write_cache() Gitlab_Diff_FileCollection_MergeRequestDiffBatch->>+Gitlab_Diff_HighlightCache: write_if_empty() Gitlab_Diff_FileCollection_MergeRequestDiffBatch->>+Gitlab_Diff_StatsCache: write_if_empty() Gitlab_Diff_HighlightCache-->>+Redis: 캐시 Gitlab_Diff_StatsCache-->>+Redis: 캐시 Note over .#diffs_batch: diffs 직렬화 및 JSON 렌더링 .#diffs_batch-->>+PaginatedDiffSerializer: represent() PaginatedDiffSerializer-->>+Gitlab_Diff_FileCollection_MergeRequestDiffBatch: diff_files() Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>+MergeRequestDiff: raw_diffs() MergeRequestDiff-->>+MergeRequestDiffFile: 모든 관련 기록 가져오기 MergeRequestDiffFile-->>-MergeRequestDiff: Gitlab::Git::DiffCollection MergeRequestDiff-->>-Gitlab_Diff_FileCollection_MergeRequestDiffBatch: diff 파일 Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>+Gitlab_Diff_StatsCache: find_by_path() Gitlab_Diff_StatsCache-->>+Redis: 캐시에서 데이터 읽기 Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>+Gitlab_Diff_HighlightCache: decorate() Gitlab_Diff_HighlightCache-->>+Redis: 캐시에서 데이터 읽기 Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>-PaginatedDiffSerializer: diff 파일 PaginatedDiffSerializer-->>-.#diffs_batch: JSON .#diffs_batch-->>+Frontend: JSON으로 200 HTTP 반환

그러나 Show whitespace changes가 선택되지 않은 경우 diffs를 볼 때:

  • 공백 변경 사항이 무시됩니다.
  • 플로우가 변경되며 이제 Gitaly가 포함됩니다.
%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: 공백 변경 없는 diff 보기 accDescr: 공백 변경 요청이 없을 때 특정 diff가 표시되는 방식의 시퀀스 다이어그램 - 먼저 HEAD diff, 다음 최신 diff, 요청된 경우 특정 버전 Frontend-->>+.#diffs_batch: API 호출 Note over .#diffs_batch: diffs 및 ivars 미리 로드 .#diffs_batch-->>+.#define_diff_vars: before_action .#define_diff_vars-->>+MergeRequest: merge_request_head_diff() 또는 merge_request_diff() MergeRequest-->>+MergeRequestDiff: find() MergeRequestDiff-->>-MergeRequest: MergeRequestDiff MergeRequest-->>-.#define_diff_vars: MergeRequestDiff .#define_diff_vars-->>-.#diffs_batch: @compare Note over .#diffs_batch: diff 파일 컬렉션 얻기 .#diffs_batch-->>+MergeRequestDiff: diffs_in_batch() MergeRequestDiff-->>+Gitlab_Diff_FileCollection_Compare: new() Gitlab_Diff_FileCollection_Compare-->>-MergeRequestDiff: diff 파일 컬렉션 MergeRequestDiff-->>-.#diffs_batch: diff 파일 컬렉션 Note over .#diffs_batch: 펼칠 수 있는 diff 라인 계산 .#diffs_batch-->>+MergeRequest: note_positions_for_paths MergeRequest-->>+Gitlab_Diff_PositionCollection: new() then unfoldable() Gitlab_Diff_PositionCollection-->>-MergeRequest: 위치 컬렉션 MergeRequest-->>-.#diffs_batch: unfoldable_positions break when ETag header is present and is not stale .#diffs_batch-->>+Frontend: 304 HTTP 반환 end opt HEAD, 최신 또는 특정 버전 보기 시 캐시 하이라이트 및 통계 .#diffs_batch->>+Gitlab_Diff_FileCollection_MergeRequestDiffBatch: write_cache() Gitlab_Diff_FileCollection_MergeRequestDiffBatch->>+Gitlab_Diff_HighlightCache: write_if_empty() Gitlab_Diff_FileCollection_MergeRequestDiffBatch->>+Gitlab_Diff_StatsCache: write_if_empty() Gitlab_Diff_HighlightCache-->>+Redis: 캐시 Gitlab_Diff_StatsCache-->>+Redis: 캐시 end Note over .#diffs_batch: diffs 직렬화 및 JSON 렌더링 .#diffs_batch-->>+PaginatedDiffSerializer: represent() PaginatedDiffSerializer-->>+Gitlab_Diff_FileCollection_MergeRequestDiffBatch: diff_files() Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>+MergeRequestDiff: raw_diffs() MergeRequestDiff-->>+Repository: diff() Repository-->>+Gitaly: CommitDiff RPC Gitaly-->>-Repository: GitalyClient::DiffStitcher Repository-->>-MergeRequestDiff: Gitlab::Git::DiffCollection MergeRequestDiff-->>-Gitlab_Diff_FileCollection_MergeRequestDiffBatch: diff 파일 Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>+Gitlab_Diff_StatsCache: find_by_path() Gitlab_Diff_StatsCache-->>+Redis: 캐시에서 데이터 읽기 Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>+Gitlab_Diff_HighlightCache: decorate() Gitlab_Diff_HighlightCache-->>+Redis: 캐시에서 데이터 읽기 Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>-PaginatedDiffSerializer: diff 파일 PaginatedDiffSerializer-->>-.#diffs_batch: JSON .#diffs_batch-->>+Frontend: JSON으로 200 HTTP 반환

병합 요청의 차이 버전 비교

차이 버전을 볼 때 서로 다른 차이 버전을 비교할 수도 있습니다.

흐름은 기본 흐름과 다르며, 두 개의 차이 버전 간 비교를 생성하기 위해 Gitaly에 요청을 합니다.

또한 강조 및 통계 캐시를 위해 Redis를 사용하지 않습니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: Comparing diffs accDescr: Sequence diagram of how diffs are compared against each other Frontend-->>+.#diffs_batch: API call Note over .#diffs_batch: Preload diffs and ivars .#diffs_batch-->>+.#define_diff_vars: before_action .#define_diff_vars-->>+MergeRequestDiff: compare_with(start_sha) MergeRequestDiff-->>+Compare: new() Compare-->>-MergeRequestDiff: Compare MergeRequestDiff-->>-.#define_diff_vars: Compare .#define_diff_vars-->>-.#diffs_batch: @compare Note over .#diffs_batch: Getting diff file collection .#define_diff_vars-->>+Compare: diffs_in_batch() Compare-->>+Gitlab_Diff_FileCollection_Compare: new() Gitlab_Diff_FileCollection_Compare-->>-Compare: diff file collection Compare-->>-.#define_diff_vars: diff file collection Note over .#diffs_batch: Calculate unfoldable diff lines .#diffs_batch-->>+MergeRequest: note_positions_for_paths MergeRequest-->>+Gitlab_Diff_PositionCollection: new() then unfoldable() Gitlab_Diff_PositionCollection-->>-MergeRequest: position collection MergeRequest-->>-.#diffs_batch: unfoldable_positions break when ETag header is present and is not stale .#diffs_batch-->>+Frontend: return 304 HTTP end Note over .#diffs_batch: Serialize diffs and render JSON .#diffs_batch-->>+PaginatedDiffSerializer: represent() PaginatedDiffSerializer-->>+Gitlab_Diff_FileCollection_Compare: diff_files() Gitlab_Diff_FileCollection_Compare-->>+Compare: raw_diffs() Compare-->>+Repository: diff() Repository-->>+Gitaly: CommitDiff RPC Gitaly-->>-Repository: GitalyClient::DiffStitcher Repository-->>-Compare: Gitlab::Git::DiffCollection Compare-->>-Gitlab_Diff_FileCollection_Compare: diff files Gitlab_Diff_FileCollection_Compare-->>-PaginatedDiffSerializer: diff files PaginatedDiffSerializer-->>-.#diffs_batch: JSON .#diffs_batch-->>+Frontend: return 200 HTTP with JSON

커밋 차이 보기

병합 요청 차이를 보는 또 다른 기능은 특정 커밋의 차이를 보는 것입니다.

이는 기본 흐름과 다르며, 특정 커밋의 차이를 가져오기 위해 Gitaly가 필요합니다.

또한 강조 및 통계 캐시를 위해 Redis를 사용하지 않습니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: Viewing commit diff accDescr: Sequence diagram showing how viewing the diff of a specific commit is different from the default diff view flow Frontend-->>+.#diffs_batch: API call Note over .#diffs_batch: Preload diffs and ivars .#diffs_batch-->>+.#define_diff_vars: before_action .#define_diff_vars-->>+Repository: commit() Repository-->>+Gitaly: FindCommit RPC Gitaly-->>-Repository: Gitlab::Git::Commit Repository-->>+Commit: new() Commit-->>-Repository: Commit Repository-->>-.#define_diff_vars: Commit .#define_diff_vars-->>-.#diffs_batch: @compare Note over .#diffs_batch: Getting diff file collection .#define_diff_vars-->>+Commit: diffs_in_batch() Commit-->>+Gitlab_Diff_FileCollection_Commit: new() Gitlab_Diff_FileCollection_Commit-->>-Commit: diff file collection Commit-->>-.#define_diff_vars: diff file collection Note over .#diffs_batch: Calculate unfoldable diff lines .#diffs_batch-->>+MergeRequest: note_positions_for_paths MergeRequest-->>+Gitlab_Diff_PositionCollection: new() then unfoldable() Gitlab_Diff_PositionCollection-->>-MergeRequest: position collection MergeRequest-->>-.#diffs_batch: unfoldable_positions break when ETag header is present and is not stale .#diffs_batch-->>+Frontend: return 304 HTTP end Note over .#diffs_batch: Serialize diffs and render JSON .#diffs_batch-->>+PaginatedDiffSerializer: represent() PaginatedDiffSerializer-->>+Gitlab_Diff_FileCollection_Commit: diff_files() Gitlab_Diff_FileCollection_Commit-->>+Commit: raw_diffs() Commit-->>+Gitaly: CommitDiff RPC Gitaly-->>-Commit: GitalyClient::DiffStitcher Commit-->>-Gitlab_Diff_FileCollection_Commit: Gitlab::Git::DiffCollection Gitlab_Diff_FileCollection_Commit-->>-PaginatedDiffSerializer: diff files PaginatedDiffSerializer-->>-.#diffs_batch: JSON .#diffs_batch-->>+Frontend: return 200 HTTP with JSON

diffs.json

머지 요청을 생성하는 동안 하단으로 스크롤하여 Changes 탭을 클릭하면 diffs를 볼 수도 있습니다.

이 시점에서는 머지 요청 기록이 생성되지 않았기 때문에 diffs_batch.json 엔드포인트를 사용하지 않습니다. 대신 diffs.json을 사용합니다.

이 플로우차트는 각 구성 요소가 diffs.json 요청에서 어떻게 사용되는지에 대한 기본 설명을 보여줍니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% flowchart TD accTitle: Diff 요청 흐름 (고급) accDescr: diffs 요청에 사용되는 구성 요소의 고급 플로우차트 A[프론트엔드] --> B[diffs.json] B --> C[머지 요청 생성] C --> D[diffs 가져오기] D --> E[diffs로 뷰 렌더링] E --> G[Gitaly] E --> F[렌더링된 뷰로 JSON 응답]

이 시퀀스 다이어그램은 이 흐름에 대한 더 자세한 설명을 보여줍니다.

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: Diff 요청 흐름 (저급) accDescr: diffs 요청에 사용되는 구성 요소에 대한 심층 시퀀스 다이어그램 Frontend-->>+.#diffs: API 호출 Note over .#diffs: 머지 요청 생성 .#diffs-->>+MergeRequests_BuildService: execute MergeRequests_BuildService-->>+Compare: new() Compare-->>-MergeRequests_BuildService: Compare MergeRequests_BuildService-->>+Compare: commits() Compare-->>+Gitaly: ListCommits RPC Gitaly-->-Compare: 커밋 Compare-->>-MergeRequests_BuildService: 커밋 MergeRequests_BuildService-->>-.#diffs: MergeRequest Note over .#diffs: diffs 가져오기 .#diffs-->>+MergeRequest: diffs() MergeRequest-->>+Compare: diffs() Compare-->>+Gitlab_Diff_FileCollection_Compare: new() Gitlab_Diff_FileCollection_Compare-->>-Compare: diff 파일 컬렉션 Compare-->>-MergeRequest: diff 파일 컬렉션 MergeRequest-->>-.#diffs: @diffs = Note over .#diffs: diffs로 뷰 렌더링 .#diffs-->>+HAML: view_to_html_string('projects/merge_requests/creations/_diffs', diffs: @diffs) HAML-->>+Gitlab_Diff_FileCollection_Compare: diff_files() Gitlab_Diff_FileCollection_Compare-->>+Compare: raw_diffs() Compare-->>+Repository: diff() Repository-->>+Gitaly: CommitDiff RPC Gitaly-->>-Repository: GitalyClient::DiffStitcher Repository-->>-Compare: Gitlab::Git::DiffCollection Compare-->>-Gitlab_Diff_FileCollection_Compare: diff 파일 Gitlab_Diff_FileCollection_Compare-->>-HAML: diff 파일 HAML-->>-.#diffs: 렌더링된 뷰 .#diffs-->>-Frontend: 렌더링된 뷰로 JSON 응답