diff --git a/app/controllers/projects/merge_requests/diffs_stream_controller.rb b/app/controllers/projects/merge_requests/diffs_stream_controller.rb index fe2ae59e23afa96b664ac3a898c40267a2c9a72a..b5dade06031b477e2b3ca8ce6adebe483dd78cb6 100644 --- a/app/controllers/projects/merge_requests/diffs_stream_controller.rb +++ b/app/controllers/projects/merge_requests/diffs_stream_controller.rb @@ -7,6 +7,7 @@ class DiffsStreamController < Projects::MergeRequests::ApplicationController urgency :low, [:diffs] + # rubocop: disable Metrics/AbcSize -- This is a throw away code def diffs return render_404 unless ::Feature.enabled?(:rapid_diffs, current_user, type: :wip) @@ -14,13 +15,65 @@ def diffs offset = params[:offset].to_i - @merge_request.diffs(offset_index: offset).diff_files.each do |diff| - response.stream.write( - render_to_string( - ::RapidDiffs::DiffFileComponent.new(diff_file: diff), - layout: false + if params[:diff_blobs] + changed_paths = @merge_request + .project + .repository + .find_changed_paths([ + Gitlab::Git::DiffTree.new( + @merge_request.diff_refs.base_sha, + @merge_request.diff_refs.head_sha + ) + ], find_renames: true) + + changed_paths.map do |changed_path| + diff_blobs = @merge_request + .project + .repository + .diff_blobs([ + Gitaly::DiffBlobsRequest::BlobPair.new( + left_oid: changed_path.old_blob_id, + right_oid: changed_path.new_blob_id + ) + ]) + + blob = diff_blobs.first + + diff_attrs = { + diff: blob.patch, + new_path: changed_path.path, + old_path: changed_path.path, + a_mode: changed_path.old_mode, + b_mode: changed_path.new_mode, + new_file: changed_path.status == :ADDED, + renamed_file: changed_path.status == :RENAMED, + deleted_file: changed_path.status == :DELETED, + too_large: false + } + + diff = Gitlab::Git::Diff.new(diff_attrs) + diff_file = Gitlab::Diff::File.new( + diff, + repository: @merge_request.project.repository, + diff_refs: @merge_request.diff_refs + ) + + response.stream.write( + render_to_string( + ::RapidDiffs::DiffFileComponent.new(diff_file: diff_file), + layout: false + ) + ) + end + else + @merge_request.diffs(offset_index: offset).diff_files.each do |diff| + response.stream.write( + render_to_string( + ::RapidDiffs::DiffFileComponent.new(diff_file: diff), + layout: false + ) ) - ) + end end rescue StandardError => e @@ -29,5 +82,6 @@ def diffs response.stream.close end end + # rubocop: enable Metrics/AbcSize end end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 9bd28345a1cd9e7034117107009a8c06245aae08..6cca854ec1c539d68b92ba631987b92bcc71ca78 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -527,13 +527,13 @@ def diff_stats(left_id, right_id) empty_diff_stats end - def find_changed_paths(treeish_objects, merge_commit_diff_mode: nil) + def find_changed_paths(treeish_objects, merge_commit_diff_mode: nil, find_renames: false) processed_objects = treeish_objects.compact return [] if processed_objects.empty? wrapped_gitaly_errors do - gitaly_commit_client.find_changed_paths(processed_objects, merge_commit_diff_mode: merge_commit_diff_mode) + gitaly_commit_client.find_changed_paths(processed_objects, merge_commit_diff_mode: merge_commit_diff_mode, find_renames: find_renames) end rescue CommandError, TypeError, NoRepository [] @@ -1175,6 +1175,12 @@ def get_patch_id(old_revision, new_revision) end end + def diff_blobs(blob_pairs) + wrapped_gitaly_errors do + gitaly_commit_client.diff_blobs(blob_pairs) + end + end + def object_pool wrapped_gitaly_errors do gitaly_repository_client.object_pool.object_pool diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb index 34a6de540418eb0d61d9c5e7212d9de5059801a1..fdf96058b8ce3989c0d518d24b7730c4686c5eb8 100644 --- a/lib/gitlab/gitaly_client/commit_service.rb +++ b/lib/gitlab/gitaly_client/commit_service.rb @@ -63,6 +63,11 @@ def diff_from_parent(commit, options = {}) call_commit_diff(request_params, options) end + def diff_blobs(blob_pairs) + request = Gitaly::DiffBlobsRequest.new(repository: @gitaly_repo, blob_pairs: blob_pairs) + gitaly_client_call(@repository.storage, :diff_service, :diff_blobs, request, timeout: GitalyClient.fast_timeout) + end + def commit_deltas(commit) request = Gitaly::CommitDeltaRequest.new(diff_from_parent_request_params(commit)) response = gitaly_client_call(@repository.storage, :diff_service, :commit_delta, request, timeout: GitalyClient.fast_timeout) @@ -251,8 +256,8 @@ def diff_stats(left_commit_sha, right_commit_sha) # else # defaults to :include_merges behavior # ['foo_bar.rb', 'bar_baz.rb'], # - def find_changed_paths(objects, merge_commit_diff_mode: nil) - request = find_changed_paths_request(objects, merge_commit_diff_mode) + def find_changed_paths(objects, merge_commit_diff_mode: nil, find_renames: false) + request = find_changed_paths_request(objects, merge_commit_diff_mode, find_renames) return [] if request.nil? @@ -647,7 +652,7 @@ def call_find_commit(revision) response.commit end - def find_changed_paths_request(objects, merge_commit_diff_mode) + def find_changed_paths_request(objects, merge_commit_diff_mode, find_renames) diff_mode = MERGE_COMMIT_DIFF_MODES[merge_commit_diff_mode] if Feature.enabled?(:merge_commit_diff_modes) requests = objects.filter_map do |object| @@ -667,7 +672,7 @@ def find_changed_paths_request(objects, merge_commit_diff_mode) return if requests.blank? - Gitaly::FindChangedPathsRequest.new(repository: @gitaly_repo, requests: requests, merge_commit_diff_mode: diff_mode) + Gitaly::FindChangedPathsRequest.new(repository: @gitaly_repo, requests: requests, merge_commit_diff_mode: diff_mode, find_renames: find_renames) end def path_error_message(path_error)