2016-06-02 11:05:42 +05:30
|
|
|
class LegacyDiffNote < Note
|
2016-08-24 12:49:21 +05:30
|
|
|
include NoteOnDiff
|
|
|
|
|
2016-06-02 11:05:42 +05:30
|
|
|
serialize :st_diff
|
|
|
|
|
|
|
|
validates :line_code, presence: true, line_code: true
|
|
|
|
|
|
|
|
before_create :set_diff
|
|
|
|
|
|
|
|
class << self
|
|
|
|
def build_discussion_id(noteable_type, noteable_id, line_code, active = true)
|
|
|
|
[super(noteable_type, noteable_id), line_code, active].join("-")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-08-24 12:49:21 +05:30
|
|
|
def legacy_diff_note?
|
2016-06-02 11:05:42 +05:30
|
|
|
true
|
|
|
|
end
|
|
|
|
|
2016-08-24 12:49:21 +05:30
|
|
|
def diff_attributes
|
|
|
|
{ line_code: line_code }
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def discussion_id
|
2016-08-24 12:49:21 +05:30
|
|
|
@discussion_id ||= self.class.build_discussion_id(noteable_type, noteable_id || commit_id, line_code)
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def diff_file_hash
|
|
|
|
line_code.split('_')[0] if line_code
|
|
|
|
end
|
|
|
|
|
|
|
|
def diff
|
|
|
|
@diff ||= Gitlab::Git::Diff.new(st_diff) if st_diff.respond_to?(:map)
|
|
|
|
end
|
|
|
|
|
2016-08-24 12:49:21 +05:30
|
|
|
def diff_file
|
|
|
|
@diff_file ||= Gitlab::Diff::File.new(diff, repository: self.project.repository) if diff
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
def diff_line
|
2016-08-24 12:49:21 +05:30
|
|
|
@diff_line ||= diff_file.line_for_line_code(self.line_code) if diff_file
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
2016-08-24 12:49:21 +05:30
|
|
|
def for_line?(line)
|
|
|
|
!line.meta? && diff_file.line_code(line) == self.line_code
|
2016-06-02 11:05:42 +05:30
|
|
|
end
|
|
|
|
|
|
|
|
# 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?
|
|
|
|
return @active if defined?(@active)
|
|
|
|
return true if for_commit?
|
2016-08-24 12:49:21 +05:30
|
|
|
return true unless diff_line
|
2016-06-02 11:05:42 +05:30
|
|
|
return false unless noteable
|
|
|
|
|
|
|
|
noteable_diff = find_noteable_diff
|
|
|
|
|
|
|
|
if noteable_diff
|
|
|
|
parsed_lines = Gitlab::Diff::Parser.new.parse(noteable_diff.diff.each_line)
|
|
|
|
|
2016-08-24 12:49:21 +05:30
|
|
|
@active = parsed_lines.any? { |line_obj| line_obj.text == diff_line.text }
|
2016-06-02 11:05:42 +05:30
|
|
|
else
|
|
|
|
@active = false
|
|
|
|
end
|
|
|
|
|
|
|
|
@active
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def find_diff
|
|
|
|
return nil unless noteable
|
|
|
|
return @diff if defined?(@diff)
|
|
|
|
|
|
|
|
@diff = noteable.diffs(Commit.max_diff_options).find do |d|
|
|
|
|
d.new_path && Digest::SHA1.hexdigest(d.new_path) == diff_file_hash
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
self.st_diff = diff.to_hash if diff
|
|
|
|
end
|
|
|
|
|
|
|
|
def diff_for_line_code
|
|
|
|
attributes = {
|
|
|
|
noteable_type: noteable_type,
|
|
|
|
line_code: line_code
|
|
|
|
}
|
|
|
|
|
|
|
|
if for_commit?
|
|
|
|
attributes[:commit_id] = commit_id
|
|
|
|
else
|
|
|
|
attributes[:noteable_id] = noteable_id
|
|
|
|
end
|
|
|
|
|
|
|
|
self.class.where(attributes).last.try(:diff)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Find the diff on noteable that matches our own
|
|
|
|
def find_noteable_diff
|
|
|
|
diffs = noteable.diffs(Commit.max_diff_options)
|
|
|
|
diffs.find { |d| d.new_path == self.diff.new_path }
|
|
|
|
end
|
|
|
|
end
|