Merge branch 'multi-line-inline-diff' into 'master'
Render inline diffs for multiple changed lines following eachother Before: ![Screen_Shot_2016-07-11_at_00.08.27](/uploads/b14664211e0f5cef6e77a78eadfcbcdf/Screen_Shot_2016-07-11_at_00.08.27.png) After: ![Screen_Shot_2016-07-11_at_00.07.34](/uploads/567be631869a4867a2edf6ff7eda6369/Screen_Shot_2016-07-11_at_00.07.34.png) See merge request !5174
This commit is contained in:
commit
5fea640e90
3 changed files with 56 additions and 23 deletions
|
@ -35,6 +35,7 @@ v 8.10.0 (unreleased)
|
|||
- Fix changing issue state columns in milestone view
|
||||
- Update health_check gem to version 2.1.0
|
||||
- Add notification settings dropdown for groups
|
||||
- Render inline diffs for multiple changed lines following eachother
|
||||
- Wildcards for protected branches. !4665
|
||||
- Allow importing from Github using Personal Access Tokens. (Eric K Idema)
|
||||
- API: Todos !3188 (Robert Schilling)
|
||||
|
|
|
@ -1,16 +1,30 @@
|
|||
module Gitlab
|
||||
module Diff
|
||||
class InlineDiff
|
||||
# Regex to find a run of deleted lines followed by the same number of added lines
|
||||
LINE_PAIRS_PATTERN = %r{
|
||||
# Runs start at the beginning of the string (the first line) or after a space (for an unchanged line)
|
||||
(?:\A|\s)
|
||||
|
||||
# This matches a number of `-`s followed by the same number of `+`s through recursion
|
||||
(?<del_ins>
|
||||
-
|
||||
\g<del_ins>?
|
||||
\+
|
||||
)
|
||||
|
||||
# Runs end at the end of the string (the last line) or before a space (for an unchanged line)
|
||||
(?=\s|\z)
|
||||
}x.freeze
|
||||
|
||||
attr_accessor :old_line, :new_line, :offset
|
||||
|
||||
def self.for_lines(lines)
|
||||
local_edit_indexes = self.find_local_edits(lines)
|
||||
changed_line_pairs = self.find_changed_line_pairs(lines)
|
||||
|
||||
inline_diffs = []
|
||||
|
||||
local_edit_indexes.each do |index|
|
||||
old_index = index
|
||||
new_index = index + 1
|
||||
changed_line_pairs.each do |old_index, new_index|
|
||||
old_line = lines[old_index]
|
||||
new_line = lines[new_index]
|
||||
|
||||
|
@ -51,18 +65,28 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
def self.find_local_edits(lines)
|
||||
line_prefixes = lines.map { |line| line.match(/\A([+-])/) ? $1 : ' ' }
|
||||
joined_line_prefixes = " #{line_prefixes.join} "
|
||||
# Finds pairs of old/new line pairs that represent the same line that changed
|
||||
def self.find_changed_line_pairs(lines)
|
||||
# Prefixes of all diff lines, indicating their types
|
||||
# For example: `" - + -+ ---+++ --+ -++"`
|
||||
line_prefixes = lines.each_with_object("") { |line, s| s << line[0] }.gsub(/[^ +-]/, ' ')
|
||||
|
||||
offset = 0
|
||||
local_edit_indexes = []
|
||||
while index = joined_line_prefixes.index(" -+ ", offset)
|
||||
local_edit_indexes << index
|
||||
offset = index + 1
|
||||
changed_line_pairs = []
|
||||
line_prefixes.scan(LINE_PAIRS_PATTERN) do
|
||||
# For `"---+++"`, `begin_index == 0`, `end_index == 6`
|
||||
begin_index, end_index = Regexp.last_match.offset(:del_ins)
|
||||
|
||||
# For `"---+++"`, `changed_line_count == 3`
|
||||
changed_line_count = (end_index - begin_index) / 2
|
||||
|
||||
halfway_index = begin_index + changed_line_count
|
||||
(begin_index...halfway_index).each do |i|
|
||||
# For `"---+++"`, index 1 maps to 1 + 3 = 4
|
||||
changed_line_pairs << [i, i + changed_line_count]
|
||||
end
|
||||
end
|
||||
|
||||
local_edit_indexes
|
||||
changed_line_pairs
|
||||
end
|
||||
|
||||
def longest_common_prefix(a, b)
|
||||
|
|
|
@ -3,14 +3,19 @@ require 'spec_helper'
|
|||
describe Gitlab::Diff::InlineDiff, lib: true do
|
||||
describe '.for_lines' do
|
||||
let(:diff) do
|
||||
<<eos
|
||||
class Test
|
||||
- def initialize(test = true)
|
||||
+ def initialize(test = false)
|
||||
@test = test
|
||||
end
|
||||
end
|
||||
eos
|
||||
<<-EOF.strip_heredoc
|
||||
class Test
|
||||
- def initialize(test = true)
|
||||
+ def initialize(test = false)
|
||||
@test = test
|
||||
- if true
|
||||
- @foo = "bar"
|
||||
+ unless false
|
||||
+ @foo = "baz"
|
||||
end
|
||||
end
|
||||
end
|
||||
EOF
|
||||
end
|
||||
|
||||
let(:subject) { described_class.for_lines(diff.lines) }
|
||||
|
@ -20,8 +25,11 @@ eos
|
|||
expect(subject[1]).to eq([25..27])
|
||||
expect(subject[2]).to eq([25..28])
|
||||
expect(subject[3]).to be_nil
|
||||
expect(subject[4]).to be_nil
|
||||
expect(subject[5]).to be_nil
|
||||
expect(subject[4]).to eq([5..10])
|
||||
expect(subject[5]).to eq([17..17])
|
||||
expect(subject[6]).to eq([5..15])
|
||||
expect(subject[7]).to eq([17..17])
|
||||
expect(subject[8]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue