diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index 60360c8e5c8..f8ec76cd4e5 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -21,8 +21,8 @@ class Projects::CompareController < Projects::ApplicationController
@commits = Commit.decorate(compare_result.commits, @project)
@diffs = compare_result.diffs
@commit = @project.commit(head_ref)
- @first_commit = @project.commit(base_ref)
- @diff_refs = [@first_commit, @commit]
+ @base_commit = @project.commit(base_ref)
+ @diff_refs = [@base_commit, @commit]
@line_notes = []
end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index a6284a24223..ed3050d59aa 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -58,7 +58,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def diffs
@commit = @merge_request.last_commit
- @first_commit = @merge_request.first_commit
+ @base_commit = @merge_request.diff_base_commit
+
+ # MRs created before 8.4 don't have a diff_base_commit,
+ # but we need it for the "View file @ ..." link by deleted files
+ @base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit
@comments_allowed = @reply_allowed = true
@comments_target = {
@@ -102,7 +106,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@source_project = merge_request.source_project
@commits = @merge_request.compare_commits.reverse
@commit = @merge_request.last_commit
- @first_commit = @merge_request.first_commit
+ @base_commit = @merge_request.diff_base_commit
@diffs = @merge_request.compare_diffs
@ci_commit = @merge_request.ci_commit
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index f500d3572e0..62971d1e14b 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -102,8 +102,7 @@ module DiffHelper
def commit_for_diff(diff)
if diff.deleted_file
- first_commit = @first_commit || @commit
- first_commit.parent || @first_commit
+ @base_commit || @commit.parent || @commit
else
@commit
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 0a890bbf6db..41dd248d80a 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -180,6 +180,14 @@ class MergeRequest < ActiveRecord::Base
merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
end
+ def diff_base_commit
+ if merge_request_diff
+ merge_request_diff.base_commit
+ else
+ self.target_project.commit(self.target_branch)
+ end
+ end
+
def last_commit_short_sha
last_commit.short_id
end
@@ -477,8 +485,7 @@ class MergeRequest < ActiveRecord::Base
end
def target_sha
- @target_sha ||= target_project.
- repository.commit(target_branch).sha
+ @target_sha ||= target_project.repository.commit(target_branch).sha
end
def source_sha
@@ -519,6 +526,8 @@ class MergeRequest < ActiveRecord::Base
end
def diff_refs
- [first_commit.parent || first_commit, last_commit]
+ return nil unless diff_base_commit
+
+ [diff_base_commit, last_commit]
end
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index c499a4b5b4c..ba0194cd0a6 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -73,6 +73,12 @@ class MergeRequestDiff < ActiveRecord::Base
commits.last
end
+ def base_commit
+ return nil unless self.base_commit_sha
+
+ merge_request.target_project.commit(self.base_commit_sha)
+ end
+
def last_commit_short_sha
@last_commit_short_sha ||= last_commit.short_id
end
@@ -156,6 +162,9 @@ class MergeRequestDiff < ActiveRecord::Base
end
self.st_diffs = new_diffs
+
+ self.base_commit_sha = merge_request.target_project.commit(target_branch).try(:sha)
+
self.save
end
diff --git a/db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb b/db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb
new file mode 100644
index 00000000000..d6c6aa4a4e8
--- /dev/null
+++ b/db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb
@@ -0,0 +1,5 @@
+class AddBaseCommitShaToMergeRequestDiffs < ActiveRecord::Migration
+ def change
+ add_column :merge_request_diffs, :base_commit_sha, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index dc7cb9f667f..7eb99a47c71 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160119145451) do
+ActiveRecord::Schema.define(version: 20160120172143) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -490,6 +490,7 @@ ActiveRecord::Schema.define(version: 20160119145451) do
t.integer "merge_request_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
+ t.string "base_commit_sha"
end
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 @@ ActiveRecord::Schema.define(version: 20160119145451) do
t.string "type"
t.string "title"
t.integer "project_id"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.boolean "active", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.boolean "active", null: false
t.text "properties"
- t.boolean "template", default: false
- t.boolean "push_events", default: true
- t.boolean "issues_events", default: true
- t.boolean "merge_requests_events", default: true
- t.boolean "tag_push_events", default: true
- t.boolean "note_events", default: true, null: false
- t.boolean "build_events", default: false, null: false
- t.string "category", default: "common", null: false
- t.boolean "default", default: false
+ t.boolean "template", default: false
+ t.boolean "push_events", default: true
+ t.boolean "issues_events", default: true
+ t.boolean "merge_requests_events", default: true
+ t.boolean "tag_push_events", default: true
+ t.boolean "note_events", default: true, null: false
+ t.boolean "build_events", default: false, null: false
+ t.string "category", default: "common", null: false
+ t.boolean "default", default: false
end
add_index "services", ["category"], name: "index_services_on_category", using: :btree
@@ -854,7 +855,7 @@ ActiveRecord::Schema.define(version: 20160119145451) do
t.boolean "hide_project_limit", default: false
t.string "unlock_token"
t.datetime "otp_grace_period_started_at"
- t.boolean "ldap_email", default: false, null: false
+ t.boolean "ldap_email", default: false, null: false
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 74b1c117129..a484177ae33 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -1,14 +1,22 @@
module Gitlab
module Diff
class File
- attr_reader :diff, :new_ref, :old_ref
+ attr_reader :diff, :diff_refs
delegate :new_file, :deleted_file, :renamed_file,
:old_path, :new_path, to: :diff, prefix: false
def initialize(diff, diff_refs)
@diff = diff
- @old_ref, @new_ref = diff_refs
+ @diff_refs = diff_refs
+ end
+
+ def old_ref
+ diff_refs[0] if diff_refs
+ end
+
+ def new_ref
+ diff_refs[1] if diff_refs
end
# Array of Gitlab::DIff::Line objects
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index b6875f07279..fe084a7399a 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -31,6 +31,8 @@ module Gitlab
private
def highlight_line(diff_line, index)
+ return html_escape(diff_line.text) unless diff_file.diff_refs
+
line_prefix = diff_line.text.match(/\A([+-])/) ? $1 : ' '
case diff_line.type
@@ -42,7 +44,7 @@ module Gitlab
# Only update text if line is found. This will prevent
# issues with submodules given the line only exists in diff content.
- rich_line ? line_prefix + rich_line : diff_line.text
+ rich_line ? line_prefix + rich_line : html_escape(diff_line.text)
end
def inline_diffs
@@ -63,6 +65,11 @@ module Gitlab
[ref.project.repository, ref.id, path]
end
+
+ def html_escape(str)
+ replacements = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' }
+ str.gsub(/[&"'><]/, replacements)
+ end
end
end
end
diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb
index c31149d374e..7ca198eeb86 100644
--- a/lib/gitlab/diff/inline_diff_marker.rb
+++ b/lib/gitlab/diff/inline_diff_marker.rb
@@ -9,17 +9,18 @@ module Gitlab
end
def mark(line_inline_diffs)
- offset = 0
+ marker_ranges = []
line_inline_diffs.each do |inline_diff_range|
# Map the inline-diff range based on the raw line to character positions in the rich line
inline_diff_positions = position_mapping[inline_diff_range].flatten
# Turn the array of character positions into ranges
- marker_ranges = collapse_ranges(inline_diff_positions)
+ marker_ranges.concat(collapse_ranges(inline_diff_positions))
+ end
- # Mark each range
- marker_ranges.each do |range|
- offset = insert_around_range(rich_line, range, "", "", offset)
- end
+ offset = 0
+ # Mark each range
+ marker_ranges.each do |range|
+ offset = insert_around_range(rich_line, range, "", "", offset)
end
rich_line