From 34657b821ae597de76ffd5a70d2b0b298dc270ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 15 Dec 2015 18:09:09 -0500 Subject: Add syntax highlighting to diff view. #3945 --- app/helpers/application_helper.rb | 6 +++++ app/helpers/blob_helper.rb | 29 +++++++++++++++++++---- app/views/projects/diffs/_parallel_view.html.haml | 8 ++++--- app/views/projects/diffs/_text_file.html.haml | 6 +++-- lib/rouge/lexers/gitlab_diff.rb | 20 ++++++++++++++++ spec/helpers/blob_helper_spec.rb | 11 +++++++++ 6 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 lib/rouge/lexers/gitlab_diff.rb diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 0b00b9a0702..bc4b6ec0327 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -326,4 +326,10 @@ module ApplicationHelper def truncate_first_line(message, length = 50) truncate(message.each_line.first.chomp, length: length) if message end + + def unescape_html(content) + text = CGI.unescapeHTML(content) + text.gsub!(' ', ' ') + text + end end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index d31d4cde08f..bf18673972c 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -1,11 +1,17 @@ module BlobHelper - def highlight(blob_name, blob_content, nowrap: false, continue: false) - @formatter ||= Rouge::Formatters::HTMLGitlab.new( - nowrap: nowrap, + def rouge_formatter(options = {}) + default_options = { + nowrap: false, cssclass: 'code highlight', lineanchors: true, lineanchorsid: 'LC' - ) + } + + Rouge::Formatters::HTMLGitlab.new(default_options.merge!(options)) + end + + def highlight(blob_name, blob_content, nowrap: false, continue: false) + @formatter ||= rouge_formatter(nowrap: nowrap) begin @lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content).new @@ -18,6 +24,21 @@ module BlobHelper result end + def highlight_line(blob_name, content, continue: false) + if @previous_blob_name != blob_name + @parent = Rouge::Lexer.guess(filename: blob_name, source: content).new rescue Rouge::Lexers::PlainText.new + @lexer = Rouge::Lexers::GitlabDiff.new(parent_lexer: @parent) + @options = Rouge::Lexers::PlainText === @parent ? {} : { continue: continue } + end + + @previous_blob_name = blob_name + @formatter ||= rouge_formatter(nowrap: true) + + content.sub!(/\A((?:\+|-)\s*)/, '') # Don't format '+' or '-' indicators. + + "#{$1}#{@formatter.format(@lexer.lex(content, @options))}".html_safe + end + def no_highlight_files %w(credits changelog news copying copyright license authors) end diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 37fd1b1ec8a..c6a9d71e789 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -1,5 +1,5 @@ / Side-by-side diff view -%div.text-file.diff-wrap-lines +%div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight{ class: user_color_scheme } %table - parallel_diff(diff_file, index).each do |line| - type_left = line[0] @@ -20,7 +20,8 @@ = link_to raw(line_number_left), "##{line_code_left}", id: line_code_left - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_left, 'old') - %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= raw line_content_left + %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }< + = highlight_line(diff_file.new_path, unescape_html(line_content_left)) - if type_right == 'new' - new_line_class = 'new' @@ -33,7 +34,8 @@ = link_to raw(line_number_right), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_right, 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= raw line_content_right + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}< + = highlight_line(diff_file.new_path, unescape_html(line_content_right)) - if @reply_allowed - comments_left, comments_right = organize_comments(type_left, type_right, line_code_left, line_code_right) diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 977ca423f75..78c66a6291e 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -3,7 +3,8 @@ .suppressed-container %a.show-suppressed-diff.js-show-suppressed-diff Changes suppressed. Click to show. -%table.text-file{class: "#{'hide' if too_big}"} +%table.text-file.code.js-syntax-highlight{ class: [user_color_scheme, too_big ? 'hide' : ''] } + - last_line = 0 - diff_file.diff_lines.each_with_index do |line, index| - type = line.type @@ -21,7 +22,8 @@ = link_to_new_diff_note(line_code) %td.new_line{data: {linenumber: line.new_pos}} = link_to raw(type == "old" ? " " : line.new_pos) , "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text) + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}< + = highlight_line(diff_file.new_path, unescape_html(diff_line_content(line.text))) - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) diff --git a/lib/rouge/lexers/gitlab_diff.rb b/lib/rouge/lexers/gitlab_diff.rb new file mode 100644 index 00000000000..e136d47df00 --- /dev/null +++ b/lib/rouge/lexers/gitlab_diff.rb @@ -0,0 +1,20 @@ +Rouge::Token::Tokens.token(:InlineDiff, 'idiff') + +module Rouge + module Lexers + class GitlabDiff < RegexLexer + title "GitLab Diff" + tag 'gitlab_diff' + + state :root do + rule %r{(.*?)} do |match| + token InlineDiff, match[1] + end + + rule /(?:(?!puts 'Hello' world) + end + + it 'should respect the inline diff markup' do + result = highlight_line('demo.rb', "puts 'Hello' world") + expect(result).to eq(expected) + end + end end -- cgit v1.2.1 From c031b9d9cd1ea41ab68f46eb5e630efaf901933a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 23 Dec 2015 19:10:13 -0500 Subject: Set initial state on parent Lexer. #3945 --- lib/rouge/lexers/gitlab_diff.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/rouge/lexers/gitlab_diff.rb b/lib/rouge/lexers/gitlab_diff.rb index e136d47df00..c7aaeb92608 100644 --- a/lib/rouge/lexers/gitlab_diff.rb +++ b/lib/rouge/lexers/gitlab_diff.rb @@ -15,6 +15,10 @@ module Rouge delegate option(:parent_lexer) end end + + start do + option(:parent_lexer).reset! + end end end end -- cgit v1.2.1 From bb96d631537d3d8181f0d3b762603a012219c3e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 30 Dec 2015 00:52:50 -0500 Subject: New implementation for highlighting diff files. #3945 * It is more performant given now we process all the diff file instead of processing line by line. * Multiline comments are highlighted correctly. --- app/helpers/application_helper.rb | 6 --- app/helpers/blob_helper.rb | 15 ------- app/helpers/diff_helper.rb | 6 +-- app/views/projects/diffs/_parallel_view.html.haml | 6 +-- app/views/projects/diffs/_text_file.html.haml | 5 +-- lib/gitlab/diff/file.rb | 4 ++ lib/gitlab/diff/highlight.rb | 55 +++++++++++++++++++++++ lib/gitlab/diff/line.rb | 1 + lib/rouge/lexers/gitlab_diff.rb | 2 +- spec/helpers/blob_helper_spec.rb | 11 ----- 10 files changed, 68 insertions(+), 43 deletions(-) create mode 100644 lib/gitlab/diff/highlight.rb diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index bc4b6ec0327..0b00b9a0702 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -326,10 +326,4 @@ module ApplicationHelper def truncate_first_line(message, length = 50) truncate(message.each_line.first.chomp, length: length) if message end - - def unescape_html(content) - text = CGI.unescapeHTML(content) - text.gsub!(' ', ' ') - text - end end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index bf18673972c..1230002e69c 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -24,21 +24,6 @@ module BlobHelper result end - def highlight_line(blob_name, content, continue: false) - if @previous_blob_name != blob_name - @parent = Rouge::Lexer.guess(filename: blob_name, source: content).new rescue Rouge::Lexers::PlainText.new - @lexer = Rouge::Lexers::GitlabDiff.new(parent_lexer: @parent) - @options = Rouge::Lexers::PlainText === @parent ? {} : { continue: continue } - end - - @previous_blob_name = blob_name - @formatter ||= rouge_formatter(nowrap: true) - - content.sub!(/\A((?:\+|-)\s*)/, '') # Don't format '+' or '-' indicators. - - "#{$1}#{@formatter.format(@lexer.lex(content, @options))}".html_safe - end - def no_highlight_files %w(credits changelog news copying copyright license authors) end diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 24134310fc5..2ff8c65e5ca 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -54,9 +54,9 @@ module DiffHelper # right_line_type, right_line_number, right_line_content, right_line_code # ] # - diff_file.diff_lines.each do |line| + diff_file.highlighted_diff_lines.each do |line| - full_line = line.text + full_line = line.highlighted_text type = line.type line_code = generate_line_code(diff_file.file_path, line) line_new = line.new_pos @@ -67,7 +67,7 @@ module DiffHelper if next_line next_line_code = generate_line_code(diff_file.file_path, next_line) next_type = next_line.type - next_line = next_line.text + next_line = next_line.highlighted_text end if type == 'match' || type.nil? diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index c6a9d71e789..4ded4d2daad 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -20,8 +20,7 @@ = link_to raw(line_number_left), "##{line_code_left}", id: line_code_left - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_left, 'old') - %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }< - = highlight_line(diff_file.new_path, unescape_html(line_content_left)) + %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= raw(line_content_left) - if type_right == 'new' - new_line_class = 'new' @@ -34,8 +33,7 @@ = link_to raw(line_number_right), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_right, 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}< - = highlight_line(diff_file.new_path, unescape_html(line_content_right)) + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= raw(line_content_right) - if @reply_allowed - comments_left, comments_right = organize_comments(type_left, type_right, line_code_left, line_code_right) diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 78c66a6291e..641e9e5501a 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -6,7 +6,7 @@ %table.text-file.code.js-syntax-highlight{ class: [user_color_scheme, too_big ? 'hide' : ''] } - last_line = 0 - - diff_file.diff_lines.each_with_index do |line, index| + - diff_file.highlighted_diff_lines.each_with_index do |line, index| - type = line.type - last_line = line.new_pos - line_code = generate_line_code(diff_file.file_path, line) @@ -22,8 +22,7 @@ = link_to_new_diff_note(line_code) %td.new_line{data: {linenumber: line.new_pos}} = link_to raw(type == "old" ? " " : line.new_pos) , "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}< - = highlight_line(diff_file.new_path, unescape_html(diff_line_content(line.text))) + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw(diff_line_content(line.highlighted_text)) - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index 79061cd0141..ff8765b8e26 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -15,6 +15,10 @@ module Gitlab @lines ||= parser.parse(raw_diff.lines) end + def highlighted_diff_lines + Gitlab::Diff::Highlight.process_diff_lines(self) + end + def mode_changed? !!(diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode) end diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb new file mode 100644 index 00000000000..f10b55eb00b --- /dev/null +++ b/lib/gitlab/diff/highlight.rb @@ -0,0 +1,55 @@ +module Gitlab + module Diff + class Highlight + def self.process_diff_lines(diff_file) + processor = new(diff_file) + processor.highlight + end + + def initialize(diff_file) + text_lines = diff_file.diff_lines.map(&:text) + @diff_file = diff_file + @diff_lines = diff_file.diff_lines + @diff_line_prefixes = text_lines.map { |line| line.sub!(/\A((\+|\-)\s*)/, '');$1 } + @raw_lines = text_lines.join("\n") + end + + def highlight + @code = unescape_html(@raw_lines) + @highlighted_code = formatter.format(lexer.lex(@code)) + + update_diff_lines + end + + private + + def update_diff_lines + @highlighted_code.lines.each_with_index do |line, i| + @diff_lines[i].highlighted_text = "#{@diff_line_prefixes[i]}#{line}" + end + + @diff_lines + end + + def lexer + parent = Rouge::Lexer.guess(filename: @diff_file.new_path, source: @code).new rescue Rouge::Lexers::PlainText.new + Rouge::Lexers::GitlabDiff.new(parent_lexer: parent) + end + + def unescape_html(content) + text = CGI.unescapeHTML(content) + text.gsub!(' ', ' ') + text + end + + def formatter + @formatter ||= Rouge::Formatters::HTMLGitlab.new( + nowrap: true, + cssclass: 'code highlight', + lineanchors: true, + lineanchorsid: 'LC' + ) + end + end + end +end diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb index 0072194606e..c48c69fb344 100644 --- a/lib/gitlab/diff/line.rb +++ b/lib/gitlab/diff/line.rb @@ -2,6 +2,7 @@ module Gitlab module Diff class Line attr_reader :type, :text, :index, :old_pos, :new_pos + attr_accessor :highlighted_text def initialize(text, type, index, old_pos, new_pos) @text, @type, @index = text, type, index diff --git a/lib/rouge/lexers/gitlab_diff.rb b/lib/rouge/lexers/gitlab_diff.rb index c7aaeb92608..d91dd6c4245 100644 --- a/lib/rouge/lexers/gitlab_diff.rb +++ b/lib/rouge/lexers/gitlab_diff.rb @@ -11,7 +11,7 @@ module Rouge token InlineDiff, match[1] end - rule /(?:(?!puts 'Hello' world) - end - - it 'should respect the inline diff markup' do - result = highlight_line('demo.rb', "puts 'Hello' world") - expect(result).to eq(expected) - end - end end -- cgit v1.2.1 From b74f36c9caae38a1d62c18281d8240ec5905c5d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 30 Dec 2015 13:10:28 -0500 Subject: Fix Rubocop complain. #3945 --- lib/gitlab/diff/highlight.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index f10b55eb00b..adb437abed2 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -44,11 +44,11 @@ module Gitlab def formatter @formatter ||= Rouge::Formatters::HTMLGitlab.new( - nowrap: true, - cssclass: 'code highlight', - lineanchors: true, - lineanchorsid: 'LC' - ) + nowrap: true, + cssclass: 'code highlight', + lineanchors: true, + lineanchorsid: 'LC' + ) end end end -- cgit v1.2.1 From 7de90f4b53f865dc417d022a9133372e57274549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 30 Dec 2015 18:42:11 -0500 Subject: Fix broken spec and small refactor. #3945 --- app/helpers/diff_helper.rb | 4 +- app/views/projects/diffs/_text_file.html.haml | 2 +- lib/gitlab/diff/highlight.rb | 2 +- lib/gitlab/diff/line.rb | 4 +- spec/fixtures/parallel_diff_result.yml | 274 ++++++++++++++++++++++++++ spec/helpers/diff_helper_spec.rb | 30 +-- 6 files changed, 281 insertions(+), 35 deletions(-) create mode 100644 spec/fixtures/parallel_diff_result.yml diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 2ff8c65e5ca..22deb69cec5 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -56,7 +56,7 @@ module DiffHelper # diff_file.highlighted_diff_lines.each do |line| - full_line = line.highlighted_text + full_line = line.text type = line.type line_code = generate_line_code(diff_file.file_path, line) line_new = line.new_pos @@ -67,7 +67,7 @@ module DiffHelper if next_line next_line_code = generate_line_code(diff_file.file_path, next_line) next_type = next_line.type - next_line = next_line.highlighted_text + next_line = next_line.text end if type == 'match' || type.nil? diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 641e9e5501a..059d0baf45e 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -22,7 +22,7 @@ = link_to_new_diff_note(line_code) %td.new_line{data: {linenumber: line.new_pos}} = link_to raw(type == "old" ? " " : line.new_pos) , "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw(diff_line_content(line.highlighted_text)) + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw(diff_line_content(line.text)) - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index adb437abed2..d0c2e3670c6 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -25,7 +25,7 @@ module Gitlab def update_diff_lines @highlighted_code.lines.each_with_index do |line, i| - @diff_lines[i].highlighted_text = "#{@diff_line_prefixes[i]}#{line}" + @diff_lines[i].text = "#{@diff_line_prefixes[i]}#{line}" end @diff_lines diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb index c48c69fb344..03730b435ad 100644 --- a/lib/gitlab/diff/line.rb +++ b/lib/gitlab/diff/line.rb @@ -1,8 +1,8 @@ module Gitlab module Diff class Line - attr_reader :type, :text, :index, :old_pos, :new_pos - attr_accessor :highlighted_text + attr_reader :type, :index, :old_pos, :new_pos + attr_accessor :text def initialize(text, type, index, old_pos, new_pos) @text, @type, @index = text, type, index diff --git a/spec/fixtures/parallel_diff_result.yml b/spec/fixtures/parallel_diff_result.yml new file mode 100644 index 00000000000..abbb364f61f --- /dev/null +++ b/spec/fixtures/parallel_diff_result.yml @@ -0,0 +1,274 @@ +--- +- - match + - 6 + - | + @@ -6,12 +6,18 @@ module Popen + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 + - match + - 6 + - | + @@ -6,12 +6,18 @@ module Popen + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 +- - + - 6 + - | + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 + - + - 6 + - | + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 +- - + - 7 + - | + def popen(cmd, path=nil) + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 + - + - 7 + - | + def popen(cmd, path=nil) + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 +- - + - 8 + - | + unless cmd.is_a?(Array) + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 + - + - 8 + - | + unless cmd.is_a?(Array) + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 +- - old + - 9 + - | + - raise "System commands must be given as an array of strings" + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9 + - new + - 9 + - | + + raise RuntimeError, "System commands must be given as an array of strings" + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9 +- - + - 10 + - | + end + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 + - + - 10 + - | + end + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 +- - + - 11 + - | + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 + - + - 11 + - | + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 +- - + - 12 + - | + path ||= Dir.pwd + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 + - + - 12 + - | + path ||= Dir.pwd + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 +- - old + - 13 + - | + - vars = { "PWD" => path } + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13 + - old + - + - " " + - +- - old + - 14 + - | + - options = { chdir: path } + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_13 + - new + - 13 + - | + + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_13 +- - + - + - " " + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 + - new + - 14 + - | + + vars = { + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 +- - + - + - " " + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 + - new + - 15 + - | + + "PWD" => path + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 +- - + - + - " " + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 + - new + - 16 + - | + + } + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 +- - + - + - " " + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 + - new + - 17 + - | + + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 +- - + - + - " " + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 + - new + - 18 + - | + + options = { + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 +- - + - + - " " + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 + - new + - 19 + - | + + chdir: path + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 +- - + - + - " " + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 + - new + - 20 + - | + + } + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 +- - + - 15 + - | + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 + - + - 21 + - | + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 +- - + - 16 + - | + unless File.directory?(path) + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 + - + - 22 + - | + unless File.directory?(path) + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 +- - + - 17 + - | + FileUtils.mkdir_p(path) + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 + - + - 23 + - | + FileUtils.mkdir_p(path) + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 +- - match + - 19 + - | + @@ -19,6 +25,7 @@ module Popen + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 + - match + - 25 + - | + @@ -19,6 +25,7 @@ module Popen + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 +- - + - 19 + - | + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 + - + - 25 + - | + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 +- - + - 20 + - | + @cmd_output = "" + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 + - + - 26 + - | + @cmd_output = "" + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 +- - + - 21 + - | + @cmd_status = 0 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 + - + - 27 + - | + @cmd_status = 0 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 +- - + - + - " " + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 + - new + - 28 + - | + + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 +- - + - 22 + - | + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 + - + - 29 + - | + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 +- - + - 23 + - | + @cmd_output << stdout.read + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 + - + - 30 + - | + @cmd_output << stdout.read + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 +- - + - 24 + - @cmd_output << stderr.read + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 + - + - 31 + - @cmd_output << stderr.read + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 7c96a74e581..0501c2e8c29 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -131,34 +131,6 @@ describe DiffHelper do end def parallel_diff_result_array - [ - ["match", 6, "@@ -6,12 +6,18 @@ module Popen", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6", "match", 6, "@@ -6,12 +6,18 @@ module Popen", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6"], - [nil, 6, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6", nil, 6, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6"], [nil, 7, " def popen(cmd, path=nil)", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7", nil, 7, " def popen(cmd, path=nil)", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"], - [nil, 8, " unless cmd.is_a?(Array)", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8", nil, 8, " unless cmd.is_a?(Array)", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8"], - ["old", 9, "- raise "System commands must be given as an array of strings"", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9", "new", 9, "+ raise RuntimeError, "System commands must be given as an array of strings"", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"], - [nil, 10, " end", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10", nil, 10, " end", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10"], - [nil, 11, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11", nil, 11, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11"], - [nil, 12, " path ||= Dir.pwd", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12", nil, 12, " path ||= Dir.pwd", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12"], - ["old", 13, "- vars = { "PWD" => path }", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13", "old", nil, " ", nil], - ["old", 14, "- options = { chdir: path }", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_13", "new", 13, "+", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_13"], - [nil, nil, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14", "new", 14, "+ vars = {", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14"], - [nil, nil, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15", "new", 15, "+ "PWD" => path", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15"], - [nil, nil, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16", "new", 16, "+ }", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16"], - [nil, nil, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17", "new", 17, "+", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17"], - [nil, nil, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18", "new", 18, "+ options = {", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18"], - [nil, nil, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19", "new", 19, "+ chdir: path", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19"], - [nil, nil, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20", "new", 20, "+ }", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20"], - [nil, 15, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21", nil, 21, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21"], - [nil, 16, " unless File.directory?(path)", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22", nil, 22, " unless File.directory?(path)", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22"], - [nil, 17, " FileUtils.mkdir_p(path)", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23", nil, 23, " FileUtils.mkdir_p(path)", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23"], - ["match", 19, "@@ -19,6 +25,7 @@ module Popen", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25", "match", 25, "@@ -19,6 +25,7 @@ module Popen", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25"], - [nil, 19, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25", nil, 25, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25"], - [nil, 20, " @cmd_output = """, "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26", nil, 26, " @cmd_output = """, "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26"], - [nil, 21, " @cmd_status = 0", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27", nil, 27, " @cmd_status = 0", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27"], - [nil, nil, " ", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28", "new", 28, "+", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28"], - [nil, 22, " Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29", nil, 29, " Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29"], - [nil, 23, " @cmd_output << stdout.read", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30", nil, 30, " @cmd_output << stdout.read", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30"], - [nil, 24, " @cmd_output << stderr.read", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31", nil, 31, " @cmd_output << stderr.read", "2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31"] - ] + YAML.load_file("#{Rails.root}/spec/fixtures/parallel_diff_result.yml") end end -- cgit v1.2.1 From d83275620a0eeaf17a2958e59e2b4d6f217c6464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 30 Dec 2015 20:18:40 -0500 Subject: Add specs for Gitlab::Diff::Highlight. #3945 --- spec/lib/gitlab/diff/highlight_spec.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 spec/lib/gitlab/diff/highlight_spec.rb diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb new file mode 100644 index 00000000000..2a827a08dba --- /dev/null +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe Gitlab::Diff::Highlight, lib: true do + include RepoHelpers + + let(:project) { create(:project) } + let(:commit) { project.commit(sample_commit.id) } + let(:diff) { commit.diffs.first } + let(:diff_file) { Gitlab::Diff::File.new(diff) } + + describe '.process_diff_lines' do + let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file) } + + it 'should return Gitlab::Diff::Line elements' do + expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line) + end + + it 'should highlight the code' do + code = %Q{ def popen(cmd, path=nil)\n} + + expect(diff_lines[2].text).to eq(code) + end + + it 'should keep the inline diff markup' do + expect(diff_lines[5].text).to match(Regexp.new(Regexp.escape('RuntimeError, '))) + end + end +end -- cgit v1.2.1 From 8b079315d98a8ccf852592148632c6f052d9cb55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 30 Dec 2015 21:23:50 -0500 Subject: A bit of refactoring. #3945 --- lib/gitlab/diff/file.rb | 2 +- lib/gitlab/diff/highlight.rb | 16 ++++++++-------- lib/rouge/lexers/gitlab_diff.rb | 2 ++ spec/lib/gitlab/diff/highlight_spec.rb | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index ff8765b8e26..69b38a32eeb 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -16,7 +16,7 @@ module Gitlab end def highlighted_diff_lines - Gitlab::Diff::Highlight.process_diff_lines(self) + Gitlab::Diff::Highlight.process_diff_lines(new_path, diff_lines) end def mode_changed? diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index d0c2e3670c6..40a54ede2bb 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -1,15 +1,15 @@ module Gitlab module Diff class Highlight - def self.process_diff_lines(diff_file) - processor = new(diff_file) + def self.process_diff_lines(file_name, diff_lines) + processor = new(file_name, diff_lines) processor.highlight end - def initialize(diff_file) - text_lines = diff_file.diff_lines.map(&:text) - @diff_file = diff_file - @diff_lines = diff_file.diff_lines + def initialize(file_name, diff_lines) + text_lines = diff_lines.map(&:text) + @file_name = file_name + @diff_lines = diff_lines @diff_line_prefixes = text_lines.map { |line| line.sub!(/\A((\+|\-)\s*)/, '');$1 } @raw_lines = text_lines.join("\n") end @@ -32,7 +32,7 @@ module Gitlab end def lexer - parent = Rouge::Lexer.guess(filename: @diff_file.new_path, source: @code).new rescue Rouge::Lexers::PlainText.new + parent = Rouge::Lexer.guess(filename: @file_name, source: @code).new rescue Rouge::Lexers::PlainText.new Rouge::Lexers::GitlabDiff.new(parent_lexer: parent) end @@ -43,7 +43,7 @@ module Gitlab end def formatter - @formatter ||= Rouge::Formatters::HTMLGitlab.new( + Rouge::Formatters::HTMLGitlab.new( nowrap: true, cssclass: 'code highlight', lineanchors: true, diff --git a/lib/rouge/lexers/gitlab_diff.rb b/lib/rouge/lexers/gitlab_diff.rb index d91dd6c4245..cbf272ee1de 100644 --- a/lib/rouge/lexers/gitlab_diff.rb +++ b/lib/rouge/lexers/gitlab_diff.rb @@ -2,6 +2,8 @@ Rouge::Token::Tokens.token(:InlineDiff, 'idiff') module Rouge module Lexers + # This new Lexer is required in order to avoid the inline diff markup + # to be tokenized, it will be rendered as raw HTML code if that happens. class GitlabDiff < RegexLexer title "GitLab Diff" tag 'gitlab_diff' diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index 2a827a08dba..80083c15cff 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -9,7 +9,7 @@ describe Gitlab::Diff::Highlight, lib: true do let(:diff_file) { Gitlab::Diff::File.new(diff) } describe '.process_diff_lines' do - let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file) } + let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file.new_path, diff_file.diff_lines) } it 'should return Gitlab::Diff::Line elements' do expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line) -- cgit v1.2.1 From fd100e1ef1726418c81ab8833cf8bcf86fab6eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 30 Dec 2015 21:44:12 -0500 Subject: Don't modify "match" diff lines. #3945 --- lib/gitlab/diff/highlight.rb | 7 ++++++- spec/lib/gitlab/diff/highlight_spec.rb | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 40a54ede2bb..c780ea21775 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -25,7 +25,12 @@ module Gitlab def update_diff_lines @highlighted_code.lines.each_with_index do |line, i| - @diff_lines[i].text = "#{@diff_line_prefixes[i]}#{line}" + diff_line = @diff_lines[i] + + # ignore highlighting for "match" lines + next if diff_line.type == 'match' + + diff_line.text = "#{@diff_line_prefixes[i]}#{line}" end @diff_lines diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index 80083c15cff..54621f773d7 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -24,5 +24,10 @@ describe Gitlab::Diff::Highlight, lib: true do it 'should keep the inline diff markup' do expect(diff_lines[5].text).to match(Regexp.new(Regexp.escape('RuntimeError, '))) end + + it 'should not modify "match" lines' do + expect(diff_lines[0].text).to eq('@@ -6,12 +6,18 @@ module Popen') + expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') + end end end -- cgit v1.2.1 From 3fbcf52ec8decc3a4e331d52b2f47d7b85d399cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Thu, 31 Dec 2015 01:05:52 -0500 Subject: Apply syntax highlighting when expanding diff plus some refactor. #3945 --- app/controllers/projects/blob_controller.rb | 2 +- app/views/projects/blob/diff.html.haml | 2 +- lib/gitlab/diff/highlight.rb | 55 ++++++++++++++++++++++------- spec/lib/gitlab/diff/highlight_spec.rb | 42 +++++++++++++++------- 4 files changed, 74 insertions(+), 27 deletions(-) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index c56a3497bb2..d22c7b550b0 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -66,7 +66,7 @@ class Projects::BlobController < Projects::ApplicationController def diff @form = UnfoldForm.new(params) - @lines = @blob.data.lines[@form.since - 1..@form.to - 1] + @lines = Gitlab::Diff::Highlight.process_diff_lines(@blob.name, @blob.data.lines[@form.since - 1..@form.to - 1]) if @form.bottom? @match_line = '' diff --git a/app/views/projects/blob/diff.html.haml b/app/views/projects/blob/diff.html.haml index f3b01ff3288..9d8f6ecb3ac 100644 --- a/app/views/projects/blob/diff.html.haml +++ b/app/views/projects/blob/diff.html.haml @@ -11,7 +11,7 @@ %td.old_line.diff-line-num{data: {linenumber: line_old}} = link_to raw(line_old), "#" %td.new_line= link_to raw(line_new) , "#" - %td.line_content.noteable_line= ' ' * @form.indent + line + %td.line_content.noteable_line= raw("#{' ' * @form.indent}#{line}") - if @form.unfold? && @form.bottom? && @form.to < @blob.loc %tr.line_holder{ id: @form.to } diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index c780ea21775..7f340de65cc 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -1,31 +1,62 @@ module Gitlab module Diff class Highlight - def self.process_diff_lines(file_name, diff_lines) - processor = new(file_name, diff_lines) + # Apply syntax highlight to provided source code + # + # file_name - The file name related to the code. + # 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. + def self.process_diff_lines(file_name, lines) + processor = new(file_name, lines) processor.highlight end - def initialize(file_name, diff_lines) - text_lines = diff_lines.map(&:text) - @file_name = file_name - @diff_lines = diff_lines - @diff_line_prefixes = text_lines.map { |line| line.sub!(/\A((\+|\-)\s*)/, '');$1 } - @raw_lines = text_lines.join("\n") + def initialize(file_name, lines) + @file_name = file_name + @lines = lines end def highlight - @code = unescape_html(@raw_lines) + return [] if @lines.empty? + + extract_line_prefixes + + @code = unescape_html(raw_content) @highlighted_code = formatter.format(lexer.lex(@code)) - update_diff_lines + is_diff_line? ? update_diff_lines : @highlighted_code.lines end private + def is_diff_line? + @lines.first.is_a?(Gitlab::Diff::Line) + end + + def text_lines + @text_lines ||= (is_diff_line? ? @lines.map(&:text) : @lines) + end + + def raw_content + @raw_content ||= text_lines.join(is_diff_line? ? "\n" : nil) + end + + def extract_line_prefixes + @diff_line_prefixes ||= begin + if is_diff_line? + text_lines.map { |line| line.sub!(/\A((\+|\-)\s*)/, '');$1 } + else + [] + end + end + end + def update_diff_lines @highlighted_code.lines.each_with_index do |line, i| - diff_line = @diff_lines[i] + diff_line = @lines[i] # ignore highlighting for "match" lines next if diff_line.type == 'match' @@ -33,7 +64,7 @@ module Gitlab diff_line.text = "#{@diff_line_prefixes[i]}#{line}" end - @diff_lines + @lines end def lexer diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index 54621f773d7..fc5cb894d2a 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -9,25 +9,41 @@ describe Gitlab::Diff::Highlight, lib: true do let(:diff_file) { Gitlab::Diff::File.new(diff) } describe '.process_diff_lines' do - let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file.new_path, diff_file.diff_lines) } + context 'when processing Gitlab::Diff::Line objects' do + let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file.new_path, diff_file.diff_lines) } - it 'should return Gitlab::Diff::Line elements' do - expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line) - end + it 'should return Gitlab::Diff::Line elements' do + expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line) + end - it 'should highlight the code' do - code = %Q{ def popen(cmd, path=nil)\n} + it 'should highlight the code' do + code = %Q{ def popen(cmd, path=nil)\n} - expect(diff_lines[2].text).to eq(code) - end + expect(diff_lines[2].text).to eq(code) + end + + it 'should keep the inline diff markup' do + expect(diff_lines[5].text).to match(Regexp.new(Regexp.escape('RuntimeError, '))) + end - it 'should keep the inline diff markup' do - expect(diff_lines[5].text).to match(Regexp.new(Regexp.escape('RuntimeError, '))) + it 'should not modify "match" lines' do + expect(diff_lines[0].text).to eq('@@ -6,12 +6,18 @@ module Popen') + expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') + end end - it 'should not modify "match" lines' do - expect(diff_lines[0].text).to eq('@@ -6,12 +6,18 @@ module Popen') - expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') + context 'when processing raw lines' do + let(:lines) { ["puts 'Hello'\n", "# A comment"] } + let(:highlighted_lines) { Gitlab::Diff::Highlight.process_diff_lines('demo.rb', lines) } + + it 'should highlight the code' do + line_1 = %Q{puts 'Hello'\n} + line_2 = %Q{# A comment} + + expect(highlighted_lines[0]).to eq(line_1) + expect(highlighted_lines[1]).to eq(line_2) + end end + end end -- cgit v1.2.1 From 795ecb498c74d7fbc2db461b3d37ff10b350a3c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Thu, 31 Dec 2015 01:46:52 -0500 Subject: Fix broken spec. #3945 --- spec/fixtures/parallel_diff_result.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/spec/fixtures/parallel_diff_result.yml b/spec/fixtures/parallel_diff_result.yml index abbb364f61f..16c4bac96df 100644 --- a/spec/fixtures/parallel_diff_result.yml +++ b/spec/fixtures/parallel_diff_result.yml @@ -1,13 +1,11 @@ --- - - match - 6 - - | - @@ -6,12 +6,18 @@ module Popen + - '@@ -6,12 +6,18 @@ module Popen' - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - match - 6 - - | - @@ -6,12 +6,18 @@ module Popen + - '@@ -6,12 +6,18 @@ module Popen' - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - - - 6 @@ -193,13 +191,11 @@ - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 - - match - 19 - - | - @@ -19,6 +25,7 @@ module Popen + - '@@ -19,6 +25,7 @@ module Popen' - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - match - 25 - - | - @@ -19,6 +25,7 @@ module Popen + - '@@ -19,6 +25,7 @@ module Popen' - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - - - 19 -- cgit v1.2.1 From 776d70d11b822e5991d518e91b138853275ef42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 6 Jan 2016 19:54:36 -0500 Subject: Use #html_safe instead of #raw in some diff views. #3945 --- app/views/projects/blob/diff.html.haml | 2 +- app/views/projects/diffs/_parallel_view.html.haml | 4 ++-- app/views/projects/diffs/_text_file.html.haml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/views/projects/blob/diff.html.haml b/app/views/projects/blob/diff.html.haml index 9d8f6ecb3ac..ef23876677a 100644 --- a/app/views/projects/blob/diff.html.haml +++ b/app/views/projects/blob/diff.html.haml @@ -11,7 +11,7 @@ %td.old_line.diff-line-num{data: {linenumber: line_old}} = link_to raw(line_old), "#" %td.new_line= link_to raw(line_new) , "#" - %td.line_content.noteable_line= raw("#{' ' * @form.indent}#{line}") + %td.line_content.noteable_line= "#{' ' * @form.indent}#{line}".html_safe - if @form.unfold? && @form.bottom? && @form.to < @blob.loc %tr.line_holder{ id: @form.to } diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 4ded4d2daad..6a7d4f2db20 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -20,7 +20,7 @@ = link_to raw(line_number_left), "##{line_code_left}", id: line_code_left - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_left, 'old') - %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= raw(line_content_left) + %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= line_content_left.html_safe - if type_right == 'new' - new_line_class = 'new' @@ -33,7 +33,7 @@ = link_to raw(line_number_right), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_right, 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= raw(line_content_right) + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= line_content_right.html_safe - if @reply_allowed - comments_left, comments_right = organize_comments(type_left, type_right, line_code_left, line_code_right) diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 059d0baf45e..5509d5403b0 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -21,8 +21,8 @@ - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code) %td.new_line{data: {linenumber: line.new_pos}} - = link_to raw(type == "old" ? " " : line.new_pos) , "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw(diff_line_content(line.text)) + = link_to raw(type == "old" ? " " : line.new_pos), "##{line_code}", id: line_code + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= diff_line_content(line.text).html_safe - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) -- cgit v1.2.1 From 1494bb3f253b2e37065080c27af22ec531966ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 6 Jan 2016 21:01:44 -0500 Subject: Force white theme when viewing diffs. #3945 --- app/views/projects/diffs/_parallel_view.html.haml | 2 +- app/views/projects/diffs/_text_file.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 6a7d4f2db20..2a43bbd11f2 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -1,5 +1,5 @@ / Side-by-side diff view -%div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight{ class: user_color_scheme } +%div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight.white %table - parallel_diff(diff_file, index).each do |line| - type_left = line[0] diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 5509d5403b0..8e86219155f 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -3,7 +3,7 @@ .suppressed-container %a.show-suppressed-diff.js-show-suppressed-diff Changes suppressed. Click to show. -%table.text-file.code.js-syntax-highlight{ class: [user_color_scheme, too_big ? 'hide' : ''] } +%table.text-file.code.js-syntax-highlight.white{ class: too_big ? 'hide' : '' } - last_line = 0 - diff_file.highlighted_diff_lines.each_with_index do |line, index| -- cgit v1.2.1 From 21958a393955037318141d39fbe14b1c2e842cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Thu, 7 Jan 2016 13:45:19 -0500 Subject: Add some styling for syntax highlighting themes. #3945 --- app/assets/stylesheets/highlight/dark.scss | 14 ++++++++++++++ app/assets/stylesheets/highlight/monokai.scss | 18 ++++++++++++++++++ app/assets/stylesheets/highlight/solarized_dark.scss | 14 ++++++++++++++ app/assets/stylesheets/highlight/solarized_light.scss | 15 +++++++++++++++ app/assets/stylesheets/pages/diff.scss | 15 +++++++++++++++ app/views/projects/diffs/_parallel_view.html.haml | 2 +- app/views/projects/diffs/_text_file.html.haml | 2 +- 7 files changed, 78 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss index 6a2b25ddc67..f7d1334705f 100644 --- a/app/assets/stylesheets/highlight/dark.scss +++ b/app/assets/stylesheets/highlight/dark.scss @@ -90,4 +90,18 @@ .vg { color: #cc6666 } /* Name.Variable.Global */ .vi { color: #cc6666 } /* Name.Variable.Instance */ .il { color: #de935f } /* Literal.Number.Integer.Long */ + + .line_holder { + &.new .old_line, + &.new .new_line, + &.new .line_content { + @include diff_background(255, 255, 255, #808080); + } + + &.old .old_line, + &.old .new_line, + &.old .line_content { + @include diff_background(255, 51, 51, #808080); + } + } } diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss index 8560c3c490f..cc03ed6ae45 100644 --- a/app/assets/stylesheets/highlight/monokai.scss +++ b/app/assets/stylesheets/highlight/monokai.scss @@ -90,4 +90,22 @@ .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */ .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */ + + .line_holder { + &.parallel .new.new_line, + &.parallel .new.line_content, + &.new .old_line, + &.new .new_line, + &.new .line_content { + @include diff_background(156, 175, 183, #808080); + } + + &.parallel .old.old_line, + &.parallel .old.line_content, + &.old .old_line, + &.old .new_line, + &.old .line_content { + @include diff_background(254, 147, 140, #808080); + } + } } diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss index 7d489a9666b..2c3648274cf 100644 --- a/app/assets/stylesheets/highlight/solarized_dark.scss +++ b/app/assets/stylesheets/highlight/solarized_dark.scss @@ -111,4 +111,18 @@ .vg { color: #268bd2 } /* Name.Variable.Global */ .vi { color: #268bd2 } /* Name.Variable.Instance */ .il { color: #2aa198 } /* Literal.Number.Integer.Long */ + + .line_holder { + &.new .old_line, + &.new .new_line, + &.new .line_content { + @include diff_background(255, 255, 255, #808080); + } + + &.old .old_line, + &.old .new_line, + &.old .line_content { + @include diff_background(255, 51, 51, #808080); + } + } } diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss index 200ed346446..c16473ffe66 100644 --- a/app/assets/stylesheets/highlight/solarized_light.scss +++ b/app/assets/stylesheets/highlight/solarized_light.scss @@ -111,4 +111,19 @@ .vg { color: #268bd2 } /* Name.Variable.Global */ .vi { color: #268bd2 } /* Name.Variable.Instance */ .il { color: #2aa198 } /* Literal.Number.Integer.Long */ + + + .line_holder { + &.new .old_line, + &.new .new_line, + &.new .line_content { + @include diff_background(92, 164, 169, #FAF3DD); + } + + &.old .old_line, + &.old .new_line, + &.old .line_content { + @include diff_background(237, 106, 90, #FAF3DD); + } + } } diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index afd6fb73675..caaad1e31d3 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -402,3 +402,18 @@ right: 15px; } } + +@mixin diff_background($r, $g, $b, $custom-border) { + /* Fallback for web browsers that doesn't support RGBa */ + background: rgb($r, $g, $b); + /* RGBa with 0.3 opacity */ + background: rgba($r, $g, $b, 0.3); + + &.new_line, &.old_line { + border-right-color: $custom-border !important; + } + + &.line_content span.idiff { + background: rgb($r, $g, $b); + } +} diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 2a43bbd11f2..1ad54d1848b 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -1,5 +1,5 @@ / Side-by-side diff view -%div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight.white +%div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight %table - parallel_diff(diff_file, index).each do |line| - type_left = line[0] diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 8e86219155f..f1b8cba5e55 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -3,7 +3,7 @@ .suppressed-container %a.show-suppressed-diff.js-show-suppressed-diff Changes suppressed. Click to show. -%table.text-file.code.js-syntax-highlight.white{ class: too_big ? 'hide' : '' } +%table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' } - last_line = 0 - diff_file.highlighted_diff_lines.each_with_index do |line, index| -- cgit v1.2.1 From f1f4fdf778245cab74ff9cda2a421315c21a99aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Thu, 7 Jan 2016 21:08:57 -0500 Subject: Don't process inline diffs on backend. #3945 --- lib/gitlab/diff/parser.rb | 5 +- lib/gitlab/inline_diff.rb | 104 ------------------------------------ spec/lib/gitlab/inline_diff_spec.rb | 39 -------------- 3 files changed, 1 insertion(+), 147 deletions(-) delete mode 100644 lib/gitlab/inline_diff.rb delete mode 100644 spec/lib/gitlab/inline_diff_spec.rb diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb index 7015fe36c3d..177bad4b1cf 100644 --- a/lib/gitlab/diff/parser.rb +++ b/lib/gitlab/diff/parser.rb @@ -11,13 +11,10 @@ module Gitlab line_new = 1 type = nil - lines_arr = ::Gitlab::InlineDiff.processing lines - - lines_arr.each do |line| + @lines.each do |line| next if filename?(line) full_line = html_escape(line.gsub(/\n/, '')) - full_line = ::Gitlab::InlineDiff.replace_markers full_line if line.match(/^@@ -/) type = "match" diff --git a/lib/gitlab/inline_diff.rb b/lib/gitlab/inline_diff.rb deleted file mode 100644 index 44507bde25d..00000000000 --- a/lib/gitlab/inline_diff.rb +++ /dev/null @@ -1,104 +0,0 @@ -module Gitlab - class InlineDiff - class << self - - START = "#!idiff-start!#" - FINISH = "#!idiff-finish!#" - - 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] - - # 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) - - last_token = find_last_token(first_line, second_line, first_token) - apply_last_token(diff_arr, index, last_token) - end - - diff_arr - end - - 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 - end - end - - first_line[0..first_the_same_symbols][1..-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 - - (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 - - 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 - - def replace_markers(line) - line.gsub!(START, "") - line.gsub!(FINISH, "") - line - end - end - end -end diff --git a/spec/lib/gitlab/inline_diff_spec.rb b/spec/lib/gitlab/inline_diff_spec.rb deleted file mode 100644 index c690c195112..00000000000 --- a/spec/lib/gitlab/inline_diff_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'spec_helper' - -describe Gitlab::InlineDiff, lib: true do - describe '#processing' do - let(:diff) do - < Date: Thu, 7 Jan 2016 22:37:01 -0500 Subject: 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. --- app/controllers/application_controller.rb | 1 + app/controllers/projects/blob_controller.rb | 7 ++- app/controllers/projects/commit_controller.rb | 1 + app/controllers/projects/compare_controller.rb | 1 + .../projects/merge_requests_controller.rb | 2 + app/helpers/diff_helper.rb | 4 +- app/views/projects/commit/show.html.haml | 3 +- app/views/projects/compare/show.html.haml | 2 +- app/views/projects/diffs/_diffs.html.haml | 2 +- .../projects/merge_requests/_new_submit.html.haml | 2 +- .../projects/merge_requests/show/_diffs.html.haml | 2 +- lib/gitlab/diff/file.rb | 8 ++- lib/gitlab/diff/highlight.rb | 70 ++++++++++++++++------ 13 files changed, 76 insertions(+), 29 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d9a37a4d45f..d3c1ff035f5 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -24,6 +24,7 @@ class ApplicationController < ActionController::Base 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 :repository rescue_from Encoding::CompatibilityError do |exception| log_exception(exception) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index d22c7b550b0..6aa602321f4 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -65,8 +65,11 @@ class Projects::BlobController < Projects::ApplicationController end def diff - @form = UnfoldForm.new(params) - @lines = Gitlab::Diff::Highlight.process_diff_lines(@blob.name, @blob.data.lines[@form.since - 1..@form.to - 1]) + ref, file_name = params[:id].split('/', 2) + + @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? @match_line = '' diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 0aaba3792bf..9bbf4581057 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -72,6 +72,7 @@ class Projects::CommitController < Projects::ApplicationController @diffs = commit.diffs end + @diff_refs = [commit.parent.id, commit.id] @notes_count = commit.notes.count @statuses = ci_commit.statuses if ci_commit diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 5200d609cc9..5b88aed7a64 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -20,6 +20,7 @@ class Projects::CompareController < Projects::ApplicationController if compare_result @commits = Commit.decorate(compare_result.commits, @project) @diffs = compare_result.diffs + @diff_refs = [base_ref, head_ref] @commit = @project.commit(head_ref) @first_commit = @project.commit(base_ref) @line_notes = [] diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index ab5c953189c..d25adbe952d 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -59,6 +59,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController def diffs @commit = @merge_request.last_commit @first_commit = @merge_request.first_commit + @diff_refs = [@merge_request.target_sha, @merge_request.source_sha] @comments_allowed = @reply_allowed = true @comments_target = { @@ -103,6 +104,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController @commit = @merge_request.last_commit @first_commit = @merge_request.first_commit @diffs = @merge_request.compare_diffs + @diff_refs = [@merge_request.target_sha, @merge_request.source_branch] @ci_commit = @merge_request.ci_commit @statuses = @ci_commit.statuses if @ci_commit diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 22deb69cec5..668610364c5 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -19,13 +19,13 @@ module DiffHelper end end - def safe_diff_files(diffs) + def safe_diff_files(diffs, diff_refs, repository) lines = 0 safe_files = [] diffs.first(allowed_diff_size).each do |diff| lines += diff.diff.lines.count break if lines > allowed_diff_lines - safe_files << Gitlab::Diff::File.new(diff) + safe_files << Gitlab::Diff::File.new(diff, diff_refs, repository) end safe_files end diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 069b8b1f169..16ebce2d771 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -5,5 +5,6 @@ = render "ci_menu" - else %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" diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 51088a7dea8..da731f28bb6 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -9,7 +9,7 @@ - if @commits.present? .prepend-top-default = 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 .light-well.prepend-top-default .center diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index f9d661d59d2..58ad7d79af9 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -1,7 +1,7 @@ - if diff_view == 'parallel' - 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 .inline-parallel-buttons diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index a14943b15d3..0cb8b6daedb 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -38,7 +38,7 @@ = render "projects/merge_requests/show/commits" #diffs.diffs.tab-pane.active - 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 .alert.alert-danger %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits. diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml index d9cfc3d7ae9..1d9af1e4160 100644 --- a/app/views/projects/merge_requests/show/_diffs.html.haml +++ b/app/views/projects/merge_requests/show/_diffs.html.haml @@ -1,5 +1,5 @@ - 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? .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch} - else diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index 69b38a32eeb..cb93c6a574a 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -1,13 +1,15 @@ module Gitlab module Diff class File - attr_reader :diff + attr_reader :diff, :repository, :new_ref, :old_ref delegate :new_file, :deleted_file, :renamed_file, :old_path, :new_path, to: :diff, prefix: false - def initialize(diff) + def initialize(diff, diff_refs, repository) @diff = diff + @repository = repository + @old_ref, @new_ref = diff_refs end # Array of Gitlab::DIff::Line objects @@ -16,7 +18,7 @@ module Gitlab end def highlighted_diff_lines - Gitlab::Diff::Highlight.process_diff_lines(new_path, diff_lines) + Gitlab::Diff::Highlight.process_diff_lines(self) end def mode_changed? diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 7f340de65cc..0d0a3268107 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -1,22 +1,43 @@ module Gitlab module Diff 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 # - # file_name - The file name related to the code. - # 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. + # diff_file - an instance of Gitlab::Diff::File # # Returns an Array with the processed items. - def self.process_diff_lines(file_name, lines) - processor = new(file_name, lines) + def self.process_diff_lines(diff_file) + processor = new(diff_file) processor.highlight end - def initialize(file_name, lines) - @file_name = file_name - @lines = lines + def self.process_file(repository, ref, file_name) + blob = repository.blob_at(ref, file_name) + 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 def highlight @@ -47,7 +68,7 @@ module Gitlab def extract_line_prefixes @diff_line_prefixes ||= begin if is_diff_line? - text_lines.map { |line| line.sub!(/\A((\+|\-)\s*)/, '');$1 } + text_lines.map { |line| line.sub!(/\A((\+|\-))/, '');$1 } else [] end @@ -57,11 +78,17 @@ module Gitlab def update_diff_lines @highlighted_code.lines.each_with_index do |line, i| diff_line = @lines[i] + line_prefix = @diff_line_prefixes[i] || ' ' # ignore highlighting for "match" lines 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 @lines @@ -79,12 +106,21 @@ module Gitlab end def formatter - Rouge::Formatters::HTMLGitlab.new( - nowrap: true, - cssclass: 'code highlight', - lineanchors: true, - lineanchorsid: 'LC' - ) + self.class.formatter + end + + def old_lines + @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 -- cgit v1.2.1 From 6282202ee84f80f2197698b6f132abdf588e94d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Fri, 8 Jan 2016 15:17:45 -0500 Subject: Remove custom Lexer. #3945 [ci skip] Inline diff is going to be generated client side now. #3945 --- lib/gitlab/diff/highlight.rb | 3 +-- lib/rouge/lexers/gitlab_diff.rb | 26 -------------------------- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 lib/rouge/lexers/gitlab_diff.rb diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 0d0a3268107..7dd44b6004a 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -95,8 +95,7 @@ module Gitlab end def lexer - parent = Rouge::Lexer.guess(filename: @file_name, source: @code).new rescue Rouge::Lexers::PlainText.new - Rouge::Lexers::GitlabDiff.new(parent_lexer: parent) + Rouge::Lexer.guess(filename: @file_name, source: @code).new rescue Rouge::Lexers::PlainText.new end def unescape_html(content) diff --git a/lib/rouge/lexers/gitlab_diff.rb b/lib/rouge/lexers/gitlab_diff.rb deleted file mode 100644 index cbf272ee1de..00000000000 --- a/lib/rouge/lexers/gitlab_diff.rb +++ /dev/null @@ -1,26 +0,0 @@ -Rouge::Token::Tokens.token(:InlineDiff, 'idiff') - -module Rouge - module Lexers - # This new Lexer is required in order to avoid the inline diff markup - # to be tokenized, it will be rendered as raw HTML code if that happens. - class GitlabDiff < RegexLexer - title "GitLab Diff" - tag 'gitlab_diff' - - state :root do - rule %r{(.*?)} do |match| - token InlineDiff, match[1] - end - - rule /(?:(?! Date: Fri, 8 Jan 2016 18:40:05 -0500 Subject: Update specs. #3945 --- spec/lib/gitlab/diff/highlight_spec.rb | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index fc5cb894d2a..4ab509f47b9 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -6,24 +6,24 @@ describe Gitlab::Diff::Highlight, lib: true do let(:project) { create(:project) } let(:commit) { project.commit(sample_commit.id) } let(:diff) { commit.diffs.first } - let(:diff_file) { Gitlab::Diff::File.new(diff) } + let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent.id, commit.id], project.repository) } describe '.process_diff_lines' do context 'when processing Gitlab::Diff::Line objects' do - let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file.new_path, diff_file.diff_lines) } + let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file) } it 'should return Gitlab::Diff::Line elements' do expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line) end it 'should highlight the code' do - code = %Q{ def popen(cmd, path=nil)\n} + code = %Q{ def popen(cmd, path=nil)\n} expect(diff_lines[2].text).to eq(code) end - it 'should keep the inline diff markup' do - expect(diff_lines[5].text).to match(Regexp.new(Regexp.escape('RuntimeError, '))) + it 'should not generate the inline diff markup' do + expect(diff_lines[5].text).not_to match(Regexp.new(Regexp.escape(''))) end it 'should not modify "match" lines' do @@ -31,19 +31,18 @@ describe Gitlab::Diff::Highlight, lib: true do expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') end end + end - context 'when processing raw lines' do - let(:lines) { ["puts 'Hello'\n", "# A comment"] } - let(:highlighted_lines) { Gitlab::Diff::Highlight.process_diff_lines('demo.rb', lines) } - - it 'should highlight the code' do - line_1 = %Q{puts 'Hello'\n} - line_2 = %Q{# A comment} - - expect(highlighted_lines[0]).to eq(line_1) - expect(highlighted_lines[1]).to eq(line_2) - end + describe '.process_file' do + let(:lines) do + Gitlab::Diff::Highlight.process_file(project.repository, commit.id, 'files/ruby/popen.rb') end + it 'should properly highlight all the lines' do + expect(lines[4]).to eq(%Q{ extend self\n}) + expect(lines[21]).to eq(%Q{ unless File.directory?(path)\n}) + expect(lines[26]).to eq(%Q{ @cmd_status = 0\n}) + end end + end -- cgit v1.2.1 From 78d7c0e0d81c40e0d9541e4ef0dd15df30d457e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Fri, 8 Jan 2016 19:05:55 -0500 Subject: Fix broken specs. #3945 --- app/views/projects/diffs/_parallel_view.html.haml | 4 ++-- lib/gitlab/diff/highlight.rb | 10 +++++----- spec/helpers/diff_helper_spec.rb | 3 ++- spec/lib/gitlab/diff/file_spec.rb | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 1ad54d1848b..77069501d1c 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -20,7 +20,7 @@ = link_to raw(line_number_left), "##{line_code_left}", id: line_code_left - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_left, 'old') - %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= line_content_left.html_safe + %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= raw(line_content_left) - if type_right == 'new' - new_line_class = 'new' @@ -33,7 +33,7 @@ = link_to raw(line_number_right), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_right, 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= line_content_right.html_safe + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= raw(line_content_right) - if @reply_allowed - comments_left, comments_right = organize_comments(type_left, type_right, line_code_left, line_code_right) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 7dd44b6004a..caeefe5bbdd 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -27,11 +27,11 @@ module Gitlab def self.formatter @formatter ||= Rouge::Formatters::HTMLGitlab.new( - nowrap: true, - cssclass: 'code highlight', - lineanchors: true, - lineanchorsid: 'LC' - ) + nowrap: true, + cssclass: 'code highlight', + lineanchors: true, + lineanchorsid: 'LC' + ) end def initialize(diff_file) diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 0501c2e8c29..84b8f4d1679 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -7,7 +7,8 @@ describe DiffHelper do let(:commit) { project.commit(sample_commit.id) } let(:diffs) { commit.diffs } let(:diff) { diffs.first } - let(:diff_file) { Gitlab::Diff::File.new(diff) } + let(:diff_refs) { [commit.parent.id, commit.id] } + let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs, project.repository) } describe 'diff_hard_limit_enabled?' do it 'should return true if param is provided' do diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb index c7cdf8691d6..97ba7f14eb1 100644 --- a/spec/lib/gitlab/diff/file_spec.rb +++ b/spec/lib/gitlab/diff/file_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::Diff::File, lib: true do let(:project) { create(:project) } let(:commit) { project.commit(sample_commit.id) } let(:diff) { commit.diffs.first } - let(:diff_file) { Gitlab::Diff::File.new(diff) } + let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent.id, commit.id], project.repository) } describe :diff_lines do let(:diff_lines) { diff_file.diff_lines } -- cgit v1.2.1 From 164c6374a708754086a1bca1033c46c01503056d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Fri, 8 Jan 2016 19:57:51 -0500 Subject: Fix broken specs. #3945 --- spec/fixtures/parallel_diff_result.yml | 156 ++++++++++++++++----------------- spec/helpers/diff_helper_spec.rb | 17 ++-- 2 files changed, 86 insertions(+), 87 deletions(-) diff --git a/spec/fixtures/parallel_diff_result.yml b/spec/fixtures/parallel_diff_result.yml index 16c4bac96df..020c1817226 100644 --- a/spec/fixtures/parallel_diff_result.yml +++ b/spec/fixtures/parallel_diff_result.yml @@ -1,86 +1,86 @@ --- - - match - 6 - - '@@ -6,12 +6,18 @@ module Popen' + - "@@ -6,12 +6,18 @@ module Popen" - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - match - 6 - - '@@ -6,12 +6,18 @@ module Popen' + - "@@ -6,12 +6,18 @@ module Popen" - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - - - 6 - - | - + - |2 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - - 6 - - | - + - |2 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - - - 7 - - | - def popen(cmd, path=nil) + - |2 + def popen(cmd, path=nil) - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 - - 7 - - | - def popen(cmd, path=nil) + - |2 + def popen(cmd, path=nil) - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 - - - 8 - - | - unless cmd.is_a?(Array) + - |2 + unless cmd.is_a?(Array) - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 - - 8 - - | - unless cmd.is_a?(Array) + - |2 + unless cmd.is_a?(Array) - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 - - old - 9 - | - - raise "System commands must be given as an array of strings" + - raise "System commands must be given as an array of strings" - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9 - new - 9 - | - + raise RuntimeError, "System commands must be given as an array of strings" + + raise RuntimeError, "System commands must be given as an array of strings" - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9 - - - 10 - - | - end + - |2 + end - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 - - 10 - - | - end + - |2 + end - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 - - - 11 - - | - + - |2 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 - - 11 - - | - + - |2 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 - - - 12 - - | - path ||= Dir.pwd + - |2 + path ||= Dir.pwd - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 - - 12 - - | - path ||= Dir.pwd + - |2 + path ||= Dir.pwd - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 - - old - 13 - | - - vars = { "PWD" => path } + - vars = { "PWD" => path } - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13 - old - @@ -89,12 +89,12 @@ - - old - 14 - | - - options = { chdir: path } + - options = { chdir: path } - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_13 - new - 13 - | - + + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_13 - - - @@ -103,7 +103,7 @@ - new - 14 - | - + vars = { + + vars = { - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 - - - @@ -112,7 +112,7 @@ - new - 15 - | - + "PWD" => path + + "PWD" => path - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 - - - @@ -121,7 +121,7 @@ - new - 16 - | - + } + + } - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 - - - @@ -130,7 +130,7 @@ - new - 17 - | - + + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 - - - @@ -139,7 +139,7 @@ - new - 18 - | - + options = { + + options = { - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 - - - @@ -148,7 +148,7 @@ - new - 19 - | - + chdir: path + + chdir: path - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 - - - @@ -157,75 +157,75 @@ - new - 20 - | - + } + + } - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 - - - 15 - - | - + - |2 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 - - 21 - - | - + - |2 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 - - - 16 - - | - unless File.directory?(path) + - |2 + unless File.directory?(path) - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 - - 22 - - | - unless File.directory?(path) + - |2 + unless File.directory?(path) - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 - - - 17 - - | - FileUtils.mkdir_p(path) + - |2 + FileUtils.mkdir_p(path) - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 - - 23 - - | - FileUtils.mkdir_p(path) + - |2 + FileUtils.mkdir_p(path) - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 - - match - 19 - - '@@ -19,6 +25,7 @@ module Popen' + - "@@ -19,6 +25,7 @@ module Popen" - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - match - 25 - - '@@ -19,6 +25,7 @@ module Popen' + - "@@ -19,6 +25,7 @@ module Popen" - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - - - 19 - - | - + - |2 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - - 25 - - | - + - |2 + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - - - 20 - - | - @cmd_output = "" + - |2 + @cmd_output = "" - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 - - 26 - - | - @cmd_output = "" + - |2 + @cmd_output = "" - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 - - - 21 - - | - @cmd_status = 0 + - |2 + @cmd_status = 0 - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 - - 27 - - | - @cmd_status = 0 + - |2 + @cmd_status = 0 - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 - - - @@ -234,37 +234,35 @@ - new - 28 - | - + + + - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 - - - 22 - - | - Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + - |2 + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 - - 29 - - | - Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + - |2 + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 - - - 23 - - | - @cmd_output << stdout.read + - |2 + @cmd_output << stdout.read - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 - - 30 - - | - @cmd_output << stdout.read + - |2 + @cmd_output << stdout.read - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 - - - 24 - - @cmd_output << stderr.read + - |2 + @cmd_output << stderr.read - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 - - 31 - - @cmd_output << stderr.read + - |2 + @cmd_output << stderr.read - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 84b8f4d1679..4b10ee3d33c 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -4,11 +4,12 @@ describe DiffHelper do include RepoHelpers let(:project) { create(:project) } + let(:repository) { project.repository } let(:commit) { project.commit(sample_commit.id) } let(:diffs) { commit.diffs } let(:diff) { diffs.first } let(:diff_refs) { [commit.parent.id, commit.id] } - let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs, project.repository) } + let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs, repository) } describe 'diff_hard_limit_enabled?' do it 'should return true if param is provided' do @@ -45,41 +46,41 @@ describe DiffHelper do describe 'safe_diff_files' do it 'should return all files from a commit that is smaller than safe limits' do - expect(safe_diff_files(diffs).length).to eq(2) + expect(safe_diff_files(diffs, diff_refs, repository).length).to eq(2) end it 'should return only the first file if the diff line count in the 2nd file takes the total beyond safe limits' do allow(diffs[1].diff).to receive(:lines).and_return([""] * 4999) #simulate 4999 lines - expect(safe_diff_files(diffs).length).to eq(1) + expect(safe_diff_files(diffs, diff_refs, repository).length).to eq(1) end it 'should return all files from a commit that is beyond safe limit for numbers of lines if force diff is true' do allow(controller).to receive(:params) { { force_show_diff: true } } allow(diffs[1].diff).to receive(:lines).and_return([""] * 4999) #simulate 4999 lines - expect(safe_diff_files(diffs).length).to eq(2) + expect(safe_diff_files(diffs, diff_refs, repository).length).to eq(2) end it 'should return only the first file if the diff line count in the 2nd file takes the total beyond hard limits' do allow(controller).to receive(:params) { { force_show_diff: true } } allow(diffs[1].diff).to receive(:lines).and_return([""] * 49999) #simulate 49999 lines - expect(safe_diff_files(diffs).length).to eq(1) + expect(safe_diff_files(diffs, diff_refs, repository).length).to eq(1) end it 'should return only a safe number of file diffs if a commit touches more files than the safe limits' do large_diffs = diffs * 100 #simulate 200 diffs - expect(safe_diff_files(large_diffs).length).to eq(100) + expect(safe_diff_files(large_diffs, diff_refs, repository).length).to eq(100) end it 'should return all file diffs if a commit touches more files than the safe limits but force diff is true' do allow(controller).to receive(:params) { { force_show_diff: true } } large_diffs = diffs * 100 #simulate 200 diffs - expect(safe_diff_files(large_diffs).length).to eq(200) + expect(safe_diff_files(large_diffs, diff_refs, repository).length).to eq(200) end it 'should return a limited file diffs if a commit touches more files than the hard limits and force diff is true' do allow(controller).to receive(:params) { { force_show_diff: true } } very_large_diffs = diffs * 1000 #simulate 2000 diffs - expect(safe_diff_files(very_large_diffs).length).to eq(1000) + expect(safe_diff_files(very_large_diffs, diff_refs, repository).length).to eq(1000) end end -- cgit v1.2.1 From fed10766e533fcef2a6840deeb8d7ea1747f0c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Sat, 9 Jan 2016 01:55:31 -0500 Subject: Fix broken spec for submodule commit. #3945 --- lib/gitlab/diff/highlight.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index caeefe5bbdd..3c44abff3fb 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -85,10 +85,14 @@ module Gitlab case diff_line.type when 'new', nil - diff_line.text = new_lines[diff_line.new_pos - 1].try(:gsub!, /\A\s/, line_prefix) + line = new_lines[diff_line.new_pos - 1] when 'old' - diff_line.text = old_lines[diff_line.old_pos - 1].try(:gsub!, /\A\s/, line_prefix) + line = old_lines[diff_line.old_pos - 1] end + + # Only update text if line is found. This will prevent + # issues with submodules given the line only exists in diff content. + diff_line.text = line.gsub!(/\A\s/, line_prefix) if line end @lines @@ -121,6 +125,10 @@ module Gitlab lines.map! { |line| " #{line}" } end end + + def submodules + @submodules ||= diff_repository.raw_repository.submodules(diff_new_ref).keys + end end end end -- cgit v1.2.1 From ee2230c3291354035f52cc4d87e3340982367fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Sat, 9 Jan 2016 02:24:30 -0500 Subject: Fix css for other highlighting themes. #3945 --- app/assets/stylesheets/highlight/dark.scss | 4 ++++ app/assets/stylesheets/highlight/solarized_dark.scss | 4 ++++ app/assets/stylesheets/highlight/solarized_light.scss | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss index f7d1334705f..8201735beb5 100644 --- a/app/assets/stylesheets/highlight/dark.scss +++ b/app/assets/stylesheets/highlight/dark.scss @@ -92,12 +92,16 @@ .il { color: #de935f } /* Literal.Number.Integer.Long */ .line_holder { + &.parallel .new.new_line, + &.parallel .new.line_content, &.new .old_line, &.new .new_line, &.new .line_content { @include diff_background(255, 255, 255, #808080); } + &.parallel .old.old_line, + &.parallel .old.line_content, &.old .old_line, &.old .new_line, &.old .line_content { diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss index 2c3648274cf..fdfac6cd249 100644 --- a/app/assets/stylesheets/highlight/solarized_dark.scss +++ b/app/assets/stylesheets/highlight/solarized_dark.scss @@ -113,12 +113,16 @@ .il { color: #2aa198 } /* Literal.Number.Integer.Long */ .line_holder { + &.parallel .new.new_line, + &.parallel .new.line_content, &.new .old_line, &.new .new_line, &.new .line_content { @include diff_background(255, 255, 255, #808080); } + &.parallel .old.old_line, + &.parallel .old.line_content, &.old .old_line, &.old .new_line, &.old .line_content { diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss index c16473ffe66..f9788951aa8 100644 --- a/app/assets/stylesheets/highlight/solarized_light.scss +++ b/app/assets/stylesheets/highlight/solarized_light.scss @@ -114,12 +114,16 @@ .line_holder { + &.parallel .new.new_line, + &.parallel .new.line_content, &.new .old_line, &.new .new_line, &.new .line_content { @include diff_background(92, 164, 169, #FAF3DD); } + &.parallel .old.old_line, + &.parallel .old.line_content, &.old .old_line, &.old .new_line, &.old .line_content { -- cgit v1.2.1 From 4b1023105a692b3f36f2a9c51fcf193b411156ed Mon Sep 17 00:00:00 2001 From: Jeroen Nijhof Date: Mon, 11 Jan 2016 17:11:22 +0100 Subject: Add housekeeping feature documentation --- doc/README.md | 1 + doc/administration/housekeeping.md | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 doc/administration/housekeeping.md diff --git a/doc/README.md b/doc/README.md index 25fe3abcb9a..5a05fbe50d3 100644 --- a/doc/README.md +++ b/doc/README.md @@ -67,6 +67,7 @@ - [Reply by email](incoming_email/README.md) Allow users to comment on issues and merge requests by replying to notification emails. - [Migrate GitLab CI to CE/EE](migrate_ci_to_ce/README.md) Follow this guide to migrate your existing GitLab CI data to GitLab CE/EE. - [Git LFS configuration](workflow/lfs/lfs_administration.md) +- [Housekeeping](administration/housekeeping.md) Keep your git repository tidy and fast. ## Contributor documentation diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md new file mode 100644 index 00000000000..9c4fb72fd73 --- /dev/null +++ b/doc/administration/housekeeping.md @@ -0,0 +1,13 @@ +# Housekeeping + +## Introduction + +The housekeeping function runs `git gc` on the current project git repository. + +`git gc` runs a number of housekeeping tasks, such as compressing file revisions (to reduce disk space and increase performance) and removing unreachable objects which may have been created from prior invocations of git add. + +Users are encouraged to run this task on a regular basis to maintain good disk space utilization and good operating performance. + +## Where can I find it? + +Just go to your project settings page and you will find the housekeeping function below the project settings form. -- cgit v1.2.1 From 80a4c808b1e5d331833f7b2ed531cb4fc81c7ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 12 Jan 2016 11:02:16 -0500 Subject: Make diff_line_content helper return a safe String. #3945 --- app/helpers/diff_helper.rb | 4 ++-- app/views/projects/blob/preview.html.haml | 2 +- app/views/projects/diffs/_text_file.html.haml | 2 +- app/views/projects/notes/discussions/_diff.html.haml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 668610364c5..28c8e58b2ad 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -111,9 +111,9 @@ module DiffHelper def diff_line_content(line) if line.blank? - "  " + "  ".html_safe else - line + line.try(:html_safe) end end diff --git a/app/views/projects/blob/preview.html.haml b/app/views/projects/blob/preview.html.haml index e7c3460ad78..fed483d6788 100644 --- a/app/views/projects/blob/preview.html.haml +++ b/app/views/projects/blob/preview.html.haml @@ -20,6 +20,6 @@ - else %td.old_line %td.new_line - %td.line_content{class: "#{line.type}"}= raw diff_line_content(line.text) + %td.line_content{class: "#{line.type}"}= diff_line_content(line.text) - else .nothing-here-block No changes. diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index f1b8cba5e55..521f2ac1e8d 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -22,7 +22,7 @@ = link_to_new_diff_note(line_code) %td.new_line{data: {linenumber: line.new_pos}} = link_to raw(type == "old" ? " " : line.new_pos), "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= diff_line_content(line.text).html_safe + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= diff_line_content(line.text) - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) diff --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml index 0301445b5b2..97347a9f67f 100644 --- a/app/views/projects/notes/discussions/_diff.html.haml +++ b/app/views/projects/notes/discussions/_diff.html.haml @@ -24,7 +24,7 @@ = raw(type == "new" ? " " : line.old_pos) %td.new_line = raw(type == "old" ? " " : line.new_pos) - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text) + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= diff_line_content(line.text) - if line_code == note.line_code = render "projects/notes/diff_notes_with_reply", notes: discussion_notes -- cgit v1.2.1 From c476395b4d8b78cfc7431153a144ffccbd414c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 12 Jan 2016 11:14:41 -0500 Subject: Reuse existent vars with ref and path. #3945 --- app/controllers/projects/blob_controller.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 6aa602321f4..6ca3a636359 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -65,10 +65,8 @@ class Projects::BlobController < Projects::ApplicationController end def diff - ref, file_name = params[:id].split('/', 2) - @form = UnfoldForm.new(params) - @lines = Gitlab::Diff::Highlight.process_file(repository, ref, file_name) + @lines = Gitlab::Diff::Highlight.process_file(repository, @ref, @path) @lines = @lines[@form.since - 1..@form.to - 1] if @form.bottom? -- cgit v1.2.1 From f1f9b5f7d388c6d7a0938229c9211beddb2fd6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 12 Jan 2016 12:53:54 -0500 Subject: Small fixes from code review. #3945 --- app/controllers/projects/merge_requests_controller.rb | 2 +- app/helpers/blob_helper.rb | 6 +++--- lib/gitlab/diff/highlight.rb | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index d25adbe952d..b70533ef7be 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -104,7 +104,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController @commit = @merge_request.last_commit @first_commit = @merge_request.first_commit @diffs = @merge_request.compare_diffs - @diff_refs = [@merge_request.target_sha, @merge_request.source_branch] + @diff_refs = [@merge_request.target_sha, @merge_request.source_sha] @ci_commit = @merge_request.ci_commit @statuses = @ci_commit.statuses if @ci_commit diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 1230002e69c..a80162a3e33 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -11,14 +11,14 @@ module BlobHelper end def highlight(blob_name, blob_content, nowrap: false, continue: false) - @formatter ||= rouge_formatter(nowrap: nowrap) + formatter = rouge_formatter(nowrap: nowrap) begin @lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content).new - result = @formatter.format(@lexer.lex(blob_content, continue: continue)).html_safe + result = formatter.format(@lexer.lex(blob_content, continue: continue)).html_safe rescue @lexer = Rouge::Lexers::PlainText - result = @formatter.format(@lexer.lex(blob_content)).html_safe + result = formatter.format(@lexer.lex(blob_content)).html_safe end result diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 3c44abff3fb..d0137ab5f08 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -125,10 +125,6 @@ module Gitlab lines.map! { |line| " #{line}" } end end - - def submodules - @submodules ||= diff_repository.raw_repository.submodules(diff_new_ref).keys - end end end end -- cgit v1.2.1 From c0385488fbfaf1285122793cea417e607c8e771e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 12 Jan 2016 15:12:30 -0500 Subject: Fix broken spec. #3945 --- app/helpers/diff_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 28c8e58b2ad..0ec532a9a90 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -113,7 +113,8 @@ module DiffHelper if line.blank? "  ".html_safe else - line.try(:html_safe) + # Return line if it isn't a String, it helps when it's Numeric + line.is_a?(String) ? line.html_safe : line end end -- cgit v1.2.1 From 6e3358a5077f5c6052e733722cd6baa63e43c081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 12 Jan 2016 17:36:08 -0500 Subject: Remove no longer required code. #3945 --- lib/gitlab/diff/highlight.rb | 51 ++++++++------------------------------------ 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index d0137ab5f08..14cf98e24a2 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -44,74 +44,41 @@ module Gitlab return [] if @lines.empty? extract_line_prefixes - - @code = unescape_html(raw_content) - @highlighted_code = formatter.format(lexer.lex(@code)) - - is_diff_line? ? update_diff_lines : @highlighted_code.lines + update_diff_lines end private - def is_diff_line? - @lines.first.is_a?(Gitlab::Diff::Line) - end - def text_lines - @text_lines ||= (is_diff_line? ? @lines.map(&:text) : @lines) - end - - def raw_content - @raw_content ||= text_lines.join(is_diff_line? ? "\n" : nil) + @text_lines ||= @lines.map(&:text) end def extract_line_prefixes - @diff_line_prefixes ||= begin - if is_diff_line? - text_lines.map { |line| line.sub!(/\A((\+|\-))/, '');$1 } - else - [] - end - end + @diff_line_prefixes ||= text_lines.map { |line| line.sub!(/\A((\+|\-))/, '');$1 } end def update_diff_lines - @highlighted_code.lines.each_with_index do |line, i| - diff_line = @lines[i] + @lines.each_with_index do |line, i| line_prefix = @diff_line_prefixes[i] || ' ' # ignore highlighting for "match" lines - next if diff_line.type == 'match' + next if line.type == 'match' - case diff_line.type + case line.type when 'new', nil - line = new_lines[diff_line.new_pos - 1] + highlighted_line = new_lines[line.new_pos - 1] when 'old' - line = old_lines[diff_line.old_pos - 1] + highlighted_line = old_lines[line.old_pos - 1] end # Only update text if line is found. This will prevent # issues with submodules given the line only exists in diff content. - diff_line.text = line.gsub!(/\A\s/, line_prefix) if line + line.text = highlighted_line.gsub!(/\A\s/, line_prefix) if line end @lines end - def lexer - Rouge::Lexer.guess(filename: @file_name, source: @code).new rescue Rouge::Lexers::PlainText.new - end - - def unescape_html(content) - text = CGI.unescapeHTML(content) - text.gsub!(' ', ' ') - text - end - - def formatter - self.class.formatter - end - def old_lines @old_lines ||= begin lines = self.class.process_file(diff_repository, diff_old_ref, diff_old_path) -- cgit v1.2.1 From f547e733d1f8acf2c8ae82835b91ae166cf95b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 12 Jan 2016 17:49:11 -0500 Subject: Add more specs. #3945 --- spec/lib/gitlab/diff/highlight_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index 4ab509f47b9..cdeed603e23 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -30,6 +30,24 @@ describe Gitlab::Diff::Highlight, lib: true do expect(diff_lines[0].text).to eq('@@ -6,12 +6,18 @@ module Popen') expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') end + + it 'should highlight unchanged lines' do + code = %Q{ def popen(cmd, path=nil)\n} + + expect(diff_lines[2].text).to eq(code) + end + + it 'should highlight added lines' do + code = %Q{+ raise RuntimeError, "System commands must be given as an array of strings"\n} + + expect(diff_lines[5].text).to eq(code) + end + + it 'should highlight removed lines' do + code = %Q{- raise "System commands must be given as an array of strings"\n} + + expect(diff_lines[4].text).to eq(code) + end end end -- cgit v1.2.1 From 7307fa48e70a9fb42902c8a84479d4cf669640aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 12 Jan 2016 19:28:31 -0500 Subject: Fix broken specs. #3945 --- app/controllers/projects/merge_requests_controller.rb | 3 ++- lib/gitlab/diff/highlight.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index b70533ef7be..95fd62b8ace 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -104,7 +104,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController @commit = @merge_request.last_commit @first_commit = @merge_request.first_commit @diffs = @merge_request.compare_diffs - @diff_refs = [@merge_request.target_sha, @merge_request.source_sha] + # We need to use #source_branch because #source_sha requires an existent MergeRequestDiff object. + @diff_refs = [@merge_request.target_sha, @merge_request.source_branch] @ci_commit = @merge_request.ci_commit @statuses = @ci_commit.statuses if @ci_commit diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 14cf98e24a2..0b6a348acbc 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -73,7 +73,7 @@ module Gitlab # Only update text if line is found. This will prevent # issues with submodules given the line only exists in diff content. - line.text = highlighted_line.gsub!(/\A\s/, line_prefix) if line + line.text = highlighted_line.gsub!(/\A\s/, line_prefix) if highlighted_line end @lines -- cgit v1.2.1 From a42fe49c8c953c0aa8ca20c8fb5a141447128894 Mon Sep 17 00:00:00 2001 From: Jeroen Nijhof Date: Wed, 13 Jan 2016 12:07:05 +0100 Subject: Replaced user recommendation with link to git-gc documentation --- doc/administration/housekeeping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md index 9c4fb72fd73..b90f916fea9 100644 --- a/doc/administration/housekeeping.md +++ b/doc/administration/housekeeping.md @@ -6,7 +6,7 @@ The housekeeping function runs `git gc` on the current project git repository. `git gc` runs a number of housekeeping tasks, such as compressing file revisions (to reduce disk space and increase performance) and removing unreachable objects which may have been created from prior invocations of git add. -Users are encouraged to run this task on a regular basis to maintain good disk space utilization and good operating performance. +See https://www.kernel.org/pub/software/scm/git/docs/git-gc.html for details. ## Where can I find it? -- cgit v1.2.1 From 48c45ba9a8a9a5536a3d501e40536cc5b73062a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 13 Jan 2016 10:58:19 -0500 Subject: Use html_safe instead of raw. #3945 --- app/views/projects/diffs/_parallel_view.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 77069501d1c..1ad54d1848b 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -20,7 +20,7 @@ = link_to raw(line_number_left), "##{line_code_left}", id: line_code_left - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_left, 'old') - %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= raw(line_content_left) + %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= line_content_left.html_safe - if type_right == 'new' - new_line_class = 'new' @@ -33,7 +33,7 @@ = link_to raw(line_number_right), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_right, 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= raw(line_content_right) + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= line_content_right.html_safe - if @reply_allowed - comments_left, comments_right = organize_comments(type_left, type_right, line_code_left, line_code_right) -- cgit v1.2.1 From 0f0af19139db71255934e9a7a5b5cd86420b7186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 13 Jan 2016 11:39:15 -0500 Subject: Little refactor for usage of html_safe. #3945 --- app/helpers/diff_helper.rb | 9 +++++---- app/views/projects/blob/diff.html.haml | 2 +- app/views/projects/diffs/_parallel_view.html.haml | 4 ++-- lib/gitlab/diff/highlight.rb | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 0ec532a9a90..d49e22e8c84 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -1,4 +1,6 @@ module DiffHelper + BLANK_SPACE = " ".html_safe + def diff_view params[:view] == 'parallel' ? 'parallel' : 'inline' end @@ -83,7 +85,7 @@ module DiffHelper elsif next_type == 'old' || next_type.nil? # Left side has text removed, right side doesn't have any change # No next line code, no new line number, no new line text - line = [type, line_old, full_line, line_code, next_type, nil, " ", nil] + line = [type, line_old, full_line, line_code, next_type, nil, BLANK_SPACE, nil] lines.push(line) end elsif type == 'new' @@ -93,7 +95,7 @@ module DiffHelper next else # Change is only on the right side, left side has no change - line = [nil, nil, " ", line_code, type, line_new, full_line, line_code] + line = [nil, nil, BLANK_SPACE, line_code, type, line_new, full_line, line_code] lines.push(line) end end @@ -113,8 +115,7 @@ module DiffHelper if line.blank? "  ".html_safe else - # Return line if it isn't a String, it helps when it's Numeric - line.is_a?(String) ? line.html_safe : line + line.html_safe end end diff --git a/app/views/projects/blob/diff.html.haml b/app/views/projects/blob/diff.html.haml index ef23876677a..2e913802be1 100644 --- a/app/views/projects/blob/diff.html.haml +++ b/app/views/projects/blob/diff.html.haml @@ -11,7 +11,7 @@ %td.old_line.diff-line-num{data: {linenumber: line_old}} = link_to raw(line_old), "#" %td.new_line= link_to raw(line_new) , "#" - %td.line_content.noteable_line= "#{' ' * @form.indent}#{line}".html_safe + %td.line_content.noteable_line==#{' ' * @form.indent}#{line} - if @form.unfold? && @form.bottom? && @form.to < @blob.loc %tr.line_holder{ id: @form.to } diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 1ad54d1848b..e9108c04cef 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -20,7 +20,7 @@ = link_to raw(line_number_left), "##{line_code_left}", id: line_code_left - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_left, 'old') - %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= line_content_left.html_safe + %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= line_content_left - if type_right == 'new' - new_line_class = 'new' @@ -33,7 +33,7 @@ = link_to raw(line_number_right), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code_right, 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= line_content_right.html_safe + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= line_content_right - if @reply_allowed - comments_left, comments_right = organize_comments(type_left, type_right, line_code_left, line_code_right) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 0b6a348acbc..f940b57d596 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -22,7 +22,7 @@ module Gitlab content = blob.data lexer = Rouge::Lexer.guess(filename: file_name, source: content).new rescue Rouge::Lexers::PlainText.new - formatter.format(lexer.lex(content)).lines + formatter.format(lexer.lex(content)).lines.map!(&:html_safe) end def self.formatter @@ -73,7 +73,7 @@ module Gitlab # Only update text if line is found. This will prevent # issues with submodules given the line only exists in diff content. - line.text = highlighted_line.gsub!(/\A\s/, line_prefix) if highlighted_line + line.text = highlighted_line.gsub!(/\A\s/, line_prefix).html_safe if highlighted_line end @lines -- cgit v1.2.1 From 1161cf2ec610cb0ceba61c92180566c9786ab059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 13 Jan 2016 18:01:40 -0500 Subject: Use current commit id if it doesn't have a parent. #3945 --- app/controllers/projects/commit_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 9bbf4581057..c8f143dd6b4 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -72,7 +72,7 @@ class Projects::CommitController < Projects::ApplicationController @diffs = commit.diffs end - @diff_refs = [commit.parent.id, commit.id] + @diff_refs = [commit.parent_id || commit.id, commit.id] @notes_count = commit.notes.count @statuses = ci_commit.statuses if ci_commit -- cgit v1.2.1 From c179b48c97be22ef55ef9f5874984f7359fb12f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 13 Jan 2016 21:04:53 -0500 Subject: Use #sub instead of #gsub!. #3945 * This is because is not a good idea to modify the original lines * Also I run into this issue https://gitlab.com/gitlab-org/gitlab_git/issues/14 which is returning Diff Lines with the same @new_pos value. --- lib/gitlab/diff/highlight.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index f940b57d596..e76a6f27856 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -73,7 +73,7 @@ module Gitlab # Only update text if line is found. This will prevent # issues with submodules given the line only exists in diff content. - line.text = highlighted_line.gsub!(/\A\s/, line_prefix).html_safe if highlighted_line + line.text = highlighted_line.sub(/\A\s/, line_prefix).html_safe if highlighted_line end @lines -- cgit v1.2.1 From c881627d114eb9c050d605e93673ef65a9da9a58 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 14 Jan 2016 14:52:08 +0100 Subject: Refactor parallel_diff generation a bit. --- app/helpers/blob_helper.rb | 11 +-- app/helpers/diff_helper.rb | 86 +++++++++++++++++------ app/views/projects/diffs/_parallel_view.html.haml | 43 +++++------- 3 files changed, 83 insertions(+), 57 deletions(-) diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index a80162a3e33..84e3cbb380b 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -13,15 +13,8 @@ module BlobHelper def highlight(blob_name, blob_content, nowrap: false, continue: false) formatter = rouge_formatter(nowrap: nowrap) - begin - @lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content).new - result = formatter.format(@lexer.lex(blob_content, continue: continue)).html_safe - rescue - @lexer = Rouge::Lexers::PlainText - result = formatter.format(@lexer.lex(blob_content)).html_safe - end - - result + @lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content).new rescue Rouge::Lexers::PlainText + formatter.format(@lexer.lex(blob_content, continue: continue)).html_safe end def no_highlight_files diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index d49e22e8c84..1596f9e7d19 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -1,6 +1,4 @@ module DiffHelper - BLANK_SPACE = " ".html_safe - def diff_view params[:view] == 'parallel' ? 'parallel' : 'inline' end @@ -49,15 +47,7 @@ module DiffHelper lines = [] skip_next = false - # Building array of lines - # - # [ - # left_type, left_line_number, left_line_content, left_line_code, - # right_line_type, right_line_number, right_line_content, right_line_code - # ] - # diff_file.highlighted_diff_lines.each do |line| - full_line = line.text type = line.type line_code = generate_line_code(diff_file.file_path, line) @@ -72,31 +62,81 @@ module DiffHelper next_line = next_line.text end - if type == 'match' || type.nil? + case type + when 'match', nil # line in the right panel is the same as in the left one - line = [type, line_old, full_line, line_code, type, line_new, full_line, line_code] - lines.push(line) - elsif type == 'old' - if next_type == 'new' + lines << { + left: { + type: type, + number: line_old, + text: full_line, + line_code: line_code, + }, + right: { + type: type, + number: line_new, + text: full_line, + line_code: line_code + } + } + when 'old' + case next_type + when 'new' # Left side has text removed, right side has text added - line = [type, line_old, full_line, line_code, next_type, line_new, next_line, next_line_code] - lines.push(line) + lines << { + left: { + type: type, + number: line_old, + text: full_line, + line_code: line_code, + }, + right: { + type: next_type, + number: line_new, + text: next_line, + line_code: next_line_code + } + } skip_next = true - elsif next_type == 'old' || next_type.nil? + when 'old', nil # Left side has text removed, right side doesn't have any change # No next line code, no new line number, no new line text - line = [type, line_old, full_line, line_code, next_type, nil, BLANK_SPACE, nil] - lines.push(line) + lines << { + left: { + type: type, + number: line_old, + text: full_line, + line_code: line_code, + }, + right: { + type: next_type, + number: nil, + text: "", + line_code: nil + } + } end - elsif type == 'new' + when 'new' if skip_next # Change has been already included in previous line so no need to do it again skip_next = false next else # Change is only on the right side, left side has no change - line = [nil, nil, BLANK_SPACE, line_code, type, line_new, full_line, line_code] - lines.push(line) + lines << { + left: { + type: nil, + number: nil, + text: "", + line_code: line_code, + }, + right: { + type: type, + number: line_new, + text: full_line, + line_code: line_code + } + } end end end diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index e9108c04cef..a2958286ada 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -2,41 +2,34 @@ %div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight %table - parallel_diff(diff_file, index).each do |line| - - type_left = line[0] - - line_number_left = line[1] - - line_content_left = line[2] - - line_code_left = line[3] - - type_right = line[4] - - line_number_right = line[5] - - line_content_right = line[6] - - line_code_right = line[7] - + - left = line[:left] + - right = line[:right] %tr.line_holder.parallel - - if type_left == 'match' - = render "projects/diffs/match_line_parallel", { line: line_content_left, - line_old: line_number_left, line_new: line_number_right } - - elsif type_left == 'old' || type_left.nil? - %td.old_line{id: line_code_left, class: "#{type_left}"} - = link_to raw(line_number_left), "##{line_code_left}", id: line_code_left + - if left[:type] == 'match' + = render "projects/diffs/match_line_parallel", { line: left[:text], + line_old: left[:number], line_new: right[:number] } + - else + %td.old_line{id: left[:line_code], class: "#{left[:type]}"} + = link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code] - if @comments_allowed && can?(current_user, :create_note, @project) - = link_to_new_diff_note(line_code_left, 'old') - %td.line_content{class: "parallel noteable_line #{type_left} #{line_code_left}", "line_code" => line_code_left }= line_content_left + = link_to_new_diff_note(left[:line_code], 'old') + %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", "line_code" => left[:line_code] }= diff_line_content(left[:text]) - - if type_right == 'new' + - if right[:type] == 'new' - new_line_class = 'new' - - new_line_code = line_code_right + - new_line_code = right[:line_code] - else - new_line_class = nil - - new_line_code = line_code_left + - new_line_code = left[:line_code] - %td.new_line{id: new_line_code, class: "#{new_line_class}", data: { linenumber: line_number_right }} - = link_to raw(line_number_right), "##{new_line_code}", id: new_line_code + %td.new_line{id: new_line_code, class: "#{new_line_class}", data: { linenumber: right[:number] }} + = link_to raw(right[:number]), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) - = link_to_new_diff_note(line_code_right, 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= line_content_right + = link_to_new_diff_note(right[:line_code], 'new') + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= diff_line_content(right[:text]) - if @reply_allowed - - comments_left, comments_right = organize_comments(type_left, type_right, line_code_left, line_code_right) + - comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code]) - if comments_left.present? || comments_right.present? = render "projects/notes/diff_notes_with_reply_parallel", notes_left: comments_left, notes_right: comments_right -- cgit v1.2.1 From 3a1d0535992594bc77320f081d1f20b760b1c1f7 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 14 Jan 2016 15:11:50 +0100 Subject: Remove duplication around highlighting. --- app/helpers/blob_helper.rb | 16 +--------------- lib/gitlab/diff/highlight.rb | 13 +------------ lib/gitlab/highlight.rb | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 27 deletions(-) create mode 100644 lib/gitlab/highlight.rb diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 84e3cbb380b..be856242c43 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -1,20 +1,6 @@ module BlobHelper - def rouge_formatter(options = {}) - default_options = { - nowrap: false, - cssclass: 'code highlight', - lineanchors: true, - lineanchorsid: 'LC' - } - - Rouge::Formatters::HTMLGitlab.new(default_options.merge!(options)) - end - def highlight(blob_name, blob_content, nowrap: false, continue: false) - formatter = rouge_formatter(nowrap: nowrap) - - @lexer ||= Rouge::Lexer.guess(filename: blob_name, source: blob_content).new rescue Rouge::Lexers::PlainText - formatter.format(@lexer.lex(blob_content, continue: continue)).html_safe + Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, continue: continue) end def no_highlight_files diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index e76a6f27856..f34eff62d79 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -20,18 +20,7 @@ module Gitlab blob = repository.blob_at(ref, file_name) 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.map!(&:html_safe) - end - - def self.formatter - @formatter ||= Rouge::Formatters::HTMLGitlab.new( - nowrap: true, - cssclass: 'code highlight', - lineanchors: true, - lineanchorsid: 'LC' - ) + Gitlab::Highlight.highlight(file_name, blob.data).lines.map!(&:html_safe) end def initialize(diff_file) diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb new file mode 100644 index 00000000000..02e097eca3d --- /dev/null +++ b/lib/gitlab/highlight.rb @@ -0,0 +1,23 @@ +module Gitlab + class Highlight + def self.highlight(blob_name, blob_content, nowrap: true, continue: false) + formatter = rouge_formatter(nowrap: nowrap) + + lexer = Rouge::Lexer.guess(filename: blob_name, source: blob_content).new rescue Rouge::Lexers::PlainText + formatter.format(lexer.lex(blob_content, continue: continue)).html_safe + end + + private + + def self.rouge_formatter(options = {}) + options = options.reverse_merge( + nowrap: true, + cssclass: 'code highlight', + lineanchors: true, + lineanchorsid: 'LC' + ) + + Rouge::Formatters::HTMLGitlab.new(options) + end + end +end -- cgit v1.2.1 From 83e4fc188b22731d89106b4da28f11bf5509c116 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 14 Jan 2016 16:13:35 +0100 Subject: Refactor highlighting lines --- lib/gitlab/diff/highlight.rb | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index f34eff62d79..ba2f12db147 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -32,23 +32,8 @@ module Gitlab def highlight return [] if @lines.empty? - extract_line_prefixes - update_diff_lines - end - - private - - def text_lines - @text_lines ||= @lines.map(&:text) - end - - def extract_line_prefixes - @diff_line_prefixes ||= text_lines.map { |line| line.sub!(/\A((\+|\-))/, '');$1 } - end - - def update_diff_lines @lines.each_with_index do |line, i| - line_prefix = @diff_line_prefixes[i] || ' ' + line_prefix = line.text.match(/\A([+-])/) ? $1 : ' ' # ignore highlighting for "match" lines next if line.type == 'match' @@ -62,24 +47,18 @@ module Gitlab # Only update text if line is found. This will prevent # issues with submodules given the line only exists in diff content. - line.text = highlighted_line.sub(/\A\s/, line_prefix).html_safe if highlighted_line + line.text = highlighted_line.insert(0, line_prefix).html_safe if highlighted_line end @lines end def old_lines - @old_lines ||= begin - lines = self.class.process_file(diff_repository, diff_old_ref, diff_old_path) - lines.map! { |line| " #{line}" } - end + @old_lines ||= self.class.process_file(diff_repository, diff_old_ref, diff_old_path) 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 + @new_lines ||= self.class.process_file(diff_repository, diff_new_ref, diff_new_path) end end end -- cgit v1.2.1 From 8dfad143d44af4896ff6c71e8a42ad32b69ad593 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 14 Jan 2016 22:28:07 +0100 Subject: Add inline diff markers in highlighted diffs. --- app/controllers/projects/blob_controller.rb | 2 +- app/views/projects/diffs/_parallel_view.html.haml | 4 +- app/views/projects/diffs/_text_file.html.haml | 2 +- lib/gitlab/diff/file.rb | 2 +- lib/gitlab/diff/highlight.rb | 206 ++++++++++++++++++---- lib/gitlab/highlight.rb | 7 + spec/lib/gitlab/diff/highlight_spec.rb | 4 +- 7 files changed, 187 insertions(+), 40 deletions(-) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 6ca3a636359..8133de90a41 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -66,7 +66,7 @@ class Projects::BlobController < Projects::ApplicationController def diff @form = UnfoldForm.new(params) - @lines = Gitlab::Diff::Highlight.process_file(repository, @ref, @path) + @lines = Gitlab::Highlight.highlight_lines(repository, @ref, @path) @lines = @lines[@form.since - 1..@form.to - 1] if @form.bottom? diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index a2958286ada..7b9cecbc3da 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -13,7 +13,7 @@ = link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code] - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(left[:line_code], 'old') - %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", "line_code" => left[:line_code] }= diff_line_content(left[:text]) + %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", data: { "line_code" => left[:line_code] }}= diff_line_content(left[:text]) - if right[:type] == 'new' - new_line_class = 'new' @@ -26,7 +26,7 @@ = link_to raw(right[:number]), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(right[:line_code], 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", "line_code" => new_line_code}= diff_line_content(right[:text]) + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", data: { "line_code" => new_line_code }}= diff_line_content(right[:text]) - if @reply_allowed - comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code]) diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 521f2ac1e8d..6761155dcf9 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -22,7 +22,7 @@ = link_to_new_diff_note(line_code) %td.new_line{data: {linenumber: line.new_pos}} = link_to raw(type == "old" ? " " : line.new_pos), "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= diff_line_content(line.text) + %td.line_content{class: "noteable_line #{type} #{line_code}", data: { "line_code" => line_code }}= diff_line_content(line.text) - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index cb93c6a574a..c1a6e16da5a 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -18,7 +18,7 @@ module Gitlab end def highlighted_diff_lines - Gitlab::Diff::Highlight.process_diff_lines(self) + Gitlab::Diff::Highlight.new(self).highlight end def mode_changed? diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index ba2f12db147..e21f496102d 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -6,59 +6,199 @@ module Gitlab delegate :repository, :old_path, :new_path, :old_ref, :new_ref, to: :diff_file, prefix: :diff - # Apply syntax highlight to provided source code - # - # diff_file - an instance of Gitlab::Diff::File - # - # Returns an Array with the processed items. - def self.process_diff_lines(diff_file) - processor = new(diff_file) - processor.highlight + def initialize(diff_file) + @diff_file = diff_file + @diff_lines = diff_file.diff_lines + @raw_lines = @diff_lines.map(&:text) end - def self.process_file(repository, ref, file_name) - blob = repository.blob_at(ref, file_name) - return [] unless blob + def highlight + return [] if @diff_lines.empty? - Gitlab::Highlight.highlight(file_name, blob.data).lines.map!(&:html_safe) - end + find_inline_diffs - def initialize(diff_file) - @diff_file = diff_file - @file_name = diff_file.new_path - @lines = diff_file.diff_lines + process_lines + + @diff_lines end - def highlight - return [] if @lines.empty? + private - @lines.each_with_index do |line, i| - line_prefix = line.text.match(/\A([+-])/) ? $1 : ' ' + def find_inline_diffs + @inline_diffs = [] + local_edit_indexes.each do |index| + old_index = index + new_index = index + 1 + old_line = @raw_lines[old_index][1..-1] + new_line = @raw_lines[new_index][1..-1] + + # Skip inline diff if empty line was replaced with content + next if old_line == "" + + lcp = longest_common_prefix(old_line, new_line) + lcs = longest_common_suffix(old_line, new_line) + + old_diff_range = lcp..(old_line.length - lcs - 1) + new_diff_range = lcp..(new_line.length - lcs - 1) + + @inline_diffs[old_index] = old_diff_range if old_diff_range.begin <= old_diff_range.end + @inline_diffs[new_index] = new_diff_range if new_diff_range.begin <= new_diff_range.end + end + end + + def process_lines + @diff_lines.each_with_index do |diff_line, i| # ignore highlighting for "match" lines - next if line.type == 'match' + next if diff_line.type == 'match' + + rich_line = highlight_line(diff_line, i) + rich_line = mark_inline_diffs(rich_line, diff_line, i) + diff_line.text = rich_line.html_safe + end + end + + def highlight_line(diff_line, index) + line_prefix = line_prefixes[index] + + case diff_line.type + when 'new', nil + rich_line = new_lines[diff_line.new_pos - 1] + when 'old' + rich_line = old_lines[diff_line.old_pos - 1] + end + + # 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 + end + + def mark_inline_diffs(rich_line, diff_line, index) + inline_diff = @inline_diffs[index] + return rich_line unless inline_diff + + raw_line = diff_line.text + + # Based on the prefixless versions + from = inline_diff.begin + 1 + to = inline_diff.end + 1 + + position_mapping = map_character_positions(raw_line, rich_line) + inline_diff_positions = position_mapping[from..to] + marker_ranges = collapse_ranges(inline_diff_positions) + + offset = 0 + marker_ranges.each do |range| + offset = insert_around_range(rich_line, range, "", "", offset) + end + + rich_line + end - case line.type - when 'new', nil - highlighted_line = new_lines[line.new_pos - 1] - when 'old' - highlighted_line = old_lines[line.old_pos - 1] + def line_prefixes + @line_prefixes ||= @raw_lines.map { |line| line.match(/\A([+-])/) ? $1 : ' ' } + end + + def local_edit_indexes + @local_edit_indexes ||= begin + joined_line_prefixes = " #{line_prefixes.join} " + + offset = 0 + local_edit_indexes = [] + while index = joined_line_prefixes.index(" -+ ", offset) + local_edit_indexes << index + offset = index + 1 end - # Only update text if line is found. This will prevent - # issues with submodules given the line only exists in diff content. - line.text = highlighted_line.insert(0, line_prefix).html_safe if highlighted_line + local_edit_indexes end + end + + def map_character_positions(raw_line, rich_line) + mapping = [] + raw_pos = 0 + rich_pos = 0 + (0..raw_line.length).each do |raw_pos| + raw_char = raw_line[raw_pos] + rich_char = rich_line[rich_pos] + + while rich_char == '<' + until rich_char == '>' + rich_pos += 1 + rich_char = rich_line[rich_pos] + end + + rich_pos += 1 + rich_char = rich_line[rich_pos] + end - @lines + mapping[raw_pos] = rich_pos + + rich_pos += 1 + end + + mapping end def old_lines - @old_lines ||= self.class.process_file(diff_repository, diff_old_ref, diff_old_path) + @old_lines ||= Gitlab::Highlight.highlight_lines(diff_repository, diff_old_ref, diff_old_path) end def new_lines - @new_lines ||= self.class.process_file(diff_repository, diff_new_ref, diff_new_path) + @new_lines ||= Gitlab::Highlight.highlight_lines(diff_repository, diff_new_ref, diff_new_path) + end + + def longest_common_suffix(a, b) + longest_common_prefix(a.reverse, b.reverse) + end + + def longest_common_prefix(a, b) + max_length = [a.length, b.length].max + + length = 0 + (0..max_length - 1).each do |pos| + old_char = a[pos] + new_char = b[pos] + + break if old_char != new_char + length += 1 + end + + length + end + + def collapse_ranges(positions) + return [] if positions.empty? + ranges = [] + + start = prev = positions[0] + range = start..prev + positions[1..-1].each do |pos| + if pos == prev + 1 + range = start..pos + prev = pos + else + ranges << range + start = prev = pos + range = start..prev + end + end + ranges << range + + ranges + end + + def insert_around_range(text, range, before, after, offset = 0) + from = range.begin + to = range.end + + text.insert(offset + from, before) + offset += before.length + + text.insert(offset + to + 1, after) + offset += after.length + + offset end end end diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb index 02e097eca3d..a5b041687e3 100644 --- a/lib/gitlab/highlight.rb +++ b/lib/gitlab/highlight.rb @@ -7,6 +7,13 @@ module Gitlab formatter.format(lexer.lex(blob_content, continue: continue)).html_safe end + def self.highlight_lines(repository, ref, file_name) + blob = repository.blob_at(ref, file_name) + return [] unless blob + + highlight(file_name, blob.data).lines.map!(&:html_safe) + end + private def self.rouge_formatter(options = {}) diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index cdeed603e23..3c66c9889ba 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -51,9 +51,9 @@ describe Gitlab::Diff::Highlight, lib: true do end end - describe '.process_file' do + describe '.highlight_lines' do let(:lines) do - Gitlab::Diff::Highlight.process_file(project.repository, commit.id, 'files/ruby/popen.rb') + Gitlab::Diff::Highlight.highlight_lines(project.repository, commit.id, 'files/ruby/popen.rb') end it 'should properly highlight all the lines' do -- cgit v1.2.1 From 70bc322415b33a4789067b81387d30f1411c9091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Thu, 14 Jan 2016 12:56:44 -0500 Subject: Use the adequate reference for the old rev. #3945 --- app/controllers/projects/merge_requests_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 95fd62b8ace..3d792af0a48 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -59,7 +59,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController def diffs @commit = @merge_request.last_commit @first_commit = @merge_request.first_commit - @diff_refs = [@merge_request.target_sha, @merge_request.source_sha] + @diff_refs = [@merge_request.last_commit.parent_id, @merge_request.source_sha] @comments_allowed = @reply_allowed = true @comments_target = { -- cgit v1.2.1 From 6b9c730e91962a6d6343bcb7fc4dc75c99b41bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Thu, 14 Jan 2016 16:38:37 -0500 Subject: More refactoring from last code review. #3945 * Use commit objects instead of IDs when generating diffs * Use proper references when generating MR's source and target * Update broken specs --- app/controllers/projects/commit_controller.rb | 2 +- app/controllers/projects/compare_controller.rb | 2 +- .../projects/merge_requests_controller.rb | 3 - app/helpers/diff_helper.rb | 4 +- app/models/merge_request.rb | 4 + app/views/projects/diffs/_diffs.html.haml | 2 +- .../projects/merge_requests/_new_submit.html.haml | 2 +- .../projects/merge_requests/show/_diffs.html.haml | 3 +- lib/gitlab/diff/file.rb | 5 +- lib/gitlab/diff/highlight.rb | 17 +- spec/fixtures/parallel_diff_result.yml | 590 +++++++++++---------- spec/helpers/diff_helper_spec.rb | 24 +- spec/lib/gitlab/diff/file_spec.rb | 2 +- spec/lib/gitlab/diff/highlight_spec.rb | 2 +- 14 files changed, 366 insertions(+), 296 deletions(-) diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index c8f143dd6b4..ba924ccc5a5 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -72,7 +72,7 @@ class Projects::CommitController < Projects::ApplicationController @diffs = commit.diffs end - @diff_refs = [commit.parent_id || commit.id, commit.id] + @diff_refs = [commit.parent || commit, commit] @notes_count = commit.notes.count @statuses = ci_commit.statuses if ci_commit diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb index 5b88aed7a64..60360c8e5c8 100644 --- a/app/controllers/projects/compare_controller.rb +++ b/app/controllers/projects/compare_controller.rb @@ -20,9 +20,9 @@ class Projects::CompareController < Projects::ApplicationController if compare_result @commits = Commit.decorate(compare_result.commits, @project) @diffs = compare_result.diffs - @diff_refs = [base_ref, head_ref] @commit = @project.commit(head_ref) @first_commit = @project.commit(base_ref) + @diff_refs = [@first_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 3d792af0a48..ab5c953189c 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -59,7 +59,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController def diffs @commit = @merge_request.last_commit @first_commit = @merge_request.first_commit - @diff_refs = [@merge_request.last_commit.parent_id, @merge_request.source_sha] @comments_allowed = @reply_allowed = true @comments_target = { @@ -104,8 +103,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController @commit = @merge_request.last_commit @first_commit = @merge_request.first_commit @diffs = @merge_request.compare_diffs - # We need to use #source_branch because #source_sha requires an existent MergeRequestDiff object. - @diff_refs = [@merge_request.target_sha, @merge_request.source_branch] @ci_commit = @merge_request.ci_commit @statuses = @ci_commit.statuses if @ci_commit diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 1596f9e7d19..425a8ced549 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -19,13 +19,13 @@ module DiffHelper end end - def safe_diff_files(diffs, diff_refs, repository) + def safe_diff_files(diffs, diff_refs) lines = 0 safe_files = [] diffs.first(allowed_diff_size).each do |diff| lines += diff.diff.lines.count break if lines > allowed_diff_lines - safe_files << Gitlab::Diff::File.new(diff, diff_refs, repository) + safe_files << Gitlab::Diff::File.new(diff, diff_refs) end safe_files end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index ac25d38eb63..fe87b820e98 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -511,4 +511,8 @@ class MergeRequest < ActiveRecord::Base def broken? self.commits.blank? || branch_missing? || cannot_be_merged? end + + def diff_range + [last_commit.parent, first_commit] + end end diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index 58ad7d79af9..b2f9c14da88 100644 --- a/app/views/projects/diffs/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -1,7 +1,7 @@ - if diff_view == 'parallel' - fluid_layout true -- diff_files = safe_diff_files(diffs, diff_refs, repository) +- diff_files = safe_diff_files(diffs, diff_refs) .gray-content-block.middle-block.oneline-block .inline-parallel-buttons diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 0cb8b6daedb..f2a12099b26 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -38,7 +38,7 @@ = render "projects/merge_requests/show/commits" #diffs.diffs.tab-pane.active - if @diffs.present? - = render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @diff_refs + = render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @merge_request.diff_range - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE .alert.alert-danger %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits. diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml index 1d9af1e4160..46c6f79937b 100644 --- a/app/views/projects/merge_requests/show/_diffs.html.haml +++ b/app/views/projects/merge_requests/show/_diffs.html.haml @@ -1,5 +1,6 @@ - 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, diff_refs: @diff_refs + = render "projects/diffs/diffs", diffs: params[:w] == '1' ? @merge_request.diffs_no_whitespace : @merge_request.diffs, + project: @merge_request.project, diff_refs: @merge_request.diff_range - elsif @merge_request_diff.empty? .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch} - else diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index c1a6e16da5a..a6a7fc8ff4c 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -1,14 +1,13 @@ module Gitlab module Diff class File - attr_reader :diff, :repository, :new_ref, :old_ref + attr_reader :diff, :new_ref, :old_ref delegate :new_file, :deleted_file, :renamed_file, :old_path, :new_path, to: :diff, prefix: false - def initialize(diff, diff_refs, repository) + def initialize(diff, diff_refs) @diff = diff - @repository = repository @old_ref, @new_ref = diff_refs end diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index e21f496102d..fb79a2a69de 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -3,8 +3,7 @@ module Gitlab class Highlight attr_reader :diff_file - delegate :repository, :old_path, :new_path, :old_ref, :new_ref, - to: :diff_file, prefix: :diff + delegate :old_path, :new_path, :old_ref, :new_ref, to: :diff_file, prefix: :diff def initialize(diff_file) @diff_file = diff_file @@ -141,11 +140,11 @@ module Gitlab end def old_lines - @old_lines ||= Gitlab::Highlight.highlight_lines(diff_repository, diff_old_ref, diff_old_path) + @old_lines ||= self.class.process_file(*processing_args(:old)) end def new_lines - @new_lines ||= Gitlab::Highlight.highlight_lines(diff_repository, diff_new_ref, diff_new_path) + @new_lines ||= self.class.process_file(*processing_args(:new)) end def longest_common_suffix(a, b) @@ -200,6 +199,16 @@ module Gitlab offset end + + private + + def processing_args(version) + ref = send("diff_#{version}_ref") + path = send("diff_#{version}_path") + + [ref.project.repository, ref.id, path] + end + end end end diff --git a/spec/fixtures/parallel_diff_result.yml b/spec/fixtures/parallel_diff_result.yml index 020c1817226..4583de1231e 100644 --- a/spec/fixtures/parallel_diff_result.yml +++ b/spec/fixtures/parallel_diff_result.yml @@ -1,268 +1,324 @@ --- -- - match - - 6 - - "@@ -6,12 +6,18 @@ module Popen" - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - - match - - 6 - - "@@ -6,12 +6,18 @@ module Popen" - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 -- - - - 6 - - |2 - - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - - - - 6 - - |2 - - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 -- - - - 7 - - |2 - def popen(cmd, path=nil) - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 - - - - 7 - - |2 - def popen(cmd, path=nil) - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 -- - - - 8 - - |2 - unless cmd.is_a?(Array) - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 - - - - 8 - - |2 - unless cmd.is_a?(Array) - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 -- - old - - 9 - - | - - raise "System commands must be given as an array of strings" - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9 - - new - - 9 - - | - + raise RuntimeError, "System commands must be given as an array of strings" - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9 -- - - - 10 - - |2 - end - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 - - - - 10 - - |2 - end - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 -- - - - 11 - - |2 - - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 - - - - 11 - - |2 - - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 -- - - - 12 - - |2 - path ||= Dir.pwd - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 - - - - 12 - - |2 - path ||= Dir.pwd - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 -- - old - - 13 - - | - - vars = { "PWD" => path } - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13 - - old - - - - " " - - -- - old - - 14 - - | - - options = { chdir: path } - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_13 - - new - - 13 - - | - + - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_13 -- - - - - - " " - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 - - new - - 14 - - | - + vars = { - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 -- - - - - - " " - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 - - new - - 15 - - | - + "PWD" => path - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 -- - - - - - " " - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 - - new - - 16 - - | - + } - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 -- - - - - - " " - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 - - new - - 17 - - | - + - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 -- - - - - - " " - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 - - new - - 18 - - | - + options = { - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 -- - - - - - " " - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 - - new - - 19 - - | - + chdir: path - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 -- - - - - - " " - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 - - new - - 20 - - | - + } - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 -- - - - 15 - - |2 - - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 - - - - 21 - - |2 - - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 -- - - - 16 - - |2 - unless File.directory?(path) - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 - - - - 22 - - |2 - unless File.directory?(path) - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 -- - - - 17 - - |2 - FileUtils.mkdir_p(path) - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 - - - - 23 - - |2 - FileUtils.mkdir_p(path) - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 -- - match - - 19 - - "@@ -19,6 +25,7 @@ module Popen" - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - - match - - 25 - - "@@ -19,6 +25,7 @@ module Popen" - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 -- - - - 19 - - |2 - - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - - - - 25 - - |2 - - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 -- - - - 20 - - |2 - @cmd_output = "" - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 - - - - 26 - - |2 - @cmd_output = "" - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 -- - - - 21 - - |2 - @cmd_status = 0 - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 - - - - 27 - - |2 - @cmd_status = 0 - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 -- - - - - - " " - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 - - new - - 28 - - | - + - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 -- - - - 22 - - |2 - Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 - - - - 29 - - |2 - Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 -- - - - 23 - - |2 - @cmd_output << stdout.read - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 - - - - 30 - - |2 - @cmd_output << stdout.read - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 -- - - - 24 - - |2 - @cmd_output << stderr.read - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 - - - - 31 - - |2 - @cmd_output << stderr.read - - 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 +- :left: + :type: match + :number: 6 + :text: "@@ -6,12 +6,18 @@ module Popen" + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 + :right: + :type: match + :number: 6 + :text: "@@ -6,12 +6,18 @@ module Popen" + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 +- :left: + :type: + :number: 6 + :text: |2 + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 + :right: + :type: + :number: 6 + :text: |2 + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 +- :left: + :type: + :number: 7 + :text: |2 + def popen(cmd, path=nil) + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 + :right: + :type: + :number: 7 + :text: |2 + def popen(cmd, path=nil) + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 +- :left: + :type: + :number: 8 + :text: |2 + unless cmd.is_a?(Array) + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 + :right: + :type: + :number: 8 + :text: |2 + unless cmd.is_a?(Array) + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 +- :left: + :type: old + :number: 9 + :text: | + - raise "System commands must be given as an array of strings" + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_9_9 + :right: + :type: new + :number: 9 + :text: | + + raise RuntimeError, "System commands must be given as an array of strings" + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9 +- :left: + :type: + :number: 10 + :text: |2 + end + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 + :right: + :type: + :number: 10 + :text: |2 + end + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 +- :left: + :type: + :number: 11 + :text: |2 + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 + :right: + :type: + :number: 11 + :text: |2 + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 +- :left: + :type: + :number: 12 + :text: |2 + path ||= Dir.pwd + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 + :right: + :type: + :number: 12 + :text: |2 + path ||= Dir.pwd + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 +- :left: + :type: old + :number: 13 + :text: | + - vars = { "PWD" => path } + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13 + :right: + :type: old + :number: + :text: '' + :line_code: +- :left: + :type: old + :number: 14 + :text: | + - options = { chdir: path } + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_14_13 + :right: + :type: new + :number: 13 + :text: | + + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_13 +- :left: + :type: + :number: + :text: '' + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 + :right: + :type: new + :number: 14 + :text: | + + vars = { + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 +- :left: + :type: + :number: + :text: '' + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 + :right: + :type: new + :number: 15 + :text: | + + "PWD" => path + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 +- :left: + :type: + :number: + :text: '' + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 + :right: + :type: new + :number: 16 + :text: | + + } + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 +- :left: + :type: + :number: + :text: '' + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 + :right: + :type: new + :number: 17 + :text: | + + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 +- :left: + :type: + :number: + :text: '' + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 + :right: + :type: new + :number: 18 + :text: | + + options = { + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 +- :left: + :type: + :number: + :text: '' + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 + :right: + :type: new + :number: 19 + :text: | + + chdir: path + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 +- :left: + :type: + :number: + :text: '' + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 + :right: + :type: new + :number: 20 + :text: | + + } + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 +- :left: + :type: + :number: 15 + :text: |2 + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 + :right: + :type: + :number: 21 + :text: |2 + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 +- :left: + :type: + :number: 16 + :text: |2 + unless File.directory?(path) + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 + :right: + :type: + :number: 22 + :text: |2 + unless File.directory?(path) + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 +- :left: + :type: + :number: 17 + :text: |2 + FileUtils.mkdir_p(path) + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 + :right: + :type: + :number: 23 + :text: |2 + FileUtils.mkdir_p(path) + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 +- :left: + :type: match + :number: 19 + :text: "@@ -19,6 +25,7 @@ module Popen" + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 + :right: + :type: match + :number: 25 + :text: "@@ -19,6 +25,7 @@ module Popen" + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 +- :left: + :type: + :number: 19 + :text: |2 + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 + :right: + :type: + :number: 25 + :text: |2 + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 +- :left: + :type: + :number: 20 + :text: |2 + @cmd_output = "" + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 + :right: + :type: + :number: 26 + :text: |2 + @cmd_output = "" + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 +- :left: + :type: + :number: 21 + :text: |2 + @cmd_status = 0 + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 + :right: + :type: + :number: 27 + :text: |2 + @cmd_status = 0 + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 +- :left: + :type: + :number: + :text: '' + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 + :right: + :type: new + :number: 28 + :text: | + + + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 +- :left: + :type: + :number: 22 + :text: |2 + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 + :right: + :type: + :number: 29 + :text: |2 + Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 +- :left: + :type: + :number: 23 + :text: |2 + @cmd_output << stdout.read + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 + :right: + :type: + :number: 30 + :text: |2 + @cmd_output << stdout.read + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 +- :left: + :type: + :number: 24 + :text: |2 + @cmd_output << stderr.read + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 + :right: + :type: + :number: 31 + :text: |2 + @cmd_output << stderr.read + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 4b10ee3d33c..435ecd04fbe 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -8,8 +8,8 @@ describe DiffHelper do let(:commit) { project.commit(sample_commit.id) } let(:diffs) { commit.diffs } let(:diff) { diffs.first } - let(:diff_refs) { [commit.parent.id, commit.id] } - let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs, repository) } + let(:diff_refs) { [commit.parent, commit] } + let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs) } describe 'diff_hard_limit_enabled?' do it 'should return true if param is provided' do @@ -46,41 +46,41 @@ describe DiffHelper do describe 'safe_diff_files' do it 'should return all files from a commit that is smaller than safe limits' do - expect(safe_diff_files(diffs, diff_refs, repository).length).to eq(2) + expect(safe_diff_files(diffs, diff_refs).length).to eq(2) end it 'should return only the first file if the diff line count in the 2nd file takes the total beyond safe limits' do allow(diffs[1].diff).to receive(:lines).and_return([""] * 4999) #simulate 4999 lines - expect(safe_diff_files(diffs, diff_refs, repository).length).to eq(1) + expect(safe_diff_files(diffs, diff_refs).length).to eq(1) end it 'should return all files from a commit that is beyond safe limit for numbers of lines if force diff is true' do allow(controller).to receive(:params) { { force_show_diff: true } } allow(diffs[1].diff).to receive(:lines).and_return([""] * 4999) #simulate 4999 lines - expect(safe_diff_files(diffs, diff_refs, repository).length).to eq(2) + expect(safe_diff_files(diffs, diff_refs).length).to eq(2) end it 'should return only the first file if the diff line count in the 2nd file takes the total beyond hard limits' do allow(controller).to receive(:params) { { force_show_diff: true } } allow(diffs[1].diff).to receive(:lines).and_return([""] * 49999) #simulate 49999 lines - expect(safe_diff_files(diffs, diff_refs, repository).length).to eq(1) + expect(safe_diff_files(diffs, diff_refs).length).to eq(1) end it 'should return only a safe number of file diffs if a commit touches more files than the safe limits' do large_diffs = diffs * 100 #simulate 200 diffs - expect(safe_diff_files(large_diffs, diff_refs, repository).length).to eq(100) + expect(safe_diff_files(large_diffs, diff_refs).length).to eq(100) end it 'should return all file diffs if a commit touches more files than the safe limits but force diff is true' do allow(controller).to receive(:params) { { force_show_diff: true } } large_diffs = diffs * 100 #simulate 200 diffs - expect(safe_diff_files(large_diffs, diff_refs, repository).length).to eq(200) + expect(safe_diff_files(large_diffs, diff_refs).length).to eq(200) end it 'should return a limited file diffs if a commit touches more files than the hard limits and force diff is true' do allow(controller).to receive(:params) { { force_show_diff: true } } very_large_diffs = diffs * 1000 #simulate 2000 diffs - expect(safe_diff_files(very_large_diffs, diff_refs, repository).length).to eq(1000) + expect(safe_diff_files(very_large_diffs, diff_refs).length).to eq(1000) end end @@ -128,7 +128,11 @@ describe DiffHelper do expect(diff_line_content(diff_file.diff_lines.first.text)). to eq('@@ -6,12 +6,18 @@ module Popen') expect(diff_line_content(diff_file.diff_lines.first.type)).to eq('match') - expect(diff_line_content(diff_file.diff_lines.first.new_pos)).to eq(6) + expect(diff_file.diff_lines.first.new_pos).to eq(6) + end + + it 'should return safe HTML' do + expect(diff_line_content(diff_file.diff_lines.first.text)).to be_html_safe end end diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb index 97ba7f14eb1..0d9694f2c13 100644 --- a/spec/lib/gitlab/diff/file_spec.rb +++ b/spec/lib/gitlab/diff/file_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::Diff::File, lib: true do let(:project) { create(:project) } let(:commit) { project.commit(sample_commit.id) } let(:diff) { commit.diffs.first } - let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent.id, commit.id], project.repository) } + let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent, commit]) } describe :diff_lines do let(:diff_lines) { diff_file.diff_lines } diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index 3c66c9889ba..f307dcaae44 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::Diff::Highlight, lib: true do let(:project) { create(:project) } let(:commit) { project.commit(sample_commit.id) } let(:diff) { commit.diffs.first } - let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent.id, commit.id], project.repository) } + let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent, commit]) } describe '.process_diff_lines' do context 'when processing Gitlab::Diff::Line objects' do -- cgit v1.2.1 From 71b4341a37dc274ce94d0b967e5b69fd49834cb8 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 15 Jan 2016 14:11:36 +0100 Subject: Method was moved --- lib/gitlab/diff/highlight.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index fb79a2a69de..65deea9d335 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -140,11 +140,11 @@ module Gitlab end def old_lines - @old_lines ||= self.class.process_file(*processing_args(:old)) + @old_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:old)) end def new_lines - @new_lines ||= self.class.process_file(*processing_args(:new)) + @new_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:new)) end def longest_common_suffix(a, b) -- cgit v1.2.1 From 7d31f372191c38e5676cd6ec746721eb64b4a634 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 15 Jan 2016 14:25:29 +0100 Subject: Move inline diff logic to its own class --- lib/gitlab/diff/highlight.rb | 84 ++++++-------------------------------------- 1 file changed, 11 insertions(+), 73 deletions(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 65deea9d335..f89121e184b 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -24,26 +24,7 @@ module Gitlab private def find_inline_diffs - @inline_diffs = [] - - local_edit_indexes.each do |index| - old_index = index - new_index = index + 1 - old_line = @raw_lines[old_index][1..-1] - new_line = @raw_lines[new_index][1..-1] - - # Skip inline diff if empty line was replaced with content - next if old_line == "" - - lcp = longest_common_prefix(old_line, new_line) - lcs = longest_common_suffix(old_line, new_line) - - old_diff_range = lcp..(old_line.length - lcs - 1) - new_diff_range = lcp..(new_line.length - lcs - 1) - - @inline_diffs[old_index] = old_diff_range if old_diff_range.begin <= old_diff_range.end - @inline_diffs[new_index] = new_diff_range if new_diff_range.begin <= new_diff_range.end - end + @inline_diffs = InlineDiff.new(@raw_lines).inline_diffs end def process_lines @@ -58,7 +39,7 @@ module Gitlab end def highlight_line(diff_line, index) - line_prefix = line_prefixes[index] + line_prefix = diff_line.text.match(/\A([+-])/) ? $1 : ' ' case diff_line.type when 'new', nil @@ -73,44 +54,23 @@ module Gitlab end def mark_inline_diffs(rich_line, diff_line, index) - inline_diff = @inline_diffs[index] - return rich_line unless inline_diff + line_inline_diffs = @inline_diffs[index] + return rich_line unless line_inline_diffs raw_line = diff_line.text - - # Based on the prefixless versions - from = inline_diff.begin + 1 - to = inline_diff.end + 1 - position_mapping = map_character_positions(raw_line, rich_line) - inline_diff_positions = position_mapping[from..to] - marker_ranges = collapse_ranges(inline_diff_positions) offset = 0 - marker_ranges.each do |range| - offset = insert_around_range(rich_line, range, "", "", offset) - end - - rich_line - end - - def line_prefixes - @line_prefixes ||= @raw_lines.map { |line| line.match(/\A([+-])/) ? $1 : ' ' } - end - - def local_edit_indexes - @local_edit_indexes ||= begin - joined_line_prefixes = " #{line_prefixes.join} " + line_inline_diffs.each do |inline_diff_range| + inline_diff_positions = position_mapping[inline_diff_range] + marker_ranges = collapse_ranges(inline_diff_positions) - offset = 0 - local_edit_indexes = [] - while index = joined_line_prefixes.index(" -+ ", offset) - local_edit_indexes << index - offset = index + 1 + marker_ranges.each do |range| + offset = insert_around_range(rich_line, range, "", "", offset) end - - local_edit_indexes end + + rich_line end def map_character_positions(raw_line, rich_line) @@ -147,25 +107,6 @@ module Gitlab @new_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:new)) end - def longest_common_suffix(a, b) - longest_common_prefix(a.reverse, b.reverse) - end - - def longest_common_prefix(a, b) - max_length = [a.length, b.length].max - - length = 0 - (0..max_length - 1).each do |pos| - old_char = a[pos] - new_char = b[pos] - - break if old_char != new_char - length += 1 - end - - length - end - def collapse_ranges(positions) return [] if positions.empty? ranges = [] @@ -200,15 +141,12 @@ module Gitlab offset end - private - def processing_args(version) ref = send("diff_#{version}_ref") path = send("diff_#{version}_path") [ref.project.repository, ref.id, path] end - end end end -- cgit v1.2.1 From 13f10efcf120f2d5244bf6abe934dc7c026834ef Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 15 Jan 2016 14:39:43 +0100 Subject: Move inline diff marker logic to its own class --- lib/gitlab/diff/highlight.rb | 106 +++++-------------------------------------- 1 file changed, 11 insertions(+), 95 deletions(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index f89121e184b..b6875f07279 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -12,32 +12,24 @@ module Gitlab end def highlight - return [] if @diff_lines.empty? - - find_inline_diffs - - process_lines - - @diff_lines - end - - private - - def find_inline_diffs - @inline_diffs = InlineDiff.new(@raw_lines).inline_diffs - end - - def process_lines @diff_lines.each_with_index do |diff_line, i| # ignore highlighting for "match" lines next if diff_line.type == 'match' rich_line = highlight_line(diff_line, i) - rich_line = mark_inline_diffs(rich_line, diff_line, i) + + if line_inline_diffs = inline_diffs[i] + rich_line = InlineDiffMarker.new(diff_line.text, rich_line).mark(line_inline_diffs) + end + diff_line.text = rich_line.html_safe end + + @diff_lines end + private + def highlight_line(diff_line, index) line_prefix = diff_line.text.match(/\A([+-])/) ? $1 : ' ' @@ -53,50 +45,8 @@ module Gitlab rich_line ? line_prefix + rich_line : diff_line.text end - def mark_inline_diffs(rich_line, diff_line, index) - line_inline_diffs = @inline_diffs[index] - return rich_line unless line_inline_diffs - - raw_line = diff_line.text - position_mapping = map_character_positions(raw_line, rich_line) - - offset = 0 - line_inline_diffs.each do |inline_diff_range| - inline_diff_positions = position_mapping[inline_diff_range] - marker_ranges = collapse_ranges(inline_diff_positions) - - marker_ranges.each do |range| - offset = insert_around_range(rich_line, range, "", "", offset) - end - end - - rich_line - end - - def map_character_positions(raw_line, rich_line) - mapping = [] - raw_pos = 0 - rich_pos = 0 - (0..raw_line.length).each do |raw_pos| - raw_char = raw_line[raw_pos] - rich_char = rich_line[rich_pos] - - while rich_char == '<' - until rich_char == '>' - rich_pos += 1 - rich_char = rich_line[rich_pos] - end - - rich_pos += 1 - rich_char = rich_line[rich_pos] - end - - mapping[raw_pos] = rich_pos - - rich_pos += 1 - end - - mapping + def inline_diffs + @inline_diffs ||= InlineDiff.new(@raw_lines).inline_diffs end def old_lines @@ -107,40 +57,6 @@ module Gitlab @new_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:new)) end - def collapse_ranges(positions) - return [] if positions.empty? - ranges = [] - - start = prev = positions[0] - range = start..prev - positions[1..-1].each do |pos| - if pos == prev + 1 - range = start..pos - prev = pos - else - ranges << range - start = prev = pos - range = start..prev - end - end - ranges << range - - ranges - end - - def insert_around_range(text, range, before, after, offset = 0) - from = range.begin - to = range.end - - text.insert(offset + from, before) - offset += before.length - - text.insert(offset + to + 1, after) - offset += after.length - - offset - end - def processing_args(version) ref = send("diff_#{version}_ref") path = send("diff_#{version}_path") -- cgit v1.2.1 From 51266f41b3150b3a198bf8316d093a86d4d38cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 15 Jan 2016 15:28:16 +0100 Subject: Consider re-assign as a mention from a notification point of view This will ensure new assignee gets an email even if his notif level is "on mention". --- app/services/notification_service.rb | 16 +++++++++++----- spec/services/notification_service_spec.rb | 18 +++++++++++++++++- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index e4edc55bf69..60b86914a38 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -379,7 +379,7 @@ class NotificationService previous_assignee_id = previous_record(target, "assignee_id") previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id - recipients = build_recipients(target, project, current_user, [previous_assignee]) + recipients = build_recipients(target, project, current_user, action: :reassign, extra_recipients: [previous_assignee]) recipients.each do |recipient| mailer.send( @@ -400,22 +400,28 @@ class NotificationService end end - def build_recipients(target, project, current_user, extra_recipients = nil) + def build_recipients(target, project, current_user, action: nil, extra_recipients: nil) recipients = target.participants(current_user) recipients = recipients.concat(extra_recipients).compact.uniq if extra_recipients recipients = add_project_watchers(recipients, project) recipients = reject_mention_users(recipients, project) - recipients = reject_muted_users(recipients, project) + # Re-assign is considered as a mention of the new assignee so we add the + # new assignee to the list of recipients after we rejected users with + # the "on mention" notification level + if action == :reassign + recipients << target.assignee + end + + recipients = reject_muted_users(recipients, project) recipients = add_subscribed_users(recipients, target) recipients = reject_unsubscribed_users(recipients, target) recipients.delete(current_user) - recipients = recipients.uniq - recipients + recipients.uniq end def mailer diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 6d219f35895..b63903af414 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -227,9 +227,11 @@ describe NotificationService, services: true do end describe :reassigned_issue do - it 'should email new assignee' do + it 'emails new assignee' do + issue.update_attribute(:assignee, @u_mentioned) notification.reassigned_issue(issue, @u_disabled) + expect(issue.assignee).to be @u_mentioned should_email(issue.assignee) should_email(@u_watcher) should_email(@u_participant_mentioned) @@ -238,6 +240,20 @@ describe NotificationService, services: true do should_not_email(@u_participating) should_not_email(@u_disabled) end + + it 'does not email new assignee if they are the current user' do + issue.update_attribute(:assignee, @u_mentioned) + notification.reassigned_issue(issue, @u_mentioned) + + expect(issue.assignee).to be @u_mentioned + should_email(@u_watcher) + should_email(@u_participant_mentioned) + should_email(@subscriber) + should_not_email(issue.assignee) + should_not_email(@unsubscriber) + should_not_email(@u_participating) + should_not_email(@u_disabled) + end end describe :close_issue do -- cgit v1.2.1 From 5de8971ddfa10cbc6a082316eee7377038670f75 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 15 Jan 2016 16:02:48 +0100 Subject: Whoops, forgot to add files --- lib/gitlab/diff/inline_diff.rb | 75 +++++++++++++++++++++++++++++++ lib/gitlab/diff/inline_diff_marker.rb | 85 +++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 lib/gitlab/diff/inline_diff.rb create mode 100644 lib/gitlab/diff/inline_diff_marker.rb diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb new file mode 100644 index 00000000000..bae297ab00f --- /dev/null +++ b/lib/gitlab/diff/inline_diff.rb @@ -0,0 +1,75 @@ +module Gitlab + module Diff + class InlineDiff + attr_accessor :lines + + def initialize(lines) + @lines = lines + end + + def inline_diffs + inline_diffs = [] + + local_edit_indexes.each do |index| + old_index = index + new_index = index + 1 + old_line = @lines[old_index] + new_line = @lines[new_index] + + suffixless_old_line = old_line[1..-1] + suffixless_new_line = new_line[1..-1] + + # Skip inline diff if empty line was replaced with content + next if suffixless_old_line == "" + + # Add one, because this is based on the suffixless version + lcp = longest_common_prefix(suffixless_old_line, suffixless_new_line) + 1 + lcs = longest_common_suffix(suffixless_old_line, suffixless_new_line) + + old_diff_range = lcp..(old_line.length - lcs - 1) + new_diff_range = lcp..(new_line.length - lcs - 1) + + inline_diffs[old_index] = [old_diff_range] if old_diff_range.begin <= old_diff_range.end + inline_diffs[new_index] = [new_diff_range] if new_diff_range.begin <= new_diff_range.end + end + + inline_diffs + end + + private + + def local_edit_indexes + line_prefixes = @lines.map { |line| line.match(/\A([+-])/) ? $1 : ' ' } + joined_line_prefixes = " #{line_prefixes.join} " + + offset = 0 + local_edit_indexes = [] + while index = joined_line_prefixes.index(" -+ ", offset) + local_edit_indexes << index + offset = index + 1 + end + + local_edit_indexes + end + + def longest_common_prefix(a, b) + max_length = [a.length, b.length].max + + length = 0 + (0..max_length - 1).each do |pos| + old_char = a[pos] + new_char = b[pos] + + break if old_char != new_char + length += 1 + end + + length + end + + def longest_common_suffix(a, b) + longest_common_prefix(a.reverse, b.reverse) + end + end + end +end diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb new file mode 100644 index 00000000000..4bb755e3d3d --- /dev/null +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -0,0 +1,85 @@ +module Gitlab + module Diff + class InlineDiffMarker + attr_accessor :raw_line, :rich_line + + def initialize(raw_line, rich_line = raw_line) + @raw_line = raw_line + @rich_line = rich_line + end + + def mark(line_inline_diffs) + offset = 0 + line_inline_diffs.each do |inline_diff_range| + inline_diff_positions = position_mapping[inline_diff_range] + marker_ranges = collapse_ranges(inline_diff_positions) + + marker_ranges.each do |range| + offset = insert_around_range(rich_line, range, "", "", offset) + end + end + + rich_line + end + + def position_mapping + @position_mapping ||= begin + mapping = [] + raw_pos = 0 + rich_pos = 0 + (0..raw_line.length).each do |raw_pos| + raw_char = raw_line[raw_pos] + rich_char = rich_line[rich_pos] + + while rich_char == '<' + until rich_char == '>' + rich_pos += 1 + rich_char = rich_line[rich_pos] + end + + rich_pos += 1 + rich_char = rich_line[rich_pos] + end + + mapping[raw_pos] = rich_pos + + rich_pos += 1 + end + + mapping + end + end + + def collapse_ranges(positions) + return [] if positions.empty? + ranges = [] + + start = prev = positions[0] + range = start..prev + positions[1..-1].each do |pos| + if pos == prev + 1 + range = start..pos + prev = pos + else + ranges << range + start = prev = pos + range = start..prev + end + end + ranges << range + + ranges + end + + def insert_around_range(text, range, before, after, offset = 0) + text.insert(offset + range.begin, before) + offset += before.length + + text.insert(offset + range.end + 1, after) + offset += after.length + + offset + end + end + end +end -- cgit v1.2.1 From 12546f895f86929ffe69299a02c93692370ee55a Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 15 Jan 2016 16:29:26 +0100 Subject: Add tests --- lib/gitlab/diff/inline_diff.rb | 1 + lib/gitlab/diff/inline_diff_marker.rb | 10 +++++++++ spec/lib/gitlab/diff/inline_diff_marker_spec.rb | 15 ++++++++++++++ spec/lib/gitlab/diff/inline_diff_spec.rb | 27 +++++++++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 spec/lib/gitlab/diff/inline_diff_marker_spec.rb create mode 100644 spec/lib/gitlab/diff/inline_diff_spec.rb diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb index bae297ab00f..e5986fd69e2 100644 --- a/lib/gitlab/diff/inline_diff.rb +++ b/lib/gitlab/diff/inline_diff.rb @@ -38,6 +38,7 @@ module Gitlab private + # Find runs of single line edits def local_edit_indexes line_prefixes = @lines.map { |line| line.match(/\A([+-])/) ? $1 : ' ' } joined_line_prefixes = " #{line_prefixes.join} " diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb index 4bb755e3d3d..405465a641f 100644 --- a/lib/gitlab/diff/inline_diff_marker.rb +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -11,9 +11,12 @@ module Gitlab def mark(line_inline_diffs) offset = 0 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] + # Turn the array of character positions into ranges marker_ranges = collapse_ranges(inline_diff_positions) + # Mark each range marker_ranges.each do |range| offset = insert_around_range(rich_line, range, "", "", offset) end @@ -22,6 +25,9 @@ module Gitlab rich_line end + private + + # Mapping of character positions in the raw line, to the rich (highlighted) line def position_mapping @position_mapping ||= begin mapping = [] @@ -31,6 +37,8 @@ module Gitlab raw_char = raw_line[raw_pos] rich_char = rich_line[rich_pos] + # The raw and rich lines are the same except for HTML tags, + # so skip over any `<...>` segment while rich_char == '<' until rich_char == '>' rich_pos += 1 @@ -50,6 +58,7 @@ module Gitlab end end + # Takes an array of integers, and returns an array of ranges covering the same integers def collapse_ranges(positions) return [] if positions.empty? ranges = [] @@ -71,6 +80,7 @@ module Gitlab ranges end + # Inserts tags around the characters identified by the given range def insert_around_range(text, range, before, after, offset = 0) text.insert(offset + range.begin, before) offset += before.length diff --git a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb new file mode 100644 index 00000000000..5d6aea17509 --- /dev/null +++ b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe Gitlab::Diff::InlineDiffMarker, lib: true do + describe '#inline_diffs' do + let(:raw) { "abc def" } + let(:rich) { %{abc def} } + let(:inline_diffs) { [2..4] } + + let(:subject) { Gitlab::Diff::InlineDiffMarker.new(raw, rich).mark(inline_diffs) } + + it 'marks the inline diffs' do + expect(subject).to eq(%{abc def}) + end + end +end diff --git a/spec/lib/gitlab/diff/inline_diff_spec.rb b/spec/lib/gitlab/diff/inline_diff_spec.rb new file mode 100644 index 00000000000..056917df893 --- /dev/null +++ b/spec/lib/gitlab/diff/inline_diff_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe Gitlab::Diff::InlineDiff, lib: true do + describe '#inline_diffs' do + let(:diff) do + < Date: Fri, 15 Jan 2016 16:38:18 +0100 Subject: Add changelog entry for fix-consider-re-assign-as-a-mention --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index d01576be67a..f3916c39ec7 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.4.0 (unreleased) + - Consider re-assign as a mention from a notification point of view - Add pagination headers to already paginated API resources - Properly generate diff of orphan commits, like the first commit in a repository - Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages -- cgit v1.2.1 From 30a4f4c9e0cc44b67ea6041b8aef01196649b8d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 15 Jan 2016 17:57:45 +0100 Subject: This will ensure previous assignee gets an email even if his notif level is "on mention" --- app/services/notification_service.rb | 9 +++---- spec/services/notification_service_spec.rb | 40 ++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 60b86914a38..ca8a41d93b8 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -376,10 +376,10 @@ class NotificationService end def reassign_resource_email(target, project, current_user, method) - previous_assignee_id = previous_record(target, "assignee_id") + previous_assignee_id = previous_record(target, 'assignee_id') previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id - recipients = build_recipients(target, project, current_user, action: :reassign, extra_recipients: [previous_assignee]) + recipients = build_recipients(target, project, current_user, action: :reassign, previous_assignee: previous_assignee) recipients.each do |recipient| mailer.send( @@ -400,11 +400,9 @@ class NotificationService end end - def build_recipients(target, project, current_user, action: nil, extra_recipients: nil) + def build_recipients(target, project, current_user, action: nil, previous_assignee: nil) recipients = target.participants(current_user) - recipients = recipients.concat(extra_recipients).compact.uniq if extra_recipients - recipients = add_project_watchers(recipients, project) recipients = reject_mention_users(recipients, project) @@ -412,6 +410,7 @@ class NotificationService # new assignee to the list of recipients after we rejected users with # the "on mention" notification level if action == :reassign + recipients << previous_assignee if previous_assignee recipients << target.assignee end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index b63903af414..2d0b5df4224 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -227,6 +227,46 @@ describe NotificationService, services: true do end describe :reassigned_issue do + it 'emails new assignee' do + notification.reassigned_issue(issue, @u_disabled) + + should_email(issue.assignee) + should_email(@u_watcher) + should_email(@u_participant_mentioned) + should_email(@subscriber) + should_not_email(@unsubscriber) + should_not_email(@u_participating) + should_not_email(@u_disabled) + end + + it 'emails previous assignee even if he has the "on mention" notif level' do + issue.update_attribute(:assignee, @u_mentioned) + issue.update_attributes(assignee: @u_watcher) + notification.reassigned_issue(issue, @u_disabled) + + should_email(@u_mentioned) + should_email(@u_watcher) + should_email(@u_participant_mentioned) + should_email(@subscriber) + should_not_email(@unsubscriber) + should_not_email(@u_participating) + should_not_email(@u_disabled) + end + + it 'emails new assignee even if he has the "on mention" notif level' do + issue.update_attributes(assignee: @u_mentioned) + notification.reassigned_issue(issue, @u_disabled) + + expect(issue.assignee).to be @u_mentioned + should_email(issue.assignee) + should_email(@u_watcher) + should_email(@u_participant_mentioned) + should_email(@subscriber) + should_not_email(@unsubscriber) + should_not_email(@u_participating) + should_not_email(@u_disabled) + end + it 'emails new assignee' do issue.update_attribute(:assignee, @u_mentioned) notification.reassigned_issue(issue, @u_disabled) -- cgit v1.2.1 From adcab296fd48074daf9cac903d90270391f3e9d1 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 15 Jan 2016 10:33:42 +0100 Subject: Expose link to CI Lint Tool on builds page --- app/views/projects/builds/index.html.haml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index 5d18c0d803a..36b308b7b8f 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -6,7 +6,19 @@ - if can?(current_user, :manage_builds, @project) .pull-left.hidden-xs - if @all_builds.running_or_pending.any? - = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), + data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + + .pull-left.hidden-xs.hidden-sm{ style: 'margin-left: 7px;' } + .dropdown + %button.btn.btn-default.dropdown-toggle{ type: 'button', id: 'tools-dropdown', 'data-toggle' => 'dropdown' } + Tools + %span.caret + %ul.dropdown-menu.dropdown-menu-right + %li + = link_to ci_lint_path do + = icon('wrench') + %span CI Lint Tool %ul.nav-links %li{class: ('active' if @scope.nil?)} -- cgit v1.2.1 From 59ffe978fd5e89b55c737a030314a0bc3fdb85bd Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sun, 17 Jan 2016 16:33:53 +0100 Subject: Reuse existing CSS classes when exposing CI Lint tool --- app/views/projects/builds/index.html.haml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index 36b308b7b8f..747d94cc9e6 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -9,16 +9,15 @@ = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - .pull-left.hidden-xs.hidden-sm{ style: 'margin-left: 7px;' } - .dropdown - %button.btn.btn-default.dropdown-toggle{ type: 'button', id: 'tools-dropdown', 'data-toggle' => 'dropdown' } - Tools - %span.caret - %ul.dropdown-menu.dropdown-menu-right - %li - = link_to ci_lint_path do - = icon('wrench') - %span CI Lint Tool + .dropdown.inline + %button.btn.btn-default.dropdown-toggle{ type: 'button', id: 'tools-dropdown', 'data-toggle' => 'dropdown' } + Tools + %span.caret + %ul.dropdown-menu.dropdown-menu-right + %li + = link_to ci_lint_path do + = icon('wrench') + %span CI Lint Tool %ul.nav-links %li{class: ('active' if @scope.nil?)} -- cgit v1.2.1 From d9629a0cf03b80c8074b2ffa003d541193ca7097 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sun, 17 Jan 2016 16:57:42 +0100 Subject: Add specs for CI Lint button exposed on a builds page --- features/project/builds/summary.feature | 10 +++++++--- features/steps/project/builds/summary.rb | 9 ++++++++- features/steps/shared/builds.rb | 6 +++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/features/project/builds/summary.feature b/features/project/builds/summary.feature index e90ea592aab..9f006fcaca8 100644 --- a/features/project/builds/summary.feature +++ b/features/project/builds/summary.feature @@ -5,7 +5,11 @@ Feature: Project Builds Summary And project has CI enabled And project has a recent build - Scenario: I browse build summary page - When I visit recent build summary page - Then I see summary for build + Scenario: I browse build details page + When I visit recent build details page + Then I see details of a build And I see build trace + + Scenario: I browse project builds page + When I visit project builds page + Then I see button to CI Lint Tool diff --git a/features/steps/project/builds/summary.rb b/features/steps/project/builds/summary.rb index 2439d48fbef..67986b958ec 100644 --- a/features/steps/project/builds/summary.rb +++ b/features/steps/project/builds/summary.rb @@ -4,11 +4,18 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps include SharedBuilds include RepoHelpers - step 'I see summary for build' do + step 'I see details of a build' do expect(page).to have_content "Build ##{@build.id}" end step 'I see build trace' do expect(page).to have_css '#build-trace' end + + step 'I see button to CI Lint Tool' do + page.within('.controls') do + ci_lint_tool_link = page.find_link('CI Lint Tool') + expect(ci_lint_tool_link[:href]).to eq ci_lint_path + end + end end diff --git a/features/steps/shared/builds.rb b/features/steps/shared/builds.rb index f88b01af84e..92bf362879b 100644 --- a/features/steps/shared/builds.rb +++ b/features/steps/shared/builds.rb @@ -10,10 +10,14 @@ module SharedBuilds @build = create :ci_build, commit: ci_commit end - step 'I visit recent build summary page' do + step 'I visit recent build details page' do visit namespace_project_build_path(@project.namespace, @project, @build) end + step 'I visit project builds page' do + visit namespace_project_builds_path(@project.namespace, @project) + end + step 'recent build has artifacts available' do artifacts = Rails.root + 'spec/fixtures/ci_build_artifacts.zip' archive = fixture_file_upload(artifacts, 'application/zip') -- cgit v1.2.1 From 968998a9d18cd6e108abafc6ba4606ce7249fd0a Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sun, 17 Jan 2016 17:04:00 +0100 Subject: Add Changelog entry for exposing CI Lint tool on builds page --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index a15bbfbc49e..102382b02f6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -58,6 +58,7 @@ v 8.4.0 (unreleased) - Import GitHub wiki into GitLab - Add reporters ability to download and browse build artifacts (Andrew Johnson) - Autofill referring url in message box when reporting user abuse. (Josh Frye) + - Expose button to CI Lint tool on project builds page v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) -- cgit v1.2.1 From 7506afe14bad7bb4f93e26a539b3ffe75303e180 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Sun, 17 Jan 2016 18:13:45 +0100 Subject: Update build artifacts feature tests --- features/project/builds/artifacts.feature | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/features/project/builds/artifacts.feature b/features/project/builds/artifacts.feature index 7a7dbb71b18..d17c8aa89e6 100644 --- a/features/project/builds/artifacts.feature +++ b/features/project/builds/artifacts.feature @@ -7,21 +7,21 @@ Feature: Project Builds Artifacts Scenario: I download build artifacts Given recent build has artifacts available - When I visit recent build summary page + When I visit recent build details page And I click artifacts download button Then download of build artifacts archive starts Scenario: I browse build artifacts Given recent build has artifacts available And recent build has artifacts metadata available - When I visit recent build summary page + When I visit recent build details page And I click artifacts browse button Then I should see content of artifacts archive Scenario: I browse subdirectory of build artifacts Given recent build has artifacts available And recent build has artifacts metadata available - When I visit recent build summary page + When I visit recent build details page And I click artifacts browse button And I click link to subdirectory within build artifacts Then I should see content of subdirectory within artifacts archive @@ -30,7 +30,7 @@ Feature: Project Builds Artifacts Given recent build has artifacts available And recent build has artifacts metadata available And recent build artifacts contain directory with UTF-8 characters - When I visit recent build summary page + When I visit recent build details page And I click artifacts browse button And I navigate to directory with UTF-8 characters in name Then I should see content of directory with UTF-8 characters in name @@ -39,7 +39,7 @@ Feature: Project Builds Artifacts Given recent build has artifacts available And recent build has artifacts metadata available And recent build artifacts contain directory with invalid UTF-8 characters - When I visit recent build summary page + When I visit recent build details page And I click artifacts browse button And I navigate to parent directory of directory with invalid name Then I should not see directory with invalid name on the list @@ -47,7 +47,7 @@ Feature: Project Builds Artifacts Scenario: I download a single file from build artifacts Given recent build has artifacts available And recent build has artifacts metadata available - When I visit recent build summary page + When I visit recent build details page And I click artifacts browse button And I click download button for a file within build artifacts Then download of a file extracted from build artifacts should start -- cgit v1.2.1 From 6fe33804dc080522242d9ea3639548c2b246a56b Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 18 Jan 2016 08:12:31 +0100 Subject: Remove dropdown containing CI Lint button on builds page Link to CI Lint on builds page will be a separate button from now on. --- app/views/projects/builds/index.html.haml | 12 +++--------- features/project/builds/summary.feature | 2 +- features/steps/project/builds/summary.rb | 4 ++-- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml index 747d94cc9e6..bbb6944a65a 100644 --- a/app/views/projects/builds/index.html.haml +++ b/app/views/projects/builds/index.html.haml @@ -9,15 +9,9 @@ = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - .dropdown.inline - %button.btn.btn-default.dropdown-toggle{ type: 'button', id: 'tools-dropdown', 'data-toggle' => 'dropdown' } - Tools - %span.caret - %ul.dropdown-menu.dropdown-menu-right - %li - = link_to ci_lint_path do - = icon('wrench') - %span CI Lint Tool + = link_to ci_lint_path, class: 'btn btn-default' do + = icon('wrench') + %span CI Lint %ul.nav-links %li{class: ('active' if @scope.nil?)} diff --git a/features/project/builds/summary.feature b/features/project/builds/summary.feature index 9f006fcaca8..b69d279517b 100644 --- a/features/project/builds/summary.feature +++ b/features/project/builds/summary.feature @@ -12,4 +12,4 @@ Feature: Project Builds Summary Scenario: I browse project builds page When I visit project builds page - Then I see button to CI Lint Tool + Then I see button to CI Lint diff --git a/features/steps/project/builds/summary.rb b/features/steps/project/builds/summary.rb index 67986b958ec..036bc0a499e 100644 --- a/features/steps/project/builds/summary.rb +++ b/features/steps/project/builds/summary.rb @@ -12,9 +12,9 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps expect(page).to have_css '#build-trace' end - step 'I see button to CI Lint Tool' do + step 'I see button to CI Lint' do page.within('.controls') do - ci_lint_tool_link = page.find_link('CI Lint Tool') + ci_lint_tool_link = page.find_link('CI Lint') expect(ci_lint_tool_link[:href]).to eq ci_lint_path end end -- cgit v1.2.1 From 790c68680893b333c0a9bedca7c528147b8417b1 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Mon, 18 Jan 2016 16:55:14 +0100 Subject: Added documentation for GitLab Metrics --- doc/README.md | 7 +++ doc/metrics/gitlab_configuration.md | 12 +++++ doc/metrics/influxdb_configuration.md | 96 +++++++++++++++++++++++++++++++++++ doc/metrics/influxdb_schema.md | 75 +++++++++++++++++++++++++++ doc/metrics/introduction.md | 55 ++++++++++++++++++++ 5 files changed, 245 insertions(+) create mode 100644 doc/metrics/gitlab_configuration.md create mode 100644 doc/metrics/influxdb_configuration.md create mode 100644 doc/metrics/influxdb_schema.md create mode 100644 doc/metrics/introduction.md diff --git a/doc/README.md b/doc/README.md index 7d4f84857e0..b9ee7de5349 100644 --- a/doc/README.md +++ b/doc/README.md @@ -49,6 +49,13 @@ - [Test Clojure applications](ci/examples/test-clojure-application.md) - Help your favorite programming language and GitLab by sending a merge request with a guide for that language. +## GitLab Metrics + +- [Introduction](metrics/introduction.md) +- [GitLab Configuration](metrics/gitlab_configuration.md) +- [InfluxDB Configuration](metrics/influxdb_configuration.md) +- [InfluxDB Schema](metrics/influxdb_schema.md) + ## Administrator documentation - [Custom git hooks](hooks/custom_hooks.md) Custom git hooks (on the filesystem) for when web hooks aren't enough. diff --git a/doc/metrics/gitlab_configuration.md b/doc/metrics/gitlab_configuration.md new file mode 100644 index 00000000000..3b44b4394ff --- /dev/null +++ b/doc/metrics/gitlab_configuration.md @@ -0,0 +1,12 @@ +# GitLab Configuration + +By default GitLab Metrics is disabled. To enable GitLab Metrics and change any +of its settings open a web browser and navigate to +`http://YOUR_GITLAB_HOST/admin/application_settings`, the settings can be found +in the "Metrics" section. A restart of all GitLab processes is required for any +changes to take effect. + +## Pending Migrations + +When any migrations are pending the metrics are disabled until the migrations +have been performed. diff --git a/doc/metrics/influxdb_configuration.md b/doc/metrics/influxdb_configuration.md new file mode 100644 index 00000000000..c67c0f15108 --- /dev/null +++ b/doc/metrics/influxdb_configuration.md @@ -0,0 +1,96 @@ +# InfluxDB Configuration + +The default settings provided by InfluxDB are not sufficient for a high traffic +GitLab environment. The settings discussed in this document are based on the +settings GitLab uses for GitLab.com, depending on your own needs you may need to +further adjust them. + +## Requirements + +* InfluxDB 0.9 or newer +* A fairly modern version of Linux +* At least 4GB of RAM +* At least 10GB of storage for InfluxDB data + +Note that the RAM and storage requirements can differ greatly depending on the +amount of data received/stored. To limit the amount of stored data users can +look into [InfluxDB Retention Policies][influxdb-retention]. + +## InfluxDB Server Settings + +Since InfluxDB has many settings that users may wish to customize themselves +(e.g. what port to run InfluxDB on) we'll only cover the essentials. + +### Storage Engine + +InfluxDB comes with different storage engines and as of InfluxDB 0.9 a new +storage engine is available called "tsm1". All users _must_ use the new tsm1 +storage engine (this will be the default engine in upcoming InfluxDB engines). + +### Admin Panel + +Production environments should have the InfluxDB admin panel _disabled_. This +feature can be disabled by adding the following to your InfluxDB configuration +file: + + [admin] + enabled = false + +### HTTP + +HTTP is required when using the InfluxDB CLI or other tools such as Grafana, +thus it should be enabled. When enabling make sure to _also_ enable +authentication: + + [http] + enabled = true + auth-enabled = true + +### UDP + +GitLab writes data to InfluxDB via UDP and thus this must be enabled. Enabling +UDP can be done using the following settings: + + [udp] + enabled = true + bind-address = ":8089" + database = "gitlab" + batch-size = 1000 + batch-pending = 5 + batch-timeout = 1s + read-buffer = 209715200 + +This does the following: + +1. Enable UDP and bind it to port 8089 for all addresses. +2. Store any data received in the "gitlab" database. +3. Define a batch of points to be 1000 points in size and allow a maximum of + 5 batches _or_ flush them automatically after 1 second. +4. Define a UDP read buffer size of 200 MB. + +One of the most important settings here is the UDP read buffer size as if this +value is set too low packets will be dropped. You must also make sure the OS +buffer size is set to the same value, the default value is almost never enough. + +To set the OS buffer size to 200 MB on Linux you can run the following command: + + sysctl -w net.core.rmem_max=209715200 + +To make this permanent, add the following to `/etc/sysctl.conf` and restart the +server: + + net.core.rmem_max=209715200 + +It is **very important** to make sure the buffer sizes are large enough to +handle all data sent to InfluxDB as otherwise you _will_ lose data. The above +buffer sizes are based on the traffic for GitLab.com. Depending on the amount of +traffic users may be able to use a smaller buffer size, but we highly recommend +using _at least_ 100 MB. + +When enabling UDP users should take care to not expose the port to the public as +doing so will allow anybody to write data into your InfluxDB database (as +InfluxDB's UDP protocol doesn't support authentication). We recommend either +whitelisting the allowed IP addresses/ranges, or setting up a VLAN and only +allowing traffic from members of said VLAN. + +[influxdb-retention]: https://docs.influxdata.com/influxdb/v0.9/query_language/database_management/#retention-policy-management diff --git a/doc/metrics/influxdb_schema.md b/doc/metrics/influxdb_schema.md new file mode 100644 index 00000000000..a8e69b5e173 --- /dev/null +++ b/doc/metrics/influxdb_schema.md @@ -0,0 +1,75 @@ +# InfluxDB Schema + +The following measurements are currently stored in InfluxDB: + +* `PROCESS_file_descriptors` +* `PROCESS_gc_statistics` +* `PROCESS_memory_usage` +* `PROCESS_method_calls` +* `PROCESS_object_counts` +* `PROCESS_transactions` +* `PROCESS_views` + +Here `PROCESS` is replaced with either "rails" or "sidekiq" depending on the +process type. In all series any form of duration is stored in milliseconds. + +## PROCESS_file_descriptors + +This measurement contains the number of open file descriptors over time. The +value field `value` contains the number of descriptors. + +## PROCESS_gc_statistics + +This measurement contains Ruby garbage collection statistics such as the amount +of minor/major GC runs (relative to the last sampling interval), the time spent +in garbage collection cycles, and all fields/values returned by `GC.stat`. + +## PROCESS_memory_usage + +This measurement contains the process' memory usage (in bytes) over time. The +value field `value` contains the number of bytes. + +## PROCESS_method_calls + +This measurement contains the methods called during a transaction along with +their durations and a name of the transaction action that invoked the method (if +available). The method call duration is stored in the value field `duration` +while the method name is stored in the tag `method`. The tag `action` contains +the full name of the transaction action. Both the `method` and `action` fields +are in the following format: + + ClassName#method_name + +For example, a method called by the `show` method in the `UsersController` class +would have `action` set to `UsersController#show`. + +## PROCESS_object_counts + +This measurement is used to store retained Ruby objects (per class) and the +amount of retained objects. The number of objects is stored in the `count` value +field while the class name is stored in the `type` tag. + +## PROCESS_transactions + +This measurement is used to store basic transaction details such as the time it +took to complete a transaction, how much time was spent in SQL queries, etc. The +following value fields are available: + +* `duration`: the total duration of the transaction. +* `allocated_memory`: the amount of bytes allocated while the transaction was + running. This value is only reliable when using single-threaded application + servers. +* `method_duration`: the total time spent in method calls. +* `sql_duration`: the total time spent in SQL queries. +* `view_duration`: the total time spent in views. + +## PROCESS_views + +This measurement is used to store view rendering timings for a transaction. The +following value fields are available: + +* `duration`: the rendering time of the view. +* `view`: the path of the view, relative to the application's root directory. + +The `action` tag contains the action name of the transaction that rendered the +view. diff --git a/doc/metrics/introduction.md b/doc/metrics/introduction.md new file mode 100644 index 00000000000..007fff9e7b4 --- /dev/null +++ b/doc/metrics/introduction.md @@ -0,0 +1,55 @@ +# Introduction to GitLab Metrics + +GitLab comes with its own application performance measuring system as of GitLab +8.4, simply called "GitLab Metrics". GitLab Metrics is available in both the +Community and Enterprise editions. + +GitLab Metrics makes it possible to measure a wide variety of statistics +including (but not limited to): + +* The time it took to complete a transaction (a web request or Sidekiq job). +* The time spent in running SQL queries and rendering HAML views. +* The time spent executing (instrumented) Ruby methods. +* Ruby object allocations, and retained objects in particular. +* System statistics such as the process' memory usage and open file descriptors. +* Ruby garbage collection statistics. + +Metrics data is written to [InfluxDB][influxdb] over [UDP](influxdb-udp). Stored +data can be visualized using [Grafana][grafana] or any other application that +supports reading data from InfluxDB. Alternatively data can be queried using the +InfluxDB CLI. + +## Metric Types + +Two types of metrics are collected: + +1. Transaction specific metrics. +2. Sampled metrics, collected at a certain interval in a separate thread. + +### Transaction Metrics + +Transaction metrics are metrics that can be associated with a single +transaction. This includes statistics such as the transaction duration, timings +of any executed SQL queries, time spent rendering HAML views, etc. These metrics +are collected for every Rack request and Sidekiq job processed. + +### Sampled Metrics + +Sampled metrics are metrics that can't be associated with a single transaction. +Examples include garbage collection statistics and retained Ruby objects. These +metrics are collected at a regular interval. This interval is made up out of two +parts: + +1. A user defined interval. +2. A randomly generated offset added on top of the interval, the same offset + can't be used twice in a row. + +The actual interval can be anywhere between a half of the defined interval and a +half above the interval. For example, for a user defined interval of 15 seconds +the actual interval can be anywhere between 7.5 and 22.5. The interval is +re-generated for every sampling run instead of being generated once and re-used +for the duration of the process' lifetime. + +[influxdb]: https://influxdata.com/time-series-platform/influxdb/ +[influxdb-udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/ +[grafana]: http://grafana.org/ -- cgit v1.2.1 From 85e0fce9eee4f20c6c627209828f7351ab0aedae Mon Sep 17 00:00:00 2001 From: Jeroen Nijhof Date: Mon, 18 Jan 2016 17:15:10 +0100 Subject: Add sentry integration --- Gemfile | 3 +++ Gemfile.lock | 3 +++ .../admin/application_settings_controller.rb | 2 ++ app/models/application_setting.rb | 6 ++++++ app/views/admin/application_settings/_form.html.haml | 17 +++++++++++++++++ config/initializers/sentry.rb | 17 +++++++++++++++++ ...20160118155830_add_sentry_to_application_settings.rb | 8 ++++++++ db/schema.rb | 4 +++- spec/models/application_setting_spec.rb | 2 ++ 9 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 config/initializers/sentry.rb create mode 100644 db/migrate/20160118155830_add_sentry_to_application_settings.rb diff --git a/Gemfile b/Gemfile index a9a8bed1064..2363f483fc0 100644 --- a/Gemfile +++ b/Gemfile @@ -314,3 +314,6 @@ gem 'oauth2', '~> 1.0.0' # Soft deletion gem "paranoia", "~> 2.0" + +# Sentry integration +gem 'sentry-raven' diff --git a/Gemfile.lock b/Gemfile.lock index f1bba7f437e..07445f00608 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -725,6 +725,8 @@ GEM activesupport (>= 3.1, < 4.3) select2-rails (3.5.9.3) thor (~> 0.14) + sentry-raven (0.15.3) + faraday (>= 0.7.6) settingslogic (2.0.9) sexp_processor (4.6.0) sham_rack (1.3.6) @@ -1008,6 +1010,7 @@ DEPENDENCIES sdoc (~> 0.3.20) seed-fu (~> 2.3.5) select2-rails (~> 3.5.9) + sentry-raven settingslogic (~> 2.0.9) sham_rack shoulda-matchers (~> 2.8.0) diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 91f7d78bd73..9943745208e 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -77,6 +77,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :recaptcha_enabled, :recaptcha_site_key, :recaptcha_private_key, + :sentry_enabled, + :sentry_dsn, restricted_visibility_levels: [], import_sources: [] ) diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 6c6c2468374..59563b8823c 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -41,6 +41,8 @@ # recaptcha_site_key :string # recaptcha_private_key :string # metrics_port :integer default(8089) +# sentry_enabled :boolean default(FALSE) +# sentry_dsn :string # class ApplicationSetting < ActiveRecord::Base @@ -82,6 +84,10 @@ class ApplicationSetting < ActiveRecord::Base presence: true, if: :recaptcha_enabled + validates :sentry_dsn, + presence: true, + if: :sentry_enabled + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 83f6814d822..35af5cf620a 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -232,5 +232,22 @@ .col-sm-10 = f.text_field :recaptcha_private_key, class: 'form-control' + %fieldset + %legend Error Reporting and Logging + %p + These settings require a restart to take effect. + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :sentry_enabled do + = f.check_box :sentry_enabled + Enable Sentry + %span.help-block#sentry_help_block Sentry is an error reporting and logging tool + + .form-group + = f.label :sentry_dsn, 'Sentry DSN', class: 'control-label col-sm-2' + .col-sm-10 + = f.text_field :sentry_dsn, class: 'form-control' + .form-actions = f.submit 'Save', class: 'btn btn-primary' diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb new file mode 100644 index 00000000000..3ef46291981 --- /dev/null +++ b/config/initializers/sentry.rb @@ -0,0 +1,17 @@ +# Be sure to restart your server when you modify this file. + +require 'gitlab/current_settings' +include Gitlab::CurrentSettings + +# allow it to fail: it may do so when create_from_defaults is executed before migrations are actually done +begin + sentry_enabled = current_application_settings.sentry_enabled +rescue + sentry_enabled = false +end + +if sentry_enabled + Raven.configure do |config| + config.dsn = current_application_settings.sentry_dsn + end +end diff --git a/db/migrate/20160118155830_add_sentry_to_application_settings.rb b/db/migrate/20160118155830_add_sentry_to_application_settings.rb new file mode 100644 index 00000000000..fa7ff9d9228 --- /dev/null +++ b/db/migrate/20160118155830_add_sentry_to_application_settings.rb @@ -0,0 +1,8 @@ +class AddSentryToApplicationSettings < ActiveRecord::Migration + def change + change_table :application_settings do |t| + t.boolean :sentry_enabled, default: false + t.string :sentry_dsn + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 9045135dd9a..8394574dfe9 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: 20160113111034) do +ActiveRecord::Schema.define(version: 20160118155830) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -62,6 +62,8 @@ ActiveRecord::Schema.define(version: 20160113111034) do t.string "recaptcha_private_key" t.integer "metrics_port", default: 8089 t.integer "metrics_sample_interval", default: 15 + t.boolean "sentry_enabled", default: false + t.string "sentry_dsn" end create_table "audit_events", force: :cascade do |t| diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 91b250265e6..f4c58882757 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -41,6 +41,8 @@ # recaptcha_site_key :string # recaptcha_private_key :string # metrics_port :integer default(8089) +# sentry_enabled :boolean default(FALSE) +# sentry_dsn :string # require 'spec_helper' -- cgit v1.2.1 From 96fb81ee38a3d5e5eb5dc8c95a758c4c853d6c63 Mon Sep 17 00:00:00 2001 From: Ruben Schmidt Date: Mon, 18 Jan 2016 17:23:49 +0000 Subject: Fixed invalid JSON in first JSON Example line 27 --- doc/web_hooks/web_hooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index 6420d65cf1b..c29037e89c2 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -56,7 +56,7 @@ X-Gitlab-Event: Push Hook "author": { "name": "Jordi Mallach", "email": "jordi@softcatala.org" - } + }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] -- cgit v1.2.1 From 62571ae1f221477bd982160fb407bb08d7bc0a8e Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Fri, 15 Jan 2016 16:24:16 -0500 Subject: Fixes tooltip doesn't duplicate the "me" name. Checks that "me" is not in the array of names in tooltip --- app/assets/javascripts/awards_handler.coffee | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 9d5ae6c04e9..5ab509b52c1 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -66,14 +66,10 @@ class @AwardsHandler addMeToAuthorList: (emoji) -> award_block = @findEmojiIcon(emoji).parent() - authors = _.compact(award_block.attr("data-original-title").split(", ")) - authors.push("me") - - if authors.length == 1 - award_block.attr("title", "me") - else - award_block.attr("title", authors.join(", ")) - + authors = award_block.attr("data-original-title").split(", ") + if authors.indexOf("me") == -1 + authors.push("me") + award_block.attr("title", authors.join(", ")) @resetTooltip(award_block) resetTooltip: (award) -> -- cgit v1.2.1 From 419bff801be88eb3e2fd1be2e3c6d02514a478bd Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Mon, 18 Jan 2016 11:12:13 -0500 Subject: Removing initial `,`. --- app/assets/javascripts/awards_handler.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 5ab509b52c1..2c9c99d502f 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -66,9 +66,10 @@ class @AwardsHandler addMeToAuthorList: (emoji) -> award_block = @findEmojiIcon(emoji).parent() - authors = award_block.attr("data-original-title").split(", ") + authors = award_block.attr("data-original-title").trim().split(", ") if authors.indexOf("me") == -1 authors.push("me") + console.log('authors'); award_block.attr("title", authors.join(", ")) @resetTooltip(award_block) -- cgit v1.2.1 From c298068c45682ad2b75727029872878cd3cc5522 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Mon, 18 Jan 2016 15:40:48 -0500 Subject: Fix underlying issue with emoji reactions Issue was: blank space was rendering as a element in an array of authors. Element was being used by `join`. Original fix !2450 was trying to remove the space after it happened. This checks properly for it and only moves forward if it does not exist. Also removes "me" upon unchecking emoji. --- app/assets/javascripts/awards_handler.coffee | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 2c9c99d502f..42644229490 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -44,8 +44,7 @@ class @AwardsHandler decrementCounter: (emoji) -> counter = @findEmojiIcon(emoji).siblings(".counter") emojiIcon = counter.parent() - - if parseInt(counter.text()) > 1 + if parseInt(counter.text()) > 0 counter.text(parseInt(counter.text()) - 1) emojiIcon.removeClass("active") @removeMeFromAuthorList(emoji) @@ -60,16 +59,19 @@ class @AwardsHandler removeMeFromAuthorList: (emoji) -> award_block = @findEmojiIcon(emoji).parent() authors = award_block.attr("data-original-title").split(", ") - authors = _.without(authors, "me").join(", ") - award_block.attr("title", authors) + if authors.indexOf("me") != -1 + authors.splice(authors.indexOf("me"),1) + award_block.closest(".award").attr("data-original-title", authors.join(", ")) @resetTooltip(award_block) addMeToAuthorList: (emoji) -> award_block = @findEmojiIcon(emoji).parent() - authors = award_block.attr("data-original-title").trim().split(", ") + origTitle = award_block.attr("data-original-title").trim() + authors = [] + if origTitle + authors = origTitle.split(', ') if authors.indexOf("me") == -1 authors.push("me") - console.log('authors'); award_block.attr("title", authors.join(", ")) @resetTooltip(award_block) -- cgit v1.2.1 From c426a571dbdffcedee4200f5acc56aae02df3bf9 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Mon, 18 Jan 2016 19:27:59 -0500 Subject: Fix the situation where the user has named themselves "me" Stopped looking for existing user since remove functionality is fixed. --- app/assets/javascripts/awards_handler.coffee | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 42644229490..7136ef3258b 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -59,8 +59,7 @@ class @AwardsHandler removeMeFromAuthorList: (emoji) -> award_block = @findEmojiIcon(emoji).parent() authors = award_block.attr("data-original-title").split(", ") - if authors.indexOf("me") != -1 - authors.splice(authors.indexOf("me"),1) + authors.splice(authors.indexOf("me"),1) award_block.closest(".award").attr("data-original-title", authors.join(", ")) @resetTooltip(award_block) @@ -70,8 +69,7 @@ class @AwardsHandler authors = [] if origTitle authors = origTitle.split(', ') - if authors.indexOf("me") == -1 - authors.push("me") + authors.push("me") award_block.attr("title", authors.join(", ")) @resetTooltip(award_block) -- cgit v1.2.1 From 3c078cef41305d2c4126501f5de571143c19e147 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 13 Jan 2016 08:59:56 -0500 Subject: adds exclamation point when assigned user cannot merge --- app/assets/stylesheets/pages/projects.scss | 5 +++++ app/views/shared/issuable/_sidebar.html.haml | 3 +++ 2 files changed, 8 insertions(+) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 3a87b71078d..b14033720b5 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -558,3 +558,8 @@ pre.light-well { width: 101%; } } + +.cannot-be-merged, .cannot-be-merged:hover { + color: #E62958; + margin-top: 2px; +} diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 9f4a7098ea2..1eb14b51533 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -10,6 +10,9 @@ .value - if issuable.assignee %strong= link_to_member(@project, issuable.assignee, size: 24) + - if issuable.instance_of?(MergeRequest) && !@merge_request.can_be_merged_by?(issuable.assignee) + %a.pull-right.cannot-be-merged{href:'#', data:{toggle:'tooltip'}, title:'Not allowed to merge'} + = icon('exclamation-triangle') - else .light None -- cgit v1.2.1 From 8b3d6793454b2a955c88d9dcd65a130133996646 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 13 Jan 2016 23:31:30 -0500 Subject: color variable for error for exclamation point --- app/assets/stylesheets/framework/variables.scss | 2 ++ app/assets/stylesheets/pages/projects.scss | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 85ecdddda79..70239a74c85 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -26,6 +26,8 @@ $gl-vert-padding: 6px; $gl-padding-top:10px; $gl-avatar-size: 46px; $secondary-text: #7f8fa4; +$error-exclamation-point: #E62958; + /* * Color schema diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index b14033720b5..b715819e30a 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -560,6 +560,6 @@ pre.light-well { } .cannot-be-merged, .cannot-be-merged:hover { - color: #E62958; + color: $error-exclamation-point; margin-top: 2px; -} +} \ No newline at end of file -- cgit v1.2.1 From fbb27a4244994103ed94c4921fc47902a767b860 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Mon, 18 Jan 2016 20:17:29 -0500 Subject: Fix spacing issues, fix naming inconsistencies. Fix conflicts. Used `issuable` instead --- app/assets/stylesheets/pages/projects.scss | 4 ++-- app/views/shared/issuable/_sidebar.html.haml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index b715819e30a..b14033720b5 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -560,6 +560,6 @@ pre.light-well { } .cannot-be-merged, .cannot-be-merged:hover { - color: $error-exclamation-point; + color: #E62958; margin-top: 2px; -} \ No newline at end of file +} diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 1eb14b51533..3092ff54242 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -10,8 +10,8 @@ .value - if issuable.assignee %strong= link_to_member(@project, issuable.assignee, size: 24) - - if issuable.instance_of?(MergeRequest) && !@merge_request.can_be_merged_by?(issuable.assignee) - %a.pull-right.cannot-be-merged{href:'#', data:{toggle:'tooltip'}, title:'Not allowed to merge'} + - if issuable.instance_of?(MergeRequest) && !issuable.can_be_merged_by?(issuable.assignee) + %a.pull-right.cannot-be-merged{href: '#', data: {toggle: 'tooltip'}, title: 'Not allowed to merge'} = icon('exclamation-triangle') - else .light None -- cgit v1.2.1 From 78754cb1c9ad3dce56dd8257e95fc9241746b9f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Mon, 18 Jan 2016 21:39:23 -0500 Subject: Update Issues/MRs updated_at when user leaves comments. --- app/services/notes/create_service.rb | 4 +++- features/project/issues/issues.feature | 8 ++++++++ features/project/merge_requests.feature | 19 +++++++++++++++++++ features/steps/project/issues/issues.rb | 5 +++++ features/steps/project/merge_requests.rb | 8 ++++++++ features/steps/shared/note.rb | 7 +++++++ 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index a8486e6a5a1..ef98f0fd223 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -10,7 +10,9 @@ module Notes # Skip system notes, like status changes and cross-references and awards unless note.system || note.is_award - event_service.leave_note(note, note.author) + event = event_service.leave_note(note, note.author) + + note.noteable.touch if event.commented? note.create_cross_references! execute_hooks(note) end diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index ab234bc7507..1502b0952cd 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -51,6 +51,14 @@ Feature: Project Issues Then I should see comment "XML attached" And I should see an error alert section within the comment form + @javascript + Scenario: Visiting Issues after leaving a comment + Given I visit issue page "Release 0.4" + And I leave a comment like "XML attached" + And I visit project "Shop" issues page + And I sort the list by "Last updated" + Then I should see "Release 0.4" at the top + @javascript Scenario: I search issue Given I fill in issue search with "Re" diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index aa9078b878f..f1629a26f10 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -75,6 +75,25 @@ Feature: Project Merge Requests And I leave a comment like "XML attached" Then I should see comment "XML attached" + @javascript + Scenario: Visiting Merge Requests after leaving a comment + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-04" + And I leave a comment like "XML attached" + And I visit project "Shop" merge requests page + And I sort the list by "Last updated" + Then I should see "Bug NS-04" at the top + + @javascript + Scenario: Visiting Merge Requests after commenting on diffs + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-05" + And I click on the Changes tab + And I leave a comment like "Line is wrong" on diff + And I visit project "Shop" merge requests page + And I sort the list by "Last updated" + Then I should see "Bug NS-05" at the top + @javascript Scenario: I comment on a merge request diff Given project "Shop" have "Bug NS-05" open merge request with diffs inside diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index 8e8c9c57452..d556b73f9fd 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -293,6 +293,11 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps expect(page).to have_content('Yay!') end end + + step 'I should see "Release 0.4" at the top' do + expect(page.find('ul.content-list.issues-list li.issue:first-child')).to have_content("Release 0.4") + end + def filter_issue(text) fill_in 'issue_search', with: text end diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index be993d11093..bec9920f91b 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -415,6 +415,14 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end end + step 'I should see "Bug NS-05" at the top' do + expect(page.find('ul.content-list.mr-list li.merge-request:first-child')).to have_content("Bug NS-05") + end + + step 'I should see "Bug NS-04" at the top' do + expect(page.find('ul.content-list.mr-list li.merge-request:first-child')).to have_content("Bug NS-04") + end + def merge_request @merge_request ||= MergeRequest.find_by!(title: "Bug NS-05") end diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index 444d6726f99..eb6df61b8e6 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -144,4 +144,11 @@ module SharedNote expect(page).to have_content("+1 Awesome!") end end + + step 'I sort the list by "Last updated"' do + find('button.dropdown-toggle.btn').click + page.within('ul.dropdown-menu.dropdown-menu-align-right li') do + click_link "Last updated" + end + end end -- cgit v1.2.1 From 08c482b87ac08dbea533b931fabfb6939edc45ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Mon, 18 Jan 2016 21:59:22 -0500 Subject: Check if object respond to #touch before update. --- app/services/notes/create_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index ef98f0fd223..b39ebac1092 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -11,8 +11,9 @@ module Notes # Skip system notes, like status changes and cross-references and awards unless note.system || note.is_award event = event_service.leave_note(note, note.author) + noteable = note.noteable - note.noteable.touch if event.commented? + noteable.touch if event.commented? && noteable.respond_to?(:touch) note.create_cross_references! execute_hooks(note) end -- cgit v1.2.1 From 19608d3ee027efb27ecf83671a85487040287619 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 19 Jan 2016 12:00:38 +0100 Subject: Fix double request issue in artifacts browser --- app/views/projects/artifacts/browse.html.haml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index 9dc7b2c2e1f..b70c776a2b2 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -23,6 +23,10 @@ .center Empty :javascript - $(document).on('click', 'tr[data-link]', function(e) { + $('.tree-holder').on('click', 'tr[data-link] a', function(e) { + e.stopImmediatePropagation(); + }); + + $('.tree-holder').on('click', 'tr[data-link]', function(e) { window.location = this.dataset.link; }); -- cgit v1.2.1 From 0a8039eb7790426880bdd7b9d67775aeb6e5dac7 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 19 Jan 2016 13:56:36 +0100 Subject: Remove useless assignments --- lib/gitlab/diff/inline_diff_marker.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb index 405465a641f..8998ccba5ce 100644 --- a/lib/gitlab/diff/inline_diff_marker.rb +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -31,10 +31,8 @@ module Gitlab def position_mapping @position_mapping ||= begin mapping = [] - raw_pos = 0 rich_pos = 0 (0..raw_line.length).each do |raw_pos| - raw_char = raw_line[raw_pos] rich_char = rich_line[rich_pos] # The raw and rich lines are the same except for HTML tags, -- cgit v1.2.1 From b4ee6f57b9322401d1439eb21f9160ae2cb91d14 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 19 Jan 2016 13:48:07 +0100 Subject: Greatly improve external_issue_tracker performance This greatly improves the performance of Project#external_issue_tracker by moving most of the fields queried in Ruby to the database and letting the database handle all logic. Prior to this change the process of finding an external issue tracker was along the lines of the following: 1. Load all project services into memory. 2. Reduce the list to only services where "issue_tracker?" returns true 3. Reduce the list from step 2 to service where "default?" returns false 4. Find the first service where "activated?" returns true This has to two big problems: 1. Loading all services into memory only to reduce the list down to a single item later on is a waste of memory (and slow timing wise). 2. Calling Array#select followed by Array#reject followed by Array#find allocates extra objects when this really isn't needed. To work around this the following service fields have been moved to the database (instead of being hardcoded): * category * default This in turn means we can get the external issue tracker using the following query: SELECT * FROM services WHERE active IS TRUE AND default IS FALSE AND category = 'issue_tracker' AND project_id = XXX LIMIT 1 This coupled with memoizing the result (just as before this commit) greatly reduces the time it takes for Project#external_issue_tracker to complete. The exact reduction depends on one's environment, but locally the execution time is reduced from roughly 230 ms to only 2 ms (= a reduction of almost 180x). Fixes gitlab-org/gitlab-ce#10771 --- app/models/project.rb | 7 ++-- app/models/project_services/ci_service.rb | 8 ++--- .../gitlab_issue_tracker_service.rb | 4 +-- .../project_services/issue_tracker_service.rb | 6 ++-- app/models/service.rb | 11 ++++-- db/migrate/20160119111158_add_services_category.rb | 39 ++++++++++++++++++++++ db/migrate/20160119112418_add_services_default.rb | 20 +++++++++++ db/schema.rb | 30 +++++++++-------- 8 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 db/migrate/20160119111158_add_services_category.rb create mode 100644 db/migrate/20160119112418_add_services_default.rb diff --git a/app/models/project.rb b/app/models/project.rb index 7e131151513..cb668e0c2f7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -468,12 +468,9 @@ class Project < ActiveRecord::Base !external_issue_tracker end - def external_issues_trackers - services.select(&:issue_tracker?).reject(&:default?) - end - def external_issue_tracker - @external_issues_tracker ||= external_issues_trackers.find(&:activated?) + @external_issue_tracker ||= + services.issue_trackers.active.without_defaults.first end def can_have_issues_tracker_id? diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb index c3f70d1f972..e10b5529b42 100644 --- a/app/models/project_services/ci_service.rb +++ b/app/models/project_services/ci_service.rb @@ -23,14 +23,12 @@ # List methods you need to implement to get your CI service # working with GitLab Merge Requests class CiService < Service - def category - :ci - end - + default_value_for :category, 'ci' + def valid_token?(token) self.respond_to?(:token) && self.token.present? && self.token == token end - + def supported_events %w(push) end diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb index 7aa04309f54..05436cd0f79 100644 --- a/app/models/project_services/gitlab_issue_tracker_service.rb +++ b/app/models/project_services/gitlab_issue_tracker_service.rb @@ -24,9 +24,7 @@ class GitlabIssueTrackerService < IssueTrackerService prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url - def default? - true - end + default_value_for :default, true def to_param 'gitlab' diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb index ed201979d39..25045224ce5 100644 --- a/app/models/project_services/issue_tracker_service.rb +++ b/app/models/project_services/issue_tracker_service.rb @@ -23,12 +23,10 @@ class IssueTrackerService < Service validates :project_url, :issues_url, :new_issue_url, presence: true, if: :activated? - def category - :issue_tracker - end + default_value_for :category, 'issue_tracker' def default? - false + default end def issue_url(iid) diff --git a/app/models/service.rb b/app/models/service.rb index 24f4bf7646e..721273250ea 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -43,6 +43,9 @@ class Service < ActiveRecord::Base validates :project_id, presence: true, unless: Proc.new { |service| service.template? } scope :visible, -> { where.not(type: ['GitlabIssueTrackerService', 'GitlabCiService']) } + scope :issue_trackers, -> { where(category: 'issue_tracker') } + scope :active, -> { where(active: true) } + scope :without_defaults, -> { where(default: false) } scope :push_hooks, -> { where(push_events: true, active: true) } scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) } @@ -51,6 +54,8 @@ class Service < ActiveRecord::Base scope :note_hooks, -> { where(note_events: true, active: true) } scope :build_hooks, -> { where(build_events: true, active: true) } + default_value_for :category, 'common' + def activated? active end @@ -60,7 +65,7 @@ class Service < ActiveRecord::Base end def category - :common + read_attribute(:category).to_sym end def initialize_properties @@ -153,7 +158,7 @@ class Service < ActiveRecord::Base # Returns a hash of the properties that have been assigned a new value since last save, # indicating their original values (attr => original value). - # ActiveRecord does not provide a mechanism to track changes in serialized keys, + # ActiveRecord does not provide a mechanism to track changes in serialized keys, # so we need a specific implementation for service properties. # This allows to track changes to properties set with the accessor methods, # but not direct manipulation of properties hash. @@ -164,7 +169,7 @@ class Service < ActiveRecord::Base def reset_updated_properties @updated_properties = nil end - + def async_execute(data) return unless supported_events.include?(data[:object_kind]) diff --git a/db/migrate/20160119111158_add_services_category.rb b/db/migrate/20160119111158_add_services_category.rb new file mode 100644 index 00000000000..a9110a8418b --- /dev/null +++ b/db/migrate/20160119111158_add_services_category.rb @@ -0,0 +1,39 @@ +class AddServicesCategory < ActiveRecord::Migration + def up + add_column :services, :category, :string, default: 'common', null: false + + category = quote_column_name('category') + type = quote_column_name('type') + + execute <<-EOF +UPDATE services +SET #{category} = 'issue_tracker' +WHERE #{type} IN ( + 'CustomIssueTrackerService', + 'GitlabIssueTrackerService', + 'IssueTrackerService', + 'JiraService', + 'RedmineService' +); +EOF + + execute <<-EOF +UPDATE services +SET #{category} = 'ci' +WHERE #{type} IN ( + 'BambooService', + 'BuildkiteService', + 'CiService', + 'DroneCiService', + 'GitlabCiService', + 'TeamcityService' +); + EOF + + add_index :services, :category + end + + def down + remove_column :services, :category + end +end diff --git a/db/migrate/20160119112418_add_services_default.rb b/db/migrate/20160119112418_add_services_default.rb new file mode 100644 index 00000000000..69a42d7b873 --- /dev/null +++ b/db/migrate/20160119112418_add_services_default.rb @@ -0,0 +1,20 @@ +class AddServicesDefault < ActiveRecord::Migration + def up + add_column :services, :default, :boolean, default: false + + default = quote_column_name('default') + type = quote_column_name('type') + + execute <<-EOF +UPDATE services +SET #{default} = true +WHERE #{type} = 'GitlabIssueTrackerService' +EOF + + add_index :services, :default + end + + def down + remove_column :services, :default + end +end diff --git a/db/schema.rb b/db/schema.rb index 9045135dd9a..a08181b910f 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: 20160113111034) do +ActiveRecord::Schema.define(version: 20160119112418) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -725,20 +725,24 @@ ActiveRecord::Schema.define(version: 20160113111034) do t.string "type" t.string "title" t.integer "project_id" - t.datetime "created_at" - t.datetime "updated_at" - t.boolean "active", default: false, 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 - end - + 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 add_index "services", ["created_at", "id"], name: "index_services_on_created_at_and_id", using: :btree + add_index "services", ["default"], name: "index_services_on_default", using: :btree add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree add_index "services", ["template"], name: "index_services_on_template", using: :btree -- cgit v1.2.1 From f5562355f4580ea049d33991aa0eaf76f46b17f7 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 19 Jan 2016 08:44:16 -0500 Subject: Move multiple css rules to multiple lines. Removes extra line breaks. --- app/assets/stylesheets/framework/variables.scss | 1 - app/assets/stylesheets/pages/projects.scss | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 70239a74c85..3ec48da9a41 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -28,7 +28,6 @@ $gl-avatar-size: 46px; $secondary-text: #7f8fa4; $error-exclamation-point: #E62958; - /* * Color schema */ diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index b14033720b5..003a4c22f20 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -559,7 +559,8 @@ pre.light-well { } } -.cannot-be-merged, .cannot-be-merged:hover { +.cannot-be-merged, +.cannot-be-merged:hover { color: #E62958; margin-top: 2px; } -- cgit v1.2.1 From 512bebe21d7f57b691a1c8355581feb64b9b6292 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 19 Jan 2016 14:52:41 +0100 Subject: Refactor Gitlab::Highlight and fix tests --- app/helpers/blob_helper.rb | 8 ++- app/views/projects/blame/show.html.haml | 5 +- app/views/shared/_file_highlight.html.haml | 3 +- lib/gitlab/highlight.rb | 26 ++++++-- spec/fixtures/parallel_diff_result.yml | 98 +++++++++++++++--------------- spec/helpers/blob_helper_spec.rb | 63 ++++++++++--------- spec/lib/gitlab/diff/highlight_spec.rb | 63 ++++++------------- 7 files changed, 131 insertions(+), 135 deletions(-) diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index be856242c43..7c55934edda 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -1,6 +1,10 @@ module BlobHelper - def highlight(blob_name, blob_content, nowrap: false, continue: false) - Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap, continue: continue) + def highlighter(blob_name, blob_content, nowrap: false) + Gitlab::Highlight.new(blob_name, blob_content, nowrap: nowrap) + end + + def highlight(blob_name, blob_content, nowrap: false) + Gitlab::Highlight.highlight(blob_name, blob_content, nowrap: nowrap) end def no_highlight_files diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index 8d9ec068a43..d5d04954490 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -15,6 +15,7 @@ .file-content.blame.highlight %table - current_line = 1 + - blame_highlighter = highlighter(@blob.name, @blob.data, nowrap: true) - @blame.each do |blame_group| %tr %td.blame-commit @@ -41,5 +42,5 @@ %pre{class: 'code highlight white'} %code - blame_group[:lines].each do |line| - :erb - <%= highlight(@blob.name, line, nowrap: true, continue: true).html_safe %> + :preserve + #{blame_highlighter.highlight(line)} diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml index 2bc98983d67..1bef1de433a 100644 --- a/app/views/shared/_file_highlight.html.haml +++ b/app/views/shared/_file_highlight.html.haml @@ -9,5 +9,4 @@ %i.fa.fa-link = i .blob-content{data: {blob_id: blob.id}} - :preserve - #{highlight(blob.name, blob.data)} + = highlight(blob.name, blob.data) diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb index a5b041687e3..28cfebef968 100644 --- a/lib/gitlab/highlight.rb +++ b/lib/gitlab/highlight.rb @@ -1,10 +1,7 @@ module Gitlab class Highlight - def self.highlight(blob_name, blob_content, nowrap: true, continue: false) - formatter = rouge_formatter(nowrap: nowrap) - - lexer = Rouge::Lexer.guess(filename: blob_name, source: blob_content).new rescue Rouge::Lexers::PlainText - formatter.format(lexer.lex(blob_content, continue: continue)).html_safe + def self.highlight(blob_name, blob_content, nowrap: true) + new(blob_name, blob_content, nowrap: nowrap).highlight(blob_content, continue: false) end def self.highlight_lines(repository, ref, file_name) @@ -14,9 +11,26 @@ module Gitlab highlight(file_name, blob.data).lines.map!(&:html_safe) end + def initialize(blob_name, blob_content, nowrap: true) + @formatter = rouge_formatter(nowrap: nowrap) + @lexer = Rouge::Lexer.guess(filename: blob_name, source: blob_content).new rescue Rouge::Lexers::PlainText + end + + def highlight(text, continue: true) + @formatter.format(lex(text, continue: continue)).html_safe + end + private - def self.rouge_formatter(options = {}) + def lex(text, continue: true) + if @lexer == Rouge::Lexers::PlainText + @lexer.lex(text) + else + @lexer.lex(text, continue: continue) + end + end + + def rouge_formatter(options = {}) options = options.reverse_merge( nowrap: true, cssclass: 'code highlight', diff --git a/spec/fixtures/parallel_diff_result.yml b/spec/fixtures/parallel_diff_result.yml index 4583de1231e..0fb9bf6c5d8 100644 --- a/spec/fixtures/parallel_diff_result.yml +++ b/spec/fixtures/parallel_diff_result.yml @@ -10,37 +10,37 @@ :text: "@@ -6,12 +6,18 @@ module Popen" :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - :left: - :type: + :type: :number: 6 :text: |2 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 :right: - :type: + :type: :number: 6 :text: |2 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6 - :left: - :type: + :type: :number: 7 :text: |2 def popen(cmd, path=nil) :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 :right: - :type: + :type: :number: 7 :text: |2 def popen(cmd, path=nil) :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7 - :left: - :type: + :type: :number: 8 :text: |2 unless cmd.is_a?(Array) :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_8_8 :right: - :type: + :type: :number: 8 :text: |2 unless cmd.is_a?(Array) @@ -55,40 +55,40 @@ :type: new :number: 9 :text: | - + raise RuntimeError, "System commands must be given as an array of strings" + + raise RuntimeError, "System commands must be given as an array of strings" :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9 - :left: - :type: + :type: :number: 10 :text: |2 end :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 :right: - :type: + :type: :number: 10 :text: |2 end :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_10 - :left: - :type: + :type: :number: 11 :text: |2 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 :right: - :type: + :type: :number: 11 :text: |2 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_11_11 - :left: - :type: + :type: :number: 12 :text: |2 path ||= Dir.pwd :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_12_12 :right: - :type: + :type: :number: 12 :text: |2 path ||= Dir.pwd @@ -101,9 +101,9 @@ :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_13_13 :right: :type: old - :number: + :number: :text: '' - :line_code: + :line_code: - :left: :type: old :number: 14 @@ -117,8 +117,8 @@ + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_13 - :left: - :type: - :number: + :type: + :number: :text: '' :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 :right: @@ -128,8 +128,8 @@ + vars = { :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_14 - :left: - :type: - :number: + :type: + :number: :text: '' :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 :right: @@ -139,8 +139,8 @@ + "PWD" => path :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_15 - :left: - :type: - :number: + :type: + :number: :text: '' :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 :right: @@ -150,8 +150,8 @@ + } :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_16 - :left: - :type: - :number: + :type: + :number: :text: '' :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 :right: @@ -161,8 +161,8 @@ + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_17 - :left: - :type: - :number: + :type: + :number: :text: '' :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 :right: @@ -172,8 +172,8 @@ + options = { :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_18 - :left: - :type: - :number: + :type: + :number: :text: '' :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 :right: @@ -183,8 +183,8 @@ + chdir: path :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_19 - :left: - :type: - :number: + :type: + :number: :text: '' :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 :right: @@ -194,37 +194,37 @@ + } :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_20 - :left: - :type: + :type: :number: 15 :text: |2 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 :right: - :type: + :type: :number: 21 :text: |2 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_15_21 - :left: - :type: + :type: :number: 16 :text: |2 unless File.directory?(path) :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 :right: - :type: + :type: :number: 22 :text: |2 unless File.directory?(path) :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_16_22 - :left: - :type: + :type: :number: 17 :text: |2 FileUtils.mkdir_p(path) :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_17_23 :right: - :type: + :type: :number: 23 :text: |2 FileUtils.mkdir_p(path) @@ -240,44 +240,44 @@ :text: "@@ -19,6 +25,7 @@ module Popen" :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - :left: - :type: + :type: :number: 19 :text: |2 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 :right: - :type: + :type: :number: 25 :text: |2 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_19_25 - :left: - :type: + :type: :number: 20 :text: |2 @cmd_output = "" :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 :right: - :type: + :type: :number: 26 :text: |2 @cmd_output = "" :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_20_26 - :left: - :type: + :type: :number: 21 :text: |2 @cmd_status = 0 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 :right: - :type: + :type: :number: 27 :text: |2 @cmd_status = 0 :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_21_27 - :left: - :type: - :number: + :type: + :number: :text: '' :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 :right: @@ -287,37 +287,37 @@ + :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_28 - :left: - :type: + :type: :number: 22 :text: |2 Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 :right: - :type: + :type: :number: 29 :text: |2 Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr| :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_22_29 - :left: - :type: + :type: :number: 23 :text: |2 @cmd_output << stdout.read :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 :right: - :type: + :type: :number: 30 :text: |2 @cmd_output << stdout.read :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_23_30 - :left: - :type: + :type: :number: 24 :text: |2 @cmd_output << stderr.read :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_24_31 :right: - :type: + :type: :number: 31 :text: |2 @cmd_output << stderr.read diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb index b8bba36439a..87849230dbe 100644 --- a/spec/helpers/blob_helper_spec.rb +++ b/spec/helpers/blob_helper_spec.rb @@ -1,22 +1,22 @@ require 'spec_helper' describe BlobHelper do - describe 'highlight' do - let(:blob_name) { 'test.lisp' } - let(:no_context_content) { ":type \"assem\"))" } - let(:blob_content) { "(make-pathname :defaults name\n#{no_context_content}" } - let(:split_content) { blob_content.split("\n") } - let(:multiline_content) do - %q( - def test(input): - """This is line 1 of a multi-line comment. - This is line 2. - """ - ) - end + let(:blob_name) { 'test.lisp' } + let(:no_context_content) { ":type \"assem\"))" } + let(:blob_content) { "(make-pathname :defaults name\n#{no_context_content}" } + let(:split_content) { blob_content.split("\n") } + let(:multiline_content) do + %q( + def test(input): + """This is line 1 of a multi-line comment. + This is line 2. + """ + ) + end + describe '#highlight' do it 'should return plaintext for unknown lexer context' do - result = highlight(blob_name, no_context_content, nowrap: true, continue: false) + result = helper.highlight(blob_name, no_context_content, nowrap: true) expect(result).to eq(':type "assem"))') end @@ -24,28 +24,17 @@ describe BlobHelper do expected = %Q[(make-pathname :defaults name :type "assem"))] - expect(highlight(blob_name, blob_content, nowrap: true, continue: false)).to eq(expected) - end - - it 'should highlight continued blocks' do - # Both lines have LC1 as ID since formatter doesn't support continue at the moment - expected = [ - '(make-pathname :defaults name', - ':type "assem"))' - ] - - result = split_content.map{ |content| highlight(blob_name, content, nowrap: true, continue: true) } - expect(result).to eq(expected) + expect(helper.highlight(blob_name, blob_content, nowrap: true)).to eq(expected) end it 'should highlight multi-line comments' do - result = highlight(blob_name, multiline_content, nowrap: true, continue: false) + result = helper.highlight(blob_name, multiline_content, nowrap: true) html = Nokogiri::HTML(result) lines = html.search('.s') expect(lines.count).to eq(3) expect(lines[0].text).to eq('"""This is line 1 of a multi-line comment.') - expect(lines[1].text).to eq(' This is line 2.') - expect(lines[2].text).to eq(' """') + expect(lines[1].text).to eq(' This is line 2.') + expect(lines[2].text).to eq(' """') end context 'diff highlighting' do @@ -59,9 +48,23 @@ describe BlobHelper do end it 'should highlight each line properly' do - result = highlight(blob_name, blob_content, nowrap: true, continue: false) + result = helper.highlight(blob_name, blob_content, nowrap: true) expect(result).to eq(expected) end end end + + describe "#highlighter" do + it 'should highlight continued blocks' do + # Both lines have LC1 as ID since formatter doesn't support continue at the moment + expected = [ + '(make-pathname :defaults name', + ':type "assem"))' + ] + + highlighter = helper.highlighter(blob_name, blob_content, nowrap: true) + result = split_content.map{ |content| highlighter.highlight(content) } + expect(result).to eq(expected) + end + end end diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index f307dcaae44..b54e95483d3 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -8,59 +8,34 @@ describe Gitlab::Diff::Highlight, lib: true do let(:diff) { commit.diffs.first } let(:diff_file) { Gitlab::Diff::File.new(diff, [commit.parent, commit]) } - describe '.process_diff_lines' do - context 'when processing Gitlab::Diff::Line objects' do - let(:diff_lines) { Gitlab::Diff::Highlight.process_diff_lines(diff_file) } + describe '#highlight' do + let(:diff_lines) { Gitlab::Diff::Highlight.new(diff_file).highlight } - it 'should return Gitlab::Diff::Line elements' do - expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line) - end - - it 'should highlight the code' do - code = %Q{ def popen(cmd, path=nil)\n} - - expect(diff_lines[2].text).to eq(code) - end - - it 'should not generate the inline diff markup' do - expect(diff_lines[5].text).not_to match(Regexp.new(Regexp.escape(''))) - end - - it 'should not modify "match" lines' do - expect(diff_lines[0].text).to eq('@@ -6,12 +6,18 @@ module Popen') - expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') - end - - it 'should highlight unchanged lines' do - code = %Q{ def popen(cmd, path=nil)\n} + it 'should return Gitlab::Diff::Line elements' do + expect(diff_lines.first).to be_an_instance_of(Gitlab::Diff::Line) + end - expect(diff_lines[2].text).to eq(code) - end + it 'should not modify "match" lines' do + expect(diff_lines[0].text).to eq('@@ -6,12 +6,18 @@ module Popen') + expect(diff_lines[22].text).to eq('@@ -19,6 +25,7 @@ module Popen') + end - it 'should highlight added lines' do - code = %Q{+ raise RuntimeError, "System commands must be given as an array of strings"\n} + it 'should highlight unchanged lines' do + code = %Q{ def popen(cmd, path=nil)\n} - expect(diff_lines[5].text).to eq(code) - end + expect(diff_lines[2].text).to eq(code) + end - it 'should highlight removed lines' do - code = %Q{- raise "System commands must be given as an array of strings"\n} + it 'should highlight removed lines' do + code = %Q{- raise "System commands must be given as an array of strings"\n} - expect(diff_lines[4].text).to eq(code) - end + expect(diff_lines[4].text).to eq(code) end - end - describe '.highlight_lines' do - let(:lines) do - Gitlab::Diff::Highlight.highlight_lines(project.repository, commit.id, 'files/ruby/popen.rb') - end + it 'should highlight added lines' do + code = %Q{+ raise RuntimeError, "System commands must be given as an array of strings"\n} - it 'should properly highlight all the lines' do - expect(lines[4]).to eq(%Q{ extend self\n}) - expect(lines[21]).to eq(%Q{ unless File.directory?(path)\n}) - expect(lines[26]).to eq(%Q{ @cmd_status = 0\n}) + expect(diff_lines[5].text).to eq(code) end end - end -- cgit v1.2.1 From 5c7259c7c30228bf85a4efbbddb673046e8d733f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 19 Jan 2016 15:13:37 +0100 Subject: Don't crash when file can't be highlighted --- lib/gitlab/highlight.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb index 28cfebef968..4ddb4fea977 100644 --- a/lib/gitlab/highlight.rb +++ b/lib/gitlab/highlight.rb @@ -17,19 +17,13 @@ module Gitlab end def highlight(text, continue: true) - @formatter.format(lex(text, continue: continue)).html_safe + @formatter.format(@lexer.lex(text, continue: continue)).html_safe + rescue + @formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe end private - def lex(text, continue: true) - if @lexer == Rouge::Lexers::PlainText - @lexer.lex(text) - else - @lexer.lex(text, continue: continue) - end - end - def rouge_formatter(options = {}) options = options.reverse_merge( nowrap: true, -- cgit v1.2.1 From 10669097fa7621a175755d144c61ecb80a5ea9fb Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Wed, 13 Jan 2016 09:07:21 -0500 Subject: Add public params to GET /projects api. Closes #3788 --- CHANGELOG | 1 + doc/api/projects.md | 1 + lib/api/helpers.rb | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 207ddf1dd64..5bccb80a64d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.5.0 (unreleased) + - Add "public" flag to GET /projects api endpoint v 8.4.0 (unreleased) - Ensure Gravatar host looks like an actual host diff --git a/doc/api/projects.md b/doc/api/projects.md index 241229221db..29ed327d983 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -29,6 +29,7 @@ GET /projects Parameters: - `archived` (optional) - if passed, limit by archived status +- `public` (optional) - if passed, limit by public visibility - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 6d2380cf47d..68d0aa671b6 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -264,6 +264,10 @@ module API projects = projects.search(params[:search]) end + if params[:public].present? && parse_boolean(params[:public]) + projects = projects.public_only + end + projects.reorder(project_order_by => project_sort) end -- cgit v1.2.1 From 6951396dbeddc72821c3beddf5aa13d24eeb0712 Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Wed, 13 Jan 2016 09:53:41 -0500 Subject: Update all docs for public param --- doc/api/groups.md | 1 + doc/api/projects.md | 3 +++ 2 files changed, 4 insertions(+) diff --git a/doc/api/groups.md b/doc/api/groups.md index 808675d8605..c6f1975bdac 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -33,6 +33,7 @@ GET /groups/:id/projects Parameters: - `archived` (optional) - if passed, limit by archived status +- `public` (optional) - if passed, limit by public visibility - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria diff --git a/doc/api/projects.md b/doc/api/projects.md index 29ed327d983..8b9dec46f38 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -153,6 +153,7 @@ GET /projects/owned Parameters: - `archived` (optional) - if passed, limit by archived status +- `public` (optional) - if passed, limit by public visibility - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria @@ -168,6 +169,7 @@ GET /projects/starred Parameters: - `archived` (optional) - if passed, limit by archived status +- `public` (optional) - if passed, limit by public visibility - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria @@ -183,6 +185,7 @@ GET /projects/all Parameters: - `archived` (optional) - if passed, limit by archived status +- `public` (optional) - if passed, limit by public visibility - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria -- cgit v1.2.1 From 11797df1af483156b8cf11290c49c3f4d6089d99 Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Mon, 18 Jan 2016 12:41:49 -0500 Subject: Change 'public' flag to more robust 'visibility' query. --- CHANGELOG | 2 +- app/models/project.rb | 4 ++++ doc/api/groups.md | 2 +- doc/api/projects.md | 8 ++++---- lib/api/helpers.rb | 4 ++-- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5bccb80a64d..965b88fc11f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.5.0 (unreleased) - - Add "public" flag to GET /projects api endpoint + - Add "visibility" flag to GET /projects api endpoint v 8.4.0 (unreleased) - Ensure Gravatar host looks like an actual host diff --git a/app/models/project.rb b/app/models/project.rb index 7e131151513..56db0ce6cf6 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -272,6 +272,10 @@ class Project < ActiveRecord::Base query: "%#{query.try(:downcase)}%") end + def search_by_visibility(level) + where(visibility_level: visibility_levels[level.capitalize]) + end + def search_by_title(query) where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%") end diff --git a/doc/api/groups.md b/doc/api/groups.md index c6f1975bdac..d47e79ba47f 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -33,7 +33,7 @@ GET /groups/:id/projects Parameters: - `archived` (optional) - if passed, limit by archived status -- `public` (optional) - if passed, limit by public visibility +- `visibility` (optional) - if passed, limit by visibility `public`, `internal`, `private` - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria diff --git a/doc/api/projects.md b/doc/api/projects.md index 8b9dec46f38..3f372c955d2 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -29,7 +29,7 @@ GET /projects Parameters: - `archived` (optional) - if passed, limit by archived status -- `public` (optional) - if passed, limit by public visibility +- `visibility` (optional) - if passed, limit by visibility `public`, `internal`, `private` - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria @@ -153,7 +153,7 @@ GET /projects/owned Parameters: - `archived` (optional) - if passed, limit by archived status -- `public` (optional) - if passed, limit by public visibility +- `visibility` (optional) - if passed, limit by visibility `public`, `internal`, `private` - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria @@ -169,7 +169,7 @@ GET /projects/starred Parameters: - `archived` (optional) - if passed, limit by archived status -- `public` (optional) - if passed, limit by public visibility +- `visibility` (optional) - if passed, limit by visibility `public`, `internal`, `private` - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria @@ -185,7 +185,7 @@ GET /projects/all Parameters: - `archived` (optional) - if passed, limit by archived status -- `public` (optional) - if passed, limit by public visibility +- `visibility` (optional) - if passed, limit by visibility `public`, `internal`, `private` - `order_by` (optional) - Return requests ordered by `id`, `name`, `path`, `created_at`, `updated_at` or `last_activity_at` fields. Default is `created_at` - `sort` (optional) - Return requests sorted in `asc` or `desc` order. Default is `desc` - `search` (optional) - Return list of authorized projects according to a search criteria diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 68d0aa671b6..3f528b9f7c0 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -264,8 +264,8 @@ module API projects = projects.search(params[:search]) end - if params[:public].present? && parse_boolean(params[:public]) - projects = projects.public_only + if params[:visibility].present? + projects = projects.search_by_visibility(params[:visibility]) end projects.reorder(project_order_by => project_sort) -- cgit v1.2.1 From ae6080c791ee8b6aedd7091e2a321f5fe41f0978 Mon Sep 17 00:00:00 2001 From: Josh Frye Date: Tue, 19 Jan 2016 09:53:40 -0500 Subject: Add specs. Adjust filter. --- app/models/project.rb | 2 +- spec/requests/api/projects_spec.rb | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 56db0ce6cf6..60729d93187 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -273,7 +273,7 @@ class Project < ActiveRecord::Base end def search_by_visibility(level) - where(visibility_level: visibility_levels[level.capitalize]) + where(visibility_level: Gitlab::VisibilityLevel.const_get(level.upcase)) end def search_by_title(query) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 6f4c336b66c..2a310f3834d 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -90,6 +90,29 @@ describe API::API, api: true do end end + context 'and using the visibility filter' do + it 'should filter based on private visibility param' do + get api('/projects', user), { visibility: 'private' } + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::PRIVATE).count) + end + + it 'should filter based on internal visibility param' do + get api('/projects', user), { visibility: 'internal' } + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::INTERNAL).count) + end + + it 'should filter based on public visibility param' do + get api('/projects', user), { visibility: 'public' } + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(user.namespace.projects.where(visibility_level: Gitlab::VisibilityLevel::PUBLIC).count) + end + end + context 'and using sorting' do before do project2 -- cgit v1.2.1 From 2ece1b774aac36f4a92801c665355e7fe1c4d48f Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 19 Jan 2016 13:24:42 -0200 Subject: Fix creator should be added as a master of the project on creation --- CHANGELOG | 1 + app/services/projects/create_service.rb | 2 +- spec/services/projects/create_service_spec.rb | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 207ddf1dd64..adda5373c3c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -67,6 +67,7 @@ v 8.4.0 (unreleased) - Improve UX in builds artifacts browser - Increase default size of `data` column in `events` table when using MySQL - Expose button to CI Lint tool on project builds page + - Fix: Creator should be added as a master of the project on creation v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index a6820183bee..c94d7ab710f 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -95,7 +95,7 @@ module Projects system_hook_service.execute_hooks_for(@project, :create) unless @project.group - @project.team << [current_user, :master, current_user] + @project.team << [current_user, :master] end @project.import_start if @project.import? diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 5d0b18558b1..e43903dbd3c 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -32,6 +32,7 @@ describe Projects::CreateService, services: true do it { expect(@project).to be_valid } it { expect(@project.owner).to eq(@user) } + it { expect(@project.team.masters).to include(@user) } it { expect(@project.namespace).to eq(@user.namespace) } end -- cgit v1.2.1 From 98e1a5b63424b6912de98ee5055d3f9e57e63899 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 19 Jan 2016 16:25:38 +0100 Subject: Allow LDAP users to change their email if it was not set by the LDAP server --- CHANGELOG | 1 + app/models/user.rb | 5 +++- app/views/profiles/show.html.haml | 4 +-- .../20160119145451_add_ldap_email_to_users.rb | 30 ++++++++++++++++++++++ db/schema.rb | 3 ++- lib/gitlab/ldap/user.rb | 29 +++++++++++---------- lib/gitlab/o_auth/auth_hash.rb | 8 ++++-- lib/gitlab/o_auth/user.rb | 14 +++++----- spec/lib/gitlab/ldap/user_spec.rb | 28 +++++++++++++++++++- 9 files changed, 95 insertions(+), 27 deletions(-) create mode 100644 db/migrate/20160119145451_add_ldap_email_to_users.rb diff --git a/CHANGELOG b/CHANGELOG index 207ddf1dd64..dce909089f1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.5.0 (unreleased) v 8.4.0 (unreleased) + - Allow LDAP users to change their email if it was not set by the LDAP server - Ensure Gravatar host looks like an actual host - Consider re-assign as a mention from a notification point of view - Add pagination headers to already paginated API resources diff --git a/app/models/user.rb b/app/models/user.rb index 592468933ed..4214f01f6a4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -664,7 +664,10 @@ class User < ActiveRecord::Base end def all_emails - [self.email, *self.emails.map(&:email)] + all_emails = [] + all_emails << self.email unless self.temp_oauth_email? + all_emails.concat(self.emails.map(&:email)) + all_emails end def hook_attrs diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 9459d8a6295..add9a00138b 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -21,10 +21,10 @@ .form-group = f.label :email, class: "control-label" .col-sm-10 - - if @user.ldap_user? + - if @user.ldap_user? && @user.ldap_email? = f.text_field :email, class: "form-control", required: true, readonly: true %span.help-block.light - Email is read-only for LDAP user + Your email address was automatically set based on the LDAP server. - else - if @user.temp_oauth_email? = f.text_field :email, class: "form-control", required: true, value: nil diff --git a/db/migrate/20160119145451_add_ldap_email_to_users.rb b/db/migrate/20160119145451_add_ldap_email_to_users.rb new file mode 100644 index 00000000000..654d31ab15a --- /dev/null +++ b/db/migrate/20160119145451_add_ldap_email_to_users.rb @@ -0,0 +1,30 @@ +class AddLdapEmailToUsers < ActiveRecord::Migration + def up + add_column :users, :ldap_email, :boolean, default: false, null: false + + if Gitlab::Database.mysql? + execute %{ + UPDATE users, identities + SET users.ldap_email = TRUE + WHERE identities.user_id = users.id + AND users.email LIKE 'temp-email-for-oauth%' + AND identities.provider LIKE 'ldap%' + AND identities.extern_uid IS NOT NULL + } + else + execute %{ + UPDATE users + SET ldap_email = TRUE + FROM identities + WHERE identities.user_id = users.id + AND users.email LIKE 'temp-email-for-oauth%' + AND identities.provider LIKE 'ldap%' + AND identities.extern_uid IS NOT NULL + } + end + end + + def down + remove_column :users, :ldap_email + end +end diff --git a/db/schema.rb b/db/schema.rb index 9045135dd9a..46811904024 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: 20160113111034) do +ActiveRecord::Schema.define(version: 20160119145451) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -850,6 +850,7 @@ ActiveRecord::Schema.define(version: 20160113111034) 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 end add_index "users", ["admin"], name: "index_users_on_admin", using: :btree diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index aef08c97d1d..e044f0ecc6d 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -30,28 +30,31 @@ module Gitlab end def find_by_uid_and_provider - self.class.find_by_uid_and_provider( - auth_hash.uid, auth_hash.provider) + self.class.find_by_uid_and_provider(auth_hash.uid, auth_hash.provider) end def find_by_email - ::User.find_by(email: auth_hash.email.downcase) + ::User.find_by(email: auth_hash.email.downcase) if auth_hash.has_email? end def update_user_attributes - return unless persisted? + if persisted? + if auth_hash.has_email? + gl_user.skip_reconfirmation! + gl_user.email = auth_hash.email + end - gl_user.skip_reconfirmation! - gl_user.email = auth_hash.email + # find_or_initialize_by doesn't update `gl_user.identities`, and isn't autosaved. + identity = gl_user.identities.find { |identity| identity.provider == auth_hash.provider } + identity ||= gl_user.identities.build(provider: auth_hash.provider) - # find_or_initialize_by doesn't update `gl_user.identities`, and isn't autosaved. - identity = gl_user.identities.find { |identity| identity.provider == auth_hash.provider } - identity ||= gl_user.identities.build(provider: auth_hash.provider) + # For a new identity set extern_uid to the LDAP DN + # For an existing identity with matching email but changed DN, update the DN. + # For an existing identity with no change in DN, this line changes nothing. + identity.extern_uid = auth_hash.uid + end - # For a new user set extern_uid to the LDAP DN - # For an existing user with matching email but changed DN, update the DN. - # For an existing user with no change in DN, this line changes nothing. - identity.extern_uid = auth_hash.uid + gl_user.ldap_email = auth_hash.has_email? gl_user end diff --git a/lib/gitlab/o_auth/auth_hash.rb b/lib/gitlab/o_auth/auth_hash.rb index ba31599432b..36e5c2670bb 100644 --- a/lib/gitlab/o_auth/auth_hash.rb +++ b/lib/gitlab/o_auth/auth_hash.rb @@ -32,6 +32,10 @@ module Gitlab @password ||= Gitlab::Utils.force_utf8(Devise.friendly_token[0, 8].downcase) end + def has_email? + get_info(:email).present? + end + private def info @@ -46,8 +50,8 @@ module Gitlab def username_and_email @username_and_email ||= begin - username = get_info(:username) || get_info(:nickname) - email = get_info(:email) + username = get_info(:username).presence || get_info(:nickname).presence + email = get_info(:email).presence username ||= generate_username(email) if email email ||= generate_temporarily_email(username) if username diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb index e3d2cc65a8f..d87a72f7ba3 100644 --- a/lib/gitlab/o_auth/user.rb +++ b/lib/gitlab/o_auth/user.rb @@ -111,7 +111,7 @@ module Gitlab def block_after_signup? if creating_linked_ldap_user? ldap_config.block_auto_created_users - else + else Gitlab.config.omniauth.block_auto_created_users end end @@ -135,16 +135,16 @@ module Gitlab def user_attributes # Give preference to LDAP for sensitive information when creating a linked account if creating_linked_ldap_user? - username = ldap_person.username - email = ldap_person.email.first - else - username = auth_hash.username - email = auth_hash.email + username = ldap_person.username.presence + email = ldap_person.email.first.presence end + username ||= auth_hash.username + email ||= auth_hash.email + name = auth_hash.name name = ::Namespace.clean_path(username) if name.strip.empty? - + { name: name, username: ::Namespace.clean_path(username), diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb index 1e755259dae..03199a2523e 100644 --- a/spec/lib/gitlab/ldap/user_spec.rb +++ b/spec/lib/gitlab/ldap/user_spec.rb @@ -37,7 +37,7 @@ describe Gitlab::LDAP::User, lib: true do end it "dont marks existing ldap user as changed" do - create(:omniauth_user, email: 'john@example.com', extern_uid: 'my-uid', provider: 'ldapmain') + create(:omniauth_user, email: 'john@example.com', extern_uid: 'my-uid', provider: 'ldapmain', ldap_email: true) expect(ldap_user.changed?).to be_falsey end end @@ -110,6 +110,32 @@ describe Gitlab::LDAP::User, lib: true do end end + describe 'updating email' do + context "when LDAP sets an email" do + it "has a real email" do + expect(ldap_user.gl_user.email).to eq(info[:email]) + end + + it "has ldap_email set to true" do + expect(ldap_user.gl_user.ldap_email?).to be(true) + end + end + + context "when LDAP doesn't set an email" do + before do + info.delete(:email) + end + + it "has a temp email" do + expect(ldap_user.gl_user.temp_oauth_email?).to be(true) + end + + it "has ldap_email set to false" do + expect(ldap_user.gl_user.ldap_email?).to be(false) + end + end + end + describe 'blocking' do def configure_block(value) allow_any_instance_of(Gitlab::LDAP::Config). -- cgit v1.2.1 From d1938fae3d9a6f4d31576461fae3efb4f09686c4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 19 Jan 2016 16:26:44 +0100 Subject: Add missing specs --- spec/lib/gitlab/highlight_spec.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 spec/lib/gitlab/highlight_spec.rb diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb new file mode 100644 index 00000000000..1620eb6c60a --- /dev/null +++ b/spec/lib/gitlab/highlight_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe Gitlab::Highlight, lib: true do + include RepoHelpers + + let(:project) { create(:project) } + let(:commit) { project.commit(sample_commit.id) } + + describe '.highlight_lines' do + let(:lines) do + Gitlab::Highlight.highlight_lines(project.repository, commit.id, 'files/ruby/popen.rb') + end + + it 'should properly highlight all the lines' do + expect(lines[4]).to eq(%Q{ extend self\n}) + expect(lines[21]).to eq(%Q{ unless File.directory?(path)\n}) + expect(lines[26]).to eq(%Q{ @cmd_status = 0\n}) + end + end + +end -- cgit v1.2.1 From 1c728ddbce1b3e459e9c9332cf8753699955db43 Mon Sep 17 00:00:00 2001 From: John Galt Date: Tue, 19 Jan 2016 16:07:46 +0000 Subject: Fixed typo --- doc/workflow/protected_branches.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/workflow/protected_branches.md b/doc/workflow/protected_branches.md index 0adf9f8e3e8..fdf9a8d391c 100644 --- a/doc/workflow/protected_branches.md +++ b/doc/workflow/protected_branches.md @@ -1,6 +1,6 @@ # Protected branches -Permission in GitLab are fundamentally defined around the idea of having read or write permission to the repository and branches. +Permissions in GitLab are fundamentally defined around the idea of having read or write permission to the repository and branches. To prevent people from messing with history or pushing code without review, we've created protected branches. -- cgit v1.2.1 From c7264d2a76abdc9d173e2160e27974d41380e93f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 19 Jan 2016 11:40:43 -0500 Subject: Check if MR is not broken. --- app/models/merge_request.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index a9fc6bc167a..9511521879b 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -254,7 +254,7 @@ class MergeRequest < ActiveRecord::Base end def mergeable? - return false unless open? && !work_in_progress? + return false unless open? && !work_in_progress? && !broken? check_if_can_be_merged -- cgit v1.2.1 From 2821306a740d62153b1a9192cb912b04b42b9279 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 19 Jan 2016 16:48:43 +0000 Subject: when starring a project it correctly increase the star count This is instead of increasing star & fork count Fixed #11396 --- app/assets/javascripts/star.js.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/star.js.coffee b/app/assets/javascripts/star.js.coffee index d849b2e7950..f27780dda93 100644 --- a/app/assets/javascripts/star.js.coffee +++ b/app/assets/javascripts/star.js.coffee @@ -6,7 +6,7 @@ class @Star $starIcon = $this.find('i') toggleStar = (isStarred) -> - $this.parent().find('span.count').text data.star_count + $this.parent().find('.star-count').text data.star_count if isStarred $starSpan.removeClass('starred').text 'Star' $starIcon.removeClass('fa-star').addClass 'fa-star-o' @@ -19,4 +19,4 @@ class @Star return ).on 'ajax:error', (e, xhr, status, error) -> new Flash('Star toggle failed. Try again later.', 'alert') - return \ No newline at end of file + return -- cgit v1.2.1 From 84124380e815e549f50d82051b2b546c12d9a724 Mon Sep 17 00:00:00 2001 From: Anton Baklanov Date: Sat, 19 Dec 2015 21:04:40 +0200 Subject: Added X-GitLab-... headers to emails from CI and Email On Push services Fixes #2098 --- CHANGELOG | 1 + app/mailers/emails/builds.rb | 13 +++++++ app/mailers/emails/projects.rb | 6 ++- app/mailers/notify.rb | 15 +++++--- lib/gitlab/email/message/repository_push.rb | 1 + spec/mailers/notify_spec.rb | 57 ++++++++++++++++++++++++++++- 6 files changed, 84 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index adda5373c3c..48f820d858a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -68,6 +68,7 @@ v 8.4.0 (unreleased) - Increase default size of `data` column in `events` table when using MySQL - Expose button to CI Lint tool on project builds page - Fix: Creator should be added as a master of the project on creation + - Added X-GitLab-... headers to emails from CI and Email On Push services v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) diff --git a/app/mailers/emails/builds.rb b/app/mailers/emails/builds.rb index d58609a2de5..64c1ce8cfab 100644 --- a/app/mailers/emails/builds.rb +++ b/app/mailers/emails/builds.rb @@ -3,13 +3,26 @@ module Emails def build_fail_email(build_id, to) @build = Ci::Build.find(build_id) @project = @build.project + add_project_headers + add_build_headers + headers['X-GitLab-Build-Status'] = "failed" mail(to: to, subject: subject("Build failed for #{@project.name}", @build.short_sha)) end def build_success_email(build_id, to) @build = Ci::Build.find(build_id) @project = @build.project + add_project_headers + add_build_headers + headers['X-GitLab-Build-Status'] = "success" mail(to: to, subject: subject("Build success for #{@project.name}", @build.short_sha)) end + + private + def add_build_headers + headers['X-GitLab-Build-Id'] = @build.id + headers['X-GitLab-Build-Ref'] = @build.ref + end + end end diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb index b96418679bd..377c2999d6c 100644 --- a/app/mailers/emails/projects.rb +++ b/app/mailers/emails/projects.rb @@ -43,7 +43,7 @@ module Emails @current_user = @created_by = User.find(created_by_id) @access_level = access_level @invite_email = invite_email - + @target_url = namespace_project_url(@project.namespace, @project) mail(to: @created_by.notification_email, @@ -65,6 +65,10 @@ module Emails # used in notify layout @target_url = @message.target_url + @project = Project.find project_id + + add_project_headers + headers['X-GitLab-Author'] = @message.author_username mail(from: sender(@message.author_id, @message.send_from_committer_email?), reply_to: @message.reply_to, diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index e1cd075a978..8cbc9eefc7b 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -100,12 +100,7 @@ class Notify < BaseMailer end def mail_thread(model, headers = {}) - if @project - headers['X-GitLab-Project'] = @project.name - headers['X-GitLab-Project-Id'] = @project.id - headers['X-GitLab-Project-Path'] = @project.path_with_namespace - end - + add_project_headers headers["X-GitLab-#{model.class.name}-ID"] = model.id headers['X-GitLab-Reply-Key'] = reply_key @@ -152,4 +147,12 @@ class Notify < BaseMailer def reply_key @reply_key ||= SentNotification.reply_key end + + def add_project_headers + return unless @project + + headers['X-GitLab-Project'] = @project.name + headers['X-GitLab-Project-Id'] = @project.id + headers['X-GitLab-Project-Path'] = @project.path_with_namespace + end end diff --git a/lib/gitlab/email/message/repository_push.rb b/lib/gitlab/email/message/repository_push.rb index a2eb7a70bd2..a05ffeb9cd2 100644 --- a/lib/gitlab/email/message/repository_push.rb +++ b/lib/gitlab/email/message/repository_push.rb @@ -9,6 +9,7 @@ module Gitlab delegate :namespace, :name_with_namespace, to: :project, prefix: :project delegate :name, to: :author, prefix: :author + delegate :username, to: :author, prefix: :author def initialize(notify, project_id, recipient, opts = {}) raise ArgumentError, 'Missing options: author_id, ref, action' unless diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 8f86c491d3f..7289e596ef3 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -40,14 +40,38 @@ describe Notify do end end + shared_examples 'an email with X-GitLab headers containing project details' do + it 'has X-GitLab-Project* headers' do + is_expected.to have_header 'X-GitLab-Project', /#{project.name}/ + is_expected.to have_header 'X-GitLab-Project-Id', /#{project.id}/ + is_expected.to have_header 'X-GitLab-Project-Path', /#{project.path_with_namespace}/ + end + end + + shared_examples 'an email with X-GitLab headers containing build details' do + it 'has X-GitLab-Build* headers' do + is_expected.to have_header 'X-GitLab-Build-Id', /#{build.id}/ + is_expected.to have_header 'X-GitLab-Build-Ref', /#{build.ref}/ + end + end + + shared_examples 'an email that contains a header with author username' do + it 'has X-GitLab-Author header containing author\'s username' do + is_expected.to have_header 'X-GitLab-Author', user.username + end + end + shared_examples 'an email starting a new thread' do |message_id_prefix| + include_examples 'an email with X-GitLab headers containing project details' + it 'has a discussion identifier' do is_expected.to have_header 'Message-ID', /<#{message_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ - is_expected.to have_header 'X-GitLab-Project', /#{project.name}/ end end shared_examples 'an answer to an existing thread' do |thread_id_prefix| + include_examples 'an email with X-GitLab headers containing project details' + it 'has a subject that begins with Re: ' do is_expected.to have_subject /^Re: / end @@ -56,7 +80,6 @@ describe Notify do is_expected.to have_header 'Message-ID', /<(.*)@#{Gitlab.config.gitlab.host}>/ is_expected.to have_header 'References', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ is_expected.to have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ - is_expected.to have_header 'X-GitLab-Project', /#{project.name}/ end end @@ -656,6 +679,8 @@ describe Notify do it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'an email with X-GitLab headers containing project details' + it_behaves_like 'an email that contains a header with author username' it 'is sent as the author' do sender = subject.header[:from].addrs[0] @@ -685,6 +710,8 @@ describe Notify do it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'an email with X-GitLab headers containing project details' + it_behaves_like 'an email that contains a header with author username' it 'is sent as the author' do sender = subject.header[:from].addrs[0] @@ -713,6 +740,8 @@ describe Notify do it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'an email with X-GitLab headers containing project details' + it_behaves_like 'an email that contains a header with author username' it 'is sent as the author' do sender = subject.header[:from].addrs[0] @@ -737,6 +766,8 @@ describe Notify do it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'an email with X-GitLab headers containing project details' + it_behaves_like 'an email that contains a header with author username' it 'is sent as the author' do sender = subject.header[:from].addrs[0] @@ -765,6 +796,8 @@ describe Notify do it_behaves_like 'it should not have Gmail Actions links' it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'an email with X-GitLab headers containing project details' + it_behaves_like 'an email that contains a header with author username' it 'is sent as the author' do sender = subject.header[:from].addrs[0] @@ -871,6 +904,8 @@ describe Notify do it_behaves_like 'it should show Gmail Actions View Commit link' it_behaves_like "a user cannot unsubscribe through footer link" + it_behaves_like 'an email with X-GitLab headers containing project details' + it_behaves_like 'an email that contains a header with author username' it 'is sent as the author' do sender = subject.header[:from].addrs[0] @@ -904,6 +939,15 @@ describe Notify do subject { Notify.build_success_email(build.id, 'wow@example.com') } + it_behaves_like 'an email with X-GitLab headers containing build details' + it_behaves_like 'an email with X-GitLab headers containing project details' do + let(:project) { build.project } + end + + it 'has header indicating build status' do + is_expected.to have_header 'X-GitLab-Build-Status', 'success' + end + it 'has the correct subject' do should have_subject /Build success for/ end @@ -918,6 +962,15 @@ describe Notify do subject { Notify.build_fail_email(build.id, 'wow@example.com') } + it_behaves_like 'an email with X-GitLab headers containing build details' + it_behaves_like 'an email with X-GitLab headers containing project details' do + let(:project) { build.project } + end + + it 'has header indicating build status' do + is_expected.to have_header 'X-GitLab-Build-Status', 'failed' + end + it 'has the correct subject' do should have_subject /Build failed for/ end -- cgit v1.2.1 From 34564296d00408ec585bb78370cf8710a22ffdf4 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 19 Jan 2016 14:25:27 -0500 Subject: Adds `t` as a shortcut for find file anywhere --- app/assets/javascripts/dispatcher.js.coffee | 1 - app/assets/javascripts/shortcuts.js.coffee | 1 + app/assets/javascripts/shortcuts_tree.coffee | 4 ---- app/views/layouts/header/_default.html.haml | 3 +++ 4 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 app/assets/javascripts/shortcuts_tree.coffee diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 58d6b9d4060..0d88e8d254a 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -87,7 +87,6 @@ class Dispatcher new GroupAvatar() when 'projects:tree:show' new TreeView() - shortcut_handler = new ShortcutsTree() when 'projects:find_file:show' shortcut_handler = true when 'projects:blob:show' diff --git a/app/assets/javascripts/shortcuts.js.coffee b/app/assets/javascripts/shortcuts.js.coffee index 4d915bfc8c5..f141fb69c3e 100644 --- a/app/assets/javascripts/shortcuts.js.coffee +++ b/app/assets/javascripts/shortcuts.js.coffee @@ -4,6 +4,7 @@ class @Shortcuts Mousetrap.reset() Mousetrap.bind('?', @selectiveHelp) Mousetrap.bind('s', Shortcuts.focusSearch) + Mousetrap.bind('t', -> Turbolinks.visit(findFileURL)) if findFileURL? selectiveHelp: (e) => Shortcuts.showHelp(e, @enabledHelp) diff --git a/app/assets/javascripts/shortcuts_tree.coffee b/app/assets/javascripts/shortcuts_tree.coffee deleted file mode 100644 index ba0839c9fc0..00000000000 --- a/app/assets/javascripts/shortcuts_tree.coffee +++ /dev/null @@ -1,4 +0,0 @@ -class @ShortcutsTree extends ShortcutsNavigation - constructor: -> - super() - Mousetrap.bind('t', -> ShortcutsTree.findAndFollowLink('.shortcuts-find-file')) diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 3892ef8eefa..a938a0c70b9 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -37,3 +37,6 @@ %h1.title= title = render 'shared/outdated_browser' +-if defined?(@project) + :javascript + var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @ref)}'; \ No newline at end of file -- cgit v1.2.1 From ecbb8d73eb5fc9e3b388a2803c2bd7129c111b98 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 19 Jan 2016 14:37:00 -0500 Subject: Add reference to the correct branch. sometimes `@ref` will be `nil`. this makes sure that the correct branch is passed in. --- app/views/layouts/header/_default.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index a938a0c70b9..ec1bdf69095 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -39,4 +39,4 @@ = render 'shared/outdated_browser' -if defined?(@project) :javascript - var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @ref)}'; \ No newline at end of file + var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}'; \ No newline at end of file -- cgit v1.2.1 From 60dbc4f68774049f809017a56914f465bfe026fe Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 19 Jan 2016 14:38:45 -0500 Subject: Removes `defined?` in favor to just `if` --- app/views/layouts/header/_default.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index ec1bdf69095..b62a19d43ba 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -37,6 +37,6 @@ %h1.title= title = render 'shared/outdated_browser' --if defined?(@project) +-if @project :javascript var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}'; \ No newline at end of file -- cgit v1.2.1 From 35a776754c45b75f48c9cd08e291de35b79d1e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 19 Jan 2016 15:02:26 -0500 Subject: Update Issue/MR everytime a Note is saved/destroyed. --- app/models/note.rb | 2 +- app/services/notes/create_service.rb | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/models/note.rb b/app/models/note.rb index 3e1375e5ad6..15f48110ad2 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -33,7 +33,7 @@ class Note < ActiveRecord::Base participant :author belongs_to :project - belongs_to :noteable, polymorphic: true + belongs_to :noteable, polymorphic: true, touch: true belongs_to :author, class_name: "User" belongs_to :updated_by, class_name: "User" diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb index b39ebac1092..a8486e6a5a1 100644 --- a/app/services/notes/create_service.rb +++ b/app/services/notes/create_service.rb @@ -10,10 +10,7 @@ module Notes # Skip system notes, like status changes and cross-references and awards unless note.system || note.is_award - event = event_service.leave_note(note, note.author) - noteable = note.noteable - - noteable.touch if event.commented? && noteable.respond_to?(:touch) + event_service.leave_note(note, note.author) note.create_cross_references! execute_hooks(note) end -- cgit v1.2.1 From 4784695860dea75864c801c6223fb348c5ac7cd3 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 19 Jan 2016 15:04:12 -0500 Subject: Proper spacing in HAML file `if` statement. --- app/views/layouts/header/_default.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index b62a19d43ba..10f80fae3c8 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -37,6 +37,6 @@ %h1.title= title = render 'shared/outdated_browser' --if @project +- if @project :javascript var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}'; \ No newline at end of file -- cgit v1.2.1 From e5cbd5885a5cf72f406a6a4cb471b59a87865d20 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 19 Jan 2016 15:43:04 -0500 Subject: Fixes issue where other emoji (not thumbup/thumbdown) were not removed --- app/assets/javascripts/awards_handler.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 7136ef3258b..1ef31c7700e 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -44,7 +44,7 @@ class @AwardsHandler decrementCounter: (emoji) -> counter = @findEmojiIcon(emoji).siblings(".counter") emojiIcon = counter.parent() - if parseInt(counter.text()) > 0 + if parseInt(counter.text()) > 1 counter.text(parseInt(counter.text()) - 1) emojiIcon.removeClass("active") @removeMeFromAuthorList(emoji) -- cgit v1.2.1 From d4c05766c7a058cbf62186723216d754eebad92e Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 19 Jan 2016 22:18:51 +0100 Subject: Refactor GitLab Metrics docs [ci skip] --- doc/README.md | 8 +- doc/integration/README.md | 1 + doc/integration/metrics/gitlab_configuration.md | 39 +++++ .../img/metrics_gitlab_configuration_settings.png | Bin 0 -> 45148 bytes doc/integration/metrics/influxdb_configuration.md | 192 +++++++++++++++++++++ doc/integration/metrics/influxdb_schema.md | 87 ++++++++++ doc/integration/metrics/introduction.md | 64 +++++++ doc/metrics/gitlab_configuration.md | 12 -- doc/metrics/influxdb_configuration.md | 96 ----------- doc/metrics/influxdb_schema.md | 75 -------- doc/metrics/introduction.md | 55 ------ 11 files changed, 384 insertions(+), 245 deletions(-) create mode 100644 doc/integration/metrics/gitlab_configuration.md create mode 100644 doc/integration/metrics/img/metrics_gitlab_configuration_settings.png create mode 100644 doc/integration/metrics/influxdb_configuration.md create mode 100644 doc/integration/metrics/influxdb_schema.md create mode 100644 doc/integration/metrics/introduction.md delete mode 100644 doc/metrics/gitlab_configuration.md delete mode 100644 doc/metrics/influxdb_configuration.md delete mode 100644 doc/metrics/influxdb_schema.md delete mode 100644 doc/metrics/introduction.md diff --git a/doc/README.md b/doc/README.md index b9ee7de5349..bee9ab05906 100644 --- a/doc/README.md +++ b/doc/README.md @@ -49,13 +49,6 @@ - [Test Clojure applications](ci/examples/test-clojure-application.md) - Help your favorite programming language and GitLab by sending a merge request with a guide for that language. -## GitLab Metrics - -- [Introduction](metrics/introduction.md) -- [GitLab Configuration](metrics/gitlab_configuration.md) -- [InfluxDB Configuration](metrics/influxdb_configuration.md) -- [InfluxDB Schema](metrics/influxdb_schema.md) - ## Administrator documentation - [Custom git hooks](hooks/custom_hooks.md) Custom git hooks (on the filesystem) for when web hooks aren't enough. @@ -74,6 +67,7 @@ - [Reply by email](incoming_email/README.md) Allow users to comment on issues and merge requests by replying to notification emails. - [Migrate GitLab CI to CE/EE](migrate_ci_to_ce/README.md) Follow this guide to migrate your existing GitLab CI data to GitLab CE/EE. - [Git LFS configuration](workflow/lfs/lfs_administration.md) +- [GitLab Metrics](integration/metrics/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics ## Contributor documentation diff --git a/doc/integration/README.md b/doc/integration/README.md index 5edac746c7b..5ba0d0fb245 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -15,6 +15,7 @@ See the documentation below for details on how to configure these services. - [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages - [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users +- [GitLab Metrics](metrics/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics GitLab Enterprise Edition contains [advanced Jenkins support][jenkins]. diff --git a/doc/integration/metrics/gitlab_configuration.md b/doc/integration/metrics/gitlab_configuration.md new file mode 100644 index 00000000000..019db1ad02c --- /dev/null +++ b/doc/integration/metrics/gitlab_configuration.md @@ -0,0 +1,39 @@ +# GitLab Configuration + +GitLab Metrics is disabled by default. To enable it and change any of its +settings, navigate to the Admin area in **Settings > Metrics** +(`/admin/application_settings`). + +The minimum required settings you need to set are the InfluxDB host and port. +Make sure _Enable InfluxDB Metrics_ is checked and hit **Save** to save the +changes. + +--- + +![GitLab Metrics Admin Settings](img/metrics_gitlab_configuration_settings.png) + +--- + +Finally, a restart of all GitLab processes is required for the changes to take +effect: + +```bash +# For Omnibus installations +sudo gitlab-ctl restart + +# For installations from source +sudo service gitlab restart +``` + +## Pending Migrations + +When any migrations are pending, the metrics are disabled until the migrations +have been performed. + +--- + +Read more on: + +- [Introduction to GitLab Metrics](introduction.md) +- [InfluxDB Configuration](influxdb_configuration.md) +- [InfluxDB Schema](influxdb_schema.md) diff --git a/doc/integration/metrics/img/metrics_gitlab_configuration_settings.png b/doc/integration/metrics/img/metrics_gitlab_configuration_settings.png new file mode 100644 index 00000000000..14d82b6ac98 Binary files /dev/null and b/doc/integration/metrics/img/metrics_gitlab_configuration_settings.png differ diff --git a/doc/integration/metrics/influxdb_configuration.md b/doc/integration/metrics/influxdb_configuration.md new file mode 100644 index 00000000000..13227f1e889 --- /dev/null +++ b/doc/integration/metrics/influxdb_configuration.md @@ -0,0 +1,192 @@ +# InfluxDB Configuration + +The default settings provided by [InfluxDB] are not sufficient for a high traffic +GitLab environment. The settings discussed in this document are based on the +settings GitLab uses for GitLab.com, depending on your own needs you may need to +further adjust them. + +If you are intending to run InfluxDB on the same server as GitLab, make sure +you have plenty of RAM since InfluxDB can use quite a bit depending on traffic. + +Unless you are going with a budget setup, it's advised to run it separately. + +## Requirements + +- InfluxDB 0.9.5 or newer +- A fairly modern version of Linux +- At least 4GB of RAM +- At least 10GB of storage for InfluxDB data + +Note that the RAM and storage requirements can differ greatly depending on the +amount of data received/stored. To limit the amount of stored data users can +look into [InfluxDB Retention Policies][influxdb-retention]. + +## Installation + +Installing InfluxDB is out of the scope of this document. Please refer to the +[InfluxDB documentation]. + +## InfluxDB Server Settings + +Since InfluxDB has many settings that users may wish to customize themselves +(e.g. what port to run InfluxDB on), we'll only cover the essentials. + +The configuration file in question is usually located at +`/etc/influxdb/influxdb.conf`. Whenever you make a change in this file, +InfluxDB needs to be restarted. + +### Storage Engine + +InfluxDB comes with different storage engines and as of InfluxDB 0.9.5 a new +storage engine is available, called [TSM Tree]. All users **must** use the new +`tsm1` storage engine as this [will be the default engine][tsm1-commit] in +upcoming InfluxDB releases. + +Make sure you have the following in your configuration file: + +``` +[data] + dir = "/var/lib/influxdb/data" + engine = "tsm1" +``` + +### Admin Panel + +Production environments should have the InfluxDB admin panel **disabled**. This +feature can be disabled by adding the following to your InfluxDB configuration +file: + +``` +[admin] + enabled = false +``` + +### HTTP + +HTTP is required when using the [InfluxDB CLI] or other tools such as Grafana, +thus it should be enabled. When enabling make sure to _also_ enable +authentication: + +``` +[http] + enabled = true + auth-enabled = true +``` + +_**Note:** Before you enable authentication, you might want to [create an +admin user](#create-a-new-admin-user)._ + +### UDP + +GitLab writes data to InfluxDB via UDP and thus this must be enabled. Enabling +UDP can be done using the following settings: + +``` +[[udp]] + enabled = true + bind-address = ":8089" + database = "gitlab" + batch-size = 1000 + batch-pending = 5 + batch-timeout = "1s" + read-buffer = 209715200 +``` + +This does the following: + +1. Enable UDP and bind it to port 8089 for all addresses. +2. Store any data received in the "gitlab" database. +3. Define a batch of points to be 1000 points in size and allow a maximum of + 5 batches _or_ flush them automatically after 1 second. +4. Define a UDP read buffer size of 200 MB. + +One of the most important settings here is the UDP read buffer size as if this +value is set too low, packets will be dropped. You must also make sure the OS +buffer size is set to the same value, the default value is almost never enough. + +To set the OS buffer size to 200 MB, on Linux you can run the following command: + +```bash +sysctl -w net.core.rmem_max=209715200 +``` + +To make this permanent, add the following to `/etc/sysctl.conf` and restart the +server: + +```bash +net.core.rmem_max=209715200 +``` + +It is **very important** to make sure the buffer sizes are large enough to +handle all data sent to InfluxDB as otherwise you _will_ lose data. The above +buffer sizes are based on the traffic for GitLab.com. Depending on the amount of +traffic, users may be able to use a smaller buffer size, but we highly recommend +using _at least_ 100 MB. + +When enabling UDP, users should take care to not expose the port to the public, +as doing so will allow anybody to write data into your InfluxDB database (as +[InfluxDB's UDP protocol][udp] doesn't support authentication). We recommend either +whitelisting the allowed IP addresses/ranges, or setting up a VLAN and only +allowing traffic from members of said VLAN. + +## Create a new admin user + +If you want to [enable authentication](#http), you might want to [create an +admin user][influx-admin]: + +``` +influx -execute "CREATE USER thedude WITH PASSWORD '1234' WITH ALL PRIVILEGES" +``` + +## Create the `gitlab` database + +Once you get InfluxDB up and running, you need to create a database for GitLab. +Make sure you have changed the [storage engine](#storage-engine) to `tsm1` +before creating a database. + +_**Note:** If you [created an admin user](#create-a-new-admin-user) and enabled +[HTTP authentication](#http), remember to append the username (`-username thedude`) +and password (`-password 1234`) to the commands below._ + +Run the following command to create a database named `gitlab`: + +```bash +influx -execute 'CREATE DATABASE gitlab' +``` + +The name **must** be `gitlab`, do not use any other name. + +Next, make sure that the database was successfully created: + +```bash +influx -execute 'SHOW DATABASES' +``` + +The output should be similar to: + +``` +name: databases +--------------- +name +_internal +gitlab +``` + +That's it! Now your GitLab instance should send data to InfluxDB. + +--- + +Read more on: + +- [Introduction to GitLab Metrics](introduction.md) +- [GitLab Configuration](gitlab_configuration.md) +- [InfluxDB Schema](influxdb_schema.md) + +[influxdb-retention]: https://docs.influxdata.com/influxdb/v0.9/query_language/database_management/#retention-policy-management +[influxdb documentation]: https://docs.influxdata.com/influxdb/v0.9/ +[influxdb cli]: https://docs.influxdata.com/influxdb/v0.9/tools/shell/ +[udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/ +[influxdb]: https://influxdata.com/time-series-platform/influxdb/ +[tsm tree]: https://influxdata.com/blog/new-storage-engine-time-structured-merge-tree/ +[tsm1-commit]: https://github.com/influxdata/influxdb/commit/15d723dc77651bac83e09e2b1c94be480966cb0d +[influx-admin]: https://docs.influxdata.com/influxdb/v0.9/administration/authentication_and_authorization/#create-a-new-admin-user diff --git a/doc/integration/metrics/influxdb_schema.md b/doc/integration/metrics/influxdb_schema.md new file mode 100644 index 00000000000..a9ef0b446c8 --- /dev/null +++ b/doc/integration/metrics/influxdb_schema.md @@ -0,0 +1,87 @@ +# InfluxDB Schema + +The following measurements are currently stored in InfluxDB: + +- `PROCESS_file_descriptors` +- `PROCESS_gc_statistics` +- `PROCESS_memory_usage` +- `PROCESS_method_calls` +- `PROCESS_object_counts` +- `PROCESS_transactions` +- `PROCESS_views` + +Here, `PROCESS` is replaced with either `rails` or `sidekiq` depending on the +process type. In all series, any form of duration is stored in milliseconds. + +## PROCESS_file_descriptors + +This measurement contains the number of open file descriptors over time. The +value field `value` contains the number of descriptors. + +## PROCESS_gc_statistics + +This measurement contains Ruby garbage collection statistics such as the amount +of minor/major GC runs (relative to the last sampling interval), the time spent +in garbage collection cycles, and all fields/values returned by `GC.stat`. + +## PROCESS_memory_usage + +This measurement contains the process' memory usage (in bytes) over time. The +value field `value` contains the number of bytes. + +## PROCESS_method_calls + +This measurement contains the methods called during a transaction along with +their duration, and a name of the transaction action that invoked the method (if +available). The method call duration is stored in the value field `duration`, +while the method name is stored in the tag `method`. The tag `action` contains +the full name of the transaction action. Both the `method` and `action` fields +are in the following format: + +``` +ClassName#method_name +``` + +For example, a method called by the `show` method in the `UsersController` class +would have `action` set to `UsersController#show`. + +## PROCESS_object_counts + +This measurement is used to store retained Ruby objects (per class) and the +amount of retained objects. The number of objects is stored in the `count` value +field while the class name is stored in the `type` tag. + +## PROCESS_transactions + +This measurement is used to store basic transaction details such as the time it +took to complete a transaction, how much time was spent in SQL queries, etc. The +following value fields are available: + +| Value | Description | +| ----- | ----------- | +| `duration` | The total duration of the transaction | +| `allocated_memory` | The amount of bytes allocated while the transaction was running. This value is only reliable when using single-threaded application servers | +| `method_duration` | The total time spent in method calls | +| `sql_duration` | The total time spent in SQL queries | +| `view_duration` | The total time spent in views | + +## PROCESS_views + +This measurement is used to store view rendering timings for a transaction. The +following value fields are available: + +| Value | Description | +| ----- | ----------- | +| `duration` | The rendering time of the view | +| `view` | The path of the view, relative to the application's root directory | + +The `action` tag contains the action name of the transaction that rendered the +view. + +--- + +Read more on: + +- [Introduction to GitLab Metrics](introduction.md) +- [GitLab Configuration](gitlab_configuration.md) +- [InfluxDB Configuration](influxdb_configuration.md) diff --git a/doc/integration/metrics/introduction.md b/doc/integration/metrics/introduction.md new file mode 100644 index 00000000000..bf388aa2bba --- /dev/null +++ b/doc/integration/metrics/introduction.md @@ -0,0 +1,64 @@ +# GitLab Metrics + +GitLab comes with its own application performance measuring system as of GitLab +8.4, simply called "GitLab Metrics". GitLab Metrics is available in both the +Community and Enterprise editions. + +Apart from this introduction, you are advised to read through the following +documents in order to understand and properly configure GitLab Metrics: + +- [GitLab Configuration](gitlab_configuration.md) +- [InfluxDB Configuration](influxdb_configuration.md) +- [InfluxDB Schema](influxdb_schema.md) + +## Introduction to GitLab Metrics + +GitLab Metrics makes it possible to measure a wide variety of statistics +including (but not limited to): + +- The time it took to complete a transaction (a web request or Sidekiq job). +- The time spent in running SQL queries and rendering HAML views. +- The time spent executing (instrumented) Ruby methods. +- Ruby object allocations, and retained objects in particular. +- System statistics such as the process' memory usage and open file descriptors. +- Ruby garbage collection statistics. + +Metrics data is written to [InfluxDB][influxdb] over [UDP][influxdb-udp]. Stored +data can be visualized using [Grafana][grafana] or any other application that +supports reading data from InfluxDB. Alternatively data can be queried using the +InfluxDB CLI. + +## Metric Types + +Two types of metrics are collected: + +1. Transaction specific metrics. +1. Sampled metrics, collected at a certain interval in a separate thread. + +### Transaction Metrics + +Transaction metrics are metrics that can be associated with a single +transaction. This includes statistics such as the transaction duration, timings +of any executed SQL queries, time spent rendering HAML views, etc. These metrics +are collected for every Rack request and Sidekiq job processed. + +### Sampled Metrics + +Sampled metrics are metrics that can't be associated with a single transaction. +Examples include garbage collection statistics and retained Ruby objects. These +metrics are collected at a regular interval. This interval is made up out of two +parts: + +1. A user defined interval. +1. A randomly generated offset added on top of the interval, the same offset + can't be used twice in a row. + +The actual interval can be anywhere between a half of the defined interval and a +half above the interval. For example, for a user defined interval of 15 seconds +the actual interval can be anywhere between 7.5 and 22.5. The interval is +re-generated for every sampling run instead of being generated once and re-used +for the duration of the process' lifetime. + +[influxdb]: https://influxdata.com/time-series-platform/influxdb/ +[influxdb-udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/ +[grafana]: http://grafana.org/ diff --git a/doc/metrics/gitlab_configuration.md b/doc/metrics/gitlab_configuration.md deleted file mode 100644 index 3b44b4394ff..00000000000 --- a/doc/metrics/gitlab_configuration.md +++ /dev/null @@ -1,12 +0,0 @@ -# GitLab Configuration - -By default GitLab Metrics is disabled. To enable GitLab Metrics and change any -of its settings open a web browser and navigate to -`http://YOUR_GITLAB_HOST/admin/application_settings`, the settings can be found -in the "Metrics" section. A restart of all GitLab processes is required for any -changes to take effect. - -## Pending Migrations - -When any migrations are pending the metrics are disabled until the migrations -have been performed. diff --git a/doc/metrics/influxdb_configuration.md b/doc/metrics/influxdb_configuration.md deleted file mode 100644 index c67c0f15108..00000000000 --- a/doc/metrics/influxdb_configuration.md +++ /dev/null @@ -1,96 +0,0 @@ -# InfluxDB Configuration - -The default settings provided by InfluxDB are not sufficient for a high traffic -GitLab environment. The settings discussed in this document are based on the -settings GitLab uses for GitLab.com, depending on your own needs you may need to -further adjust them. - -## Requirements - -* InfluxDB 0.9 or newer -* A fairly modern version of Linux -* At least 4GB of RAM -* At least 10GB of storage for InfluxDB data - -Note that the RAM and storage requirements can differ greatly depending on the -amount of data received/stored. To limit the amount of stored data users can -look into [InfluxDB Retention Policies][influxdb-retention]. - -## InfluxDB Server Settings - -Since InfluxDB has many settings that users may wish to customize themselves -(e.g. what port to run InfluxDB on) we'll only cover the essentials. - -### Storage Engine - -InfluxDB comes with different storage engines and as of InfluxDB 0.9 a new -storage engine is available called "tsm1". All users _must_ use the new tsm1 -storage engine (this will be the default engine in upcoming InfluxDB engines). - -### Admin Panel - -Production environments should have the InfluxDB admin panel _disabled_. This -feature can be disabled by adding the following to your InfluxDB configuration -file: - - [admin] - enabled = false - -### HTTP - -HTTP is required when using the InfluxDB CLI or other tools such as Grafana, -thus it should be enabled. When enabling make sure to _also_ enable -authentication: - - [http] - enabled = true - auth-enabled = true - -### UDP - -GitLab writes data to InfluxDB via UDP and thus this must be enabled. Enabling -UDP can be done using the following settings: - - [udp] - enabled = true - bind-address = ":8089" - database = "gitlab" - batch-size = 1000 - batch-pending = 5 - batch-timeout = 1s - read-buffer = 209715200 - -This does the following: - -1. Enable UDP and bind it to port 8089 for all addresses. -2. Store any data received in the "gitlab" database. -3. Define a batch of points to be 1000 points in size and allow a maximum of - 5 batches _or_ flush them automatically after 1 second. -4. Define a UDP read buffer size of 200 MB. - -One of the most important settings here is the UDP read buffer size as if this -value is set too low packets will be dropped. You must also make sure the OS -buffer size is set to the same value, the default value is almost never enough. - -To set the OS buffer size to 200 MB on Linux you can run the following command: - - sysctl -w net.core.rmem_max=209715200 - -To make this permanent, add the following to `/etc/sysctl.conf` and restart the -server: - - net.core.rmem_max=209715200 - -It is **very important** to make sure the buffer sizes are large enough to -handle all data sent to InfluxDB as otherwise you _will_ lose data. The above -buffer sizes are based on the traffic for GitLab.com. Depending on the amount of -traffic users may be able to use a smaller buffer size, but we highly recommend -using _at least_ 100 MB. - -When enabling UDP users should take care to not expose the port to the public as -doing so will allow anybody to write data into your InfluxDB database (as -InfluxDB's UDP protocol doesn't support authentication). We recommend either -whitelisting the allowed IP addresses/ranges, or setting up a VLAN and only -allowing traffic from members of said VLAN. - -[influxdb-retention]: https://docs.influxdata.com/influxdb/v0.9/query_language/database_management/#retention-policy-management diff --git a/doc/metrics/influxdb_schema.md b/doc/metrics/influxdb_schema.md deleted file mode 100644 index a8e69b5e173..00000000000 --- a/doc/metrics/influxdb_schema.md +++ /dev/null @@ -1,75 +0,0 @@ -# InfluxDB Schema - -The following measurements are currently stored in InfluxDB: - -* `PROCESS_file_descriptors` -* `PROCESS_gc_statistics` -* `PROCESS_memory_usage` -* `PROCESS_method_calls` -* `PROCESS_object_counts` -* `PROCESS_transactions` -* `PROCESS_views` - -Here `PROCESS` is replaced with either "rails" or "sidekiq" depending on the -process type. In all series any form of duration is stored in milliseconds. - -## PROCESS_file_descriptors - -This measurement contains the number of open file descriptors over time. The -value field `value` contains the number of descriptors. - -## PROCESS_gc_statistics - -This measurement contains Ruby garbage collection statistics such as the amount -of minor/major GC runs (relative to the last sampling interval), the time spent -in garbage collection cycles, and all fields/values returned by `GC.stat`. - -## PROCESS_memory_usage - -This measurement contains the process' memory usage (in bytes) over time. The -value field `value` contains the number of bytes. - -## PROCESS_method_calls - -This measurement contains the methods called during a transaction along with -their durations and a name of the transaction action that invoked the method (if -available). The method call duration is stored in the value field `duration` -while the method name is stored in the tag `method`. The tag `action` contains -the full name of the transaction action. Both the `method` and `action` fields -are in the following format: - - ClassName#method_name - -For example, a method called by the `show` method in the `UsersController` class -would have `action` set to `UsersController#show`. - -## PROCESS_object_counts - -This measurement is used to store retained Ruby objects (per class) and the -amount of retained objects. The number of objects is stored in the `count` value -field while the class name is stored in the `type` tag. - -## PROCESS_transactions - -This measurement is used to store basic transaction details such as the time it -took to complete a transaction, how much time was spent in SQL queries, etc. The -following value fields are available: - -* `duration`: the total duration of the transaction. -* `allocated_memory`: the amount of bytes allocated while the transaction was - running. This value is only reliable when using single-threaded application - servers. -* `method_duration`: the total time spent in method calls. -* `sql_duration`: the total time spent in SQL queries. -* `view_duration`: the total time spent in views. - -## PROCESS_views - -This measurement is used to store view rendering timings for a transaction. The -following value fields are available: - -* `duration`: the rendering time of the view. -* `view`: the path of the view, relative to the application's root directory. - -The `action` tag contains the action name of the transaction that rendered the -view. diff --git a/doc/metrics/introduction.md b/doc/metrics/introduction.md deleted file mode 100644 index 007fff9e7b4..00000000000 --- a/doc/metrics/introduction.md +++ /dev/null @@ -1,55 +0,0 @@ -# Introduction to GitLab Metrics - -GitLab comes with its own application performance measuring system as of GitLab -8.4, simply called "GitLab Metrics". GitLab Metrics is available in both the -Community and Enterprise editions. - -GitLab Metrics makes it possible to measure a wide variety of statistics -including (but not limited to): - -* The time it took to complete a transaction (a web request or Sidekiq job). -* The time spent in running SQL queries and rendering HAML views. -* The time spent executing (instrumented) Ruby methods. -* Ruby object allocations, and retained objects in particular. -* System statistics such as the process' memory usage and open file descriptors. -* Ruby garbage collection statistics. - -Metrics data is written to [InfluxDB][influxdb] over [UDP](influxdb-udp). Stored -data can be visualized using [Grafana][grafana] or any other application that -supports reading data from InfluxDB. Alternatively data can be queried using the -InfluxDB CLI. - -## Metric Types - -Two types of metrics are collected: - -1. Transaction specific metrics. -2. Sampled metrics, collected at a certain interval in a separate thread. - -### Transaction Metrics - -Transaction metrics are metrics that can be associated with a single -transaction. This includes statistics such as the transaction duration, timings -of any executed SQL queries, time spent rendering HAML views, etc. These metrics -are collected for every Rack request and Sidekiq job processed. - -### Sampled Metrics - -Sampled metrics are metrics that can't be associated with a single transaction. -Examples include garbage collection statistics and retained Ruby objects. These -metrics are collected at a regular interval. This interval is made up out of two -parts: - -1. A user defined interval. -2. A randomly generated offset added on top of the interval, the same offset - can't be used twice in a row. - -The actual interval can be anywhere between a half of the defined interval and a -half above the interval. For example, for a user defined interval of 15 seconds -the actual interval can be anywhere between 7.5 and 22.5. The interval is -re-generated for every sampling run instead of being generated once and re-used -for the duration of the process' lifetime. - -[influxdb]: https://influxdata.com/time-series-platform/influxdb/ -[influxdb-udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/ -[grafana]: http://grafana.org/ -- cgit v1.2.1 From a382ad99efd4c792f70705d386b2be688b667f24 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 19 Jan 2016 16:45:11 -0500 Subject: Update CHANGELOG - Add attribution for Anton Baklanov - Remove attributions for employees [ci skip] --- CHANGELOG | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ca759a263b8..2e0eee52a59 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,9 +10,9 @@ v 8.4.0 (unreleased) - Add pagination headers to already paginated API resources - Properly generate diff of orphan commits, like the first commit in a repository - Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages - - Autocomplete data is now always loaded, instead of when focusing a comment text area (Yorick Peterse) - - Improved performance of finding issues for an entire group (Yorick Peterse) - - Added custom application performance measuring system powered by InfluxDB (Yorick Peterse) + - Autocomplete data is now always loaded, instead of when focusing a comment text area + - Improved performance of finding issues for an entire group + - Added custom application performance measuring system powered by InfluxDB - Bump fog to 1.36.0 (Stan Hu) - Add user's last used IP addresses to admin page (Stan Hu) - Add housekeeping function to project settings page @@ -63,14 +63,14 @@ v 8.4.0 (unreleased) - Autosize Markdown textareas - Import GitHub wiki into GitLab - Add reporters ability to download and browse build artifacts (Andrew Johnson) - - Autofill referring url in message box when reporting user abuse. (Josh Frye) + - Autofill referring url in message box when reporting user abuse. - Remove leading comma on award emoji when the user is the first to award the emoji (Zeger-Jan van de Weg) - Add build artifacts browser - Improve UX in builds artifacts browser - Increase default size of `data` column in `events` table when using MySQL - Expose button to CI Lint tool on project builds page - Fix: Creator should be added as a master of the project on creation - - Added X-GitLab-... headers to emails from CI and Email On Push services + - Added X-GitLab-... headers to emails from CI and Email On Push services (Anton Baklanov) v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) -- cgit v1.2.1 From c26816f7a732b339b14d7d6d928f5a86f490d77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Tue, 19 Jan 2016 17:35:43 -0500 Subject: Fix broken specs. --- spec/lib/gitlab/note_data_builder_spec.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb index 6cbdae737f4..691f36e6cb7 100644 --- a/spec/lib/gitlab/note_data_builder_spec.rb +++ b/spec/lib/gitlab/note_data_builder_spec.rb @@ -37,7 +37,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do it 'returns the note and issue-specific data' do expect(data).to have_key(:issue) - expect(data[:issue]).to eq(issue.hook_attrs) + expect(data[:issue].except('updated_at')).to eq(issue.hook_attrs.except('updated_at')) + expect(data[:issue]['updated_at']).to be > issue.hook_attrs['updated_at'] end end @@ -47,7 +48,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do it 'returns the note and merge request data' do expect(data).to have_key(:merge_request) - expect(data[:merge_request]).to eq(merge_request.hook_attrs) + expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at')) + expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at'] end end @@ -57,7 +59,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do it 'returns the note and merge request diff data' do expect(data).to have_key(:merge_request) - expect(data[:merge_request]).to eq(merge_request.hook_attrs) + expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at')) + expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at'] end end @@ -67,7 +70,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do it 'returns the note and project snippet data' do expect(data).to have_key(:snippet) - expect(data[:snippet]).to eq(snippet.hook_attrs) + expect(data[:snippet].except('updated_at')).to eq(snippet.hook_attrs.except('updated_at')) + expect(data[:snippet]['updated_at']).to be > snippet.hook_attrs['updated_at'] end end end -- cgit v1.2.1 From 70e59035c0803bbed29d69fe1c535a15f0249f53 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Tue, 19 Jan 2016 21:39:48 -0500 Subject: Fix project find url so branch ref is not nil Also adds autocomplete="off" to find input. --- app/views/layouts/header/_default.html.haml | 8 ++++++-- app/views/projects/find_file/show.html.haml | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 10f80fae3c8..b83b5b1c9b0 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -37,6 +37,10 @@ %h1.title= title = render 'shared/outdated_browser' -- if @project +-if @project && !@project.empty_repo? && @ref :javascript - var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}'; \ No newline at end of file + var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @ref)}'; + +-elsif @project && !@project.empty_repo? + :javascript + var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @project.repository.root_ref)}'; \ No newline at end of file diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml index 40a2a61d8a1..905f6bbbd48 100644 --- a/app/views/projects/find_file/show.html.haml +++ b/app/views/projects/find_file/show.html.haml @@ -10,7 +10,7 @@ = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do = @project.path %li.file-finder - %input#file_find.form-control.file-finder-input{type: "text", placeholder: 'Find by path'} + %input#file_find.form-control.file-finder-input{type: "text", placeholder: 'Find by path', autocomplete: 'off'} %div.tree-content-holder .table-holder -- cgit v1.2.1 From 3278c5b073a1f3e6d48f246525178863959203af Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 20 Jan 2016 00:15:55 -0500 Subject: Adds disabled comment field and disabled avatar. --- app/assets/stylesheets/pages/merge_requests.scss | 36 ++++++++++++++++++++++ .../projects/notes/_notes_with_form.html.haml | 10 ++++++ 2 files changed, 46 insertions(+) diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 75f2ae80a92..6c1272d5d8c 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -201,3 +201,39 @@ .mr-source-target { line-height: 31px; } + +.disabled-comment-area { + padding: 16px 0; + + .disabled-profile { + width: 40px; + height: 40px; + background: #CCC; + border-radius: 20px; + display: inline-block; + margin-right: 10px; + } + + .disabled-comment { + background: #F3F3F3; + display: inline-block; + vertical-align: top; + height: 200px; + border-radius: 4px; + border: 1px solid #CCC; + padding-top: 90px; + text-align: center; + right: 20px; + position: absolute; + left: 70px; + margin-bottom: 20px; + + span { + color: #B2B2B2; + + a { + color: $md-link-color; + } + } + } +} \ No newline at end of file diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index eb378b42603..910eb6cf66e 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -5,6 +5,16 @@ .js-main-target-form - if can? current_user, :create_note, @project = render "projects/notes/form", view: diff_view +- else + .disabled-comment-area + .disabled-profile + .disabled-comment + %span + Please + = link_to "register",new_user_session_path + or + = link_to "login",new_user_session_path + to post a comment :javascript var notes = new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}") -- cgit v1.2.1 From a7f2d75c5d27c0042ca79e8a71b204c2bb6f1375 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 20 Jan 2016 00:27:32 -0500 Subject: Uses color variables instead. --- app/assets/stylesheets/pages/merge_requests.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 6c1272d5d8c..f033ff15f88 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -208,19 +208,19 @@ .disabled-profile { width: 40px; height: 40px; - background: #CCC; + background: $border-gray-dark; border-radius: 20px; display: inline-block; margin-right: 10px; } .disabled-comment { - background: #F3F3F3; + background: $gray-light; display: inline-block; vertical-align: top; height: 200px; border-radius: 4px; - border: 1px solid #CCC; + border: 1px solid $border-gray-normal; padding-top: 90px; text-align: center; right: 20px; -- cgit v1.2.1 From 106939fa2af87f644a4cad618d1f177b37675b5f Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 20 Jan 2016 01:52:01 -0500 Subject: Fixes test to not search whole page for content. --- features/steps/project/merge_requests.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index be993d11093..28f87a9bea0 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -41,7 +41,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end step 'I should not see "master" branch' do - expect(page).not_to have_content "master" + expect(find('.merge-request-info')).not_to have_content "master" end step 'I should see "other_branch" branch' do -- cgit v1.2.1 From f1b4f20c75d0a97c0b1f2efe6366c586a5236094 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 20 Jan 2016 02:09:19 -0500 Subject: Fix HTML so code passes Code was failing because branch was named `'test'` with quotes which was escaping the javascript I was using. --- app/views/layouts/header/_default.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index b83b5b1c9b0..d1425cd0e88 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -39,8 +39,8 @@ = render 'shared/outdated_browser' -if @project && !@project.empty_repo? && @ref :javascript - var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @ref)}'; + var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref)}"; -elsif @project && !@project.empty_repo? :javascript - var findFileURL = '#{namespace_project_find_file_path(@project.namespace, @project, @project.repository.root_ref)}'; \ No newline at end of file + var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @project.repository.root_ref)}"; \ No newline at end of file -- cgit v1.2.1 From 6d09338f8819b9772c56e5e4b509483baca72b78 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 20 Jan 2016 08:50:48 +0100 Subject: Remove `Compressed to` column from build artifacts browser See #10982. --- app/views/projects/artifacts/_tree_directory.html.haml | 1 - app/views/projects/artifacts/_tree_file.html.haml | 2 -- app/views/projects/artifacts/browse.html.haml | 1 - 3 files changed, 4 deletions(-) diff --git a/app/views/projects/artifacts/_tree_directory.html.haml b/app/views/projects/artifacts/_tree_directory.html.haml index e4b7979949c..def493c56f5 100644 --- a/app/views/projects/artifacts/_tree_directory.html.haml +++ b/app/views/projects/artifacts/_tree_directory.html.haml @@ -6,4 +6,3 @@ %span.str-truncated = link_to directory.name, path_to_directory %td - %td diff --git a/app/views/projects/artifacts/_tree_file.html.haml b/app/views/projects/artifacts/_tree_file.html.haml index 3dfc09cc495..36fb4c998c9 100644 --- a/app/views/projects/artifacts/_tree_file.html.haml +++ b/app/views/projects/artifacts/_tree_file.html.haml @@ -7,5 +7,3 @@ = link_to file.name, path_to_file %td = number_to_human_size(file.metadata[:size], precision: 2) - %td - = number_to_human_size(file.metadata[:zipped], precision: 2) diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index b70c776a2b2..d3c969cc035 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -15,7 +15,6 @@ %tr %th Name %th Size - %th Compressed to = render partial: 'tree_directory', collection: @entry.directories(parent: true), as: :directory = render partial: 'tree_file', collection: @entry.files, as: :file -- cgit v1.2.1 From 7a609858f063c1089f3a6ec05f9f87a01efa909a Mon Sep 17 00:00:00 2001 From: Jeroen Nijhof Date: Wed, 20 Jan 2016 09:48:38 +0100 Subject: Use sentry in env production only --- Gemfile | 6 +++--- app/views/admin/application_settings/_form.html.haml | 4 +++- config/initializers/sentry.rb | 20 +++++++++++--------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index e8fa75e0974..1a91e9cc3e8 100644 --- a/Gemfile +++ b/Gemfile @@ -293,6 +293,9 @@ end group :production do gem "gitlab_meta", '7.0' + + # Sentry integration + gem 'sentry-raven' end gem "newrelic_rpm", '~> 3.9.4.245' @@ -314,6 +317,3 @@ gem 'oauth2', '~> 1.0.0' # Soft deletion gem "paranoia", "~> 2.0" - -# Sentry integration -gem 'sentry-raven' diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 35af5cf620a..f5a87933fde 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -242,7 +242,9 @@ = f.label :sentry_enabled do = f.check_box :sentry_enabled Enable Sentry - %span.help-block#sentry_help_block Sentry is an error reporting and logging tool + .help-block + Sentry is an error reporting and logging tool which is currently not shipped with GitLab, get it here: + %a{ href: 'https://getsentry.com', target: 'blank' } https://getsentry.com .form-group = f.label :sentry_dsn, 'Sentry DSN', class: 'control-label col-sm-2' diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb index 3ef46291981..d0630b9fa07 100644 --- a/config/initializers/sentry.rb +++ b/config/initializers/sentry.rb @@ -3,15 +3,17 @@ require 'gitlab/current_settings' include Gitlab::CurrentSettings -# allow it to fail: it may do so when create_from_defaults is executed before migrations are actually done -begin - sentry_enabled = current_application_settings.sentry_enabled -rescue - sentry_enabled = false -end +if Rails.env.production? + # allow it to fail: it may do so when create_from_defaults is executed before migrations are actually done + begin + sentry_enabled = current_application_settings.sentry_enabled + rescue + sentry_enabled = false + end -if sentry_enabled - Raven.configure do |config| - config.dsn = current_application_settings.sentry_dsn + if sentry_enabled + Raven.configure do |config| + config.dsn = current_application_settings.sentry_dsn + end end end -- cgit v1.2.1 From 9d756f3d8be74103fff0c119e2e1e0701ec93d54 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 20 Jan 2016 10:33:59 +0100 Subject: Add document on restarting GitLab [ci skip] --- doc/README.md | 1 + doc/administration/restart_gitlab.md | 138 +++++++++++++++++++++++++++++++++++ doc/development/doc_styleguide.md | 11 +++ 3 files changed, 150 insertions(+) create mode 100644 doc/administration/restart_gitlab.md diff --git a/doc/README.md b/doc/README.md index 7d4f84857e0..f6dbfedafca 100644 --- a/doc/README.md +++ b/doc/README.md @@ -53,6 +53,7 @@ - [Custom git hooks](hooks/custom_hooks.md) Custom git hooks (on the filesystem) for when web hooks aren't enough. - [Install](install/README.md) Requirements, directory structures and installation from source. +- [Restart GitLab](administration/restart_gitlab.md) Learn how to restart GitLab and its components - [Integration](integration/README.md) How to integrate with systems such as JIRA, Redmine, LDAP and Twitter. - [Issue closing](customization/issue_closing.md) Customize how to close an issue from commit messages. - [Libravatar](customization/libravatar.md) Use Libravatar for user avatars. diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md new file mode 100644 index 00000000000..bb4fe9f414e --- /dev/null +++ b/doc/administration/restart_gitlab.md @@ -0,0 +1,138 @@ +# How to restart GitLab + +Depending on how you installed GitLab, there are different methods to restart +its service(s). + +If you want the TL;DR versions, jump to: + +- [Omnibus GitLab restart](#omnibus-gitlab-restart) +- [Omnibus GitLab reconfigure](#omnibus-gitlab-reconfigure) +- [Source installation restart](#installations-from-source) + +## Omnibus installations + +If you have used the [Omnibus packages][omnibus-dl] to install GitLab, then +you should already have `gitlab-ctl` in your `PATH`. To find out, run: + +```bash +which gitlab-ctl +``` + +The output should be: `/usr/bin/gitlab-ctl`. + +`gitlab-ctl` interacts with the Omnibus packages and can be used to restart the +GitLab Rails application (Unicorn) as well as the other components, like: + +- GitLab Workhorse +- Sidekiq +- PostgreSQL (if you are using the bundled one) +- NGINX (if you are using the bundled one) +- Redis (if you are using the bundled one) +- [Mailroom][] +- Logrotate. + +### Omnibus GitLab restart + +When you are asked to _restart GitLab_, you need to run the following command: + +```bash +sudo gitlab-ctl restart +``` + +The output should be similar to this: + +``` +ok: run: gitlab-workhorse: (pid 11291) 1s +ok: run: logrotate: (pid 11299) 0s +ok: run: mailroom: (pid 11306) 0s +ok: run: nginx: (pid 11309) 0s +ok: run: postgresql: (pid 11316) 1s +ok: run: redis: (pid 11325) 0s +ok: run: sidekiq: (pid 11331) 1s +ok: run: unicorn: (pid 11338) 0s +``` + +To restart a component separately, you can append its service name to the +`restart` command. For example, to restart **only** NGINX you would run: + +```bash +sudo gitlab-ctl restart nginx +``` + +To check the status of GitLab services, run: + +```bash +sudo gitlab-ctl status +``` + +Notice that all services say `ok: run`. If you get any weird results, like the +unicorn service not starting, you may need to +[reconfigure GitLab](#omnibus-gitlab-reconfigure) instead. + +### Omnibus GitLab reconfigure + +There may be times where you will be asked to _reconfigure_ GitLab. Remember +that this method applies only for the Omnibus packages. + +Reconfigure Omnibus GitLab with: + +```bash +sudo gitlab-ctl reconfigure +``` + +Reconfiguring GitLab should occur in the event that something in its +configuration (`/etc/gitlab/gitlab.rb`) has changed. + +When you run this command, [Chef], the underlying configuration management +application that powers Omnibus GitLab, will make sure that all directories, +permissions, services, etc., are in place and in the same shape that they were +initially shipped. This is where the _idempotency_ buzz-word you've been reading +here and there fits. + +## Installations from source + +If you have followed the official installation guide to [install GitLab from +source][install], run the following command to restart GitLab: + +``` +sudo service gitlab restart +``` + +The output should be similar to this: + +``` +Shutting down GitLab Unicorn +Shutting down GitLab Sidekiq +Shutting down GitLab Workhorse +Shutting down GitLab MailRoom +... +GitLab is not running. +Starting GitLab Unicorn +Starting GitLab Sidekiq +Starting GitLab Workhorse +Starting GitLab MailRoom +... +The GitLab Unicorn web server with pid 28059 is running. +The GitLab Sidekiq job dispatcher with pid 28176 is running. +The GitLab Workhorse with pid 28122 is running. +The GitLab MailRoom email processor with pid 28114 is running. +GitLab and all its components are up and running. +``` + +This should restart Unicorn, Sidekiq, GitLab Workhorse and [Mailroom][] +(if enabled). The init service file that does all the magic can be found in +[`lib/support/init.d/gitlab`][src-service]. + +--- + +If you are using other init systems, like systemd, you can check the +[GitLab Recipes][gl-recipes] repository for some unofficial services. These are +**not** officially supported so use at your own risk. + + +[omnibus-dl]: https://about.gitlab.com/downloads/ "Download the Omnibus packages" +[install]: ../install/installation.md "Documentation to install GitLab from source" +[mailroom]: ../incoming_email/README.md "Used for replying by email in GitLab issues and merge requests" +[chef]: https://www.chef.io/chef/ "Chef official website" +[src-service]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/support/init.d/gitlab "GitLab init service file" +[gl-recipes]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/init "GitLab Recipes repository" diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md index 0bd32b78201..0539bc2df21 100644 --- a/doc/development/doc_styleguide.md +++ b/doc/development/doc_styleguide.md @@ -103,6 +103,17 @@ Inside the document: `_**Note:** This feature was introduced in GitLab EE 8.3_`. Otherwise, leave this mention out +## References + +- There are many cases that a restart/reconfigure of GitLab is required. To + avoid duplication, link to the special document that can be found in + `doc/administration/restart_gitlab.md`. Usually the text will read like: + + ``` + Save the file and [reconfigure GitLab](../administration/restart_gitlab.md) for the changes to take effect. + ``` + Replace `reconfigure` with `restart` where appropriate. + ## API Here is a list of must-have items. Use them in the exact order that appears -- cgit v1.2.1 From 086cbca6bf9d6fdad862a19b7fe468a315b05803 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 20 Jan 2016 10:44:26 +0100 Subject: Link to restart_gitlab.md and some more fixes [ci skip] --- doc/development/doc_styleguide.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md index 0539bc2df21..caaa4032db2 100644 --- a/doc/development/doc_styleguide.md +++ b/doc/development/doc_styleguide.md @@ -105,13 +105,19 @@ Inside the document: ## References -- There are many cases that a restart/reconfigure of GitLab is required. To +- **GitLab Restart:** + There are many cases that a restart/reconfigure of GitLab is required. To avoid duplication, link to the special document that can be found in - `doc/administration/restart_gitlab.md`. Usually the text will read like: + [`doc/administration/restart_gitlab.md`][doc-restart]. Usually the text will + read like: ``` - Save the file and [reconfigure GitLab](../administration/restart_gitlab.md) for the changes to take effect. + Save the file and [reconfigure GitLab](../administration/restart_gitlab.md) + for the changes to take effect. ``` + If the document you are editing resides in a place other than the GitLab CE/EE + `doc/` directory, instead of the relative link, use the full path: + `http://doc.gitlab.com/ce/administration/restart_gitlab.html`. Replace `reconfigure` with `restart` where appropriate. ## API @@ -240,3 +246,4 @@ curl -X PUT -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" -d "restricted_signup_domai [cURL]: http://curl.haxx.se/ "cURL website" [single spaces]: http://www.slate.com/articles/technology/technology/2011/01/space_invaders.html [gfm]: http://doc.gitlab.com/ce/markdown/markdown.html#newlines "GitLab flavored markdown documentation" +[doc-restart]: ../administration/restart_gitlab.md "GitLab restart documentation" -- cgit v1.2.1 From 36aa3e617001e3b84ed4b5dd9025261cd531344c Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 20 Jan 2016 10:56:41 +0100 Subject: Add basic documentation for build artifacts --- doc/README.md | 1 + doc/ci/README.md | 1 + doc/ci/artifacts/README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 doc/ci/artifacts/README.md diff --git a/doc/README.md b/doc/README.md index 7d4f84857e0..d75c1fbfe79 100644 --- a/doc/README.md +++ b/doc/README.md @@ -30,6 +30,7 @@ - [User permissions](ci/permissions/README.md) - [API](ci/api/README.md) - [Triggering builds through the API](ci/triggers/README.md) +- [Build artifacts](ci/artifacts/README.md) ### CI Languages diff --git a/doc/ci/README.md b/doc/ci/README.md index 4cdd2e1ad33..19d08721467 100644 --- a/doc/ci/README.md +++ b/doc/ci/README.md @@ -12,6 +12,7 @@ * [Using Variables](variables/README.md) * [Using SSH keys](ssh_keys/README.md) * [Triggering builds through the API](triggers/README.md) +* [Build artifacts](artifacts/README.md) ### Languages diff --git a/doc/ci/artifacts/README.md b/doc/ci/artifacts/README.md new file mode 100644 index 00000000000..1166304f33c --- /dev/null +++ b/doc/ci/artifacts/README.md @@ -0,0 +1,50 @@ +# Build artifacts + +Since version 8.2 of GitLab and version 0.7.0 of GitLab Runner, build artifacts +created by GitLab Runner are uploaded to GitLab, and then you can download +artifacts archive using GitLab UI. + +Since version 8.4 of GitLab and version 1.0 of GitLab Runner artifacts are +compressed using ZIP format and it is possible to browse content of such an +archive using GitLab UI, and then download a single file from inside it. + +## Artifacts in .gitlab-ci.yml + +Please look into `.gitlab-ci.yml` [documentation](../yaml/README.md). + +## Artifacts archive format + +Prior to version 8.4 of GitLab and 1.0 of GitLab Runner, build artifacts were +compressed using `tar.gz` format. + +Since then, we use a ZIP format. + +## How build artifacts are stored + +After a successful build, GitLab Runner uploads an archive containing build +artifacts to GitLab. This archive is not extracted after that, so its save a +storage space. + +## How do we access content of an artifacts archive + +When GitLab receives an artifacts archive, archive metadata file is being +generated. Metadata file describes all entries that are located in artifacts +archive. This file is in a binary format, with additional GZIP compression. + +It is possible then to browse artifacts using GitLab UI and artifacts browser. + +TODO IMG + +GitLab does not extract artifacts archive to make it possible to browse it. We +use artifacts metadata file instead that contains are relevant information. +This is especially important when there is a lot of artifacts, or an archive is +a very large file. + +## How do we make files downloadable + +When user clicks a regular file, then download of this particular file starts. +GitLab does not extract entire artifacts archive to send a single file to user. + +Instead of extracting entire file, only one file is being extracted. It is not +necessary to extract large archive, just to download a small file that is +inside. -- cgit v1.2.1 From 21fab4f41317fe3c7acc7f9395cb1222e4a41074 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 20 Jan 2016 11:49:42 +0100 Subject: Use env variables for Unicorn memory limits This makes it easier for users to use their own limits based on their server configuration. --- config.ru | 5 ++++- doc/administration/environment_variables.md | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/config.ru b/config.ru index a2525c81361..1b258e0bd5e 100644 --- a/config.ru +++ b/config.ru @@ -7,8 +7,11 @@ if defined?(Unicorn) # Unicorn self-process killer require 'unicorn/worker_killer' + min = (ENV['GITLAB_UNICORN_MEMORY_MIN'] || 200 * 1 << 20).to_i + max = (ENV['GITLAB_UNICORN_MEMORY_MAX'] || 250 * 1 << 20).to_i + # Max memory size (RSS) per worker - use Unicorn::WorkerKiller::Oom, (200 * (1 << 20)), (250 * (1 << 20)) + use Unicorn::WorkerKiller::Oom, min, max end end diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index 1eb3a74d304..42a27dcf6d6 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -17,6 +17,8 @@ DATABASE_URL | url | For example: postgresql://localhost/blog_development?pool=5 GITLAB_EMAIL_FROM | email | Email address used in the "From" field in mails sent by GitLab GITLAB_EMAIL_DISPLAY_NAME | string | Name used in the "From" field in mails sent by GitLab GITLAB_EMAIL_REPLY_TO | email | Email address used in the "Reply-To" field in mails sent by GitLab +GITLAB_UNICORN_MEMORY_MIN | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer +GITLAB_UNICORN_MEMORY_MAX | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer ## Complete database variables -- cgit v1.2.1 From 89c65a3789ab51d58633841120c33f570064f242 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 20 Jan 2016 11:52:01 +0100 Subject: Increase Unicorn memory limits to 300-350 Using this limit on GitLab.com it appears we're able to reduce response timings by about 620 milliseconds compared to the previous limit. See gitlab-org/gitlab-ce!2421 for more information. --- config.ru | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.ru b/config.ru index 1b258e0bd5e..065ce59932f 100644 --- a/config.ru +++ b/config.ru @@ -7,8 +7,8 @@ if defined?(Unicorn) # Unicorn self-process killer require 'unicorn/worker_killer' - min = (ENV['GITLAB_UNICORN_MEMORY_MIN'] || 200 * 1 << 20).to_i - max = (ENV['GITLAB_UNICORN_MEMORY_MAX'] || 250 * 1 << 20).to_i + min = (ENV['GITLAB_UNICORN_MEMORY_MIN'] || 300 * 1 << 20).to_i + max = (ENV['GITLAB_UNICORN_MEMORY_MAX'] || 350 * 1 << 20).to_i # Max memory size (RSS) per worker use Unicorn::WorkerKiller::Oom, min, max -- cgit v1.2.1 From 6f32459f2c0ebc0aa10c728e5562375db9cf4c52 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 20 Jan 2016 12:05:03 +0100 Subject: Renamed "Metrics" to "Performance Monitoring" --- doc/README.md | 2 +- doc/integration/README.md | 2 +- doc/integration/metrics/gitlab_configuration.md | 6 +++--- doc/integration/metrics/influxdb_configuration.md | 2 +- doc/integration/metrics/influxdb_schema.md | 2 +- doc/integration/metrics/introduction.md | 10 +++++----- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/README.md b/doc/README.md index bee9ab05906..05c0d6fa0fe 100644 --- a/doc/README.md +++ b/doc/README.md @@ -67,7 +67,7 @@ - [Reply by email](incoming_email/README.md) Allow users to comment on issues and merge requests by replying to notification emails. - [Migrate GitLab CI to CE/EE](migrate_ci_to_ce/README.md) Follow this guide to migrate your existing GitLab CI data to GitLab CE/EE. - [Git LFS configuration](workflow/lfs/lfs_administration.md) -- [GitLab Metrics](integration/metrics/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics +- [GitLab Performance Monitoring](integration/metrics/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics ## Contributor documentation diff --git a/doc/integration/README.md b/doc/integration/README.md index 5ba0d0fb245..297e4f6e7bf 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -15,7 +15,7 @@ See the documentation below for details on how to configure these services. - [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages - [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users -- [GitLab Metrics](metrics/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics +- [GitLab Performance Monitoring](metrics/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics GitLab Enterprise Edition contains [advanced Jenkins support][jenkins]. diff --git a/doc/integration/metrics/gitlab_configuration.md b/doc/integration/metrics/gitlab_configuration.md index 019db1ad02c..b856e7935a3 100644 --- a/doc/integration/metrics/gitlab_configuration.md +++ b/doc/integration/metrics/gitlab_configuration.md @@ -1,6 +1,6 @@ # GitLab Configuration -GitLab Metrics is disabled by default. To enable it and change any of its +GitLab Performance Monitoring is disabled by default. To enable it and change any of its settings, navigate to the Admin area in **Settings > Metrics** (`/admin/application_settings`). @@ -10,7 +10,7 @@ changes. --- -![GitLab Metrics Admin Settings](img/metrics_gitlab_configuration_settings.png) +![GitLab Performance Monitoring Admin Settings](img/metrics_gitlab_configuration_settings.png) --- @@ -34,6 +34,6 @@ have been performed. Read more on: -- [Introduction to GitLab Metrics](introduction.md) +- [Introduction to GitLab Performance Monitoring](introduction.md) - [InfluxDB Configuration](influxdb_configuration.md) - [InfluxDB Schema](influxdb_schema.md) diff --git a/doc/integration/metrics/influxdb_configuration.md b/doc/integration/metrics/influxdb_configuration.md index 13227f1e889..df5e4af7fad 100644 --- a/doc/integration/metrics/influxdb_configuration.md +++ b/doc/integration/metrics/influxdb_configuration.md @@ -178,7 +178,7 @@ That's it! Now your GitLab instance should send data to InfluxDB. Read more on: -- [Introduction to GitLab Metrics](introduction.md) +- [Introduction to GitLab Performance Monitoring](introduction.md) - [GitLab Configuration](gitlab_configuration.md) - [InfluxDB Schema](influxdb_schema.md) diff --git a/doc/integration/metrics/influxdb_schema.md b/doc/integration/metrics/influxdb_schema.md index a9ef0b446c8..a5a8aebd2d1 100644 --- a/doc/integration/metrics/influxdb_schema.md +++ b/doc/integration/metrics/influxdb_schema.md @@ -82,6 +82,6 @@ view. Read more on: -- [Introduction to GitLab Metrics](introduction.md) +- [Introduction to GitLab Performance Monitoring](introduction.md) - [GitLab Configuration](gitlab_configuration.md) - [InfluxDB Configuration](influxdb_configuration.md) diff --git a/doc/integration/metrics/introduction.md b/doc/integration/metrics/introduction.md index bf388aa2bba..f2460d31302 100644 --- a/doc/integration/metrics/introduction.md +++ b/doc/integration/metrics/introduction.md @@ -1,19 +1,19 @@ -# GitLab Metrics +# GitLab Performance Monitoring GitLab comes with its own application performance measuring system as of GitLab -8.4, simply called "GitLab Metrics". GitLab Metrics is available in both the +8.4, simply called "GitLab Performance Monitoring". GitLab Performance Monitoring is available in both the Community and Enterprise editions. Apart from this introduction, you are advised to read through the following -documents in order to understand and properly configure GitLab Metrics: +documents in order to understand and properly configure GitLab Performance Monitoring: - [GitLab Configuration](gitlab_configuration.md) - [InfluxDB Configuration](influxdb_configuration.md) - [InfluxDB Schema](influxdb_schema.md) -## Introduction to GitLab Metrics +## Introduction to GitLab Performance Monitoring -GitLab Metrics makes it possible to measure a wide variety of statistics +GitLab Performance Monitoring makes it possible to measure a wide variety of statistics including (but not limited to): - The time it took to complete a transaction (a web request or Sidekiq job). -- cgit v1.2.1 From d14ed863f7723b7de201a09861deac8787fca25d Mon Sep 17 00:00:00 2001 From: Henning Hoefer Date: Wed, 20 Jan 2016 12:47:51 +0000 Subject: Add note about minimum GitLab CI version --- doc/ci/variables/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index b99ea25a3fe..862cacda586 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -56,7 +56,7 @@ export CI_SERVER_VERSION="" ``` ### YAML-defined variables -**This feature requires GitLab Runner 0.5.0 or higher** +**This feature requires GitLab Runner 0.5.0 or higher and GitLab CI 7.14 or higher ** GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in build environment. The variables are stored in repository and are meant to store non-sensitive project configuration, ie. RAILS_ENV or DATABASE_URL. -- cgit v1.2.1 From 701513dcc7afb403372bc738642a9a52e9be5983 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 14:51:56 +0100 Subject: Move parallel diff logic to separate class --- app/helpers/diff_helper.rb | 104 ------------------ app/views/projects/diffs/_parallel_view.html.haml | 6 +- app/views/projects/diffs/_text_file.html.haml | 2 +- .../projects/notes/discussions/_diff.html.haml | 2 +- lib/gitlab/diff/file.rb | 4 + lib/gitlab/diff/parallel_diff.rb | 117 +++++++++++++++++++++ spec/helpers/diff_helper_spec.rb | 18 ---- spec/lib/gitlab/diff/parallel_diff_spec.rb | 22 ++++ 8 files changed, 148 insertions(+), 127 deletions(-) create mode 100644 lib/gitlab/diff/parallel_diff.rb create mode 100644 spec/lib/gitlab/diff/parallel_diff_spec.rb diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index 425a8ced549..e524f6da9c8 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -39,110 +39,6 @@ module DiffHelper end end - def generate_line_code(file_path, line) - Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) - end - - def parallel_diff(diff_file, index) - lines = [] - skip_next = false - - diff_file.highlighted_diff_lines.each do |line| - full_line = line.text - type = line.type - line_code = generate_line_code(diff_file.file_path, line) - line_new = line.new_pos - line_old = line.old_pos - - next_line = diff_file.next_line(line.index) - - if next_line - next_line_code = generate_line_code(diff_file.file_path, next_line) - next_type = next_line.type - next_line = next_line.text - end - - case type - when 'match', nil - # line in the right panel is the same as in the left one - lines << { - left: { - type: type, - number: line_old, - text: full_line, - line_code: line_code, - }, - right: { - type: type, - number: line_new, - text: full_line, - line_code: line_code - } - } - when 'old' - case next_type - when 'new' - # Left side has text removed, right side has text added - lines << { - left: { - type: type, - number: line_old, - text: full_line, - line_code: line_code, - }, - right: { - type: next_type, - number: line_new, - text: next_line, - line_code: next_line_code - } - } - skip_next = true - when 'old', nil - # Left side has text removed, right side doesn't have any change - # No next line code, no new line number, no new line text - lines << { - left: { - type: type, - number: line_old, - text: full_line, - line_code: line_code, - }, - right: { - type: next_type, - number: nil, - text: "", - line_code: nil - } - } - end - when 'new' - if skip_next - # Change has been already included in previous line so no need to do it again - skip_next = false - next - else - # Change is only on the right side, left side has no change - lines << { - left: { - type: nil, - number: nil, - text: "", - line_code: line_code, - }, - right: { - type: type, - number: line_new, - text: full_line, - line_code: line_code - } - } - end - end - end - lines - end - def unfold_bottom_class(bottom) (bottom) ? 'js-unfold-bottom' : '' end diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 7b9cecbc3da..986d30d36a8 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -1,7 +1,7 @@ / Side-by-side diff view %div.text-file.diff-wrap-lines.code.file-content.js-syntax-highlight %table - - parallel_diff(diff_file, index).each do |line| + - diff_file.parallel_diff_lines.each do |line| - left = line[:left] - right = line[:right] %tr.line_holder.parallel @@ -13,7 +13,7 @@ = link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code] - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(left[:line_code], 'old') - %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", data: { "line_code" => left[:line_code] }}= diff_line_content(left[:text]) + %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", data: { line_code: left[:line_code] }}= diff_line_content(left[:text]) - if right[:type] == 'new' - new_line_class = 'new' @@ -26,7 +26,7 @@ = link_to raw(right[:number]), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(right[:line_code], 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", data: { "line_code" => new_line_code }}= diff_line_content(right[:text]) + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", data: { line_code: new_line_code }}= diff_line_content(right[:text]) - if @reply_allowed - comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code]) diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 6761155dcf9..310bbd4efea 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -22,7 +22,7 @@ = link_to_new_diff_note(line_code) %td.new_line{data: {linenumber: line.new_pos}} = link_to raw(type == "old" ? " " : line.new_pos), "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", data: { "line_code" => line_code }}= diff_line_content(line.text) + %td.line_content{class: "noteable_line #{type} #{line_code}", data: { line_code: line_code }}= diff_line_content(line.text) - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) diff --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml index 97347a9f67f..46962b184ce 100644 --- a/app/views/projects/notes/discussions/_diff.html.haml +++ b/app/views/projects/notes/discussions/_diff.html.haml @@ -24,7 +24,7 @@ = raw(type == "new" ? " " : line.old_pos) %td.new_line = raw(type == "old" ? " " : line.new_pos) - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= diff_line_content(line.text) + %td.line_content{class: "noteable_line #{type} #{line_code}", line_code: line_code}= diff_line_content(line.text) - if line_code == note.line_code = render "projects/notes/diff_notes_with_reply", notes: discussion_notes diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index a6a7fc8ff4c..74b1c117129 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -20,6 +20,10 @@ module Gitlab Gitlab::Diff::Highlight.new(self).highlight end + def parallel_diff_lines + Gitlab::Diff::ParallelDiff.new(self).parallelize + end + def mode_changed? !!(diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode) end diff --git a/lib/gitlab/diff/parallel_diff.rb b/lib/gitlab/diff/parallel_diff.rb new file mode 100644 index 00000000000..a0dc3da875d --- /dev/null +++ b/lib/gitlab/diff/parallel_diff.rb @@ -0,0 +1,117 @@ +module Gitlab + module Diff + class ParallelDiff + attr_accessor :diff_file + + def initialize(diff_file) + @diff_file = diff_file + end + + def parallelize + lines = [] + skip_next = false + + diff_file.highlighted_diff_lines.each do |line| + full_line = line.text + type = line.type + line_code = generate_line_code(diff_file.file_path, line) + line_new = line.new_pos + line_old = line.old_pos + + next_line = diff_file.next_line(line.index) + + if next_line + next_line_code = generate_line_code(diff_file.file_path, next_line) + next_type = next_line.type + next_line = next_line.text + end + + case type + when 'match', nil + # line in the right panel is the same as in the left one + lines << { + left: { + type: type, + number: line_old, + text: full_line, + line_code: line_code, + }, + right: { + type: type, + number: line_new, + text: full_line, + line_code: line_code + } + } + when 'old' + case next_type + when 'new' + # Left side has text removed, right side has text added + lines << { + left: { + type: type, + number: line_old, + text: full_line, + line_code: line_code, + }, + right: { + type: next_type, + number: line_new, + text: next_line, + line_code: next_line_code + } + } + skip_next = true + when 'old', nil + # Left side has text removed, right side doesn't have any change + # No next line code, no new line number, no new line text + lines << { + left: { + type: type, + number: line_old, + text: full_line, + line_code: line_code, + }, + right: { + type: next_type, + number: nil, + text: "", + line_code: nil + } + } + end + when 'new' + if skip_next + # Change has been already included in previous line so no need to do it again + skip_next = false + next + else + # Change is only on the right side, left side has no change + lines << { + left: { + type: nil, + number: nil, + text: "", + line_code: line_code, + }, + right: { + type: type, + number: line_new, + text: full_line, + line_code: line_code + } + } + end + end + end + lines + end + + private + + def generate_line_code(file_path, line) + Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) + end + end + end +end diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index 435ecd04fbe..955d2852cfd 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -84,20 +84,6 @@ describe DiffHelper do end end - describe 'parallel_diff' do - it 'should return an array of arrays containing the parsed diff' do - expect(parallel_diff(diff_file, 0)). - to match_array(parallel_diff_result_array) - end - end - - describe 'generate_line_code' do - it 'should generate correct line code' do - expect(generate_line_code(diff_file.file_path, diff_file.diff_lines.first)). - to eq('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6') - end - end - describe 'unfold_bottom_class' do it 'should return empty string when bottom line shouldnt be unfolded' do expect(unfold_bottom_class(false)).to eq('') @@ -135,8 +121,4 @@ describe DiffHelper do expect(diff_line_content(diff_file.diff_lines.first.text)).to be_html_safe end end - - def parallel_diff_result_array - YAML.load_file("#{Rails.root}/spec/fixtures/parallel_diff_result.yml") - end end diff --git a/spec/lib/gitlab/diff/parallel_diff_spec.rb b/spec/lib/gitlab/diff/parallel_diff_spec.rb new file mode 100644 index 00000000000..852218b4e62 --- /dev/null +++ b/spec/lib/gitlab/diff/parallel_diff_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe Gitlab::Diff::ParallelDiff, lib: true do + include RepoHelpers + + let(:project) { create(:project) } + let(:repository) { project.repository } + let(:commit) { project.commit(sample_commit.id) } + let(:diffs) { commit.diffs } + let(:diff) { diffs.first } + let(:diff_refs) { [commit.parent, commit] } + let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs) } + subject { described_class.new(diff_file) } + + let(:parallel_diff_result_array) { YAML.load_file("#{Rails.root}/spec/fixtures/parallel_diff_result.yml") } + + describe '#parallelize' do + it 'should return an array of arrays containing the parsed diff' do + expect(subject.parallelize).to match_array(parallel_diff_result_array) + end + end +end -- cgit v1.2.1 From 88bd13851300b98c9d0290cfac5ad1f14673b34d Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 14:59:14 +0100 Subject: Restore helper --- app/helpers/diff_helper.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index e524f6da9c8..f500d3572e0 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -39,6 +39,10 @@ module DiffHelper end end + def generate_line_code(file_path, line) + Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) + end + def unfold_bottom_class(bottom) (bottom) ? 'js-unfold-bottom' : '' end -- cgit v1.2.1 From a010db5db243a532cb8d1c2d5ac787e90da0044f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 15:26:44 +0100 Subject: Properly handle HTML entities with inline diffs --- lib/gitlab/diff/inline_diff.rb | 11 ++++------- lib/gitlab/diff/inline_diff_marker.rb | 16 ++++++++++++++-- lib/gitlab/diff/parser.rb | 7 +------ spec/lib/gitlab/diff/inline_diff_marker_spec.rb | 8 ++++---- spec/lib/gitlab/diff/parser_spec.rb | 2 +- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb index e5986fd69e2..b8a61ad6115 100644 --- a/lib/gitlab/diff/inline_diff.rb +++ b/lib/gitlab/diff/inline_diff.rb @@ -16,15 +16,12 @@ module Gitlab old_line = @lines[old_index] new_line = @lines[new_index] - suffixless_old_line = old_line[1..-1] - suffixless_new_line = new_line[1..-1] - # Skip inline diff if empty line was replaced with content - next if suffixless_old_line == "" + next if old_line[1..-1] == "" - # Add one, because this is based on the suffixless version - lcp = longest_common_prefix(suffixless_old_line, suffixless_new_line) + 1 - lcs = longest_common_suffix(suffixless_old_line, suffixless_new_line) + # Add one, because this is based on the prefixless version + lcp = longest_common_prefix(old_line[1..-1], new_line[1..-1]) + 1 + lcs = longest_common_suffix(old_line[lcp..-1], new_line[lcp..-1]) old_diff_range = lcp..(old_line.length - lcs - 1) new_diff_range = lcp..(new_line.length - lcs - 1) diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb index 8998ccba5ce..c31149d374e 100644 --- a/lib/gitlab/diff/inline_diff_marker.rb +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -12,7 +12,7 @@ module Gitlab offset = 0 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] + inline_diff_positions = position_mapping[inline_diff_range].flatten # Turn the array of character positions into ranges marker_ranges = collapse_ranges(inline_diff_positions) @@ -47,7 +47,19 @@ module Gitlab rich_char = rich_line[rich_pos] end - mapping[raw_pos] = rich_pos + # multi-char HTML entities in the rich line correspond to a single character in the raw line + if rich_char == '&' + multichar_mapping = [rich_pos] + until rich_char == ';' + rich_pos += 1 + multichar_mapping << rich_pos + rich_char = rich_line[rich_pos] + end + + mapping[raw_pos] = multichar_mapping + else + mapping[raw_pos] = rich_pos + end rich_pos += 1 end diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb index 2c0a866e8ba..6c8a1fc6d6f 100644 --- a/lib/gitlab/diff/parser.rb +++ b/lib/gitlab/diff/parser.rb @@ -14,7 +14,7 @@ module Gitlab @lines.each do |line| next if filename?(line) - full_line = html_escape(line.gsub(/\n/, '')) + full_line = line.gsub(/\n/, '') if line.match(/^@@ -/) type = "match" @@ -67,11 +67,6 @@ module Gitlab nil end end - - def html_escape(str) - replacements = { '&' => '&', '>' => '>', '<' => '<', '"' => '"', "'" => ''' } - str.gsub(/[&"'><]/, replacements) - end end end end diff --git a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb index 5d6aea17509..6f3276a8b53 100644 --- a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb +++ b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb @@ -2,14 +2,14 @@ require 'spec_helper' describe Gitlab::Diff::InlineDiffMarker, lib: true do describe '#inline_diffs' do - let(:raw) { "abc def" } - let(:rich) { %{abc def} } - let(:inline_diffs) { [2..4] } + let(:raw) { "abc 'def'" } + let(:rich) { %{abc 'def'} } + let(:inline_diffs) { [2..5] } let(:subject) { Gitlab::Diff::InlineDiffMarker.new(raw, rich).mark(inline_diffs) } it 'marks the inline diffs' do - expect(subject).to eq(%{abc def}) + expect(subject).to eq(%{abc 'def'}) end end end diff --git a/spec/lib/gitlab/diff/parser_spec.rb b/spec/lib/gitlab/diff/parser_spec.rb index ba577bd28e5..fe0dea77909 100644 --- a/spec/lib/gitlab/diff/parser_spec.rb +++ b/spec/lib/gitlab/diff/parser_spec.rb @@ -86,7 +86,7 @@ eos it { expect(line.type).to eq(nil) } it { expect(line.old_pos).to eq(24) } it { expect(line.new_pos).to eq(31) } - it { expect(line.text).to eq(' @cmd_output << stderr.read') } + it { expect(line.text).to eq(' @cmd_output << stderr.read') } end end end -- cgit v1.2.1 From 8536e083f7b2d7ed77ecae83774d75f68d66e0b4 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Wed, 20 Jan 2016 13:16:34 +0100 Subject: Add IP blocking against DNSBL at sign-up --- CHANGELOG | 1 + .../admin/application_settings_controller.rb | 2 + app/controllers/registrations_controller.rb | 5 + app/models/application_setting.rb | 2 + .../admin/application_settings/_form.html.haml | 16 ++++ ...ip_blocking_settings_to_application_settings.rb | 6 ++ db/schema.rb | 4 +- lib/dnsxl_check.rb | 105 +++++++++++++++++++++ lib/gitlab/ip_check.rb | 34 +++++++ spec/lib/dnsxl_check_spec.rb | 68 +++++++++++++ 10 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb create mode 100644 lib/dnsxl_check.rb create mode 100644 lib/gitlab/ip_check.rb create mode 100644 spec/lib/dnsxl_check_spec.rb diff --git a/CHANGELOG b/CHANGELOG index 2e0eee52a59..a17f2bfef45 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -71,6 +71,7 @@ v 8.4.0 (unreleased) - Expose button to CI Lint tool on project builds page - Fix: Creator should be added as a master of the project on creation - Added X-GitLab-... headers to emails from CI and Email On Push services (Anton Baklanov) + - Add IP check against DNSBLs at account sign-up v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 91f7d78bd73..6df8e8e4cd8 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -74,6 +74,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :metrics_timeout, :metrics_method_call_threshold, :metrics_sample_interval, + :ip_blocking_enabled, + :dnsbl_servers_list, :recaptcha_enabled, :recaptcha_site_key, :recaptcha_private_key, diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index c48175a4c5a..5efdd613e79 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -8,6 +8,11 @@ class RegistrationsController < Devise::RegistrationsController def create if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha + if Gitlab::IpCheck.new(request.remote_ip).spam? + flash[:alert] = 'Could not create an account. This IP is listed for spam.' + return render action: 'new' + end + super else flash[:alert] = "There was an error with the reCAPTCHA code below. Please re-enter the code." diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 6c6c2468374..db208884aa6 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -41,6 +41,8 @@ # recaptcha_site_key :string # recaptcha_private_key :string # metrics_port :integer default(8089) +# ip_blocking_enabled :boolean default(FALSE) +# dns_blacklist_threshold :float default(0.33) # class ApplicationSetting < ActiveRecord::Base diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 83f6814d822..4f915818d8f 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -212,6 +212,22 @@ %fieldset %legend Spam and Anti-bot Protection + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :ip_blocking_enabled do + = f.check_box :ip_blocking_enabled + Enable IP check against blacklist at sign-up + .help-block Helps preventing accounts creation from 'known spam sources' + + .form-group + = f.label :dnsbl_servers_list, class: 'control-label col-sm-2' do + DNSBL servers list + .col-sm-10 + = f.text_field :dnsbl_servers_list, class: 'form-control' + .help-block + Please enter DNSBL servers separated with comma + .form-group .col-sm-offset-2.col-sm-10 .checkbox diff --git a/db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb b/db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb new file mode 100644 index 00000000000..26606b10b54 --- /dev/null +++ b/db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb @@ -0,0 +1,6 @@ +class AddIpBlockingSettingsToApplicationSettings < ActiveRecord::Migration + def change + add_column :application_settings, :ip_blocking_enabled, :boolean, default: false + add_column :application_settings, :dnsbl_servers_list, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index dc7cb9f667f..1457259ebaf 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: 20160120130905) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -62,6 +62,8 @@ ActiveRecord::Schema.define(version: 20160119145451) do t.string "recaptcha_private_key" t.integer "metrics_port", default: 8089 t.integer "metrics_sample_interval", default: 15 + t.boolean "ip_blocking_enabled", default: false + t.text "dnsbl_servers_list" end create_table "audit_events", force: :cascade do |t| diff --git a/lib/dnsxl_check.rb b/lib/dnsxl_check.rb new file mode 100644 index 00000000000..1e506b2d9cb --- /dev/null +++ b/lib/dnsxl_check.rb @@ -0,0 +1,105 @@ +require 'resolv' + +class DNSXLCheck + + class Resolver + def self.search(query) + begin + Resolv.getaddress(query) + true + rescue Resolv::ResolvError + false + end + end + end + + IP_REGEXP = /\A(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\z/ + DEFAULT_THRESHOLD = 0.33 + + def self.create_from_list(list) + dnsxl_check = DNSXLCheck.new + + list.each do |entry| + dnsxl_check.add_list(entry.domain, entry.weight) + end + + dnsxl_check + end + + def test(ip) + if use_threshold? + test_with_threshold(ip) + else + test_strict(ip) + end + end + + def test_with_threshold(ip) + return false if lists.empty? + + search(ip) + final_score >= threshold + end + + def test_strict(ip) + return false if lists.empty? + + search(ip) + @score > 0 + end + + def use_threshold=(value) + @use_threshold = value == true + end + + def use_threshold? + @use_threshold &&= true + end + + def threshold=(threshold) + raise ArgumentError, "'threshold' value must be grather than 0 and less than or equal to 1" unless threshold > 0 && threshold <= 1 + @threshold = threshold + end + + def threshold + @threshold ||= DEFAULT_THRESHOLD + end + + def add_list(domain, weight) + @lists ||= [] + @lists << { domain: domain, weight: weight } + end + + def lists + @lists ||= [] + end + + private + + def search(ip) + raise ArgumentError, "'ip' value must be in #{IP_REGEXP} format" unless ip.match(IP_REGEXP) + + @score = 0 + + reversed = reverse_ip(ip) + search_in_rbls(reversed) + end + + def reverse_ip(ip) + ip.split('.').reverse.join('.') + end + + def search_in_rbls(reversed_ip) + lists.each do |rbl| + query = "#{reversed_ip}.#{rbl[:domain]}" + @score += rbl[:weight] if Resolver.search(query) + end + end + + def final_score + weights = lists.map{ |rbl| rbl[:weight] }.reduce(:+).to_i + return 0 if weights == 0 + + (@score.to_f / weights.to_f).round(2) + end +end diff --git a/lib/gitlab/ip_check.rb b/lib/gitlab/ip_check.rb new file mode 100644 index 00000000000..f2e9b50d225 --- /dev/null +++ b/lib/gitlab/ip_check.rb @@ -0,0 +1,34 @@ +module Gitlab + class IpCheck + + def initialize(ip) + @ip = ip + + application_settings = ApplicationSetting.current + @ip_blocking_enabled = application_settings.ip_blocking_enabled + @dnsbl_servers_list = application_settings.dnsbl_servers_list + end + + def spam? + @ip_blocking_enabled && blacklisted? + end + + private + + def blacklisted? + on_dns_blacklist? + end + + def on_dns_blacklist? + dnsbl_check = DNSXLCheck.new + prepare_dnsbl_list(dnsbl_check) + dnsbl_check.test(@ip) + end + + def prepare_dnsbl_list(dnsbl_check) + @dnsbl_servers_list.split(',').map(&:strip).reject(&:empty?).each do |domain| + dnsbl_check.add_list(domain, 1) + end + end + end +end diff --git a/spec/lib/dnsxl_check_spec.rb b/spec/lib/dnsxl_check_spec.rb new file mode 100644 index 00000000000..a35a1be0c90 --- /dev/null +++ b/spec/lib/dnsxl_check_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' +require 'ostruct' + +describe 'DNSXLCheck', lib: true, no_db: true do + let(:spam_ip) { '127.0.0.2' } + let(:no_spam_ip) { '127.0.0.3' } + let(:invalid_ip) { 'a.b.c.d' } + let!(:dnsxl_check) { DNSXLCheck.create_from_list([OpenStruct.new({ domain: 'test', weight: 1 })]) } + + before(:context) do + class DNSXLCheck::Resolver + class << self + alias_method :old_search, :search + def search(query) + return false if query.match(/always\.failing\.domain\z/) + return true if query.match(/\A2\.0\.0\.127\./) + return false if query.match(/\A3\.0\.0\.127\./) + end + end + end + end + + describe '#test' do + before do + dnsxl_check.threshold = 0.75 + dnsxl_check.add_list('always.failing.domain', 1) + end + + context 'when threshold is used' do + before { dnsxl_check.use_threshold= true } + + it { expect(dnsxl_check.test(spam_ip)).to be_falsey } + end + + context 'when threshold is not used' do + before { dnsxl_check.use_threshold= false } + + it { expect(dnsxl_check.test(spam_ip)).to be_truthy } + end + end + + describe '#test_with_threshold' do + it { expect{ dnsxl_check.test_with_threshold(invalid_ip) }.to raise_error(ArgumentError) } + + it { expect(dnsxl_check.test_with_threshold(spam_ip)).to be_truthy } + it { expect(dnsxl_check.test_with_threshold(no_spam_ip)).to be_falsey } + end + + describe '#test_strict' do + before do + dnsxl_check.threshold = 1 + dnsxl_check.add_list('always.failing.domain', 1) + end + + it { expect{ dnsxl_check.test_strict(invalid_ip) }.to raise_error(ArgumentError) } + + it { expect(dnsxl_check.test_with_threshold(spam_ip)).to be_falsey } + it { expect(dnsxl_check.test_with_threshold(no_spam_ip)).to be_falsey } + it { expect(dnsxl_check.test_strict(spam_ip)).to be_truthy } + it { expect(dnsxl_check.test_strict(no_spam_ip)).to be_falsey } + end + + describe '#threshold=' do + it { expect{ dnsxl_check.threshold = 0 }.to raise_error(ArgumentError) } + it { expect{ dnsxl_check.threshold = 1.1 }.to raise_error(ArgumentError) } + it { expect{ dnsxl_check.threshold = 0.5 }.not_to raise_error } + end +end -- cgit v1.2.1 From 987e3d94b017cb94f55cf47cdbb417c45adf0681 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 15:40:49 +0100 Subject: Fix MR diff_refs --- app/models/merge_request.rb | 4 ++-- app/views/projects/merge_requests/_new_submit.html.haml | 2 +- app/views/projects/merge_requests/show/_diffs.html.haml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 9511521879b..0a890bbf6db 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -518,7 +518,7 @@ class MergeRequest < ActiveRecord::Base @ci_commit ||= source_project.ci_commit(last_commit.id) if last_commit && source_project end - def diff_range - [last_commit.parent, first_commit] + def diff_refs + [first_commit.parent || first_commit, last_commit] end end diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index 8b75976abd1..4c5a9818e3e 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -38,7 +38,7 @@ = render "projects/merge_requests/show/commits" #diffs.diffs.tab-pane.active - if @diffs.present? - = render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @merge_request.diff_range + = render "projects/diffs/diffs", diffs: @diffs, project: @project, diff_refs: @merge_request.diff_refs - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE .alert.alert-danger %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits. diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml index 46c6f79937b..64cd484193e 100644 --- a/app/views/projects/merge_requests/show/_diffs.html.haml +++ b/app/views/projects/merge_requests/show/_diffs.html.haml @@ -1,6 +1,6 @@ - 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, diff_refs: @merge_request.diff_range + project: @merge_request.project, diff_refs: @merge_request.diff_refs - elsif @merge_request_diff.empty? .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch} - else -- cgit v1.2.1 From a10ab94b068c31601c7d4ab0062b9d567af6cee2 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 13 Jan 2016 07:05:28 -0800 Subject: Gracefully handle invalid UTF-8 sequences in Markdown links Closes #6077 --- CHANGELOG | 1 + lib/banzai/filter/reference_filter.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 2e0eee52a59..64121d05143 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,7 @@ v 8.4.0 (unreleased) - Autocomplete data is now always loaded, instead of when focusing a comment text area - Improved performance of finding issues for an entire group - Added custom application performance measuring system powered by InfluxDB + - Gracefully handle invalid UTF-8 sequences in Markdown links (Stan Hu) - Bump fog to 1.36.0 (Stan Hu) - Add user's last used IP addresses to admin page (Stan Hu) - Add housekeeping function to project settings page diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb index 20bd4f7ee6e..3637b1bac94 100644 --- a/lib/banzai/filter/reference_filter.rb +++ b/lib/banzai/filter/reference_filter.rb @@ -133,6 +133,7 @@ module Banzai next unless link && text link = CGI.unescape(link) + next unless link.force_encoding('UTF-8').valid_encoding? # Ignore ending punctionation like periods or commas next unless link == text && text =~ /\A#{pattern}/ @@ -170,6 +171,7 @@ module Banzai next unless link && text link = CGI.unescape(link) + next unless link.force_encoding('UTF-8').valid_encoding? next unless link && link =~ /\A#{pattern}\z/ html = yield link, text -- cgit v1.2.1 From 0ad6b44a27baa260fb94569c354f30a54cf86d13 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 16:15:19 +0100 Subject: Send user context to Sentry --- app/controllers/application_controller.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index bf99b2e777d..633c3f55614 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,6 +15,7 @@ class ApplicationController < ActionController::Base before_action :check_password_expiration before_action :check_2fa_requirement before_action :ldap_security_check + before_action :sentry_user_context before_action :default_headers before_action :add_gon_variables before_action :configure_permitted_parameters, if: :devise_controller? @@ -41,6 +42,16 @@ class ApplicationController < ActionController::Base protected + def sentry_user_context + if Rails.env.production? && current_application_settings.sentry_enabled && current_user + Raven.user_context( + id: current_user.id, + email: current_user.email, + username: current_user.username, + ) + end + end + # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 def authenticate_user_from_token! -- cgit v1.2.1 From 7838c957c23a36fb64125a1baf14454b735e9561 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 16:18:42 +0100 Subject: Target '_blank' --- app/views/admin/application_settings/_form.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index f5a87933fde..35e4dd761ab 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -226,7 +226,7 @@ = f.text_field :recaptcha_site_key, class: 'form-control' .help-block Generate site and private keys here: - %a{ href: 'http://www.google.com/recaptcha', target: 'blank'} http://www.google.com/recaptcha + %a{ href: 'http://www.google.com/recaptcha', target: '_blank'} http://www.google.com/recaptcha .form-group = f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'control-label col-sm-2' .col-sm-10 @@ -244,7 +244,7 @@ Enable Sentry .help-block Sentry is an error reporting and logging tool which is currently not shipped with GitLab, get it here: - %a{ href: 'https://getsentry.com', target: 'blank' } https://getsentry.com + %a{ href: 'https://getsentry.com', target: '_blank' } https://getsentry.com .form-group = f.label :sentry_dsn, 'Sentry DSN', class: 'control-label col-sm-2' -- cgit v1.2.1 From 7377abf84a7fc20eb93938f73ce77ae26d3ec8ec Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 20 Jan 2016 10:50:26 -0500 Subject: Simplifies the HAML if statement for project branch URL --- app/views/layouts/header/_default.html.haml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index d1425cd0e88..fcb6b835a7e 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -37,10 +37,6 @@ %h1.title= title = render 'shared/outdated_browser' --if @project && !@project.empty_repo? && @ref +- if @project && !@project.empty_repo? :javascript - var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref)}"; - --elsif @project && !@project.empty_repo? - :javascript - var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @project.repository.root_ref)}"; \ No newline at end of file + var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}"; \ No newline at end of file -- cgit v1.2.1 From 419a5e00eb83d3ae1fb9725200bb4a72cb8a52e2 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 20 Jan 2016 17:12:30 +0100 Subject: updated gitlab_git to fix issue #5858 and updated changelog --- CHANGELOG | 1 + Gemfile | 2 +- Gemfile.lock | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2e0eee52a59..03fce7e2157 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.5.0 (unreleased) - Add "visibility" flag to GET /projects api endpoint + - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push v 8.4.0 (unreleased) - Allow LDAP users to change their email if it was not set by the LDAP server diff --git a/Gemfile b/Gemfile index 072f7a9fcc8..1c586adbfb5 100644 --- a/Gemfile +++ b/Gemfile @@ -49,7 +49,7 @@ gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 7.2.22' +gem "gitlab_git", '~> 7.2.23' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes diff --git a/Gemfile.lock b/Gemfile.lock index a14fdbeed23..acd7978c345 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -356,7 +356,7 @@ GEM posix-spawn (~> 0.3) gitlab_emoji (0.2.0) gemojione (~> 2.1) - gitlab_git (7.2.22) + gitlab_git (7.2.23) activesupport (~> 4.0) charlock_holmes (~> 0.7.3) github-linguist (~> 4.7.0) @@ -932,7 +932,7 @@ DEPENDENCIES github-markup (~> 1.3.1) gitlab-flowdock-git-hook (~> 1.0.1) gitlab_emoji (~> 0.2.0) - gitlab_git (~> 7.2.22) + gitlab_git (~> 7.2.23) gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.1.0) -- cgit v1.2.1 From 26f7d023e6d15f4deab39f74509bd6dddebf6974 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 17:14:26 +0100 Subject: Update tests --- spec/fixtures/parallel_diff_result.yml | 2 +- spec/lib/gitlab/diff/highlight_spec.rb | 2 +- spec/lib/gitlab/diff/parallel_diff_spec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/fixtures/parallel_diff_result.yml b/spec/fixtures/parallel_diff_result.yml index 0fb9bf6c5d8..a326b651aad 100644 --- a/spec/fixtures/parallel_diff_result.yml +++ b/spec/fixtures/parallel_diff_result.yml @@ -55,7 +55,7 @@ :type: new :number: 9 :text: | - + raise RuntimeError, "System commands must be given as an array of strings" + + raise RuntimeError, "System commands must be given as an array of strings" :line_code: 2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9 - :left: :type: diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index b54e95483d3..b84a57f357a 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -33,7 +33,7 @@ describe Gitlab::Diff::Highlight, lib: true do end it 'should highlight added lines' do - code = %Q{+ raise RuntimeError, "System commands must be given as an array of strings"\n} + code = %Q{+ raise RuntimeError, "System commands must be given as an array of strings"\n} expect(diff_lines[5].text).to eq(code) end diff --git a/spec/lib/gitlab/diff/parallel_diff_spec.rb b/spec/lib/gitlab/diff/parallel_diff_spec.rb index 852218b4e62..1c5bbc47120 100644 --- a/spec/lib/gitlab/diff/parallel_diff_spec.rb +++ b/spec/lib/gitlab/diff/parallel_diff_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Gitlab::Diff::ParallelDiff, lib: true do include RepoHelpers - + let(:project) { create(:project) } let(:repository) { project.repository } let(:commit) { project.commit(sample_commit.id) } -- cgit v1.2.1 From 577f2fb47a7ef57415b78b49d5c746d4e99f6a98 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 18:44:27 +0100 Subject: Save and use actual diff base commit for MR diff highlighting --- app/controllers/projects/compare_controller.rb | 4 +-- .../projects/merge_requests_controller.rb | 8 ++++-- app/helpers/diff_helper.rb | 3 +-- app/models/merge_request.rb | 15 ++++++++--- app/models/merge_request_diff.rb | 9 +++++++ ...3_add_base_commit_sha_to_merge_request_diffs.rb | 5 ++++ db/schema.rb | 29 +++++++++++----------- lib/gitlab/diff/file.rb | 12 +++++++-- lib/gitlab/diff/highlight.rb | 9 ++++++- lib/gitlab/diff/inline_diff_marker.rb | 13 +++++----- 10 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb 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 -- cgit v1.2.1 From 0e992a3b4e710f8486a37bfa73ad6981365fceb2 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 19:20:13 +0100 Subject: Properly highlight lines around '\ No newline at end of file' --- app/views/projects/diffs/_parallel_view.html.haml | 5 +++++ app/views/projects/diffs/_text_file.html.haml | 4 ++++ lib/gitlab/diff/highlight.rb | 4 ++-- lib/gitlab/diff/parallel_diff.rb | 2 +- lib/gitlab/diff/parser.rb | 16 ++++++++++++---- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index 986d30d36a8..a15d147ab05 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -8,6 +8,11 @@ - if left[:type] == 'match' = render "projects/diffs/match_line_parallel", { line: left[:text], line_old: left[:number], line_new: right[:number] } + - elsif left[:type] == 'nonewline' + %td.old_line + %td.line_content.parallel.matched= left[:text] + %td.new_line + %td.line_content.parallel.matched= left[:text] - else %td.old_line{id: left[:line_code], class: "#{left[:type]}"} = link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code] diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 310bbd4efea..f4fc6caba0f 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -15,6 +15,10 @@ - if type == "match" = render "projects/diffs/match_line", {line: line.text, line_old: line_old, line_new: line.new_pos, bottom: false, new_file: diff_file.new_file} + - elsif type == 'nonewline' + %td.old_line.diff-line-num + %td.new_line.diff-line-num + %td.line_content.matched= line.text - else %td.old_line = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index fe084a7399a..179f8164c84 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -14,7 +14,7 @@ module Gitlab def highlight @diff_lines.each_with_index do |diff_line, i| # ignore highlighting for "match" lines - next if diff_line.type == 'match' + next if diff_line.type == 'match' || diff_line.type == 'nonewline' rich_line = highlight_line(diff_line, i) @@ -33,7 +33,7 @@ module Gitlab 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 : ' ' + line_prefix = diff_line.text.match(/\A(.)/) ? $1 : ' ' case diff_line.type when 'new', nil diff --git a/lib/gitlab/diff/parallel_diff.rb b/lib/gitlab/diff/parallel_diff.rb index a0dc3da875d..c0db3559e3a 100644 --- a/lib/gitlab/diff/parallel_diff.rb +++ b/lib/gitlab/diff/parallel_diff.rb @@ -62,7 +62,7 @@ module Gitlab } } skip_next = true - when 'old', nil + when 'old', 'nonewline', nil # Left side has text removed, right side doesn't have any change # No next line code, no new line number, no new line text lines << { diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb index 6c8a1fc6d6f..3666063bf8b 100644 --- a/lib/gitlab/diff/parser.rb +++ b/lib/gitlab/diff/parser.rb @@ -26,6 +26,10 @@ module Gitlab lines_obj << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new) line_obj_index += 1 next + elsif line[0] == '\\' + type = 'nonewline' + lines_obj << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new) + line_obj_index += 1 else type = identification_type(line) lines_obj << Gitlab::Diff::Line.new(full_line, type, line_obj_index, line_old, line_new) @@ -33,10 +37,13 @@ module Gitlab end - if line[0] == "+" + case line[0] + when "+" line_new += 1 - elsif line[0] == "-" + when "-" line_old += 1 + when "\\" + # No increment else line_new += 1 line_old += 1 @@ -59,9 +66,10 @@ module Gitlab end def identification_type(line) - if line[0] == "+" + case line[0] + when "+" "new" - elsif line[0] == "-" + when "-" "old" else nil -- cgit v1.2.1 From 34b132d49ae2552104e937642495203598ad59cf Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 20 Jan 2016 13:24:52 -0500 Subject: Fix term height so text overflap does not happen. --- app/assets/stylesheets/pages/search.scss | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index bdcf1897522..3aaa96da609 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -3,10 +3,6 @@ border-bottom: 1px solid #DDD; padding-bottom: 15px; margin-bottom: 15px; - - .term { - height: 22px; - } } } -- cgit v1.2.1 From 6000f8545f43b449035cb50382901ce40fb807b0 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 20 Jan 2016 19:33:34 +0100 Subject: Validate bounds just to be sure --- lib/gitlab/diff/inline_diff_marker.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb index 7ca198eeb86..1d7fa1bce06 100644 --- a/lib/gitlab/diff/inline_diff_marker.rb +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -93,6 +93,9 @@ module Gitlab # Inserts tags around the characters identified by the given range def insert_around_range(text, range, before, after, offset = 0) + # Just to be sure + return offset if offset + range.end + 1 > text.length + text.insert(offset + range.begin, before) offset += before.length -- cgit v1.2.1 From 7a0bde935ae487c172e80cbd0c965db86f640634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20HULARD?= Date: Wed, 20 Jan 2016 18:38:15 +0000 Subject: Fix a missing letter in the documentation. --- doc/ci/languages/php.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ci/languages/php.md b/doc/ci/languages/php.md index dacb67fa3ff..77f9fae5bb6 100644 --- a/doc/ci/languages/php.md +++ b/doc/ci/languages/php.md @@ -12,7 +12,7 @@ configuration from the developer. To overcome this we will be using the official [PHP docker image][php-hub] that can be found in Docker Hub. This will allow us to test PHP projects against different versions of PHP. -However, not everything is plug 'n' play, you still need to onfigure some +However, not everything is plug 'n' play, you still need to configure some things manually. As with every build, you need to create a valid `.gitlab-ci.yml` describing the -- cgit v1.2.1 From 86b75f4713fa6cb14cbf443c1e29ca6384204b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D=C3=A1vila?= Date: Wed, 20 Jan 2016 14:38:34 -0500 Subject: Use a MR with commits. --- spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb index 449cecaa789..de9fed2b7dd 100644 --- a/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb +++ b/spec/services/merge_requests/merge_when_build_succeeds_service_spec.rb @@ -6,7 +6,7 @@ describe MergeRequests::MergeWhenBuildSucceedsService do let(:mr_merge_if_green_enabled) do create(:merge_request, merge_when_build_succeeds: true, merge_user: user, - source_branch: "source_branch", target_branch: project.default_branch, + source_branch: "master", target_branch: 'feature', source_project: project, target_project: project, state: "opened") end -- cgit v1.2.1 From 9b0f57781e8c71eb0e627a63078fedcedfe62bbb Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 20 Jan 2016 21:48:22 +0100 Subject: Add method that calculates total size for artifacts subfolder --- app/models/ci/build.rb | 8 ++++---- app/views/projects/builds/show.html.haml | 2 +- lib/gitlab/ci/build/artifacts/metadata.rb | 8 +++++--- lib/gitlab/ci/build/artifacts/metadata/entry.rb | 7 +++++++ .../gitlab/ci/build/artifacts/metadata/entry_spec.rb | 15 ++++++++++----- spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb | 17 +++++++++++++++-- spec/models/build_spec.rb | 8 ++++---- 7 files changed, 46 insertions(+), 19 deletions(-) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 16a5b03f591..623edd8bc57 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -346,17 +346,17 @@ module Ci end def artifacts_browse_url - if artifacts_browser_supported? + if artifacts_metadata? browse_namespace_project_build_artifacts_path(project.namespace, project, self) end end - def artifacts_browser_supported? + def artifacts_metadata? artifacts? && artifacts_metadata.exists? end - def artifacts_metadata_entry(path) - Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path).to_entry + def artifacts_metadata_entry(path, **options) + Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path, **options).to_entry end private diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index 2be572d3b10..ba1fdc6f0e7 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -96,7 +96,7 @@ .center .btn-group{ role: :group } = link_to "Download", @build.artifacts_download_url, class: 'btn btn-sm btn-primary' - - if @build.artifacts_browser_supported? + - if @build.artifacts_metadata? = link_to "Browse", @build.artifacts_browse_url, class: 'btn btn-sm btn-primary' .build-widget diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb index 1344f5d120b..f2020c82d40 100644 --- a/lib/gitlab/ci/build/artifacts/metadata.rb +++ b/lib/gitlab/ci/build/artifacts/metadata.rb @@ -13,8 +13,8 @@ module Gitlab attr_reader :file, :path, :full_version - def initialize(file, path) - @file, @path = file, path + def initialize(file, path, **opts) + @file, @path, @opts = file, path, opts @full_version = read_version end @@ -52,7 +52,9 @@ module Gitlab def match_entries(gz) entries = {} - match_pattern = %r{^#{Regexp.escape(@path)}[^/]*/?$} + + child_pattern = '[^/]*/?$' unless @opts[:recursive] + match_pattern = /^#{Regexp.escape(@path)}#{child_pattern}/ until gz.eof? do begin diff --git a/lib/gitlab/ci/build/artifacts/metadata/entry.rb b/lib/gitlab/ci/build/artifacts/metadata/entry.rb index 25b71fc3275..7f4c750b6fd 100644 --- a/lib/gitlab/ci/build/artifacts/metadata/entry.rb +++ b/lib/gitlab/ci/build/artifacts/metadata/entry.rb @@ -95,6 +95,13 @@ module Gitlab children.empty? end + def total_size + descendant_pattern = %r{^#{Regexp.escape(@path)}} + entries.sum do |path, entry| + (entry[:size] if path =~ descendant_pattern).to_i + end + end + def to_s @path end diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb index 41257103ead..acca0b08bab 100644 --- a/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb +++ b/spec/lib/gitlab/ci/build/artifacts/metadata/entry_spec.rb @@ -4,13 +4,13 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do let(:entries) do { 'path/' => {}, 'path/dir_1/' => {}, - 'path/dir_1/file_1' => {}, - 'path/dir_1/file_b' => {}, + 'path/dir_1/file_1' => { size: 10 }, + 'path/dir_1/file_b' => { size: 10 }, 'path/dir_1/subdir/' => {}, - 'path/dir_1/subdir/subfile' => {}, + 'path/dir_1/subdir/subfile' => { size: 10 }, 'path/second_dir' => {}, - 'path/second_dir/dir_3/file_2' => {}, - 'path/second_dir/dir_3/file_3'=> {}, + 'path/second_dir/dir_3/file_2' => { size: 10 }, + 'path/second_dir/dir_3/file_3'=> { size: 10 }, 'another_directory/'=> {}, 'another_file' => {}, '/file/with/absolute_path' => {} } @@ -112,6 +112,11 @@ describe Gitlab::Ci::Build::Artifacts::Metadata::Entry do subject { |example| path(example).empty? } it { is_expected.to be false } end + + describe '#total_size' do + subject { |example| path(example).total_size } + it { is_expected.to eq(30) } + end end end diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb index 828eedfa7b0..eea01f91879 100644 --- a/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb +++ b/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' describe Gitlab::Ci::Build::Artifacts::Metadata do - def metadata(path = '') - described_class.new(metadata_file_path, path) + def metadata(path = '', **opts) + described_class.new(metadata_file_path, path, **opts) end let(:metadata_file_path) do @@ -51,6 +51,19 @@ describe Gitlab::Ci::Build::Artifacts::Metadata do end end + describe '#find_entries! recursively for other_artifacts_0.1.2/' do + subject { metadata('other_artifacts_0.1.2/', recursive: true).find_entries! } + + it 'matches correct paths' do + expect(subject.keys). + to contain_exactly 'other_artifacts_0.1.2/', + 'other_artifacts_0.1.2/doc_sample.txt', + 'other_artifacts_0.1.2/another-subdirectory/', + 'other_artifacts_0.1.2/another-subdirectory/empty_directory/', + 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' + end + end + describe '#to_entry' do subject { metadata('').to_entry } it { is_expected.to be_an_instance_of(Gitlab::Ci::Build::Artifacts::Metadata::Entry) } diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index d12b9e65c82..d30bc7d0554 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -362,12 +362,12 @@ describe Ci::Build, models: true do subject { build.artifacts_browse_url } it "should be nil if artifacts browser is unsupported" do - allow(build).to receive(:artifacts_browser_supported?).and_return(false) + allow(build).to receive(:artifacts_metadata?).and_return(false) is_expected.to be_nil end it 'should not be nil if artifacts browser is supported' do - allow(build).to receive(:artifacts_browser_supported?).and_return(true) + allow(build).to receive(:artifacts_metadata?).and_return(true) is_expected.to_not be_nil end end @@ -391,8 +391,8 @@ describe Ci::Build, models: true do end - describe :artifacts_browser_supported? do - subject { build.artifacts_browser_supported? } + describe :artifacts_metadata? do + subject { build.artifacts_metadata? } context 'artifacts metadata does not exist' do it { is_expected.to be_falsy } end -- cgit v1.2.1 From cd7f27543b4d676424785a6c3d16850909341dba Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 20 Jan 2016 22:32:10 +0100 Subject: Mention required Ruby version [ci skip] --- doc/install/installation.md | 15 +++++++++++++-- doc/install/requirements.md | 11 +++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 00030729a4b..4772ed3c566 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -107,9 +107,16 @@ Then select 'Internet Site' and press enter to confirm the hostname. ## 2. Ruby -The use of Ruby version managers such as [RVM](https://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly advise everyone to follow the instructions below to use a system Ruby. +_**Note:** The current supported Ruby versions are 2.1.x. Ruby 2.2 and 2.3 are +currently not supported._ -Remove the old Ruby 1.8 if present +The use of Ruby version managers such as [RVM], [rbenv] or [chruby] with GitLab +in production, frequently leads to hard to diagnose problems. For example, +GitLab Shell is called from OpenSSH, and having a version manager can prevent +pushing and pulling over SSH. Version managers are not supported and we strongly +advise everyone to follow the instructions below to use a system Ruby. + +Remove the old Ruby 1.8 if present: sudo apt-get remove ruby1.8 @@ -555,3 +562,7 @@ this is likely due to an outdated Nginx or Apache configuration, or a missing or misconfigured gitlab-workhorse instance. Double-check that you've [installed Go](#3-go), [installed gitlab-workhorse](#install-gitlab-workhorse), and correctly [configured Nginx](#site-configuration). + +[RVM]: https://rvm.io/ "RVM Homepage" +[rbenv]: https://github.com/sstephenson/rbenv "rbenv on GitHub" +[chruby]: https://github.com/postmodern/chruby "chruby on GitHub" diff --git a/doc/install/requirements.md b/doc/install/requirements.md index c0ccdd37458..c0425f27ab1 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -32,15 +32,18 @@ Please consider using a virtual machine to run GitLab. ## Ruby versions -GitLab requires Ruby (MRI) 2.1 +GitLab requires Ruby (MRI) 2.1.x and currently does not work with versions 2.2 +and 2.3. + You will have to use the standard MRI implementation of Ruby. -We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab needs several Gems that have native extensions. +We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab +needs several Gems that have native extensions. ## Hardware requirements ### Storage -The necessary hard drive space largely depends on the size of the repos you want to store in GitLab but as a *rule of thumb* you should have at least as much free space as all your repos combined take up. +The necessary hard drive space largely depends on the size of the repos you want to store in GitLab but as a *rule of thumb* you should have at least as much free space as all your repos combined take up. If you want to be flexible about growing your hard drive space in the future consider mounting it using LVM so you can add more hard drives when you need them. @@ -109,4 +112,4 @@ On a very active server (10,000 active users) the Sidekiq process can use 1GB+ o - Firefox (Latest released version and [latest ESR version](https://www.mozilla.org/en-US/firefox/organizations/)) - Safari 7+ (known problem: required fields in html5 do not work) - Opera (Latest released version) -- Internet Explorer (IE) 10+ but please make sure that you have the `Compatibility View` mode disabled. \ No newline at end of file +- Internet Explorer (IE) 10+ but please make sure that you have the `Compatibility View` mode disabled. -- cgit v1.2.1 From f4bdbecfd54c39baed79d0143de97933d26e3215 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 20 Jan 2016 19:36:35 -0200 Subject: Fix cross projects detection when importing GitHub pull requests --- lib/gitlab/github_import/pull_request_formatter.rb | 6 ++++- .../github_import/pull_request_formatter_spec.rb | 27 ++++++++++++++-------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/lib/gitlab/github_import/pull_request_formatter.rb b/lib/gitlab/github_import/pull_request_formatter.rb index b7c47958cc7..f96fed0f5cf 100644 --- a/lib/gitlab/github_import/pull_request_formatter.rb +++ b/lib/gitlab/github_import/pull_request_formatter.rb @@ -18,7 +18,7 @@ module Gitlab end def cross_project? - source_repo.fork == true + source_repo.id != target_repo.id end def number @@ -73,6 +73,10 @@ module Gitlab project end + def target_repo + raw_data.base.repo + end + def target_branch target_project.repository.find_branch(raw_data.base.ref) end diff --git a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb index 9aefec77f6d..6cebcb5009a 100644 --- a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb +++ b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb @@ -2,8 +2,11 @@ require 'spec_helper' describe Gitlab::GithubImport::PullRequestFormatter, lib: true do let(:project) { create(:project) } - let(:source_branch) { OpenStruct.new(ref: 'feature') } - let(:target_branch) { OpenStruct.new(ref: 'master') } + let(:repository) { OpenStruct.new(id: 1, fork: false) } + let(:source_repo) { repository } + let(:source_branch) { OpenStruct.new(ref: 'feature', repo: source_repo) } + let(:target_repo) { repository } + let(:target_branch) { OpenStruct.new(ref: 'master', repo: target_repo) } let(:octocat) { OpenStruct.new(id: 123456, login: 'octocat') } let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') } let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') } @@ -125,10 +128,8 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do end describe '#cross_project?' do - context 'when source repo is not a fork' do - let(:local_repo) { OpenStruct.new(fork: false) } - let(:source_branch) { OpenStruct.new(ref: 'feature', repo: local_repo) } - let(:raw_data) { OpenStruct.new(base_data.merge(head: source_branch)) } + context 'when source, and target repositories are the same' do + let(:raw_data) { OpenStruct.new(base_data) } it 'returns false' do expect(pull_request.cross_project?).to eq false @@ -136,9 +137,17 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do end context 'when source repo is a fork' do - let(:forked_repo) { OpenStruct.new(fork: true) } - let(:source_branch) { OpenStruct.new(ref: 'feature', repo: forked_repo) } - let(:raw_data) { OpenStruct.new(base_data.merge(head: source_branch)) } + let(:source_repo) { OpenStruct.new(id: 2, fork: true) } + let(:raw_data) { OpenStruct.new(base_data) } + + it 'returns true' do + expect(pull_request.cross_project?).to eq true + end + end + + context 'when target repo is a fork' do + let(:target_repo) { OpenStruct.new(id: 2, fork: true) } + let(:raw_data) { OpenStruct.new(base_data) } it 'returns true' do expect(pull_request.cross_project?).to eq true -- cgit v1.2.1 From 82bc7679e782059568402a282905d3d607dbb97d Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 20 Jan 2016 23:02:24 +0100 Subject: Move integration/metrics to monitoring/performance [ci skip] --- doc/README.md | 2 +- doc/integration/metrics/gitlab_configuration.md | 39 ----- .../img/metrics_gitlab_configuration_settings.png | Bin 45148 -> 0 bytes doc/integration/metrics/influxdb_configuration.md | 192 --------------------- doc/integration/metrics/influxdb_schema.md | 87 ---------- doc/integration/metrics/introduction.md | 64 ------- doc/monitoring/performance/gitlab_configuration.md | 39 +++++ .../img/metrics_gitlab_configuration_settings.png | Bin 0 -> 45148 bytes .../performance/influxdb_configuration.md | 192 +++++++++++++++++++++ doc/monitoring/performance/influxdb_schema.md | 87 ++++++++++ doc/monitoring/performance/introduction.md | 64 +++++++ 11 files changed, 383 insertions(+), 383 deletions(-) delete mode 100644 doc/integration/metrics/gitlab_configuration.md delete mode 100644 doc/integration/metrics/img/metrics_gitlab_configuration_settings.png delete mode 100644 doc/integration/metrics/influxdb_configuration.md delete mode 100644 doc/integration/metrics/influxdb_schema.md delete mode 100644 doc/integration/metrics/introduction.md create mode 100644 doc/monitoring/performance/gitlab_configuration.md create mode 100644 doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png create mode 100644 doc/monitoring/performance/influxdb_configuration.md create mode 100644 doc/monitoring/performance/influxdb_schema.md create mode 100644 doc/monitoring/performance/introduction.md diff --git a/doc/README.md b/doc/README.md index 05c0d6fa0fe..1efed2871f9 100644 --- a/doc/README.md +++ b/doc/README.md @@ -67,7 +67,7 @@ - [Reply by email](incoming_email/README.md) Allow users to comment on issues and merge requests by replying to notification emails. - [Migrate GitLab CI to CE/EE](migrate_ci_to_ce/README.md) Follow this guide to migrate your existing GitLab CI data to GitLab CE/EE. - [Git LFS configuration](workflow/lfs/lfs_administration.md) -- [GitLab Performance Monitoring](integration/metrics/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics +- [GitLab Performance Monitoring](monitoring/performance/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics ## Contributor documentation diff --git a/doc/integration/metrics/gitlab_configuration.md b/doc/integration/metrics/gitlab_configuration.md deleted file mode 100644 index b856e7935a3..00000000000 --- a/doc/integration/metrics/gitlab_configuration.md +++ /dev/null @@ -1,39 +0,0 @@ -# GitLab Configuration - -GitLab Performance Monitoring is disabled by default. To enable it and change any of its -settings, navigate to the Admin area in **Settings > Metrics** -(`/admin/application_settings`). - -The minimum required settings you need to set are the InfluxDB host and port. -Make sure _Enable InfluxDB Metrics_ is checked and hit **Save** to save the -changes. - ---- - -![GitLab Performance Monitoring Admin Settings](img/metrics_gitlab_configuration_settings.png) - ---- - -Finally, a restart of all GitLab processes is required for the changes to take -effect: - -```bash -# For Omnibus installations -sudo gitlab-ctl restart - -# For installations from source -sudo service gitlab restart -``` - -## Pending Migrations - -When any migrations are pending, the metrics are disabled until the migrations -have been performed. - ---- - -Read more on: - -- [Introduction to GitLab Performance Monitoring](introduction.md) -- [InfluxDB Configuration](influxdb_configuration.md) -- [InfluxDB Schema](influxdb_schema.md) diff --git a/doc/integration/metrics/img/metrics_gitlab_configuration_settings.png b/doc/integration/metrics/img/metrics_gitlab_configuration_settings.png deleted file mode 100644 index 14d82b6ac98..00000000000 Binary files a/doc/integration/metrics/img/metrics_gitlab_configuration_settings.png and /dev/null differ diff --git a/doc/integration/metrics/influxdb_configuration.md b/doc/integration/metrics/influxdb_configuration.md deleted file mode 100644 index df5e4af7fad..00000000000 --- a/doc/integration/metrics/influxdb_configuration.md +++ /dev/null @@ -1,192 +0,0 @@ -# InfluxDB Configuration - -The default settings provided by [InfluxDB] are not sufficient for a high traffic -GitLab environment. The settings discussed in this document are based on the -settings GitLab uses for GitLab.com, depending on your own needs you may need to -further adjust them. - -If you are intending to run InfluxDB on the same server as GitLab, make sure -you have plenty of RAM since InfluxDB can use quite a bit depending on traffic. - -Unless you are going with a budget setup, it's advised to run it separately. - -## Requirements - -- InfluxDB 0.9.5 or newer -- A fairly modern version of Linux -- At least 4GB of RAM -- At least 10GB of storage for InfluxDB data - -Note that the RAM and storage requirements can differ greatly depending on the -amount of data received/stored. To limit the amount of stored data users can -look into [InfluxDB Retention Policies][influxdb-retention]. - -## Installation - -Installing InfluxDB is out of the scope of this document. Please refer to the -[InfluxDB documentation]. - -## InfluxDB Server Settings - -Since InfluxDB has many settings that users may wish to customize themselves -(e.g. what port to run InfluxDB on), we'll only cover the essentials. - -The configuration file in question is usually located at -`/etc/influxdb/influxdb.conf`. Whenever you make a change in this file, -InfluxDB needs to be restarted. - -### Storage Engine - -InfluxDB comes with different storage engines and as of InfluxDB 0.9.5 a new -storage engine is available, called [TSM Tree]. All users **must** use the new -`tsm1` storage engine as this [will be the default engine][tsm1-commit] in -upcoming InfluxDB releases. - -Make sure you have the following in your configuration file: - -``` -[data] - dir = "/var/lib/influxdb/data" - engine = "tsm1" -``` - -### Admin Panel - -Production environments should have the InfluxDB admin panel **disabled**. This -feature can be disabled by adding the following to your InfluxDB configuration -file: - -``` -[admin] - enabled = false -``` - -### HTTP - -HTTP is required when using the [InfluxDB CLI] or other tools such as Grafana, -thus it should be enabled. When enabling make sure to _also_ enable -authentication: - -``` -[http] - enabled = true - auth-enabled = true -``` - -_**Note:** Before you enable authentication, you might want to [create an -admin user](#create-a-new-admin-user)._ - -### UDP - -GitLab writes data to InfluxDB via UDP and thus this must be enabled. Enabling -UDP can be done using the following settings: - -``` -[[udp]] - enabled = true - bind-address = ":8089" - database = "gitlab" - batch-size = 1000 - batch-pending = 5 - batch-timeout = "1s" - read-buffer = 209715200 -``` - -This does the following: - -1. Enable UDP and bind it to port 8089 for all addresses. -2. Store any data received in the "gitlab" database. -3. Define a batch of points to be 1000 points in size and allow a maximum of - 5 batches _or_ flush them automatically after 1 second. -4. Define a UDP read buffer size of 200 MB. - -One of the most important settings here is the UDP read buffer size as if this -value is set too low, packets will be dropped. You must also make sure the OS -buffer size is set to the same value, the default value is almost never enough. - -To set the OS buffer size to 200 MB, on Linux you can run the following command: - -```bash -sysctl -w net.core.rmem_max=209715200 -``` - -To make this permanent, add the following to `/etc/sysctl.conf` and restart the -server: - -```bash -net.core.rmem_max=209715200 -``` - -It is **very important** to make sure the buffer sizes are large enough to -handle all data sent to InfluxDB as otherwise you _will_ lose data. The above -buffer sizes are based on the traffic for GitLab.com. Depending on the amount of -traffic, users may be able to use a smaller buffer size, but we highly recommend -using _at least_ 100 MB. - -When enabling UDP, users should take care to not expose the port to the public, -as doing so will allow anybody to write data into your InfluxDB database (as -[InfluxDB's UDP protocol][udp] doesn't support authentication). We recommend either -whitelisting the allowed IP addresses/ranges, or setting up a VLAN and only -allowing traffic from members of said VLAN. - -## Create a new admin user - -If you want to [enable authentication](#http), you might want to [create an -admin user][influx-admin]: - -``` -influx -execute "CREATE USER thedude WITH PASSWORD '1234' WITH ALL PRIVILEGES" -``` - -## Create the `gitlab` database - -Once you get InfluxDB up and running, you need to create a database for GitLab. -Make sure you have changed the [storage engine](#storage-engine) to `tsm1` -before creating a database. - -_**Note:** If you [created an admin user](#create-a-new-admin-user) and enabled -[HTTP authentication](#http), remember to append the username (`-username thedude`) -and password (`-password 1234`) to the commands below._ - -Run the following command to create a database named `gitlab`: - -```bash -influx -execute 'CREATE DATABASE gitlab' -``` - -The name **must** be `gitlab`, do not use any other name. - -Next, make sure that the database was successfully created: - -```bash -influx -execute 'SHOW DATABASES' -``` - -The output should be similar to: - -``` -name: databases ---------------- -name -_internal -gitlab -``` - -That's it! Now your GitLab instance should send data to InfluxDB. - ---- - -Read more on: - -- [Introduction to GitLab Performance Monitoring](introduction.md) -- [GitLab Configuration](gitlab_configuration.md) -- [InfluxDB Schema](influxdb_schema.md) - -[influxdb-retention]: https://docs.influxdata.com/influxdb/v0.9/query_language/database_management/#retention-policy-management -[influxdb documentation]: https://docs.influxdata.com/influxdb/v0.9/ -[influxdb cli]: https://docs.influxdata.com/influxdb/v0.9/tools/shell/ -[udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/ -[influxdb]: https://influxdata.com/time-series-platform/influxdb/ -[tsm tree]: https://influxdata.com/blog/new-storage-engine-time-structured-merge-tree/ -[tsm1-commit]: https://github.com/influxdata/influxdb/commit/15d723dc77651bac83e09e2b1c94be480966cb0d -[influx-admin]: https://docs.influxdata.com/influxdb/v0.9/administration/authentication_and_authorization/#create-a-new-admin-user diff --git a/doc/integration/metrics/influxdb_schema.md b/doc/integration/metrics/influxdb_schema.md deleted file mode 100644 index a5a8aebd2d1..00000000000 --- a/doc/integration/metrics/influxdb_schema.md +++ /dev/null @@ -1,87 +0,0 @@ -# InfluxDB Schema - -The following measurements are currently stored in InfluxDB: - -- `PROCESS_file_descriptors` -- `PROCESS_gc_statistics` -- `PROCESS_memory_usage` -- `PROCESS_method_calls` -- `PROCESS_object_counts` -- `PROCESS_transactions` -- `PROCESS_views` - -Here, `PROCESS` is replaced with either `rails` or `sidekiq` depending on the -process type. In all series, any form of duration is stored in milliseconds. - -## PROCESS_file_descriptors - -This measurement contains the number of open file descriptors over time. The -value field `value` contains the number of descriptors. - -## PROCESS_gc_statistics - -This measurement contains Ruby garbage collection statistics such as the amount -of minor/major GC runs (relative to the last sampling interval), the time spent -in garbage collection cycles, and all fields/values returned by `GC.stat`. - -## PROCESS_memory_usage - -This measurement contains the process' memory usage (in bytes) over time. The -value field `value` contains the number of bytes. - -## PROCESS_method_calls - -This measurement contains the methods called during a transaction along with -their duration, and a name of the transaction action that invoked the method (if -available). The method call duration is stored in the value field `duration`, -while the method name is stored in the tag `method`. The tag `action` contains -the full name of the transaction action. Both the `method` and `action` fields -are in the following format: - -``` -ClassName#method_name -``` - -For example, a method called by the `show` method in the `UsersController` class -would have `action` set to `UsersController#show`. - -## PROCESS_object_counts - -This measurement is used to store retained Ruby objects (per class) and the -amount of retained objects. The number of objects is stored in the `count` value -field while the class name is stored in the `type` tag. - -## PROCESS_transactions - -This measurement is used to store basic transaction details such as the time it -took to complete a transaction, how much time was spent in SQL queries, etc. The -following value fields are available: - -| Value | Description | -| ----- | ----------- | -| `duration` | The total duration of the transaction | -| `allocated_memory` | The amount of bytes allocated while the transaction was running. This value is only reliable when using single-threaded application servers | -| `method_duration` | The total time spent in method calls | -| `sql_duration` | The total time spent in SQL queries | -| `view_duration` | The total time spent in views | - -## PROCESS_views - -This measurement is used to store view rendering timings for a transaction. The -following value fields are available: - -| Value | Description | -| ----- | ----------- | -| `duration` | The rendering time of the view | -| `view` | The path of the view, relative to the application's root directory | - -The `action` tag contains the action name of the transaction that rendered the -view. - ---- - -Read more on: - -- [Introduction to GitLab Performance Monitoring](introduction.md) -- [GitLab Configuration](gitlab_configuration.md) -- [InfluxDB Configuration](influxdb_configuration.md) diff --git a/doc/integration/metrics/introduction.md b/doc/integration/metrics/introduction.md deleted file mode 100644 index f2460d31302..00000000000 --- a/doc/integration/metrics/introduction.md +++ /dev/null @@ -1,64 +0,0 @@ -# GitLab Performance Monitoring - -GitLab comes with its own application performance measuring system as of GitLab -8.4, simply called "GitLab Performance Monitoring". GitLab Performance Monitoring is available in both the -Community and Enterprise editions. - -Apart from this introduction, you are advised to read through the following -documents in order to understand and properly configure GitLab Performance Monitoring: - -- [GitLab Configuration](gitlab_configuration.md) -- [InfluxDB Configuration](influxdb_configuration.md) -- [InfluxDB Schema](influxdb_schema.md) - -## Introduction to GitLab Performance Monitoring - -GitLab Performance Monitoring makes it possible to measure a wide variety of statistics -including (but not limited to): - -- The time it took to complete a transaction (a web request or Sidekiq job). -- The time spent in running SQL queries and rendering HAML views. -- The time spent executing (instrumented) Ruby methods. -- Ruby object allocations, and retained objects in particular. -- System statistics such as the process' memory usage and open file descriptors. -- Ruby garbage collection statistics. - -Metrics data is written to [InfluxDB][influxdb] over [UDP][influxdb-udp]. Stored -data can be visualized using [Grafana][grafana] or any other application that -supports reading data from InfluxDB. Alternatively data can be queried using the -InfluxDB CLI. - -## Metric Types - -Two types of metrics are collected: - -1. Transaction specific metrics. -1. Sampled metrics, collected at a certain interval in a separate thread. - -### Transaction Metrics - -Transaction metrics are metrics that can be associated with a single -transaction. This includes statistics such as the transaction duration, timings -of any executed SQL queries, time spent rendering HAML views, etc. These metrics -are collected for every Rack request and Sidekiq job processed. - -### Sampled Metrics - -Sampled metrics are metrics that can't be associated with a single transaction. -Examples include garbage collection statistics and retained Ruby objects. These -metrics are collected at a regular interval. This interval is made up out of two -parts: - -1. A user defined interval. -1. A randomly generated offset added on top of the interval, the same offset - can't be used twice in a row. - -The actual interval can be anywhere between a half of the defined interval and a -half above the interval. For example, for a user defined interval of 15 seconds -the actual interval can be anywhere between 7.5 and 22.5. The interval is -re-generated for every sampling run instead of being generated once and re-used -for the duration of the process' lifetime. - -[influxdb]: https://influxdata.com/time-series-platform/influxdb/ -[influxdb-udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/ -[grafana]: http://grafana.org/ diff --git a/doc/monitoring/performance/gitlab_configuration.md b/doc/monitoring/performance/gitlab_configuration.md new file mode 100644 index 00000000000..b856e7935a3 --- /dev/null +++ b/doc/monitoring/performance/gitlab_configuration.md @@ -0,0 +1,39 @@ +# GitLab Configuration + +GitLab Performance Monitoring is disabled by default. To enable it and change any of its +settings, navigate to the Admin area in **Settings > Metrics** +(`/admin/application_settings`). + +The minimum required settings you need to set are the InfluxDB host and port. +Make sure _Enable InfluxDB Metrics_ is checked and hit **Save** to save the +changes. + +--- + +![GitLab Performance Monitoring Admin Settings](img/metrics_gitlab_configuration_settings.png) + +--- + +Finally, a restart of all GitLab processes is required for the changes to take +effect: + +```bash +# For Omnibus installations +sudo gitlab-ctl restart + +# For installations from source +sudo service gitlab restart +``` + +## Pending Migrations + +When any migrations are pending, the metrics are disabled until the migrations +have been performed. + +--- + +Read more on: + +- [Introduction to GitLab Performance Monitoring](introduction.md) +- [InfluxDB Configuration](influxdb_configuration.md) +- [InfluxDB Schema](influxdb_schema.md) diff --git a/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png b/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png new file mode 100644 index 00000000000..14d82b6ac98 Binary files /dev/null and b/doc/monitoring/performance/img/metrics_gitlab_configuration_settings.png differ diff --git a/doc/monitoring/performance/influxdb_configuration.md b/doc/monitoring/performance/influxdb_configuration.md new file mode 100644 index 00000000000..df5e4af7fad --- /dev/null +++ b/doc/monitoring/performance/influxdb_configuration.md @@ -0,0 +1,192 @@ +# InfluxDB Configuration + +The default settings provided by [InfluxDB] are not sufficient for a high traffic +GitLab environment. The settings discussed in this document are based on the +settings GitLab uses for GitLab.com, depending on your own needs you may need to +further adjust them. + +If you are intending to run InfluxDB on the same server as GitLab, make sure +you have plenty of RAM since InfluxDB can use quite a bit depending on traffic. + +Unless you are going with a budget setup, it's advised to run it separately. + +## Requirements + +- InfluxDB 0.9.5 or newer +- A fairly modern version of Linux +- At least 4GB of RAM +- At least 10GB of storage for InfluxDB data + +Note that the RAM and storage requirements can differ greatly depending on the +amount of data received/stored. To limit the amount of stored data users can +look into [InfluxDB Retention Policies][influxdb-retention]. + +## Installation + +Installing InfluxDB is out of the scope of this document. Please refer to the +[InfluxDB documentation]. + +## InfluxDB Server Settings + +Since InfluxDB has many settings that users may wish to customize themselves +(e.g. what port to run InfluxDB on), we'll only cover the essentials. + +The configuration file in question is usually located at +`/etc/influxdb/influxdb.conf`. Whenever you make a change in this file, +InfluxDB needs to be restarted. + +### Storage Engine + +InfluxDB comes with different storage engines and as of InfluxDB 0.9.5 a new +storage engine is available, called [TSM Tree]. All users **must** use the new +`tsm1` storage engine as this [will be the default engine][tsm1-commit] in +upcoming InfluxDB releases. + +Make sure you have the following in your configuration file: + +``` +[data] + dir = "/var/lib/influxdb/data" + engine = "tsm1" +``` + +### Admin Panel + +Production environments should have the InfluxDB admin panel **disabled**. This +feature can be disabled by adding the following to your InfluxDB configuration +file: + +``` +[admin] + enabled = false +``` + +### HTTP + +HTTP is required when using the [InfluxDB CLI] or other tools such as Grafana, +thus it should be enabled. When enabling make sure to _also_ enable +authentication: + +``` +[http] + enabled = true + auth-enabled = true +``` + +_**Note:** Before you enable authentication, you might want to [create an +admin user](#create-a-new-admin-user)._ + +### UDP + +GitLab writes data to InfluxDB via UDP and thus this must be enabled. Enabling +UDP can be done using the following settings: + +``` +[[udp]] + enabled = true + bind-address = ":8089" + database = "gitlab" + batch-size = 1000 + batch-pending = 5 + batch-timeout = "1s" + read-buffer = 209715200 +``` + +This does the following: + +1. Enable UDP and bind it to port 8089 for all addresses. +2. Store any data received in the "gitlab" database. +3. Define a batch of points to be 1000 points in size and allow a maximum of + 5 batches _or_ flush them automatically after 1 second. +4. Define a UDP read buffer size of 200 MB. + +One of the most important settings here is the UDP read buffer size as if this +value is set too low, packets will be dropped. You must also make sure the OS +buffer size is set to the same value, the default value is almost never enough. + +To set the OS buffer size to 200 MB, on Linux you can run the following command: + +```bash +sysctl -w net.core.rmem_max=209715200 +``` + +To make this permanent, add the following to `/etc/sysctl.conf` and restart the +server: + +```bash +net.core.rmem_max=209715200 +``` + +It is **very important** to make sure the buffer sizes are large enough to +handle all data sent to InfluxDB as otherwise you _will_ lose data. The above +buffer sizes are based on the traffic for GitLab.com. Depending on the amount of +traffic, users may be able to use a smaller buffer size, but we highly recommend +using _at least_ 100 MB. + +When enabling UDP, users should take care to not expose the port to the public, +as doing so will allow anybody to write data into your InfluxDB database (as +[InfluxDB's UDP protocol][udp] doesn't support authentication). We recommend either +whitelisting the allowed IP addresses/ranges, or setting up a VLAN and only +allowing traffic from members of said VLAN. + +## Create a new admin user + +If you want to [enable authentication](#http), you might want to [create an +admin user][influx-admin]: + +``` +influx -execute "CREATE USER thedude WITH PASSWORD '1234' WITH ALL PRIVILEGES" +``` + +## Create the `gitlab` database + +Once you get InfluxDB up and running, you need to create a database for GitLab. +Make sure you have changed the [storage engine](#storage-engine) to `tsm1` +before creating a database. + +_**Note:** If you [created an admin user](#create-a-new-admin-user) and enabled +[HTTP authentication](#http), remember to append the username (`-username thedude`) +and password (`-password 1234`) to the commands below._ + +Run the following command to create a database named `gitlab`: + +```bash +influx -execute 'CREATE DATABASE gitlab' +``` + +The name **must** be `gitlab`, do not use any other name. + +Next, make sure that the database was successfully created: + +```bash +influx -execute 'SHOW DATABASES' +``` + +The output should be similar to: + +``` +name: databases +--------------- +name +_internal +gitlab +``` + +That's it! Now your GitLab instance should send data to InfluxDB. + +--- + +Read more on: + +- [Introduction to GitLab Performance Monitoring](introduction.md) +- [GitLab Configuration](gitlab_configuration.md) +- [InfluxDB Schema](influxdb_schema.md) + +[influxdb-retention]: https://docs.influxdata.com/influxdb/v0.9/query_language/database_management/#retention-policy-management +[influxdb documentation]: https://docs.influxdata.com/influxdb/v0.9/ +[influxdb cli]: https://docs.influxdata.com/influxdb/v0.9/tools/shell/ +[udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/ +[influxdb]: https://influxdata.com/time-series-platform/influxdb/ +[tsm tree]: https://influxdata.com/blog/new-storage-engine-time-structured-merge-tree/ +[tsm1-commit]: https://github.com/influxdata/influxdb/commit/15d723dc77651bac83e09e2b1c94be480966cb0d +[influx-admin]: https://docs.influxdata.com/influxdb/v0.9/administration/authentication_and_authorization/#create-a-new-admin-user diff --git a/doc/monitoring/performance/influxdb_schema.md b/doc/monitoring/performance/influxdb_schema.md new file mode 100644 index 00000000000..a5a8aebd2d1 --- /dev/null +++ b/doc/monitoring/performance/influxdb_schema.md @@ -0,0 +1,87 @@ +# InfluxDB Schema + +The following measurements are currently stored in InfluxDB: + +- `PROCESS_file_descriptors` +- `PROCESS_gc_statistics` +- `PROCESS_memory_usage` +- `PROCESS_method_calls` +- `PROCESS_object_counts` +- `PROCESS_transactions` +- `PROCESS_views` + +Here, `PROCESS` is replaced with either `rails` or `sidekiq` depending on the +process type. In all series, any form of duration is stored in milliseconds. + +## PROCESS_file_descriptors + +This measurement contains the number of open file descriptors over time. The +value field `value` contains the number of descriptors. + +## PROCESS_gc_statistics + +This measurement contains Ruby garbage collection statistics such as the amount +of minor/major GC runs (relative to the last sampling interval), the time spent +in garbage collection cycles, and all fields/values returned by `GC.stat`. + +## PROCESS_memory_usage + +This measurement contains the process' memory usage (in bytes) over time. The +value field `value` contains the number of bytes. + +## PROCESS_method_calls + +This measurement contains the methods called during a transaction along with +their duration, and a name of the transaction action that invoked the method (if +available). The method call duration is stored in the value field `duration`, +while the method name is stored in the tag `method`. The tag `action` contains +the full name of the transaction action. Both the `method` and `action` fields +are in the following format: + +``` +ClassName#method_name +``` + +For example, a method called by the `show` method in the `UsersController` class +would have `action` set to `UsersController#show`. + +## PROCESS_object_counts + +This measurement is used to store retained Ruby objects (per class) and the +amount of retained objects. The number of objects is stored in the `count` value +field while the class name is stored in the `type` tag. + +## PROCESS_transactions + +This measurement is used to store basic transaction details such as the time it +took to complete a transaction, how much time was spent in SQL queries, etc. The +following value fields are available: + +| Value | Description | +| ----- | ----------- | +| `duration` | The total duration of the transaction | +| `allocated_memory` | The amount of bytes allocated while the transaction was running. This value is only reliable when using single-threaded application servers | +| `method_duration` | The total time spent in method calls | +| `sql_duration` | The total time spent in SQL queries | +| `view_duration` | The total time spent in views | + +## PROCESS_views + +This measurement is used to store view rendering timings for a transaction. The +following value fields are available: + +| Value | Description | +| ----- | ----------- | +| `duration` | The rendering time of the view | +| `view` | The path of the view, relative to the application's root directory | + +The `action` tag contains the action name of the transaction that rendered the +view. + +--- + +Read more on: + +- [Introduction to GitLab Performance Monitoring](introduction.md) +- [GitLab Configuration](gitlab_configuration.md) +- [InfluxDB Configuration](influxdb_configuration.md) diff --git a/doc/monitoring/performance/introduction.md b/doc/monitoring/performance/introduction.md new file mode 100644 index 00000000000..f2460d31302 --- /dev/null +++ b/doc/monitoring/performance/introduction.md @@ -0,0 +1,64 @@ +# GitLab Performance Monitoring + +GitLab comes with its own application performance measuring system as of GitLab +8.4, simply called "GitLab Performance Monitoring". GitLab Performance Monitoring is available in both the +Community and Enterprise editions. + +Apart from this introduction, you are advised to read through the following +documents in order to understand and properly configure GitLab Performance Monitoring: + +- [GitLab Configuration](gitlab_configuration.md) +- [InfluxDB Configuration](influxdb_configuration.md) +- [InfluxDB Schema](influxdb_schema.md) + +## Introduction to GitLab Performance Monitoring + +GitLab Performance Monitoring makes it possible to measure a wide variety of statistics +including (but not limited to): + +- The time it took to complete a transaction (a web request or Sidekiq job). +- The time spent in running SQL queries and rendering HAML views. +- The time spent executing (instrumented) Ruby methods. +- Ruby object allocations, and retained objects in particular. +- System statistics such as the process' memory usage and open file descriptors. +- Ruby garbage collection statistics. + +Metrics data is written to [InfluxDB][influxdb] over [UDP][influxdb-udp]. Stored +data can be visualized using [Grafana][grafana] or any other application that +supports reading data from InfluxDB. Alternatively data can be queried using the +InfluxDB CLI. + +## Metric Types + +Two types of metrics are collected: + +1. Transaction specific metrics. +1. Sampled metrics, collected at a certain interval in a separate thread. + +### Transaction Metrics + +Transaction metrics are metrics that can be associated with a single +transaction. This includes statistics such as the transaction duration, timings +of any executed SQL queries, time spent rendering HAML views, etc. These metrics +are collected for every Rack request and Sidekiq job processed. + +### Sampled Metrics + +Sampled metrics are metrics that can't be associated with a single transaction. +Examples include garbage collection statistics and retained Ruby objects. These +metrics are collected at a regular interval. This interval is made up out of two +parts: + +1. A user defined interval. +1. A randomly generated offset added on top of the interval, the same offset + can't be used twice in a row. + +The actual interval can be anywhere between a half of the defined interval and a +half above the interval. For example, for a user defined interval of 15 seconds +the actual interval can be anywhere between 7.5 and 22.5. The interval is +re-generated for every sampling run instead of being generated once and re-used +for the duration of the process' lifetime. + +[influxdb]: https://influxdata.com/time-series-platform/influxdb/ +[influxdb-udp]: https://docs.influxdata.com/influxdb/v0.9/write_protocols/udp/ +[grafana]: http://grafana.org/ -- cgit v1.2.1 From 096485ef65ffce7d31d0cefe530cc1b5c1825b52 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 20 Jan 2016 16:55:47 -0200 Subject: Creator should be added as a master of the project on creation This also enable a project creator to add themselves as a master of the project. --- app/models/member.rb | 7 ++++++- app/services/projects/create_service.rb | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index 28aee2e3799..34efcd0088d 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -91,7 +91,7 @@ class Member < ActiveRecord::Base member.invite_email = user end - if can_update_member?(current_user, member) + if can_update_member?(current_user, member) || project_creator?(member, access_level) member.created_by ||= current_user member.access_level = access_level @@ -107,6 +107,11 @@ class Member < ActiveRecord::Base current_user.can?(:update_group_member, member) || current_user.can?(:update_project_member, member) end + + def project_creator?(member, access_level) + member.new_record? && member.owner? && + access_level.to_i == ProjectMember::MASTER + end end def invite? diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index c94d7ab710f..a6820183bee 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -95,7 +95,7 @@ module Projects system_hook_service.execute_hooks_for(@project, :create) unless @project.group - @project.team << [current_user, :master] + @project.team << [current_user, :master, current_user] end @project.import_start if @project.import? -- cgit v1.2.1 From dd59fc213c6cf2a2efb39eda241f453bbd1e82c7 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Wed, 20 Jan 2016 23:10:27 +0100 Subject: Change InfluxDB admin username [ci skip] --- doc/monitoring/performance/influxdb_configuration.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/monitoring/performance/influxdb_configuration.md b/doc/monitoring/performance/influxdb_configuration.md index df5e4af7fad..3a2b598b78f 100644 --- a/doc/monitoring/performance/influxdb_configuration.md +++ b/doc/monitoring/performance/influxdb_configuration.md @@ -135,7 +135,7 @@ If you want to [enable authentication](#http), you might want to [create an admin user][influx-admin]: ``` -influx -execute "CREATE USER thedude WITH PASSWORD '1234' WITH ALL PRIVILEGES" +influx -execute "CREATE USER jeff WITH PASSWORD '1234' WITH ALL PRIVILEGES" ``` ## Create the `gitlab` database @@ -145,8 +145,8 @@ Make sure you have changed the [storage engine](#storage-engine) to `tsm1` before creating a database. _**Note:** If you [created an admin user](#create-a-new-admin-user) and enabled -[HTTP authentication](#http), remember to append the username (`-username thedude`) -and password (`-password 1234`) to the commands below._ +[HTTP authentication](#http), remember to append the username (`-username `) +and password (`-password `) you set earlier to the commands below._ Run the following command to create a database named `gitlab`: -- cgit v1.2.1 From c45a6bf3ba13cbd532852dfcc48ef3fd7aa545e4 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 14 Jan 2016 17:52:59 +0100 Subject: Added cache:key to .gitlab-ci.yml allowing to fine tune the caching --- CHANGELOG | 1 + doc/ci/yaml/README.md | 60 ++++++++++++++++++++++++++-- lib/ci/gitlab_ci_yaml_processor.rb | 8 ++++ spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 25 ++++++++++-- 4 files changed, 86 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 9490540f1b1..e7c7e65ac4a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -74,6 +74,7 @@ v 8.4.0 (unreleased) - Fix: Creator should be added as a master of the project on creation - Added X-GitLab-... headers to emails from CI and Email On Push services (Anton Baklanov) - Add IP check against DNSBLs at account sign-up + - Added cache:key to .gitlab-ci.yml allowing to fine tune the caching v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index fd0d49de4e4..3b594df659d 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -135,10 +135,9 @@ thus allowing to fine tune them. ### cache `cache` is used to specify a list of files and directories which should be -cached between builds. Caches are stored according to the branch/ref and the -job name. They are not currently shared between different job names or between -branches/refs, which means that caching will benefit you if you push subsequent -commits to an existing feature branch. +cached between builds. + +**By default the caching is enabled per-job and per-branch.** If `cache` is defined outside the scope of the jobs, it means it is set globally and all jobs will use its definition. @@ -152,6 +151,59 @@ cache: - binaries/ ``` +#### cache:key + +_**Note:** Introduced in GitLab Runner v1.0.0._ + +The `key` directive allows you to define the affinity of caching +between jobs, allowing to have a single cache for all jobs, +cache per-job, cache per-branch or any other way you deem proper. + +This allows you to fine tune caching, allowing you to cache data between different jobs or even different branches. +The `cache:key` variable can use any of the [predefined variables](../variables/README.md): + +Example configurations: + +To enable per-job caching: + + ```yaml + cache: + key: "$CI_BUILD_NAME" + untracked: true + ``` + +To enable per-branch caching: + + ```yaml + cache: + key: "$CI_BUILD_REF_NAME" + untracked: true + ``` + +To enable per-job and per-branch caching: + + ```yaml + cache: + key: "$CI_BUILD_NAME/$CI_BUILD_REF_NAME" + untracked: true + ``` + +To enable per-branch and per-stage caching: + + ```yaml + cache: + key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME" + untracked: true + ``` + +If you use **Windows Batch** to run your shell scripts you need to replace the `$` with `%`: + + ```yaml + cache: + key: "%CI_BUILD_STAGE%/%CI_BUILD_REF_NAME%" + untracked: true + ``` + ## Jobs `.gitlab-ci.yml` allows you to specify an unlimited number of jobs. Each job diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index bcdfd38d292..1a3f662811a 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -115,6 +115,10 @@ module Ci end if @cache + if @cache[:key] && !validate_string(@cache[:key]) + raise ValidationError, "cache:key parameter should be a string" + end + if @cache[:untracked] && !validate_boolean(@cache[:untracked]) raise ValidationError, "cache:untracked parameter should be an boolean" end @@ -198,6 +202,10 @@ module Ci end def validate_job_cache!(name, job) + if job[:cache][:key] && !validate_string(job[:cache][:key]) + raise ValidationError, "#{name} job: cache:key parameter should be a string" + end + if job[:cache][:untracked] && !validate_boolean(job[:cache][:untracked]) raise ValidationError, "#{name} job: cache:untracked parameter should be an boolean" end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index d15100fc6d8..f3394910c5b 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -336,7 +336,7 @@ module Ci describe "Caches" do it "returns cache when defined globally" do config = YAML.dump({ - cache: { paths: ["logs/", "binaries/"], untracked: true }, + cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'key' }, rspec: { script: "rspec" } @@ -348,13 +348,14 @@ module Ci expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq( paths: ["logs/", "binaries/"], untracked: true, + key: 'key', ) end it "returns cache when defined in a job" do config = YAML.dump({ rspec: { - cache: { paths: ["logs/", "binaries/"], untracked: true }, + cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'key' }, script: "rspec" } }) @@ -365,15 +366,16 @@ module Ci expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq( paths: ["logs/", "binaries/"], untracked: true, + key: 'key', ) end it "overwrite cache when defined for a job and globally" do config = YAML.dump({ - cache: { paths: ["logs/", "binaries/"], untracked: true }, + cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'global' }, rspec: { script: "rspec", - cache: { paths: ["test/"], untracked: false }, + cache: { paths: ["test/"], untracked: false, key: 'local' }, } }) @@ -383,6 +385,7 @@ module Ci expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq( paths: ["test/"], untracked: false, + key: 'local', ) end end @@ -615,6 +618,20 @@ module Ci end.to raise_error(GitlabCiYamlProcessor::ValidationError, "cache:paths parameter should be an array of strings") end + it "returns errors if cache:key is not a string" do + config = YAML.dump({ cache: { key: 1 }, rspec: { script: "test" } }) + expect do + GitlabCiYamlProcessor.new(config) + end.to raise_error(GitlabCiYamlProcessor::ValidationError, "cache:key parameter should be a string") + end + + it "returns errors if job cache:key is not an a string" do + config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", cache: { key: 1 } } }) + expect do + GitlabCiYamlProcessor.new(config) + end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:key parameter should be a string") + end + it "returns errors if job cache:untracked is not an array of strings" do config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", cache: { untracked: "string" } } }) expect do -- cgit v1.2.1 From 3ae0ca8941603d974c3242881d4248b9c8af00da Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 20 Jan 2016 17:47:18 -0500 Subject: Update CHANGELOG [ci skip] --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 9490540f1b1..704950231d4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,7 @@ v 8.4.0 (unreleased) - Autocomplete data is now always loaded, instead of when focusing a comment text area - Improved performance of finding issues for an entire group - Added custom application performance measuring system powered by InfluxDB + - Add syntax highlighting to diffs - Gracefully handle invalid UTF-8 sequences in Markdown links (Stan Hu) - Bump fog to 1.36.0 (Stan Hu) - Add user's last used IP addresses to admin page (Stan Hu) -- cgit v1.2.1 From 3a6fac4a852c96391ba9f1eea57a873f1a13e12f Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 20 Jan 2016 18:00:29 -0500 Subject: Remove Performance Monitoring from Integration docs [ci skip] --- doc/integration/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/integration/README.md b/doc/integration/README.md index 297e4f6e7bf..5edac746c7b 100644 --- a/doc/integration/README.md +++ b/doc/integration/README.md @@ -15,7 +15,6 @@ See the documentation below for details on how to configure these services. - [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages - [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users -- [GitLab Performance Monitoring](metrics/introduction.md) Configure GitLab and InfluxDB for measuring performance metrics GitLab Enterprise Edition contains [advanced Jenkins support][jenkins]. -- cgit v1.2.1 From 8367e4abebcf23a6be830db57193417d3efe20b5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 20 Jan 2016 09:42:13 -0800 Subject: Implement new UI for pagination --- CHANGELOG | 1 + app/assets/stylesheets/framework/pagination.scss | 29 +++------------------- .../framework/tw_bootstrap_variables.scss | 22 ++++++++-------- app/views/kaminari/gitlab/_next_page.html.haml | 8 ++++-- app/views/kaminari/gitlab/_paginator.html.haml | 4 +-- app/views/kaminari/gitlab/_prev_page.html.haml | 8 ++++-- app/views/projects/issues/_issues.html.haml | 5 ---- .../merge_requests/_merge_requests.html.haml | 5 ---- config/locales/en.yml | 4 +++ 9 files changed, 33 insertions(+), 53 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 704950231d4..79d4b5f94c8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.5.0 (unreleased) - Add "visibility" flag to GET /projects api endpoint - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push + - New UI for pagination v 8.4.0 (unreleased) - Allow LDAP users to change their email if it was not set by the LDAP server diff --git a/app/assets/stylesheets/framework/pagination.scss b/app/assets/stylesheets/framework/pagination.scss index 2cd30491bf5..8a5bde83335 100644 --- a/app/assets/stylesheets/framework/pagination.scss +++ b/app/assets/stylesheets/framework/pagination.scss @@ -1,35 +1,12 @@ .gl-pagination { + text-align: center; + width: 100%; border-top: 1px solid $border-color; - background-color: $background-color; - margin: -$gl-padding; + margin: 0; margin-top: 0; .pagination { padding: 0; - margin: 0; - display: block; - - li.first, - li.last, - li.next, - li.prev { - > a { - color: $link-color; - - &:hover { - color: #fff; - } - } - } - - li > a, - li > span { - border: none; - margin: 0; - @include border-radius(0 !important); - padding: 13px 19px; - border-right: 1px solid $border-color; - } } } diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss index cd0621cdbf3..798cd224ad0 100644 --- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss +++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss @@ -66,20 +66,20 @@ $legend-color: $text-color; //## $pagination-color: $gl-gray; -$pagination-bg: $background-color; -$pagination-border: transparent; +$pagination-bg: #fff; +$pagination-border: $border-color; -$pagination-hover-color: #fff; -$pagination-hover-bg: $brand-info; -$pagination-hover-border: transparent; +$pagination-hover-color: $gl-gray; +$pagination-hover-bg: $hover; +$pagination-hover-border: $border-color; -$pagination-active-color: #fff; -$pagination-active-bg: $brand-info; -$pagination-active-border: transparent; +$pagination-active-color: $blue-dark; +$pagination-active-bg: #fff; +$pagination-active-border: $border-color; -$pagination-disabled-color: #fff; -$pagination-disabled-bg: lighten($brand-info, 15%); -$pagination-disabled-border: transparent; +$pagination-disabled-color: #cdcdcd; +$pagination-disabled-bg: $background-color; +$pagination-disabled-border: $border-color; //== Form states and alerts diff --git a/app/views/kaminari/gitlab/_next_page.html.haml b/app/views/kaminari/gitlab/_next_page.html.haml index 00c5f0b6f4e..c805914fc3f 100644 --- a/app/views/kaminari/gitlab/_next_page.html.haml +++ b/app/views/kaminari/gitlab/_next_page.html.haml @@ -5,5 +5,9 @@ -# num_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%li.next - = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, rel: 'next', remote: remote +- if current_page.last? + %li{ class: "next disabled" } + %span= raw(t 'views.pagination.next') +- else + %li{ class: "next" } + = link_to raw(t 'views.pagination.next'), url, rel: 'next', remote: remote diff --git a/app/views/kaminari/gitlab/_paginator.html.haml b/app/views/kaminari/gitlab/_paginator.html.haml index 2f645186921..a12c53bcfe7 100644 --- a/app/views/kaminari/gitlab/_paginator.html.haml +++ b/app/views/kaminari/gitlab/_paginator.html.haml @@ -10,13 +10,13 @@ %ul.pagination.clearfix - unless current_page.first? = first_page_tag unless num_pages < 5 # As kaminari will always show the first 5 pages - = prev_page_tag + = prev_page_tag - each_page do |page| - if page.left_outer? || page.right_outer? || page.inside_window? = page_tag page - elsif !page.was_truncated? = gap_tag + = next_page_tag - unless current_page.last? - = next_page_tag = last_page_tag unless num_pages < 5 diff --git a/app/views/kaminari/gitlab/_prev_page.html.haml b/app/views/kaminari/gitlab/_prev_page.html.haml index f673abdb3ae..afb20455e0a 100644 --- a/app/views/kaminari/gitlab/_prev_page.html.haml +++ b/app/views/kaminari/gitlab/_prev_page.html.haml @@ -5,5 +5,9 @@ -# num_pages: total number of pages -# per_page: number of items to fetch per page -# remote: data-remote -%li{class: "prev" } - = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote +- if current_page.first? + %li{ class: "prev disabled" } + %span= raw(t 'views.pagination.previous') +- else + %li{ class: "prev" } + = link_to raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml index e0e89b764d5..f34f3c05737 100644 --- a/app/views/projects/issues/_issues.html.haml +++ b/app/views/projects/issues/_issues.html.haml @@ -5,9 +5,4 @@ .nothing-here-block No issues to show - if @issues.present? - .issuable-filter-count - %span.pull-right - = number_with_delimiter(@issues.total_count) - issues for this filter - = paginate @issues, theme: "gitlab" diff --git a/app/views/projects/merge_requests/_merge_requests.html.haml b/app/views/projects/merge_requests/_merge_requests.html.haml index 29d09d0a652..5473fa19166 100644 --- a/app/views/projects/merge_requests/_merge_requests.html.haml +++ b/app/views/projects/merge_requests/_merge_requests.html.haml @@ -5,10 +5,5 @@ .nothing-here-block No merge requests to show - if @merge_requests.present? - .issuable-filter-count - %span.pull-right - = number_with_delimiter(@merge_requests.total_count) - merge requests for this filter - = paginate @merge_requests, theme: "gitlab" diff --git a/config/locales/en.yml b/config/locales/en.yml index f6cfb5efd2a..cedb5e207bd 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -8,3 +8,7 @@ en: wrong_size: "is the wrong size (should be %{file_size})" size_too_small: "is too small (should be at least %{file_size})" size_too_big: "is too big (should be at most %{file_size})" + views: + pagination: + previous: "Prev" + next: "Next" -- cgit v1.2.1 From ceab12866f55b422bee4ad3d6828d08abce8b874 Mon Sep 17 00:00:00 2001 From: Jacob Schatz Date: Wed, 20 Jan 2016 21:25:26 -0500 Subject: Removes 100% width because it is a block element. --- app/assets/stylesheets/framework/pagination.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/stylesheets/framework/pagination.scss b/app/assets/stylesheets/framework/pagination.scss index 8a5bde83335..b6f21fd8c91 100644 --- a/app/assets/stylesheets/framework/pagination.scss +++ b/app/assets/stylesheets/framework/pagination.scss @@ -1,6 +1,5 @@ .gl-pagination { text-align: center; - width: 100%; border-top: 1px solid $border-color; margin: 0; margin-top: 0; -- cgit v1.2.1 From fe4affcc3ff9c315e95a0ac36513e1558c5c8b43 Mon Sep 17 00:00:00 2001 From: Pirate Praveen Date: Tue, 15 Dec 2015 06:04:53 -0500 Subject: add execution permission for script --- Rakefile | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 Rakefile diff --git a/Rakefile b/Rakefile old mode 100644 new mode 100755 -- cgit v1.2.1 From 33a5bbcf2f4fe9cf4ea1faf7bf6aeae5fc2810d5 Mon Sep 17 00:00:00 2001 From: Pirate Praveen Date: Thu, 21 Jan 2016 01:29:16 -0500 Subject: remove execution permissions from fonts --- app/assets/fonts/OFL.txt | 0 app/assets/fonts/SourceSansPro-Black.ttf.woff | Bin app/assets/fonts/SourceSansPro-Black.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-BlackIt.ttf.woff | Bin app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-Bold.ttf.woff | Bin app/assets/fonts/SourceSansPro-Bold.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-BoldIt.ttf.woff | Bin app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff | Bin app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff | Bin app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-It.ttf.woff | Bin app/assets/fonts/SourceSansPro-It.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-Light.ttf.woff | Bin app/assets/fonts/SourceSansPro-Light.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-LightIt.ttf.woff | Bin app/assets/fonts/SourceSansPro-LightIt.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-Regular.ttf.woff | Bin app/assets/fonts/SourceSansPro-Regular.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-Semibold.ttf.woff | Bin app/assets/fonts/SourceSansPro-Semibold.ttf.woff2 | Bin app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff | Bin app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2 | Bin 25 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 app/assets/fonts/OFL.txt mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Black.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Black.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-BlackIt.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Bold.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Bold.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-BoldIt.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-It.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-It.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Light.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Light.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-LightIt.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-LightIt.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Regular.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Regular.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Semibold.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-Semibold.ttf.woff2 mode change 100755 => 100644 app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff mode change 100755 => 100644 app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2 diff --git a/app/assets/fonts/OFL.txt b/app/assets/fonts/OFL.txt old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Black.ttf.woff b/app/assets/fonts/SourceSansPro-Black.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Black.ttf.woff2 b/app/assets/fonts/SourceSansPro-Black.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-BlackIt.ttf.woff b/app/assets/fonts/SourceSansPro-BlackIt.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Bold.ttf.woff b/app/assets/fonts/SourceSansPro-Bold.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Bold.ttf.woff2 b/app/assets/fonts/SourceSansPro-Bold.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-BoldIt.ttf.woff b/app/assets/fonts/SourceSansPro-BoldIt.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff b/app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2 b/app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff b/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-It.ttf.woff b/app/assets/fonts/SourceSansPro-It.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-It.ttf.woff2 b/app/assets/fonts/SourceSansPro-It.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Light.ttf.woff b/app/assets/fonts/SourceSansPro-Light.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Light.ttf.woff2 b/app/assets/fonts/SourceSansPro-Light.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-LightIt.ttf.woff b/app/assets/fonts/SourceSansPro-LightIt.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-LightIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-LightIt.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Regular.ttf.woff b/app/assets/fonts/SourceSansPro-Regular.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Regular.ttf.woff2 b/app/assets/fonts/SourceSansPro-Regular.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Semibold.ttf.woff b/app/assets/fonts/SourceSansPro-Semibold.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-Semibold.ttf.woff2 b/app/assets/fonts/SourceSansPro-Semibold.ttf.woff2 old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff b/app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff old mode 100755 new mode 100644 diff --git a/app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2 b/app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2 old mode 100755 new mode 100644 -- cgit v1.2.1 From 7d1b51fac1c518dec5c33d30c4cc4e5bffdc127e Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 21 Jan 2016 11:27:31 +0100 Subject: Instrument Gitlab::Git::Repository This adds instrumentation for the instance methods of Gitlab::Git::Repository. --- config/initializers/metrics.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/initializers/metrics.rb b/config/initializers/metrics.rb index b1fe36dc21c..0945b93ed5d 100644 --- a/config/initializers/metrics.rb +++ b/config/initializers/metrics.rb @@ -49,6 +49,7 @@ if Gitlab::Metrics.enabled? config.instrument_instance_methods(Gitlab::Shell) config.instrument_methods(Gitlab::Git) + config.instrument_instance_methods(Gitlab::Git::Repository) Gitlab::Git.constants.each do |name| const = Gitlab::Git.const_get(name) -- cgit v1.2.1 From 693fa7a458645291cc903bf400f9b463941cb63d Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 21 Jan 2016 13:36:55 +0100 Subject: Init script changes for gitlab-workhorse in 8.4 --- lib/support/init.d/gitlab | 9 ++++++--- lib/support/init.d/gitlab.default.example | 3 +++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index c5f07c8b508..1633891c8a0 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -38,6 +38,7 @@ web_server_pid_path="$pid_path/unicorn.pid" sidekiq_pid_path="$pid_path/sidekiq.pid" mail_room_enabled=false mail_room_pid_path="$pid_path/mail_room.pid" +gitlab_workhorse_dir=$(cd $app_root/../gitlab-workhorse && pwd) gitlab_workhorse_pid_path="$pid_path/gitlab-workhorse.pid" gitlab_workhorse_options="-listenUmask 0 -listenNetwork unix -listenAddr $socket_path/gitlab-workhorse.socket -authBackend http://127.0.0.1:8080 -authSocket $rails_socket -documentRoot $app_root/public" gitlab_workhorse_log="$app_root/log/gitlab-workhorse.log" @@ -233,10 +234,12 @@ start_gitlab() { if [ "$gitlab_workhorse_status" = "0" ]; then echo "The gitlab-workhorse is already running with pid $spid, not restarting" else - # No need to remove a socket, gitlab-workhorse does this itself + # No need to remove a socket, gitlab-workhorse does this itself. + # Because gitlab-workhorse has multiple executables we need to fix + # the PATH. $app_root/bin/daemon_with_pidfile $gitlab_workhorse_pid_path \ - $app_root/../gitlab-workhorse/gitlab-workhorse \ - $gitlab_workhorse_options \ + /usr/bin/env PATH=$gitlab_workhorse_dir:$PATH \ + gitlab-workhorse $gitlab_workhorse_options \ >> $gitlab_workhorse_log 2>&1 & fi diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example index 1937ca582b0..4e6e56ac2db 100755 --- a/lib/support/init.d/gitlab.default.example +++ b/lib/support/init.d/gitlab.default.example @@ -30,6 +30,9 @@ web_server_pid_path="$pid_path/unicorn.pid" # The default is "$pid_path/sidekiq.pid" sidekiq_pid_path="$pid_path/sidekiq.pid" +# The directory where the gitlab-workhorse binaries are. Usually +# /home/git/gitlab-workhorse . +gitlab_workhorse_dir=$(cd $app_root/../gitlab-workhorse && pwd) gitlab_workhorse_pid_path="$pid_path/gitlab-workhorse.pid" # The -listenXxx settings determine where gitlab-workhorse # listens for connections from NGINX. To listen on localhost:8181, write -- cgit v1.2.1 From 21facf535377ad58d07e8943033fe14efface8b2 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 21 Jan 2016 14:23:53 +0100 Subject: Use consistent markup and styling for highlighting across blobs, diffs, blame and snippets --- app/assets/stylesheets/framework/common.scss | 8 --- app/assets/stylesheets/framework/files.scss | 21 +++----- app/assets/stylesheets/highlight/dark.scss | 49 +++++++++--------- app/assets/stylesheets/highlight/monokai.scss | 49 +++++++++--------- .../stylesheets/highlight/solarized_dark.scss | 49 +++++++++--------- .../stylesheets/highlight/solarized_light.scss | 50 +++++++++--------- app/assets/stylesheets/highlight/white.scss | 60 ++++++++++++++++++---- app/assets/stylesheets/pages/diff.scss | 47 ++--------------- app/assets/stylesheets/pages/note_form.scss | 12 ----- app/assets/stylesheets/pages/notes.scss | 3 -- app/models/members/project_member.rb | 6 +-- app/views/projects/blame/show.html.haml | 17 +++--- app/views/projects/blob/diff.html.haml | 3 +- app/views/projects/blob/preview.html.haml | 10 ++-- app/views/projects/diffs/_match_line.html.haml | 2 +- .../projects/diffs/_match_line_parallel.html.haml | 8 +-- app/views/projects/diffs/_parallel_view.html.haml | 16 +++--- app/views/projects/diffs/_text_file.html.haml | 6 +-- .../projects/notes/discussions/_diff.html.haml | 10 ++-- app/views/search/results/_snippet_blob.html.haml | 42 ++++++++------- app/views/shared/_file_highlight.html.haml | 4 +- 21 files changed, 212 insertions(+), 260 deletions(-) diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 585a9d83913..9bc814cfd2d 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -120,14 +120,6 @@ span.update-author { display: inline; } -.line_holder { - &:hover { - td { - background: #FFFFCF !important; - } - } -} - p.time { color: #999; font-size: 90%; diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 6ee104ee31a..a4791cf6b34 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -92,15 +92,6 @@ &:last-child { border-right: none; } - background: #fff; - } - .lines { - pre { - padding: 0; - margin: 0; - background: none; - border: none; - } } img.avatar { border: 0 none; @@ -116,18 +107,18 @@ color: #888; } } - td.blame-numbers { - pre { - color: #AAA; - white-space: pre; - } - background: #f1f1f1; + td.line-numbers { + float: none; border-left: 1px solid #DDD; } td.lines { + padding: 0; code { font-family: $monospace_font; } + pre { + margin: 0; + } } } diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss index 8201735beb5..3ba2cc94ad2 100644 --- a/app/assets/stylesheets/highlight/dark.scss +++ b/app/assets/stylesheets/highlight/dark.scss @@ -1,20 +1,35 @@ /* https://github.com/MozMorris/tomorrow-pygments */ .code.dark { + // Line numbers + .line-numbers, .diff-line-num { + background-color: #1d1f21; + } - background-color: #1d1f21 !important; - color: #c5c8c6 !important; - - pre.highlight, - .line-numbers, - .line-numbers a { - background-color: #1d1f21 !important; - color: #c5c8c6 !important; + .diff-line-num, .diff-line-num a { + color: rgba(255, 255, 255, 0.3); } + // Code itself pre.code { border-left: 1px solid #666; } + &, pre.code, .line_holder .line_content { + background-color: #1d1f21; + color: #c5c8c6; + } + + // Diff line + .line_holder { + .diff-line-num.new, .line_content.new { + @include diff_background(51, 255, 51, #808080); + } + + .diff-line-num.old, .line_content.old { + @include diff_background(255, 51, 51, #808080); + } + } + // highlight line via anchor pre .hll { background-color: #557 !important; @@ -90,22 +105,4 @@ .vg { color: #cc6666 } /* Name.Variable.Global */ .vi { color: #cc6666 } /* Name.Variable.Instance */ .il { color: #de935f } /* Literal.Number.Integer.Long */ - - .line_holder { - &.parallel .new.new_line, - &.parallel .new.line_content, - &.new .old_line, - &.new .new_line, - &.new .line_content { - @include diff_background(255, 255, 255, #808080); - } - - &.parallel .old.old_line, - &.parallel .old.line_content, - &.old .old_line, - &.old .new_line, - &.old .line_content { - @include diff_background(255, 51, 51, #808080); - } - } } diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss index cc03ed6ae45..b47aef73d2b 100644 --- a/app/assets/stylesheets/highlight/monokai.scss +++ b/app/assets/stylesheets/highlight/monokai.scss @@ -1,20 +1,35 @@ /* https://github.com/richleland/pygments-css/blob/master/monokai.css */ .code.monokai { + // Line numbers + .line-numbers, .diff-line-num { + background-color: #272822; + } - background-color: #272822 !important; - color: #f8f8f2 !important; - - pre.highlight, - .line-numbers, - .line-numbers a { - background-color :#272822 !important; - color: #f8f8f2 !important; + .diff-line-num, .diff-line-num a { + color: #f8f8f2; } + // Code itself pre.code { border-left: 1px solid #555; } + &, pre.code, .line_holder .line_content { + background-color: #272822; + color: #f8f8f2; + } + + // Diff line + .line_holder { + .diff-line-num.new, .line_content.new { + @include diff_background(156, 175, 183, #808080); + } + + .diff-line-num.old, .line_content.old { + @include diff_background(254, 147, 140, #808080); + } + } + // highlight line via anchor pre .hll { background-color: #49483e !important; @@ -90,22 +105,4 @@ .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ .gd { color: #f92672; } /* Generic.Deleted & Diff Deleted */ .gi { color: #a6e22e; } /* Generic.Inserted & Diff Inserted */ - - .line_holder { - &.parallel .new.new_line, - &.parallel .new.line_content, - &.new .old_line, - &.new .new_line, - &.new .line_content { - @include diff_background(156, 175, 183, #808080); - } - - &.parallel .old.old_line, - &.parallel .old.line_content, - &.old .old_line, - &.old .new_line, - &.old .line_content { - @include diff_background(254, 147, 140, #808080); - } - } } diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss index fdfac6cd249..0aab580bd3c 100644 --- a/app/assets/stylesheets/highlight/solarized_dark.scss +++ b/app/assets/stylesheets/highlight/solarized_dark.scss @@ -1,20 +1,35 @@ /* https://gist.github.com/qguv/7936275 */ .code.solarized-dark { + // Line numbers + .line-numbers, .diff-line-num { + background-color: #002b36; + } - background-color: #002b36 !important; - color: #93a1a1 !important; - - pre.highlight, - .line-numbers, - .line-numbers a { - background-color: #002b36 !important; - color: #93a1a1 !important; + .diff-line-num, .diff-line-num a { + color: #93a1a1; } + // Code itself pre.code { border-left: 1px solid #113b46; } + &, pre.code, .line_holder .line_content { + background-color: #002b36; + color: #93a1a1; + } + + // Diff line + .line_holder { + .diff-line-num.new, .line_content.new { + @include diff_background(255, 255, 255, #808080); + } + + .diff-line-num.old, .line_content.old { + @include diff_background(255, 51, 51, #808080); + } + } + // highlight line via anchor pre .hll { background-color: #174652 !important; @@ -111,22 +126,4 @@ .vg { color: #268bd2 } /* Name.Variable.Global */ .vi { color: #268bd2 } /* Name.Variable.Instance */ .il { color: #2aa198 } /* Literal.Number.Integer.Long */ - - .line_holder { - &.parallel .new.new_line, - &.parallel .new.line_content, - &.new .old_line, - &.new .new_line, - &.new .line_content { - @include diff_background(255, 255, 255, #808080); - } - - &.parallel .old.old_line, - &.parallel .old.line_content, - &.old .old_line, - &.old .new_line, - &.old .line_content { - @include diff_background(255, 51, 51, #808080); - } - } } diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss index f9788951aa8..3aaadcd0f96 100644 --- a/app/assets/stylesheets/highlight/solarized_light.scss +++ b/app/assets/stylesheets/highlight/solarized_light.scss @@ -1,20 +1,35 @@ /* https://gist.github.com/qguv/7936275 */ .code.solarized-light { + // Line numbers + .line-numbers, .diff-line-num { + background-color: #fdf6e3; + } - background-color: #fdf6e3 !important; - color: #586e75 !important; - - pre.highlight, - .line-numbers, - .line-numbers a { - background-color: #fdf6e3 !important; - color: #586e75 !important; + .diff-line-num, .diff-line-num a { + color: #586e75; } + // Code itself pre.code { border-left: 1px solid #c5d0d4; } + &, pre.code, .line_holder .line_content { + background-color: #fdf6e3; + color: #586e75; + } + + // Diff line + .line_holder { + .diff-line-num.new, .line_content.new { + @include diff_background(92, 164, 169, #FAF3DD); + } + + .diff-line-num.old, .line_content.old { + @include diff_background(237, 106, 90, #FAF3DD); + } + } + // highlight line via anchor pre .hll { background-color: #ddd8c5 !important; @@ -111,23 +126,4 @@ .vg { color: #268bd2 } /* Name.Variable.Global */ .vi { color: #268bd2 } /* Name.Variable.Instance */ .il { color: #2aa198 } /* Literal.Number.Integer.Long */ - - - .line_holder { - &.parallel .new.new_line, - &.parallel .new.line_content, - &.new .old_line, - &.new .new_line, - &.new .line_content { - @include diff_background(92, 164, 169, #FAF3DD); - } - - &.parallel .old.old_line, - &.parallel .old.line_content, - &.old .old_line, - &.old .new_line, - &.old .line_content { - @include diff_background(237, 106, 90, #FAF3DD); - } - } } diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss index e2626da7871..8a932e6540e 100644 --- a/app/assets/stylesheets/highlight/white.scss +++ b/app/assets/stylesheets/highlight/white.scss @@ -1,20 +1,60 @@ /* https://github.com/aahan/pygments-github-style */ .code.white { + // Line numbers + .line-numbers, .diff-line-num { + background-color: $background-color; + } - background-color: #f8fafc !important; - color: #5b6169 !important; - - pre.highlight, - .line-numbers, - .line-numbers a { - background-color: $background-color !important; - color: $gl-gray !important; + .diff-line-num, .diff-line-num a { + color: rgba(0, 0, 0, 0.3); } + // Code itself pre.code { border-left: 1px solid $border-color; - background-color: #fff !important; - color: #333 !important; + } + + &, pre.code, .line_holder .line_content { + background-color: #fff; + color: #333; + } + + // Diff line + .line_holder { + .diff-line-num { + &.old { + background: #ffdddd; + border-color: #f1c0c0; + } + + &.new { + background: #dbffdb; + border-color: #c1e9c1; + } + } + + .line_content { + &.old { + background: #ffecec; + + span.idiff { + background-color: #f8cbcb; + } + } + + &.new { + background: #eaffea; + + span.idiff { + background-color: #a6f3a6; + } + } + + &.match { + color: rgba(0, 0, 0, 0.3); + background: #fafafa; + } + } } // highlight line via anchor diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 0b79aa172a4..06d0ece1c66 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -32,16 +32,6 @@ background: #FFF; color: #333; - .old { - span.idiff { - background-color: #f8cbcb; - } - } - .new { - span.idiff { - background-color: #a6f3a6; - } - } .unfold { cursor: pointer; } @@ -76,7 +66,7 @@ } tr.line_holder.parallel { - .old_line, .new_line, .diff_line { + .old_line, .new_line { min-width: 50px; } @@ -85,7 +75,7 @@ } } - .old_line, .new_line, .diff_line { + .old_line, .new_line { margin: 0px; padding: 0px; border: none; @@ -107,43 +97,12 @@ text-decoration: underline; } } - &.new { - background: #CFD; - } - &.old { - background: #FDD; - } - } - .diff_line { - padding: 0; - } - .line_holder { - &.old .old_line, - &.old .new_line { - background: #ffdddd; - border-color: #f1c0c0; - } - &.new .old_line, - &.new .new_line { - background: #dbffdb; - border-color: #c1e9c1; - } } .line_content { display: block; margin: 0px; padding: 0px 0.5em; border: none; - &.new { - background: #eaffea; - } - &.old { - background: #ffecec; - } - &.matched { - color: $border-color; - background: #fafafa; - } &.parallel { display: table-cell; } @@ -400,7 +359,7 @@ /* RGBa with 0.3 opacity */ background: rgba($r, $g, $b, 0.3); - &.new_line, &.old_line { + &.diff-line-num { border-right-color: $custom-border !important; } diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 2c9a42f9892..32ba1676333 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -10,18 +10,6 @@ margin: 10px $gl-padding; } .diff-file .diff-content { - tr.line_holder:hover { - &> td.line_content { - background: $hover !important; - border-color: darken($hover, 10%) !important; - } - &> td.new_line, - &> td.old_line { - background: darken($hover, 4%) !important; - border-color: darken($hover, 10%) !important; - } - } - tr.line_holder:hover > td .line_note_link { opacity: 1.0; filter: alpha(opacity=100); diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 72b0ed29a69..f6343e6bb1e 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -242,11 +242,8 @@ ul.notes { // "show" the icon also if we just hover somewhere over the line &:hover > td { - background: $hover !important; - .add-diff-note { @include show-add-diff-note; } } } - diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index 1b0c76917aa..560d1690e14 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -84,7 +84,7 @@ class ProjectMember < Member def truncate_teams(project_ids) ProjectMember.transaction do members = ProjectMember.where(source_id: project_ids) - + members.each do |member| member.destroy end @@ -133,13 +133,13 @@ class ProjectMember < Member event_service.join_project(self.project, self.user) notification_service.new_project_member(self) end - + super end def post_update_hook if access_level_changed? - notification_service.update_project_member(self) + notification_service.update_project_member(self) end super diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index d5d04954490..53dcac78a9f 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -12,7 +12,7 @@ %small= number_to_human_size @blob.size .file-actions = render "projects/blob/actions" - .file-content.blame.highlight + .file-content.blame.code.js-syntax-highlight %table - current_line = 1 - blame_highlighter = highlighter(@blob.name, @blob.data, nowrap: true) @@ -31,15 +31,14 @@ = commit_author_link(commit, avatar: false) authored #{time_ago_with_tooltip(commit.committed_date, skip_js: true)} - %td.lines.blame-numbers - %pre - - line_count = blame_group[:lines].count - - (current_line...(current_line + line_count)).each do |i| - = i - \ - - current_line += line_count + %td.line-numbers + - line_count = blame_group[:lines].count + - (current_line...(current_line + line_count)).each do |i| + %a.diff-line-num= i + \ + - current_line += line_count %td.lines - %pre{class: 'code highlight white'} + %pre{class: 'code highlight'} %code - blame_group[:lines].each do |line| :preserve diff --git a/app/views/projects/blob/diff.html.haml b/app/views/projects/blob/diff.html.haml index 2e913802be1..abcfca4cd11 100644 --- a/app/views/projects/blob/diff.html.haml +++ b/app/views/projects/blob/diff.html.haml @@ -10,7 +10,8 @@ %tr.line_holder %td.old_line.diff-line-num{data: {linenumber: line_old}} = link_to raw(line_old), "#" - %td.new_line= link_to raw(line_new) , "#" + %td.new_line.diff-line-num + = link_to raw(line_new) , "#" %td.line_content.noteable_line==#{' ' * @form.indent}#{line} - if @form.unfold? && @form.bottom? && @form.to < @blob.loc diff --git a/app/views/projects/blob/preview.html.haml b/app/views/projects/blob/preview.html.haml index fed483d6788..c5a269f334c 100644 --- a/app/views/projects/blob/preview.html.haml +++ b/app/views/projects/blob/preview.html.haml @@ -14,12 +14,12 @@ - @diff_lines.each do |line| %tr.line_holder{ class: "#{line.type}" } - if line.type == "match" - %td.old_line= "..." - %td.new_line= "..." - %td.line_content.matched= line.text + %td.old_line.diff-line-num= "..." + %td.new_line.diff-line-num= "..." + %td.line_content.match= line.text - else - %td.old_line - %td.new_line + %td.old_line.diff-line-num + %td.new_line.diff-line-num %td.line_content{class: "#{line.type}"}= diff_line_content(line.text) - else .nothing-here-block No changes. diff --git a/app/views/projects/diffs/_match_line.html.haml b/app/views/projects/diffs/_match_line.html.haml index d1f897b99f7..d6dddd97879 100644 --- a/app/views/projects/diffs/_match_line.html.haml +++ b/app/views/projects/diffs/_match_line.html.haml @@ -4,4 +4,4 @@ %td.new_line.diff-line-num{data: {linenumber: line_new}, class: [unfold_bottom_class(bottom), unfold_class(!new_file)]} \... -%td.line_content.matched= line +%td.line_content.match= line diff --git a/app/views/projects/diffs/_match_line_parallel.html.haml b/app/views/projects/diffs/_match_line_parallel.html.haml index 815df16aa4a..0cd888876e0 100644 --- a/app/views/projects/diffs/_match_line_parallel.html.haml +++ b/app/views/projects/diffs/_match_line_parallel.html.haml @@ -1,4 +1,4 @@ -%td.old_line - %td.line_content.parallel.matched= line -%td.new_line - %td.line_content.parallel.matched= line +%td.old_line.diff-line-num +%td.line_content.parallel.match= line +%td.new_line.diff-line-num +%td.line_content.parallel.match= line diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml index a15d147ab05..d7c49068745 100644 --- a/app/views/projects/diffs/_parallel_view.html.haml +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -9,16 +9,16 @@ = render "projects/diffs/match_line_parallel", { line: left[:text], line_old: left[:number], line_new: right[:number] } - elsif left[:type] == 'nonewline' - %td.old_line - %td.line_content.parallel.matched= left[:text] - %td.new_line - %td.line_content.parallel.matched= left[:text] + %td.old_line.diff-line-num + %td.line_content.parallel.match= left[:text] + %td.new_line.diff-line-num + %td.line_content.parallel.match= left[:text] - else - %td.old_line{id: left[:line_code], class: "#{left[:type]}"} + %td.old_line.diff-line-num{id: left[:line_code], class: "#{left[:type]}"} = link_to raw(left[:number]), "##{left[:line_code]}", id: left[:line_code] - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(left[:line_code], 'old') - %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", data: { line_code: left[:line_code] }}= diff_line_content(left[:text]) + %td.line_content{class: "parallel noteable_line #{left[:type]} #{left[:line_code]}", data: { line_code: left[:line_code] }}= diff_line_content(left[:text]) - if right[:type] == 'new' - new_line_class = 'new' @@ -27,11 +27,11 @@ - new_line_class = nil - new_line_code = left[:line_code] - %td.new_line{id: new_line_code, class: "#{new_line_class}", data: { linenumber: right[:number] }} + %td.new_line.diff-line-num{id: new_line_code, class: "#{new_line_class}", data: { linenumber: right[:number] }} = link_to raw(right[:number]), "##{new_line_code}", id: new_line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(right[:line_code], 'new') - %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", data: { line_code: new_line_code }}= diff_line_content(right[:text]) + %td.line_content.parallel{class: "noteable_line #{new_line_class} #{new_line_code}", data: { line_code: new_line_code }}= diff_line_content(right[:text]) - if @reply_allowed - comments_left, comments_right = organize_comments(left[:type], right[:type], left[:line_code], right[:line_code]) diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index f4fc6caba0f..d9f2dce1389 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -18,13 +18,13 @@ - elsif type == 'nonewline' %td.old_line.diff-line-num %td.new_line.diff-line-num - %td.line_content.matched= line.text + %td.line_content.match= line.text - else - %td.old_line + %td.old_line.diff-line-num{class: type} = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code - if @comments_allowed && can?(current_user, :create_note, @project) = link_to_new_diff_note(line_code) - %td.new_line{data: {linenumber: line.new_pos}} + %td.new_line.diff-line-num{class: type, data: {linenumber: line.new_pos}} = link_to raw(type == "old" ? " " : line.new_pos), "##{line_code}", id: line_code %td.line_content{class: "noteable_line #{type} #{line_code}", data: { line_code: line_code }}= diff_line_content(line.text) diff --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml index 46962b184ce..92bbaf0961a 100644 --- a/app/views/projects/notes/discussions/_diff.html.haml +++ b/app/views/projects/notes/discussions/_diff.html.haml @@ -16,13 +16,13 @@ - line_code = generate_line_code(note.file_path, line) %tr.line_holder{ id: line_code, class: "#{type}" } - if type == "match" - %td.old_line= "..." - %td.new_line= "..." - %td.line_content.matched= line.text + %td.old_line.diff-line-num= "..." + %td.new_line.diff-line-num= "..." + %td.line_content.match= line.text - else - %td.old_line + %td.old_line.diff-line-num = raw(type == "new" ? " " : line.old_pos) - %td.new_line + %td.new_line.diff-line-num = raw(type == "old" ? " " : line.new_pos) %td.line_content{class: "noteable_line #{type} #{line_code}", line_code: line_code}= diff_line_content(line.text) diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml index 9a4f9fb9485..dcd61199717 100644 --- a/app/views/search/results/_snippet_blob.html.haml +++ b/app/views/search/results/_snippet_blob.html.haml @@ -22,29 +22,27 @@ .file-content.code .nothing-here-block Empty file - else - .file-content.code - %div.highlighted-data{ class: user_color_scheme } - .line-numbers + .file-content.code.js-syntax-highlight + .line-numbers + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + - snippet[:data].lines.to_a.size.times do |index| + - offset = defined?(snippet[:start_line]) ? snippet[:start_line] : 1 + - i = index + offset + = link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}", class: "diff-line-num" do + %i.fa.fa-link + = i + - unless snippet == snippet_blob[:snippet_chunks].last + %a.diff-line-num + = "." + %pre.code + %code - snippet_blob[:snippet_chunks].each do |snippet| - unless snippet[:data].empty? - - snippet[:data].lines.to_a.size.times do |index| - - offset = defined?(snippet[:start_line]) ? snippet[:start_line] : 1 - - i = index + offset - = link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}" do - %i.fa.fa-link - = i + = snippet[:data] - unless snippet == snippet_blob[:snippet_chunks].last %a - = "." - .highlight.term - %pre - %code - - snippet_blob[:snippet_chunks].each do |snippet| - - unless snippet[:data].empty? - = snippet[:data] - - unless snippet == snippet_blob[:snippet_chunks].last - %a - = "..." - - else - .file-content.code - .nothing-here-block Empty file + = "..." + - else + .file-content.code + .nothing-here-block Empty file diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml index 1bef1de433a..ee242c94db8 100644 --- a/app/views/shared/_file_highlight.html.haml +++ b/app/views/shared/_file_highlight.html.haml @@ -1,11 +1,11 @@ -.file-content.code.js-syntax-highlight{ class: user_color_scheme } +.file-content.code.js-syntax-highlight .line-numbers - if blob.data.present? - blob.data.lines.each_index do |index| - offset = defined?(first_line_number) ? first_line_number : 1 - i = index + offset -# We're not using `link_to` because it is too slow once we get to thousands of lines. - %a{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i} + %a.diff-line-num{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i} %i.fa.fa-link = i .blob-content{data: {blob_id: blob.id}} -- cgit v1.2.1 From ad6b6b9ede9b8652dd5479009734cc0a462a65b1 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 21 Jan 2016 14:24:40 +0100 Subject: Mention init script update --- doc/update/8.3-to-8.4.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/update/8.3-to-8.4.md b/doc/update/8.3-to-8.4.md index 604939cd733..5f1372e7725 100644 --- a/doc/update/8.3-to-8.4.md +++ b/doc/update/8.3-to-8.4.md @@ -104,10 +104,7 @@ via [/etc/default/gitlab]. #### Init script -We updated the init script for GitLab in order to pass new -configuration options to gitlab-workhorse. We let gitlab-workhorse -connect to the Rails application via a Unix domain socket and we tell -it where the 'public' directory of GitLab is. +We updated the init script for GitLab in order to set a specific PATH for gitlab-workhorse. ``` cd /home/git/gitlab -- cgit v1.2.1 From 1c1590a510de0e6836e204b6d47fa810e5ec4f6c Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 21 Jan 2016 14:44:56 +0100 Subject: Use gitlab-workhorse 0.6.1 --- GITLAB_WORKHORSE_VERSION | 2 +- doc/update/8.3-to-8.4.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index a918a2aa18d..ee6cdce3c29 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -0.6.0 +0.6.1 diff --git a/doc/update/8.3-to-8.4.md b/doc/update/8.3-to-8.4.md index 5f1372e7725..bf80f66d004 100644 --- a/doc/update/8.3-to-8.4.md +++ b/doc/update/8.3-to-8.4.md @@ -48,7 +48,7 @@ which should already be on your system from GitLab 8.1. ```bash cd /home/git/gitlab-workhorse sudo -u git -H git fetch --all -sudo -u git -H git checkout 0.6.0 +sudo -u git -H git checkout 0.6.1 sudo -u git -H make ``` -- cgit v1.2.1 From b2c071fad4b7767e1e2e140cf3b3e4c6621c25a1 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 21 Jan 2016 14:56:23 +0100 Subject: Pretty highlighted diffs for every theme --- app/assets/stylesheets/highlight/dark.scss | 9 +++++++-- app/assets/stylesheets/highlight/monokai.scss | 11 ++++++++--- app/assets/stylesheets/highlight/solarized_dark.scss | 11 ++++++++--- app/assets/stylesheets/highlight/solarized_light.scss | 11 ++++++++--- app/assets/stylesheets/pages/diff.scss | 15 ++++++--------- 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss index 3ba2cc94ad2..8464727de9d 100644 --- a/app/assets/stylesheets/highlight/dark.scss +++ b/app/assets/stylesheets/highlight/dark.scss @@ -22,11 +22,16 @@ // Diff line .line_holder { .diff-line-num.new, .line_content.new { - @include diff_background(51, 255, 51, #808080); + @include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.2), #808080); } .diff-line-num.old, .line_content.old { - @include diff_background(255, 51, 51, #808080); + @include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.2), #808080); + } + + .line_content.match { + color: rgba(255, 255, 255, 0.3); + background: rgba(255, 255, 255, 0.1); } } diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss index b47aef73d2b..516d8aef960 100644 --- a/app/assets/stylesheets/highlight/monokai.scss +++ b/app/assets/stylesheets/highlight/monokai.scss @@ -6,7 +6,7 @@ } .diff-line-num, .diff-line-num a { - color: #f8f8f2; + color: rgba(255, 255, 255, 0.3); } // Code itself @@ -22,11 +22,16 @@ // Diff line .line_holder { .diff-line-num.new, .line_content.new { - @include diff_background(156, 175, 183, #808080); + @include diff_background(rgba(166, 226, 46, 0.2), rgba(166, 226, 46, 0.3), #808080); } .diff-line-num.old, .line_content.old { - @include diff_background(254, 147, 140, #808080); + @include diff_background(rgba(254, 147, 140, 0.2), rgba(254, 147, 140, 0.3), #808080); + } + + .line_content.match { + color: rgba(255, 255, 255, 0.3); + background: rgba(255, 255, 255, 0.1); } } diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss index 0aab580bd3c..ae7ecc65c39 100644 --- a/app/assets/stylesheets/highlight/solarized_dark.scss +++ b/app/assets/stylesheets/highlight/solarized_dark.scss @@ -6,7 +6,7 @@ } .diff-line-num, .diff-line-num a { - color: #93a1a1; + color: rgba(255, 255, 255, 0.3); } // Code itself @@ -22,11 +22,16 @@ // Diff line .line_holder { .diff-line-num.new, .line_content.new { - @include diff_background(255, 255, 255, #808080); + @include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.3), #808080); } .diff-line-num.old, .line_content.old { - @include diff_background(255, 51, 51, #808080); + @include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.3), #808080); + } + + .line_content.match { + color: rgba(255, 255, 255, 0.3); + background: rgba(255, 255, 255, 0.1); } } diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss index 3aaadcd0f96..1c138572145 100644 --- a/app/assets/stylesheets/highlight/solarized_light.scss +++ b/app/assets/stylesheets/highlight/solarized_light.scss @@ -6,7 +6,7 @@ } .diff-line-num, .diff-line-num a { - color: #586e75; + color: rgba(0, 0, 0, 0.3); } // Code itself @@ -22,11 +22,16 @@ // Diff line .line_holder { .diff-line-num.new, .line_content.new { - @include diff_background(92, 164, 169, #FAF3DD); + @include diff_background(rgba(133, 153, 0, 0.2), rgba(133, 153, 0, 0.3), #FAF3DD); } .diff-line-num.old, .line_content.old { - @include diff_background(237, 106, 90, #FAF3DD); + @include diff_background(rgba(220, 50, 47, 0.2), rgba(220, 50, 47, 0.3), #FAF3DD); + } + + .line_content.match { + color: rgba(0, 0, 0, 0.3); + background: rgba(255, 255, 255, 0.4); } } diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 06d0ece1c66..5215df04a6e 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -353,17 +353,14 @@ } } -@mixin diff_background($r, $g, $b, $custom-border) { - /* Fallback for web browsers that doesn't support RGBa */ - background: rgb($r, $g, $b); - /* RGBa with 0.3 opacity */ - background: rgba($r, $g, $b, 0.3); +@mixin diff_background($background, $idiff, $border) { + background: $background; - &.diff-line-num { - border-right-color: $custom-border !important; + &.line_content span.idiff { + background: $idiff; } - &.line_content span.idiff { - background: rgb($r, $g, $b); + &.diff-line-num { + border-color: $border; } } -- cgit v1.2.1 From e5232ccc1ec44ae62b05f80f728b21ee7460b79d Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 21 Jan 2016 15:05:51 +0100 Subject: Do not use progress bar when downloading build artifacts Closes #12491 --- app/views/projects/artifacts/browse.html.haml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index d3c969cc035..8a6fb785708 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -4,7 +4,7 @@ .top-block.gray-content-block.clearfix .pull-right = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), - class: 'btn btn-default' do + class: 'btn btn-default download' do = icon('download') Download artifacts archive @@ -22,6 +22,10 @@ .center Empty :javascript + $('.top-block').on('click', '.download', function(e) { + e.stopPropagation(); + }); + $('.tree-holder').on('click', 'tr[data-link] a', function(e) { e.stopImmediatePropagation(); }); -- cgit v1.2.1 From 85fd6c861fbff3fd0b2d6fdb135b335ece635254 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 21 Jan 2016 15:07:21 +0100 Subject: Make dark inline diffs a little more obvious --- app/assets/stylesheets/highlight/dark.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss index 8464727de9d..c7f7a5aaf07 100644 --- a/app/assets/stylesheets/highlight/dark.scss +++ b/app/assets/stylesheets/highlight/dark.scss @@ -22,11 +22,11 @@ // Diff line .line_holder { .diff-line-num.new, .line_content.new { - @include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.2), #808080); + @include diff_background(rgba(51, 255, 51, 0.1), rgba(51, 255, 51, 0.3), #808080); } .diff-line-num.old, .line_content.old { - @include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.2), #808080); + @include diff_background(rgba(255, 51, 51, 0.2), rgba(255, 51, 51, 0.3), #808080); } .line_content.match { -- cgit v1.2.1 From ad9799bdb0232bf3899b184a47f644e13a7dd031 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 21 Jan 2016 14:17:59 +0000 Subject: Milestone drag & drop cursor Fixes #4097 --- app/assets/stylesheets/framework/jquery.scss | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/assets/stylesheets/framework/jquery.scss b/app/assets/stylesheets/framework/jquery.scss index 871b808bad4..d6cd78813c0 100644 --- a/app/assets/stylesheets/framework/jquery.scss +++ b/app/assets/stylesheets/framework/jquery.scss @@ -53,3 +53,14 @@ color: #333; } } + +.ui-sortable-handle { + cursor: move; + cursor: -webkit-grab; + cursor: -moz-grab; + + &:active { + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + } +} -- cgit v1.2.1 From 66b0927bb5e19f8a4a3df3e7e401ddd1e3d8e768 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 21 Jan 2016 15:51:44 +0100 Subject: Move build artifacts javascripts into separate file --- app/assets/javascripts/build_artifacts.js.coffee | 14 ++++++++++++++ app/assets/javascripts/dispatcher.js.coffee | 2 ++ app/views/projects/artifacts/browse.html.haml | 13 ------------- 3 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 app/assets/javascripts/build_artifacts.js.coffee diff --git a/app/assets/javascripts/build_artifacts.js.coffee b/app/assets/javascripts/build_artifacts.js.coffee new file mode 100644 index 00000000000..5ae6cba56c8 --- /dev/null +++ b/app/assets/javascripts/build_artifacts.js.coffee @@ -0,0 +1,14 @@ +class @BuildArtifacts + constructor: () -> + @disablePropagation() + @setupEntryClick() + + disablePropagation: -> + $('.top-block').on 'click', '.download', (e) -> + e.stopPropagation() + $('.tree-holder').on 'click', 'tr[data-link] a', (e) -> + e.stopImmediatePropagation() + + setupEntryClick: -> + $('.tree-holder').on 'click', 'tr[data-link]', (e) -> + window.location = @dataset.link diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 0d88e8d254a..2cdf01d874c 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -100,6 +100,8 @@ class Dispatcher shortcut_handler = true when 'projects:forks:new' new ProjectFork() + when 'projects:artifacts:browse' + new BuildArtifacts() when 'users:show' new User() new Activities() diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index 8a6fb785708..84034c8bf16 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -20,16 +20,3 @@ - if @entry.empty? .center Empty - -:javascript - $('.top-block').on('click', '.download', function(e) { - e.stopPropagation(); - }); - - $('.tree-holder').on('click', 'tr[data-link] a', function(e) { - e.stopImmediatePropagation(); - }); - - $('.tree-holder').on('click', 'tr[data-link]', function(e) { - window.location = this.dataset.link; - }); -- cgit v1.2.1 From 4861b1bbfbd962416452e1e883c67b885678b5a0 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 21 Jan 2016 13:11:38 -0200 Subject: Fix import of GitHub's wiki when the repository has not been created --- lib/gitlab/github_import/importer.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb index 18929b9113b..663402e8197 100644 --- a/lib/gitlab/github_import/importer.rb +++ b/lib/gitlab/github_import/importer.rb @@ -82,8 +82,12 @@ module Gitlab end true - rescue Gitlab::Shell::Error - false + rescue Gitlab::Shell::Error => e + if e.message =~ /repository not exported/ + true + else + false + end end end end -- cgit v1.2.1 From 93b942ec7c9dfc5f2f117d1d2161f69e9a39e16f Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 21 Jan 2016 17:27:23 +0100 Subject: Refactor build artifacts documentation [ci skip] --- doc/README.md | 2 +- doc/ci/README.md | 2 +- doc/ci/artifacts/README.md | 50 ------ doc/ci/build_artifacts/README.md | 173 +++++++++++++++++++++ .../img/build_artifacts_browser.png | Bin 0 -> 89132 bytes .../img/build_artifacts_browser_button.png | Bin 0 -> 11614 bytes 6 files changed, 175 insertions(+), 52 deletions(-) delete mode 100644 doc/ci/artifacts/README.md create mode 100644 doc/ci/build_artifacts/README.md create mode 100644 doc/ci/build_artifacts/img/build_artifacts_browser.png create mode 100644 doc/ci/build_artifacts/img/build_artifacts_browser_button.png diff --git a/doc/README.md b/doc/README.md index d75c1fbfe79..f3836d32e20 100644 --- a/doc/README.md +++ b/doc/README.md @@ -30,7 +30,7 @@ - [User permissions](ci/permissions/README.md) - [API](ci/api/README.md) - [Triggering builds through the API](ci/triggers/README.md) -- [Build artifacts](ci/artifacts/README.md) +- [Build artifacts](ci/build_artifacts/README.md) ### CI Languages diff --git a/doc/ci/README.md b/doc/ci/README.md index 19d08721467..5886829be51 100644 --- a/doc/ci/README.md +++ b/doc/ci/README.md @@ -12,7 +12,7 @@ * [Using Variables](variables/README.md) * [Using SSH keys](ssh_keys/README.md) * [Triggering builds through the API](triggers/README.md) -* [Build artifacts](artifacts/README.md) +* [Build artifacts](build_artifacts/README.md) ### Languages diff --git a/doc/ci/artifacts/README.md b/doc/ci/artifacts/README.md deleted file mode 100644 index 1166304f33c..00000000000 --- a/doc/ci/artifacts/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Build artifacts - -Since version 8.2 of GitLab and version 0.7.0 of GitLab Runner, build artifacts -created by GitLab Runner are uploaded to GitLab, and then you can download -artifacts archive using GitLab UI. - -Since version 8.4 of GitLab and version 1.0 of GitLab Runner artifacts are -compressed using ZIP format and it is possible to browse content of such an -archive using GitLab UI, and then download a single file from inside it. - -## Artifacts in .gitlab-ci.yml - -Please look into `.gitlab-ci.yml` [documentation](../yaml/README.md). - -## Artifacts archive format - -Prior to version 8.4 of GitLab and 1.0 of GitLab Runner, build artifacts were -compressed using `tar.gz` format. - -Since then, we use a ZIP format. - -## How build artifacts are stored - -After a successful build, GitLab Runner uploads an archive containing build -artifacts to GitLab. This archive is not extracted after that, so its save a -storage space. - -## How do we access content of an artifacts archive - -When GitLab receives an artifacts archive, archive metadata file is being -generated. Metadata file describes all entries that are located in artifacts -archive. This file is in a binary format, with additional GZIP compression. - -It is possible then to browse artifacts using GitLab UI and artifacts browser. - -TODO IMG - -GitLab does not extract artifacts archive to make it possible to browse it. We -use artifacts metadata file instead that contains are relevant information. -This is especially important when there is a lot of artifacts, or an archive is -a very large file. - -## How do we make files downloadable - -When user clicks a regular file, then download of this particular file starts. -GitLab does not extract entire artifacts archive to send a single file to user. - -Instead of extracting entire file, only one file is being extracted. It is not -necessary to extract large archive, just to download a small file that is -inside. diff --git a/doc/ci/build_artifacts/README.md b/doc/ci/build_artifacts/README.md new file mode 100644 index 00000000000..b02caa9edff --- /dev/null +++ b/doc/ci/build_artifacts/README.md @@ -0,0 +1,173 @@ +# Introduction to build artifacts + +Artifacts is a list of files and directories which are attached to a build +after it completes successfully. + +Since GitLab 8.2 and [GitLab Runner] 0.7.0, build artifacts that are created by +GitLab Runner are uploaded to GitLab and are downloadable as a single archive +(`tar.gz`) using the GitLab UI. + +Starting from GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format +changed to `ZIP`, and it is now possible to browse its contents, with the added +ability of downloading the files separately. + +## Enabling build artifacts + +If you are searching for ways to use the artifacts feature, jump to +[Defining artifacts in `.gitlab-ci.yml`](#defining-artifacts-in-gitlab-ciyml). + +The artifacts feature is enabled by default in all GitLab installations. + +If by any chance you want to disable the artifacts feature on your GitLab +instance, follow the steps below. + +--- + +**In Omnibus installations:** + +1. Edit `/etc/gitlab/gitlab.rb` and add the following line: + + ```ruby + gitlab_rails['artifacts_enabled'] = false + ``` + +1. Save the file and [reconfigure GitLab][] for the changes to take effect. + +--- + +**In installations from source:** + +1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines: + + ```yaml + artifacts: + enabled: false + ``` + +1. Save the file and [restart GitLab][] for the changes to take effect. + +## Defining artifacts in `.gitlab-ci.yml` + +A simple example of using the artifacts definition in `.gitlab-ci.yml` would be +the following: + +```yaml +pdf: + script: xelatex mycv.tex + artifacts: + paths: + - mycv.pdf +``` + +A job named `pdf` calls the `xelatex` command in order to build a pdf file from +the latex source file `mycv.tex`. We then define the `artifacts` paths which in +turn are defined with the `paths` keyword. All paths to files and directories +are relative to the repository that was cloned during the build. + +For more examples on artifacts, follow the +[separate artifacts yaml documentation](../yaml/README.md#artifacts). + +## Storing build artifacts + +After a successful build, GitLab Runner uploads an archive containing the build +artifacts to GitLab. + +To change the location where the artifacts are stored, follow the steps below. + +--- + +**In Omnibus installations:** + +_The artifacts are stored by default in +`/var/opt/gitlab/gitlab-rails/shared/artifacts`._ + +1. To change the storage path for example to `/mnt/storage/artifacts`, edit + `/etc/gitlab/gitlab.rb` and add the following line: + + ```ruby + gitlab_rails['artifacts_path'] = "/mnt/storage/artifacts" + ``` + +1. Save the file and [reconfigure GitLab][] for the changes to take effect. + +--- + +**In installations from source:** + +_The artifacts are stored by default in +`/home/git/gitlab/shared/artifacts`._ + +1. To change the storage path for example to `/mnt/storage/artifacts`, edit + `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines: + + ```yaml + artifacts: + enabled: true + path: /mnt/storage/artifacts + ``` + +1. Save the file and [restart GitLab][] for the changes to take effect. + +## Browsing build artifacts + +When GitLab receives an artifacts archive, an archive metadata file is also +generated. This metadata file describes all the entries that are located in the +artifacts archive itself. The metadata file is in a binary format, with +additional GZIP compression. + +GitLab does not extract the artifacts archive in order to save space, memory +and disk I/O. It instead inspects the metadata file which contains all the +relevant information. This is especially important when there is a lot of +artifacts, or an archive is a very large file. + +--- + +After a successful build, if you visit the build's specific page, you can see +that there are two buttons. + +One is for downloading the artifacts archive and the other for browsing its +contents. + +![Build artifacts browser button](img/build_artifacts_browser_button.png) + +--- + +The archive browser shows the name and the actual file size of each file in the +archive. If your artifacts contained directories, then you are also able to +browse inside them. + +Below you can see an image of three different file formats, as well as two +directories. + +![Build artifacts browser](img/build_artifacts_browser.png) + +--- + +## Downloading build artifacts + +If you need to download the whole archive, there are buttons in various places +inside GitLab that make that possible. + +1. While on the builds page, you can see the download icon for each build's + artifacts archive in the right corner + +1. While inside a specific build, you are presented with a download button + along with the one that browses the archive + +1. And finally, when browsing and archive you can see the download button at + the top right corner + +--- + +Note that GitLab does not extract the entire artifacts archive to send just a +single file to the user. + +When clicking on a specific file, [GitLab Workhorse] extracts it from the +archive and the download begins. + +This implementation saves space, memory and disk I/O. + +[gitlab runner]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner "GitLab Runner repository" +[reconfigure gitlab]: ../../administration/restart_gitlab.md "How to restart GitLab documentation" +[restart gitlab]: ../../administration/restart_gitlab.md "How to restart GitLab documentation" +[gitlab workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse "GitLab Workhorse repository" diff --git a/doc/ci/build_artifacts/img/build_artifacts_browser.png b/doc/ci/build_artifacts/img/build_artifacts_browser.png new file mode 100644 index 00000000000..73ed4eeb927 Binary files /dev/null and b/doc/ci/build_artifacts/img/build_artifacts_browser.png differ diff --git a/doc/ci/build_artifacts/img/build_artifacts_browser_button.png b/doc/ci/build_artifacts/img/build_artifacts_browser_button.png new file mode 100644 index 00000000000..f5d15bc3e7d Binary files /dev/null and b/doc/ci/build_artifacts/img/build_artifacts_browser_button.png differ -- cgit v1.2.1 From dc5a20520a02daaa589ad7c7c0a2d4d8ea7d208a Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 21 Jan 2016 19:57:41 +0100 Subject: Fix typos, make things more clear [ci skip] --- doc/administration/restart_gitlab.md | 43 +++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md index bb4fe9f414e..483060395dd 100644 --- a/doc/administration/restart_gitlab.md +++ b/doc/administration/restart_gitlab.md @@ -12,13 +12,7 @@ If you want the TL;DR versions, jump to: ## Omnibus installations If you have used the [Omnibus packages][omnibus-dl] to install GitLab, then -you should already have `gitlab-ctl` in your `PATH`. To find out, run: - -```bash -which gitlab-ctl -``` - -The output should be: `/usr/bin/gitlab-ctl`. +you should already have `gitlab-ctl` in your `PATH`. `gitlab-ctl` interacts with the Omnibus packages and can be used to restart the GitLab Rails application (Unicorn) as well as the other components, like: @@ -29,11 +23,12 @@ GitLab Rails application (Unicorn) as well as the other components, like: - NGINX (if you are using the bundled one) - Redis (if you are using the bundled one) - [Mailroom][] -- Logrotate. +- Logrotate ### Omnibus GitLab restart -When you are asked to _restart GitLab_, you need to run the following command: +There may be times in the documentation where you will be asked to _restart_ +GitLab. In that case, you need to run the following command: ```bash sudo gitlab-ctl restart @@ -65,14 +60,20 @@ To check the status of GitLab services, run: sudo gitlab-ctl status ``` -Notice that all services say `ok: run`. If you get any weird results, like the -unicorn service not starting, you may need to +Notice that all services say `ok: run`. + +Sometimes, components time out during the restart and sometimes they get stuck. +In that case, you can use `gitlab-ctl kill ` to send the `SIGKILL` +signal to the service, for example `sidekiq`. After that, a restart should +perform fine. + +As a last resort, you can try to [reconfigure GitLab](#omnibus-gitlab-reconfigure) instead. ### Omnibus GitLab reconfigure -There may be times where you will be asked to _reconfigure_ GitLab. Remember -that this method applies only for the Omnibus packages. +There may be times in the documentation where you will be asked to _reconfigure_ +GitLab. Remember that this method applies only for the Omnibus packages. Reconfigure Omnibus GitLab with: @@ -86,8 +87,14 @@ configuration (`/etc/gitlab/gitlab.rb`) has changed. When you run this command, [Chef], the underlying configuration management application that powers Omnibus GitLab, will make sure that all directories, permissions, services, etc., are in place and in the same shape that they were -initially shipped. This is where the _idempotency_ buzz-word you've been reading -here and there fits. +initially shipped. + +It will also restart GitLab components where needed, if any of their +configuration files have changed. + +If you manually edit any files in `/var/opt/gitlab` that are managed by Chef, +running reconfigure will revert the changes AND restart the services that +depend on those files. ## Installations from source @@ -120,14 +127,14 @@ GitLab and all its components are up and running. ``` This should restart Unicorn, Sidekiq, GitLab Workhorse and [Mailroom][] -(if enabled). The init service file that does all the magic can be found in -[`lib/support/init.d/gitlab`][src-service]. +(if enabled). The init service file that does all the magic can be found on +your server in `/etc/init.d/gitlab`. --- If you are using other init systems, like systemd, you can check the [GitLab Recipes][gl-recipes] repository for some unofficial services. These are -**not** officially supported so use at your own risk. +**not** officially supported so use them at your own risk. [omnibus-dl]: https://about.gitlab.com/downloads/ "Download the Omnibus packages" -- cgit v1.2.1 From 465e4616c980367a7e075ef7f795879810d9b1e2 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 21 Jan 2016 22:32:55 +0100 Subject: Add file finder documentation [ci skip] --- doc/workflow/README.md | 1 + doc/workflow/file_finder.md | 42 +++++++++++++++++++++++++++ doc/workflow/img/file_finder_find_button.png | Bin 0 -> 30974 bytes doc/workflow/img/file_finder_find_file.png | Bin 0 -> 42658 bytes 4 files changed, 43 insertions(+) create mode 100644 doc/workflow/file_finder.md create mode 100644 doc/workflow/img/file_finder_find_button.png create mode 100644 doc/workflow/img/file_finder_find_file.png diff --git a/doc/workflow/README.md b/doc/workflow/README.md index 3651b55f438..bf62ab41053 100644 --- a/doc/workflow/README.md +++ b/doc/workflow/README.md @@ -6,6 +6,7 @@ - [GitLab Flow](gitlab_flow.md) - [Groups](groups.md) - [Keyboard shortcuts](shortcuts.md) +- [File finder](file_finder.md) - [Labels](labels.md) - [Notification emails](notifications.md) - [Project Features](project_features.md) diff --git a/doc/workflow/file_finder.md b/doc/workflow/file_finder.md new file mode 100644 index 00000000000..52ac5f032a5 --- /dev/null +++ b/doc/workflow/file_finder.md @@ -0,0 +1,42 @@ +# File finder + +_**Note:** This feature was [introduced][gh-9889] in GitLab 8.4._ + +--- + +The file finder feature allows you to quickly shortcut your way when you are +searching for a file in a repository using the GitLab UI. + +You can find the **Find File** button when in the **Files** section of a +project. + +![Find file button](img/file_finder_find_button.png) + +--- + +For the more lazy, there is a [shortcut button](shortcuts.md) as well. + +Go the **Files** section of a project and press `t` on your keyboard to launch +the search function. Start typing what you are searching for and watch the +magic being unfold. With the up/down arrows, you go up and down the results, +with `Esc` you close the search and go back to **Files**. + +## How it works + +The File finder feature is powered by the [Fuzzy filter] library. + +It implements a fuzzy search with highlight, and tries to provide intuitive +results by recognizing patterns that people use while searching. + +For example, consider the [GitLab CE repository][ce] and that we want to open +the `app/controllers/admin/deploy_keys_controller.rb` file. + +Using fuzzy search, we start by typing letters that get us closer to the file. + +**Protip:** To narrow down your search, include `/` in your search terms. + +![Find file button](img/file_finder_find_file.png) + +[gh-9889]: https://github.com/gitlabhq/gitlabhq/pull/9889 "File finder pull request" +[fuzzy filter]: https://github.com/jeancroy/fuzzaldrin-plus "fuzzaldrin-plus on GitHub" +[ce]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master "GitLab CE repository" diff --git a/doc/workflow/img/file_finder_find_button.png b/doc/workflow/img/file_finder_find_button.png new file mode 100644 index 00000000000..c5005d0d7ca Binary files /dev/null and b/doc/workflow/img/file_finder_find_button.png differ diff --git a/doc/workflow/img/file_finder_find_file.png b/doc/workflow/img/file_finder_find_file.png new file mode 100644 index 00000000000..58500f4c163 Binary files /dev/null and b/doc/workflow/img/file_finder_find_file.png differ -- cgit v1.2.1 From 9369b7ec1f98f8e94a0483e4fbb8c36c2333d60b Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 21 Jan 2016 22:46:49 +0100 Subject: Fix MR diff 'Edit' button --- app/controllers/concerns/creates_commit.rb | 2 +- app/helpers/blob_helper.rb | 12 ++++----- app/helpers/commits_helper.rb | 2 +- app/views/projects/diffs/_file.html.haml | 40 ++++++++++++++---------------- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/app/controllers/concerns/creates_commit.rb b/app/controllers/concerns/creates_commit.rb index 62127a09081..b9eb0a22f88 100644 --- a/app/controllers/concerns/creates_commit.rb +++ b/app/controllers/concerns/creates_commit.rb @@ -97,7 +97,7 @@ module CreatesCommit # Merge request from fork to this project @mr_source_project = @tree_edit_project @mr_target_project = @project - @mr_target_branch = @mr_target_project.repository.root_ref + @mr_target_branch = @ref end end end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 7c55934edda..8b689b29a41 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -26,10 +26,10 @@ module BlobHelper tree_join(ref, path), link_opts) - if !on_top_of_branch? + if !on_top_of_branch?(project, ref) button_tag "Edit", class: "btn btn-default disabled has_tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' } - elsif can_edit_blob?(blob) - link_to "Edit", edit_path, class: 'btn btn-small' + elsif can_edit_blob?(blob, project, ref) + link_to "Edit", edit_path, class: 'btn' elsif can?(current_user, :fork_project, project) continue_params = { to: edit_path, @@ -39,7 +39,7 @@ module BlobHelper fork_path = namespace_project_fork_path(project.namespace, project, namespace_key: current_user.namespace.id, continue: continue_params) - link_to "Edit", fork_path, class: 'btn btn-small', method: :post + link_to "Edit", fork_path, class: 'btn', method: :post end end @@ -50,11 +50,11 @@ module BlobHelper return unless blob - if !on_top_of_branch? + if !on_top_of_branch?(project, ref) button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' } elsif blob.lfs_pointer? button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "It is not possible to #{action} files that are stored in LFS using the web interface", data: { container: 'body' } - elsif can_edit_blob?(blob) + elsif can_edit_blob?(blob, project, ref) button_tag label, class: "btn btn-#{btn_class}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal' elsif can?(current_user, :fork_project, project) continue_params = { diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 590d20ac7b3..d26f007c8e6 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -166,7 +166,7 @@ module CommitsHelper link_to( namespace_project_blob_path(project.namespace, project, tree_join(commit_sha, diff.new_path)), - class: 'btn btn-small view-file js-view-file' + class: 'btn view-file js-view-file' ) do raw('View file @') + content_tag(:span, commit_sha[0..6], class: 'commit-short-id') diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index 517f6aef7c5..fc0eaef2286 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -1,39 +1,37 @@ -.diff-file{id: "diff-#{i}", data: diff_file_html_data(project, diff_commit, diff_file)} - .diff-header{id: "file-path-#{hexdigest(diff_file.file_path)}"} +.diff-file.file-holder{id: "diff-#{i}", data: diff_file_html_data(project, diff_commit, diff_file)} + .file-title{id: "file-path-#{hexdigest(diff_file.file_path)}"} - if diff_file.diff.submodule? %span = icon('archive fw') %strong = submodule_link(blob, @commit.id, project.repository) - else - %span - = blob_icon blob.mode, blob.name - = link_to "#diff-#{i}" do - %strong - = diff_file.new_path + = blob_icon blob.mode, blob.name + = link_to "#diff-#{i}" do + %strong + = diff_file.new_path - - if diff_file.deleted_file - deleted - - elsif diff_file.renamed_file - renamed from - %strong - = diff_file.old_path + - if diff_file.deleted_file + deleted + - elsif diff_file.renamed_file + renamed from + %strong + = diff_file.old_path - - if diff_file.mode_changed? - %small - = "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}" + - if diff_file.mode_changed? + %small + = "#{diff_file.diff.a_mode} → #{diff_file.diff.b_mode}" - .diff-controls + .file-actions.hidden-xs - if blob_text_viewable?(blob) - = link_to '#', class: 'js-toggle-diff-comments btn btn-sm active has_tooltip', title: "Toggle comments for this file" do - %i.fa.fa-comments -   + = link_to '#', class: 'js-toggle-diff-comments btn active has_tooltip', title: "Toggle comments for this file" do + = icon('comments') + \ - if editable_diff?(diff_file) = edit_blob_link(@merge_request.source_project, @merge_request.source_branch, diff_file.new_path, from_merge_request_id: @merge_request.id) -   = view_file_btn(diff_commit.id, diff_file, project) -- cgit v1.2.1 From e08e90edbbd28533f215f0dcf274baefb9fc87fd Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 21 Jan 2016 23:10:47 +0100 Subject: Refactor housekeeping documentation [ci skip] --- doc/administration/housekeeping.md | 21 +++++++++++++++------ doc/administration/img/housekeeping_settings.png | Bin 0 -> 23856 bytes 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 doc/administration/img/housekeeping_settings.png diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md index b90f916fea9..c27cf1812dc 100644 --- a/doc/administration/housekeeping.md +++ b/doc/administration/housekeeping.md @@ -1,13 +1,22 @@ # Housekeeping -## Introduction +_**Note:** This feature was [introduced][ce-2371] in GitLab 8.4_ -The housekeeping function runs `git gc` on the current project git repository. +--- -`git gc` runs a number of housekeeping tasks, such as compressing file revisions (to reduce disk space and increase performance) and removing unreachable objects which may have been created from prior invocations of git add. +The housekeeping function runs [`git gc`][man] on the current project Git +repository. -See https://www.kernel.org/pub/software/scm/git/docs/git-gc.html for details. +`git gc` runs a number of housekeeping tasks, such as compressing file +revisions (to reduce disk space and increase performance) and removing +unreachable objects which may have been created from prior invocations of +`git add`. -## Where can I find it? +You can find this option under your **[Project] > Settings**. -Just go to your project settings page and you will find the housekeeping function below the project settings form. +--- + +![Housekeeping settings](img/housekeeping_settings.png) + +[ce-2371]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2371 "Housekeeping merge request" +[man]: https://www.kernel.org/pub/software/scm/git/docs/git-gc.html "git gc man page" diff --git a/doc/administration/img/housekeeping_settings.png b/doc/administration/img/housekeeping_settings.png new file mode 100644 index 00000000000..f7c5bc44367 Binary files /dev/null and b/doc/administration/img/housekeeping_settings.png differ -- cgit v1.2.1 From 68ac1a665846676057d4a845a1af3274db70c160 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Fri, 22 Jan 2016 00:23:20 +0100 Subject: File finder can be invoked from anywhere! [ci skip] --- doc/workflow/file_finder.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/workflow/file_finder.md b/doc/workflow/file_finder.md index 52ac5f032a5..4bf0a179411 100644 --- a/doc/workflow/file_finder.md +++ b/doc/workflow/file_finder.md @@ -14,12 +14,15 @@ project. --- -For the more lazy, there is a [shortcut button](shortcuts.md) as well. +For the more lazy, there is a [shortcut button](shortcuts.md) as well, which +you can invoke from _anywhere_ in a project. -Go the **Files** section of a project and press `t` on your keyboard to launch -the search function. Start typing what you are searching for and watch the -magic being unfold. With the up/down arrows, you go up and down the results, -with `Esc` you close the search and go back to **Files**. +Press `t` on your keyboard to launch the File search function when in **Issues**, +**Merge requests**, **Milestones**, even the project's settings. + +Start typing what you are searching for and watch the magic being unfold. With +the up/down arrows, you go up and down the results, with `Esc` you close the +search and go back to **Files**. ## How it works -- cgit v1.2.1 From 150b4f66e6a244b5f6bd1119de3ce68336a9bf9e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 22 Jan 2016 01:43:06 +0100 Subject: Make sure non-highlighted diffs are still escaped --- app/controllers/projects/blob_controller.rb | 4 +++- app/models/note.rb | 8 ++++++-- lib/gitlab/diff/highlight.rb | 16 +++++++++++----- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb index 8133de90a41..bb72232edd7 100644 --- a/app/controllers/projects/blob_controller.rb +++ b/app/controllers/projects/blob_controller.rb @@ -52,7 +52,9 @@ class Projects::BlobController < Projects::ApplicationController def preview @content = params[:content] diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true) - @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/)) + diff_lines = diffy.diff.scan(/.*\n/)[2..-1] + diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines) + @diff_lines = Gitlab::Diff::Highlight.new(diff_lines).highlight render layout: false end diff --git a/app/models/note.rb b/app/models/note.rb index 15f48110ad2..55255d22c2f 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -244,7 +244,7 @@ class Note < ActiveRecord::Base prev_match_line = nil prev_lines = [] - diff_lines.each do |line| + highlighted_diff_lines.each do |line| if line.type == "match" prev_lines.clear prev_match_line = line @@ -261,7 +261,11 @@ class Note < ActiveRecord::Base end def diff_lines - @diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.lines.to_a) + @diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.lines) + end + + def highlighted_diff_lines + Gitlab::Diff::Highlight.new(diff_lines).highlight end def discussion_id diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 179f8164c84..964c89de6c6 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -1,13 +1,17 @@ module Gitlab module Diff class Highlight - attr_reader :diff_file + attr_reader :diff_file, :diff_lines, :raw_lines delegate :old_path, :new_path, :old_ref, :new_ref, to: :diff_file, prefix: :diff - def initialize(diff_file) - @diff_file = diff_file - @diff_lines = diff_file.diff_lines + def initialize(diff_lines) + if diff_lines.is_a?(Gitlab::Diff::File) + @diff_file = diff_file + @diff_lines = diff_file.diff_lines + else + @diff_lines = diff_lines + end @raw_lines = @diff_lines.map(&:text) end @@ -31,7 +35,7 @@ module Gitlab private def highlight_line(diff_line, index) - return html_escape(diff_line.text) unless diff_file.diff_refs + return html_escape(diff_line.text) unless diff_file && diff_file.diff_refs line_prefix = diff_line.text.match(/\A(.)/) ? $1 : ' ' @@ -52,10 +56,12 @@ module Gitlab end def old_lines + return unless diff_file @old_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:old)) end def new_lines + return unless diff_file @new_lines ||= Gitlab::Highlight.highlight_lines(*processing_args(:new)) end -- cgit v1.2.1 From 82d0fa8e451de384150394d8465f6f165adfeae9 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 22 Jan 2016 01:53:01 +0100 Subject: Fix --- lib/gitlab/diff/highlight.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 964c89de6c6..9283b5e185d 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -7,8 +7,8 @@ module Gitlab def initialize(diff_lines) if diff_lines.is_a?(Gitlab::Diff::File) - @diff_file = diff_file - @diff_lines = diff_file.diff_lines + @diff_file = diff_lines + @diff_lines = @diff_file.diff_lines else @diff_lines = diff_lines end -- cgit v1.2.1 From 16d17b78cabe2efd762a4aa0e9fa2c2792fab32d Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 22 Jan 2016 02:10:58 +0100 Subject: Restore diff comments --- app/views/projects/diffs/_text_file.html.haml | 3 ++- lib/gitlab/diff/highlight.rb | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index f4fc6caba0f..2e329a823a6 100644 --- a/app/views/projects/diffs/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -6,6 +6,7 @@ %table.text-file.code.js-syntax-highlight{ class: too_big ? 'hide' : '' } - last_line = 0 + - raw_diff_lines = diff_file.diff_lines - diff_file.highlighted_diff_lines.each_with_index do |line, index| - type = line.type - last_line = line.new_pos @@ -31,7 +32,7 @@ - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code && n.active? }.sort_by(&:created_at) - unless comments.empty? - = render "projects/notes/diff_notes_with_reply", notes: comments, line: line.text + = render "projects/notes/diff_notes_with_reply", notes: comments, line: raw_diff_lines[index].text - if last_line > 0 = render "projects/diffs/match_line", {line: "", diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 179f8164c84..ac8537ad31a 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -12,9 +12,10 @@ module Gitlab end def highlight - @diff_lines.each_with_index do |diff_line, i| + @diff_lines.map.with_index do |diff_line, i| + diff_line = diff_line.dup # ignore highlighting for "match" lines - next if diff_line.type == 'match' || diff_line.type == 'nonewline' + next diff_line if diff_line.type == 'match' || diff_line.type == 'nonewline' rich_line = highlight_line(diff_line, i) @@ -23,9 +24,9 @@ module Gitlab end diff_line.text = rich_line.html_safe - end - @diff_lines + diff_line + end end private -- cgit v1.2.1 From 3db24ec9e80369834ccf7d2423808fcf5e51b5a6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 22 Jan 2016 02:12:43 +0100 Subject: Properly highlight right side of parallel diff --- lib/gitlab/diff/parallel_diff.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/diff/parallel_diff.rb b/lib/gitlab/diff/parallel_diff.rb index c0db3559e3a..74f9b3c050a 100644 --- a/lib/gitlab/diff/parallel_diff.rb +++ b/lib/gitlab/diff/parallel_diff.rb @@ -11,7 +11,8 @@ module Gitlab lines = [] skip_next = false - diff_file.highlighted_diff_lines.each do |line| + highlighted_diff_lines = diff_file.highlighted_diff_lines + highlighted_diff_lines.each do |line| full_line = line.text type = line.type line_code = generate_line_code(diff_file.file_path, line) @@ -21,6 +22,7 @@ module Gitlab next_line = diff_file.next_line(line.index) if next_line + next_line = highlighted_diff_lines[next_line.index] next_line_code = generate_line_code(diff_file.file_path, next_line) next_type = next_line.type next_line = next_line.text -- cgit v1.2.1 From de7ee6c37bbf26509c1c533d915f6dbaecdd6ab3 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Fri, 22 Jan 2016 08:26:48 +0100 Subject: Fix grammar and typos in file finder docs [ci skip] --- doc/workflow/file_finder.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/workflow/file_finder.md b/doc/workflow/file_finder.md index 4bf0a179411..b69ae663272 100644 --- a/doc/workflow/file_finder.md +++ b/doc/workflow/file_finder.md @@ -14,15 +14,16 @@ project. --- -For the more lazy, there is a [shortcut button](shortcuts.md) as well, which -you can invoke from _anywhere_ in a project. +For those who prefer to keep their fingers on the keyboard, there is a +[shortcut button](shortcuts.md) as well, which you can invoke from _anywhere_ +in a project. -Press `t` on your keyboard to launch the File search function when in **Issues**, +Press `t` to launch the File search function when in **Issues**, **Merge requests**, **Milestones**, even the project's settings. -Start typing what you are searching for and watch the magic being unfold. With -the up/down arrows, you go up and down the results, with `Esc` you close the -search and go back to **Files**. +Start typing what you are searching for and watch the magic happen. With the +up/down arrows, you go up and down the results, with `Esc` you close the search +and go back to **Files**. ## How it works -- cgit v1.2.1