병합 요청 차이 개발 안내
이 문서는 병합 요청 차이의 백엔드 디자인과 흐름을 설명합니다.
기여자가 다음을 돕는 데 도움이 될 것입니다:
- 코드 디자인을 이해합니다.
- 기여를 통해 개선할 수 있는 영역을 식별합니다.
구현 세부 정보가 많지 않도록 의도된 바입니다. 왜냐하면 이것들은 자주 변경될 수 있기 때문입니다. 코드가 이러한 세부 사항을 더 잘 설명합니다. 여기서 언급된 구성 요소는 병합 요청 차이가 생성, 저장되고 사용자에게 반환되는 응용 프로그램의 주요 부분입니다.
참고:
이 페이지는 지속적인 문서입니다. 코드베이스의 부분이 변경되거나 제거되거나 새 구성 요소가 추가될 때 해당 내용에 맞게 업데이트하십시오.
데이터 모델
네 개의 주요 ActiveRecord 모델은 우리가 _차이_로 통칭하는 것을 나타냅니다. 이러한 데이터베이스를 지원하는 레코드들은 프로젝트의 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: 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
레코드가 :commit_author
, :committer
로 :belongs_to
됩니다. 이러한 레코드는 다른 사람일 수도 있습니다.
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
에 포함된 단일 파일의 차이를 나타냅니다. 파일의 변경과 관련된 메타데이터와 특정 정보를 포함하고 있으며 다음과 같은 사항도 포함합니다:
- 추가되었는지 또는 이름이 변경되었는지 여부
- 차이에서의 순서
- 실제 차이 출력
외부 차이 저장
기본적으로 MergeRequestDiffFile
의 차이 데이터는 merge_request_diff_files
테이블의 diff
열에 저장됩니다. 일부 설치에서는 테이블이 너무 커져서 공간을 저장하기 위해 차이 데이터를 외부 저장소에 저장하도록 구성될 수 있습니다. 이를 구성하려면 병합 요청 차이 저장를 참조하십시오.
외부 저장소를 사용하도록 구성된 경우:
- 데이터베이스의
diff
열은 NULL
로 유지됩니다.
- 연관된
MergeRequestDiff
레코드는 stored_externally
속성을 true
로 설정합니다.
ScheduleMigrateExternalDiffsWorker
라는 크론 작업이 매 시간 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>
플로우
이 플로우 차트는 컨트롤러에서 모델로 이어지는 여러 기능에 대한 플로우를 설명하는 데 도움이 될 것입니다. 이 페이지는 액세스 및 차이를 사용하여 작업하는 다양한 옵션을 문서화하는 것을 목적으로 하지는 않습니다. 이는 주로 일반적인 기능에 중점을 둡니다.
MergeRequestDiff*
레코드 생성
위에서 설명했듯이 병합 요청에서 차이를 표시할 때 Gitaly에서 정보를 캐시하기 위해 데이터베이스 테이블을 사용합니다. 활성화된 경우 차이를 저장할 때 개체 저장소도 사용합니다.
두 가지 유형의 병합 요청 차이가 있습니다: 기본 차이 및 HEAD
차이. 각 유형은 다르게 생성됩니다.
기본 차이
병합 요청 브랜치로의 모든 푸시마다 새로운 병합 요청 차이 버전을 만듭니다.
이 플로우 차트는 이런 경우 각 구성 요소가 어떻게 사용되는지에 대한 기본적인 설명을 보여줍니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart TD
accTitle: 새로운 차이 버전 생성의 플로우 차트
accDescr: 브랜치로의 Git 푸시를 기반으로 새로운 차이 버전을 생성할 때 사용되는 구성 요소의 고수준 플로우 차트
A[PostReceive worker] --> B[MergeRequests::RefreshService]
B --> C[병합 요청의 차이 다시로드]
C --> D[병합 요청 차이 생성]
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]
I --> J[하이라이트 및 통계 캐시 지우기]
J --> N[(Redis)]
이 순서도는 이러한 플로우에 대한 더 자세한 설명을 보여줍니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
accTitle: 새로운 차이 빌드의 데이터 플로우
accDescr: 새로운 차이 버전을 구성하는 구성 요소를 통한 데이터 플로우의 자세한 모델
PostReceive-->>+MergeRequests_RefreshService: 실행()
Note over MergeRequests_RefreshService: 병합 요청의 차이 다시로드
MergeRequests_RefreshService-->>+MergeRequest: reload_diff()
Note over MergeRequests_ReloadDiffsService: 병합 요청 차이 생성
MergeRequest-->>+MergeRequests_ReloadDiffsService: 실행()
MergeRequests_ReloadDiffsService-->>+MergeRequest: create_merge_request_diff()
MergeRequest-->>+MergeRequestDiff: 생성()
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: 커밋 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
Note over MergeRequests_ReloadDiffsService: 하이라이트 및 통계 캐시 지우기
MergeRequests_ReloadDiffsService->>+Gitlab_Diff_HighlightCache: 지우기()
MergeRequests_ReloadDiffsService->>+Gitlab_Diff_StatsCache: 지우기()
Gitlab_Diff_HighlightCache-->>+Redis: 캐시
Gitlab_Diff_StatsCache-->>+Redis: 캐시
HEAD
차이
병합 요청의 병합 가능성을 확인하고 병합 요청 merge_status
가 :unchecked
, :cannot_be_merged_recheck
, :checking
, 또는 :cannot_be_merged_rechecking
중일 때, 소스 브랜치에서 대상 브랜치로 변경 사항을 병합하고 참조에 쓰려고 시도합니다. 성공하면(즉, 충돌이없는 경우) 생성된 커밋을 기반으로 차이를 생성하고 HEAD
차이로 표시합니다.
이 플로우는 기본 차이 생성과 다른 항목이고 다른 진입점을 갖습니다.
이 플로우 차트는 HEAD
차이를 생성할 때 각 구성 요소가 어떻게 사용되는지에 대한 기본적인 설명을 보여줍니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart TD
accTitle: HEAD 차이 생성(고수준 뷰)
accDescr: HEAD 차이를 생성할 때 사용되는 구성 요소의 고수준 플로우 차트
A[병합 요청 병합 가능성 확인 worker] --> B[MergeRequests::MergeabilityCheckService]
B --> C[참조에 변경 사항 병합]
C --> L[Gitaly]
C --> D[병합 요청 HEAD 차이 재생성]
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 차이 생성(상세 뷰)
accDescr: 새로운 HEAD 차이 생성의 자세한 시퀀스 다이어그램
병합 요청 병합 가능성 확인 worker-->>+MergeRequests_MergeabilityCheckService: 실행()
Note over MergeRequests_MergeabilityCheckService: 참조에 변경 사항 병합
MergeRequests_MergeabilityCheckService-->>+MergeRequests_MergeToRefService: 실행()
MergeRequests_MergeToRefService-->>+Repository: merge_to_ref()
Repository-->>+Gitaly: UserMergeBranch RPC
Gitaly-->>-Repository: 커밋 SHA
MergeRequests_MergeToRefService-->>+Repository: 커밋()
Repository-->>+Gitaly: FindCommit RPC
Gitaly-->>-Repository: Gitlab::Git::Commit
Repository-->>+Commit: new()
Commit-->>-Repository: Commit
Repository-->>-MergeRequests_MergeToRefService: Commit
Note over MergeRequests_MergeabilityCheckService: 병합 요청 HEAD 차이 재생성
MergeRequests_MergeabilityCheckService-->>+MergeRequests_ReloadMergeHeadDiffService: 실행()
MergeRequests_ReloadMergeHeadDiffService-->>+MergeRequest: create_merge_request_diff()
MergeRequest-->>+MergeRequestDiff: 생성()
Note over MergeRequestDiff: 커밋 SHA 보장
MergeRequestDiff-->>+MergeRequest: merge_ref_head()
MergeRequest-->>+Repository: 커밋()
Repository-->>+Gitaly: FindCommit RPC
Gitaly-->>-Repository: Gitlab::Git::Commit
Repository-->>+Commit: new()
Commit-->>-Repository: Commit
Repository-->>-MergeRequestDiff: Commit
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
가장 일반적인 차이를 볼 수 있는 경로는 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: 차이 보기
accDescr: 브라우저 표시를 위해 diffs_batch 요청을 그리는 고수위 플로우차트
A[프론트엔드] --> B[diffs_batch.json]
B --> C[diffs 사전로드와 ivars]
C -->D[Gitaly]
C -->E[(데이터베이스)]
C --> F[차이 파일 컬렉션 가져오기]
F --> G[펼칠 수 있는 차이 행 계산]
G --> E
G --> H{ETag 헤더가 낡지 않은 경우}
H --> |예| I[304 반환]
H --> |아니요| J[차이 직렬화]
J --> D
J --> E
J --> K[(Redis)]
J --> L[JSON으로 200 반환]
다양한 경우에 따라 차이를 볼 때 서로 다른 사례가 존재하며, 각 사례에 대한 플로우가 다릅니다.
HEAD, 최신 또는 특정 차이 버전 보기
HEAD 차이는 기본적으로 사용 가능한 경우에만 볼 수 있습니다. 그렇지 않은 경우에는 최신 차이 버전으로 되돌아갑니다. 또는 특정 차이 버전도 볼 수 있습니다. 이러한 경우에는 동일한 플로우가 적용됩니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
accTitle: 가장 최근 차이 보기
accDescr: 특정 차이가 표시되는 시퀀스 다이어그램을 나타내는 것. 먼저 HEAD 차이로 시작하여, 그 다음에는 최신 차이로, 그 다음에는 요청된 경우에 특정 버전으로
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: 차이 파일 컬렉션 가져오기
.#diffs_batch-->>+MergeRequestDiff: diffs_in_batch()
MergeRequestDiff-->>+Gitlab_Diff_FileCollection_MergeRequestDiffBatch: new()
Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>-MergeRequestDiff: 차이 파일 컬렉션
MergeRequestDiff-->>-.#diffs_batch: 차이 파일 컬렉션
Note over .#diffs_batch: 펼칼 수 있는 차이 행 계산
.#diffs_batch-->>+MergeRequest: note_positions_for_paths
MergeRequest-->>+Gitlab_Diff_PositionCollection: new() 그런 다음 unfoldable()
Gitlab_Diff_PositionCollection-->>-MergeRequest: 포지션 컬렉션
MergeRequest-->>-.#diffs_batch: unfoldable_positions
break ETag 헤더가 있고 낡지 않은 경우
.#diffs_batch-->>+프론트엔드: 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: 차이 직렬화 및 JSON 렌더링
.#diffs_batch-->>+PaginatedDiffSerializer: represent()
PaginatedDiffSerializer-->>+Gitlab_Diff_FileCollection_MergeRequestDiffBatch: diff_files()
Gitlab_Diff_FileCollection_MergeRequestDiffBatch-->>+MergeRequestDiff: raw_diffs()
MergeRequestDiff-->>-MergeRequestDiff: Gitlab::Git::DiffCollection
MergeRequestDiff-->>-MergeRequestDiff: diff files
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 files
PaginatedDiffSerializer-->>-.#diffs_batch: JSON
.#diffs_batch-->>+프론트엔드: 200 HTTP와 JSON 반환
그러나 차이를 보는 중 화이트스페이스 변경 보기가 선택되지 않은 경우:
- 화이트스페이스 변경은 무시됩니다.
- 플로우가 변경되며 이제 Gitaly가 관련됩니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
accTitle: 화이트스페이스 변경 없이 차이 보기
accDescr: 특정 차이가 표시되는 시퀀스 다이어그램을 나타내는 것. 먼저 HEAD 차이로 시작하여, 그 다음에는 최신 차이로, 그 다음에는 요청된 경우에 특정 버전으로
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: 차이 파일 컬렉션 가져오기
.#diffs_batch-->>+MergeRequestDiff: diffs_in_batch()
MergeRequestDiff-->>+Gitlab_Diff_FileCollection_Compare: new()
Gitlab_Diff_FileCollection_Compare-->>-MergeRequestDiff: diff file collection
MergeRequestDiff-->>-.#diffs_batch: diff file collection
Note over .#diffs_batch: 펼칼 수 있는 차이 행 계산
.#diffs_batch-->>+MergeRequest: note_positions_for_paths
MergeRequest-->>+Gitlab_Diff_PositionCollection: new() 그런 다음 unfoldable()
Gitlab_Diff_PositionCollection-->>-MergeRequest: position collection
MergeRequest-->>-.#diffs_batch: unfoldable_positions
ETag 헤더가 있고 낡지 않은 경우
.#diffs_batch-->>+프론트엔드: 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: 차이 직렬화 및 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 files
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 files
PaginatedDiffSerializer-->>-.#diffs_batch: JSON
.#diffs_batch-->>+프론트엔드: 200 HTTP와 JSON 반환
병합 요청 차이 버전 비교
파일들을 보는 동안 다른 차이 버전도 비교할 수 있습니다. 이 흐름은 기본 흐름과 다르며 두 개의 차이 버전을 비교하기 위해 Gitaly에 요청을 생성합니다. 하이라이트 및 통계 캐시에 대해 Redis를 사용하지 않습니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
accTitle: 차이 비교
accDescr: 서로 다른 차이를 비교하는 순서도
Frontend-->>+.#diffs_batch: API 호출
Note over .#diffs_batch: 미리 로드(diff) 및 인스턴스 변수(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: 차이 파일 컬렉션 가져오기
.#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: 접을 수 있는 차이 행 계산
.#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
ETag 헤더가 존재하고 빠르지 않을 때까지 중단
.#diffs_batch-->>+Frontend: 304 HTTP 반환
end
Note over .#diffs_batch: 차이 직렬화 및 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: 렌더링된 뷰의 JSON으로 200 HTTP 반환
커밋 차이 보기
병합 요청 차이를 보는 또 다른 기능은 특정 커밋의 차이를 볼 수 있습니다. 기본 흐름과 다르며 특정 커밋의 차이를 가져 오기 위해 Gitaly가 필요합니다. 하이라이트 및 통계 캐시에 대해 Redis를 사용하지 않습니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
accTitle: 커밋 차이 보기
accDescr: 특정 커밋의 차이를 보는 방식에 대한 순서도
Frontend-->>+.#diffs_batch: API 호출
Note over .#diffs_batch: 미리 로드(diff) 및 인스턴스 변수(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: 차이 파일 컬렉션 가져오기
.#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: 접을 수 있는 차이 행 계산
.#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
ETag 헤더가 존재하고 빠르지 않을 때까지 중단
.#diffs_batch-->>+Frontend: 304 HTTP 반환
end
Note over .#diffs_batch: 차이 직렬화 및 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: 렌더링된 뷰의 JSON으로 200 HTTP 반환
diffs.json
새로운 병합 요청 페이지 하단으로 스크롤하여 Changes 탭을 클릭하여 병합 요청을 작성하면 차이를 볼 수 있습니다. 이때 diffs_batch.json
엔드포인트를 사용하지 않습니다. 왜냐하면 해당 시점에서 병합 요청 레코드가 아직 생성되지 않았기 때문에 대신 diffs.json
을 사용합니다.
이 플로우차트는 diffs.json
요청에 사용되는 각 구성 요소에 대한 기본 설명을 보여줍니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart TD
accTitle: 차이 요청 플로우 (상위 수준)
accDescr: 차이 요청에 사용되는 구성 요소의 고수준 플로우차트
A[Frontend] --> B[diffs.json]
B --> C[병합 요청 작성]
C --> D[차이 얻기]
D --> E[차이가 포함된 뷰 렌더링]
E --> G[Gitaly]
E --> F[렌더된 뷰와 함께 JSON 응답]
다음의 순서도는 이 흐름에 대한 보다 자세한 설명을 보여줍니다.
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
accTitle: 차이 요청 플로우 (하위 수준)
accDescr: 차이 요청에 사용되는 구성 요소를 보다 자세히 보여주는 순서도
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: Commits
Compare-->>-MergeRequests_BuildService: Commits
MergeRequests_BuildService-->>-.#diffs: 병합 요청
Note over .#diffs: 차이 얻기
.#diffs-->>+MergeRequest: diffs()
MergeRequest-->>+Compare: diffs()
Compare-->>+Gitlab_Diff_FileCollection_Compare: new()
Gitlab_Diff_FileCollection_Compare-->>-Compare: diff file collection
Compare-->>-MergeRequest: diff file collection
MergeRequest-->>-.#diffs: @diffs =
Note over .#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 files
Gitlab_Diff_FileCollection_Compare-->>-HAML: diff files
HAML-->>-.#diffs: 렌더링된 뷰
.#diffs-->>-Frontend: 렌더된 뷰와 함께 JSON 응답