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 | ... | ... |