Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean McGivern <sean@gitlab.com>2016-08-05 15:24:15 +0300
committerFatih Acet <acetfatih@gmail.com>2016-08-12 23:24:48 +0300
commit4952a24f584aea1e8e878f5ca276b2682422fbd4 (patch)
tree69c1bd70a0b7ee92d6316236ef641356210017f9 /lib/gitlab/conflict
parentce7eb4e49279ab56cac992b6743fe77cac578b48 (diff)
Find match line headers by backtracking
This is more efficient for large files than performing a regex match on every single line.
Diffstat (limited to 'lib/gitlab/conflict')
-rw-r--r--lib/gitlab/conflict/file.rb35
1 files changed, 24 insertions, 11 deletions
diff --git a/lib/gitlab/conflict/file.rb b/lib/gitlab/conflict/file.rb
index 3560fae5b09..926b65d46fc 100644
--- a/lib/gitlab/conflict/file.rb
+++ b/lib/gitlab/conflict/file.rb
@@ -18,6 +18,7 @@ module Gitlab
@our_mode = conflict[:ours][:mode]
@merge_request = merge_request
@repository = merge_request.project.repository
+ @match_line_headers = {}
end
# Array of Gitlab::Diff::Line objects
@@ -71,13 +72,6 @@ module Gitlab
def sections
return @sections if @sections
- # Any line beginning with a letter, an underscore, or a dollar can be used in a
- # match line header. Only context sections can contain match lines, as match lines
- # have to exist in both versions of the file.
- candidate_match_headers = lines.map do |line|
- " #{line.text}" if line.text.match(/\A[A-Za-z$_]/) && line.type.nil?
- end
-
chunked_lines = lines.chunk { |line| line.type.nil? }
match_line = nil
@@ -98,7 +92,7 @@ module Gitlab
# Ensure any existing match line has text for all lines up to the last
# line of its context.
- update_match_line_text(match_line, head_lines.last, candidate_match_headers)
+ update_match_line_text(match_line, head_lines.last)
# Insert a new match line after the created gap.
match_line = create_match_line(tail_lines.first)
@@ -128,7 +122,7 @@ module Gitlab
# We want to update the match line's text every time unless we've already
# created a gap and its corresponding match line.
- update_match_line_text(match_line, lines.last, candidate_match_headers) unless section
+ update_match_line_text(match_line, lines.last) unless section
section ||= { conflict: !no_conflict, lines: lines }
section[:id] = line_code(lines.first) unless no_conflict
@@ -144,13 +138,32 @@ module Gitlab
Gitlab::Diff::Line.new('', 'match', line.index, line.old_pos, line.new_pos)
end
+ # Any line beginning with a letter, an underscore, or a dollar can be used in a
+ # match line header. Only context sections can contain match lines, as match lines
+ # have to exist in both versions of the file.
+ def find_match_line_header(index)
+ return @match_line_headers[index] if @match_line_headers.key?(index)
+
+ @match_line_headers[index] = begin
+ if index >= 0
+ line = lines[index]
+
+ if line.type.nil? && line.text.match(/\A[A-Za-z$_]/)
+ " #{line.text}"
+ else
+ find_match_line_header(index - 1)
+ end
+ end
+ end
+ end
+
# Set the match line's text for the current line. A match line takes its start
# position and context header (where present) from itself, and its end position from
# the line passed in.
- def update_match_line_text(match_line, line, headers)
+ def update_match_line_text(match_line, line)
return unless match_line
- header = headers.first(match_line.index).compact.last
+ header = find_match_line_header(match_line.index - 1)
match_line.text = "@@ -#{match_line.old_pos},#{line.old_pos} +#{match_line.new_pos},#{line.new_pos} @@#{header}"
end