Commit af5faaf0e1e001558302704a421eb01f5e7a26ea
1 parent
8f05fbba
Exists in
master
and in
4 other branches
Move diff parsing to own class. Correctly identify note diff line
Showing
8 changed files
with
99 additions
and
64 deletions
Show diff stats
app/helpers/commits_helper.rb
... | ... | @@ -15,63 +15,9 @@ module CommitsHelper |
15 | 15 | commit_person_link(commit, options.merge(source: :committer)) |
16 | 16 | end |
17 | 17 | |
18 | - def identification_type(line) | |
19 | - if line[0] == "+" | |
20 | - "new" | |
21 | - elsif line[0] == "-" | |
22 | - "old" | |
23 | - else | |
24 | - nil | |
25 | - end | |
26 | - end | |
27 | - | |
28 | - def build_line_anchor(diff, line_new, line_old) | |
29 | - "#{hexdigest(diff.new_path)}_#{line_old}_#{line_new}" | |
30 | - end | |
31 | - | |
32 | 18 | def each_diff_line(diff, index) |
33 | - diff_arr = diff.diff.lines.to_a | |
34 | - | |
35 | - line_old = 1 | |
36 | - line_new = 1 | |
37 | - type = nil | |
38 | - | |
39 | - lines_arr = ::Gitlab::InlineDiff.processing diff_arr | |
40 | - lines_arr.each do |line| | |
41 | - raw_line = line.dup | |
42 | - | |
43 | - next if line.match(/^\-\-\- \/dev\/null/) | |
44 | - next if line.match(/^\+\+\+ \/dev\/null/) | |
45 | - next if line.match(/^\-\-\- a/) | |
46 | - next if line.match(/^\+\+\+ b/) | |
47 | - | |
48 | - full_line = html_escape(line.gsub(/\n/, '')) | |
49 | - full_line = ::Gitlab::InlineDiff.replace_markers full_line | |
50 | - | |
51 | - if line.match(/^@@ -/) | |
52 | - type = "match" | |
53 | - | |
54 | - line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0 | |
55 | - line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0 | |
56 | - | |
57 | - next if line_old == 1 && line_new == 1 #top of file | |
58 | - yield(full_line, type, nil, nil, nil) | |
59 | - next | |
60 | - else | |
61 | - type = identification_type(line) | |
62 | - line_code = build_line_anchor(diff, line_new, line_old) | |
63 | - yield(full_line, type, line_code, line_new, line_old, raw_line) | |
64 | - end | |
65 | - | |
66 | - | |
67 | - if line[0] == "+" | |
68 | - line_new += 1 | |
69 | - elsif line[0] == "-" | |
70 | - line_old += 1 | |
71 | - else | |
72 | - line_new += 1 | |
73 | - line_old += 1 | |
74 | - end | |
19 | + Gitlab::DiffParser.new(diff).each do |full_line, type, line_code, line_new, line_old| | |
20 | + yield(full_line, type, line_code, line_new, line_old) | |
75 | 21 | end |
76 | 22 | end |
77 | 23 | ... | ... |
app/models/note.rb
... | ... | @@ -51,7 +51,7 @@ class Note < ActiveRecord::Base |
51 | 51 | scope :inc_author, ->{ includes(:author) } |
52 | 52 | |
53 | 53 | serialize :st_diff |
54 | - before_create :set_diff, if: ->(n) { n.noteable_type == 'MergeRequest' && n.line_code.present? } | |
54 | + before_create :set_diff, if: ->(n) { n.line_code.present? } | |
55 | 55 | |
56 | 56 | def self.create_status_change_note(noteable, author, status) |
57 | 57 | create({ |
... | ... | @@ -81,7 +81,7 @@ class Note < ActiveRecord::Base |
81 | 81 | def set_diff |
82 | 82 | # First lets find notes with same diff |
83 | 83 | # before iterating over all mr diffs |
84 | - diff = self.noteable.notes.where(line_code: self.line_code).last.try(:diff) | |
84 | + diff = Note.where(noteable_id: self.noteable_id, noteable_type: self.noteable_type, line_code: self.line_code).last.try(:diff) | |
85 | 85 | diff ||= find_diff |
86 | 86 | |
87 | 87 | self.st_diff = diff.to_hash if diff |
... | ... | @@ -91,6 +91,12 @@ class Note < ActiveRecord::Base |
91 | 91 | @diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map) |
92 | 92 | end |
93 | 93 | |
94 | + def active? | |
95 | + # TODO: determine if discussion is outdated | |
96 | + # according to recent MR diff or not | |
97 | + true | |
98 | + end | |
99 | + | |
94 | 100 | def diff_file_index |
95 | 101 | line_code.split('_')[0] |
96 | 102 | end |
... | ... | @@ -108,10 +114,15 @@ class Note < ActiveRecord::Base |
108 | 114 | end |
109 | 115 | |
110 | 116 | def diff_line |
117 | + return @diff_line if @diff_line | |
118 | + | |
111 | 119 | if diff |
112 | - @diff_line ||= diff.diff.lines.select { |line| line =~ /\A\+/ }[diff_new_line] || | |
113 | - diff.diff.lines.select { |line| line =~ /\A\-/ }[diff_old_line] | |
120 | + Gitlab::DiffParser.new(diff).each do |full_line, type, line_code, line_new, line_old| | |
121 | + @diff_line = full_line if line_code == self.line_code | |
122 | + end | |
114 | 123 | end |
124 | + | |
125 | + @diff_line | |
115 | 126 | end |
116 | 127 | |
117 | 128 | def discussion_id | ... | ... |
app/views/projects/commits/_text_file.html.haml
... | ... | @@ -20,4 +20,4 @@ |
20 | 20 | - if @reply_allowed |
21 | 21 | - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) |
22 | 22 | - unless comments.empty? |
23 | - = render "projects/notes/diff_notes_with_reply", notes: comments, raw_line: raw_line | |
23 | + = render "projects/notes/diff_notes_with_reply", notes: comments, line: line | ... | ... |
app/views/projects/notes/_diff_notes_with_reply.html.haml
app/views/projects/notes/_discussion.html.haml
doc/update/5.4-to-6.0.md
... | ... | @@ -61,6 +61,7 @@ sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production |
61 | 61 | sudo -u git -H bundle exec rake migrate_groups RAILS_ENV=production |
62 | 62 | sudo -u git -H bundle exec rake migrate_global_projects RAILS_ENV=production |
63 | 63 | sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production |
64 | +sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production | |
64 | 65 | |
65 | 66 | ``` |
66 | 67 | ... | ... |
... | ... | @@ -0,0 +1,77 @@ |
1 | +module Gitlab | |
2 | + class DiffParser | |
3 | + include Enumerable | |
4 | + | |
5 | + attr_reader :lines, :new_path | |
6 | + | |
7 | + def initialize(diff) | |
8 | + @lines = diff.diff.lines.to_a | |
9 | + @new_path = diff.new_path | |
10 | + end | |
11 | + | |
12 | + def each | |
13 | + line_old = 1 | |
14 | + line_new = 1 | |
15 | + type = nil | |
16 | + | |
17 | + lines_arr = ::Gitlab::InlineDiff.processing lines | |
18 | + lines_arr.each do |line| | |
19 | + raw_line = line.dup | |
20 | + | |
21 | + next if line.match(/^\-\-\- \/dev\/null/) | |
22 | + next if line.match(/^\+\+\+ \/dev\/null/) | |
23 | + next if line.match(/^\-\-\- a/) | |
24 | + next if line.match(/^\+\+\+ b/) | |
25 | + | |
26 | + full_line = html_escape(line.gsub(/\n/, '')) | |
27 | + full_line = ::Gitlab::InlineDiff.replace_markers full_line | |
28 | + | |
29 | + if line.match(/^@@ -/) | |
30 | + type = "match" | |
31 | + | |
32 | + line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0 | |
33 | + line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0 | |
34 | + | |
35 | + next if line_old == 1 && line_new == 1 #top of file | |
36 | + yield(full_line, type, nil, nil, nil) | |
37 | + next | |
38 | + else | |
39 | + type = identification_type(line) | |
40 | + line_code = generate_line_code(new_path, line_new, line_old) | |
41 | + yield(full_line, type, line_code, line_new, line_old, raw_line) | |
42 | + end | |
43 | + | |
44 | + | |
45 | + if line[0] == "+" | |
46 | + line_new += 1 | |
47 | + elsif line[0] == "-" | |
48 | + line_old += 1 | |
49 | + else | |
50 | + line_new += 1 | |
51 | + line_old += 1 | |
52 | + end | |
53 | + end | |
54 | + end | |
55 | + | |
56 | + private | |
57 | + | |
58 | + def identification_type(line) | |
59 | + if line[0] == "+" | |
60 | + "new" | |
61 | + elsif line[0] == "-" | |
62 | + "old" | |
63 | + else | |
64 | + nil | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + def generate_line_code(path, line_new, line_old) | |
69 | + "#{Digest::SHA1.hexdigest(path)}_#{line_old}_#{line_new}" | |
70 | + end | |
71 | + | |
72 | + def html_escape str | |
73 | + replacements = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' } | |
74 | + str.gsub(/[&"'><]/, replacements) | |
75 | + end | |
76 | + end | |
77 | +end | ... | ... |
lib/tasks/migrate/migrate_inline_notes.rake
1 | 1 | desc "GITLAB | Migrate inline notes" |
2 | 2 | task migrate_inline_notes: :environment do |
3 | - Note.where(noteable_type: 'MergeRequest').find_each(batch_size: 100) do |note| | |
3 | + Note.where('line_code IS NOT NULL').find_each(batch_size: 100) do |note| | |
4 | 4 | begin |
5 | 5 | note.set_diff |
6 | 6 | if note.save | ... | ... |