summaryrefslogtreecommitdiff
path: root/lib/gitlab/diff
diff options
context:
space:
mode:
authorOswaldo Ferreira <oswaldo@gitlab.com>2018-12-16 14:00:43 -0200
committerOswaldo Ferreira <oswaldo@gitlab.com>2018-12-21 16:59:21 -0200
commit7cf4947792647fd985c38ebf37c27989fd5a1632 (patch)
tree46bef7a798e8749e815f594a918266c8d9f9dd61 /lib/gitlab/diff
parenta9049532a271117983430d2d80b8ad61879ecf7a (diff)
downloadgitlab-ce-7cf4947792647fd985c38ebf37c27989fd5a1632.tar.gz
Cache diff highlight in discussions
This commit handles note diffs caching, which considerably improves the performance on merge requests with lots of comments. Important to note that the caching approach taken here is different from `Gitlab::Diff::HighlightCache`. We do not reset the whole cache when a new push is sent or anything else. That's because discussions diffs are persisted and do not change.
Diffstat (limited to 'lib/gitlab/diff')
-rw-r--r--lib/gitlab/diff/file.rb26
1 files changed, 23 insertions, 3 deletions
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index b5fc8d364c8..bcbded6be9a 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -3,7 +3,7 @@
module Gitlab
module Diff
class File
- attr_reader :diff, :repository, :diff_refs, :fallback_diff_refs
+ attr_reader :diff, :repository, :diff_refs, :fallback_diff_refs, :unique_identifier
delegate :new_file?, :deleted_file?, :renamed_file?,
:old_path, :new_path, :a_mode, :b_mode, :mode_changed?,
@@ -22,12 +22,20 @@ module Gitlab
DiffViewer::Image
].sort_by { |v| v.binary? ? 0 : 1 }.freeze
- def initialize(diff, repository:, diff_refs: nil, fallback_diff_refs: nil, stats: nil)
+ def initialize(
+ diff,
+ repository:,
+ diff_refs: nil,
+ fallback_diff_refs: nil,
+ stats: nil,
+ unique_identifier: nil)
+
@diff = diff
@stats = stats
@repository = repository
@diff_refs = diff_refs
@fallback_diff_refs = fallback_diff_refs
+ @unique_identifier = unique_identifier
@unfolded = false
# Ensure items are collected in the the batch
@@ -67,7 +75,15 @@ module Gitlab
def line_for_position(pos)
return nil unless pos.position_type == 'text'
- diff_lines.find { |line| line.old_line == pos.old_line && line.new_line == pos.new_line }
+ # This method is normally used to find which line the diff was
+ # commented on, and in this context, it's normally the raw diff persisted
+ # at `note_diff_files`, which is a fraction of the entire diff
+ # (it goes from the first line, to the commented line, or
+ # one line below). Therefore it's more performant to fetch
+ # from bottom to top instead of the other way around.
+ diff_lines
+ .reverse_each
+ .find { |line| line.old_line == pos.old_line && line.new_line == pos.new_line }
end
def position_for_line_code(code)
@@ -166,6 +182,10 @@ module Gitlab
@unfolded
end
+ def highlight_loaded?
+ @highlighted_diff_lines.present?
+ end
+
def highlighted_diff_lines
@highlighted_diff_lines ||=
Gitlab::Diff::Highlight.new(self, repository: self.repository).highlight