Commit 8f359ea9 authored by Paco Guzman's avatar Paco Guzman
Browse files

Move to Gitlab::Diff::FileCollection

Instead calling diff_collection.count use diff_collection.size which is cache on the diff_collection
parent 5a39ebb5d0da
......@@ -28,7 +28,7 @@ def show
end
def diff_for_path
render_diff_for_path(SafeDiffs::Commit.new(@commit, diff_options: diff_options))
render_diff_for_path(@commit.diff_file_collection(diff_options))
end
def builds
......@@ -110,7 +110,7 @@ def define_commit_vars
opts = diff_options
opts[:ignore_whitespace_change] = true if params[:format] == 'diff'
@diffs = SafeDiffs::Commit.new(commit, diff_options: opts)
@diffs = commit.diff_file_collection(opts)
@notes_count = commit.notes.count
end
......
......@@ -21,7 +21,7 @@ def show
def diff_for_path
return render_404 unless @compare
render_diff_for_path(SafeDiffs::Compare.new(@compare, project: @project, diff_options: diff_options))
render_diff_for_path(Compare.decorate(@compare, @project).diff_file_collection(diff_options: diff_options))
end
def create
......@@ -51,7 +51,7 @@ def define_diff_vars
start_sha: @start_commit.try(:sha),
head_sha: @commit.try(:sha)
)
@diffs = SafeDiffs::Compare.new(@compare, project: @project, diff_options: diff_options, diff_refs: diff_refs)
@diffs = Compare.decorate(@compare, @project).diff_file_collection(diff_options: diff_options, diff_refs: diff_refs)
@diff_notes_disabled = true
@grouped_diff_discussions = {}
......
......@@ -85,7 +85,11 @@ def diffs
respond_to do |format|
format.html { define_discussion_vars }
format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } }
format.json do
@diffs = @merge_request.diff_file_collection(diff_options) if @merge_request_diff.collected?
render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") }
end
end
end
......@@ -104,7 +108,7 @@ def diff_for_path
define_commit_vars
render_diff_for_path(SafeDiffs::MergeRequest.new(merge_request, diff_options: diff_options))
render_diff_for_path(@merge_request.diff_file_collection(diff_options))
end
def commits
......@@ -153,10 +157,10 @@ def new
@commit = @merge_request.diff_head_commit
@base_commit = @merge_request.diff_base_commit
if @merge_request.compare
@diffs = SafeDiffs::Compare.new(@merge_request.compare,
project: @merge_request.project,
diff_refs: @merge_request.diff_refs,
diff_options: diff_options)
@diffs = Compare.decorate(@merge_request.compare, @project).diff_file_collection(
diff_options: diff_options,
diff_refs: @merge_request.diff_refs
)
end
@diff_notes_disabled = true
......
......@@ -23,7 +23,7 @@ def diff_view
end
def diff_options
options = SafeDiffs.default_options.merge(
options = Gitlab::Diff::FileCollection.default_options.merge(
ignore_whitespace_change: hide_whitespace?,
no_collapse: expand_all_diffs?
)
......
......@@ -317,6 +317,10 @@ def uri_type(path)
nil
end
def diff_file_collection(diff_options)
Gitlab::Diff::FileCollection::Commit.new(self, diff_options: diff_options)
end
private
def find_author_by_any_email
......
class Compare
delegate :commits, :same, :head, :base, to: :@compare
def self.decorate(compare, project)
if compare.is_a?(Compare)
compare
else
self.new(compare, project)
end
end
def initialize(compare, project)
@compare = compare
@project = project
end
def diff_file_collection(diff_options:, diff_refs: nil)
Gitlab::Diff::FileCollection::Compare.new(@compare,
project: @project,
diff_options: diff_options,
diff_refs: diff_refs)
end
end
......@@ -168,6 +168,10 @@ def diffs(*args)
merge_request_diff ? merge_request_diff.diffs(*args) : compare.diffs(*args)
end
def diff_file_collection(diff_options)
Gitlab::Diff::FileCollection::MergeRequest.new(self, diff_options: diff_options)
end
def diff_size
merge_request_diff.size
end
......
module SafeDiffs
def self.default_options
::Commit.max_diff_options.merge(ignore_whitespace_change: false, no_collapse: false)
end
end
module SafeDiffs
class Base
attr_reader :project, :diff_options, :diff_view, :diff_refs
delegate :count, :real_size, to: :diff_files
def initialize(diffs, project:, diff_options:, diff_refs: nil)
@diffs = diffs
@project = project
@diff_options = diff_options
@diff_refs = diff_refs
end
def diff_files
@diff_files ||= begin
diffs = @diffs.decorate! do |diff|
Gitlab::Diff::File.new(diff, diff_refs: @diff_refs, repository: @project.repository)
end
highlight!(diffs)
diffs
end
end
private
def highlight!(diff_files)
if cacheable?
cache_highlight!(diff_files)
else
diff_files.each { |diff_file| highlight_diff_file!(diff_file) }
end
end
def cacheable?
false
end
def cache_highlight!
raise NotImplementedError
end
def highlight_diff_file_from_cache!(diff_file, cache_diff_lines)
diff_file.diff_lines = cache_diff_lines.map do |line|
Gitlab::Diff::Line.init_from_hash(line)
end
end
def highlight_diff_file!(diff_file)
diff_file.diff_lines = Gitlab::Diff::Highlight.new(diff_file, repository: diff_file.repository).highlight
diff_file.highlighted_diff_lines = diff_file.diff_lines # To be used on parallel diff
diff_file
end
end
end
module SafeDiffs
class Commit < Base
def initialize(commit, diff_options:)
super(commit.diffs(diff_options),
project: commit.project,
diff_options: diff_options,
diff_refs: commit.diff_refs)
end
end
end
module SafeDiffs
class Compare < Base
def initialize(compare, project:, diff_options:, diff_refs: nil)
super(compare.diffs(diff_options),
project: project,
diff_options: diff_options,
diff_refs: diff_refs)
end
end
end
module SafeDiffs
class MergeRequest < Base
def initialize(merge_request, diff_options:)
@merge_request = merge_request
super(merge_request.diffs(diff_options),
project: merge_request.project,
diff_options: diff_options,
diff_refs: merge_request.diff_refs)
end
private
#
# If we find the highlighted diff files lines on the cache we replace existing diff_files lines (no highlighted)
# for the highlighted ones, so we just skip their execution.
# If the highlighted diff files lines are not cached we calculate and cache them.
#
# The content of the cache is and Hash where the key correspond to the file_path and the values are Arrays of
# hashes than represent serialized diff lines.
#
def cache_highlight!(diff_files)
highlighted_cache = Rails.cache.read(cache_key) || {}
highlighted_cache_was_empty = highlighted_cache.empty?
diff_files.each do |diff_file|
file_path = diff_file.file_path
if highlighted_cache[file_path]
highlight_diff_file_from_cache!(diff_file, highlighted_cache[file_path])
else
highlight_diff_file!(diff_file)
highlighted_cache[file_path] = diff_file.diff_lines.map(&:to_hash)
end
end
if highlighted_cache_was_empty
Rails.cache.write(cache_key, highlighted_cache)
end
diff_files
end
def cacheable?
@merge_request.merge_request_diff.present?
end
def cache_key
[@merge_request.merge_request_diff, 'highlighted-safe-diff-files', diff_options]
end
end
end
......@@ -2,7 +2,7 @@ module MergeRequests
class MergeRequestDiffCacheService
def execute(merge_request)
# Executing the iteration we cache all the highlighted diff information
SafeDiffs::MergeRequest.new(merge_request, diff_options: SafeDiffs.default_options).diff_files.to_a
merge_request.diff_file_collection(Gitlab::Diff::FileCollection.default_options).diff_files.to_a
end
end
end
......@@ -75,7 +75,7 @@
- blob = diff_file.blob
- if blob && blob.respond_to?(:text?) && blob_text_viewable?(blob)
%table.code.white
- diff_file.diff_lines.each do |line|
- diff_file.highlighted_diff_lines.each do |line|
= render "projects/diffs/line", line: line, diff_file: diff_file, plain: true
- else
No preview for this file type
......
......@@ -2,7 +2,7 @@
= nav_link(path: 'commit#show') do
= link_to namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Changes
%span.badge= @diffs.count
%span.badge= @diffs.size
= nav_link(path: 'commit#builds') do
= link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Builds
......
......@@ -5,7 +5,7 @@
%table.text-file.code.js-syntax-highlight{ data: diff_view_data, class: too_big ? 'hide' : '' }
- last_line = 0
- diff_file.diff_lines.each do |line|
- diff_file.highlighted_diff_lines.each do |line|
- last_line = line.new_pos
= render "projects/diffs/line", line: line, diff_file: diff_file
......
- if @merge_request_diff.collected?
- diffs = SafeDiffs::MergeRequest.new(@merge_request, diff_options: diff_options)
= render "projects/diffs/diffs", diff_files: diffs.diff_files,
diff_refs: diffs.diff_refs, project: diffs.project
= render "projects/diffs/diffs", diff_files: @diffs.diff_files,
diff_refs: @diffs.diff_refs, project: @diffs.project
- elsif @merge_request_diff.empty?
.nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch}
- else
......
......@@ -142,7 +142,7 @@ def commit_from_id(project, id)
def files_count(commit)
files = "#{commit.diffs.real_size} file"
files += 's' if commit.diffs.count > 1
files += 's' if commit.diffs.size > 1
files
end
......
......@@ -63,7 +63,7 @@ def new_ref
diff_refs.try(:head_sha)
end
attr_writer :diff_lines, :highlighted_diff_lines
attr_writer :highlighted_diff_lines
# Array of Gitlab::Diff::Line objects
def diff_lines
......
module Gitlab
module Diff
module FileCollection
def self.default_options
::Commit.max_diff_options.merge(ignore_whitespace_change: false, no_collapse: false)
end
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment