Skip to content

Commit 577f2fb

Browse files
committed
Save and use actual diff base commit for MR diff highlighting
1 parent 26f7d02 commit 577f2fb

10 files changed

+75
-32
lines changed

app/controllers/projects/compare_controller.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ def show
2121
@commits = Commit.decorate(compare_result.commits, @project)
2222
@diffs = compare_result.diffs
2323
@commit = @project.commit(head_ref)
24-
@first_commit = @project.commit(base_ref)
25-
@diff_refs = [@first_commit, @commit]
24+
@base_commit = @project.commit(base_ref)
25+
@diff_refs = [@base_commit, @commit]
2626
@line_notes = []
2727
end
2828
end

app/controllers/projects/merge_requests_controller.rb

+6-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ def show
5858

5959
def diffs
6060
@commit = @merge_request.last_commit
61-
@first_commit = @merge_request.first_commit
61+
@base_commit = @merge_request.diff_base_commit
62+
63+
# MRs created before 8.4 don't have a diff_base_commit,
64+
# but we need it for the "View file @ ..." link by deleted files
65+
@base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit
6266

6367
@comments_allowed = @reply_allowed = true
6468
@comments_target = {
@@ -102,7 +106,7 @@ def new
102106
@source_project = merge_request.source_project
103107
@commits = @merge_request.compare_commits.reverse
104108
@commit = @merge_request.last_commit
105-
@first_commit = @merge_request.first_commit
109+
@base_commit = @merge_request.diff_base_commit
106110
@diffs = @merge_request.compare_diffs
107111

108112
@ci_commit = @merge_request.ci_commit

app/helpers/diff_helper.rb

+1-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,7 @@ def submodule_link(blob, ref, repository = @repository)
102102

103103
def commit_for_diff(diff)
104104
if diff.deleted_file
105-
first_commit = @first_commit || @commit
106-
first_commit.parent || @first_commit
105+
@base_commit || @commit.parent || @commit
107106
else
108107
@commit
109108
end

app/models/merge_request.rb

+12-3
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ def first_commit
180180
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
181181
end
182182

183+
def diff_base_commit
184+
if merge_request_diff
185+
merge_request_diff.base_commit
186+
else
187+
self.target_project.commit(self.target_branch)
188+
end
189+
end
190+
183191
def last_commit_short_sha
184192
last_commit.short_id
185193
end
@@ -477,8 +485,7 @@ def state_human_name
477485
end
478486

479487
def target_sha
480-
@target_sha ||= target_project.
481-
repository.commit(target_branch).sha
488+
@target_sha ||= target_project.repository.commit(target_branch).sha
482489
end
483490

484491
def source_sha
@@ -519,6 +526,8 @@ def ci_commit
519526
end
520527

521528
def diff_refs
522-
[first_commit.parent || first_commit, last_commit]
529+
return nil unless diff_base_commit
530+
531+
[diff_base_commit, last_commit]
523532
end
524533
end

app/models/merge_request_diff.rb

+9
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ def first_commit
7373
commits.last
7474
end
7575

76+
def base_commit
77+
return nil unless self.base_commit_sha
78+
79+
merge_request.target_project.commit(self.base_commit_sha)
80+
end
81+
7682
def last_commit_short_sha
7783
@last_commit_short_sha ||= last_commit.short_id
7884
end
@@ -156,6 +162,9 @@ def reload_diffs
156162
end
157163

158164
self.st_diffs = new_diffs
165+
166+
self.base_commit_sha = merge_request.target_project.commit(target_branch).try(:sha)
167+
159168
self.save
160169
end
161170

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class AddBaseCommitShaToMergeRequestDiffs < ActiveRecord::Migration
2+
def change
3+
add_column :merge_request_diffs, :base_commit_sha, :string
4+
end
5+
end

db/schema.rb

+15-14
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#
1212
# It's strongly recommended that you check this file into your version control system.
1313

14-
ActiveRecord::Schema.define(version: 20160119145451) do
14+
ActiveRecord::Schema.define(version: 20160120172143) do
1515

1616
# These are extensions that must be enabled in order to support this database
1717
enable_extension "plpgsql"
@@ -490,6 +490,7 @@
490490
t.integer "merge_request_id", null: false
491491
t.datetime "created_at"
492492
t.datetime "updated_at"
493+
t.string "base_commit_sha"
493494
end
494495

495496
add_index "merge_request_diffs", ["merge_request_id"], name: "index_merge_request_diffs_on_merge_request_id", unique: true, using: :btree
@@ -725,19 +726,19 @@
725726
t.string "type"
726727
t.string "title"
727728
t.integer "project_id"
728-
t.datetime "created_at", null: false
729-
t.datetime "updated_at", null: false
730-
t.boolean "active", null: false
729+
t.datetime "created_at", null: false
730+
t.datetime "updated_at", null: false
731+
t.boolean "active", null: false
731732
t.text "properties"
732-
t.boolean "template", default: false
733-
t.boolean "push_events", default: true
734-
t.boolean "issues_events", default: true
735-
t.boolean "merge_requests_events", default: true
736-
t.boolean "tag_push_events", default: true
737-
t.boolean "note_events", default: true, null: false
738-
t.boolean "build_events", default: false, null: false
739-
t.string "category", default: "common", null: false
740-
t.boolean "default", default: false
733+
t.boolean "template", default: false
734+
t.boolean "push_events", default: true
735+
t.boolean "issues_events", default: true
736+
t.boolean "merge_requests_events", default: true
737+
t.boolean "tag_push_events", default: true
738+
t.boolean "note_events", default: true, null: false
739+
t.boolean "build_events", default: false, null: false
740+
t.string "category", default: "common", null: false
741+
t.boolean "default", default: false
741742
end
742743

743744
add_index "services", ["category"], name: "index_services_on_category", using: :btree
@@ -854,7 +855,7 @@
854855
t.boolean "hide_project_limit", default: false
855856
t.string "unlock_token"
856857
t.datetime "otp_grace_period_started_at"
857-
t.boolean "ldap_email", default: false, null: false
858+
t.boolean "ldap_email", default: false, null: false
858859
end
859860

860861
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree

lib/gitlab/diff/file.rb

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
module Gitlab
22
module Diff
33
class File
4-
attr_reader :diff, :new_ref, :old_ref
4+
attr_reader :diff, :diff_refs
55

66
delegate :new_file, :deleted_file, :renamed_file,
77
:old_path, :new_path, to: :diff, prefix: false
88

99
def initialize(diff, diff_refs)
1010
@diff = diff
11-
@old_ref, @new_ref = diff_refs
11+
@diff_refs = diff_refs
12+
end
13+
14+
def old_ref
15+
diff_refs[0] if diff_refs
16+
end
17+
18+
def new_ref
19+
diff_refs[1] if diff_refs
1220
end
1321

1422
# Array of Gitlab::DIff::Line objects

lib/gitlab/diff/highlight.rb

+8-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ def highlight
3131
private
3232

3333
def highlight_line(diff_line, index)
34+
return html_escape(diff_line.text) unless diff_file.diff_refs
35+
3436
line_prefix = diff_line.text.match(/\A([+-])/) ? $1 : ' '
3537

3638
case diff_line.type
@@ -42,7 +44,7 @@ def highlight_line(diff_line, index)
4244

4345
# Only update text if line is found. This will prevent
4446
# issues with submodules given the line only exists in diff content.
45-
rich_line ? line_prefix + rich_line : diff_line.text
47+
rich_line ? line_prefix + rich_line : html_escape(diff_line.text)
4648
end
4749

4850
def inline_diffs
@@ -63,6 +65,11 @@ def processing_args(version)
6365

6466
[ref.project.repository, ref.id, path]
6567
end
68+
69+
def html_escape(str)
70+
replacements = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#39;' }
71+
str.gsub(/[&"'><]/, replacements)
72+
end
6673
end
6774
end
6875
end

lib/gitlab/diff/inline_diff_marker.rb

+7-6
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ def initialize(raw_line, rich_line = raw_line)
99
end
1010

1111
def mark(line_inline_diffs)
12-
offset = 0
12+
marker_ranges = []
1313
line_inline_diffs.each do |inline_diff_range|
1414
# Map the inline-diff range based on the raw line to character positions in the rich line
1515
inline_diff_positions = position_mapping[inline_diff_range].flatten
1616
# Turn the array of character positions into ranges
17-
marker_ranges = collapse_ranges(inline_diff_positions)
17+
marker_ranges.concat(collapse_ranges(inline_diff_positions))
18+
end
1819

19-
# Mark each range
20-
marker_ranges.each do |range|
21-
offset = insert_around_range(rich_line, range, "<span class='idiff'>", "</span>", offset)
22-
end
20+
offset = 0
21+
# Mark each range
22+
marker_ranges.each do |range|
23+
offset = insert_around_range(rich_line, range, "<span class='idiff'>", "</span>", offset)
2324
end
2425

2526
rich_line

0 commit comments

Comments
 (0)