summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2016-06-20 19:17:25 +0200
committerDouwe Maan <douwe@selenight.nl>2016-07-06 18:50:59 -0400
commit9abcc0a98f76984fa843eb0db3cf66bc1107e3ed (patch)
treebe92aa8d64a9c0a358e85cff71cb18039eeaacff
parenta27462a5c6da0182f6b3a55c9417e6405f2c0415 (diff)
downloadgitlab-ce-9abcc0a98f76984fa843eb0db3cf66bc1107e3ed.tar.gz
Add Gitlab::Git::Position
-rw-r--r--lib/gitlab/diff/file.rb32
-rw-r--r--lib/gitlab/diff/position.rb150
2 files changed, 182 insertions, 0 deletions
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index c73208329d5..3941e963c03 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -13,6 +13,20 @@ module Gitlab
@diff_refs = diff_refs
end
+ def position(line)
+ return unless diff_refs
+
+ Position.new(
+ old_path: old_path,
+ new_path: new_path,
+ old_line: line.old_line,
+ new_line: line.new_line,
+ base_sha: diff_refs.base_sha,
+ start_sha: diff_refs.start_sha,
+ head_sha: diff_refs.head_sha
+ )
+ end
+
def line_code(line)
return if line.meta?
@@ -23,6 +37,20 @@ module Gitlab
diff_lines.find { |line| line_code(line) == code }
end
+ def line_for_position(pos)
+ diff_lines.find { |line| position(line) == pos }
+ end
+
+ def position_for_line_code(code)
+ line = line_for_line_code(code)
+ position(line) if line
+ end
+
+ def line_code_for_position(pos)
+ line = line_for_position(pos)
+ line_code(line) if line
+ end
+
def content_commit
return unless diff_refs
@@ -66,6 +94,10 @@ module Gitlab
diff_lines[index - 1] if index > 0
end
+ def paths
+ [old_path, new_path].compact
+ end
+
def file_path
new_path.presence || old_path
end
diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb
new file mode 100644
index 00000000000..4eff71859c3
--- /dev/null
+++ b/lib/gitlab/diff/position.rb
@@ -0,0 +1,150 @@
+# Defines a specific location, identified by paths and line numbers,
+# within a specific diff, identified by start, head and base commit ids.
+module Gitlab
+ module Diff
+ class Position
+ attr_reader :old_path
+ attr_reader :new_path
+ attr_reader :old_line
+ attr_reader :new_line
+ attr_reader :base_sha
+ attr_reader :start_sha
+ attr_reader :head_sha
+
+ def initialize(attrs = {})
+ @old_path = attrs[:old_path]
+ @new_path = attrs[:new_path]
+ @old_line = attrs[:old_line]
+ @new_line = attrs[:new_line]
+
+ if attrs[:diff_refs]
+ @base_sha = attrs[:diff_refs].base_sha
+ @start_sha = attrs[:diff_refs].start_sha
+ @head_sha = attrs[:diff_refs].head_sha
+ else
+ @base_sha = attrs[:base_sha]
+ @start_sha = attrs[:start_sha]
+ @head_sha = attrs[:head_sha]
+ end
+ end
+
+ def init_with(coder)
+ initialize(coder['attributes'])
+
+ self
+ end
+
+ def encode_with(coder)
+ coder['attributes'] = self.to_h
+ end
+
+ def key
+ @key ||= [base_sha, start_sha, head_sha, Digest::SHA1.hexdigest(old_path || ""), Digest::SHA1.hexdigest(new_path || ""), old_line, new_line]
+ end
+
+ def ==(other)
+ other.is_a?(self.class) && key == other.key
+ end
+
+ def to_h
+ {
+ old_path: old_path,
+ new_path: new_path,
+ old_line: old_line,
+ new_line: new_line,
+ base_sha: base_sha,
+ start_sha: start_sha,
+ head_sha: head_sha
+ }
+ end
+
+ def inspect
+ %(#<#{self.class}:#{object_id} #{to_h}>)
+ end
+
+ def complete?
+ file_path.present? &&
+ (old_line || new_line) &&
+ diff_refs.complete?
+ end
+
+ def to_json
+ JSON.generate(self.to_h)
+ end
+
+ def type
+ if old_line && new_line
+ nil
+ elsif new_line
+ 'new'
+ else
+ 'old'
+ end
+ end
+
+ def unchanged?
+ type.nil?
+ end
+
+ def added?
+ type == 'new'
+ end
+
+ def removed?
+ type == 'old'
+ end
+
+ def paths
+ [old_path, new_path].compact.uniq
+ end
+
+ def file_path
+ new_path.presence || old_path
+ end
+
+ def diff_refs
+ @diff_refs ||= DiffRefs.new(base_sha: base_sha, start_sha: start_sha, head_sha: head_sha)
+ end
+
+ def diff_file(repository)
+ @diff_file ||= begin
+ if RequestStore.active?
+ key = {
+ project_id: repository.project.id,
+ start_sha: start_sha,
+ head_sha: head_sha,
+ path: file_path
+ }
+
+ RequestStore.fetch(key) { find_diff_file(repository) }
+ else
+ find_diff_file(repository)
+ end
+ end
+ end
+
+ def diff_line(repository)
+ @diff_line ||= diff_file(repository).line_for_position(self)
+ end
+
+ def line_code(repository)
+ @line_code ||= diff_file(repository).line_code_for_position(self)
+ end
+
+ private
+
+ def find_diff_file(repository)
+ diffs = Gitlab::Git::Compare.new(
+ repository.raw_repository,
+ start_sha,
+ head_sha
+ ).diffs(paths: paths)
+
+ diff = diffs.first
+ return unless diff
+
+ Gitlab::Diff::File.new(diff, repository: repository, diff_refs: diff_refs)
+ end
+ end
+ end
+end