summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-09-08 16:25:50 +0300
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2014-09-08 16:25:50 +0300
commit4ef809c77d7f4155709a6d3f0188332c206ba0e0 (patch)
tree99dffb56cf4e7840f3551a0414a56e203625079a /lib
parent205358b1ae71611a04e03789b3bac74bd1052da5 (diff)
downloadgitlab-ce-4ef809c77d7f4155709a6d3f0188332c206ba0e0.tar.gz
Gitlab::Diff classes added
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/diff/file.rb42
-rw-r--r--lib/gitlab/diff/line.rb12
-rw-r--r--lib/gitlab/diff/parser.rb86
3 files changed, 140 insertions, 0 deletions
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
new file mode 100644
index 00000000000..adc78616f64
--- /dev/null
+++ b/lib/gitlab/diff/file.rb
@@ -0,0 +1,42 @@
+module Gitlab
+ module Diff
+ class File
+ attr_reader :diff, :blob
+
+ delegate :new_file, :deleted_file, :renamed_file,
+ :old_path, :new_path, to: :diff, prefix: false
+
+ def initialize(project, commit, diff)
+ @diff = diff
+ @blob = project.repository.blob_for_diff(commit, diff)
+ end
+
+ # Array of Gitlab::DIff::Line objects
+ def diff_lines
+ @lines ||= parser.parse(diff.diff.lines, old_path, new_path)
+ end
+
+ def blob_exists?
+ !@blob.nil?
+ end
+
+ def mode_changed?
+ diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode
+ end
+
+ def parser
+ Gitlab::Diff::Parser.new
+ end
+
+ def next_line(index)
+ diff_lines[index + 1]
+ end
+
+ def prev_line(index)
+ if index > 0
+ diff_lines[index - 1]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
new file mode 100644
index 00000000000..e8b9c980a1a
--- /dev/null
+++ b/lib/gitlab/diff/line.rb
@@ -0,0 +1,12 @@
+module Gitlab
+ module Diff
+ class Line
+ attr_reader :type, :text, :index, :code, :old_pos, :new_pos
+
+ def initialize(text, type, index, old_pos, new_pos, code = nil)
+ @text, @type, @index, @code = text, type, index, code
+ @old_pos, @new_pos = old_pos, new_pos
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
new file mode 100644
index 00000000000..0fd11c69a59
--- /dev/null
+++ b/lib/gitlab/diff/parser.rb
@@ -0,0 +1,86 @@
+module Gitlab
+ module Diff
+ class Parser
+ include Enumerable
+
+ def parse(lines, old_path, new_path)
+ @lines = lines,
+ lines_obj = []
+ line_obj_index = 0
+ line_old = 1
+ line_new = 1
+ type = nil
+
+ lines_arr = ::Gitlab::InlineDiff.processing lines
+
+ lines_arr.each do |line|
+ raw_line = line.dup
+
+ next if filename?(line)
+
+ full_line = html_escape(line.gsub(/\n/, ''))
+ full_line = ::Gitlab::InlineDiff.replace_markers full_line
+
+ if line.match(/^@@ -/)
+ type = "match"
+
+ line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0
+ line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0
+
+ next if line_old == 1 && line_new == 1 #top of file
+ lines_obj << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
+ line_obj_index += 1
+ next
+ else
+ type = identification_type(line)
+ line_code = generate_line_code(new_path, line_new, line_old)
+ lines_obj << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new, line_code)
+ line_obj_index += 1
+ end
+
+
+ if line[0] == "+"
+ line_new += 1
+ elsif line[0] == "-"
+ line_old += 1
+ else
+ line_new += 1
+ line_old += 1
+ end
+ end
+
+ lines_obj
+ end
+
+ def empty?
+ @lines.empty?
+ end
+
+ private
+
+ def filename?(line)
+ line.start_with?('--- /dev/null', '+++ /dev/null', '--- a', '+++ b',
+ '--- /tmp/diffy', '+++ /tmp/diffy')
+ end
+
+ def identification_type(line)
+ if line[0] == "+"
+ "new"
+ elsif line[0] == "-"
+ "old"
+ else
+ nil
+ end
+ end
+
+ def generate_line_code(path, line_new, line_old)
+ "#{Digest::SHA1.hexdigest(path)}_#{line_old}_#{line_new}"
+ end
+
+ def html_escape str
+ replacements = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#39;' }
+ str.gsub(/[&"'><]/, replacements)
+ end
+ end
+ end
+end