Commit 21b602c6 authored by Rubén Dávila's avatar Rubén Dávila

Change strategy to highlight diffs. #3945

Now we apply syntax highlighting to the whole old and new files.
This basically help us to highlight adequately multiline content.
parent f1f4fdf7
...@@ -24,6 +24,7 @@ class ApplicationController < ActionController::Base ...@@ -24,6 +24,7 @@ class ApplicationController < ActionController::Base
helper_method :abilities, :can?, :current_application_settings helper_method :abilities, :can?, :current_application_settings
helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled? helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?
helper_method :repository
rescue_from Encoding::CompatibilityError do |exception| rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception) log_exception(exception)
......
...@@ -65,8 +65,11 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -65,8 +65,11 @@ class Projects::BlobController < Projects::ApplicationController
end end
def diff def diff
@form = UnfoldForm.new(params) ref, file_name = params[:id].split('/', 2)
@lines = Gitlab::Diff::Highlight.process_diff_lines(@blob.name, @blob.data.lines[@form.since - 1..@form.to - 1])
@form = UnfoldForm.new(params)
@lines = Gitlab::Diff::Highlight.process_file(repository, ref, file_name)
@lines = @lines[@form.since - 1..@form.to - 1]
if @form.bottom? if @form.bottom?
@match_line = '' @match_line = ''
......
...@@ -72,6 +72,7 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -72,6 +72,7 @@ class Projects::CommitController < Projects::ApplicationController
@diffs = commit.diffs @diffs = commit.diffs
end end
@diff_refs = [commit.parent.id, commit.id]
@notes_count = commit.notes.count @notes_count = commit.notes.count
@statuses = ci_commit.statuses if ci_commit @statuses = ci_commit.statuses if ci_commit
......
...@@ -20,6 +20,7 @@ class Projects::CompareController < Projects::ApplicationController ...@@ -20,6 +20,7 @@ class Projects::CompareController < Projects::ApplicationController
if compare_result if compare_result
@commits = Commit.decorate(compare_result.commits, @project) @commits = Commit.decorate(compare_result.commits, @project)
@diffs = compare_result.diffs @diffs = compare_result.diffs
@diff_refs = [base_ref, head_ref]
@commit = @project.commit(head_ref) @commit = @project.commit(head_ref)
@first_commit = @project.commit(base_ref) @first_commit = @project.commit(base_ref)
@line_notes = [] @line_notes = []
......
...@@ -59,6 +59,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -59,6 +59,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def diffs def diffs
@commit = @merge_request.last_commit @commit = @merge_request.last_commit
@first_commit = @merge_request.first_commit @first_commit = @merge_request.first_commit
@diff_refs = [@merge_request.target_sha, @merge_request.source_sha]
@comments_allowed = @reply_allowed = true @comments_allowed = @reply_allowed = true
@comments_target = { @comments_target = {
...@@ -103,6 +104,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -103,6 +104,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@commit = @merge_request.last_commit @commit = @merge_request.last_commit
@first_commit = @merge_request.first_commit @first_commit = @merge_request.first_commit
@diffs = @merge_request.compare_diffs @diffs = @merge_request.compare_diffs
@diff_refs = [@merge_request.target_sha, @merge_request.source_branch]
@ci_commit = @merge_request.ci_commit @ci_commit = @merge_request.ci_commit
@statuses = @ci_commit.statuses if @ci_commit @statuses = @ci_commit.statuses if @ci_commit
......
...@@ -19,13 +19,13 @@ module DiffHelper ...@@ -19,13 +19,13 @@ module DiffHelper
end end
end end
def safe_diff_files(diffs) def safe_diff_files(diffs, diff_refs, repository)
lines = 0 lines = 0
safe_files = [] safe_files = []
diffs.first(allowed_diff_size).each do |diff| diffs.first(allowed_diff_size).each do |diff|
lines += diff.diff.lines.count lines += diff.diff.lines.count
break if lines > allowed_diff_lines break if lines > allowed_diff_lines
safe_files << Gitlab::Diff::File.new(diff) safe_files << Gitlab::Diff::File.new(diff, diff_refs, repository)
end end
safe_files safe_files
end end
......
...@@ -5,5 +5,6 @@ ...@@ -5,5 +5,6 @@
= render "ci_menu" = render "ci_menu"
- else - else
%div.block-connector %div.block-connector
= render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/diffs/diffs", diffs: @diffs, project: @project,
diff_refs: @diff_refs
= render "projects/notes/notes_with_form" = render "projects/notes/notes_with_form"
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
- if @commits.present? - if @commits.present?
.prepend-top-default .prepend-top-default
= render "projects/commits/commit_list" = render "projects/commits/commit_list"
= render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @diff_refs
- else - else
.light-well.prepend-top-default .light-well.prepend-top-default
.center .center
......
- if diff_view == 'parallel' - if diff_view == 'parallel'
- fluid_layout true - fluid_layout true
- diff_files = safe_diff_files(diffs) - diff_files = safe_diff_files(diffs, diff_refs, repository)
.gray-content-block.middle-block.oneline-block .gray-content-block.middle-block.oneline-block
.inline-parallel-buttons .inline-parallel-buttons
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
= render "projects/merge_requests/show/commits" = render "projects/merge_requests/show/commits"
#diffs.diffs.tab-pane.active #diffs.diffs.tab-pane.active
- if @diffs.present? - if @diffs.present?
= render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @diff_refs
- elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
.alert.alert-danger .alert.alert-danger
%h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits. %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits.
......
- if @merge_request_diff.collected? - if @merge_request_diff.collected?
= render "projects/diffs/diffs", diffs: params[:w] == '1' ? @merge_request.diffs_no_whitespace : @merge_request.diffs, project: @merge_request.project = render "projects/diffs/diffs", diffs: params[:w] == '1' ? @merge_request.diffs_no_whitespace : @merge_request.diffs, project: @merge_request.project, diff_refs: @diff_refs
- elsif @merge_request_diff.empty? - elsif @merge_request_diff.empty?
.nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch} .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch}
- else - else
......
module Gitlab module Gitlab
module Diff module Diff
class File class File
attr_reader :diff attr_reader :diff, :repository, :new_ref, :old_ref
delegate :new_file, :deleted_file, :renamed_file, delegate :new_file, :deleted_file, :renamed_file,
:old_path, :new_path, to: :diff, prefix: false :old_path, :new_path, to: :diff, prefix: false
def initialize(diff) def initialize(diff, diff_refs, repository)
@diff = diff @diff = diff
@repository = repository
@old_ref, @new_ref = diff_refs
end end
# Array of Gitlab::DIff::Line objects # Array of Gitlab::DIff::Line objects
...@@ -16,7 +18,7 @@ module Gitlab ...@@ -16,7 +18,7 @@ module Gitlab
end end
def highlighted_diff_lines def highlighted_diff_lines
Gitlab::Diff::Highlight.process_diff_lines(new_path, diff_lines) Gitlab::Diff::Highlight.process_diff_lines(self)
end end
def mode_changed? def mode_changed?
......
module Gitlab module Gitlab
module Diff module Diff
class Highlight class Highlight
attr_reader :diff_file
delegate :repository, :old_path, :new_path, :old_ref, :new_ref,
to: :diff_file, prefix: :diff
# Apply syntax highlight to provided source code # Apply syntax highlight to provided source code
# #
# file_name - The file name related to the code. # diff_file - an instance of Gitlab::Diff::File
# lines - It can be an Array of Gitlab::Diff::Line objects or simple Strings.
# When passing Strings you need to provide the required 'end of lines'
# chars ("\n") for each String given that we don't append them automatically.
# #
# Returns an Array with the processed items. # Returns an Array with the processed items.
def self.process_diff_lines(file_name, lines) def self.process_diff_lines(diff_file)
processor = new(file_name, lines) processor = new(diff_file)
processor.highlight processor.highlight
end end
def initialize(file_name, lines) def self.process_file(repository, ref, file_name)
@file_name = file_name blob = repository.blob_at(ref, file_name)
@lines = lines return [] unless blob
content = blob.data
lexer = Rouge::Lexer.guess(filename: file_name, source: content).new rescue Rouge::Lexers::PlainText.new
formatter.format(lexer.lex(content)).lines
end
def self.formatter
@formatter ||= Rouge::Formatters::HTMLGitlab.new(
nowrap: true,
cssclass: 'code highlight',
lineanchors: true,
lineanchorsid: 'LC'
)
end
def initialize(diff_file)
@diff_file = diff_file
@file_name = diff_file.new_path
@lines = diff_file.diff_lines
end end
def highlight def highlight
...@@ -47,7 +68,7 @@ module Gitlab ...@@ -47,7 +68,7 @@ module Gitlab
def extract_line_prefixes def extract_line_prefixes
@diff_line_prefixes ||= begin @diff_line_prefixes ||= begin
if is_diff_line? if is_diff_line?
text_lines.map { |line| line.sub!(/\A((\+|\-)\s*)/, '');$1 } text_lines.map { |line| line.sub!(/\A((\+|\-))/, '');$1 }
else else
[] []
end end
...@@ -57,11 +78,17 @@ module Gitlab ...@@ -57,11 +78,17 @@ module Gitlab
def update_diff_lines def update_diff_lines
@highlighted_code.lines.each_with_index do |line, i| @highlighted_code.lines.each_with_index do |line, i|
diff_line = @lines[i] diff_line = @lines[i]
line_prefix = @diff_line_prefixes[i] || ' '
# ignore highlighting for "match" lines # ignore highlighting for "match" lines
next if diff_line.type == 'match' next if diff_line.type == 'match'
diff_line.text = "#{@diff_line_prefixes[i]}#{line}" case diff_line.type
when 'new', nil
diff_line.text = new_lines[diff_line.new_pos - 1].try(:gsub!, /\A\s/, line_prefix)
when 'old'
diff_line.text = old_lines[diff_line.old_pos - 1].try(:gsub!, /\A\s/, line_prefix)
end
end end
@lines @lines
...@@ -79,12 +106,21 @@ module Gitlab ...@@ -79,12 +106,21 @@ module Gitlab
end end
def formatter def formatter
Rouge::Formatters::HTMLGitlab.new( self.class.formatter
nowrap: true, end
cssclass: 'code highlight',
lineanchors: true, def old_lines
lineanchorsid: 'LC' @old_lines ||= begin
) lines = self.class.process_file(diff_repository, diff_old_ref, diff_old_path)
lines.map! { |line| " #{line}" }
end
end
def new_lines
@new_lines ||= begin
lines = self.class.process_file(diff_repository, diff_new_ref, diff_new_path)
lines.map! { |line| " #{line}" }
end
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment