git文件比较功能
This commit is contained in:
parent
c2629ebdc0
commit
a2439f0a14
4782
db/schema.rb
4782
db/schema.rb
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,4 @@
|
|||
module Trustie
|
||||
module Gitlab
|
||||
module Diff
|
||||
class File
|
||||
|
@ -20,7 +21,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def parser
|
||||
Gitlab::Diff::Parser.new
|
||||
Parser.new
|
||||
end
|
||||
|
||||
def raw_diff
|
||||
|
@ -55,3 +56,4 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,4 @@
|
|||
module Trustie
|
||||
module Gitlab
|
||||
module Diff
|
||||
class Line
|
||||
|
@ -18,3 +19,4 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,4 @@
|
|||
module Trustie
|
||||
module Gitlab
|
||||
module Diff
|
||||
class LineCode
|
||||
|
@ -7,3 +8,5 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
module Trustie
|
||||
module Gitlab
|
||||
module Diff
|
||||
class Parser
|
||||
|
@ -11,13 +12,13 @@ module Gitlab
|
|||
line_new = 1
|
||||
type = nil
|
||||
|
||||
lines_arr = ::Gitlab::InlineDiff.processing lines
|
||||
lines_arr = InlineDiff.processing lines
|
||||
|
||||
lines_arr.each do |line|
|
||||
next if filename?(line)
|
||||
|
||||
full_line = html_escape(line.gsub(/\n/, ''))
|
||||
full_line = ::Gitlab::InlineDiff.replace_markers full_line
|
||||
full_line = InlineDiff.replace_markers full_line
|
||||
|
||||
if line.match(/^@@ -/)
|
||||
type = "match"
|
||||
|
@ -26,12 +27,12 @@ module Gitlab
|
|||
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)
|
||||
lines_obj << Line.new(full_line, type, line_obj_index, line_old, line_new)
|
||||
line_obj_index += 1
|
||||
next
|
||||
else
|
||||
type = identification_type(line)
|
||||
lines_obj << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new)
|
||||
lines_obj << Line.new(full_line, type, line_obj_index, line_old, line_new)
|
||||
line_obj_index += 1
|
||||
end
|
||||
|
||||
|
@ -77,3 +78,4 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,103 +1,105 @@
|
|||
module Gitlab
|
||||
class InlineDiff
|
||||
class << self
|
||||
module Trustie
|
||||
module Gitlab
|
||||
class InlineDiff
|
||||
class << self
|
||||
|
||||
START = "#!idiff-start!#"
|
||||
FINISH = "#!idiff-finish!#"
|
||||
START = "#!idiff-start!#"
|
||||
FINISH = "#!idiff-finish!#"
|
||||
|
||||
def processing(diff_arr)
|
||||
indexes = _indexes_of_changed_lines diff_arr
|
||||
def processing(diff_arr)
|
||||
indexes = _indexes_of_changed_lines diff_arr
|
||||
|
||||
indexes.each do |index|
|
||||
first_line = diff_arr[index+1]
|
||||
second_line = diff_arr[index+2]
|
||||
indexes.each do |index|
|
||||
first_line = diff_arr[index+1]
|
||||
second_line = diff_arr[index+2]
|
||||
|
||||
# Skip inline diff if empty line was replaced with content
|
||||
next if first_line == "-\n"
|
||||
# Skip inline diff if empty line was replaced with content
|
||||
next if first_line == "-\n"
|
||||
|
||||
first_token = find_first_token(first_line, second_line)
|
||||
apply_first_token(diff_arr, index, first_token)
|
||||
first_token = find_first_token(first_line, second_line)
|
||||
apply_first_token(diff_arr, index, first_token)
|
||||
|
||||
last_token = find_last_token(first_line, second_line, first_token)
|
||||
apply_last_token(diff_arr, index, last_token)
|
||||
last_token = find_last_token(first_line, second_line, first_token)
|
||||
apply_last_token(diff_arr, index, last_token)
|
||||
end
|
||||
|
||||
diff_arr
|
||||
end
|
||||
|
||||
diff_arr
|
||||
end
|
||||
def apply_first_token(diff_arr, index, first_token)
|
||||
start = first_token + START
|
||||
|
||||
def apply_first_token(diff_arr, index, first_token)
|
||||
start = first_token + START
|
||||
|
||||
if first_token.empty?
|
||||
# In case if we remove string of spaces in commit
|
||||
diff_arr[index+1].sub!("-", "-" => "-#{START}")
|
||||
diff_arr[index+2].sub!("+", "+" => "+#{START}")
|
||||
else
|
||||
diff_arr[index+1].sub!(first_token, first_token => start)
|
||||
diff_arr[index+2].sub!(first_token, first_token => start)
|
||||
end
|
||||
end
|
||||
|
||||
def apply_last_token(diff_arr, index, last_token)
|
||||
# This is tricky: escape backslashes so that `sub` doesn't interpret them
|
||||
# as backreferences. Regexp.escape does NOT do the right thing.
|
||||
replace_token = FINISH + last_token.gsub(/\\/, '\&\&')
|
||||
diff_arr[index+1].sub!(/#{Regexp.escape(last_token)}$/, replace_token)
|
||||
diff_arr[index+2].sub!(/#{Regexp.escape(last_token)}$/, replace_token)
|
||||
end
|
||||
|
||||
def find_first_token(first_line, second_line)
|
||||
max_length = [first_line.size, second_line.size].max
|
||||
first_the_same_symbols = 0
|
||||
|
||||
(0..max_length + 1).each do |i|
|
||||
first_the_same_symbols = i - 1
|
||||
|
||||
if first_line[i] != second_line[i] && i > 0
|
||||
break
|
||||
if first_token.empty?
|
||||
# In case if we remove string of spaces in commit
|
||||
diff_arr[index+1].sub!("-", "-" => "-#{START}")
|
||||
diff_arr[index+2].sub!("+", "+" => "+#{START}")
|
||||
else
|
||||
diff_arr[index+1].sub!(first_token, first_token => start)
|
||||
diff_arr[index+2].sub!(first_token, first_token => start)
|
||||
end
|
||||
end
|
||||
|
||||
first_line[0..first_the_same_symbols][1..-1]
|
||||
end
|
||||
def apply_last_token(diff_arr, index, last_token)
|
||||
# This is tricky: escape backslashes so that `sub` doesn't interpret them
|
||||
# as backreferences. Regexp.escape does NOT do the right thing.
|
||||
replace_token = FINISH + last_token.gsub(/\\/, '\&\&')
|
||||
diff_arr[index+1].sub!(/#{Regexp.escape(last_token)}$/, replace_token)
|
||||
diff_arr[index+2].sub!(/#{Regexp.escape(last_token)}$/, replace_token)
|
||||
end
|
||||
|
||||
def find_last_token(first_line, second_line, first_token)
|
||||
max_length = [first_line.size, second_line.size].max
|
||||
last_the_same_symbols = 0
|
||||
def find_first_token(first_line, second_line)
|
||||
max_length = [first_line.size, second_line.size].max
|
||||
first_the_same_symbols = 0
|
||||
|
||||
(1..max_length + 1).each do |i|
|
||||
last_the_same_symbols = -i
|
||||
shortest_line = second_line.size > first_line.size ? first_line : second_line
|
||||
(0..max_length + 1).each do |i|
|
||||
first_the_same_symbols = i - 1
|
||||
|
||||
if (first_line[-i] != second_line[-i]) || "#{first_token}#{START}".size == shortest_line[1..-i].size
|
||||
break
|
||||
if first_line[i] != second_line[i] && i > 0
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
first_line[0..first_the_same_symbols][1..-1]
|
||||
end
|
||||
|
||||
last_the_same_symbols += 1
|
||||
first_line[last_the_same_symbols..-1]
|
||||
end
|
||||
def find_last_token(first_line, second_line, first_token)
|
||||
max_length = [first_line.size, second_line.size].max
|
||||
last_the_same_symbols = 0
|
||||
|
||||
def _indexes_of_changed_lines(diff_arr)
|
||||
chain_of_first_symbols = ""
|
||||
diff_arr.each_with_index do |line, i|
|
||||
chain_of_first_symbols += line[0]
|
||||
(1..max_length + 1).each do |i|
|
||||
last_the_same_symbols = -i
|
||||
shortest_line = second_line.size > first_line.size ? first_line : second_line
|
||||
|
||||
if (first_line[-i] != second_line[-i]) || "#{first_token}#{START}".size == shortest_line[1..-i].size
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
last_the_same_symbols += 1
|
||||
first_line[last_the_same_symbols..-1]
|
||||
end
|
||||
chain_of_first_symbols.gsub!(/[^\-\+]/, "#")
|
||||
|
||||
offset = 0
|
||||
indexes = []
|
||||
while index = chain_of_first_symbols.index("#-+#", offset)
|
||||
indexes << index
|
||||
offset = index + 1
|
||||
def _indexes_of_changed_lines(diff_arr)
|
||||
chain_of_first_symbols = ""
|
||||
diff_arr.each_with_index do |line, i|
|
||||
chain_of_first_symbols += line[0]
|
||||
end
|
||||
chain_of_first_symbols.gsub!(/[^\-\+]/, "#")
|
||||
|
||||
offset = 0
|
||||
indexes = []
|
||||
while index = chain_of_first_symbols.index("#-+#", offset)
|
||||
indexes << index
|
||||
offset = index + 1
|
||||
end
|
||||
indexes
|
||||
end
|
||||
indexes
|
||||
end
|
||||
|
||||
def replace_markers(line)
|
||||
line.gsub!(START, "<span class='idiff'>")
|
||||
line.gsub!(FINISH, "</span>")
|
||||
line
|
||||
def replace_markers(line)
|
||||
line.gsub!(START, "<span class='idiff'>")
|
||||
line.gsub!(FINISH, "</span>")
|
||||
line
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
require 'spec_helper'
|
||||
require 'rails_helper'
|
||||
|
||||
require 'ostruct'
|
||||
|
||||
describe "Git diff" do
|
||||
before(:each) do
|
||||
@content = '''
|
||||
[{"diff":"--- a/readme\n+++ b/readme\n@@ -1,7 +1,8 @@\n 邀请界面\n 1.1 界面设计 (已处理)\n- 1.2 改写成html功能 (已处理)\n+sdkfsjkdf\n 1.3 集成到游戏邀请功能 (已处理)\n+adfjsdajlfk\n \n 微信登录功能\n 2.1 集成sdk (已处理)\n","new_path":"readme","old_path":"readme","a_mode":"100644","b_mode":"100644","new_file":false,"renamed_file":false,"deleted_file":false}]
|
||||
'''
|
||||
|
||||
@output = %Q{
|
||||
| 1 | 1 | 邀请界面
|
||||
| 2 | 2 | 1.1 界面设计 (已处理)
|
||||
| 3 | |-<span class='idiff'> 1.2 改写成html功能 (已处理)</span>
|
||||
| | 3 |+<span class='idiff'>sdkfsjkdf</span>
|
||||
| 4 | 4 | 1.3 集成到游戏邀请功能 (已处理)
|
||||
| | 5 |+adfjsdajlfk
|
||||
| 5 | 6 | } +
|
||||
%Q{
|
||||
| 6 | 7 | 微信登录功能
|
||||
| 7 | 8 | 2.1 集成sdk (已处理)
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
it "正确解析diff文件" do
|
||||
diff = ActiveSupport::JSON.decode(@content).first
|
||||
diff = OpenStruct.new(diff)
|
||||
diff_file = Trustie::Gitlab::Diff::File.new(diff)
|
||||
|
||||
output = ''
|
||||
diff_file.diff_lines.each_with_index do |line, index|
|
||||
type = line.type
|
||||
last_line = line.new_pos
|
||||
line_code = Trustie::Gitlab::Diff::LineCode.generate('diff.file_path', line.new_pos, line.old_pos)
|
||||
line_old = line.old_pos.to_s
|
||||
|
||||
#puts "type: #{type} last_line: #{last_line} last_code: #{line_code} line_old: #{line_old} text: #{line.text}"
|
||||
|
||||
if type == 'match'
|
||||
## 表示没有修改,两个都要显示行号
|
||||
output += "|#{line_old.center(4)}|#{line.new_pos.to_s.center(4)}|#{line.text}\n"
|
||||
else
|
||||
|
||||
old_line = type == 'new' ? ' '*4: line_old
|
||||
new_line = type == 'old' ? ' '*4: line.new_pos
|
||||
output += "|#{old_line.to_s.center(4)}|#{new_line.to_s.center(4)}|#{line.text}\n"
|
||||
end
|
||||
end
|
||||
|
||||
puts output
|
||||
|
||||
expect(output.strip).to eq(@output.strip)
|
||||
end
|
||||
|
||||
|
||||
end
|
Loading…
Reference in New Issue