병합 요청 차이 개발 가이드
이 문서는 병합 요청 차이의 백엔드 설계 및 흐름에 대해 설명합니다.
기여자들이 다음을 이해하는 데 도움이 되어야 합니다:
- 코드 설계를 이해합니다.
- 기여를 통한 개선 영역을 식별합니다.
구현 세부 사항이 너무 많이 포함되지 않은 것은 의도적이며, 변경될 수 있는 부분입니다. 이러한 세부 사항은 코드가 더 잘 설명합니다. 여기 언급된 구성 요소는 병합 요청 차이가 생성, 저장 및 사용자에게 반환되는 방식에서 애플리케이션의 주요 부분입니다.
참고:
이 페이지는 살아있는 문서입니다. 이 문서에서 다루는 코드베이스의 부분이 변경되거나 제거될 때, 또는 새로운 구성 요소가 추가될 때 적절히 업데이트하세요.
데이터 모델
네 개의 주요 ActiveRecord 모델은 우리가 _diffs_라고 통칭하는 것을 나타냅니다. 이 데이터베이스 기반 레코드는 프로젝트의 Git 저장소에 포함된 데이터를 복제하며, Gitaly에 대한 과도한 접근 요청을 방지하는 캐시 역할을 합니다. 또한, 다음에 대한 논리적 위치를 제공합니다:
- 차이에 대한 메타데이터를 계산하고 검색합니다.
- 일반적인 클래스 및 인스턴스 기반 논리입니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
erDiagram
accTitle: 차이에 대한 데이터 모델
accDescr: 차이에 사용되는 네 개의 ActiveRecord 모델의 데이터 모델
MergeRequest ||--|{ MergeRequestDiff: ""
MergeRequestDiff |{--|{ MergeRequestDiffCommit: ""
MergeRequestDiff |{--|| MergeRequestDiffDetail: ""
MergeRequestDiff |{--|{ MergeRequestDiffFile: ""
MergeRequestDiffCommit |{--|| MergeRequestDiffCommitUser: ""
MergeRequestDiff
MergeRequestDiff
는 app/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
MergeRequestDiffCommit
는 app/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::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 출력 자체.
외부 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
MergeRequestDiffDetail
는 app/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 응답