gitlab-org--gitlab-foss/app/models/legacy_diff_note.rb

120 lines
3 KiB
Ruby
Raw Normal View History

2017-04-04 18:27:23 -04:00
# A note on merge request or commit diffs, using the legacy implementation.
#
2017-04-04 18:27:23 -04:00
# All new diff notes are of the type `DiffNote`, but any diff notes created
# before the introduction of the new implementation still use `LegacyDiffNote`.
#
# A note of this type is never resolvable.
2016-05-10 18:41:46 -04:00
class LegacyDiffNote < Note
include NoteOnDiff
serialize :st_diff # rubocop:disable Cop/ActiverecordSerialize
2016-05-10 18:41:46 -04:00
validates :line_code, presence: true, line_code: true
before_create :set_diff
def discussion_class(*)
LegacyDiffDiscussion
2016-05-10 18:41:46 -04:00
end
def project_repository
if RequestStore.active?
RequestStore.fetch("project:#{project_id}:repository") { self.project.repository }
else
self.project.repository
end
end
2016-05-13 15:53:31 -04:00
def diff_file_hash
line_code.split('_')[0] if line_code
2016-05-10 18:41:46 -04:00
end
def diff
@diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map)
end
def diff_file
@diff_file ||= Gitlab::Diff::File.new(diff, repository: project_repository) if diff
2016-05-13 15:53:31 -04:00
end
def diff_line
@diff_line ||= diff_file.line_for_line_code(self.line_code) if diff_file
2016-05-13 15:53:31 -04:00
end
def for_line?(line)
!line.meta? && diff_file.line_code(line) == self.line_code
2016-05-10 18:41:46 -04:00
end
def original_line_code
self.line_code
end
2016-05-10 18:41:46 -04:00
# Check if this note is part of an "active" discussion
#
# This will always return true for anything except MergeRequest noteables,
# which have special logic.
#
# If the note's current diff cannot be matched in the MergeRequest's current
# diff, it's considered inactive.
def active?(diff_refs = nil)
2016-05-13 15:53:31 -04:00
return @active if defined?(@active)
2016-05-10 18:41:46 -04:00
return true if for_commit?
return true unless diff_line
2016-05-10 18:41:46 -04:00
return false unless noteable
return false if diff_refs && diff_refs != noteable.diff_refs
2016-05-10 18:41:46 -04:00
noteable_diff = find_noteable_diff
if noteable_diff
parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line)
@active = parsed_lines.any? { |line_obj| line_obj.text == diff_line.text }
2016-05-10 18:41:46 -04:00
else
@active = false
end
@active
end
2016-05-13 15:53:31 -04:00
private
2016-05-10 18:41:46 -04:00
2016-05-13 15:53:31 -04:00
def find_diff
return nil unless noteable
return @diff if defined?(@diff)
2016-05-10 18:41:46 -04:00
@diff = noteable.raw_diffs(Commit.max_diff_options).find do |d|
2016-05-13 15:53:31 -04:00
d.new_path && Digest::SHA1.hexdigest(d.new_path) == diff_file_hash
2016-05-10 18:41:46 -04:00
end
end
2016-05-13 15:53:31 -04:00
def set_diff
# First lets find notes with same diff
# before iterating over all mr diffs
diff = diff_for_line_code unless for_merge_request?
diff ||= find_diff
2016-05-10 18:41:46 -04:00
2016-05-13 15:53:31 -04:00
self.st_diff = diff.to_hash if diff
2016-05-10 18:41:46 -04:00
end
2016-05-13 15:53:31 -04:00
def diff_for_line_code
attributes = {
noteable_type: noteable_type,
line_code: line_code
}
2016-05-10 18:41:46 -04:00
2016-05-13 15:53:31 -04:00
if for_commit?
attributes[:commit_id] = commit_id
else
attributes[:noteable_id] = noteable_id
2016-05-10 18:41:46 -04:00
end
2016-05-13 15:53:31 -04:00
self.class.where(attributes).last.try(:diff)
2016-05-10 18:41:46 -04:00
end
# Find the diff on noteable that matches our own
def find_noteable_diff
diffs = noteable.raw_diffs(Commit.max_diff_options)
2016-05-10 18:41:46 -04:00
diffs.find { |d| d.new_path == self.diff.new_path }
end
end