diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 21:18:33 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-16 21:18:33 +0300 |
commit | f64a639bcfa1fc2bc89ca7db268f594306edfd7c (patch) | |
tree | a2c3c2ebcc3b45e596949db485d6ed18ffaacfa1 /lib/gitlab/diff | |
parent | bfbc3e0d6583ea1a91f627528bedc3d65ba4b10f (diff) |
Add latest changes from gitlab-org/gitlab@13-10-stable-eev13.10.0-rc40
Diffstat (limited to 'lib/gitlab/diff')
-rw-r--r-- | lib/gitlab/diff/char_diff.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/diff/highlight.rb | 8 | ||||
-rw-r--r-- | lib/gitlab/diff/highlight_cache.rb | 18 | ||||
-rw-r--r-- | lib/gitlab/diff/inline_diff.rb | 100 | ||||
-rw-r--r-- | lib/gitlab/diff/inline_diff_markdown_marker.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/diff/inline_diff_marker.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/diff/pair_selector.rb | 58 |
7 files changed, 84 insertions, 112 deletions
diff --git a/lib/gitlab/diff/char_diff.rb b/lib/gitlab/diff/char_diff.rb index c8bb39e9f5d..1b3af8f75ca 100644 --- a/lib/gitlab/diff/char_diff.rb +++ b/lib/gitlab/diff/char_diff.rb @@ -32,12 +32,12 @@ module Gitlab end if action == :delete - old_diffs << (old_pointer..(old_pointer + content_size - 1)) + old_diffs << MarkerRange.new(old_pointer, old_pointer + content_size - 1, mode: MarkerRange::DELETION) old_pointer += content_size end if action == :insert - new_diffs << (new_pointer..(new_pointer + content_size - 1)) + new_diffs << MarkerRange.new(new_pointer, new_pointer + content_size - 1, mode: MarkerRange::ADDITION) new_pointer += content_size end end diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 035084d4861..baa46e7e306 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -31,6 +31,12 @@ module Gitlab if line_inline_diffs = inline_diffs[i] begin + # MarkerRange objects are converted to Ranges to keep the previous behavior + # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/324068 + if Feature.disabled?(:introduce_marker_ranges, project, default_enabled: :yaml) + line_inline_diffs = line_inline_diffs.map { |marker_range| marker_range.to_range } + end + rich_line = InlineDiffMarker.new(diff_line.text, rich_line).mark(line_inline_diffs) # This should only happen when the encoding of the diff doesn't # match the blob, which is a bug. But we shouldn't fail to render @@ -67,7 +73,7 @@ module Gitlab end def inline_diffs - @inline_diffs ||= InlineDiff.for_lines(@raw_lines, project: project) + @inline_diffs ||= InlineDiff.for_lines(@raw_lines) end def old_lines diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb index 7932cd2a837..c5e9bfdc321 100644 --- a/lib/gitlab/diff/highlight_cache.rb +++ b/lib/gitlab/diff/highlight_cache.rb @@ -7,8 +7,7 @@ module Gitlab include Gitlab::Utils::StrongMemoize EXPIRATION = 1.week - VERSION = 1 - NEXT_VERSION = 2 + VERSION = 2 delegate :diffable, to: :@diff_collection delegate :diff_options, to: :@diff_collection @@ -70,20 +69,17 @@ module Gitlab def key strong_memoize(:redis_key) do - ['highlighted-diff-files', diffable.cache_key, version, diff_options].join(":") + [ + 'highlighted-diff-files', + diffable.cache_key, VERSION, + diff_options, + Feature.enabled?(:introduce_marker_ranges, diffable.project, default_enabled: :yaml) + ].join(":") end end private - def version - if Feature.enabled?(:improved_merge_diff_highlighting, diffable.project, default_enabled: :yaml) - NEXT_VERSION - else - VERSION - end - end - def set_highlighted_diff_lines(diff_file, content) diff_file.highlighted_diff_lines = content.map do |line| Gitlab::Diff::Line.safe_init_from_hash(line) diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb index cf769262958..dd73e4d6c15 100644 --- a/lib/gitlab/diff/inline_diff.rb +++ b/lib/gitlab/diff/inline_diff.rb @@ -3,22 +3,6 @@ module Gitlab module Diff class InlineDiff - # Regex to find a run of deleted lines followed by the same number of added lines - LINE_PAIRS_PATTERN = %r{ - # Runs start at the beginning of the string (the first line) or after a space (for an unchanged line) - (?:\A|\s) - - # This matches a number of `-`s followed by the same number of `+`s through recursion - (?<del_ins> - - - \g<del_ins>? - \+ - ) - - # Runs end at the end of the string (the last line) or before a space (for an unchanged line) - (?=\s|\z) - }x.freeze - attr_accessor :old_line, :new_line, :offset def initialize(old_line, new_line, offset: 0) @@ -27,28 +11,24 @@ module Gitlab @offset = offset end - def inline_diffs(project: nil) + def inline_diffs # Skip inline diff if empty line was replaced with content return if old_line == "" - if Feature.enabled?(:improved_merge_diff_highlighting, project, default_enabled: :yaml) - CharDiff.new(old_line, new_line).changed_ranges(offset: offset) - else - deprecated_diff - end + CharDiff.new(old_line, new_line).changed_ranges(offset: offset) end class << self - def for_lines(lines, project: nil) - changed_line_pairs = find_changed_line_pairs(lines) + def for_lines(lines) + pair_selector = Gitlab::Diff::PairSelector.new(lines) inline_diffs = [] - changed_line_pairs.each do |old_index, new_index| + pair_selector.each do |old_index, new_index| old_line = lines[old_index] new_line = lines[new_index] - old_diffs, new_diffs = new(old_line, new_line, offset: 1).inline_diffs(project: project) + old_diffs, new_diffs = new(old_line, new_line, offset: 1).inline_diffs inline_diffs[old_index] = old_diffs inline_diffs[new_index] = new_diffs @@ -56,74 +36,6 @@ module Gitlab inline_diffs end - - private - - # Finds pairs of old/new line pairs that represent the same line that changed - # rubocop: disable CodeReuse/ActiveRecord - def find_changed_line_pairs(lines) - # Prefixes of all diff lines, indicating their types - # For example: `" - + -+ ---+++ --+ -++"` - line_prefixes = lines.each_with_object(+"") { |line, s| s << (line[0] || ' ') }.gsub(/[^ +-]/, ' ') - - changed_line_pairs = [] - line_prefixes.scan(LINE_PAIRS_PATTERN) do - # For `"---+++"`, `begin_index == 0`, `end_index == 6` - begin_index, end_index = Regexp.last_match.offset(:del_ins) - - # For `"---+++"`, `changed_line_count == 3` - changed_line_count = (end_index - begin_index) / 2 - - halfway_index = begin_index + changed_line_count - (begin_index...halfway_index).each do |i| - # For `"---+++"`, index 1 maps to 1 + 3 = 4 - changed_line_pairs << [i, i + changed_line_count] - end - end - - changed_line_pairs - end - # rubocop: enable CodeReuse/ActiveRecord - end - - private - - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/299884 - def deprecated_diff - lcp = longest_common_prefix(old_line, new_line) - lcs = longest_common_suffix(old_line[lcp..-1], new_line[lcp..-1]) - - lcp += offset - old_length = old_line.length + offset - new_length = new_line.length + offset - - old_diff_range = lcp..(old_length - lcs - 1) - new_diff_range = lcp..(new_length - lcs - 1) - - old_diffs = [old_diff_range] if old_diff_range.begin <= old_diff_range.end - new_diffs = [new_diff_range] if new_diff_range.begin <= new_diff_range.end - - [old_diffs, new_diffs] - end - - def longest_common_prefix(a, b) # rubocop:disable Naming/UncommunicativeMethodParamName - max_length = [a.length, b.length].max - - length = 0 - (0..max_length - 1).each do |pos| - old_char = a[pos] - new_char = b[pos] - - break if old_char != new_char - - length += 1 - end - - length - end - - def longest_common_suffix(a, b) # rubocop:disable Naming/UncommunicativeMethodParamName - longest_common_prefix(a.reverse, b.reverse) end end end diff --git a/lib/gitlab/diff/inline_diff_markdown_marker.rb b/lib/gitlab/diff/inline_diff_markdown_marker.rb index 3c536c43a9e..d8d596ebce7 100644 --- a/lib/gitlab/diff/inline_diff_markdown_marker.rb +++ b/lib/gitlab/diff/inline_diff_markdown_marker.rb @@ -8,8 +8,8 @@ module Gitlab deletion: "-" }.freeze - def mark(line_inline_diffs, mode: nil) - super(line_inline_diffs) do |text, left:, right:| + def mark(line_inline_diffs) + super(line_inline_diffs) do |text, left:, right:, mode:| symbol = MARKDOWN_SYMBOLS[mode] "{#{symbol}#{text}#{symbol}}" end diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb index 29dff699ba5..c8cc1c0e649 100644 --- a/lib/gitlab/diff/inline_diff_marker.rb +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -7,8 +7,8 @@ module Gitlab super(line, rich_line || line) end - def mark(line_inline_diffs, mode: nil) - super(line_inline_diffs) do |text, left:, right:| + def mark(line_inline_diffs) + super(line_inline_diffs) do |text, left:, right:, mode:| %{<span class="#{html_class_names(left, right, mode)}">#{text}</span>}.html_safe end end diff --git a/lib/gitlab/diff/pair_selector.rb b/lib/gitlab/diff/pair_selector.rb new file mode 100644 index 00000000000..2e5ee3a7363 --- /dev/null +++ b/lib/gitlab/diff/pair_selector.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Gitlab + module Diff + class PairSelector + include Enumerable + + # Regex to find a run of deleted lines followed by the same number of added lines + # rubocop: disable Lint/MixedRegexpCaptureTypes + LINE_PAIRS_PATTERN = %r{ + # Runs start at the beginning of the string (the first line) or after a space (for an unchanged line) + (?:\A|\s) + + # This matches a number of `-`s followed by the same number of `+`s through recursion + (?<del_ins> + - + \g<del_ins>? + \+ + ) + + # Runs end at the end of the string (the last line) or before a space (for an unchanged line) + (?=\s|\z) + }x.freeze + # rubocop: enable Lint/MixedRegexpCaptureTypes + + def initialize(lines) + @lines = lines + end + + # Finds pairs of old/new line pairs that represent the same line that changed + # rubocop: disable CodeReuse/ActiveRecord + def each + # Prefixes of all diff lines, indicating their types + # For example: `" - + -+ ---+++ --+ -++"` + line_prefixes = lines.each_with_object(+"") { |line, s| s << (line[0] || ' ') }.gsub(/[^ +-]/, ' ') + + line_prefixes.scan(LINE_PAIRS_PATTERN) do + # For `"---+++"`, `begin_index == 0`, `end_index == 6` + begin_index, end_index = Regexp.last_match.offset(:del_ins) + + # For `"---+++"`, `changed_line_count == 3` + changed_line_count = (end_index - begin_index) / 2 + + halfway_index = begin_index + changed_line_count + (begin_index...halfway_index).each do |i| + # For `"---+++"`, index 1 maps to 1 + 3 = 4 + yield [i, i + changed_line_count] + end + end + end + # rubocop: enable CodeReuse/ActiveRecord + + private + + attr_reader :lines + end + end +end |