From 295cecfb56af4e064340d255140a28959c47b25d Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Sun, 7 May 2017 08:29:43 +1100 Subject: Allow numeric values in gitlab-ci.yml --- lib/gitlab/ci/config/entry/legacy_validation_helpers.rb | 8 +++++++- lib/gitlab/ci/config/entry/variables.rb | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb b/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb index 9b9a0a8125a..a78a85397bd 100644 --- a/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb +++ b/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb @@ -21,7 +21,13 @@ module Gitlab def validate_variables(variables) variables.is_a?(Hash) && - variables.all? { |key, value| validate_string(key) && validate_string(value) } + variables.flatten.all? do |value| + validate_string(value) || validate_integer(value) + end + end + + def validate_integer(value) + value.is_a?(Integer) end def validate_string(value) diff --git a/lib/gitlab/ci/config/entry/variables.rb b/lib/gitlab/ci/config/entry/variables.rb index c3b0e651c3a..8acab605c91 100644 --- a/lib/gitlab/ci/config/entry/variables.rb +++ b/lib/gitlab/ci/config/entry/variables.rb @@ -15,6 +15,10 @@ module Gitlab def self.default {} end + + def value + Hash[@config.map { |key, value| [key.to_s, value.to_s] }] + end end end end -- cgit v1.2.3 From 1ebd9dad8e4a3ade4fa829d1d5ac6cbc9825bf48 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 8 May 2017 07:41:58 +0000 Subject: Add confirm delete protected branch modal --- lib/gitlab/checks/change_access.rb | 68 +++++++++++++++++++++++--------------- lib/gitlab/user_access.rb | 10 ++++++ 2 files changed, 51 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb index 8793b20aa35..c984eb20606 100644 --- a/lib/gitlab/checks/change_access.rb +++ b/lib/gitlab/checks/change_access.rb @@ -1,7 +1,6 @@ module Gitlab module Checks class ChangeAccess - # protocol is currently used only in EE attr_reader :user_access, :project, :skip_authorization, :protocol def initialize( @@ -18,7 +17,9 @@ module Gitlab end def exec - error = push_checks || tag_checks || protected_branch_checks + return GitAccessStatus.new(true) if skip_authorization + + error = push_checks || branch_checks || tag_checks if error GitAccessStatus.new(false, error) @@ -29,35 +30,59 @@ module Gitlab protected - def protected_branch_checks - return if skip_authorization + def push_checks + if user_access.cannot_do_action?(:push_code) + "You are not allowed to push code to this project." + end + end + + def branch_checks return unless @branch_name + + if deletion? && @branch_name == project.default_branch + return "The default branch of a project cannot be deleted." + end + + protected_branch_checks + end + + def protected_branch_checks return unless ProtectedBranch.protected?(project, @branch_name) if forced_push? return "You are not allowed to force push code to a protected branch on this project." - elsif deletion? - return "You are not allowed to delete protected branches from this project." end + if deletion? + protected_branch_deletion_checks + else + protected_branch_push_checks + end + end + + def protected_branch_deletion_checks + unless user_access.can_delete_branch?(@branch_name) + return 'You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.' + end + + unless protocol == 'web' + 'You can only delete protected branches using the web interface.' + end + end + + def protected_branch_push_checks if matching_merge_request? - if user_access.can_merge_to_branch?(@branch_name) || user_access.can_push_to_branch?(@branch_name) - return - else + unless user_access.can_merge_to_branch?(@branch_name) || user_access.can_push_to_branch?(@branch_name) "You are not allowed to merge code into protected branches on this project." end else - if user_access.can_push_to_branch?(@branch_name) - return - else + unless user_access.can_push_to_branch?(@branch_name) "You are not allowed to push code to protected branches on this project." end end end def tag_checks - return if skip_authorization - return unless @tag_name if tag_exists? && user_access.cannot_do_action?(:admin_project) @@ -68,7 +93,8 @@ module Gitlab end def protected_tag_checks - return unless tag_protected? + return unless ProtectedTag.protected?(project, @tag_name) + return "Protected tags cannot be updated." if update? return "Protected tags cannot be deleted." if deletion? @@ -77,18 +103,6 @@ module Gitlab end end - def tag_protected? - ProtectedTag.protected?(project, @tag_name) - end - - def push_checks - return if skip_authorization - - if user_access.cannot_do_action?(:push_code) - "You are not allowed to push code to this project." - end - end - private def tag_exists? diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb index e46ff313654..3b922da7ced 100644 --- a/lib/gitlab/user_access.rb +++ b/lib/gitlab/user_access.rb @@ -38,6 +38,16 @@ module Gitlab end end + def can_delete_branch?(ref) + return false unless can_access_git? + + if ProtectedBranch.protected?(project, ref) + user.can?(:delete_protected_branch, project) + else + user.can?(:push_code, project) + end + end + def can_push_to_branch?(ref) return false unless can_access_git? -- cgit v1.2.3 From 7854824b8fe13312819812726c991f5a4c48d9d8 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Mon, 8 May 2017 10:38:26 +0000 Subject: Add index_redirect_routes_path_for_link migration to setup_postgresql.rake --- lib/tasks/migrate/setup_postgresql.rake | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/tasks/migrate/setup_postgresql.rake b/lib/tasks/migrate/setup_postgresql.rake index 1e00b47303d..4108cee08b4 100644 --- a/lib/tasks/migrate/setup_postgresql.rake +++ b/lib/tasks/migrate/setup_postgresql.rake @@ -4,6 +4,7 @@ require Rails.root.join('db/migrate/20151007120511_namespaces_projects_path_lowe require Rails.root.join('db/migrate/20151008110232_add_users_lower_username_email_indexes') require Rails.root.join('db/migrate/20161212142807_add_lower_path_index_to_routes') require Rails.root.join('db/migrate/20170317203554_index_routes_path_for_like') +require Rails.root.join('db/migrate/20170503185032_index_redirect_routes_path_for_like') desc 'GitLab | Sets up PostgreSQL' task setup_postgresql: :environment do -- cgit v1.2.3 From 0151325dacebb99d54b6effb1d5842c0c712168c Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Tue, 9 May 2017 04:15:34 +0000 Subject: Merge request widget redesign --- lib/gitlab/prometheus.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/prometheus.rb b/lib/gitlab/prometheus.rb index 8827507955d..37125980b1c 100644 --- a/lib/gitlab/prometheus.rb +++ b/lib/gitlab/prometheus.rb @@ -13,18 +13,18 @@ module Gitlab json_api_get('query', query: '1') end - def query(query) + def query(query, time: Time.now) get_result('vector') do - json_api_get('query', query: query) + json_api_get('query', query: query, time: time.utc.to_f) end end - def query_range(query, start: 8.hours.ago) + def query_range(query, start: 8.hours.ago, stop: Time.now) get_result('matrix') do json_api_get('query_range', query: query, start: start.to_f, - end: Time.now.utc.to_f, + end: stop.to_f, step: 1.minute.to_i) end end -- cgit v1.2.3 From 48254d187f421dfeb85a84bf2b86399add6e6a67 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 9 May 2017 12:27:17 +0200 Subject: Don't use DiffCollection for deltas --- lib/gitlab/git/commit.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index 3a73697dc5d..f9a9b767ef4 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -192,6 +192,10 @@ module Gitlab Commit.diff_from_parent(raw_commit, options) end + def deltas + @deltas ||= diff_from_parent.each_delta.map { |d| Gitlab::Git::Diff.new(d) } + end + def has_zero_stats? stats.total.zero? rescue -- cgit v1.2.3 From fc0e00bd3c7c99072675bf625b3832eb29464649 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 28 Mar 2017 18:03:42 +0200 Subject: Remove some unused Gitlab::Git code --- lib/gitlab/git/repository.rb | 50 -------------------------------------------- 1 file changed, 50 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 6a0f12b7e50..9ed12ead023 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1112,56 +1112,6 @@ module Gitlab end end - def archive_to_file(treeish = 'master', filename = 'archive.tar.gz', format = nil, compress_cmd = %w(gzip -n)) - git_archive_cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path} archive) - - # Put files into a directory before archiving - prefix = "#{archive_name(treeish)}/" - git_archive_cmd << "--prefix=#{prefix}" - - # Format defaults to tar - git_archive_cmd << "--format=#{format}" if format - - git_archive_cmd += %W(-- #{treeish}) - - open(filename, 'w') do |file| - # Create a pipe to act as the '|' in 'git archive ... | gzip' - pipe_rd, pipe_wr = IO.pipe - - # Get the compression process ready to accept data from the read end - # of the pipe - compress_pid = spawn(*nice(compress_cmd), in: pipe_rd, out: file) - # The read end belongs to the compression process now; we should - # close our file descriptor for it. - pipe_rd.close - - # Start 'git archive' and tell it to write into the write end of the - # pipe. - git_archive_pid = spawn(*nice(git_archive_cmd), out: pipe_wr) - # The write end belongs to 'git archive' now; close it. - pipe_wr.close - - # When 'git archive' and the compression process are finished, we are - # done. - Process.waitpid(git_archive_pid) - raise "#{git_archive_cmd.join(' ')} failed" unless $?.success? - Process.waitpid(compress_pid) - raise "#{compress_cmd.join(' ')} failed" unless $?.success? - end - end - - def nice(cmd) - nice_cmd = %w(nice -n 20) - unless unsupported_platform? - nice_cmd += %w(ionice -c 2 -n 7) - end - nice_cmd + cmd - end - - def unsupported_platform? - %w[darwin freebsd solaris].map { |platform| RUBY_PLATFORM.include?(platform) }.any? - end - # Returns true if the index entry has the special file mode that denotes # a submodule. def submodule?(index_entry) -- cgit v1.2.3 From 29a3203b3fe08649b80def65b7750a866454d3d6 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Wed, 10 May 2017 15:26:17 +1100 Subject: Use relative paths for group/project/user avatars --- lib/api/entities.rb | 13 ++++++++++--- lib/api/v3/entities.rb | 8 ++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index f8f5548d23d..00d494f02f5 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -5,7 +5,10 @@ module API end class UserBasic < UserSafe - expose :id, :state, :avatar_url + expose :id, :state + expose :avatar_url do |user, options| + user.avatar_url(only_path: false) + end expose :web_url do |user, options| Gitlab::Routing.url_helpers.user_url(user) @@ -97,7 +100,9 @@ module API expose :creator_id expose :namespace, using: 'API::Entities::Namespace' expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? } - expose :avatar_url + expose :avatar_url do |user, options| + user.avatar_url(only_path: false) + end expose :star_count, :forks_count expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) && project.default_issues_tracker? } expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] } @@ -141,7 +146,9 @@ module API class Group < Grape::Entity expose :id, :name, :path, :description, :visibility expose :lfs_enabled?, as: :lfs_enabled - expose :avatar_url + expose :avatar_url do |user, options| + user.avatar_url(only_path: false) + end expose :web_url expose :request_access_enabled expose :full_name, :full_path diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index 7c8be7e51db..56a9b019f1b 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -69,7 +69,9 @@ module API expose :creator_id expose :namespace, using: 'API::Entities::Namespace' expose :forked_from_project, using: ::API::Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? } - expose :avatar_url + expose :avatar_url do |user, options| + user.avatar_url(only_path: false) + end expose :star_count, :forks_count expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) && project.default_issues_tracker? } expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] } @@ -129,7 +131,9 @@ module API class Group < Grape::Entity expose :id, :name, :path, :description, :visibility_level expose :lfs_enabled?, as: :lfs_enabled - expose :avatar_url + expose :avatar_url do |user, options| + user.avatar_url(only_path: false) + end expose :web_url expose :request_access_enabled expose :full_name, :full_path -- cgit v1.2.3 From e179707844b043fac6f81a30f82e5f4ba446abde Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Sun, 10 Jul 2016 15:10:59 -0500 Subject: Extract generic parts of Gitlab::Diff::InlineDiffMarker --- lib/gitlab/diff/inline_diff_markdown_marker.rb | 17 ++++ lib/gitlab/diff/inline_diff_marker.rb | 130 ++----------------------- lib/gitlab/string_range_marker.rb | 102 +++++++++++++++++++ 3 files changed, 126 insertions(+), 123 deletions(-) create mode 100644 lib/gitlab/diff/inline_diff_markdown_marker.rb create mode 100644 lib/gitlab/string_range_marker.rb (limited to 'lib') diff --git a/lib/gitlab/diff/inline_diff_markdown_marker.rb b/lib/gitlab/diff/inline_diff_markdown_marker.rb new file mode 100644 index 00000000000..c2a2eb15931 --- /dev/null +++ b/lib/gitlab/diff/inline_diff_markdown_marker.rb @@ -0,0 +1,17 @@ +module Gitlab + module Diff + class InlineDiffMarkdownMarker < Gitlab::StringRangeMarker + MARKDOWN_SYMBOLS = { + addition: "+", + deletion: "-" + }.freeze + + def mark(line_inline_diffs, mode: nil) + super(line_inline_diffs) do |text, left:, right:| + symbol = MARKDOWN_SYMBOLS[mode] + "{#{symbol}#{text}#{symbol}}" + end + end + end + end +end diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb index 736933b1c4b..919965100ae 100644 --- a/lib/gitlab/diff/inline_diff_marker.rb +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -1,137 +1,21 @@ module Gitlab module Diff - class InlineDiffMarker - MARKDOWN_SYMBOLS = { - addition: "+", - deletion: "-" - }.freeze - - attr_accessor :raw_line, :rich_line - - def initialize(raw_line, rich_line = raw_line) - @raw_line = raw_line - @rich_line = ERB::Util.html_escape(rich_line) - end - - def mark(line_inline_diffs, mode: nil, markdown: false) - return rich_line unless line_inline_diffs - - 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.concat(collapse_ranges(inline_diff_positions)) - end - - offset = 0 - - # Mark each range - marker_ranges.each_with_index do |range, index| - before_content = - if markdown - "{#{MARKDOWN_SYMBOLS[mode]}" - else - "" - end - after_content = - if markdown - "#{MARKDOWN_SYMBOLS[mode]}}" - else - "" - end - offset = insert_around_range(rich_line, range, before_content, after_content, offset) + class InlineDiffMarker < Gitlab::StringRangeMarker + def mark(line_inline_diffs, mode: nil) + super(line_inline_diffs) do |text, left:, right:| + %{#{text}} end - - rich_line.html_safe end private - def html_class_names(marker_ranges, mode, index) + def html_class_names(left, right, mode) class_names = ["idiff"] - class_names << "left" if index == 0 - class_names << "right" if index == marker_ranges.length - 1 + class_names << "left" if left + class_names << "right" if right class_names << mode if mode class_names.join(" ") end - - # Mapping of character positions in the raw line, to the rich (highlighted) line - def position_mapping - @position_mapping ||= begin - mapping = [] - rich_pos = 0 - (0..raw_line.length).each do |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 - rich_char = rich_line[rich_pos] - end - - rich_pos += 1 - rich_char = rich_line[rich_pos] - end - - # 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 - - mapping - 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 = [] - - 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 - - # 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 - - text.insert(offset + range.end + 1, after) - offset += after.length - - offset - end end end end diff --git a/lib/gitlab/string_range_marker.rb b/lib/gitlab/string_range_marker.rb new file mode 100644 index 00000000000..94fba0a221a --- /dev/null +++ b/lib/gitlab/string_range_marker.rb @@ -0,0 +1,102 @@ +module Gitlab + class StringRangeMarker + attr_accessor :raw_line, :rich_line + + def initialize(raw_line, rich_line = raw_line) + @raw_line = raw_line + @rich_line = ERB::Util.html_escape(rich_line) + end + + def mark(marker_ranges) + return rich_line unless marker_ranges + + rich_marker_ranges = [] + marker_ranges.each do |range| + # Map the inline-diff range based on the raw line to character positions in the rich line + rich_positions = position_mapping[range].flatten + # Turn the array of character positions into ranges + rich_marker_ranges.concat(collapse_ranges(rich_positions)) + end + + offset = 0 + # Mark each range + rich_marker_ranges.each_with_index do |range, i| + offset_range = (range.begin + offset)..(range.end + offset) + original_text = rich_line[offset_range] + + text = yield(original_text, left: i == 0, right: i == rich_marker_ranges.length - 1) + + rich_line[offset_range] = text + + offset += text.length - original_text.length + end + + rich_line.html_safe + end + + private + + # Mapping of character positions in the raw line, to the rich (highlighted) line + def position_mapping + @position_mapping ||= begin + mapping = [] + rich_pos = 0 + (0..raw_line.length).each do |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 + rich_char = rich_line[rich_pos] + end + + rich_pos += 1 + rich_char = rich_line[rich_pos] + end + + # 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 + + mapping + 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 = [] + + 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 + end +end -- cgit v1.2.3 From 3f6d91c53c1bf99ce2e7dfeb9c25ef5f8149b72e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Sun, 10 Jul 2016 15:17:20 -0500 Subject: Add Gitlab::StringRegexMarker --- lib/gitlab/string_regex_marker.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lib/gitlab/string_regex_marker.rb (limited to 'lib') diff --git a/lib/gitlab/string_regex_marker.rb b/lib/gitlab/string_regex_marker.rb new file mode 100644 index 00000000000..7ebf1c0428c --- /dev/null +++ b/lib/gitlab/string_regex_marker.rb @@ -0,0 +1,13 @@ +module Gitlab + class StringRegexMarker < StringRangeMarker + def mark(regex, group: 0, &block) + regex_match = raw_line.match(regex) + return rich_line unless regex_match + + begin_index, end_index = regex_match.offset(group) + name_range = begin_index..(end_index - 1) + + super([name_range], &block) + end + end +end -- cgit v1.2.3 From b1012d986c4142d7c45d46fa70511ea5faa6150f Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Sun, 10 Jul 2016 16:13:06 -0500 Subject: Autolink package names in Gemfile --- lib/gitlab/dependency_linker.rb | 18 +++++ lib/gitlab/dependency_linker/base_linker.rb | 103 +++++++++++++++++++++++++ lib/gitlab/dependency_linker/gemfile_linker.rb | 28 +++++++ lib/gitlab/highlight.rb | 37 ++++++--- 4 files changed, 176 insertions(+), 10 deletions(-) create mode 100644 lib/gitlab/dependency_linker.rb create mode 100644 lib/gitlab/dependency_linker/base_linker.rb create mode 100644 lib/gitlab/dependency_linker/gemfile_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb new file mode 100644 index 00000000000..5e884c4bea1 --- /dev/null +++ b/lib/gitlab/dependency_linker.rb @@ -0,0 +1,18 @@ +module Gitlab + module DependencyLinker + LINKERS = [ + GemfileLinker, + ].freeze + + def self.linker(blob_name) + LINKERS.find { |linker| linker.support?(blob_name) } + end + + def self.link(blob_name, plain_text, highlighted_text) + linker = linker(blob_name) + return highlighted_text unless linker + + linker.link(plain_text, highlighted_text) + end + end +end diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb new file mode 100644 index 00000000000..40a4ad11372 --- /dev/null +++ b/lib/gitlab/dependency_linker/base_linker.rb @@ -0,0 +1,103 @@ +module Gitlab + module DependencyLinker + class BaseLinker + def self.link(plain_text, highlighted_text) + new(plain_text, highlighted_text).link + end + + attr_accessor :plain_text, :highlighted_text + + def initialize(plain_text, highlighted_text) + @plain_text = plain_text + @highlighted_text = highlighted_text + end + + def link + link_dependencies + + highlighted_lines.join.html_safe + end + + private + + def package_url(name) + raise NotImplementedError + end + + def link_dependencies + raise NotImplementedError + end + + def package_link(name, url = package_url(name)) + return name unless url + + %{#{ERB::Util.html_escape_once(name)}} + end + + # Links package names in a method call or assignment string argument. + # + # Example: + # link_method_call("gem") + # # Will link `package` in `gem "package"`, `gem("package")` and `gem = "package"` + # + # link_method_call("gem", "specific_package") + # # Will link `specific_package` in `gem "specific_package"` + # + # link_method_call("github", /[^\/]+\/[^\/]+/) + # # Will link `user/repo` in `github "user/repo"`, but not `github "package"` + # + # link_method_call(%w[add_dependency add_development_dependency]) + # # Will link `spec.add_dependency "package"` and `spec.add_development_dependency "package"` + # + # link_method_call("name") + # # Will link `package` in `self.name = "package"` + def link_method_call(method_names, value = nil, &url_proc) + value = + case value + when String + Regexp.escape(value) + when nil + /[^'"]+/ + else + value + end + + method_names = Array(method_names).map { |name| Regexp.escape(name) } + + regex = %r{ + #{Regexp.union(method_names)} # Method name + \s* # Whitespace + [(=]? # Opening brace or equals sign + \s* # Whitespace + ['"](?#{value})['"] # Package name in quotes + }x + + link_regex(regex, &url_proc) + end + + # Links package names based on regex. + # + # Example: + # link_regex(/(github:|:github =>)\s*['"](?[^'"]+)['"]/) + # # Will link `user/repo` in `github: "user/repo"` or `:github => "user/repo"` + def link_regex(regex) + highlighted_lines.map!.with_index do |rich_line, i| + marker = StringRegexMarker.new(plain_lines[i], rich_line.html_safe) + + marker.mark(regex, group: :name) do |text, left:, right:| + url = block_given? ? yield(text) : package_url(text) + package_link(text, url) + end + end + end + + def plain_lines + @plain_lines ||= plain_text.lines + end + + def highlighted_lines + @highlighted_lines ||= highlighted_text.lines + end + end + end +end diff --git a/lib/gitlab/dependency_linker/gemfile_linker.rb b/lib/gitlab/dependency_linker/gemfile_linker.rb new file mode 100644 index 00000000000..e36b88d357d --- /dev/null +++ b/lib/gitlab/dependency_linker/gemfile_linker.rb @@ -0,0 +1,28 @@ +module Gitlab + module DependencyLinker + class GemfileLinker < BaseLinker + def self.support?(blob_name) + blob_name == 'Gemfile' || blob_name == 'gems.rb' + end + + private + + def link_dependencies + # Link `gem "package_name"` to https://rubygems.org/gems/package_name + link_method_call("gem") + + # Link `github: "user/repo"` to https://github.com/user/repo + link_regex(/(github:|:github\s*=>)\s*['"](?[^'"]+)['"]/) do |name| + "https://github.com/#{name}" + end + + # Link `source "https://rubygems.org"` to https://rubygems.org + link_method_call("source", %r{https?://[^'"]+}) { |url| url } + end + + def package_url(name) + "https://rubygems.org/gems/#{name}" + end + end + end +end diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb index d787d5db4a0..83bc230df3e 100644 --- a/lib/gitlab/highlight.rb +++ b/lib/gitlab/highlight.rb @@ -13,6 +13,8 @@ module Gitlab highlight(file_name, blob.data, repository: repository).lines.map!(&:html_safe) end + attr_reader :blob_name + def initialize(blob_name, blob_content, repository: nil) @formatter = Rouge::Formatters::HTMLGitlab @repository = repository @@ -21,16 +23,9 @@ module Gitlab end def highlight(text, continue: true, plain: false) - if plain - hl_lexer = Rouge::Lexers::PlainText - continue = false - else - hl_lexer = self.lexer - end - - @formatter.format(hl_lexer.lex(text, continue: continue), tag: hl_lexer.tag).html_safe - rescue - @formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe + highlighted_text = highlight_text(text, continue: continue, plain: plain) + highlighted_text = link_dependencies(text, highlighted_text) if blob_name + highlighted_text end def lexer @@ -50,5 +45,27 @@ module Gitlab Rouge::Lexer.find_fancy(language_name) end + + def highlight_text(text, continue: true, plain: false) + if plain + highlight_plain(text) + else + highlight_rich(text, continue: continue) + end + end + + def highlight_plain(text) + @formatter.format(Rouge::Lexers::PlainText.lex(text)).html_safe + end + + def highlight_rich(text, continue: true) + @formatter.format(lexer.lex(text, continue: continue), tag: lexer.tag).html_safe + rescue + highlight_plain(text) + end + + def link_dependencies(text, highlighted_text) + Gitlab::DependencyLinker.link(blob_name, text, highlighted_text) + end end end -- cgit v1.2.3 From b03179b4a6be9a59d7856059284e7d18ed8328f1 Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Wed, 10 May 2017 13:21:23 +0200 Subject: Print Go version in rake gitlab:env:info --- lib/tasks/gitlab/info.rake | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake index a2a2db487b7..e3883278886 100644 --- a/lib/tasks/gitlab/info.rake +++ b/lib/tasks/gitlab/info.rake @@ -16,6 +16,8 @@ namespace :gitlab do redis_version = run_and_match(%w(redis-cli --version), /redis-cli (\d+\.\d+\.\d+)/).to_a # check Git version git_version = run_and_match([Gitlab.config.git.bin_path, '--version'], /git version ([\d\.]+)/).to_a + # check Go version + go_version = run_and_match(%w(go version), /go version (.+)/).to_a puts "" puts "System information".color(:yellow) @@ -30,6 +32,7 @@ namespace :gitlab do puts "Redis Version:\t#{redis_version[1] || "unknown".color(:red)}" puts "Git Version:\t#{git_version[1] || "unknown".color(:red)}" puts "Sidekiq Version:#{Sidekiq::VERSION}" + puts "Go Version:\t#{go_version[1] || "unknown".color(:red)}" # check database adapter database_adapter = ActiveRecord::Base.connection.adapter_name.downcase -- cgit v1.2.3 From 99996b6bc7c13e7e7f871919942907b380d4b58c Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 2 May 2017 14:52:19 +0000 Subject: Merge branch 'bvl-security-9-1-markup-pipeline' (security-9-1) Render asciidoc & other markup using banzai in a pipeline See merge request !2098 --- lib/banzai/pipeline/markup_pipeline.rb | 13 +++++++++++++ lib/gitlab/asciidoc.rb | 8 ++++---- lib/gitlab/other_markup.rb | 6 +++--- 3 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 lib/banzai/pipeline/markup_pipeline.rb (limited to 'lib') diff --git a/lib/banzai/pipeline/markup_pipeline.rb b/lib/banzai/pipeline/markup_pipeline.rb new file mode 100644 index 00000000000..c56d908009f --- /dev/null +++ b/lib/banzai/pipeline/markup_pipeline.rb @@ -0,0 +1,13 @@ +module Banzai + module Pipeline + class MarkupPipeline < BasePipeline + def self.filters + @filters ||= FilterArray[ + Filter::SanitizationFilter, + Filter::ExternalLinkFilter, + Filter::PlantumlFilter + ] + end + end + end +end diff --git a/lib/gitlab/asciidoc.rb b/lib/gitlab/asciidoc.rb index fba80c7132e..96d38f6daa0 100644 --- a/lib/gitlab/asciidoc.rb +++ b/lib/gitlab/asciidoc.rb @@ -15,17 +15,17 @@ module Gitlab # # input - the source text in Asciidoc format # - def self.render(input) + def self.render(input, context) asciidoc_opts = { safe: :secure, backend: :gitlab_html5, attributes: DEFAULT_ADOC_ATTRS } + context[:pipeline] = :markup + plantuml_setup html = ::Asciidoctor.convert(input, asciidoc_opts) - - filter = Banzai::Filter::SanitizationFilter.new(html) - html = filter.call.to_s + html = Banzai.render(html, context) html.html_safe end diff --git a/lib/gitlab/other_markup.rb b/lib/gitlab/other_markup.rb index c2adc9aa10b..31a24460f0f 100644 --- a/lib/gitlab/other_markup.rb +++ b/lib/gitlab/other_markup.rb @@ -5,12 +5,12 @@ module Gitlab # # input - the source text in a markup format # - def self.render(file_name, input) + def self.render(file_name, input, context) html = GitHub::Markup.render(file_name, input). force_encoding(input.encoding) + context[:pipeline] = :markup - filter = Banzai::Filter::SanitizationFilter.new(html) - html = filter.call.to_s + html = Banzai.render(html, context) html.html_safe end -- cgit v1.2.3 From da13d1af3ecfdf124d63c5cf53aca6cac8a9f36d Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 2 May 2017 22:25:58 +0000 Subject: Merge branch 'bvl-security-9-1-validate-urls-in-markdown-using-uri' (security-9-1) Add correct `rel` attributes to external links when rendering markdown See merge request !2097 --- lib/banzai/filter/external_link_filter.rb | 36 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb index d67d466bce8..7d15a0f6d44 100644 --- a/lib/banzai/filter/external_link_filter.rb +++ b/lib/banzai/filter/external_link_filter.rb @@ -2,16 +2,17 @@ module Banzai module Filter # HTML Filter to modify the attributes of external links class ExternalLinkFilter < HTML::Pipeline::Filter + SCHEMES = ['http', 'https', nil].freeze + def call links.each do |node| - href = href_to_lowercase_scheme(node["href"].to_s) + uri = uri(node['href'].to_s) + next unless uri - unless node["href"].to_s == href - node.set_attribute('href', href) - end + node.set_attribute('href', uri.to_s) - if href =~ %r{\A(https?:)?//[^/]} && external_url?(href) - node.set_attribute('rel', 'nofollow noreferrer') + if SCHEMES.include?(uri.scheme) && external_url?(uri) + node.set_attribute('rel', 'nofollow noreferrer noopener') node.set_attribute('target', '_blank') end end @@ -21,27 +22,26 @@ module Banzai private + def uri(href) + URI.parse(href) + rescue URI::InvalidURIError + nil + end + def links query = 'descendant-or-self::a[@href and not(@href = "")]' doc.xpath(query) end - def href_to_lowercase_scheme(href) - scheme_match = href.match(/\A(\w+):\/\//) - - if scheme_match - scheme_match.to_s.downcase + scheme_match.post_match - else - href - end - end + def external_url?(uri) + # Relative URLs miss a hostname + return false unless uri.hostname - def external_url?(url) - !url.start_with?(internal_url) + uri.hostname != internal_url.hostname end def internal_url - @internal_url ||= Gitlab.config.gitlab.url + @internal_url ||= URI.parse(Gitlab.config.gitlab.url) end end end -- cgit v1.2.3 From 61a81a3ac225296f8aefc4d2f350de72a531bf3d Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 24 Apr 2017 15:09:29 +0000 Subject: Merge branch '31157-respect-project-features-in-wiki-search' into 'security' Respect project features in wiki and blob search See merge request !2089 --- lib/gitlab/project_search_results.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb index 0b8959f2fb9..47cfe412715 100644 --- a/lib/gitlab/project_search_results.rb +++ b/lib/gitlab/project_search_results.rb @@ -82,6 +82,8 @@ module Gitlab private def blobs + return [] unless Ability.allowed?(@current_user, :download_code, @project) + @blobs ||= begin blobs = project.repository.search_files_by_content(query, repository_ref).first(100) found_file_names = Set.new @@ -102,6 +104,8 @@ module Gitlab end def wiki_blobs + return [] unless Ability.allowed?(@current_user, :read_wiki, @project) + @wiki_blobs ||= begin if project.wiki_enabled? && query.present? project_wiki = ProjectWiki.new(project) -- cgit v1.2.3 From ad309f5d110ebf8859b2e7196c7a1d0b039c0d7c Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 28 Apr 2017 22:06:27 +0000 Subject: Merge branch 'snippets-finder-visibility' into 'security' Refactor snippets finder & dont return internal snippets for external users See merge request !2094 --- lib/api/project_snippets.rb | 3 +-- lib/api/snippets.rb | 4 ++-- lib/api/v3/project_snippets.rb | 3 +-- lib/api/v3/snippets.rb | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb index cfee38a9baf..98bc9c28527 100644 --- a/lib/api/project_snippets.rb +++ b/lib/api/project_snippets.rb @@ -17,8 +17,7 @@ module API end def snippets_for_current_user - finder_params = { filter: :by_project, project: user_project } - SnippetsFinder.new.execute(current_user, finder_params) + SnippetsFinder.new(current_user, project: user_project).execute end end diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb index b93fdc62808..53f5953a8fb 100644 --- a/lib/api/snippets.rb +++ b/lib/api/snippets.rb @@ -8,11 +8,11 @@ module API resource :snippets do helpers do def snippets_for_current_user - SnippetsFinder.new.execute(current_user, filter: :by_user, user: current_user) + SnippetsFinder.new(current_user, author: current_user).execute end def public_snippets - SnippetsFinder.new.execute(current_user, filter: :public) + SnippetsFinder.new(current_user, visibility: Snippet::PUBLIC).execute end end diff --git a/lib/api/v3/project_snippets.rb b/lib/api/v3/project_snippets.rb index fc065a22d74..c41fee32610 100644 --- a/lib/api/v3/project_snippets.rb +++ b/lib/api/v3/project_snippets.rb @@ -18,8 +18,7 @@ module API end def snippets_for_current_user - finder_params = { filter: :by_project, project: user_project } - SnippetsFinder.new.execute(current_user, finder_params) + SnippetsFinder.new(current_user, project: user_project).execute end end diff --git a/lib/api/v3/snippets.rb b/lib/api/v3/snippets.rb index 07dac7e9904..0762fc02d70 100644 --- a/lib/api/v3/snippets.rb +++ b/lib/api/v3/snippets.rb @@ -8,11 +8,11 @@ module API resource :snippets do helpers do def snippets_for_current_user - SnippetsFinder.new.execute(current_user, filter: :by_user, user: current_user) + SnippetsFinder.new(current_user, author: current_user).execute end def public_snippets - SnippetsFinder.new.execute(current_user, filter: :public) + SnippetsFinder.new(current_user, visibility: Snippet::PUBLIC).execute end end -- cgit v1.2.3 From ea4eb460479a24fea9ee890c8ba8f6f4dec7f44b Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 3 May 2017 23:51:25 +0000 Subject: Merge branch 'tc-fix-private-subgroups-shown' into 'security' Use GroupsFinder to find subgroups the user has access to See merge request !2096 --- lib/api/groups.rb | 2 +- lib/api/v3/groups.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 09d105f6b4c..9ccc75681f9 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -52,7 +52,7 @@ module API elsif current_user.admin Group.all elsif params[:all_available] - GroupsFinder.new.execute(current_user) + GroupsFinder.new(current_user).execute else current_user.groups end diff --git a/lib/api/v3/groups.rb b/lib/api/v3/groups.rb index 63d464b926b..dbf7a3cf785 100644 --- a/lib/api/v3/groups.rb +++ b/lib/api/v3/groups.rb @@ -45,7 +45,7 @@ module API groups = if current_user.admin Group.all elsif params[:all_available] - GroupsFinder.new.execute(current_user) + GroupsFinder.new(current_user).execute else current_user.groups end -- cgit v1.2.3 From ebd8b7f60f41358df562625a4692f352b86b8c80 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Wed, 10 May 2017 12:03:29 +0200 Subject: Use new SnippetsFinder signature in API --- lib/api/helpers.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 86bf567fe69..c643ea8e5a7 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -91,8 +91,8 @@ module API end def find_project_snippet(id) - finder_params = { filter: :by_project, project: user_project } - SnippetsFinder.new.execute(current_user, finder_params).find(id) + finder_params = { project: user_project } + SnippetsFinder.new(current_user, finder_params).execute.find(id) end def find_merge_request_with_access(iid, access_level = :read_merge_request) -- cgit v1.2.3 From 11759374698eb172c05e6a701d4ff7dc5f9d8251 Mon Sep 17 00:00:00 2001 From: Dosuken shinya Date: Wed, 10 May 2017 15:48:09 +0000 Subject: Resolve "Update gem sidekiq-cron from 0.4.4 to 0.6.0 and rufus-scheduler from 3.1.10 to 3.4.0" --- lib/gitlab/ci/cron_parser.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/ci/cron_parser.rb b/lib/gitlab/ci/cron_parser.rb index dad8c3cdf5b..551483d0aaa 100644 --- a/lib/gitlab/ci/cron_parser.rb +++ b/lib/gitlab/ci/cron_parser.rb @@ -11,7 +11,7 @@ module Gitlab def next_time_from(time) @cron_line ||= try_parse_cron(@cron, @cron_timezone) - @cron_line.next_time(time).in_time_zone(Time.zone) if @cron_line.present? + @cron_line.next_time(time).utc.in_time_zone(Time.zone) if @cron_line.present? end def cron_valid? -- cgit v1.2.3 From d40e1f547ea9e31e822229bb808aaa6b9201f473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 3 May 2017 13:22:03 +0200 Subject: Enable the Style/TrailingCommaInLiteral cop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the EnforcedStyleForMultiline: no_comma option. Signed-off-by: Rémy Coutable --- lib/api/internal.rb | 2 +- lib/api/projects.rb | 2 +- lib/api/services.rb | 6 +++--- lib/api/subscriptions.rb | 2 +- lib/api/v3/services.rb | 2 +- lib/api/v3/subscriptions.rb | 2 +- lib/ci/ansi2html.rb | 2 +- lib/ci/gitlab_ci_yaml_processor.rb | 2 +- lib/gitlab/access.rb | 6 +++--- lib/gitlab/chat_commands/command.rb | 2 +- lib/gitlab/cycle_analytics/permissions.rb | 2 +- lib/gitlab/data_builder/build.rb | 6 +++--- lib/gitlab/etag_caching/router.rb | 2 +- lib/gitlab/git/repository.rb | 2 +- lib/gitlab/kubernetes.rb | 4 ++-- lib/gitlab/workhorse.rb | 8 ++++---- lib/tasks/gemojione.rake | 2 +- lib/tasks/gitlab/update_templates.rake | 2 +- lib/tasks/spec.rake | 2 +- 19 files changed, 29 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 2a11790b215..96aaaf868ea 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -90,7 +90,7 @@ module API { api_version: API.version, gitlab_version: Gitlab::VERSION, - gitlab_rev: Gitlab::REVISION, + gitlab_rev: Gitlab::REVISION } end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 9a6cb43abf7..687efe7da65 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -226,7 +226,7 @@ module API :shared_runners_enabled, :snippets_enabled, :visibility, - :wiki_enabled, + :wiki_enabled ] optional :name, type: String, desc: 'The name of the project' optional :default_branch, type: String, desc: 'The default branch of the project' diff --git a/lib/api/services.rb b/lib/api/services.rb index 23ef62c2258..cb07df9e249 100644 --- a/lib/api/services.rb +++ b/lib/api/services.rb @@ -356,7 +356,7 @@ module API name: :ca_pem, type: String, desc: 'A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)' - }, + } ], 'mattermost-slash-commands' => [ { @@ -559,7 +559,7 @@ module API SlackService, MattermostService, MicrosoftTeamsService, - TeamcityService, + TeamcityService ] if Rails.env.development? @@ -577,7 +577,7 @@ module API service_classes += [ MockCiService, MockDeploymentService, - MockMonitoringService, + MockMonitoringService ] end diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb index dbe54d3cd31..91567909998 100644 --- a/lib/api/subscriptions.rb +++ b/lib/api/subscriptions.rb @@ -5,7 +5,7 @@ module API subscribable_types = { 'merge_requests' => proc { |id| find_merge_request_with_access(id, :update_merge_request) }, 'issues' => proc { |id| find_project_issue(id) }, - 'labels' => proc { |id| find_project_label(id) }, + 'labels' => proc { |id| find_project_label(id) } } params do diff --git a/lib/api/v3/services.rb b/lib/api/v3/services.rb index 61629a04174..118c6df6549 100644 --- a/lib/api/v3/services.rb +++ b/lib/api/v3/services.rb @@ -377,7 +377,7 @@ module API name: :ca_pem, type: String, desc: 'A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)' - }, + } ], 'mattermost-slash-commands' => [ { diff --git a/lib/api/v3/subscriptions.rb b/lib/api/v3/subscriptions.rb index 068750ec077..690768db82f 100644 --- a/lib/api/v3/subscriptions.rb +++ b/lib/api/v3/subscriptions.rb @@ -7,7 +7,7 @@ module API 'merge_request' => proc { |id| find_merge_request_with_access(id, :update_merge_request) }, 'merge_requests' => proc { |id| find_merge_request_with_access(id, :update_merge_request) }, 'issues' => proc { |id| find_project_issue(id) }, - 'labels' => proc { |id| find_project_label(id) }, + 'labels' => proc { |id| find_project_label(id) } } params do diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb index b439b0ee29b..55402101e43 100644 --- a/lib/ci/ansi2html.rb +++ b/lib/ci/ansi2html.rb @@ -20,7 +20,7 @@ module Ci italic: 0x02, underline: 0x04, conceal: 0x08, - cross: 0x10, + cross: 0x10 }.freeze def self.convert(ansi, state = nil) diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 15a461a16dd..b06474cda7f 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -70,7 +70,7 @@ module Ci cache: job[:cache], dependencies: job[:dependencies], after_script: job[:after_script], - environment: job[:environment], + environment: job[:environment] }.compact } end diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb index 8c28009b9c6..4714ab18cc1 100644 --- a/lib/gitlab/access.rb +++ b/lib/gitlab/access.rb @@ -32,7 +32,7 @@ module Gitlab "Guest" => GUEST, "Reporter" => REPORTER, "Developer" => DEVELOPER, - "Master" => MASTER, + "Master" => MASTER } end @@ -47,7 +47,7 @@ module Gitlab guest: GUEST, reporter: REPORTER, developer: DEVELOPER, - master: MASTER, + master: MASTER } end @@ -60,7 +60,7 @@ module Gitlab "Not protected: Both developers and masters can push new commits, force push, or delete the branch." => PROTECTION_NONE, "Protected against pushes: Developers cannot push new commits, but are allowed to accept merge requests to the branch." => PROTECTION_DEV_CAN_MERGE, "Partially protected: Developers can push new commits, but cannot force push or delete the branch. Masters can do all of those." => PROTECTION_DEV_CAN_PUSH, - "Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL, + "Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL } end diff --git a/lib/gitlab/chat_commands/command.rb b/lib/gitlab/chat_commands/command.rb index f34ed0f4cf2..3e0c30c33b7 100644 --- a/lib/gitlab/chat_commands/command.rb +++ b/lib/gitlab/chat_commands/command.rb @@ -5,7 +5,7 @@ module Gitlab Gitlab::ChatCommands::IssueShow, Gitlab::ChatCommands::IssueNew, Gitlab::ChatCommands::IssueSearch, - Gitlab::ChatCommands::Deploy, + Gitlab::ChatCommands::Deploy ].freeze def execute diff --git a/lib/gitlab/cycle_analytics/permissions.rb b/lib/gitlab/cycle_analytics/permissions.rb index bef3b95ff1b..1e11e84a9cb 100644 --- a/lib/gitlab/cycle_analytics/permissions.rb +++ b/lib/gitlab/cycle_analytics/permissions.rb @@ -7,7 +7,7 @@ module Gitlab test: :read_build, review: :read_merge_request, staging: :read_build, - production: :read_issue, + production: :read_issue }.freeze def self.get(*args) diff --git a/lib/gitlab/data_builder/build.rb b/lib/gitlab/data_builder/build.rb index f78106f5b10..8e74e18a311 100644 --- a/lib/gitlab/data_builder/build.rb +++ b/lib/gitlab/data_builder/build.rb @@ -36,7 +36,7 @@ module Gitlab user: { id: user.try(:id), name: user.try(:name), - email: user.try(:email), + email: user.try(:email) }, commit: { @@ -49,7 +49,7 @@ module Gitlab status: commit.status, duration: commit.duration, started_at: commit.started_at, - finished_at: commit.finished_at, + finished_at: commit.finished_at }, repository: { @@ -60,7 +60,7 @@ module Gitlab git_http_url: project.http_url_to_repo, git_ssh_url: project.ssh_url_to_repo, visibility_level: project.visibility_level - }, + } } data diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index 692c909d838..31a5b9d108b 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -40,7 +40,7 @@ module Gitlab Gitlab::EtagCaching::Router::Route.new( %r(^(?!.*(#{RESERVED_WORDS})).*/pipelines/\d+\.json\z), 'project_pipeline' - ), + ) ].freeze def self.match(env) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 9ed12ead023..256318cb833 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -258,7 +258,7 @@ module Gitlab 'RepoPath' => path, 'ArchivePrefix' => prefix, 'ArchivePath' => archive_file_path(prefix, storage_path, format), - 'CommitId' => commit.id, + 'CommitId' => commit.id } end diff --git a/lib/gitlab/kubernetes.rb b/lib/gitlab/kubernetes.rb index 3a7af363548..4a6091488c8 100644 --- a/lib/gitlab/kubernetes.rb +++ b/lib/gitlab/kubernetes.rb @@ -38,7 +38,7 @@ module Gitlab url: container_exec_url(api_url, namespace, pod_name, container["name"]), subprotocols: ['channel.k8s.io'], headers: Hash.new { |h, k| h[k] = [] }, - created_at: created_at, + created_at: created_at } end end @@ -64,7 +64,7 @@ module Gitlab tty: true, stdin: true, stdout: true, - stderr: true, + stderr: true }.to_query + '&' + EXEC_COMMAND case url.scheme diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index 8c5ad01e8c2..f3b3dea5318 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -22,7 +22,7 @@ module Gitlab params = { GL_ID: Gitlab::GlId.gl_id(user), GL_REPOSITORY: Gitlab::GlRepository.gl_repository(project, is_wiki), - RepoPath: repo_path, + RepoPath: repo_path } if Gitlab.config.gitaly.enabled @@ -51,7 +51,7 @@ module Gitlab { StoreLFSPath: "#{Gitlab.config.lfs.storage_path}/tmp/upload", LfsOid: oid, - LfsSize: size, + LfsSize: size } end @@ -62,7 +62,7 @@ module Gitlab def send_git_blob(repository, blob) params = { 'RepoPath' => repository.path_to_repo, - 'BlobId' => blob.id, + 'BlobId' => blob.id } [ @@ -127,7 +127,7 @@ module Gitlab 'Subprotocols' => terminal[:subprotocols], 'Url' => terminal[:url], 'Header' => terminal[:headers], - 'MaxSessionTime' => terminal[:max_session_time], + 'MaxSessionTime' => terminal[:max_session_time] } } details['Terminal']['CAPem'] = terminal[:ca_pem] if terminal.has_key?(:ca_pem) diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake index b5572a39d30..87ca39b079b 100644 --- a/lib/tasks/gemojione.rake +++ b/lib/tasks/gemojione.rake @@ -21,7 +21,7 @@ namespace :gemojione do moji: emoji_hash['moji'], description: emoji_hash['description'], unicodeVersion: Gitlab::Emoji.emoji_unicode_version(name), - digest: hash_digest, + digest: hash_digest } resultant_emoji_map[name] = entry diff --git a/lib/tasks/gitlab/update_templates.rake b/lib/tasks/gitlab/update_templates.rake index 1b04e1350ed..59c32bbe7a4 100644 --- a/lib/tasks/gitlab/update_templates.rake +++ b/lib/tasks/gitlab/update_templates.rake @@ -49,7 +49,7 @@ namespace :gitlab do Template.new( "https://gitlab.com/gitlab-org/Dockerfile.git", /(\.{1,2}|LICENSE|CONTRIBUTING.md|\.Dockerfile)\z/ - ), + ) ].freeze def vendor_directory diff --git a/lib/tasks/spec.rake b/lib/tasks/spec.rake index 602c60be828..2eddcb3c777 100644 --- a/lib/tasks/spec.rake +++ b/lib/tasks/spec.rake @@ -60,7 +60,7 @@ desc "GitLab | Run specs" task :spec do cmds = [ %w(rake gitlab:setup), - %w(rspec spec), + %w(rspec spec) ] run_commands(cmds) end -- cgit v1.2.3 From 3db37e05622aa3daa2be41bb9edc486cd2e54bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 3 May 2017 13:27:17 +0200 Subject: Enable the Style/TrailingCommaInArguments cop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the EnforcedStyleForMultiline: no_comma option. Signed-off-by: Rémy Coutable --- lib/api/groups.rb | 2 +- lib/api/helpers.rb | 2 +- lib/api/projects.rb | 2 +- lib/api/v3/groups.rb | 2 +- lib/api/v3/projects.rb | 2 +- lib/gitlab/git/blob.rb | 2 +- lib/gitlab/git/tree.rb | 2 +- lib/gitlab/gitaly_client/commit.rb | 2 +- lib/gitlab/gitaly_client/util.rb | 2 +- lib/gitlab/ldap/config.rb | 2 +- lib/gitlab/sentry.rb | 2 +- lib/gitlab/workhorse.rb | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 09d105f6b4c..450b2f8d9a9 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -24,7 +24,7 @@ module API def present_groups(groups, options = {}) options = options.reverse_merge( with: Entities::Group, - current_user: current_user, + current_user: current_user ) groups = groups.with_statistics if options[:statistics] diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 86bf567fe69..4caa210b9f2 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -301,7 +301,7 @@ module API UploadedFile.new( file_path, params["#{field}.name"], - params["#{field}.type"] || 'application/octet-stream', + params["#{field}.type"] || 'application/octet-stream' ) end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 687efe7da65..ed5004e8d1a 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -69,7 +69,7 @@ module API options = options.reverse_merge( with: Entities::Project, current_user: current_user, - simple: params[:simple], + simple: params[:simple] ) projects = filter_projects(projects) diff --git a/lib/api/v3/groups.rb b/lib/api/v3/groups.rb index 63d464b926b..0a63cfd3df1 100644 --- a/lib/api/v3/groups.rb +++ b/lib/api/v3/groups.rb @@ -20,7 +20,7 @@ module API def present_groups(groups, options = {}) options = options.reverse_merge( with: Entities::Group, - current_user: current_user, + current_user: current_user ) groups = groups.with_statistics if options[:statistics] diff --git a/lib/api/v3/projects.rb b/lib/api/v3/projects.rb index 06cc704afc6..164612cb8dd 100644 --- a/lib/api/v3/projects.rb +++ b/lib/api/v3/projects.rb @@ -88,7 +88,7 @@ module API options = options.reverse_merge( with: ::API::V3::Entities::Project, current_user: current_user, - simple: params[:simple], + simple: params[:simple] ) projects = filter_projects(projects) diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb index 12458f9f410..c1b31618e0d 100644 --- a/lib/gitlab/git/blob.rb +++ b/lib/gitlab/git/blob.rb @@ -90,7 +90,7 @@ module Gitlab name: blob_entry[:name], data: '', path: path, - commit_id: sha, + commit_id: sha ) end end diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb index b722d8a9f56..d41256d9a84 100644 --- a/lib/gitlab/git/tree.rb +++ b/lib/gitlab/git/tree.rb @@ -35,7 +35,7 @@ module Gitlab type: entry[:type], mode: entry[:filemode].to_s(8), path: path ? File.join(path, entry[:name]) : entry[:name], - commit_id: sha, + commit_id: sha ) end end diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb index 0b001a9903d..8e9323b05e1 100644 --- a/lib/gitlab/gitaly_client/commit.rb +++ b/lib/gitlab/gitaly_client/commit.rb @@ -34,7 +34,7 @@ module Gitlab left_commit_id: parent_id, right_commit_id: commit.id, ignore_whitespace_change: options.fetch(:ignore_whitespace_change, false), - paths: options.fetch(:paths, []), + paths: options.fetch(:paths, []) ) Gitlab::Git::DiffCollection.new(stub.commit_diff(request), options) diff --git a/lib/gitlab/gitaly_client/util.rb b/lib/gitlab/gitaly_client/util.rb index 4acd297f5cb..86d055d3533 100644 --- a/lib/gitlab/gitaly_client/util.rb +++ b/lib/gitlab/gitaly_client/util.rb @@ -6,7 +6,7 @@ module Gitlab Gitaly::Repository.new( path: File.join(Gitlab.config.repositories.storages[repository_storage]['path'], relative_path), storage_name: repository_storage, - relative_path: relative_path, + relative_path: relative_path ) end end diff --git a/lib/gitlab/ldap/config.rb b/lib/gitlab/ldap/config.rb index 46deea3cc9f..6fdf68641e2 100644 --- a/lib/gitlab/ldap/config.rb +++ b/lib/gitlab/ldap/config.rb @@ -39,7 +39,7 @@ module Gitlab def adapter_options opts = base_options.merge( - encryption: encryption, + encryption: encryption ) opts.merge!(auth_options) if has_auth? diff --git a/lib/gitlab/sentry.rb b/lib/gitlab/sentry.rb index 117fc508135..2442c2ded3b 100644 --- a/lib/gitlab/sentry.rb +++ b/lib/gitlab/sentry.rb @@ -11,7 +11,7 @@ module Gitlab Raven.user_context( id: current_user.id, email: current_user.email, - username: current_user.username, + username: current_user.username ) end end diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index f3b3dea5318..351e2b10595 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -165,7 +165,7 @@ module Gitlab encoded_message, secret, true, - { iss: 'gitlab-workhorse', verify_iss: true, algorithm: 'HS256' }, + { iss: 'gitlab-workhorse', verify_iss: true, algorithm: 'HS256' } ) end -- cgit v1.2.3 From 47b8516c15415e4111973fbc9a3a2782c1de3ed8 Mon Sep 17 00:00:00 2001 From: David Turner Date: Wed, 10 May 2017 13:31:12 -0400 Subject: Add username field to push webhook Signed-off-by: David Turner --- lib/gitlab/data_builder/push.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb index d76aa38f741..ee3a1c7c008 100644 --- a/lib/gitlab/data_builder/push.rb +++ b/lib/gitlab/data_builder/push.rb @@ -11,6 +11,7 @@ module Gitlab # ref: String, # user_id: String, # user_name: String, + # user_username: String, # user_email: String # project_id: String, # repository: { @@ -51,6 +52,7 @@ module Gitlab message: message, user_id: user.id, user_name: user.name, + user_username: user.username, user_email: user.email, user_avatar: user.avatar_url, project_id: project.id, -- cgit v1.2.3 From 08706f683725dcfbda1708ddf079347d989fbef1 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 8 May 2017 18:50:23 -0500 Subject: Implement auxiliary blob viewers --- lib/gitlab/file_detector.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb index c9ca4cadd1c..f8b3d0b4965 100644 --- a/lib/gitlab/file_detector.rb +++ b/lib/gitlab/file_detector.rb @@ -13,7 +13,8 @@ module Gitlab gitignore: '.gitignore', koding: '.koding.yml', gitlab_ci: '.gitlab-ci.yml', - avatar: /\Alogo\.(png|jpg|gif)\z/ + avatar: /\Alogo\.(png|jpg|gif)\z/, + route_map: 'route-map.yml' }.freeze # Returns an Array of file types based on the given paths. -- cgit v1.2.3 From d2d6435372bd9a68ce1bad1dfe24f34d0924e048 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Tue, 9 May 2017 20:58:22 +0100 Subject: Add hostname to usage ping --- lib/gitlab/usage_data.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 14d8e925d0e..4382cf7b12f 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -52,6 +52,7 @@ module Gitlab def license_usage_data usage_data = { uuid: current_application_settings.uuid, + hostname: Gitlab.config.gitlab.host, version: Gitlab::VERSION, active_user_count: User.active.count, recorded_at: Time.now, -- cgit v1.2.3 From 27fb64d6a33ea61ba5a0a3ad50babff8c30fa45f Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 11 May 2017 10:52:45 +0200 Subject: Remove deltas_only from DiffCollection --- lib/gitlab/git/diff_collection.rb | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb index 4e45ec7c174..bcbad8ec829 100644 --- a/lib/gitlab/git/diff_collection.rb +++ b/lib/gitlab/git/diff_collection.rb @@ -15,7 +15,6 @@ module Gitlab @safe_max_bytes = @safe_max_files * 5120 # Average 5 KB per file @all_diffs = !!options.fetch(:all_diffs, false) @no_collapse = !!options.fetch(:no_collapse, true) - @deltas_only = !!options.fetch(:deltas_only, false) @line_count = 0 @byte_count = 0 @@ -27,8 +26,6 @@ module Gitlab if @populated # @iterator.each is slower than just iterating the array in place @array.each(&block) - elsif @deltas_only - each_delta(&block) else Gitlab::GitalyClient.migrate(:commit_raw_diffs) do each_patch(&block) @@ -81,14 +78,6 @@ module Gitlab files >= @safe_max_files || @line_count > @safe_max_lines || @byte_count >= @safe_max_bytes end - def each_delta - @iterator.each_delta.with_index do |delta, i| - diff = Gitlab::Git::Diff.new(delta) - - yield @array[i] = diff - end - end - def each_patch @iterator.each_with_index do |raw, i| # First yield cached Diff instances from @array -- cgit v1.2.3 From 49fb31db416cb73899cf5211de8f5817c00adc0b Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 11 May 2017 16:25:15 +0200 Subject: Add a new column before creating rename triggers MySQL doesn't allow us to create a trigger for a column that doesn't exist yet. Failing with this error: ``` Mysql2::Error: Unknown column 'build_events' in 'NEW': CREATE TRIGGER trigger_6a80c097c862_insert BEFORE INSERT ON `services` FOR EACH ROW SET NEW.`build_events` = NEW.`job_events` ``` Creating the new column before creating the trigger avoids this. --- lib/gitlab/database/migration_helpers.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index 298b1a1f4e6..f04a907004c 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -278,6 +278,16 @@ module Gitlab raise 'rename_column_concurrently can not be run inside a transaction' end + old_col = column_for(table, old) + new_type = type || old_col.type + + add_column(table, new, new_type, + limit: old_col.limit, + default: old_col.default, + null: old_col.null, + precision: old_col.precision, + scale: old_col.scale) + trigger_name = rename_trigger_name(table, old, new) quoted_table = quote_table_name(table) quoted_old = quote_column_name(old) @@ -291,16 +301,6 @@ module Gitlab quoted_old, quoted_new) end - old_col = column_for(table, old) - new_type = type || old_col.type - - add_column(table, new, new_type, - limit: old_col.limit, - default: old_col.default, - null: old_col.null, - precision: old_col.precision, - scale: old_col.scale) - update_column_in_batches(table, new, Arel::Table.new(table)[old]) copy_indexes(table, old, new) -- cgit v1.2.3 From 22722659c233efb3b65bb35286ff07c192e3fc85 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 8 May 2017 17:58:42 +0300 Subject: fix for Follow-up from "Backport of Multiple Assignees feature --- lib/api/helpers/common_helpers.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers/common_helpers.rb b/lib/api/helpers/common_helpers.rb index 6236fdd43ca..322624c6092 100644 --- a/lib/api/helpers/common_helpers.rb +++ b/lib/api/helpers/common_helpers.rb @@ -2,11 +2,11 @@ module API module Helpers module CommonHelpers def convert_parameters_from_legacy_format(params) - if params[:assignee_id].present? - params[:assignee_ids] = [params.delete(:assignee_id)] + params.tap do |params| + if params[:assignee_id].present? + params[:assignee_ids] = [params.delete(:assignee_id)] + end end - - params end end end -- cgit v1.2.3 From 6d46e51031e3d27044f692eba2fe332f26f59478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Thu, 11 May 2017 16:48:59 -0300 Subject: Use gitaly_migrate helper on all current migrations in repository --- lib/gitlab/git/repository.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 256318cb833..639240b83cc 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -114,7 +114,7 @@ module Gitlab # Returns the number of valid branches def branch_count - Gitlab::GitalyClient.migrate(:branch_names) do |is_enabled| + gitaly_migrate(:branch_names) do |is_enabled| if is_enabled gitaly_ref_client.count_branch_names else @@ -133,7 +133,7 @@ module Gitlab # Returns the number of valid tags def tag_count - Gitlab::GitalyClient.migrate(:tag_names) do |is_enabled| + gitaly_migrate(:tag_names) do |is_enabled| if is_enabled gitaly_ref_client.count_tag_names else @@ -471,7 +471,7 @@ module Gitlab def ref_name_for_sha(ref_path, sha) # NOTE: This feature is intentionally disabled until # https://gitlab.com/gitlab-org/gitaly/issues/180 is resolved - # Gitlab::GitalyClient.migrate(:find_ref_name) do |is_enabled| + # gitaly_migrate(:find_ref_name) do |is_enabled| # if is_enabled # gitaly_ref_client.find_ref_name(sha, ref_path) # else -- cgit v1.2.3 From c5e4e676e3b1dc5aa0b71fd9c026c0e172cda808 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 11 May 2017 17:29:42 -0300 Subject: Fix token interpolation when setting the Github remote --- lib/github/import.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/github/import.rb b/lib/github/import.rb index 06beb607a3e..452aebc66cb 100644 --- a/lib/github/import.rb +++ b/lib/github/import.rb @@ -1,4 +1,5 @@ require_relative 'error' + module Github class Import include Gitlab::ShellAdapter @@ -79,7 +80,7 @@ module Github def fetch_repository begin project.create_repository unless project.repository.exists? - project.repository.add_remote('github', "https://{options.fetch(:token)}@github.com/#{repo}.git") + project.repository.add_remote('github', "https://#{options.fetch(:token)}@github.com/#{repo}.git") project.repository.set_remote_as_mirror('github') project.repository.fetch_remote('github', forced: true) rescue Gitlab::Shell::Error => e -- cgit v1.2.3 From e901d1209e77e2ff0d85bb14c4a8df6da135b333 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 11 May 2017 17:30:56 -0300 Subject: Reset create callbacks for Issues/MRs while importing GitHub projects --- lib/github/import.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/github/import.rb b/lib/github/import.rb index 452aebc66cb..9c7eb965f93 100644 --- a/lib/github/import.rb +++ b/lib/github/import.rb @@ -7,6 +7,7 @@ module Github class MergeRequest < ::MergeRequest self.table_name = 'merge_requests' + self.reset_callbacks :create self.reset_callbacks :save self.reset_callbacks :commit self.reset_callbacks :update @@ -17,6 +18,7 @@ module Github self.table_name = 'issues' self.reset_callbacks :save + self.reset_callbacks :create self.reset_callbacks :commit self.reset_callbacks :update self.reset_callbacks :validate -- cgit v1.2.3 From 4f824d2aecf4fec46febd767fa7f7d747c732112 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Wed, 26 Apr 2017 22:09:03 +0200 Subject: Custom queries for prometheus - Tests for prometheus queries - fix rubocop warnings - Remove unused method. Add more queries to deployment queries. - Wrap BaseQuery in module hierarchy Renname Prometheus class to PrometheusClient --- lib/gitlab/prometheus.rb | 76 ---------------------- lib/gitlab/prometheus/queries/base_query.rb | 26 ++++++++ lib/gitlab/prometheus/queries/deployment_query.rb | 26 ++++++++ lib/gitlab/prometheus/queries/environment_query.rb | 20 ++++++ lib/gitlab/prometheus_client.rb | 76 ++++++++++++++++++++++ 5 files changed, 148 insertions(+), 76 deletions(-) delete mode 100644 lib/gitlab/prometheus.rb create mode 100644 lib/gitlab/prometheus/queries/base_query.rb create mode 100644 lib/gitlab/prometheus/queries/deployment_query.rb create mode 100644 lib/gitlab/prometheus/queries/environment_query.rb create mode 100644 lib/gitlab/prometheus_client.rb (limited to 'lib') diff --git a/lib/gitlab/prometheus.rb b/lib/gitlab/prometheus.rb deleted file mode 100644 index 37125980b1c..00000000000 --- a/lib/gitlab/prometheus.rb +++ /dev/null @@ -1,76 +0,0 @@ -module Gitlab - PrometheusError = Class.new(StandardError) - - # Helper methods to interact with Prometheus network services & resources - class Prometheus - attr_reader :api_url - - def initialize(api_url:) - @api_url = api_url - end - - def ping - json_api_get('query', query: '1') - end - - def query(query, time: Time.now) - get_result('vector') do - json_api_get('query', query: query, time: time.utc.to_f) - end - end - - def query_range(query, start: 8.hours.ago, stop: Time.now) - get_result('matrix') do - json_api_get('query_range', - query: query, - start: start.to_f, - end: stop.to_f, - step: 1.minute.to_i) - end - end - - private - - def json_api_get(type, args = {}) - get(join_api_url(type, args)) - rescue Errno::ECONNREFUSED - raise PrometheusError, 'Connection refused' - end - - def join_api_url(type, args = {}) - url = URI.parse(api_url) - rescue URI::Error - raise PrometheusError, "Invalid API URL: #{api_url}" - else - url.path = [url.path.sub(%r{/+\z}, ''), 'api', 'v1', type].join('/') - url.query = args.to_query - - url.to_s - end - - def get(url) - handle_response(HTTParty.get(url)) - rescue SocketError - raise PrometheusError, "Can't connect to #{url}" - rescue OpenSSL::SSL::SSLError - raise PrometheusError, "#{url} contains invalid SSL data" - rescue HTTParty::Error - raise PrometheusError, "Network connection error" - end - - def handle_response(response) - if response.code == 200 && response['status'] == 'success' - response['data'] || {} - elsif response.code == 400 - raise PrometheusError, response['error'] || 'Bad data received' - else - raise PrometheusError, "#{response.code} - #{response.body}" - end - end - - def get_result(expected_type) - data = yield - data['result'] if data['resultType'] == expected_type - end - end -end diff --git a/lib/gitlab/prometheus/queries/base_query.rb b/lib/gitlab/prometheus/queries/base_query.rb new file mode 100644 index 00000000000..2a2eb4ae57f --- /dev/null +++ b/lib/gitlab/prometheus/queries/base_query.rb @@ -0,0 +1,26 @@ +module Gitlab + module Prometheus + module Queries + class BaseQuery + attr_accessor :client + delegate :query_range, :query, to: :client, prefix: true + + def raw_memory_usage_query(environment_slug) + %{avg(container_memory_usage_bytes{container_name!="POD",environment="#{environment_slug}"}) / 2^20} + end + + def raw_cpu_usage_query(environment_slug) + %{avg(rate(container_cpu_usage_seconds_total{container_name!="POD",environment="#{environment_slug}"}[2m])) * 100} + end + + def initialize(client) + @client = client + end + + def query(*args) + raise NotImplementedError + end + end + end + end +end diff --git a/lib/gitlab/prometheus/queries/deployment_query.rb b/lib/gitlab/prometheus/queries/deployment_query.rb new file mode 100644 index 00000000000..98675c179b1 --- /dev/null +++ b/lib/gitlab/prometheus/queries/deployment_query.rb @@ -0,0 +1,26 @@ +module Gitlab::Prometheus::Queries + class DeploymentQuery < BaseQuery + def query(deployment_id) + deployment = Deployment.find_by(id: deployment_id) + environment_slug = deployment.environment.slug + + memory_query = raw_memory_usage_query(environment_slug) + memory_avg_query = %{avg(avg_over_time(container_memory_usage_bytes{container_name!="POD",environment="#{environment_slug}"}[30m]))} + cpu_query = raw_cpu_usage_query(environment_slug) + cpu_avg_query = %{avg(rate(container_cpu_usage_seconds_total{container_name!="POD",environment="#{environment_slug}"}[30m])) * 100} + + timeframe_start = (deployment.created_at - 30.minutes).to_f + timeframe_end = (deployment.created_at + 30.minutes).to_f + + { + memory_values: client_query_range(memory_query, start: timeframe_start, stop: timeframe_end), + memory_before: client_query(memory_avg_query, time: deployment.created_at.to_f), + memory_after: client_query(memory_avg_query, time: timeframe_end), + + cpu_values: client_query_range(cpu_query, start: timeframe_start, stop: timeframe_end), + cpu_before: client_query(cpu_avg_query, time: deployment.created_at.to_f), + cpu_after: client_query(cpu_avg_query, time: timeframe_end), + } + end + end +end diff --git a/lib/gitlab/prometheus/queries/environment_query.rb b/lib/gitlab/prometheus/queries/environment_query.rb new file mode 100644 index 00000000000..9981272220e --- /dev/null +++ b/lib/gitlab/prometheus/queries/environment_query.rb @@ -0,0 +1,20 @@ +module Gitlab::Prometheus::Queries + class EnvironmentQuery < BaseQuery + def query(environment_id) + environment = Environment.find_by(id: environment_id) + environment_slug = environment.slug + timeframe_start = 8.hours.ago.to_f + timeframe_end = Time.now.to_f + + memory_query = raw_memory_usage_query(environment_slug) + cpu_query = raw_cpu_usage_query(environment_slug) + + { + memory_values: client_query_range(memory_query, start: timeframe_start, stop: timeframe_end), + memory_current: client_query(memory_query, time: timeframe_end), + cpu_values: client_query_range(cpu_query, start: timeframe_start, stop: timeframe_end), + cpu_current: client_query(cpu_query, time: timeframe_end), + } + end + end +end diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb new file mode 100644 index 00000000000..5b51a1779dd --- /dev/null +++ b/lib/gitlab/prometheus_client.rb @@ -0,0 +1,76 @@ +module Gitlab + PrometheusError = Class.new(StandardError) + + # Helper methods to interact with Prometheus network services & resources + class PrometheusClient + attr_reader :api_url + + def initialize(api_url:) + @api_url = api_url + end + + def ping + json_api_get('query', query: '1') + end + + def query(query, time: Time.now) + get_result('vector') do + json_api_get('query', query: query, time: time.to_f) + end + end + + def query_range(query, start: 8.hours.ago, stop: Time.now) + get_result('matrix') do + json_api_get('query_range', + query: query, + start: start.to_f, + end: stop.to_f, + step: 1.minute.to_i) + end + end + + private + + def json_api_get(type, args = {}) + get(join_api_url(type, args)) + rescue Errno::ECONNREFUSED + raise PrometheusError, 'Connection refused' + end + + def join_api_url(type, args = {}) + url = URI.parse(api_url) + rescue URI::Error + raise PrometheusError, "Invalid API URL: #{api_url}" + else + url.path = [url.path.sub(%r{/+\z}, ''), 'api', 'v1', type].join('/') + url.query = args.to_query + + url.to_s + end + + def get(url) + handle_response(HTTParty.get(url)) + rescue SocketError + raise PrometheusError, "Can't connect to #{url}" + rescue OpenSSL::SSL::SSLError + raise PrometheusError, "#{url} contains invalid SSL data" + rescue HTTParty::Error + raise PrometheusError, "Network connection error" + end + + def handle_response(response) + if response.code == 200 && response['status'] == 'success' + response['data'] || {} + elsif response.code == 400 + raise PrometheusError, response['error'] || 'Bad data received' + else + raise PrometheusError, "#{response.code} - #{response.body}" + end + end + + def get_result(expected_type) + data = yield + data['result'] if data['resultType'] == expected_type + end + end +end -- cgit v1.2.3 From f6c4ccd1f234e1b5bab8f7ffbd98b3d1092b4873 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 12 May 2017 10:16:33 +0300 Subject: Backport FileFinder from EE --- lib/gitlab/file_finder.rb | 32 ++++++++++++++++++++++++++++++++ lib/gitlab/project_search_results.rb | 18 +----------------- 2 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 lib/gitlab/file_finder.rb (limited to 'lib') diff --git a/lib/gitlab/file_finder.rb b/lib/gitlab/file_finder.rb new file mode 100644 index 00000000000..093d9ed8092 --- /dev/null +++ b/lib/gitlab/file_finder.rb @@ -0,0 +1,32 @@ +# This class finds files in a repository by name and content +# the result is joined and sorted by file name +module Gitlab + class FileFinder + BATCH_SIZE = 100 + + attr_reader :project, :ref + + def initialize(project, ref) + @project = project + @ref = ref + end + + def find(query) + blobs = project.repository.search_files_by_content(query, ref).first(BATCH_SIZE) + found_file_names = Set.new + + results = blobs.map do |blob| + blob = Gitlab::ProjectSearchResults.parse_search_result(blob) + found_file_names << blob.filename + + [blob.filename, blob] + end + + project.repository.search_files_by_name(query, ref).first(BATCH_SIZE).each do |filename| + results << [filename, OpenStruct.new(ref: ref)] unless found_file_names.include?(filename) + end + + results.sort_by(&:first) + end + end +end diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb index 47cfe412715..561aa9e162c 100644 --- a/lib/gitlab/project_search_results.rb +++ b/lib/gitlab/project_search_results.rb @@ -84,23 +84,7 @@ module Gitlab def blobs return [] unless Ability.allowed?(@current_user, :download_code, @project) - @blobs ||= begin - blobs = project.repository.search_files_by_content(query, repository_ref).first(100) - found_file_names = Set.new - - results = blobs.map do |blob| - blob = self.class.parse_search_result(blob) - found_file_names << blob.filename - - [blob.filename, blob] - end - - project.repository.search_files_by_name(query, repository_ref).first(100).each do |filename| - results << [filename, nil] unless found_file_names.include?(filename) - end - - results.sort_by(&:first) - end + @blobs ||= Gitlab::FileFinder.new(project, repository_ref).find(query) end def wiki_blobs -- cgit v1.2.3 From 2a89d2c97dee52121747f933c5786dbf3d78647e Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Fri, 12 May 2017 13:09:46 +0200 Subject: Avoid comma t the end of hash --- lib/gitlab/prometheus/queries/deployment_query.rb | 2 +- lib/gitlab/prometheus/queries/environment_query.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/prometheus/queries/deployment_query.rb b/lib/gitlab/prometheus/queries/deployment_query.rb index 98675c179b1..2cc08731f8d 100644 --- a/lib/gitlab/prometheus/queries/deployment_query.rb +++ b/lib/gitlab/prometheus/queries/deployment_query.rb @@ -19,7 +19,7 @@ module Gitlab::Prometheus::Queries cpu_values: client_query_range(cpu_query, start: timeframe_start, stop: timeframe_end), cpu_before: client_query(cpu_avg_query, time: deployment.created_at.to_f), - cpu_after: client_query(cpu_avg_query, time: timeframe_end), + cpu_after: client_query(cpu_avg_query, time: timeframe_end) } end end diff --git a/lib/gitlab/prometheus/queries/environment_query.rb b/lib/gitlab/prometheus/queries/environment_query.rb index 9981272220e..01d756d7284 100644 --- a/lib/gitlab/prometheus/queries/environment_query.rb +++ b/lib/gitlab/prometheus/queries/environment_query.rb @@ -13,7 +13,7 @@ module Gitlab::Prometheus::Queries memory_values: client_query_range(memory_query, start: timeframe_start, stop: timeframe_end), memory_current: client_query(memory_query, time: timeframe_end), cpu_values: client_query_range(cpu_query, start: timeframe_start, stop: timeframe_end), - cpu_current: client_query(cpu_query, time: timeframe_end), + cpu_current: client_query(cpu_query, time: timeframe_end) } end end -- cgit v1.2.3 From 3fc20c01170ebb6648ff9dbe76b0d52d0c13d68d Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Fri, 12 May 2017 16:27:30 +0200 Subject: Fix adding defaults for concurrent column renames By adding the default value _after_ adding the column we avoid updating all rows in a table, saving a lot of time and unnecessary work in the process. --- lib/gitlab/database/migration_helpers.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index f04a907004c..f3476dadec8 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -283,11 +283,15 @@ module Gitlab add_column(table, new, new_type, limit: old_col.limit, - default: old_col.default, null: old_col.null, precision: old_col.precision, scale: old_col.scale) + # We set the default value _after_ adding the column so we don't end up + # updating any existing data with the default value. This isn't + # necessary since we copy over old values further down. + change_column_default(table, new, old_col.default) if old_col.default + trigger_name = rename_trigger_name(table, old, new) quoted_table = quote_table_name(table) quoted_old = quote_column_name(old) -- cgit v1.2.3 From e9d7b6cd8facc4828fc4abfb82902d803d523882 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 12 May 2017 10:29:25 -0500 Subject: Link Gemfile git URLs --- lib/gitlab/dependency_linker/gemfile_linker.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/dependency_linker/gemfile_linker.rb b/lib/gitlab/dependency_linker/gemfile_linker.rb index e36b88d357d..45be760d89e 100644 --- a/lib/gitlab/dependency_linker/gemfile_linker.rb +++ b/lib/gitlab/dependency_linker/gemfile_linker.rb @@ -16,6 +16,9 @@ module Gitlab "https://github.com/#{name}" end + # Link `git: "https://gitlab.example.com/user/repo"` to https://gitlab.example.com/user/repo + link_regex(%r{(git:|:git\s*=>)\s*['"](?https?://[^'"]+)['"]}) { |url| url } + # Link `source "https://rubygems.org"` to https://rubygems.org link_method_call("source", %r{https?://[^'"]+}) { |url| url } end -- cgit v1.2.3 From 3760a7c230512fef8643bbd078e59ad20787d591 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Fri, 12 May 2017 17:10:05 +0200 Subject: Only rename namespaces and projects with an invalid path For exact matches, not namespaces that end with an invalid path --- lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb index de4e6e7c404..95606290486 100644 --- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb +++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb @@ -15,7 +15,7 @@ module Gitlab end def path_patterns - @path_patterns ||= paths.map { |path| "%#{path}" } + @path_patterns ||= paths.map { |path| ["%/#{path}", "#{path}"] }.flatten end def rename_path_for_routable(routable) -- cgit v1.2.3 From 48ffec9e74ad7ac381936d61f73cef86d9919513 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Fri, 12 May 2017 16:00:18 +0000 Subject: Update rename_base.rb --- lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb index 95606290486..5397877b5d5 100644 --- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb +++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb @@ -15,7 +15,7 @@ module Gitlab end def path_patterns - @path_patterns ||= paths.map { |path| ["%/#{path}", "#{path}"] }.flatten + @path_patterns ||= paths.flat_map { |path| ["%/#{path}", path] } end def rename_path_for_routable(routable) -- cgit v1.2.3 From ad2bfeb85756db8c4cea9290be743665efd1c918 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 11 May 2017 16:23:02 +0100 Subject: Fix conflict resolution from corrupted upstream I don't know why this happens exactly, but given an upstream and fork repository from a customer, both of which required GC, resolving conflicts would corrupt the fork so badly that it couldn't be cloned. This isn't a perfect fix for that case, because the MR may still need to be merged manually, but it does ensure that the repository is at least usable. My best guess is that when we generate the index for the conflict resolution (which we previously did in the target project), we obtain a reference to an OID that doesn't exist in the source, even though we already fetch the refs from the target into the source. Explicitly setting the source project as the place to get the merge index from seems to prevent repository corruption in this way. --- lib/gitlab/conflict/file_collection.rb | 42 +++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/conflict/file_collection.rb b/lib/gitlab/conflict/file_collection.rb index 990b719ecfd..6e73361cad1 100644 --- a/lib/gitlab/conflict/file_collection.rb +++ b/lib/gitlab/conflict/file_collection.rb @@ -3,16 +3,33 @@ module Gitlab class FileCollection ConflictSideMissing = Class.new(StandardError) - attr_reader :merge_request, :our_commit, :their_commit + attr_reader :merge_request, :our_commit, :their_commit, :project - def initialize(merge_request) - @merge_request = merge_request - @our_commit = merge_request.source_branch_head.raw.raw_commit - @their_commit = merge_request.target_branch_head.raw.raw_commit - end + delegate :repository, to: :project + + class << self + # We can only write when getting the merge index from the source + # project, because we will write to that project. We don't use this all + # the time because this fetches a ref into the source project, which + # isn't needed for reading. + def for_resolution(merge_request) + project = merge_request.source_project + + new(merge_request, project).tap do |file_collection| + project. + repository. + with_repo_branch_commit(merge_request.target_project.repository, merge_request.target_branch) do + + yield file_collection + end + end + end - def repository - merge_request.project.repository + # We don't need to do `with_repo_branch_commit` here, because the target + # project always fetches source refs when creating merge request diffs. + def read_only(merge_request) + new(merge_request, merge_request.target_project) + end end def merge_index @@ -55,6 +72,15 @@ Merge branch '#{merge_request.target_branch}' into '#{merge_request.source_branc #{conflict_filenames.join("\n")} EOM end + + private + + def initialize(merge_request, project) + @merge_request = merge_request + @our_commit = merge_request.source_branch_head.raw.raw_commit + @their_commit = merge_request.target_branch_head.raw.raw_commit + @project = project + end end end end -- cgit v1.2.3 From 8ae2e6bdbb4e1254fd27dc8112c8b6c5c4015f07 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 12 May 2017 14:01:54 -0700 Subject: Remove trailing comma in dependency linker to satisfy Rubocop --- lib/gitlab/dependency_linker.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index 5e884c4bea1..c45ae8feb2c 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -1,7 +1,7 @@ module Gitlab module DependencyLinker LINKERS = [ - GemfileLinker, + GemfileLinker ].freeze def self.linker(blob_name) -- cgit v1.2.3 From f661980904f718440cc700b7d1f38ea8bf0e5480 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Wed, 3 May 2017 04:36:13 +0200 Subject: Added repository_update hook --- lib/gitlab/data_builder/repository.rb | 35 +++++++++++++++++++++++++++++++++++ lib/gitlab/git_post_receive.rb | 10 ++++++++++ 2 files changed, 45 insertions(+) create mode 100644 lib/gitlab/data_builder/repository.rb (limited to 'lib') diff --git a/lib/gitlab/data_builder/repository.rb b/lib/gitlab/data_builder/repository.rb new file mode 100644 index 00000000000..b42dc052949 --- /dev/null +++ b/lib/gitlab/data_builder/repository.rb @@ -0,0 +1,35 @@ +module Gitlab + module DataBuilder + module Repository + extend self + + # Produce a hash of post-receive data + def update(project, user, changes, refs) + { + event_name: 'repository_update', + + user_id: user.id, + user_name: user.name, + user_email: user.email, + user_avatar: user.avatar_url, + + project_id: project.id, + project: project.hook_attrs, + + changes: changes, + + refs: refs + } + end + + # Produce a hash of partial data for a single change + def single_change(oldrev, newrev, ref) + { + before: oldrev, + after: newrev, + ref: ref + } + end + end + end +end diff --git a/lib/gitlab/git_post_receive.rb b/lib/gitlab/git_post_receive.rb index 0e14253ab4e..742118b76a8 100644 --- a/lib/gitlab/git_post_receive.rb +++ b/lib/gitlab/git_post_receive.rb @@ -13,6 +13,16 @@ module Gitlab super(identifier, project, revision) end + def changes_refs + return enum_for(:changes_refs) unless block_given? + + changes.each do |change| + oldrev, newrev, ref = change.strip.split(' ') + + yield oldrev, newrev, ref + end + end + private def deserialize_changes(changes) -- cgit v1.2.3 From cfb4404ef6464ed4780bc7619268287716ae5e73 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Fri, 5 May 2017 18:00:32 +0200 Subject: Update SystemHooks API to expose and handle new repository_update_events --- lib/api/entities.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 00d494f02f5..3fc2b453eb6 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -53,7 +53,7 @@ module API end class Hook < Grape::Entity - expose :id, :url, :created_at, :push_events, :tag_push_events + expose :id, :url, :created_at, :push_events, :tag_push_events, :repository_update_events expose :enable_ssl_verification end -- cgit v1.2.3 From 38d84f83600d890f4227fc510a484554f009a1c0 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 12 May 2017 14:31:05 -0500 Subject: Select dependency linker based on file type --- lib/gitlab/dependency_linker/base_linker.rb | 10 ++++++++-- lib/gitlab/dependency_linker/gemfile_linker.rb | 4 +--- lib/gitlab/file_detector.rb | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb index 40a4ad11372..5f4027e7e81 100644 --- a/lib/gitlab/dependency_linker/base_linker.rb +++ b/lib/gitlab/dependency_linker/base_linker.rb @@ -1,8 +1,14 @@ module Gitlab module DependencyLinker class BaseLinker - def self.link(plain_text, highlighted_text) - new(plain_text, highlighted_text).link + class_attribute :file_type + + def self.support?(blob_name) + Gitlab::FileDetector.type_of(blob_name) == file_type + end + + def self.link(*args) + new(*args).link end attr_accessor :plain_text, :highlighted_text diff --git a/lib/gitlab/dependency_linker/gemfile_linker.rb b/lib/gitlab/dependency_linker/gemfile_linker.rb index 45be760d89e..9b82e126528 100644 --- a/lib/gitlab/dependency_linker/gemfile_linker.rb +++ b/lib/gitlab/dependency_linker/gemfile_linker.rb @@ -1,9 +1,7 @@ module Gitlab module DependencyLinker class GemfileLinker < BaseLinker - def self.support?(blob_name) - blob_name == 'Gemfile' || blob_name == 'gems.rb' - end + self.file_type = :gemfile private diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb index f8b3d0b4965..c6a89597b23 100644 --- a/lib/gitlab/file_detector.rb +++ b/lib/gitlab/file_detector.rb @@ -12,6 +12,7 @@ module Gitlab version: 'version', gitignore: '.gitignore', koding: '.koding.yml', + gemfile: /\A(Gemfile|gems\.rb)\z/, gitlab_ci: '.gitlab-ci.yml', avatar: /\Alogo\.(png|jpg|gif)\z/, route_map: 'route-map.yml' -- cgit v1.2.3 From 6bc48d0e25668a6cd6810178e68adab6fca58dae Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Sat, 13 May 2017 18:00:49 +0300 Subject: Allow GitLab instance to start when InfluxDB hostname cannot be resolved Closes #24438 --- lib/gitlab/metrics.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb index c6dfa4ad9bd..cb8db2f1e9f 100644 --- a/lib/gitlab/metrics.rb +++ b/lib/gitlab/metrics.rb @@ -49,6 +49,9 @@ module Gitlab end end end + rescue Errno::EADDRNOTAVAIL, SocketError => ex + Gitlab::EnvironmentLogger.error('Cannot resolve InfluxDB address. GitLab Performance Monitoring will not work.') + Gitlab::EnvironmentLogger.error(ex) end def self.prepare_metrics(metrics) -- cgit v1.2.3 From 99feed6e00e0f012f7e879a710e8b478b6160d2f Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Fri, 5 May 2017 16:55:12 +0200 Subject: Add support for deltas_only under Gitaly Closes gitaly#199 --- lib/gitlab/git/diff.rb | 20 +++++++------- lib/gitlab/gitaly_client/commit.rb | 54 ++++++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index 019be151353..31d1b66b4f7 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -183,6 +183,8 @@ module Gitlab when Gitaly::CommitDiffResponse init_from_gitaly(raw_diff) prune_diff_if_eligible(collapse) + when Gitaly::CommitDelta + init_from_gitaly(raw_diff) when nil raise "Nil as raw diff passed" else @@ -278,15 +280,15 @@ module Gitlab end end - def init_from_gitaly(diff_msg) - @diff = diff_msg.raw_chunks.join - @new_path = encode!(diff_msg.to_path.dup) - @old_path = encode!(diff_msg.from_path.dup) - @a_mode = diff_msg.old_mode.to_s(8) - @b_mode = diff_msg.new_mode.to_s(8) - @new_file = diff_msg.from_id == BLANK_SHA - @renamed_file = diff_msg.from_path != diff_msg.to_path - @deleted_file = diff_msg.to_id == BLANK_SHA + def init_from_gitaly(msg) + @diff = msg.raw_chunks.join if msg.respond_to?(:raw_chunks) + @new_path = encode!(msg.to_path.dup) + @old_path = encode!(msg.from_path.dup) + @a_mode = msg.old_mode.to_s(8) + @b_mode = msg.new_mode.to_s(8) + @new_file = msg.from_id == BLANK_SHA + @renamed_file = msg.from_path != msg.to_path + @deleted_file = msg.to_id == BLANK_SHA end def prune_diff_if_eligible(collapse = false) diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb index 8e9323b05e1..15c57420fb2 100644 --- a/lib/gitlab/gitaly_client/commit.rb +++ b/lib/gitlab/gitaly_client/commit.rb @@ -5,41 +5,55 @@ module Gitlab # See http://stackoverflow.com/a/40884093/1856239 and https://github.com/git/git/blob/3ad8b5bf26362ac67c9020bf8c30eee54a84f56d/cache.h#L1011-L1012 EMPTY_TREE_ID = '4b825dc642cb6eb9a060e54bf8d69288fbee4904'.freeze - attr_accessor :stub - def initialize(repository) @gitaly_repo = repository.gitaly_repository - @stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: repository.gitaly_channel) + @repository = repository end def is_ancestor(ancestor_id, child_id) + stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: @repository.gitaly_channel) request = Gitaly::CommitIsAncestorRequest.new( repository: @gitaly_repo, ancestor_id: ancestor_id, child_id: child_id ) - @stub.commit_is_ancestor(request).value + stub.commit_is_ancestor(request).value + end + + def diff_from_parent(commit, options = {}) + request_params = commit_diff_request_params(commit, options) + request_params[:ignore_whitespace_change] = options.fetch(:ignore_whitespace_change, false) + + response = diff_service_stub.commit_diff(Gitaly::CommitDiffRequest.new(request_params)) + Gitlab::Git::DiffCollection.new(response, options) end - class << self - def diff_from_parent(commit, options = {}) - repository = commit.project.repository - gitaly_repo = repository.gitaly_repository - stub = Gitaly::Diff::Stub.new(nil, nil, channel_override: repository.gitaly_channel) - parent = commit.parents[0] - parent_id = parent ? parent.id : EMPTY_TREE_ID - request = Gitaly::CommitDiffRequest.new( - repository: gitaly_repo, - left_commit_id: parent_id, - right_commit_id: commit.id, - ignore_whitespace_change: options.fetch(:ignore_whitespace_change, false), - paths: options.fetch(:paths, []) - ) - - Gitlab::Git::DiffCollection.new(stub.commit_diff(request), options) + def commit_deltas(commit) + request_params = commit_diff_request_params(commit) + + response = diff_service_stub.commit_delta(Gitaly::CommitDeltaRequest.new(request_params)) + response.flat_map do |msg| + msg.deltas.map { |d| Gitlab::Git::Diff.new(d) } end end + + private + + def commit_diff_request_params(commit, options = {}) + parent_id = commit.parents[0]&.id || EMPTY_TREE_ID + + { + repository: @gitaly_repo, + left_commit_id: parent_id, + right_commit_id: commit.id, + paths: options.fetch(:paths, []) + } + end + + def diff_service_stub + Gitaly::Diff::Stub.new(nil, nil, channel_override: @repository.gitaly_channel) + end end end end -- cgit v1.2.3 From 3efb60642a1803adbe8dccfc684ce1771765b750 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Sat, 13 May 2017 21:19:49 +0100 Subject: Rename all references to rendered_title to realtime_changes --- lib/gitlab/etag_caching/router.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index 31a5b9d108b..ba31041d0c1 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -7,8 +7,8 @@ module Gitlab # - Don't contain a reserved word (expect for the words used in the # regex itself) # - Ending in `noteable/issue//notes` for the `issue_notes` route - # - Ending in `issues/id`/rendered_title` for the `issue_title` route - USED_IN_ROUTES = %w[noteable issue notes issues rendered_title + # - Ending in `issues/id`/realtime_changes` for the `issue_title` route + USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes commit pipelines merge_requests new].freeze RESERVED_WORDS = DynamicPathValidator::WILDCARD_ROUTES - USED_IN_ROUTES RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS) @@ -18,7 +18,7 @@ module Gitlab 'issue_notes' ), Gitlab::EtagCaching::Router::Route.new( - %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/issues/\d+/rendered_title\z), + %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/issues/\d+/realtime_changes\z), 'issue_title' ), Gitlab::EtagCaching::Router::Route.new( -- cgit v1.2.3 From 43f037c903605b55ca1c34a24ab1ea1a522816fb Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Wed, 10 May 2017 14:18:59 +0200 Subject: Don't reuse gRPC channels It seems that bad things happen when two gRPC stubs share one gRPC channel so let's stop doing that. The downside of this is that we create more gRPC connections; one per stub. --- lib/gitlab/git/repository.rb | 14 +++---- lib/gitlab/gitaly_client.rb | 64 ++++++++++++------------------- lib/gitlab/gitaly_client/commit.rb | 4 +- lib/gitlab/gitaly_client/notifications.rb | 2 +- lib/gitlab/gitaly_client/ref.rb | 2 +- lib/gitlab/workhorse.rb | 2 +- 6 files changed, 36 insertions(+), 52 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 256318cb833..7a051444603 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -27,13 +27,15 @@ module Gitlab # Rugged repo object attr_reader :rugged + attr_reader :storage + # 'path' must be the path to a _bare_ git repository, e.g. # /path/to/my-repo.git - def initialize(repository_storage, relative_path) - @repository_storage = repository_storage + def initialize(storage, relative_path) + @storage = storage @relative_path = relative_path - storage_path = Gitlab.config.repositories.storages[@repository_storage]['path'] + storage_path = Gitlab.config.repositories.storages[@storage]['path'] @path = File.join(storage_path, @relative_path) @name = @relative_path.split("/").last @attributes = Gitlab::Git::Attributes.new(path) @@ -965,11 +967,7 @@ module Gitlab end def gitaly_repository - Gitlab::GitalyClient::Util.repository(@repository_storage, @relative_path) - end - - def gitaly_channel - Gitlab::GitalyClient.get_channel(@repository_storage) + Gitlab::GitalyClient::Util.repository(@storage, @relative_path) end private diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index c69676a1dac..72466700c05 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -4,56 +4,42 @@ module Gitlab module GitalyClient SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'.freeze - # This function is not thread-safe because it updates Hashes in instance variables. - def self.configure_channels - @addresses = {} - @channels = {} - Gitlab.config.repositories.storages.each do |name, params| - address = params['gitaly_address'] - unless address.present? - raise "storage #{name.inspect} is missing a gitaly_address" - end + MUTEX = Mutex.new + private_constant :MUTEX - unless URI(address).scheme.in?(%w(tcp unix)) - raise "Unsupported Gitaly address: #{address.inspect} does not use URL scheme 'tcp' or 'unix'" + def self.stub(name, storage) + MUTEX.synchronize do + @stubs ||= {} + @stubs[storage] ||= {} + @stubs[storage][name] ||= begin + klass = Gitaly.const_get(name.to_s.camelcase.to_sym).const_get(:Stub) + addr = address(storage) + addr = addr.sub(%r{^tcp://}, '') if URI(addr).scheme == 'tcp' + klass.new(addr, :this_channel_is_insecure) end - - @addresses[name] = address - @channels[name] = new_channel(address) end end - def self.new_channel(address) - address = address.sub(%r{^tcp://}, '') if URI(address).scheme == 'tcp' - # NOTE: When Gitaly runs on a Unix socket, permissions are - # handled using the file system and no additional authentication is - # required (therefore the :this_channel_is_insecure flag) - # TODO: Add authentication support when Gitaly is running on a TCP socket. - GRPC::Core::Channel.new(address, {}, :this_channel_is_insecure) + def self.clear_stubs! + MUTEX.synchronize do + @stubs = nil + end end - def self.get_channel(storage) - if !Rails.env.production? && @channels.nil? - # In development mode the Rails auto-loader may reset the instance - # variables of this class. What we do here is not thread-safe. In normal - # circumstances (including production) these instance variables have - # been initialized from config/initializers. - configure_channels - end + def self.address(storage) + params = Gitlab.config.repositories.storages[storage] + raise "storage not found: #{storage.inspect}" if params.nil? - @channels[storage] - end + address = params['gitaly_address'] + unless address.present? + raise "storage #{storage.inspect} is missing a gitaly_address" + end - def self.get_address(storage) - if !Rails.env.production? && @addresses.nil? - # In development mode the Rails auto-loader may reset the instance - # variables of this class. What we do here is not thread-safe. In normal - # circumstances (including development) these instance variables have - # been initialized from config/initializers. - configure_channels + unless URI(address).scheme.in?(%w(tcp unix)) + raise "Unsupported Gitaly address: #{address.inspect} does not use URL scheme 'tcp' or 'unix'" end - @addresses[storage] + address end def self.enabled? diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb index 15c57420fb2..4491903d788 100644 --- a/lib/gitlab/gitaly_client/commit.rb +++ b/lib/gitlab/gitaly_client/commit.rb @@ -11,7 +11,7 @@ module Gitlab end def is_ancestor(ancestor_id, child_id) - stub = Gitaly::Commit::Stub.new(nil, nil, channel_override: @repository.gitaly_channel) + stub = GitalyClient.stub(:commit, @repository.storage) request = Gitaly::CommitIsAncestorRequest.new( repository: @gitaly_repo, ancestor_id: ancestor_id, @@ -52,7 +52,7 @@ module Gitlab end def diff_service_stub - Gitaly::Diff::Stub.new(nil, nil, channel_override: @repository.gitaly_channel) + GitalyClient.stub(:diff, @repository.storage) end end end diff --git a/lib/gitlab/gitaly_client/notifications.rb b/lib/gitlab/gitaly_client/notifications.rb index a94a54883db..719554eac52 100644 --- a/lib/gitlab/gitaly_client/notifications.rb +++ b/lib/gitlab/gitaly_client/notifications.rb @@ -6,7 +6,7 @@ module Gitlab # 'repository' is a Gitlab::Git::Repository def initialize(repository) @gitaly_repo = repository.gitaly_repository - @stub = Gitaly::Notifications::Stub.new(nil, nil, channel_override: repository.gitaly_channel) + @stub = GitalyClient.stub(:notifications, repository.storage) end def post_receive diff --git a/lib/gitlab/gitaly_client/ref.rb b/lib/gitlab/gitaly_client/ref.rb index f6c77ef1a3e..bf04e1fa50b 100644 --- a/lib/gitlab/gitaly_client/ref.rb +++ b/lib/gitlab/gitaly_client/ref.rb @@ -6,7 +6,7 @@ module Gitlab # 'repository' is a Gitlab::Git::Repository def initialize(repository) @gitaly_repo = repository.gitaly_repository - @stub = Gitaly::Ref::Stub.new(nil, nil, channel_override: repository.gitaly_channel) + @stub = GitalyClient.stub(:ref, repository.storage) end def default_branch_name diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index 351e2b10595..fe37e4da94f 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -26,7 +26,7 @@ module Gitlab } if Gitlab.config.gitaly.enabled - address = Gitlab::GitalyClient.get_address(project.repository_storage) + address = Gitlab::GitalyClient.address(project.repository_storage) params[:Repository] = repository.gitaly_repository.to_h feature_enabled = case action.to_s -- cgit v1.2.3 From cac7e03fa1cb39a685bcde87d4d67fb17c4f48f2 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 11 May 2017 11:41:36 +0200 Subject: Rename `build_events` to `job_events` in code --- lib/api/entities.rb | 4 ++-- lib/api/project_hooks.rb | 2 -- lib/api/v3/entities.rb | 6 ++++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3fc2b453eb6..01cc8e8e1ca 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -60,7 +60,7 @@ module API class ProjectHook < Hook expose :project_id, :issues_events, :merge_requests_events expose :note_events, :pipeline_events, :wiki_page_events - expose :build_events, as: :job_events + expose :job_events end class BasicProjectDetails < Grape::Entity @@ -470,7 +470,7 @@ module API expose :id, :title, :created_at, :updated_at, :active expose :push_events, :issues_events, :merge_requests_events expose :tag_push_events, :note_events, :pipeline_events - expose :build_events, as: :job_events + expose :job_events # Expose serialized properties expose :properties do |service, options| field_names = service.fields. diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb index 87dfd1573a4..7a345289617 100644 --- a/lib/api/project_hooks.rb +++ b/lib/api/project_hooks.rb @@ -54,7 +54,6 @@ module API end post ":id/hooks" do hook_params = declared_params(include_missing: false) - hook_params[:build_events] = hook_params.delete(:job_events) { false } hook = user_project.hooks.new(hook_params) @@ -78,7 +77,6 @@ module API hook = user_project.hooks.find(params.delete(:hook_id)) update_params = declared_params(include_missing: false) - update_params[:build_events] = update_params.delete(:job_events) if update_params[:job_events] if hook.update_attributes(update_params) present hook, with: Entities::ProjectHook diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index 56a9b019f1b..332f233bf5e 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -238,7 +238,8 @@ module API class ProjectService < Grape::Entity expose :id, :title, :created_at, :updated_at, :active expose :push_events, :issues_events, :merge_requests_events - expose :tag_push_events, :note_events, :build_events, :pipeline_events + expose :tag_push_events, :note_events, :pipeline_events + expose :job_events, as: :build_events # Expose serialized properties expose :properties do |service, options| field_names = service.fields. @@ -250,7 +251,8 @@ module API class ProjectHook < ::API::Entities::Hook expose :project_id, :issues_events, :merge_requests_events - expose :note_events, :build_events, :pipeline_events, :wiki_page_events + expose :note_events, :pipeline_events, :wiki_page_events + expose :job_events, as: :build_events end class Issue < ::API::Entities::Issue -- cgit v1.2.3 From 872e7b7efe923192d4ef90b01672038518ba66fc Mon Sep 17 00:00:00 2001 From: George Andrinopoulos Date: Mon, 15 May 2017 13:53:12 +0000 Subject: Create a Users Finder --- lib/api/users.rb | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/api/users.rb b/lib/api/users.rb index 40acaebf670..3d83720b7b9 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -56,16 +56,7 @@ module API authenticated_as_admin! if params[:external].present? || (params[:extern_uid].present? && params[:provider].present?) - users = User.all - users = User.where(username: params[:username]) if params[:username] - users = users.active if params[:active] - users = users.search(params[:search]) if params[:search].present? - users = users.blocked if params[:blocked] - - if current_user.admin? - users = users.joins(:identities).merge(Identity.with_extern_uid(params[:provider], params[:extern_uid])) if params[:extern_uid] && params[:provider] - users = users.external if params[:external] - end + users = UsersFinder.new(current_user, params).execute entity = current_user.admin? ? Entities::UserPublic : Entities::UserBasic present paginate(users), with: entity -- cgit v1.2.3 From 950fa32a7c2c25d70bf8b2d495d759ce40bf2d9b Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 15 May 2017 20:24:19 +0000 Subject: Revert "Merge branch 'bvl-rename-build-events-to-job-events' into 'master'" This reverts merge request !11287 --- lib/api/entities.rb | 4 ++-- lib/api/project_hooks.rb | 2 ++ lib/api/v3/entities.rb | 6 ++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 01cc8e8e1ca..3fc2b453eb6 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -60,7 +60,7 @@ module API class ProjectHook < Hook expose :project_id, :issues_events, :merge_requests_events expose :note_events, :pipeline_events, :wiki_page_events - expose :job_events + expose :build_events, as: :job_events end class BasicProjectDetails < Grape::Entity @@ -470,7 +470,7 @@ module API expose :id, :title, :created_at, :updated_at, :active expose :push_events, :issues_events, :merge_requests_events expose :tag_push_events, :note_events, :pipeline_events - expose :job_events + expose :build_events, as: :job_events # Expose serialized properties expose :properties do |service, options| field_names = service.fields. diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb index 7a345289617..87dfd1573a4 100644 --- a/lib/api/project_hooks.rb +++ b/lib/api/project_hooks.rb @@ -54,6 +54,7 @@ module API end post ":id/hooks" do hook_params = declared_params(include_missing: false) + hook_params[:build_events] = hook_params.delete(:job_events) { false } hook = user_project.hooks.new(hook_params) @@ -77,6 +78,7 @@ module API hook = user_project.hooks.find(params.delete(:hook_id)) update_params = declared_params(include_missing: false) + update_params[:build_events] = update_params.delete(:job_events) if update_params[:job_events] if hook.update_attributes(update_params) present hook, with: Entities::ProjectHook diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index 332f233bf5e..56a9b019f1b 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -238,8 +238,7 @@ module API class ProjectService < Grape::Entity expose :id, :title, :created_at, :updated_at, :active expose :push_events, :issues_events, :merge_requests_events - expose :tag_push_events, :note_events, :pipeline_events - expose :job_events, as: :build_events + expose :tag_push_events, :note_events, :build_events, :pipeline_events # Expose serialized properties expose :properties do |service, options| field_names = service.fields. @@ -251,8 +250,7 @@ module API class ProjectHook < ::API::Entities::Hook expose :project_id, :issues_events, :merge_requests_events - expose :note_events, :pipeline_events, :wiki_page_events - expose :job_events, as: :build_events + expose :note_events, :build_events, :pipeline_events, :wiki_page_events end class Issue < ::API::Entities::Issue -- cgit v1.2.3 From beec97f6cf5f7357238e6f27e48115d6960f3de4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 15 May 2017 16:01:09 -0500 Subject: Disallow NULL on renamed column after default has been set --- lib/gitlab/database/migration_helpers.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index f3476dadec8..e76c9abbe04 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -283,7 +283,6 @@ module Gitlab add_column(table, new, new_type, limit: old_col.limit, - null: old_col.null, precision: old_col.precision, scale: old_col.scale) @@ -307,6 +306,8 @@ module Gitlab update_column_in_batches(table, new, Arel::Table.new(table)[old]) + change_column_null(table, new, false) unless old_col.null + copy_indexes(table, old, new) copy_foreign_keys(table, old, new) end -- cgit v1.2.3 From 1fd83f972cf5ce73b3e46fd2df5ffb07889b1fd1 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 15 May 2017 15:11:45 +0000 Subject: Merge branch 'bvl-rename-build-events-to-job-events' into 'master' Rename `build_events` to `job_events` Closes #31620 See merge request !11287 --- lib/api/entities.rb | 4 ++-- lib/api/project_hooks.rb | 2 -- lib/api/v3/entities.rb | 6 ++++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3fc2b453eb6..01cc8e8e1ca 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -60,7 +60,7 @@ module API class ProjectHook < Hook expose :project_id, :issues_events, :merge_requests_events expose :note_events, :pipeline_events, :wiki_page_events - expose :build_events, as: :job_events + expose :job_events end class BasicProjectDetails < Grape::Entity @@ -470,7 +470,7 @@ module API expose :id, :title, :created_at, :updated_at, :active expose :push_events, :issues_events, :merge_requests_events expose :tag_push_events, :note_events, :pipeline_events - expose :build_events, as: :job_events + expose :job_events # Expose serialized properties expose :properties do |service, options| field_names = service.fields. diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb index 87dfd1573a4..7a345289617 100644 --- a/lib/api/project_hooks.rb +++ b/lib/api/project_hooks.rb @@ -54,7 +54,6 @@ module API end post ":id/hooks" do hook_params = declared_params(include_missing: false) - hook_params[:build_events] = hook_params.delete(:job_events) { false } hook = user_project.hooks.new(hook_params) @@ -78,7 +77,6 @@ module API hook = user_project.hooks.find(params.delete(:hook_id)) update_params = declared_params(include_missing: false) - update_params[:build_events] = update_params.delete(:job_events) if update_params[:job_events] if hook.update_attributes(update_params) present hook, with: Entities::ProjectHook diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index 56a9b019f1b..332f233bf5e 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -238,7 +238,8 @@ module API class ProjectService < Grape::Entity expose :id, :title, :created_at, :updated_at, :active expose :push_events, :issues_events, :merge_requests_events - expose :tag_push_events, :note_events, :build_events, :pipeline_events + expose :tag_push_events, :note_events, :pipeline_events + expose :job_events, as: :build_events # Expose serialized properties expose :properties do |service, options| field_names = service.fields. @@ -250,7 +251,8 @@ module API class ProjectHook < ::API::Entities::Hook expose :project_id, :issues_events, :merge_requests_events - expose :note_events, :build_events, :pipeline_events, :wiki_page_events + expose :note_events, :pipeline_events, :wiki_page_events + expose :job_events, as: :build_events end class Issue < ::API::Entities::Issue -- cgit v1.2.3 From b3da5e15bd8b7259a6eaef139b63a61bd2e32c39 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 16 May 2017 13:04:52 +0000 Subject: Update ee_compat_check.rb to include `git apply --reject` suggestion --- lib/gitlab/ee_compat_check.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index 496ee0bdcb0..06438d2df41 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -309,6 +309,17 @@ module Gitlab U lib/gitlab/ee_compat_check.rb Resolve them, stage the changes and commit them. + + If the patch couldn't be applied cleanly, use the following command: + + # In the EE repo + $ git apply --reject path/to/#{ce_branch}.patch + + This option makes git apply the parts of the patch that are applicable, + and leave the rejected hunks in corresponding `.rej` files. + You can then resolve the conflicts highlighted in `.rej` by + manually applying the correct diff from the `.rej` file to the file with conflicts. + When finished, you can delete the `.rej` files and commit your changes. ⚠️ Don't forget to push your branch to gitlab-ee: -- cgit v1.2.3 From 992dfd7eb4c5bf26517d5d5adf3b3b9894ac397e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 16 May 2017 15:34:04 +0200 Subject: Fetch CE/branch before running `git apply --check --3way patch` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- lib/gitlab/ee_compat_check.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index 06438d2df41..198896220ac 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -131,10 +131,12 @@ module Gitlab def check_patch(patch_path) step("Checking out master", %w[git checkout master]) step("Resetting to latest master", %w[git reset --hard origin/master]) + step("Fetching CE/#{branch}", %W[git fetch #{CE_REPO} #{branch}]) step( "Checking if #{patch_path} applies cleanly to EE/master", %W[git apply --check --3way #{patch_path}] ) do |output, status| + puts output unless status.zero? @failed_files = output.lines.reduce([]) do |memo, line| if line.start_with?('error: patch failed:') @@ -309,12 +311,12 @@ module Gitlab U lib/gitlab/ee_compat_check.rb Resolve them, stage the changes and commit them. - + If the patch couldn't be applied cleanly, use the following command: - + # In the EE repo $ git apply --reject path/to/#{ce_branch}.patch - + This option makes git apply the parts of the patch that are applicable, and leave the rejected hunks in corresponding `.rej` files. You can then resolve the conflicts highlighted in `.rej` by -- cgit v1.2.3 From cf09c826a534d782de9cee4d28d3cdfa504099e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Thu, 11 May 2017 17:26:51 -0300 Subject: Re-enable gitaly migration for ref_name_for_sha after bugfixes --- lib/gitlab/git/repository.rb | 26 +++++++++++++------------- lib/gitlab/gitaly_client/ref.rb | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index d380c5021ee..a2c01ec4432 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -471,19 +471,19 @@ module Gitlab # Returns a RefName for a given SHA def ref_name_for_sha(ref_path, sha) - # NOTE: This feature is intentionally disabled until - # https://gitlab.com/gitlab-org/gitaly/issues/180 is resolved - # gitaly_migrate(:find_ref_name) do |is_enabled| - # if is_enabled - # gitaly_ref_client.find_ref_name(sha, ref_path) - # else - args = %W(#{Gitlab.config.git.bin_path} for-each-ref --count=1 #{ref_path} --contains #{sha}) - - # Not found -> ["", 0] - # Found -> ["b8d95eb4969eefacb0a58f6a28f6803f8070e7b9 commit\trefs/environments/production/77\n", 0] - Gitlab::Popen.popen(args, @path).first.split.last - # end - # end + raise ArgumentError, "sha can't be empty" unless sha.present? + + gitaly_migrate(:find_ref_name) do |is_enabled| + if is_enabled + gitaly_ref_client.find_ref_name(sha, ref_path) + else + args = %W(#{Gitlab.config.git.bin_path} for-each-ref --count=1 #{ref_path} --contains #{sha}) + + # Not found -> ["", 0] + # Found -> ["b8d95eb4969eefacb0a58f6a28f6803f8070e7b9 commit\trefs/environments/production/77\n", 0] + Gitlab::Popen.popen(args, @path).first.split.last + end + end end # Returns commits collection diff --git a/lib/gitlab/gitaly_client/ref.rb b/lib/gitlab/gitaly_client/ref.rb index bf04e1fa50b..53c43e28df8 100644 --- a/lib/gitlab/gitaly_client/ref.rb +++ b/lib/gitlab/gitaly_client/ref.rb @@ -28,7 +28,7 @@ module Gitlab def find_ref_name(commit_id, ref_prefix) request = Gitaly::FindRefNameRequest.new( - repository: @repository, + repository: @gitaly_repo, commit_id: commit_id, prefix: ref_prefix ) -- cgit v1.2.3 From 71569a9c410d297469c86227807c9f60cc069ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Tue, 9 May 2017 15:41:21 -0300 Subject: Compare ids of commits if present for equality test This solves a problem where commits populated with Gitaly were not equal to commits populated with Rugged. This is because Gitaly may not return all fields of a commit for optimizations purposes, which resulted in false negatives when comparing the same commit (commits with the same sha) with different sources. --- lib/gitlab/git/commit.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index f9a9b767ef4..e14c3511e60 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -19,13 +19,7 @@ module Gitlab def ==(other) return false unless other.is_a?(Gitlab::Git::Commit) - methods = [:message, :parent_ids, :authored_date, :author_name, - :author_email, :committed_date, :committer_name, - :committer_email] - - methods.all? do |method| - send(method) == other.send(method) - end + id && id == other.id end class << self -- cgit v1.2.3 From 71777a4a184945d6b58170af55d9fd9fef821ac9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 16 May 2017 19:41:15 +0800 Subject: Rename BuildsController to JobsController Rename other URL generators admin_builds_path -> admin_jobs_path Fix tests and more renaming Fix more tests Also change build_id to job_id in the controller --- lib/gitlab/ci/status/build/cancelable.rb | 2 +- lib/gitlab/ci/status/build/common.rb | 2 +- lib/gitlab/ci/status/build/play.rb | 2 +- lib/gitlab/ci/status/build/retryable.rb | 2 +- lib/gitlab/ci/status/build/stop.rb | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/status/build/cancelable.rb b/lib/gitlab/ci/status/build/cancelable.rb index 57b533bad99..439ef0ce015 100644 --- a/lib/gitlab/ci/status/build/cancelable.rb +++ b/lib/gitlab/ci/status/build/cancelable.rb @@ -12,7 +12,7 @@ module Gitlab end def action_path - cancel_namespace_project_build_path(subject.project.namespace, + cancel_namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/common.rb b/lib/gitlab/ci/status/build/common.rb index 3fec2c5d4db..b173c23fba4 100644 --- a/lib/gitlab/ci/status/build/common.rb +++ b/lib/gitlab/ci/status/build/common.rb @@ -8,7 +8,7 @@ module Gitlab end def details_path - namespace_project_build_path(subject.project.namespace, + namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/play.rb b/lib/gitlab/ci/status/build/play.rb index c6139f1b716..e80f3263794 100644 --- a/lib/gitlab/ci/status/build/play.rb +++ b/lib/gitlab/ci/status/build/play.rb @@ -20,7 +20,7 @@ module Gitlab end def action_path - play_namespace_project_build_path(subject.project.namespace, + play_namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/retryable.rb b/lib/gitlab/ci/status/build/retryable.rb index 505f80848b2..56303e4cb17 100644 --- a/lib/gitlab/ci/status/build/retryable.rb +++ b/lib/gitlab/ci/status/build/retryable.rb @@ -16,7 +16,7 @@ module Gitlab end def action_path - retry_namespace_project_build_path(subject.project.namespace, + retry_namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/stop.rb b/lib/gitlab/ci/status/build/stop.rb index 0b5199e5483..2778d6f3b52 100644 --- a/lib/gitlab/ci/status/build/stop.rb +++ b/lib/gitlab/ci/status/build/stop.rb @@ -20,7 +20,7 @@ module Gitlab end def action_path - play_namespace_project_build_path(subject.project.namespace, + play_namespace_project_job_path(subject.project.namespace, subject.project, subject) end -- cgit v1.2.3 From 831d6f5f777370e4ad424211df24e2f5bd380445 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 16 May 2017 22:51:56 -0700 Subject: Properly handle container registry redirects to fix metadata stored on a S3 backend The previous behavior would include the Authorization header, which would make fetching an S3 blob fail quietly. Closes #22403 Update sh-fix-container-registry-s3-redirects.yml --- lib/container_registry/client.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb index 7f5f6d9ddb6..c7263f302ab 100644 --- a/lib/container_registry/client.rb +++ b/lib/container_registry/client.rb @@ -75,10 +75,7 @@ module ContainerRegistry def redirect_response(location) return unless location - # We explicitly remove authorization token - faraday_blob.get(location) do |req| - req['Authorization'] = '' - end + faraday_redirect.get(location) end def faraday @@ -93,5 +90,14 @@ module ContainerRegistry initialize_connection(conn, @options) end end + + # Create a new request to make sure the Authorization header is not inserted + # via the Faraday middleware + def faraday_redirect + @faraday_redirect ||= Faraday.new(@base_uri) do |conn| + conn.request :json + conn.adapter :net_http + end + end end end -- cgit v1.2.3 From 6ced4d138e56a82fc460d6281ae445fb7b739636 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Tue, 16 May 2017 16:25:02 +0200 Subject: Fix transient CI errors by increasing command execution timeouts from 1s to 30s + actually make local tests correctly detect wether 'timeout' or 'gtimeout' is available --- lib/gitlab/health_checks/fs_shards_check.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/health_checks/fs_shards_check.rb b/lib/gitlab/health_checks/fs_shards_check.rb index df962d203b7..90612af3d63 100644 --- a/lib/gitlab/health_checks/fs_shards_check.rb +++ b/lib/gitlab/health_checks/fs_shards_check.rb @@ -42,6 +42,7 @@ module Gitlab private RANDOM_STRING = SecureRandom.hex(1000).freeze + COMMAND_TIMEOUT = 1.second def operation_metrics(ok_metric, latency_metric, operation, **labels) with_timing operation do |result, elapsed| @@ -64,7 +65,11 @@ module Gitlab end def with_timeout(args) - %w{timeout 1}.concat(args) + %W{timeout #{COMMAND_TIMEOUT.to_i}}.concat(args) + end + + def exec_with_timeout(cmd_args, *args, &block) + Gitlab::Popen.popen(with_timeout(cmd_args), *args, &block) end def tmp_file_path(storage_name) @@ -78,7 +83,7 @@ module Gitlab def storage_stat_test(storage_name) stat_path = File.join(path(storage_name), '.') begin - _, status = Gitlab::Popen.popen(with_timeout(%W{ stat #{stat_path} })) + _, status = exec_with_timeout(%W{ stat #{stat_path} }) status == 0 rescue Errno::ENOENT File.exist?(stat_path) && File::Stat.new(stat_path).readable? @@ -86,7 +91,7 @@ module Gitlab end def storage_write_test(tmp_path) - _, status = Gitlab::Popen.popen(with_timeout(%W{ tee #{tmp_path} })) do |stdin| + _, status = exec_with_timeout(%W{ tee #{tmp_path} }) do |stdin| stdin.write(RANDOM_STRING) end status == 0 @@ -96,7 +101,7 @@ module Gitlab end def storage_read_test(tmp_path) - _, status = Gitlab::Popen.popen(with_timeout(%W{ diff #{tmp_path} - })) do |stdin| + _, status = exec_with_timeout(%W{ diff #{tmp_path} - }) do |stdin| stdin.write(RANDOM_STRING) end status == 0 @@ -106,7 +111,7 @@ module Gitlab end def delete_test_file(tmp_path) - _, status = Gitlab::Popen.popen(with_timeout(%W{ rm -f #{tmp_path} })) + _, status = exec_with_timeout(%W{ rm -f #{tmp_path} }) status == 0 rescue Errno::ENOENT File.delete(tmp_path) rescue Errno::ENOENT -- cgit v1.2.3 From ac382b5682dc2d5eea750313c59fb2581af13326 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Mon, 24 Apr 2017 17:19:22 +0200 Subject: Use CTEs for nested groups and authorizations This commit introduces the usage of Common Table Expressions (CTEs) to efficiently retrieve nested group hierarchies, without having to rely on the "routes" table (which is an _incredibly_ inefficient way of getting the data). This requires a patch to ActiveRecord (found in the added initializer) to work properly as ActiveRecord doesn't support WITH statements properly out of the box. Unfortunately MySQL provides no efficient way of getting nested groups. For example, the old routes setup could easily take 5-10 seconds depending on the amount of "routes" in a database. Providing vastly different logic for both MySQL and PostgreSQL will negatively impact the development process. Because of this the various nested groups related methods return empty relations when used in combination with MySQL. For project authorizations the logic is split up into two classes: * Gitlab::ProjectAuthorizations::WithNestedGroups * Gitlab::ProjectAuthorizations::WithoutNestedGroups Both classes get the fresh project authorizations (= as they should be in the "project_authorizations" table), including nested groups if PostgreSQL is used. The logic of these two classes is quite different apart from their public interface. This complicates development a bit, but unfortunately there is no way around this. This commit also introduces Gitlab::GroupHierarchy. This class can be used to get the ancestors and descendants of a base relation, or both by using a UNION. This in turn is used by methods such as: * Namespace#ancestors * Namespace#descendants * User#all_expanded_groups Again this class relies on CTEs and thus only works on PostgreSQL. The Namespace methods will return an empty relation when MySQL is used, while User#all_expanded_groups will return only the groups a user is a direct member of. Performance wise the impact is quite large. For example, on GitLab.com Namespace#descendants used to take around 580 ms to retrieve data for a particular user. Using CTEs we are able to reduce this down to roughly 1 millisecond, returning the exact same data. == On The Fly Refreshing Refreshing of authorizations on the fly (= when users.authorized_projects_populated was not set) is removed with this commit. This simplifies the code, and ensures any queries used for authorizations are not mutated because they are executed in a Rails scope (e.g. Project.visible_to_user). This commit includes a migration to schedule refreshing authorizations for all users, ensuring all of them have their authorizations in place. Said migration schedules users in batches of 5000, with 5 minutes between every batch to smear the load around a bit. == Spec Changes This commit also introduces some changes to various specs. For example, some specs for ProjectTeam assumed that creating a personal project would _not_ lead to the owner having access, which is incorrect. Because we also no longer refresh authorizations on the fly for new users some code had to be added to the "empty_project" factory. This chunk of code ensures that the owner's permissions are refreshed after creating the project, something that is normally done in Projects::CreateService. --- lib/gitlab/group_hierarchy.rb | 98 ++++++++++++++++ .../project_authorizations/with_nested_groups.rb | 128 +++++++++++++++++++++ .../without_nested_groups.rb | 35 ++++++ lib/gitlab/sql/recursive_cte.rb | 62 ++++++++++ 4 files changed, 323 insertions(+) create mode 100644 lib/gitlab/group_hierarchy.rb create mode 100644 lib/gitlab/project_authorizations/with_nested_groups.rb create mode 100644 lib/gitlab/project_authorizations/without_nested_groups.rb create mode 100644 lib/gitlab/sql/recursive_cte.rb (limited to 'lib') diff --git a/lib/gitlab/group_hierarchy.rb b/lib/gitlab/group_hierarchy.rb new file mode 100644 index 00000000000..50e057892a6 --- /dev/null +++ b/lib/gitlab/group_hierarchy.rb @@ -0,0 +1,98 @@ +module Gitlab + # Retrieving of parent or child groups based on a base ActiveRecord relation. + # + # This class uses recursive CTEs and as a result will only work on PostgreSQL. + class GroupHierarchy + attr_reader :base, :model + + # base - An instance of ActiveRecord::Relation for which to get parent or + # child groups. + def initialize(base) + @base = base + @model = base.model + end + + # Returns a relation that includes the base set of groups and all their + # ancestors (recursively). + def base_and_ancestors + base_and_ancestors_cte.apply_to(model.all) + end + + # Returns a relation that includes the base set of groups and all their + # descendants (recursively). + def base_and_descendants + base_and_descendants_cte.apply_to(model.all) + end + + # Returns a relation that includes the base groups, their ancestors, and the + # descendants of the base groups. + # + # The resulting query will roughly look like the following: + # + # WITH RECURSIVE ancestors AS ( ... ), + # descendants AS ( ... ) + # SELECT * + # FROM ( + # SELECT * + # FROM ancestors namespaces + # + # UNION + # + # SELECT * + # FROM descendants namespaces + # ) groups; + # + # Using this approach allows us to further add criteria to the relation with + # Rails thinking it's selecting data the usual way. + def all_groups + ancestors = base_and_ancestors_cte + descendants = base_and_descendants_cte + + ancestors_table = ancestors.alias_to(groups_table) + descendants_table = descendants.alias_to(groups_table) + + union = SQL::Union.new([model.unscoped.from(ancestors_table), + model.unscoped.from(descendants_table)]) + + model. + unscoped. + with. + recursive(ancestors.to_arel, descendants.to_arel). + from("(#{union.to_sql}) #{model.table_name}") + end + + private + + def base_and_ancestors_cte + cte = SQL::RecursiveCTE.new(:base_and_ancestors) + + cte << base.except(:order) + + # Recursively get all the ancestors of the base set. + cte << model. + from([groups_table, cte.table]). + where(groups_table[:id].eq(cte.table[:parent_id])). + except(:order) + + cte + end + + def base_and_descendants_cte + cte = SQL::RecursiveCTE.new(:base_and_descendants) + + cte << base.except(:order) + + # Recursively get all the descendants of the base set. + cte << model. + from([groups_table, cte.table]). + where(groups_table[:parent_id].eq(cte.table[:id])). + except(:order) + + cte + end + + def groups_table + model.arel_table + end + end +end diff --git a/lib/gitlab/project_authorizations/with_nested_groups.rb b/lib/gitlab/project_authorizations/with_nested_groups.rb new file mode 100644 index 00000000000..79c082c08fd --- /dev/null +++ b/lib/gitlab/project_authorizations/with_nested_groups.rb @@ -0,0 +1,128 @@ +module Gitlab + module ProjectAuthorizations + # Calculating new project authorizations when supporting nested groups. + # + # This class relies on Common Table Expressions to efficiently get all data, + # including data for nested groups. As a result this class can only be used + # on PostgreSQL. + class WithNestedGroups + attr_reader :user + + # user - The User object for which to calculate the authorizations. + def initialize(user) + @user = user + end + + def calculate + cte = recursive_cte + cte_alias = cte.table.alias(Group.table_name) + projects = Project.arel_table + links = ProjectGroupLink.arel_table + + # These queries don't directly use the user object so they don't depend + # on the state of said object, ensuring the produced queries are always + # the same. + relations = [ + # The project a user has direct access to. + user.projects.select_for_project_authorization, + + # The personal projects of the user. + user.personal_projects.select_as_master_for_project_authorization, + + # Projects that belong directly to any of the groups the user has + # access to. + Namespace. + unscoped. + select([alias_as_column(projects[:id], 'project_id'), + cte_alias[:access_level]]). + from(cte_alias). + joins(:projects), + + # Projects shared with any of the namespaces the user has access to. + Namespace. + unscoped. + select([links[:project_id], + least(cte_alias[:access_level], + links[:group_access], + 'access_level')]). + from(cte_alias). + joins('INNER JOIN project_group_links ON project_group_links.group_id = namespaces.id'). + joins('INNER JOIN projects ON projects.id = project_group_links.project_id'). + joins('INNER JOIN namespaces p_ns ON p_ns.id = projects.namespace_id'). + where('p_ns.share_with_group_lock IS FALSE') + ] + + union = Gitlab::SQL::Union.new(relations) + + ProjectAuthorization. + unscoped. + with. + recursive(cte.to_arel). + select_from_union(union) + end + + private + + # Builds a recursive CTE that gets all the groups the current user has + # access to, including any nested groups. + def recursive_cte + cte = Gitlab::SQL::RecursiveCTE.new(:namespaces_cte) + members = Member.arel_table + namespaces = Namespace.arel_table + + # Namespaces the user is a member of. + cte << user.groups. + select([namespaces[:id], members[:access_level]]). + except(:order) + + # Sub groups of any groups the user is a member of. + cte << Group.select([namespaces[:id], + greatest(members[:access_level], + cte.table[:access_level], 'access_level')]). + joins(join_cte(cte)). + joins(join_members). + except(:order) + + cte + end + + # Builds a LEFT JOIN to join optional memberships onto the CTE. + def join_members + members = Member.arel_table + namespaces = Namespace.arel_table + + cond = members[:source_id]. + eq(namespaces[:id]). + and(members[:source_type].eq('Namespace')). + and(members[:requested_at].eq(nil)). + and(members[:user_id].eq(user.id)) + + Arel::Nodes::OuterJoin.new(members, Arel::Nodes::On.new(cond)) + end + + # Builds an INNER JOIN to join namespaces onto the CTE. + def join_cte(cte) + namespaces = Namespace.arel_table + cond = cte.table[:id].eq(namespaces[:parent_id]) + + Arel::Nodes::InnerJoin.new(cte.table, Arel::Nodes::On.new(cond)) + end + + def greatest(left, right, column_alias) + sql_function('GREATEST', [left, right], column_alias) + end + + def least(left, right, column_alias) + sql_function('LEAST', [left, right], column_alias) + end + + def sql_function(name, args, column_alias) + alias_as_column(Arel::Nodes::NamedFunction.new(name, args), column_alias) + end + + def alias_as_column(value, alias_to) + Arel::Nodes::As.new(value, Arel::Nodes::SqlLiteral.new(alias_to)) + end + end + end +end diff --git a/lib/gitlab/project_authorizations/without_nested_groups.rb b/lib/gitlab/project_authorizations/without_nested_groups.rb new file mode 100644 index 00000000000..627e8c5fba2 --- /dev/null +++ b/lib/gitlab/project_authorizations/without_nested_groups.rb @@ -0,0 +1,35 @@ +module Gitlab + module ProjectAuthorizations + # Calculating new project authorizations when not supporting nested groups. + class WithoutNestedGroups + attr_reader :user + + # user - The User object for which to calculate the authorizations. + def initialize(user) + @user = user + end + + def calculate + relations = [ + # Projects the user is a direct member of + user.projects.select_for_project_authorization, + + # Personal projects + user.personal_projects.select_as_master_for_project_authorization, + + # Projects of groups the user is a member of + user.groups_projects.select_for_project_authorization, + + # Projects shared with groups the user is a member of + user.groups.joins(:shared_projects).select_for_project_authorization + ] + + union = Gitlab::SQL::Union.new(relations) + + ProjectAuthorization. + unscoped. + select_from_union(union) + end + end + end +end diff --git a/lib/gitlab/sql/recursive_cte.rb b/lib/gitlab/sql/recursive_cte.rb new file mode 100644 index 00000000000..5b1b03820a3 --- /dev/null +++ b/lib/gitlab/sql/recursive_cte.rb @@ -0,0 +1,62 @@ +module Gitlab + module SQL + # Class for easily building recursive CTE statements. + # + # Example: + # + # cte = RecursiveCTE.new(:my_cte_name) + # ns = Arel::Table.new(:namespaces) + # + # cte << Namespace. + # where(ns[:parent_id].eq(some_namespace_id)) + # + # cte << Namespace. + # from([ns, cte.table]). + # where(ns[:parent_id].eq(cte.table[:id])) + # + # Namespace.with. + # recursive(cte.to_arel). + # from(cte.alias_to(ns)) + class RecursiveCTE + attr_reader :table + + # name - The name of the CTE as a String or Symbol. + def initialize(name) + @table = Arel::Table.new(name) + @queries = [] + end + + # Adds a query to the body of the CTE. + # + # relation - The relation object to add to the body of the CTE. + def <<(relation) + @queries << relation + end + + # Returns the Arel relation for this CTE. + def to_arel + sql = Arel::Nodes::SqlLiteral.new(Union.new(@queries).to_sql) + + Arel::Nodes::As.new(table, Arel::Nodes::Grouping.new(sql)) + end + + # Returns an "AS" statement that aliases the CTE name as the given table + # name. This allows one to trick ActiveRecord into thinking it's selecting + # from an actual table, when in reality it's selecting from a CTE. + # + # alias_table - The Arel table to use as the alias. + def alias_to(alias_table) + Arel::Nodes::As.new(table, alias_table) + end + + # Applies the CTE to the given relation, returning a new one that will + # query from it. + def apply_to(relation) + relation.except(:where). + with. + recursive(to_arel). + from(alias_to(relation.model.arel_table)) + end + end + end +end -- cgit v1.2.3 From 34974258bc3f745c86512319231bad47232fe007 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Wed, 3 May 2017 14:49:37 +0200 Subject: Hide nested group UI/API support for MySQL This hides/disables some UI elements and API parameters related to nested groups when MySQL is used, since nested groups are not supported for MySQL. --- lib/api/entities.rb | 5 ++++- lib/api/groups.rb | 6 +++++- lib/api/v3/entities.rb | 5 ++++- lib/api/v3/groups.rb | 6 +++++- lib/gitlab/group_hierarchy.rb | 6 ++++++ lib/gitlab/project_authorizations/with_nested_groups.rb | 3 --- 6 files changed, 24 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3fc2b453eb6..e3692a58119 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -152,7 +152,10 @@ module API expose :web_url expose :request_access_enabled expose :full_name, :full_path - expose :parent_id + + if ::Group.supports_nested_groups? + expose :parent_id + end expose :statistics, if: :statistics do with_options format_with: -> (value) { value.to_i } do diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 3da7d735da8..ee85b777aff 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -70,7 +70,11 @@ module API params do requires :name, type: String, desc: 'The name of the group' requires :path, type: String, desc: 'The path of the group' - optional :parent_id, type: Integer, desc: 'The parent group id for creating nested group' + + if ::Group.supports_nested_groups? + optional :parent_id, type: Integer, desc: 'The parent group id for creating nested group' + end + use :optional_params end post do diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index 56a9b019f1b..101f566f1dd 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -137,7 +137,10 @@ module API expose :web_url expose :request_access_enabled expose :full_name, :full_path - expose :parent_id + + if ::Group.supports_nested_groups? + expose :parent_id + end expose :statistics, if: :statistics do with_options format_with: -> (value) { value.to_i } do diff --git a/lib/api/v3/groups.rb b/lib/api/v3/groups.rb index 6187445fc8d..2c52d21fa1c 100644 --- a/lib/api/v3/groups.rb +++ b/lib/api/v3/groups.rb @@ -74,7 +74,11 @@ module API params do requires :name, type: String, desc: 'The name of the group' requires :path, type: String, desc: 'The path of the group' - optional :parent_id, type: Integer, desc: 'The parent group id for creating nested group' + + if ::Group.supports_nested_groups? + optional :parent_id, type: Integer, desc: 'The parent group id for creating nested group' + end + use :optional_params end post do diff --git a/lib/gitlab/group_hierarchy.rb b/lib/gitlab/group_hierarchy.rb index 50e057892a6..e9d5d52cabb 100644 --- a/lib/gitlab/group_hierarchy.rb +++ b/lib/gitlab/group_hierarchy.rb @@ -15,12 +15,16 @@ module Gitlab # Returns a relation that includes the base set of groups and all their # ancestors (recursively). def base_and_ancestors + return model.none unless Group.supports_nested_groups? + base_and_ancestors_cte.apply_to(model.all) end # Returns a relation that includes the base set of groups and all their # descendants (recursively). def base_and_descendants + return model.none unless Group.supports_nested_groups? + base_and_descendants_cte.apply_to(model.all) end @@ -45,6 +49,8 @@ module Gitlab # Using this approach allows us to further add criteria to the relation with # Rails thinking it's selecting data the usual way. def all_groups + return base unless Group.supports_nested_groups? + ancestors = base_and_ancestors_cte descendants = base_and_descendants_cte diff --git a/lib/gitlab/project_authorizations/with_nested_groups.rb b/lib/gitlab/project_authorizations/with_nested_groups.rb index 79c082c08fd..bb0df1e3dad 100644 --- a/lib/gitlab/project_authorizations/with_nested_groups.rb +++ b/lib/gitlab/project_authorizations/with_nested_groups.rb @@ -19,9 +19,6 @@ module Gitlab projects = Project.arel_table links = ProjectGroupLink.arel_table - # These queries don't directly use the user object so they don't depend - # on the state of said object, ensuring the produced queries are always - # the same. relations = [ # The project a user has direct access to. user.projects.select_for_project_authorization, -- cgit v1.2.3 From 24b105e2e1339fd65cc43727e550edb004277383 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 17 May 2017 11:27:30 -0500 Subject: Add auxiliary blob viewers to dependency files --- lib/gitlab/file_detector.rb | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb index c6a89597b23..a8cb7fc3fe7 100644 --- a/lib/gitlab/file_detector.rb +++ b/lib/gitlab/file_detector.rb @@ -5,17 +5,33 @@ module Gitlab # a README or a CONTRIBUTING file. module FileDetector PATTERNS = { + # Project files readme: /\Areadme/i, changelog: /\A(changelog|history|changes|news)/i, license: /\A(licen[sc]e|copying)(\..+|\z)/i, contributing: /\Acontributing/i, version: 'version', + avatar: /\Alogo\.(png|jpg|gif)\z/, + + # Configuration files gitignore: '.gitignore', koding: '.koding.yml', - gemfile: /\A(Gemfile|gems\.rb)\z/, gitlab_ci: '.gitlab-ci.yml', - avatar: /\Alogo\.(png|jpg|gif)\z/, - route_map: 'route-map.yml' + route_map: 'route-map.yml', + + # Dependency files + cartfile: /\ACartfile/, + composer_json: 'composer.json', + gemfile: /\A(Gemfile|gems\.rb)\z/, + gemfile_lock: 'Gemfile.lock', + gemspec: /\.gemspec\z/, + godeps_json: 'Godeps.json', + package_json: 'package.json', + podfile: 'Podfile', + podspec_json: /\.podspec\.json\z/, + podspec: /\.podspec\z/, + requirements_txt: /requirements\.txt\z/, + yarn_lock: 'yarn.lock' }.freeze # Returns an Array of file types based on the given paths. -- cgit v1.2.3 From 611c2fb0bc1dea8ff8e47b8a62354ca9a1c002d7 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 17 May 2017 15:17:02 -0400 Subject: Fix invalid object reference in ee_compat_check script --- lib/gitlab/ee_compat_check.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index 198896220ac..38e27513281 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -131,7 +131,7 @@ module Gitlab def check_patch(patch_path) step("Checking out master", %w[git checkout master]) step("Resetting to latest master", %w[git reset --hard origin/master]) - step("Fetching CE/#{branch}", %W[git fetch #{CE_REPO} #{branch}]) + step("Fetching CE/#{ce_branch}", %W[git fetch #{CE_REPO} #{ce_branch}]) step( "Checking if #{patch_path} applies cleanly to EE/master", %W[git apply --check --3way #{patch_path}] -- cgit v1.2.3 From 925945f01b1dcaf7b288afd7be53175a04eaecad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Fri, 17 Mar 2017 16:36:46 -0300 Subject: Incorporate Gitaly's local_branches operation into repo code --- lib/gitlab/git/branch.rb | 34 ++++++++++++++++++++++++++++++++++ lib/gitlab/git/commit.rb | 1 + lib/gitlab/git/repository.rb | 37 +++++++++++++++++++++++++++++++------ lib/gitlab/gitaly_client/ref.rb | 16 ++++++++++++++++ 4 files changed, 82 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/branch.rb b/lib/gitlab/git/branch.rb index 586380da94a..124526e4b59 100644 --- a/lib/gitlab/git/branch.rb +++ b/lib/gitlab/git/branch.rb @@ -1,6 +1,40 @@ module Gitlab module Git class Branch < Ref + def initialize(repository, name, target) + if target.is_a?(Gitaly::FindLocalBranchResponse) + target = target_from_gitaly_local_branches_response(target) + end + + super(repository, name, target) + end + + def target_from_gitaly_local_branches_response(response) + # Git messages have no encoding enforcements. However, in the UI we only + # handle UTF-8, so basically we cross our fingers that the message force + # encoded to UTF-8 is readable. + message = response.commit_subject.dup.force_encoding('UTF-8') + + # NOTE: For ease of parsing in Gitaly, we have only the subject of + # the commit and not the full message. This is ok, since all the + # code that uses `local_branches` only cares at most about the + # commit message. + # TODO: Once gitaly "takes over" Rugged consider separating the + # subject from the message to make it clearer when there's one + # available but not the other. + hash = { + id: response.commit_id, + message: message, + authored_date: Time.at(response.commit_author.date.seconds), + author_name: response.commit_author.name, + author_email: response.commit_author.email, + committed_date: Time.at(response.commit_committer.date.seconds), + committer_name: response.commit_committer.name, + committer_email: response.commit_committer.email + } + + Gitlab::Git::Commit.decorate(hash) + end end end end diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index e14c3511e60..297531db4cc 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -49,6 +49,7 @@ module Gitlab # Commit.find(repo, 'master') # def find(repo, commit_id = "HEAD") + return commit_id if commit_id.is_a?(Gitlab::Git::Commit) return decorate(commit_id) if commit_id.is_a?(Rugged::Commit) obj = if commit_id.is_a?(String) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index d380c5021ee..018b56c6dbe 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -80,14 +80,16 @@ module Gitlab end # Returns an Array of Branches - def branches - rugged.branches.map do |rugged_ref| + def branches(filter: nil, sort_by: nil) + branches = rugged.branches.each(filter).map do |rugged_ref| begin Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target) rescue Rugged::ReferenceError # Omit invalid branch end - end.compact.sort_by(&:name) + end.compact + + sort_branches(branches, sort_by) end def reload_rugged @@ -108,9 +110,15 @@ module Gitlab Gitlab::Git::Branch.new(self, rugged_ref.name, rugged_ref.target) if rugged_ref end - def local_branches - rugged.branches.each(:local).map do |branch| - Gitlab::Git::Branch.new(self, branch.name, branch.target) + def local_branches(sort_by: nil) + gitaly_migrate(:local_branches) do |is_enabled| + if is_enabled + gitaly_ref_client.local_branches(sort_by: sort_by).map do |gitaly_branch| + Gitlab::Git::Branch.new(self, gitaly_branch.name, gitaly_branch) + end + else + branches(filter: :local, sort_by: sort_by) + end end end @@ -1202,6 +1210,23 @@ module Gitlab diff.each_patch end + def sort_branches(branches, sort_by) + case sort_by + when 'name' + branches.sort_by(&:name) + when 'updated_desc' + branches.sort do |a, b| + b.dereferenced_target.committed_date <=> a.dereferenced_target.committed_date + end + when 'updated_asc' + branches.sort do |a, b| + a.dereferenced_target.committed_date <=> b.dereferenced_target.committed_date + end + else + branches + end + end + def gitaly_ref_client @gitaly_ref_client ||= Gitlab::GitalyClient::Ref.new(self) end diff --git a/lib/gitlab/gitaly_client/ref.rb b/lib/gitlab/gitaly_client/ref.rb index bf04e1fa50b..614c6be3029 100644 --- a/lib/gitlab/gitaly_client/ref.rb +++ b/lib/gitlab/gitaly_client/ref.rb @@ -44,6 +44,12 @@ module Gitlab branch_names.count end + def local_branches(sort_by: nil) + request = Gitaly::FindLocalBranchesRequest.new(repository: @gitaly_repo) + request.sort_by = sort_by_param(sort_by) if sort_by + consume_branches_response(stub.find_local_branches(request)) + end + private def consume_refs_response(response, prefix:) @@ -51,6 +57,16 @@ module Gitlab r.names.map { |name| name.sub(/\A#{Regexp.escape(prefix)}/, '') } end end + + def sort_by_param(sort_by) + enum_value = Gitaly::FindLocalBranchesRequest::SortBy.resolve(sort_by.upcase.to_sym) + raise ArgumentError, "Invalid sort_by key `#{sort_by}`" unless enum_value + enum_value + end + + def consume_branches_response(response) + response.flat_map { |r| r.branches } + end end end end -- cgit v1.2.3 From e6a4b8c16337f26c6688f0b6ef5579daf9a50d39 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Thu, 18 May 2017 09:40:35 +0100 Subject: Add current_user_avatar_url to gon --- lib/gitlab/gon_helper.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index 26473f99bc3..6200bd460ea 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -17,6 +17,7 @@ module Gitlab gon.current_user_id = current_user.id gon.current_username = current_user.username gon.current_user_fullname = current_user.name + gon.current_user_avatar_url = current_user.avatar_url end end end -- cgit v1.2.3 From 110f5a16547865156c5cae10d0d6171dab442029 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 18 May 2017 10:47:18 -0500 Subject: Catch all URI errors in ExternalLinkFilter --- lib/banzai/filter/external_link_filter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb index 7d15a0f6d44..d6327ef31cb 100644 --- a/lib/banzai/filter/external_link_filter.rb +++ b/lib/banzai/filter/external_link_filter.rb @@ -24,7 +24,7 @@ module Banzai def uri(href) URI.parse(href) - rescue URI::InvalidURIError + rescue URI::Error nil end -- cgit v1.2.3 From 3396edcea054f97c41b334b2800760817a47ba0a Mon Sep 17 00:00:00 2001 From: Ruben Davila Date: Thu, 18 May 2017 11:49:11 -0500 Subject: Remove Services count from usage ping payload. This query was timing out and is blocking the sync of usage data for GitLab.com --- lib/gitlab/usage_data.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 4382cf7b12f..bcba2e3e1b6 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -40,7 +40,6 @@ module Gitlab projects_prometheus_active: PrometheusService.active.count, protected_branches: ProtectedBranch.count, releases: Release.count, - services: Service.where(active: true).count, snippets: Snippet.count, todos: Todo.count, uploads: Upload.count, -- cgit v1.2.3 From fb3077e67b527f92a917e0f8b6f2745a322bce9a Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 19 May 2017 00:57:37 +0800 Subject: Complete all legacy builds URL. Tests are added --- lib/gitlab/routes/legacy_builds.rb | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 lib/gitlab/routes/legacy_builds.rb (limited to 'lib') diff --git a/lib/gitlab/routes/legacy_builds.rb b/lib/gitlab/routes/legacy_builds.rb new file mode 100644 index 00000000000..ecf0c65d70a --- /dev/null +++ b/lib/gitlab/routes/legacy_builds.rb @@ -0,0 +1,44 @@ + +module Gitlab + module Routes + class LegacyBuilds + def initialize(map) + @map = map + end + + def draw + redirect_builds_to_jobs = @map.redirect(&method(:redirect)) + + @map.get '/builds(/:id(/*action))', to: redirect_builds_to_jobs, + as: 'legacy_build', + format: false + end + + def redirect(params, req) + args = params.values_at(:namespace_id, :project_id, :id).compact + url_helpers = Gitlab::Routing.url_helpers + + if params[:id] + case params[:action] + when 'status' + url_helpers.status_namespace_project_job_path(*args, format: params[:format]) + when 'trace' + url_helpers.trace_namespace_project_job_path(*args, format: params[:format]) + when 'raw' + url_helpers.raw_namespace_project_job_path(*args) + when String + if params[:id] == 'artifacts' + url_helpers.latest_succeeded_namespace_project_artifacts_path(params[:namespace_id], params[:project_id], params[:action], job: req.GET[:job]) + else + "#{url_helpers.namespace_project_job_path(*args)}/#{params[:action]}" + end + else # show + url_helpers.namespace_project_job_path(*args) + end + else # index + url_helpers.namespace_project_jobs_path(*args) + end + end + end + end +end -- cgit v1.2.3 From de33a5bd535d6f4a1dc6cbdb2bd1b208ab6475e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Thu, 18 May 2017 15:33:43 -0400 Subject: Prevent errors from non-functional notify_post_receive endpoint --- lib/api/internal.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 96aaaf868ea..9ebd4841296 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -136,14 +136,15 @@ module API post "/notify_post_receive" do status 200 - return unless Gitlab::GitalyClient.enabled? - - begin - repository = wiki? ? project.wiki.repository : project.repository - Gitlab::GitalyClient::Notifications.new(repository.raw_repository).post_receive - rescue GRPC::Unavailable => e - render_api_error!(e, 500) - end + # TODO: Re-enable when Gitaly is processing the post-receive notification + # return unless Gitlab::GitalyClient.enabled? + # + # begin + # repository = wiki? ? project.wiki.repository : project.repository + # Gitlab::GitalyClient::Notifications.new(repository.raw_repository).post_receive + # rescue GRPC::Unavailable => e + # render_api_error!(e, 500) + # end end end end -- cgit v1.2.3 From f62f0c258d89465bea514e5127ea1effdeb3b35d Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 18 May 2017 20:08:32 +0000 Subject: Fixes for the rename reserved paths helpers --- .../rename_reserved_paths_migration/v1/migration_classes.rb | 8 ++++++++ .../database/rename_reserved_paths_migration/v1/rename_base.rb | 3 ++- .../rename_reserved_paths_migration/v1/rename_namespaces.rb | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb index 4fdcb682c2f..5481024db8e 100644 --- a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb +++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb @@ -48,6 +48,14 @@ module Gitlab def self.name 'Namespace' end + + def kind + type == 'Group' ? 'group' : 'user' + end + end + + class User < ActiveRecord::Base + self.table_name = 'users' end class Route < ActiveRecord::Base diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb index 5397877b5d5..d60fd4bb551 100644 --- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb +++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb @@ -41,7 +41,8 @@ module Gitlab new_full_path) update_column_in_batches(:routes, :path, replace_statement) do |table, query| - query.where(MigrationClasses::Route.arel_table[:path].matches("#{old_full_path}%")) + path_or_children = table[:path].matches_any([old_full_path, "#{old_full_path}/%"]) + query.where(path_or_children) end end diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb index b9f4f3cff3c..2958ad4b8e5 100644 --- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb +++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb @@ -29,9 +29,15 @@ module Gitlab move_repositories(namespace, old_full_path, new_full_path) move_uploads(old_full_path, new_full_path) move_pages(old_full_path, new_full_path) + rename_user(old_full_path, new_full_path) if namespace.kind == 'user' remove_cached_html_for_projects(projects_for_namespace(namespace).map(&:id)) end + def rename_user(old_username, new_username) + MigrationClasses::User.where(username: old_username) + .update_all(username: new_username) + end + def move_repositories(namespace, old_full_path, new_full_path) repo_paths_for_namespace(namespace).each do |repository_storage_path| # Ensure old directory exists before moving it -- cgit v1.2.3 From 7a7e9288d4dea50a9797b3f624bf8174fa7060d4 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 18 May 2017 15:48:42 -0500 Subject: Stop MR conflict code from blowing up when branches are missing --- lib/gitlab/diff/position_tracer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/diff/position_tracer.rb b/lib/gitlab/diff/position_tracer.rb index c7542a8fabc..e89ff238ec7 100644 --- a/lib/gitlab/diff/position_tracer.rb +++ b/lib/gitlab/diff/position_tracer.rb @@ -16,7 +16,7 @@ module Gitlab end def trace(old_position) - return unless old_diff_refs.complete? && new_diff_refs.complete? + return unless old_diff_refs&.complete? && new_diff_refs&.complete? return unless old_position.diff_refs == old_diff_refs # Suppose we have an MR with source branch `feature` and target branch `master`. -- cgit v1.2.3 From 876acc7e0d654ebc89df3c596cc504334a37f7d8 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 19 May 2017 14:59:05 +0800 Subject: Separate artifacts from builds, reusing artifacts_action_path --- lib/gitlab/routes/legacy_builds.rb | 49 +++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/routes/legacy_builds.rb b/lib/gitlab/routes/legacy_builds.rb index ecf0c65d70a..2ae6a93981b 100644 --- a/lib/gitlab/routes/legacy_builds.rb +++ b/lib/gitlab/routes/legacy_builds.rb @@ -2,43 +2,60 @@ module Gitlab module Routes class LegacyBuilds + include Gitlab::Routing.url_helpers + include GitlabRoutingHelper + def initialize(map) @map = map end def draw - redirect_builds_to_jobs = @map.redirect(&method(:redirect)) + redirect_artifacts = @map.redirect(&method(:redirect_artifacts)) + redirect_builds = @map.redirect(&method(:redirect_builds)) + + @map.get '/builds(/:id)/artifacts/*action', to: redirect_artifacts, + as: 'legacy_artifacts', + format: false - @map.get '/builds(/:id(/*action))', to: redirect_builds_to_jobs, - as: 'legacy_build', + @map.get '/builds(/:id(/*action))', to: redirect_builds, + as: 'legacy_builds', format: false end - def redirect(params, req) + private + + def redirect_artifacts(params, req) + if params[:id] + project = fake_project(*params.values_at(:namespace_id, :project_id)) + + artifacts_action_path(params[:action], project, params[:id]) + else + latest_succeeded_namespace_project_artifacts_path(params[:namespace_id], params[:project_id], params[:action], job: req.GET[:job]) + end + end + + def redirect_builds(params, req) args = params.values_at(:namespace_id, :project_id, :id).compact - url_helpers = Gitlab::Routing.url_helpers if params[:id] case params[:action] when 'status' - url_helpers.status_namespace_project_job_path(*args, format: params[:format]) + status_namespace_project_job_path(*args, format: params[:format]) when 'trace' - url_helpers.trace_namespace_project_job_path(*args, format: params[:format]) + trace_namespace_project_job_path(*args, format: params[:format]) when 'raw' - url_helpers.raw_namespace_project_job_path(*args) - when String - if params[:id] == 'artifacts' - url_helpers.latest_succeeded_namespace_project_artifacts_path(params[:namespace_id], params[:project_id], params[:action], job: req.GET[:job]) - else - "#{url_helpers.namespace_project_job_path(*args)}/#{params[:action]}" - end + raw_namespace_project_job_path(*args) else # show - url_helpers.namespace_project_job_path(*args) + namespace_project_job_path(*args) end else # index - url_helpers.namespace_project_jobs_path(*args) + namespace_project_jobs_path(*args) end end + + def fake_project(namespace_id, project_id) + Struct.new(:namespace, :to_param).new(namespace_id, project_id) + end end end end -- cgit v1.2.3 From ef73fe300c047d659c5bb665f200531efa95ac0b Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Sun, 21 May 2017 13:38:03 +0100 Subject: Use Gitlab::REVISION over reading HEAD sha from git --- lib/gitlab/gon_helper.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index 6200bd460ea..21f2e6b6970 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -12,6 +12,7 @@ module Gitlab gon.katex_js_url = ActionController::Base.helpers.asset_path('katex.js') gon.sentry_dsn = current_application_settings.clientside_sentry_dsn if current_application_settings.clientside_sentry_enabled gon.gitlab_url = Gitlab.config.gitlab.url + gon.revision = Gitlab::REVISION if current_user gon.current_user_id = current_user.id -- cgit v1.2.3 From 9735ce15de5255365e302d1f50b301039512f50d Mon Sep 17 00:00:00 2001 From: Horatiu Eugen Vlad Date: Fri, 19 May 2017 08:38:31 +0000 Subject: Avoid resource intensive login checks if password is not provided Fixes #32598 --- lib/gitlab/auth.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index ea918b23a63..099c45dcfb7 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -37,6 +37,9 @@ module Gitlab end def find_with_user_password(login, password) + # Avoid resource intensive login checks if password is not provided + return unless password.present? + Gitlab::Auth::UniqueIpsLimiter.limit_user! do user = User.by_login(login) @@ -44,7 +47,7 @@ module Gitlab # LDAP users are only authenticated via LDAP if user.nil? || user.ldap_user? # Second chance - try LDAP authentication - return nil unless Gitlab::LDAP::Config.enabled? + return unless Gitlab::LDAP::Config.enabled? Gitlab::LDAP::Authentication.login(login, password) else -- cgit v1.2.3 From bb8ae56085cbae9545f8a78d0131bb857f53fbf6 Mon Sep 17 00:00:00 2001 From: Richard Clamp Date: Mon, 22 May 2017 15:49:19 +0100 Subject: Add missing `can_push` parameter to POST /v3/deploy_keys The v3 API documentation claims that `can_push` is supported when adding a deploy_key. https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/deploy_keys.md#add-deploy-key Here we make good on this promise by adding `can_push` as an optional parameter so grape can route it. This was copied from the v4 API. --- lib/api/v3/deploy_keys.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/api/v3/deploy_keys.rb b/lib/api/v3/deploy_keys.rb index bbb174b6003..b90e2061da3 100644 --- a/lib/api/v3/deploy_keys.rb +++ b/lib/api/v3/deploy_keys.rb @@ -41,6 +41,7 @@ module API params do requires :key, type: String, desc: 'The new deploy key' requires :title, type: String, desc: 'The name of the deploy key' + optional :can_push, type: Boolean, desc: "Can deploy key push to the project's repository" end post ":id/#{path}" do params[:key].strip! -- cgit v1.2.3 From ebede2b3ff1c2b089529c4f9d6268641580e280b Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 12 May 2017 15:19:27 +0200 Subject: Use etag caching for environments JSON For the index view, the environments can now be requested every 15 seconds. Any transition state of a projects environments will trigger a cache invalidation action. Fixes gitlab-org/gitlab-ce#31701 --- lib/gitlab/etag_caching/router.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index ba31041d0c1..01bf578c570 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -7,9 +7,10 @@ module Gitlab # - Don't contain a reserved word (expect for the words used in the # regex itself) # - Ending in `noteable/issue//notes` for the `issue_notes` route - # - Ending in `issues/id`/realtime_changes` for the `issue_title` route + # - Ending in `issues/id`/rendered_title` for the `issue_title` route USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes - commit pipelines merge_requests new].freeze + commit pipelines merge_requests new + environments].freeze RESERVED_WORDS = DynamicPathValidator::WILDCARD_ROUTES - USED_IN_ROUTES RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS) ROUTES = [ @@ -40,6 +41,10 @@ module Gitlab Gitlab::EtagCaching::Router::Route.new( %r(^(?!.*(#{RESERVED_WORDS})).*/pipelines/\d+\.json\z), 'project_pipeline' + ), + Gitlab::EtagCaching::Router::Route.new( + %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/environments\.json\z), + 'environments' ) ].freeze -- cgit v1.2.3 From 33961ee418e861a021d7f70bdb1540de9d159b95 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Mon, 22 May 2017 19:24:27 +0200 Subject: Add Etag caching for Pipeline#Show action Due to a typo this was not actually the case. Now that is fixed and performance should improve because of this. --- lib/gitlab/etag_caching/router.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index ba31041d0c1..bdf885559c5 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -38,7 +38,7 @@ module Gitlab 'project_pipelines' ), Gitlab::EtagCaching::Router::Route.new( - %r(^(?!.*(#{RESERVED_WORDS})).*/pipelines/\d+\.json\z), + %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/pipelines/\d+\.json\z), 'project_pipeline' ) ].freeze -- cgit v1.2.3 From 450e2cd879d2e819f084dd3940cf19a9521c2611 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 23 May 2017 10:20:54 +0200 Subject: Add missing regex to backup manager https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10901/diffs introduced a new naming scheme for backups, but the code which cleans up old backups wasn't updated accordingly. In order to maintain backward compatibility, we need to account for 3 naming schemes. --- lib/backup/manager.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 330cd963626..e8e0e2f07d4 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -84,7 +84,12 @@ module Backup Dir.chdir(backup_path) do backup_file_list.each do |file| - next unless file =~ /(\d+)(?:_\d{4}_\d{2}_\d{2})?_gitlab_backup\.tar/ + + # For backward compatibility, there are 3 names the backups can have: + # - 1495527122_gitlab_backup.tar + # - 1495527068_2017_05_23_gitlab_backup.tar + # - 1495527097_2017_05_23_9.3.0-pre_gitlab_backup.tar + next unless file =~ /(\d+)(?:_\d{4}_\d{2}_\d{2}(_\d+\.\d+\.\d+.*)?)?_gitlab_backup\.tar$/ timestamp = $1.to_i -- cgit v1.2.3 From e4d9be0e6b3a17b8197928336ba9f27f86c3564b Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 23 May 2017 11:17:25 +0200 Subject: Fix rubocop --- lib/backup/manager.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index e8e0e2f07d4..f755c99ea4a 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -84,7 +84,6 @@ module Backup Dir.chdir(backup_path) do backup_file_list.each do |file| - # For backward compatibility, there are 3 names the backups can have: # - 1495527122_gitlab_backup.tar # - 1495527068_2017_05_23_gitlab_backup.tar -- cgit v1.2.3 From 43981250c426595c9b3c03a5153ae05d3de2a8e2 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 23 May 2017 21:20:59 +0800 Subject: Use controllers to redirect --- lib/gitlab/routes/legacy_builds.rb | 68 ++++++++++++++------------------------ 1 file changed, 24 insertions(+), 44 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/routes/legacy_builds.rb b/lib/gitlab/routes/legacy_builds.rb index 2ae6a93981b..cbb8b960c7e 100644 --- a/lib/gitlab/routes/legacy_builds.rb +++ b/lib/gitlab/routes/legacy_builds.rb @@ -1,4 +1,3 @@ - module Gitlab module Routes class LegacyBuilds @@ -10,52 +9,33 @@ module Gitlab end def draw - redirect_artifacts = @map.redirect(&method(:redirect_artifacts)) - redirect_builds = @map.redirect(&method(:redirect_builds)) - - @map.get '/builds(/:id)/artifacts/*action', to: redirect_artifacts, - as: 'legacy_artifacts', - format: false - - @map.get '/builds(/:id(/*action))', to: redirect_builds, - as: 'legacy_builds', - format: false - end - - private - - def redirect_artifacts(params, req) - if params[:id] - project = fake_project(*params.values_at(:namespace_id, :project_id)) - - artifacts_action_path(params[:action], project, params[:id]) - else - latest_succeeded_namespace_project_artifacts_path(params[:namespace_id], params[:project_id], params[:action], job: req.GET[:job]) - end - end - - def redirect_builds(params, req) - args = params.values_at(:namespace_id, :project_id, :id).compact - - if params[:id] - case params[:action] - when 'status' - status_namespace_project_job_path(*args, format: params[:format]) - when 'trace' - trace_namespace_project_job_path(*args, format: params[:format]) - when 'raw' - raw_namespace_project_job_path(*args) - else # show - namespace_project_job_path(*args) + @map.instance_eval do + resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do + collection do + resources :artifacts, only: [], controller: 'build_artifacts' do + collection do + get :latest_succeeded, + path: '*ref_name_and_path', + format: false + end + end + end + + member do + get :status + get :trace, defaults: { format: 'json' } + get :raw + end + + resource :artifacts, only: [], controller: 'build_artifacts' do + get :download + get :browse, path: 'browse(/*path)', format: false + get :file, path: 'file/*path', format: false + get :raw, path: 'raw/*path', format: false + end end - else # index - namespace_project_jobs_path(*args) end end - - def fake_project(namespace_id, project_id) - Struct.new(:namespace, :to_param).new(namespace_id, project_id) - end end end end -- cgit v1.2.3 From aa24feed6fa0e24d1e78d38b3f26b4bd26b016b8 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:25:57 -0500 Subject: Refactor DependencyLinker::BaseLinker --- lib/gitlab/dependency_linker/base_linker.rb | 58 ++++---------------------- lib/gitlab/dependency_linker/gemfile_linker.rb | 23 +++++----- lib/gitlab/dependency_linker/method_linker.rb | 48 +++++++++++++++++++++ 3 files changed, 70 insertions(+), 59 deletions(-) create mode 100644 lib/gitlab/dependency_linker/method_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb index 5f4027e7e81..019e670081e 100644 --- a/lib/gitlab/dependency_linker/base_linker.rb +++ b/lib/gitlab/dependency_linker/base_linker.rb @@ -1,6 +1,8 @@ module Gitlab module DependencyLinker class BaseLinker + URL_REGEX = %r{https?://[^'"]+}.freeze + class_attribute :file_type def self.support?(blob_name) @@ -26,59 +28,17 @@ module Gitlab private - def package_url(name) - raise NotImplementedError - end - def link_dependencies raise NotImplementedError end - def package_link(name, url = package_url(name)) - return name unless url - - %{#{ERB::Util.html_escape_once(name)}} + def license_url(name) + Licensee::License.find(name)&.url end - # Links package names in a method call or assignment string argument. - # - # Example: - # link_method_call("gem") - # # Will link `package` in `gem "package"`, `gem("package")` and `gem = "package"` - # - # link_method_call("gem", "specific_package") - # # Will link `specific_package` in `gem "specific_package"` - # - # link_method_call("github", /[^\/]+\/[^\/]+/) - # # Will link `user/repo` in `github "user/repo"`, but not `github "package"` - # - # link_method_call(%w[add_dependency add_development_dependency]) - # # Will link `spec.add_dependency "package"` and `spec.add_development_dependency "package"` - # - # link_method_call("name") - # # Will link `package` in `self.name = "package"` - def link_method_call(method_names, value = nil, &url_proc) - value = - case value - when String - Regexp.escape(value) - when nil - /[^'"]+/ - else - value - end - - method_names = Array(method_names).map { |name| Regexp.escape(name) } - - regex = %r{ - #{Regexp.union(method_names)} # Method name - \s* # Whitespace - [(=]? # Opening brace or equals sign - \s* # Whitespace - ['"](?#{value})['"] # Package name in quotes - }x - link_regex(regex, &url_proc) + def link_tag(name, url) + %{#{ERB::Util.html_escape_once(name)}} end # Links package names based on regex. @@ -86,13 +46,13 @@ module Gitlab # Example: # link_regex(/(github:|:github =>)\s*['"](?[^'"]+)['"]/) # # Will link `user/repo` in `github: "user/repo"` or `:github => "user/repo"` - def link_regex(regex) + def link_regex(regex, &url_proc) highlighted_lines.map!.with_index do |rich_line, i| marker = StringRegexMarker.new(plain_lines[i], rich_line.html_safe) marker.mark(regex, group: :name) do |text, left:, right:| - url = block_given? ? yield(text) : package_url(text) - package_link(text, url) + url = yield(text) + url ? link_tag(text, url) : text end end end diff --git a/lib/gitlab/dependency_linker/gemfile_linker.rb b/lib/gitlab/dependency_linker/gemfile_linker.rb index 9b82e126528..d034ea67387 100644 --- a/lib/gitlab/dependency_linker/gemfile_linker.rb +++ b/lib/gitlab/dependency_linker/gemfile_linker.rb @@ -1,28 +1,31 @@ module Gitlab module DependencyLinker - class GemfileLinker < BaseLinker + class GemfileLinker < MethodLinker self.file_type = :gemfile private def link_dependencies - # Link `gem "package_name"` to https://rubygems.org/gems/package_name - link_method_call("gem") + link_urls + link_packages + end + def link_urls # Link `github: "user/repo"` to https://github.com/user/repo - link_regex(/(github:|:github\s*=>)\s*['"](?[^'"]+)['"]/) do |name| - "https://github.com/#{name}" - end + link_regex(/(github:|:github\s*=>)\s*['"](?[^'"]+)['"]/, &method(:github_url)) # Link `git: "https://gitlab.example.com/user/repo"` to https://gitlab.example.com/user/repo - link_regex(%r{(git:|:git\s*=>)\s*['"](?https?://[^'"]+)['"]}) { |url| url } + link_regex(%r{(git:|:git\s*=>)\s*['"](?#{URL_REGEX})['"]}, &:itself) # Link `source "https://rubygems.org"` to https://rubygems.org - link_method_call("source", %r{https?://[^'"]+}) { |url| url } + link_method_call('source', URL_REGEX, &:itself) end - def package_url(name) - "https://rubygems.org/gems/#{name}" + def link_packages + # Link `gem "package_name"` to https://rubygems.org/gems/package_name + link_method_call('gem') do |name| + "https://rubygems.org/gems/#{name}" + end end end end diff --git a/lib/gitlab/dependency_linker/method_linker.rb b/lib/gitlab/dependency_linker/method_linker.rb new file mode 100644 index 00000000000..eeb7c1587c0 --- /dev/null +++ b/lib/gitlab/dependency_linker/method_linker.rb @@ -0,0 +1,48 @@ +module Gitlab + module DependencyLinker + class MethodLinker < BaseLinker + private + + # Links package names in a method call or assignment string argument. + # + # Example: + # link_method_call('gem') + # # Will link `package` in `gem "package"`, `gem("package")` and `gem = "package"` + # + # link_method_call('gem', 'specific_package') + # # Will link `specific_package` in `gem "specific_package"` + # + # link_method_call('github', /[^\/"]+\/[^\/"]+/) + # # Will link `user/repo` in `github "user/repo"`, but not `github "package"` + # + # link_method_call(%w[add_dependency add_development_dependency]) + # # Will link `spec.add_dependency "package"` and `spec.add_development_dependency "package"` + # + # link_method_call('name') + # # Will link `package` in `self.name = "package"` + def link_method_call(method_names, value = nil, &url_proc) + method_names = Array(method_names).map { |name| Regexp.escape(name) } + + value = + case value + when String + Regexp.escape(value) + when nil + /[^'"]+/ + else + value + end + + regex = %r{ + #{Regexp.union(method_names)} # Method name + \s* # Whitespace + [(=]? # Opening brace or equals sign + \s* # Whitespace + ['"](?#{value})['"] # Package name in quotes + }x + + link_regex(regex, &url_proc) + end + end + end +end -- cgit v1.2.3 From 02ad8c0c68b575ca4957e0a478714ef2144a9b8a Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:26:31 -0500 Subject: Autolink package names in gemspec --- lib/gitlab/dependency_linker.rb | 3 ++- lib/gitlab/dependency_linker/gemspec_linker.rb | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 lib/gitlab/dependency_linker/gemspec_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index c45ae8feb2c..14fc506fbb7 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -1,7 +1,8 @@ module Gitlab module DependencyLinker LINKERS = [ - GemfileLinker + GemfileLinker, + GemspecLinker, ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/gemspec_linker.rb b/lib/gitlab/dependency_linker/gemspec_linker.rb new file mode 100644 index 00000000000..f1783ee2ab4 --- /dev/null +++ b/lib/gitlab/dependency_linker/gemspec_linker.rb @@ -0,0 +1,18 @@ +module Gitlab + module DependencyLinker + class GemspecLinker < MethodLinker + self.file_type = :gemspec + + private + + def link_dependencies + link_method_call('homepage', URL_REGEX, &:itself) + link_method_call('license', &method(:license_url)) + + link_method_call(%w[name add_dependency add_runtime_dependency add_development_dependency]) do |name| + "https://rubygems.org/gems/#{name}" + end + end + end + end +end -- cgit v1.2.3 From 83747783e25b2d8b60efa2cb1aa9d6bd823fcdfe Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:27:50 -0500 Subject: Autolink package names in package.json --- lib/gitlab/dependency_linker.rb | 1 + lib/gitlab/dependency_linker/base_linker.rb | 4 ++ lib/gitlab/dependency_linker/json_linker.rb | 63 ++++++++++++++++++++++ .../dependency_linker/package_json_linker.rb | 44 +++++++++++++++ 4 files changed, 112 insertions(+) create mode 100644 lib/gitlab/dependency_linker/json_linker.rb create mode 100644 lib/gitlab/dependency_linker/package_json_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index 14fc506fbb7..88f4ebedb9f 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -3,6 +3,7 @@ module Gitlab LINKERS = [ GemfileLinker, GemspecLinker, + PackageJsonLinker, ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb index 019e670081e..15fa9f40116 100644 --- a/lib/gitlab/dependency_linker/base_linker.rb +++ b/lib/gitlab/dependency_linker/base_linker.rb @@ -2,6 +2,7 @@ module Gitlab module DependencyLinker class BaseLinker URL_REGEX = %r{https?://[^'"]+}.freeze + REPO_REGEX = %r{[^/'"]+/[^/'"]+}.freeze class_attribute :file_type @@ -36,6 +37,9 @@ module Gitlab Licensee::License.find(name)&.url end + def github_url(name) + "https://github.com/#{name}" + end def link_tag(name, url) %{#{ERB::Util.html_escape_once(name)}} diff --git a/lib/gitlab/dependency_linker/json_linker.rb b/lib/gitlab/dependency_linker/json_linker.rb new file mode 100644 index 00000000000..021347b6429 --- /dev/null +++ b/lib/gitlab/dependency_linker/json_linker.rb @@ -0,0 +1,63 @@ +module Gitlab + module DependencyLinker + class JsonLinker < BaseLinker + def link + return highlighted_text unless json + + super + end + + private + + # Links package names in a JSON key or values. + # + # Example: + # link_json('name') + # # Will link `package` in `"name": "package"` + # + # link_json('name', 'specific_package') + # # Will link `specific_package` in `"name": "specific_package"` + # + # link_json('name', /[^\/]+\/[^\/]+/) + # # Will link `user/repo` in `"name": "user/repo"`, but not `"name": "package"` + # + # link_json('specific_package', '1.0.1', link: :key) + # # Will link `specific_package` in `"specific_package": "1.0.1"` + def link_json(key, value = nil, link: :value, &url_proc) + key = + case key + when Array + Regexp.union(key.map { |name| Regexp.escape(name) }) + when String + Regexp.escape(key) + when nil + '[^"]+' + else + key + end + + value = + case value + when String + Regexp.escape(value) + when nil + '[^"]+' + else + value + end + + if link == :value + value = "(?#{value})" + else + key = "(?#{key})" + end + + link_regex(/"#{key}":\s*"#{value}"/, &url_proc) + end + + def json + @json ||= JSON.parse(plain_text) rescue nil + end + end + end +end diff --git a/lib/gitlab/dependency_linker/package_json_linker.rb b/lib/gitlab/dependency_linker/package_json_linker.rb new file mode 100644 index 00000000000..330c95f0880 --- /dev/null +++ b/lib/gitlab/dependency_linker/package_json_linker.rb @@ -0,0 +1,44 @@ +module Gitlab + module DependencyLinker + class PackageJsonLinker < JsonLinker + self.file_type = :package_json + + private + + def link_dependencies + link_json('name', json["name"], &method(:package_url)) + link_json('license', &method(:license_url)) + link_json(%w[homepage url], URL_REGEX, &:itself) + + link_packages + end + + def link_packages + link_packages_at_key("dependencies", &method(:package_url)) + link_packages_at_key("devDependencies", &method(:package_url)) + end + + def link_packages_at_key(key, &url_proc) + dependencies = json[key] + return unless dependencies + + dependencies.each do |name, version| + link_json(name, version, link: :key, &url_proc) + + link_json(name) do |value| + case value + when /\A#{URL_REGEX}\z/ + value + when /\A#{REPO_REGEX}\z/ + github_url(value) + end + end + end + end + + def package_url(name) + "https://npmjs.com/package/#{name}" + end + end + end +end -- cgit v1.2.3 From fbec6dbd1a120cd111608c637cd63c8313aeb976 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:28:11 -0500 Subject: Autolink package names in composer.json --- lib/gitlab/dependency_linker.rb | 1 + lib/gitlab/dependency_linker/composer_json_linker.rb | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 lib/gitlab/dependency_linker/composer_json_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index 88f4ebedb9f..9cd2fbdfd17 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -4,6 +4,7 @@ module Gitlab GemfileLinker, GemspecLinker, PackageJsonLinker, + ComposerJsonLinker, ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/composer_json_linker.rb b/lib/gitlab/dependency_linker/composer_json_linker.rb new file mode 100644 index 00000000000..0245bf4077a --- /dev/null +++ b/lib/gitlab/dependency_linker/composer_json_linker.rb @@ -0,0 +1,18 @@ +module Gitlab + module DependencyLinker + class ComposerJsonLinker < PackageJsonLinker + self.file_type = :composer_json + + private + + def link_packages + link_packages_at_key("require", &method(:package_url)) + link_packages_at_key("require-dev", &method(:package_url)) + end + + def package_url(name) + "https://packagist.org/packages/#{name}" if name =~ %r{\A#{REPO_REGEX}\z} + end + end + end +end -- cgit v1.2.3 From 03db4f110613c73003f86d0ff98a7dcb6f0dae59 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:28:52 -0500 Subject: Autolink package names in Podfile --- lib/gitlab/dependency_linker.rb | 1 + lib/gitlab/dependency_linker/cocoapods.rb | 10 ++++++++++ lib/gitlab/dependency_linker/podfile_linker.rb | 15 +++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 lib/gitlab/dependency_linker/cocoapods.rb create mode 100644 lib/gitlab/dependency_linker/podfile_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index 9cd2fbdfd17..44358d2634b 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -5,6 +5,7 @@ module Gitlab GemspecLinker, PackageJsonLinker, ComposerJsonLinker, + PodfileLinker, ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/cocoapods.rb b/lib/gitlab/dependency_linker/cocoapods.rb new file mode 100644 index 00000000000..2fbde7da1b4 --- /dev/null +++ b/lib/gitlab/dependency_linker/cocoapods.rb @@ -0,0 +1,10 @@ +module Gitlab + module DependencyLinker + module Cocoapods + def package_url(name) + package = name.split("/", 2).first + "https://cocoapods.org/pods/#{package}" + end + end + end +end diff --git a/lib/gitlab/dependency_linker/podfile_linker.rb b/lib/gitlab/dependency_linker/podfile_linker.rb new file mode 100644 index 00000000000..60ad166ea17 --- /dev/null +++ b/lib/gitlab/dependency_linker/podfile_linker.rb @@ -0,0 +1,15 @@ +module Gitlab + module DependencyLinker + class PodfileLinker < GemfileLinker + include Cocoapods + + self.file_type = :podfile + + private + + def link_packages + link_method_call('pod', &method(:package_url)) + end + end + end +end -- cgit v1.2.3 From 190b7b45a605475668a089a0ce43f3d89b9d7c47 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:29:13 -0500 Subject: Autolink package names in podspec --- lib/gitlab/dependency_linker.rb | 1 + lib/gitlab/dependency_linker/podspec_linker.rb | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 lib/gitlab/dependency_linker/podspec_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index 44358d2634b..ffd6ab8e2f8 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -6,6 +6,7 @@ module Gitlab PackageJsonLinker, ComposerJsonLinker, PodfileLinker, + PodspecLinker, ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/podspec_linker.rb b/lib/gitlab/dependency_linker/podspec_linker.rb new file mode 100644 index 00000000000..a52c7a02439 --- /dev/null +++ b/lib/gitlab/dependency_linker/podspec_linker.rb @@ -0,0 +1,24 @@ +module Gitlab + module DependencyLinker + class PodspecLinker < MethodLinker + include Cocoapods + + STRING_REGEX = /['"](?[^'"]+)['"]/.freeze + + self.file_type = :podspec + + private + + def link_dependencies + link_method_call('homepage', URL_REGEX, &:itself) + + link_regex(%r{(git:|:git\s*=>)\s*['"](?#{URL_REGEX})['"]}, &:itself) + + link_method_call('license', &method(:license_url)) + link_regex(/license\s*=\s*\{\s*(type:|:type\s*=>)\s*#{STRING_REGEX}/, &method(:license_url)) + + link_method_call(%w[name dependency], &method(:package_url)) + end + end + end +end -- cgit v1.2.3 From c35463d5f856c2f8025893f2e185825dfb691f8e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:29:34 -0500 Subject: Autolink package names in podspec.json --- lib/gitlab/dependency_linker.rb | 1 + .../dependency_linker/podspec_json_linker.rb | 32 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 lib/gitlab/dependency_linker/podspec_json_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index ffd6ab8e2f8..ac16b9bde2f 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -7,6 +7,7 @@ module Gitlab ComposerJsonLinker, PodfileLinker, PodspecLinker, + PodspecJsonLinker, ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/podspec_json_linker.rb b/lib/gitlab/dependency_linker/podspec_json_linker.rb new file mode 100644 index 00000000000..d82237ed3f1 --- /dev/null +++ b/lib/gitlab/dependency_linker/podspec_json_linker.rb @@ -0,0 +1,32 @@ +module Gitlab + module DependencyLinker + class PodspecJsonLinker < JsonLinker + include Cocoapods + + self.file_type = :podspec_json + + private + + def link_dependencies + link_json('name', json["name"], &method(:package_url)) + link_json('license', &method(:license_url)) + link_json(%w[homepage git], URL_REGEX, &:itself) + + link_packages_at_key("dependencies", &method(:package_url)) + + json["subspecs"]&.each do |subspec| + link_packages_at_key("dependencies", subspec, &method(:package_url)) + end + end + + def link_packages_at_key(key, root = json, &url_proc) + dependencies = root[key] + return unless dependencies + + dependencies.each do |name, _| + link_regex(/"(?#{Regexp.escape(name)})":\s*\[/, &url_proc) + end + end + end + end +end -- cgit v1.2.3 From e780259a650ea476be0617c435798b85a252605a Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:29:56 -0500 Subject: Autolink package names in Cartfile --- lib/gitlab/dependency_linker.rb | 1 + lib/gitlab/dependency_linker/cartfile_linker.rb | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 lib/gitlab/dependency_linker/cartfile_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index ac16b9bde2f..2f68dfc00fb 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -8,6 +8,7 @@ module Gitlab PodfileLinker, PodspecLinker, PodspecJsonLinker, + CartfileLinker, ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/cartfile_linker.rb b/lib/gitlab/dependency_linker/cartfile_linker.rb new file mode 100644 index 00000000000..f65577588f8 --- /dev/null +++ b/lib/gitlab/dependency_linker/cartfile_linker.rb @@ -0,0 +1,20 @@ +module Gitlab + module DependencyLinker + class CartfileLinker < MethodLinker + self.file_type = :cartfile + + private + + def link_dependencies + link_method_call(%w[github git binary]) do |value| + case value + when %r{\A#{REPO_REGEX}\z} + github_url(value) + when /\A#{URL_REGEX}\z/ + value + end + end + end + end + end +end -- cgit v1.2.3 From 640440c9d8e1dea94067825e79734eb0f9774acf Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:30:18 -0500 Subject: Autolink package names in Godeps.json --- lib/gitlab/dependency_linker.rb | 1 + lib/gitlab/dependency_linker/godeps_json_linker.rb | 26 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 lib/gitlab/dependency_linker/godeps_json_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index 2f68dfc00fb..9ff355a9085 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -9,6 +9,7 @@ module Gitlab PodspecLinker, PodspecJsonLinker, CartfileLinker, + GodepsJsonLinker, ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/godeps_json_linker.rb b/lib/gitlab/dependency_linker/godeps_json_linker.rb new file mode 100644 index 00000000000..fe091baee6d --- /dev/null +++ b/lib/gitlab/dependency_linker/godeps_json_linker.rb @@ -0,0 +1,26 @@ +module Gitlab + module DependencyLinker + class GodepsJsonLinker < JsonLinker + NESTED_REPO_REGEX = %r{([^/]+/)+[^/]+?}.freeze + + self.file_type = :godeps_json + + private + + def link_dependencies + link_json('ImportPath') do |path| + case path + when %r{\A(?gitlab\.com/#{NESTED_REPO_REGEX})\.git/(?.+)\z}, + %r{\A(?git(lab|hub)\.com/#{REPO_REGEX})/(?.+)\z} + + "https://#{$~[:repo]}/tree/master/#{$~[:path]}" + when /\Agolang\.org/ + "https://godoc.org/#{path}" + else + "https://#{path}" + end + end + end + end + end +end -- cgit v1.2.3 From c734f2f0dd5ea5220b60a9dde9b3abef4f33fd93 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 16 May 2017 15:30:29 -0500 Subject: Autolink package names in requirements.txt --- lib/gitlab/dependency_linker.rb | 1 + lib/gitlab/dependency_linker/requirements_txt_linker.rb | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 lib/gitlab/dependency_linker/requirements_txt_linker.rb (limited to 'lib') diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb index 9ff355a9085..3192bf6f667 100644 --- a/lib/gitlab/dependency_linker.rb +++ b/lib/gitlab/dependency_linker.rb @@ -10,6 +10,7 @@ module Gitlab PodspecJsonLinker, CartfileLinker, GodepsJsonLinker, + RequirementsTxtLinker ].freeze def self.linker(blob_name) diff --git a/lib/gitlab/dependency_linker/requirements_txt_linker.rb b/lib/gitlab/dependency_linker/requirements_txt_linker.rb new file mode 100644 index 00000000000..2e197e5cd94 --- /dev/null +++ b/lib/gitlab/dependency_linker/requirements_txt_linker.rb @@ -0,0 +1,17 @@ +module Gitlab + module DependencyLinker + class RequirementsTxtLinker < BaseLinker + self.file_type = :requirements_txt + + private + + def link_dependencies + link_regex(/^(?(?![a-z+]+:)[^#.-][^ ><=;\[]+)/) do |name| + "https://pypi.python.org/pypi/#{name}" + end + + link_regex(%r{^(?https?://[^ ]+)}, &:itself) + end + end + end +end -- cgit v1.2.3 From d9a0188d2f7dfc07b426d36eeebc2c94385c12ca Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 15 May 2017 12:10:29 -0500 Subject: Add question mark to Gitlab::Diff::File predicate methods --- lib/api/entities.rb | 4 +++- lib/gitlab/diff/file.rb | 11 ++++------- lib/gitlab/git/diff.rb | 8 ++++++++ 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 01cc8e8e1ca..cf4affe1758 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -252,7 +252,9 @@ module API class RepoDiff < Grape::Entity expose :old_path, :new_path, :a_mode, :b_mode, :diff - expose :new_file, :renamed_file, :deleted_file + expose :new_file?, as: :new_file + expose :renamed_file?, as: :renamed_file + expose :deleted_file?, as: :deleted_file end class Milestone < ProjectEntity diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index c6bf25b5874..cb9fda36156 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -3,8 +3,8 @@ module Gitlab class File attr_reader :diff, :repository, :diff_refs - delegate :new_file, :deleted_file, :renamed_file, - :old_path, :new_path, :a_mode, :b_mode, + delegate :new_file?, :deleted_file?, :renamed_file?, + :old_path, :new_path, :a_mode, :b_mode, :mode_changed?, :submodule?, :too_large?, :collapsed?, to: :diff, prefix: false def initialize(diff, repository:, diff_refs: nil) @@ -85,10 +85,6 @@ module Gitlab @parallel_diff_lines ||= Gitlab::Diff::ParallelDiff.new(self).parallelize end - def mode_changed? - a_mode && b_mode && a_mode != b_mode - end - def raw_diff diff.diff.to_s end @@ -119,6 +115,7 @@ module Gitlab def old_blob(commit = old_content_commit) return unless commit + return if new_file? repository.blob_at(commit.id, old_path) end @@ -130,7 +127,7 @@ module Gitlab end def file_identifier - "#{file_path}-#{new_file}-#{deleted_file}-#{renamed_file}" + "#{file_path}-#{new_file?}-#{deleted_file?}-#{renamed_file?}" end end end diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index 31d1b66b4f7..deade337354 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -11,6 +11,10 @@ module Gitlab # Stats properties attr_accessor :new_file, :renamed_file, :deleted_file + alias_method :new_file?, :new_file + alias_method :deleted_file?, :deleted_file + alias_method :renamed_file?, :renamed_file + attr_accessor :too_large # The maximum size of a diff to display. @@ -208,6 +212,10 @@ module Gitlab hash end + def mode_changed? + a_mode && b_mode && a_mode != b_mode + end + def submodule? a_mode == '160000' || b_mode == '160000' end -- cgit v1.2.3 From db40c668de96e6dfcdb07792b881118867c2ff52 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 15 May 2017 12:10:51 -0500 Subject: Rename Diff::File {old,new}_ref to {old,new}_sha --- lib/gitlab/diff/file.rb | 8 ++++---- lib/gitlab/diff/highlight.rb | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index cb9fda36156..a812d549397 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -52,20 +52,20 @@ module Gitlab def content_commit return unless diff_refs - repository.commit(deleted_file ? old_ref : new_ref) + repository.commit(deleted_file? ? old_sha : new_sha) end def old_content_commit return unless diff_refs - repository.commit(old_ref) + repository.commit(old_sha) end - def old_ref + def old_sha diff_refs.try(:base_sha) end - def new_ref + def new_sha diff_refs.try(:head_sha) end diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index 7db896522a9..ed2f541977a 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -3,7 +3,7 @@ module Gitlab class Highlight attr_reader :diff_file, :diff_lines, :raw_lines, :repository - delegate :old_path, :new_path, :old_ref, :new_ref, to: :diff_file, prefix: :diff + delegate :old_path, :new_path, :old_sha, :new_sha, to: :diff_file, prefix: :diff def initialize(diff_lines, repository: nil) @repository = repository @@ -61,12 +61,12 @@ module Gitlab def old_lines return unless diff_file - @old_lines ||= Gitlab::Highlight.highlight_lines(self.repository, diff_old_ref, diff_old_path) + @old_lines ||= Gitlab::Highlight.highlight_lines(self.repository, diff_old_sha, diff_old_path) end def new_lines return unless diff_file - @new_lines ||= Gitlab::Highlight.highlight_lines(self.repository, diff_new_ref, diff_new_path) + @new_lines ||= Gitlab::Highlight.highlight_lines(self.repository, diff_new_sha, diff_new_path) end end end -- cgit v1.2.3 From 7e09a9b7dcef125af2e775869754a3327935b12d Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 15 May 2017 12:18:19 -0500 Subject: Clean up diff rendering --- lib/gitlab/git/diff_collection.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb index bcbad8ec829..bce3aef8bd3 100644 --- a/lib/gitlab/git/diff_collection.rb +++ b/lib/gitlab/git/diff_collection.rb @@ -64,6 +64,8 @@ module Gitlab collection end + alias_method :to_ary, :to_a + private def populate! -- cgit v1.2.3 From 7c479d88a92233790bc0fb63146fe004f8b9b5d7 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 15 May 2017 13:19:49 -0500 Subject: Pass fallback_diff_refs to Diff::File instead of using view helpers --- lib/gitlab/diff/file.rb | 70 +++++++++++++++------- lib/gitlab/diff/file_collection/base.rb | 15 ++--- .../diff/file_collection/merge_request_diff.rb | 3 +- 3 files changed, 57 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index a812d549397..2aef7fdaa35 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -1,16 +1,17 @@ module Gitlab module Diff class File - attr_reader :diff, :repository, :diff_refs + attr_reader :diff, :repository, :diff_refs, :fallback_diff_refs delegate :new_file?, :deleted_file?, :renamed_file?, :old_path, :new_path, :a_mode, :b_mode, :mode_changed?, :submodule?, :too_large?, :collapsed?, to: :diff, prefix: false - def initialize(diff, repository:, diff_refs: nil) + def initialize(diff, repository:, diff_refs: nil, fallback_diff_refs: nil) @diff = diff @repository = repository @diff_refs = diff_refs + @fallback_diff_refs = fallback_diff_refs end def position(line) @@ -49,24 +50,60 @@ module Gitlab line_code(line) if line end + def old_sha + diff_refs&.base_sha + end + + def new_sha + diff_refs&.head_sha + end + + def content_sha + return old_content_sha if deleted_file? + return @content_sha if defined?(@content_sha) + + refs = diff_refs || fallback_diff_refs + @content_sha = refs&.head_sha + end + def content_commit - return unless diff_refs + return @content_commit if defined?(@content_commit) + + sha = content_sha + @content_commit = repository.commit(sha) if sha + end + + def old_content_sha + return if new_file? + return @old_content_sha if defined?(@old_content_sha) - repository.commit(deleted_file? ? old_sha : new_sha) + refs = diff_refs || fallback_diff_refs + @old_content_sha = refs&.base_sha end def old_content_commit - return unless diff_refs + return @old_content_commit if defined?(@old_content_commit) - repository.commit(old_sha) + sha = old_content_sha + @old_content_commit = repository.commit(sha) if sha end - def old_sha - diff_refs.try(:base_sha) + def blob + return @blob if defined?(@blob) + + sha = content_sha + return @blob = nil unless sha + + repository.blob_at(sha, file_path) end - def new_sha - diff_refs.try(:head_sha) + def old_blob + return @old_blob if defined?(@old_blob) + + sha = old_content_sha + return @old_blob = nil unless sha + + @old_blob = repository.blob_at(sha, old_path) end attr_writer :highlighted_diff_lines @@ -113,19 +150,6 @@ module Gitlab diff_lines.count(&:removed?) end - def old_blob(commit = old_content_commit) - return unless commit - return if new_file? - - repository.blob_at(commit.id, old_path) - end - - def blob(commit = content_commit) - return unless commit - - repository.blob_at(commit.id, file_path) - end - def file_identifier "#{file_path}-#{new_file?}-#{deleted_file?}-#{renamed_file?}" end diff --git a/lib/gitlab/diff/file_collection/base.rb b/lib/gitlab/diff/file_collection/base.rb index 2b9fc65b985..7330f3377e1 100644 --- a/lib/gitlab/diff/file_collection/base.rb +++ b/lib/gitlab/diff/file_collection/base.rb @@ -2,7 +2,7 @@ module Gitlab module Diff module FileCollection class Base - attr_reader :project, :diff_options, :diff_view, :diff_refs + attr_reader :project, :diff_options, :diff_view, :diff_refs, :fallback_diff_refs delegate :count, :size, :real_size, to: :diff_files @@ -10,14 +10,15 @@ module Gitlab ::Commit.max_diff_options.merge(ignore_whitespace_change: false, no_collapse: false) end - def initialize(diffable, project:, diff_options: nil, diff_refs: nil) + def initialize(diffable, project:, diff_options: nil, diff_refs: nil, fallback_diff_refs: nil) diff_options = self.class.default_options.merge(diff_options || {}) - @diffable = diffable - @diffs = diffable.raw_diffs(diff_options) - @project = project + @diffable = diffable + @diffs = diffable.raw_diffs(diff_options) + @project = project @diff_options = diff_options - @diff_refs = diff_refs + @diff_refs = diff_refs + @fallback_diff_refs = fallback_diff_refs end def diff_files @@ -27,7 +28,7 @@ module Gitlab private def decorate_diff!(diff) - Gitlab::Diff::File.new(diff, repository: project.repository, diff_refs: diff_refs) + Gitlab::Diff::File.new(diff, repository: project.repository, diff_refs: diff_refs, fallback_diff_refs: fallback_diff_refs) end end end diff --git a/lib/gitlab/diff/file_collection/merge_request_diff.rb b/lib/gitlab/diff/file_collection/merge_request_diff.rb index 0bd226ef050..9a58b500a2c 100644 --- a/lib/gitlab/diff/file_collection/merge_request_diff.rb +++ b/lib/gitlab/diff/file_collection/merge_request_diff.rb @@ -8,7 +8,8 @@ module Gitlab super(merge_request_diff, project: merge_request_diff.project, diff_options: diff_options, - diff_refs: merge_request_diff.diff_refs) + diff_refs: merge_request_diff.diff_refs, + fallback_diff_refs: merge_request_diff.fallback_diff_refs) end def diff_files -- cgit v1.2.3 From ab91f76e8b275d0fc1d78b38b95d4b2cd8e73bdb Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Sun, 21 May 2017 15:38:33 -0500 Subject: Add system note with link to diff comparison when MR discussion becomes outdated --- lib/gitlab/diff/file_collection/base.rb | 8 ++ lib/gitlab/diff/position.rb | 30 +++-- lib/gitlab/diff/position_tracer.rb | 215 ++++++++++++++++++++------------ 3 files changed, 161 insertions(+), 92 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/diff/file_collection/base.rb b/lib/gitlab/diff/file_collection/base.rb index 2b9fc65b985..7c32adc6ce7 100644 --- a/lib/gitlab/diff/file_collection/base.rb +++ b/lib/gitlab/diff/file_collection/base.rb @@ -24,6 +24,14 @@ module Gitlab @diff_files ||= @diffs.decorate! { |diff| decorate_diff!(diff) } end + def diff_file_with_old_path(old_path) + diff_files.find { |diff_file| diff_file.old_path == old_path } + end + + def diff_file_with_new_path(new_path) + diff_files.find { |diff_file| diff_file.new_path == new_path } + end + private def decorate_diff!(diff) diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb index fc728123c97..4d96778a2b2 100644 --- a/lib/gitlab/diff/position.rb +++ b/lib/gitlab/diff/position.rb @@ -12,20 +12,26 @@ module Gitlab attr_reader :head_sha def initialize(attrs = {}) + if diff_file = attrs[:diff_file] + attrs[:diff_refs] = diff_file.diff_refs + attrs[:old_path] = diff_file.old_path + attrs[:new_path] = diff_file.new_path + end + + if diff_refs = attrs[:diff_refs] + attrs[:base_sha] = diff_refs.base_sha + attrs[:start_sha] = diff_refs.start_sha + attrs[:head_sha] = diff_refs.head_sha + end + @old_path = attrs[:old_path] @new_path = attrs[:new_path] + @base_sha = attrs[:base_sha] + @start_sha = attrs[:start_sha] + @head_sha = attrs[:head_sha] + @old_line = attrs[:old_line] @new_line = attrs[:new_line] - - if attrs[:diff_refs] - @base_sha = attrs[:diff_refs].base_sha - @start_sha = attrs[:diff_refs].start_sha - @head_sha = attrs[:diff_refs].head_sha - else - @base_sha = attrs[:base_sha] - @start_sha = attrs[:start_sha] - @head_sha = attrs[:head_sha] - end end # `Gitlab::Diff::Position` objects are stored as serialized attributes in @@ -129,11 +135,11 @@ module Gitlab end def diff_line(repository) - @diff_line ||= diff_file(repository).line_for_position(self) + @diff_line ||= diff_file(repository)&.line_for_position(self) end def line_code(repository) - @line_code ||= diff_file(repository).line_code_for_position(self) + @line_code ||= diff_file(repository)&.line_code_for_position(self) end private diff --git a/lib/gitlab/diff/position_tracer.rb b/lib/gitlab/diff/position_tracer.rb index e89ff238ec7..3705361a185 100644 --- a/lib/gitlab/diff/position_tracer.rb +++ b/lib/gitlab/diff/position_tracer.rb @@ -3,21 +3,21 @@ module Gitlab module Diff class PositionTracer - attr_accessor :repository + attr_accessor :project attr_accessor :old_diff_refs attr_accessor :new_diff_refs attr_accessor :paths - def initialize(repository:, old_diff_refs:, new_diff_refs:, paths: nil) - @repository = repository + def initialize(project:, old_diff_refs:, new_diff_refs:, paths: nil) + @project = project @old_diff_refs = old_diff_refs @new_diff_refs = new_diff_refs @paths = paths end - def trace(old_position) + def trace(ab_position) return unless old_diff_refs&.complete? && new_diff_refs&.complete? - return unless old_position.diff_refs == old_diff_refs + return unless ab_position.diff_refs == old_diff_refs # Suppose we have an MR with source branch `feature` and target branch `master`. # When the MR was created, the head of `master` was commit A, and the @@ -44,14 +44,14 @@ module Gitlab # # For diff notes for diff A->B, the position looks like this: # Position - # base_sha - ID of commit A + # start_sha - ID of commit A # head_sha - ID of commit B # old_path - path as of A (nil if file was newly created) # new_path - path as of B (nil if file was deleted) # old_line - line number as of A (nil if file was newly created) # new_line - line number as of B (nil if file was deleted) # - # We can easily update `base_sha` and `head_sha` to hold the IDs of commits C and D, + # We can easily update `start_sha` and `head_sha` to hold the IDs of commits C and D, # but need to find the paths and line numbers as of C and D. # # If the file was unchanged or newly created in A->B, the path as of D can be found @@ -68,107 +68,162 @@ module Gitlab # by generating diff A->C ("base to base"), finding the diff file with # `diff_file.old_path == position.old_path`, and taking `diff_file.new_path`. # The path as of D can be found by taking diff C->D, finding the diff file - # with that same `old_path` and taking `diff_file.new_path`. + # with `old_path` set to that `diff_file.new_path` and taking `diff_file.new_path`. # The line number as of C can be found by using the LineMapper on diff A->C # and providing the line number as of A. # The line number as of D can be found by using the LineMapper on diff C->D # and providing the line number as of C. - results = nil - results ||= trace_added_line(old_position) if old_position.added? || old_position.unchanged? - results ||= trace_removed_line(old_position) if old_position.removed? || old_position.unchanged? - - return unless results - - file_diff, old_line, new_line = results - - new_position = Position.new( - old_path: file_diff.old_path, - new_path: file_diff.new_path, - head_sha: new_diff_refs.head_sha, - start_sha: new_diff_refs.start_sha, - base_sha: new_diff_refs.base_sha, - old_line: old_line, - new_line: new_line - ) - - # If a position is found, but is not actually contained in the diff, for example - # because it was an unchanged line in the context of a change that was undone, - # we cannot return this as a successful trace. - return unless new_position.diff_line(repository) - - new_position + if ab_position.added? + trace_added_line(ab_position) + elsif ab_position.removed? + trace_removed_line(ab_position) + else # unchanged + trace_unchanged_line(ab_position) + end end private - def trace_added_line(old_position) - file_path = old_position.new_path - - return unless diff_head_to_head - - file_head_to_head = diff_head_to_head.find { |diff_file| diff_file.old_path == file_path } - - file_path = file_head_to_head.new_path if file_head_to_head - - new_line = LineMapper.new(file_head_to_head).old_to_new(old_position.new_line) - - return unless new_line - - file_diff = new_diffs.find { |diff_file| diff_file.new_path == file_path } - return unless file_diff - - old_line = LineMapper.new(file_diff).new_to_old(new_line) - - [file_diff, old_line, new_line] + def trace_added_line(ab_position) + b_path = ab_position.new_path + b_line = ab_position.new_line + + bd_diff = bd_diffs.diff_file_with_old_path(b_path) + + d_path = bd_diff&.new_path || b_path + d_line = LineMapper.new(bd_diff).old_to_new(b_line) + + if d_line + cd_diff = cd_diffs.diff_file_with_new_path(d_path) + + c_path = cd_diff&.old_path || d_path + c_line = LineMapper.new(cd_diff).new_to_old(d_line) + + if c_line + # If the line is still in D but also in C, it has turned from an + # added line into an unchanged one. + new_position = position(cd_diff, c_line, d_line) + if valid_position?(new_position) + # If the line is still in the MR, we don't treat this as outdated. + { position: new_position, outdated: false } + else + # If the line is no longer in the MR, we unfortunately cannot show + # the current state on the CD diff, so we treat it as outdated. + ac_diff = ac_diffs.diff_file_with_new_path(c_path) + + { position: position(ac_diff, nil, c_line), outdated: true } + end + else + # If the line is still in D and not in C, it is still added. + { position: position(cd_diff, nil, d_line), outdated: false } + end + else + # If the line is no longer in D, it has been removed from the MR. + { position: position(bd_diff, b_line, nil), outdated: true } + end end - def trace_removed_line(old_position) - file_path = old_position.old_path + def trace_removed_line(ab_position) + a_path = ab_position.old_path + a_line = ab_position.old_line - return unless diff_base_to_base + ac_diff = ac_diffs.diff_file_with_old_path(a_path) - file_base_to_base = diff_base_to_base.find { |diff_file| diff_file.old_path == file_path } + c_path = ac_diff&.new_path || a_path + c_line = LineMapper.new(ac_diff).old_to_new(a_line) - file_path = file_base_to_base.old_path if file_base_to_base + if c_line + cd_diff = cd_diffs.diff_file_with_old_path(c_path) - old_line = LineMapper.new(file_base_to_base).old_to_new(old_position.old_line) + d_path = cd_diff&.new_path || c_path + d_line = LineMapper.new(cd_diff).old_to_new(c_line) - return unless old_line + if d_line + # If the line is still in C but also in D, it has turned from a + # removed line into an unchanged one. + bd_diff = bd_diffs.diff_file_with_new_path(d_path) - file_diff = new_diffs.find { |diff_file| diff_file.old_path == file_path } - return unless file_diff - - new_line = LineMapper.new(file_diff).old_to_new(old_line) + { position: position(bd_diff, nil, d_line), outdated: true } + else + # If the line is still in C and not in D, it is still removed. + { position: position(cd_diff, c_line, nil), outdated: false } + end + else + # If the line is no longer in C, it has been removed outside of the MR. + { position: position(ac_diff, a_line, nil), outdated: true } + end + end - [file_diff, old_line, new_line] + def trace_unchanged_line(ab_position) + a_path = ab_position.old_path + a_line = ab_position.old_line + b_path = ab_position.new_path + b_line = ab_position.new_line + + ac_diff = ac_diffs.diff_file_with_old_path(a_path) + + c_path = ac_diff&.new_path || a_path + c_line = LineMapper.new(ac_diff).old_to_new(a_line) + + bd_diff = bd_diffs.diff_file_with_old_path(b_path) + + d_path = bd_diff&.new_path || b_path + d_line = LineMapper.new(bd_diff).old_to_new(b_line) + + cd_diff = cd_diffs.diff_file_with_old_path(c_path) + + if c_line && d_line + # If the line is still in C and D, it is still unchanged. + new_position = position(cd_diff, c_line, d_line) + if valid_position?(new_position) + # If the line is still in the MR, we don't treat this as outdated. + { position: new_position, outdated: false } + else + # If the line is no longer in the MR, we unfortunately cannot show + # the current state on the CD diff or any change on the BD diff, + # so we treat it as outdated. + { position: nil, outdated: true } + end + elsif d_line # && !c_line + # If the line is still in D but no longer in C, it has turned from + # an unchanged line into an added one. + # We don't treat this as outdated since the line is still in the MR. + { position: position(cd_diff, nil, d_line), outdated: false } + else # !d_line && (c_line || !c_line) + # If the line is no longer in D, it has turned from an unchanged line + # into a removed one. + { position: position(bd_diff, b_line, nil), outdated: true } + end end - def diff_base_to_base - @diff_base_to_base ||= diff_files(old_diff_refs.base_sha || old_diff_refs.start_sha, new_diff_refs.base_sha || new_diff_refs.start_sha) + def ac_diffs + @ac_diffs ||= compare( + old_diff_refs.base_sha || old_diff_refs.start_sha, + new_diff_refs.base_sha || new_diff_refs.start_sha, + straight: true + ) end - def diff_head_to_head - @diff_head_to_head ||= diff_files(old_diff_refs.head_sha, new_diff_refs.head_sha) + def bd_diffs + @bd_diffs ||= compare(old_diff_refs.head_sha, new_diff_refs.head_sha, straight: true) end - def new_diffs - @new_diffs ||= diff_files(new_diff_refs.start_sha, new_diff_refs.head_sha, use_base: true) + def cd_diffs + @cd_diffs ||= compare(new_diff_refs.start_sha, new_diff_refs.head_sha) end - def diff_files(start_sha, head_sha, use_base: false) - base_sha = self.repository.merge_base(start_sha, head_sha) || start_sha + def compare(start_sha, head_sha, straight: false) + compare = CompareService.new(project, head_sha).execute(project, start_sha, straight: straight) + compare.diffs(paths: paths) + end - diffs = self.repository.raw_repository.diff( - use_base ? base_sha : start_sha, - head_sha, - {}, - *paths - ) + def position(diff_file, old_line, new_line) + Position.new(diff_file: diff_file, old_line: old_line, new_line: new_line) + end - diffs.decorate! do |diff| - Gitlab::Diff::File.new(diff, repository: self.repository) - end + def valid_position?(position) + !!position.diff_line(project.repository) end end end -- cgit v1.2.3 From 6e698b254ecddf23a866d9e98a885912102ccbce Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 22 May 2017 15:56:20 -0500 Subject: Fix specs --- lib/gitlab/diff/position_tracer.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/diff/position_tracer.rb b/lib/gitlab/diff/position_tracer.rb index 3705361a185..46f8f7e8238 100644 --- a/lib/gitlab/diff/position_tracer.rb +++ b/lib/gitlab/diff/position_tracer.rb @@ -168,7 +168,6 @@ module Gitlab bd_diff = bd_diffs.diff_file_with_old_path(b_path) - d_path = bd_diff&.new_path || b_path d_line = LineMapper.new(bd_diff).old_to_new(b_line) cd_diff = cd_diffs.diff_file_with_old_path(c_path) -- cgit v1.2.3 From 4345bb8c507a11af694617187dea14284f48fb96 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 19 May 2017 19:46:40 -0500 Subject: Fix ambiguous routing issues by teaching router about reserved words --- lib/api/repositories.rb | 2 +- lib/api/v3/repositories.rb | 2 +- lib/constraints/group_url_constrainer.rb | 6 +- lib/constraints/project_url_constrainer.rb | 4 +- lib/constraints/user_url_constrainer.rb | 6 +- lib/gitlab/etag_caching/router.rb | 2 +- lib/gitlab/path_regex.rb | 264 +++++++++++++++++++++++++++++ lib/gitlab/regex.rb | 80 +-------- 8 files changed, 278 insertions(+), 88 deletions(-) create mode 100644 lib/gitlab/path_regex.rb (limited to 'lib') diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 8f16e532ecb..14d2bff9cb5 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -85,7 +85,7 @@ module API optional :sha, type: String, desc: 'The commit sha of the archive to be downloaded' optional :format, type: String, desc: 'The archive format' end - get ':id/repository/archive', requirements: { format: Gitlab::Regex.archive_formats_regex } do + get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do begin send_git_archive user_project.repository, ref: params[:sha], format: params[:format] rescue diff --git a/lib/api/v3/repositories.rb b/lib/api/v3/repositories.rb index e4d14bc8168..0eaa0de2eef 100644 --- a/lib/api/v3/repositories.rb +++ b/lib/api/v3/repositories.rb @@ -72,7 +72,7 @@ module API optional :sha, type: String, desc: 'The commit sha of the archive to be downloaded' optional :format, type: String, desc: 'The archive format' end - get ':id/repository/archive', requirements: { format: Gitlab::Regex.archive_formats_regex } do + get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do begin send_git_archive user_project.repository, ref: params[:sha], format: params[:format] rescue diff --git a/lib/constraints/group_url_constrainer.rb b/lib/constraints/group_url_constrainer.rb index 5f379756c11..6fc1d56d7a0 100644 --- a/lib/constraints/group_url_constrainer.rb +++ b/lib/constraints/group_url_constrainer.rb @@ -1,9 +1,9 @@ class GroupUrlConstrainer def matches?(request) - id = request.params[:id] + full_path = request.params[:group_id] || request.params[:id] - return false unless DynamicPathValidator.valid?(id) + return false unless DynamicPathValidator.valid_group_path?(full_path) - Group.find_by_full_path(id, follow_redirects: request.get?).present? + Group.find_by_full_path(full_path, follow_redirects: request.get?).present? end end diff --git a/lib/constraints/project_url_constrainer.rb b/lib/constraints/project_url_constrainer.rb index 6f542f63f98..4c0aee6c48f 100644 --- a/lib/constraints/project_url_constrainer.rb +++ b/lib/constraints/project_url_constrainer.rb @@ -2,9 +2,9 @@ class ProjectUrlConstrainer def matches?(request) namespace_path = request.params[:namespace_id] project_path = request.params[:project_id] || request.params[:id] - full_path = namespace_path + '/' + project_path + full_path = [namespace_path, project_path].join('/') - return false unless DynamicPathValidator.valid?(full_path) + return false unless DynamicPathValidator.valid_project_path?(full_path) Project.find_by_full_path(full_path, follow_redirects: request.get?).present? end diff --git a/lib/constraints/user_url_constrainer.rb b/lib/constraints/user_url_constrainer.rb index 28159dc0dec..d16ae7f3f40 100644 --- a/lib/constraints/user_url_constrainer.rb +++ b/lib/constraints/user_url_constrainer.rb @@ -1,5 +1,9 @@ class UserUrlConstrainer def matches?(request) - User.find_by_full_path(request.params[:username], follow_redirects: request.get?).present? + full_path = request.params[:username] + + return false unless DynamicPathValidator.valid_user_path?(full_path) + + User.find_by_full_path(full_path, follow_redirects: request.get?).present? end end diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index ba31041d0c1..7d03209684a 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -10,7 +10,7 @@ module Gitlab # - Ending in `issues/id`/realtime_changes` for the `issue_title` route USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes commit pipelines merge_requests new].freeze - RESERVED_WORDS = DynamicPathValidator::WILDCARD_ROUTES - USED_IN_ROUTES + RESERVED_WORDS = Gitlab::PathRegex::ILLEGAL_PROJECT_PATH_WORDS - USED_IN_ROUTES RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS) ROUTES = [ Gitlab::EtagCaching::Router::Route.new( diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb new file mode 100644 index 00000000000..1ee0f2b3998 --- /dev/null +++ b/lib/gitlab/path_regex.rb @@ -0,0 +1,264 @@ +module Gitlab + module PathRegex + extend self + + # All routes that appear on the top level must be listed here. + # This will make sure that groups cannot be created with these names + # as these routes would be masked by the paths already in place. + # + # Example: + # /api/api-project + # + # the path `api` shouldn't be allowed because it would be masked by `api/*` + # + TOP_LEVEL_ROUTES = %w[ + - + .well-known + abuse_reports + admin + all + api + assets + autocomplete + ci + dashboard + explore + files + groups + health_check + help + hooks + import + invites + issues + jwt + koding + member + merge_requests + new + notes + notification_settings + oauth + profile + projects + public + repository + robots.txt + s + search + sent_notifications + services + snippets + teams + u + unicorn_test + unsubscribes + uploads + users + ].freeze + + # This list should contain all words following `/*namespace_id/:project_id` in + # routes that contain a second wildcard. + # + # Example: + # /*namespace_id/:project_id/badges/*ref/build + # + # If `badges` was allowed as a project/group name, we would not be able to access the + # `badges` route for those projects: + # + # Consider a namespace with path `foo/bar` and a project called `badges`. + # The route to the build badge would then be `/foo/bar/badges/badges/master/build.svg` + # + # When accessing this path the route would be matched to the `badges` path + # with the following params: + # - namespace_id: `foo` + # - project_id: `bar` + # - ref: `badges/master` + # + # Failing to find the project, this would result in a 404. + # + # By rejecting `badges` the router can _count_ on the fact that `badges` will + # be preceded by the `namespace/project`. + PROJECT_WILDCARD_ROUTES = %w[ + badges + blame + blob + builds + commits + create + create_dir + edit + environments/folders + files + find_file + gitlab-lfs/objects + info/lfs/objects + new + preview + raw + refs + tree + update + wikis + ].freeze + + # These are all the paths that follow `/groups/*id/ or `/groups/*group_id` + # We need to reject these because we have a `/groups/*id` page that is the same + # as the `/*id`. + # + # If we would allow a subgroup to be created with the name `activity` then + # this group would not be accessible through `/groups/parent/activity` since + # this would map to the activity-page of its parent. + GROUP_ROUTES = %w[ + activity + analytics + audit_events + avatar + edit + group_members + hooks + issues + labels + ldap + ldap_group_links + merge_requests + milestones + notification_setting + pipeline_quota + projects + subgroups + ].freeze + + ILLEGAL_PROJECT_PATH_WORDS = PROJECT_WILDCARD_ROUTES + ILLEGAL_GROUP_PATH_WORDS = (PROJECT_WILDCARD_ROUTES | GROUP_ROUTES).freeze + + # The namespace regex is used in JavaScript to validate usernames in the "Register" form. However, Javascript + # does not support the negative lookbehind assertion (? Date: Mon, 22 May 2017 20:08:33 -0500 Subject: Remove changes that are not absolutely necessary --- lib/api/repositories.rb | 2 +- lib/api/v3/repositories.rb | 2 +- lib/constraints/group_url_constrainer.rb | 6 +- lib/constraints/project_url_constrainer.rb | 2 +- lib/constraints/user_url_constrainer.rb | 6 +- lib/gitlab/etag_caching/router.rb | 2 +- lib/gitlab/path_regex.rb | 264 ----------------------------- lib/gitlab/regex.rb | 263 +++++++++++++++++++++++++++- 8 files changed, 270 insertions(+), 277 deletions(-) delete mode 100644 lib/gitlab/path_regex.rb (limited to 'lib') diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 14d2bff9cb5..8f16e532ecb 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -85,7 +85,7 @@ module API optional :sha, type: String, desc: 'The commit sha of the archive to be downloaded' optional :format, type: String, desc: 'The archive format' end - get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do + get ':id/repository/archive', requirements: { format: Gitlab::Regex.archive_formats_regex } do begin send_git_archive user_project.repository, ref: params[:sha], format: params[:format] rescue diff --git a/lib/api/v3/repositories.rb b/lib/api/v3/repositories.rb index 0eaa0de2eef..e4d14bc8168 100644 --- a/lib/api/v3/repositories.rb +++ b/lib/api/v3/repositories.rb @@ -72,7 +72,7 @@ module API optional :sha, type: String, desc: 'The commit sha of the archive to be downloaded' optional :format, type: String, desc: 'The archive format' end - get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do + get ':id/repository/archive', requirements: { format: Gitlab::Regex.archive_formats_regex } do begin send_git_archive user_project.repository, ref: params[:sha], format: params[:format] rescue diff --git a/lib/constraints/group_url_constrainer.rb b/lib/constraints/group_url_constrainer.rb index 6fc1d56d7a0..0ea2f97352d 100644 --- a/lib/constraints/group_url_constrainer.rb +++ b/lib/constraints/group_url_constrainer.rb @@ -1,9 +1,9 @@ class GroupUrlConstrainer def matches?(request) - full_path = request.params[:group_id] || request.params[:id] + id = request.params[:group_id] || request.params[:id] - return false unless DynamicPathValidator.valid_group_path?(full_path) + return false unless DynamicPathValidator.valid_namespace_path?(id) - Group.find_by_full_path(full_path, follow_redirects: request.get?).present? + Group.find_by_full_path(id, follow_redirects: request.get?).present? end end diff --git a/lib/constraints/project_url_constrainer.rb b/lib/constraints/project_url_constrainer.rb index 4c0aee6c48f..4444a1abee3 100644 --- a/lib/constraints/project_url_constrainer.rb +++ b/lib/constraints/project_url_constrainer.rb @@ -2,7 +2,7 @@ class ProjectUrlConstrainer def matches?(request) namespace_path = request.params[:namespace_id] project_path = request.params[:project_id] || request.params[:id] - full_path = [namespace_path, project_path].join('/') + full_path = namespace_path + '/' + project_path return false unless DynamicPathValidator.valid_project_path?(full_path) diff --git a/lib/constraints/user_url_constrainer.rb b/lib/constraints/user_url_constrainer.rb index d16ae7f3f40..28159dc0dec 100644 --- a/lib/constraints/user_url_constrainer.rb +++ b/lib/constraints/user_url_constrainer.rb @@ -1,9 +1,5 @@ class UserUrlConstrainer def matches?(request) - full_path = request.params[:username] - - return false unless DynamicPathValidator.valid_user_path?(full_path) - - User.find_by_full_path(full_path, follow_redirects: request.get?).present? + User.find_by_full_path(request.params[:username], follow_redirects: request.get?).present? end end diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index 7d03209684a..8ed23e79b3b 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -10,7 +10,7 @@ module Gitlab # - Ending in `issues/id`/realtime_changes` for the `issue_title` route USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes commit pipelines merge_requests new].freeze - RESERVED_WORDS = Gitlab::PathRegex::ILLEGAL_PROJECT_PATH_WORDS - USED_IN_ROUTES + RESERVED_WORDS = Gitlab::Regex::ILLEGAL_PROJECT_PATH_WORDS - USED_IN_ROUTES RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS) ROUTES = [ Gitlab::EtagCaching::Router::Route.new( diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb deleted file mode 100644 index 1ee0f2b3998..00000000000 --- a/lib/gitlab/path_regex.rb +++ /dev/null @@ -1,264 +0,0 @@ -module Gitlab - module PathRegex - extend self - - # All routes that appear on the top level must be listed here. - # This will make sure that groups cannot be created with these names - # as these routes would be masked by the paths already in place. - # - # Example: - # /api/api-project - # - # the path `api` shouldn't be allowed because it would be masked by `api/*` - # - TOP_LEVEL_ROUTES = %w[ - - - .well-known - abuse_reports - admin - all - api - assets - autocomplete - ci - dashboard - explore - files - groups - health_check - help - hooks - import - invites - issues - jwt - koding - member - merge_requests - new - notes - notification_settings - oauth - profile - projects - public - repository - robots.txt - s - search - sent_notifications - services - snippets - teams - u - unicorn_test - unsubscribes - uploads - users - ].freeze - - # This list should contain all words following `/*namespace_id/:project_id` in - # routes that contain a second wildcard. - # - # Example: - # /*namespace_id/:project_id/badges/*ref/build - # - # If `badges` was allowed as a project/group name, we would not be able to access the - # `badges` route for those projects: - # - # Consider a namespace with path `foo/bar` and a project called `badges`. - # The route to the build badge would then be `/foo/bar/badges/badges/master/build.svg` - # - # When accessing this path the route would be matched to the `badges` path - # with the following params: - # - namespace_id: `foo` - # - project_id: `bar` - # - ref: `badges/master` - # - # Failing to find the project, this would result in a 404. - # - # By rejecting `badges` the router can _count_ on the fact that `badges` will - # be preceded by the `namespace/project`. - PROJECT_WILDCARD_ROUTES = %w[ - badges - blame - blob - builds - commits - create - create_dir - edit - environments/folders - files - find_file - gitlab-lfs/objects - info/lfs/objects - new - preview - raw - refs - tree - update - wikis - ].freeze - - # These are all the paths that follow `/groups/*id/ or `/groups/*group_id` - # We need to reject these because we have a `/groups/*id` page that is the same - # as the `/*id`. - # - # If we would allow a subgroup to be created with the name `activity` then - # this group would not be accessible through `/groups/parent/activity` since - # this would map to the activity-page of its parent. - GROUP_ROUTES = %w[ - activity - analytics - audit_events - avatar - edit - group_members - hooks - issues - labels - ldap - ldap_group_links - merge_requests - milestones - notification_setting - pipeline_quota - projects - subgroups - ].freeze - - ILLEGAL_PROJECT_PATH_WORDS = PROJECT_WILDCARD_ROUTES - ILLEGAL_GROUP_PATH_WORDS = (PROJECT_WILDCARD_ROUTES | GROUP_ROUTES).freeze - - # The namespace regex is used in JavaScript to validate usernames in the "Register" form. However, Javascript - # does not support the negative lookbehind assertion (? Date: Tue, 23 May 2017 23:42:26 +0800 Subject: Add checks before redirect, remove status/trace compatible urls, which were for javascripts --- lib/gitlab/routes/legacy_builds.rb | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/routes/legacy_builds.rb b/lib/gitlab/routes/legacy_builds.rb index cbb8b960c7e..1b6f6df26a2 100644 --- a/lib/gitlab/routes/legacy_builds.rb +++ b/lib/gitlab/routes/legacy_builds.rb @@ -22,8 +22,6 @@ module Gitlab end member do - get :status - get :trace, defaults: { format: 'json' } get :raw end -- cgit v1.2.3 From ec525efddba67d840cc409aa4b9a8857dac7453f Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 23 May 2017 23:43:48 +0800 Subject: Routing helpers are no longer needed --- lib/gitlab/routes/legacy_builds.rb | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/routes/legacy_builds.rb b/lib/gitlab/routes/legacy_builds.rb index 1b6f6df26a2..36d1a8a6f64 100644 --- a/lib/gitlab/routes/legacy_builds.rb +++ b/lib/gitlab/routes/legacy_builds.rb @@ -1,9 +1,6 @@ module Gitlab module Routes class LegacyBuilds - include Gitlab::Routing.url_helpers - include GitlabRoutingHelper - def initialize(map) @map = map end -- cgit v1.2.3 From 6018afa89fc34b0ea9ba691e3690a9837fadc122 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 6 May 2017 03:16:39 +0900 Subject: Add reverse_line --- lib/gitlab/ci/trace/stream.rb | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index fa462cbe095..be8e40af016 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -73,7 +73,7 @@ module Gitlab match = "" - stream.each_line do |line| + reverse_line do |line| matches = line.scan(regex) next unless matches.is_a?(Array) next if matches.empty? @@ -115,6 +115,26 @@ module Gitlab chunks.join.lines.last(last_lines).join end + + def reverse_line + pos = 0 + max = stream.size + + while true + pos += BUFFER_SIZE + + buf = + if pos <= max + stream.seek(-pos, IO::SEEK_END) + stream.read(BUFFER_SIZE) + else # Reached the head, read only left + stream.seek(0) + stream.read(BUFFER_SIZE - (pos - max)) + end + + yield(buf) + end + end end end end -- cgit v1.2.3 From ddf67424ec5d84ff373e5e39195b5012c84eb920 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 6 May 2017 17:38:56 +0900 Subject: Fix while true --- lib/gitlab/ci/trace/stream.rb | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index be8e40af016..72a0d669de0 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -117,23 +117,18 @@ module Gitlab end def reverse_line - pos = 0 + pos = BUFFER_SIZE max = stream.size - while true + while pos < max + stream.seek(-pos, IO::SEEK_END) + yield(stream.read(BUFFER_SIZE)) pos += BUFFER_SIZE - - buf = - if pos <= max - stream.seek(-pos, IO::SEEK_END) - stream.read(BUFFER_SIZE) - else # Reached the head, read only left - stream.seek(0) - stream.read(BUFFER_SIZE - (pos - max)) - end - - yield(buf) end + + # Reached the head, read only left + stream.seek(0) + yield(stream.read(BUFFER_SIZE - (pos - max))) end end end -- cgit v1.2.3 From 3d11b7d8e25ca39b347e61e12100c7745b6ea085 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 10 May 2017 02:40:34 +0900 Subject: Fix reverse_line from chunk based --- lib/gitlab/ci/trace/stream.rb | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 72a0d669de0..546f6788a78 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -119,16 +119,31 @@ module Gitlab def reverse_line pos = BUFFER_SIZE max = stream.size + debris = '' while pos < max stream.seek(-pos, IO::SEEK_END) - yield(stream.read(BUFFER_SIZE)) + stream.read(BUFFER_SIZE).tap do |buf| + buf = buf + debris + lines = buf.split("\n") + lines.reverse.each do |line| + yield(line) + end + debris = lines.count > 0 ? lines[0] : '' + end pos += BUFFER_SIZE end # Reached the head, read only left stream.seek(0) - yield(stream.read(BUFFER_SIZE - (pos - max))) + last = (max > BUFFER_SIZE) ? (max % BUFFER_SIZE) : max + stream.read(last).tap do |buf| + buf = buf + debris + lines = buf.split("\n") + lines.reverse.each do |line| + yield(line) + end + end end end end -- cgit v1.2.3 From b9950c22b38456537af92c77210f1b837bdc914c Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Tue, 16 May 2017 22:35:18 +0900 Subject: Use each_line. Avoid comparison of partial. Add UTF-8 spec. --- lib/gitlab/ci/trace/stream.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 546f6788a78..56d6855c3c6 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -125,11 +125,10 @@ module Gitlab stream.seek(-pos, IO::SEEK_END) stream.read(BUFFER_SIZE).tap do |buf| buf = buf + debris - lines = buf.split("\n") - lines.reverse.each do |line| + debris, *lines = buf.each_line.to_a + lines.reverse_each do |line| yield(line) end - debris = lines.count > 0 ? lines[0] : '' end pos += BUFFER_SIZE end @@ -139,8 +138,7 @@ module Gitlab last = (max > BUFFER_SIZE) ? (max % BUFFER_SIZE) : max stream.read(last).tap do |buf| buf = buf + debris - lines = buf.split("\n") - lines.reverse.each do |line| + buf.each_line.reverse_each do |line| yield(line) end end -- cgit v1.2.3 From a6f6056c62693f18d9a2da570578b2e19aa20afe Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 15:05:18 +0900 Subject: Use force_encoding when regex contains UTF-8 char --- lib/gitlab/ci/trace/stream.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 56d6855c3c6..233cc5c1c7a 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -74,7 +74,7 @@ module Gitlab match = "" reverse_line do |line| - matches = line.scan(regex) + matches = line.force_encoding(Encoding.default_external).scan(regex) next unless matches.is_a?(Array) next if matches.empty? -- cgit v1.2.3 From 318b46407239f35cd11d35b21271fa743d435dad Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 17:53:31 +0900 Subject: Use force_encoding(regex.encoding) --- lib/gitlab/ci/trace/stream.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 233cc5c1c7a..3b4728951c4 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -74,7 +74,7 @@ module Gitlab match = "" reverse_line do |line| - matches = line.force_encoding(Encoding.default_external).scan(regex) + matches = line.force_encoding(regex.encoding).scan(regex) next unless matches.is_a?(Array) next if matches.empty? @@ -86,7 +86,7 @@ module Gitlab nil rescue # if bad regex or something goes wrong we dont want to interrupt transition - # so we just silentrly ignore error for now + # so we just silently ignore error for now end private -- cgit v1.2.3 From dddfa28eec6a55f8548e848d41b4fa3749a7d4d7 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 18:18:16 +0900 Subject: Refer reverse_line from read_last_lines --- lib/gitlab/ci/trace/stream.rb | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 3b4728951c4..3d32fae6525 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -91,29 +91,14 @@ module Gitlab private - def read_last_lines(last_lines) - chunks = [] - pos = lines = 0 - max = stream.size - - # We want an extra line to make sure fist line has full contents - while lines <= last_lines && pos < max - pos += BUFFER_SIZE - - buf = - if pos <= max - stream.seek(-pos, IO::SEEK_END) - stream.read(BUFFER_SIZE) - else # Reached the head, read only left - stream.seek(0) - stream.read(BUFFER_SIZE - (pos - max)) - end - - lines += buf.count("\n") - chunks.unshift(buf) + def read_last_lines(limit) + result = '' + reverse_line do |line| + result = line + result + limit -= 1 + return result if limit <= 0 end - - chunks.join.lines.last(last_lines).join + result end def reverse_line -- cgit v1.2.3 From 6be609dd6418f1688d027f21cfe6fdb167375bc0 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 18:26:38 +0900 Subject: much better --- lib/gitlab/ci/trace/stream.rb | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 3d32fae6525..5777332b251 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -92,13 +92,7 @@ module Gitlab private def read_last_lines(limit) - result = '' - reverse_line do |line| - result = line + result - limit -= 1 - return result if limit <= 0 - end - result + to_enum(:reverse_line).first(limit).reverse.join end def reverse_line -- cgit v1.2.3 From 8c1b07e0cc3e461939cae0a9566cbab172360cdf Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 20:21:13 +0900 Subject: Optimize reverse_line --- lib/gitlab/ci/trace/stream.rb | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 5777332b251..e8c34f3da05 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -96,30 +96,31 @@ module Gitlab end def reverse_line - pos = BUFFER_SIZE + pos = 0 max = stream.size debris = '' - while pos < max + while (read_size = calc_read_size(pos, max)) > 0 + pos += read_size stream.seek(-pos, IO::SEEK_END) - stream.read(BUFFER_SIZE).tap do |buf| + stream.read(read_size).tap do |buf| buf = buf + debris debris, *lines = buf.each_line.to_a lines.reverse_each do |line| yield(line) end end - pos += BUFFER_SIZE end - # Reached the head, read only left - stream.seek(0) - last = (max > BUFFER_SIZE) ? (max % BUFFER_SIZE) : max - stream.read(last).tap do |buf| - buf = buf + debris - buf.each_line.reverse_each do |line| - yield(line) - end + yield(debris) if debris != '' + end + + def calc_read_size(pos, max) + if pos > max + BUFFER_SIZE + (pos - max) + else + remain = max - pos + (remain > BUFFER_SIZE) ? BUFFER_SIZE : remain end end end -- cgit v1.2.3 From fdcd2f192dd37ac2a2ea5b73926122009fbbe0aa Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 20:39:47 +0900 Subject: Improve calc_read_size --- lib/gitlab/ci/trace/stream.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index e8c34f3da05..39826846be0 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -116,12 +116,8 @@ module Gitlab end def calc_read_size(pos, max) - if pos > max - BUFFER_SIZE + (pos - max) - else - remain = max - pos - (remain > BUFFER_SIZE) ? BUFFER_SIZE : remain - end + remain = max - pos + (remain > BUFFER_SIZE) ? BUFFER_SIZE : remain end end end -- cgit v1.2.3 From 72b0af2c4cefea51c521d3606a0a3307aee41348 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 18 May 2017 01:44:15 +0900 Subject: Avoid tap. Use unless&empty. --- lib/gitlab/ci/trace/stream.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 39826846be0..d64c43df1d5 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -103,16 +103,14 @@ module Gitlab while (read_size = calc_read_size(pos, max)) > 0 pos += read_size stream.seek(-pos, IO::SEEK_END) - stream.read(read_size).tap do |buf| - buf = buf + debris - debris, *lines = buf.each_line.to_a - lines.reverse_each do |line| - yield(line) - end + buf = stream.read(read_size) + debris + debris, *lines = buf.each_line.to_a + lines.reverse_each do |line| + yield(line) end end - yield(debris) if debris != '' + yield(debris) unless debris.empty? end def calc_read_size(pos, max) -- cgit v1.2.3 From 22f1d2a1c46ce9eb2835611c4eac6948bd983488 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 18 May 2017 01:59:04 +0900 Subject: Append gurad clause. remove unless debris.empty --- lib/gitlab/ci/trace/stream.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index d64c43df1d5..c2abe37f003 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -96,6 +96,8 @@ module Gitlab end def reverse_line + return if stream.size <= 0 + pos = 0 max = stream.size debris = '' @@ -110,7 +112,7 @@ module Gitlab end end - yield(debris) unless debris.empty? + yield(debris) end def calc_read_size(pos, max) -- cgit v1.2.3 From a16387486ae6db94b1aa49310cfc67642b68f23c Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Mon, 22 May 2017 15:17:08 +0900 Subject: put force_encoding in def reverse_line --- lib/gitlab/ci/trace/stream.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index c2abe37f003..45b32e4a7f2 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -74,7 +74,7 @@ module Gitlab match = "" reverse_line do |line| - matches = line.force_encoding(regex.encoding).scan(regex) + matches = line.scan(regex) next unless matches.is_a?(Array) next if matches.empty? @@ -108,11 +108,11 @@ module Gitlab buf = stream.read(read_size) + debris debris, *lines = buf.each_line.to_a lines.reverse_each do |line| - yield(line) + yield(line.force_encoding('UTF-8')) end end - yield(debris) + yield(debris.force_encoding('UTF-8')) end def calc_read_size(pos, max) -- cgit v1.2.3 From cf4ab10d71ea03c83fad22abf70dac21bbf73e72 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 24 May 2017 20:20:20 +0900 Subject: Adopt ayufan script --- lib/gitlab/ci/trace/stream.rb | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 45b32e4a7f2..c5a1ddfe691 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -96,28 +96,29 @@ module Gitlab end def reverse_line - return if stream.size <= 0 - - pos = 0 - max = stream.size + stream.seek(0, IO::SEEK_END) debris = '' - while (read_size = calc_read_size(pos, max)) > 0 - pos += read_size - stream.seek(-pos, IO::SEEK_END) - buf = stream.read(read_size) + debris + while !(buf = read_backward(BUFFER_SIZE)).empty? + buf += debris debris, *lines = buf.each_line.to_a lines.reverse_each do |line| yield(line.force_encoding('UTF-8')) end end - yield(debris.force_encoding('UTF-8')) + yield(debris.force_encoding('UTF-8')) if !(debris).empty? end - def calc_read_size(pos, max) - remain = max - pos - (remain > BUFFER_SIZE) ? BUFFER_SIZE : remain + def read_backward(length) + cur_offset = stream.tell + start = cur_offset - length + start = 0 if start < 0 + + stream.seek(start, IO::SEEK_SET) + stream.read(cur_offset - start).tap do + stream.seek(start, IO::SEEK_SET) + end end end end -- cgit v1.2.3 From 2f62af684e127010cffd81e027f469dcde3bc9b2 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 24 May 2017 13:37:19 +0200 Subject: Restore original comment [ci skip] --- lib/gitlab/etag_caching/router.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index 01bf578c570..9deca760469 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -7,7 +7,7 @@ module Gitlab # - Don't contain a reserved word (expect for the words used in the # regex itself) # - Ending in `noteable/issue//notes` for the `issue_notes` route - # - Ending in `issues/id`/rendered_title` for the `issue_title` route + # - Ending in `issues/id`/realtime_changes` for the `issue_title` route USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes commit pipelines merge_requests new environments].freeze -- cgit v1.2.3 From 16168b5b10ddccfc409c13e6c105a2862ba01c7c Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 23 May 2017 16:14:52 +0200 Subject: Use the iterator inside DiffCollection only once --- lib/gitlab/git/diff_collection.rb | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb index bcbad8ec829..398d6013d35 100644 --- a/lib/gitlab/git/diff_collection.rb +++ b/lib/gitlab/git/diff_collection.rb @@ -19,22 +19,19 @@ module Gitlab @line_count = 0 @byte_count = 0 @overflow = false + @empty = true @array = Array.new end def each(&block) - if @populated - # @iterator.each is slower than just iterating the array in place - @array.each(&block) - else - Gitlab::GitalyClient.migrate(:commit_raw_diffs) do - each_patch(&block) - end + Gitlab::GitalyClient.migrate(:commit_raw_diffs) do + each_patch(&block) end end def empty? - !@iterator.any? + any? # Make sure the iterator has been exercised + @empty end def overflow? @@ -60,7 +57,6 @@ module Gitlab collection = each_with_index do |element, i| @array[i] = yield(element) end - @populated = true collection end @@ -70,7 +66,6 @@ module Gitlab return if @populated each { nil } # force a loop through all diffs - @populated = true nil end @@ -79,15 +74,17 @@ module Gitlab end def each_patch - @iterator.each_with_index do |raw, i| - # First yield cached Diff instances from @array - if @array[i] - yield @array[i] - next - end + i = 0 + @array.each do |diff| + yield diff + i += 1 + end + + return if @overflow + return if @iterator.nil? - # We have exhausted @array, time to create new Diff instances or stop. - break if @overflow + @iterator.each do |raw| + @empty = false if !@all_diffs && i >= @max_files @overflow = true @@ -113,7 +110,13 @@ module Gitlab end yield @array[i] = diff + i += 1 end + + @populated = true + + # Allow iterator to be garbage-collected. It cannot be reused anyway. + @iterator = nil end end end -- cgit v1.2.3 From 3ca932844316f567f9ed091d7185ad9fafc27c51 Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Tue, 9 May 2017 14:14:24 +0200 Subject: Fix LaTeX formatting for AsciiDoc wiki --- lib/banzai/filter/ascii_doc_post_processing_filter.rb | 13 +++++++++++++ lib/banzai/filter/sanitization_filter.rb | 4 ++++ lib/banzai/pipeline/ascii_doc_pipeline.rb | 14 ++++++++++++++ lib/gitlab/asciidoc.rb | 13 ++++++------- 4 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 lib/banzai/filter/ascii_doc_post_processing_filter.rb create mode 100644 lib/banzai/pipeline/ascii_doc_pipeline.rb (limited to 'lib') diff --git a/lib/banzai/filter/ascii_doc_post_processing_filter.rb b/lib/banzai/filter/ascii_doc_post_processing_filter.rb new file mode 100644 index 00000000000..c9fcf057c5f --- /dev/null +++ b/lib/banzai/filter/ascii_doc_post_processing_filter.rb @@ -0,0 +1,13 @@ +module Banzai + module Filter + class AsciiDocPostProcessingFilter < HTML::Pipeline::Filter + def call + doc.search('[data-math-style]').each do |node| + node.set_attribute('class', 'code math js-render-math') + end + + doc + end + end + end +end diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb index 522217deae4..2d6e8ffc90f 100644 --- a/lib/banzai/filter/sanitization_filter.rb +++ b/lib/banzai/filter/sanitization_filter.rb @@ -31,6 +31,10 @@ module Banzai # Allow span elements whitelist[:elements].push('span') + # Allow data-math-style attribute in order to support LaTeX formatting + whitelist[:attributes]['code'] = %w(data-math-style) + whitelist[:attributes]['pre'] = %w(data-math-style) + # Allow html5 details/summary elements whitelist[:elements].push('details') whitelist[:elements].push('summary') diff --git a/lib/banzai/pipeline/ascii_doc_pipeline.rb b/lib/banzai/pipeline/ascii_doc_pipeline.rb new file mode 100644 index 00000000000..1048b927cd3 --- /dev/null +++ b/lib/banzai/pipeline/ascii_doc_pipeline.rb @@ -0,0 +1,14 @@ +module Banzai + module Pipeline + class AsciiDocPipeline < BasePipeline + def self.filters + FilterArray[ + Filter::SanitizationFilter, + Filter::ExternalLinkFilter, + Filter::PlantumlFilter, + Filter::AsciiDocPostProcessingFilter + ] + end + end + end +end diff --git a/lib/gitlab/asciidoc.rb b/lib/gitlab/asciidoc.rb index 96d38f6daa0..3d41ac76406 100644 --- a/lib/gitlab/asciidoc.rb +++ b/lib/gitlab/asciidoc.rb @@ -20,21 +20,20 @@ module Gitlab backend: :gitlab_html5, attributes: DEFAULT_ADOC_ATTRS } - context[:pipeline] = :markup + context[:pipeline] = :ascii_doc plantuml_setup html = ::Asciidoctor.convert(input, asciidoc_opts) html = Banzai.render(html, context) - html.html_safe end def self.plantuml_setup Asciidoctor::PlantUml.configure do |conf| - conf.url = ApplicationSetting.current.plantuml_url - conf.svg_enable = ApplicationSetting.current.plantuml_enabled - conf.png_enable = ApplicationSetting.current.plantuml_enabled + conf.url = current_application_settings.plantuml_url + conf.svg_enable = current_application_settings.plantuml_enabled + conf.png_enable = current_application_settings.plantuml_enabled conf.txt_enable = false end end @@ -47,13 +46,13 @@ module Gitlab def stem(node) return super unless node.style.to_sym == :latexmath - %(#{node.content}) + %(#{node.content}) end def inline_quoted(node) return super unless node.type.to_sym == :latexmath - %(#{node.text}) + %(#{node.text}) end private -- cgit v1.2.3 From 0bf339f0ed2f91a805e99fc7483572ad7d22093a Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 24 May 2017 10:10:10 -0500 Subject: Address review --- lib/gitlab/diff/position_tracer.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/diff/position_tracer.rb b/lib/gitlab/diff/position_tracer.rb index 46f8f7e8238..dcabb5f7fe5 100644 --- a/lib/gitlab/diff/position_tracer.rb +++ b/lib/gitlab/diff/position_tracer.rb @@ -46,12 +46,14 @@ module Gitlab # Position # start_sha - ID of commit A # head_sha - ID of commit B + # base_sha - ID of base commit of A and B # old_path - path as of A (nil if file was newly created) # new_path - path as of B (nil if file was deleted) # old_line - line number as of A (nil if file was newly created) # new_line - line number as of B (nil if file was deleted) # - # We can easily update `start_sha` and `head_sha` to hold the IDs of commits C and D, + # We can easily update `start_sha` and `head_sha` to hold the IDs of + # commits C and D, and can trivially determine `base_sha` based on those, # but need to find the paths and line numbers as of C and D. # # If the file was unchanged or newly created in A->B, the path as of D can be found -- cgit v1.2.3 From f9c9daac780666dbd2ce4ad6270c66e1ee32545a Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 25 May 2017 01:35:40 +0900 Subject: Resolve static analysys. Use until instead of negative while --- lib/gitlab/ci/trace/stream.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index c5a1ddfe691..c4c0623df6c 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -99,7 +99,7 @@ module Gitlab stream.seek(0, IO::SEEK_END) debris = '' - while !(buf = read_backward(BUFFER_SIZE)).empty? + until (buf = read_backward(BUFFER_SIZE)).empty? buf += debris debris, *lines = buf.each_line.to_a lines.reverse_each do |line| @@ -107,7 +107,7 @@ module Gitlab end end - yield(debris.force_encoding('UTF-8')) if !(debris).empty? + yield(debris.force_encoding('UTF-8')) unless debris.empty? end def read_backward(length) -- cgit v1.2.3 From ff8ecbca17234897b26ea8de5caecaef1667d12d Mon Sep 17 00:00:00 2001 From: Alexis Reigel Date: Tue, 23 May 2017 14:09:45 +0200 Subject: rake task to reset all rss tokens --- lib/tasks/tokens.rake | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib') diff --git a/lib/tasks/tokens.rake b/lib/tasks/tokens.rake index 95735f43802..893c69d6e89 100644 --- a/lib/tasks/tokens.rake +++ b/lib/tasks/tokens.rake @@ -11,6 +11,11 @@ namespace :tokens do reset_all_users_token(:reset_incoming_email_token!) end + desc "Reset all GitLab rss tokens" + task reset_all_rss: :environment do + reset_all_users_token(:reset_rss_token!) + end + def reset_all_users_token(reset_token_method) TmpUser.find_in_batches do |batch| puts "Processing batch starting with user ID: #{batch.first.id}" @@ -35,4 +40,9 @@ class TmpUser < ActiveRecord::Base write_new_token(:incoming_email_token) save!(validate: false) end + + def reset_rss_token! + write_new_token(:rss_token) + save!(validate: false) + end end -- cgit v1.2.3 From dfc2542f55953815f703d743635d6faf2523d1a1 Mon Sep 17 00:00:00 2001 From: Alexis Reigel Date: Tue, 23 May 2017 22:20:53 +0200 Subject: use full caps RSS instead of rss --- lib/tasks/tokens.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/tasks/tokens.rake b/lib/tasks/tokens.rake index 893c69d6e89..ad1818ff1fa 100644 --- a/lib/tasks/tokens.rake +++ b/lib/tasks/tokens.rake @@ -11,7 +11,7 @@ namespace :tokens do reset_all_users_token(:reset_incoming_email_token!) end - desc "Reset all GitLab rss tokens" + desc "Reset all GitLab RSS tokens" task reset_all_rss: :environment do reset_all_users_token(:reset_rss_token!) end -- cgit v1.2.3 From 43b1750892369d579edc7cd4e4ea1f7ac8667e34 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 24 May 2017 20:59:26 +0000 Subject: Revert "Remove changes that are not absolutely necessary" This reverts commit b0498c176fa134761d899c9b369be12f1ca789c5 --- lib/api/repositories.rb | 2 +- lib/api/v3/repositories.rb | 2 +- lib/constraints/group_url_constrainer.rb | 6 +- lib/constraints/project_url_constrainer.rb | 2 +- lib/constraints/user_url_constrainer.rb | 6 +- lib/gitlab/etag_caching/router.rb | 2 +- lib/gitlab/path_regex.rb | 264 +++++++++++++++++++++++++++++ lib/gitlab/regex.rb | 263 +--------------------------- 8 files changed, 277 insertions(+), 270 deletions(-) create mode 100644 lib/gitlab/path_regex.rb (limited to 'lib') diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb index 8f16e532ecb..14d2bff9cb5 100644 --- a/lib/api/repositories.rb +++ b/lib/api/repositories.rb @@ -85,7 +85,7 @@ module API optional :sha, type: String, desc: 'The commit sha of the archive to be downloaded' optional :format, type: String, desc: 'The archive format' end - get ':id/repository/archive', requirements: { format: Gitlab::Regex.archive_formats_regex } do + get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do begin send_git_archive user_project.repository, ref: params[:sha], format: params[:format] rescue diff --git a/lib/api/v3/repositories.rb b/lib/api/v3/repositories.rb index e4d14bc8168..0eaa0de2eef 100644 --- a/lib/api/v3/repositories.rb +++ b/lib/api/v3/repositories.rb @@ -72,7 +72,7 @@ module API optional :sha, type: String, desc: 'The commit sha of the archive to be downloaded' optional :format, type: String, desc: 'The archive format' end - get ':id/repository/archive', requirements: { format: Gitlab::Regex.archive_formats_regex } do + get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do begin send_git_archive user_project.repository, ref: params[:sha], format: params[:format] rescue diff --git a/lib/constraints/group_url_constrainer.rb b/lib/constraints/group_url_constrainer.rb index 0ea2f97352d..6fc1d56d7a0 100644 --- a/lib/constraints/group_url_constrainer.rb +++ b/lib/constraints/group_url_constrainer.rb @@ -1,9 +1,9 @@ class GroupUrlConstrainer def matches?(request) - id = request.params[:group_id] || request.params[:id] + full_path = request.params[:group_id] || request.params[:id] - return false unless DynamicPathValidator.valid_namespace_path?(id) + return false unless DynamicPathValidator.valid_group_path?(full_path) - Group.find_by_full_path(id, follow_redirects: request.get?).present? + Group.find_by_full_path(full_path, follow_redirects: request.get?).present? end end diff --git a/lib/constraints/project_url_constrainer.rb b/lib/constraints/project_url_constrainer.rb index 4444a1abee3..4c0aee6c48f 100644 --- a/lib/constraints/project_url_constrainer.rb +++ b/lib/constraints/project_url_constrainer.rb @@ -2,7 +2,7 @@ class ProjectUrlConstrainer def matches?(request) namespace_path = request.params[:namespace_id] project_path = request.params[:project_id] || request.params[:id] - full_path = namespace_path + '/' + project_path + full_path = [namespace_path, project_path].join('/') return false unless DynamicPathValidator.valid_project_path?(full_path) diff --git a/lib/constraints/user_url_constrainer.rb b/lib/constraints/user_url_constrainer.rb index 28159dc0dec..d16ae7f3f40 100644 --- a/lib/constraints/user_url_constrainer.rb +++ b/lib/constraints/user_url_constrainer.rb @@ -1,5 +1,9 @@ class UserUrlConstrainer def matches?(request) - User.find_by_full_path(request.params[:username], follow_redirects: request.get?).present? + full_path = request.params[:username] + + return false unless DynamicPathValidator.valid_user_path?(full_path) + + User.find_by_full_path(full_path, follow_redirects: request.get?).present? end end diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index 2b0e19b338b..cc285162b44 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -10,7 +10,7 @@ module Gitlab # - Ending in `issues/id`/realtime_changes` for the `issue_title` route USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes commit pipelines merge_requests new].freeze - RESERVED_WORDS = Gitlab::Regex::ILLEGAL_PROJECT_PATH_WORDS - USED_IN_ROUTES + RESERVED_WORDS = Gitlab::PathRegex::ILLEGAL_PROJECT_PATH_WORDS - USED_IN_ROUTES RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS) ROUTES = [ Gitlab::EtagCaching::Router::Route.new( diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb new file mode 100644 index 00000000000..1ee0f2b3998 --- /dev/null +++ b/lib/gitlab/path_regex.rb @@ -0,0 +1,264 @@ +module Gitlab + module PathRegex + extend self + + # All routes that appear on the top level must be listed here. + # This will make sure that groups cannot be created with these names + # as these routes would be masked by the paths already in place. + # + # Example: + # /api/api-project + # + # the path `api` shouldn't be allowed because it would be masked by `api/*` + # + TOP_LEVEL_ROUTES = %w[ + - + .well-known + abuse_reports + admin + all + api + assets + autocomplete + ci + dashboard + explore + files + groups + health_check + help + hooks + import + invites + issues + jwt + koding + member + merge_requests + new + notes + notification_settings + oauth + profile + projects + public + repository + robots.txt + s + search + sent_notifications + services + snippets + teams + u + unicorn_test + unsubscribes + uploads + users + ].freeze + + # This list should contain all words following `/*namespace_id/:project_id` in + # routes that contain a second wildcard. + # + # Example: + # /*namespace_id/:project_id/badges/*ref/build + # + # If `badges` was allowed as a project/group name, we would not be able to access the + # `badges` route for those projects: + # + # Consider a namespace with path `foo/bar` and a project called `badges`. + # The route to the build badge would then be `/foo/bar/badges/badges/master/build.svg` + # + # When accessing this path the route would be matched to the `badges` path + # with the following params: + # - namespace_id: `foo` + # - project_id: `bar` + # - ref: `badges/master` + # + # Failing to find the project, this would result in a 404. + # + # By rejecting `badges` the router can _count_ on the fact that `badges` will + # be preceded by the `namespace/project`. + PROJECT_WILDCARD_ROUTES = %w[ + badges + blame + blob + builds + commits + create + create_dir + edit + environments/folders + files + find_file + gitlab-lfs/objects + info/lfs/objects + new + preview + raw + refs + tree + update + wikis + ].freeze + + # These are all the paths that follow `/groups/*id/ or `/groups/*group_id` + # We need to reject these because we have a `/groups/*id` page that is the same + # as the `/*id`. + # + # If we would allow a subgroup to be created with the name `activity` then + # this group would not be accessible through `/groups/parent/activity` since + # this would map to the activity-page of its parent. + GROUP_ROUTES = %w[ + activity + analytics + audit_events + avatar + edit + group_members + hooks + issues + labels + ldap + ldap_group_links + merge_requests + milestones + notification_setting + pipeline_quota + projects + subgroups + ].freeze + + ILLEGAL_PROJECT_PATH_WORDS = PROJECT_WILDCARD_ROUTES + ILLEGAL_GROUP_PATH_WORDS = (PROJECT_WILDCARD_ROUTES | GROUP_ROUTES).freeze + + # The namespace regex is used in JavaScript to validate usernames in the "Register" form. However, Javascript + # does not support the negative lookbehind assertion (? Date: Wed, 24 May 2017 16:56:16 -0500 Subject: Remove extra space --- lib/gitlab/path_regex.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb index 1ee0f2b3998..1c0abc9f7cf 100644 --- a/lib/gitlab/path_regex.rb +++ b/lib/gitlab/path_regex.rb @@ -258,7 +258,7 @@ module Gitlab def single_line_regexp(regex) # Turns a multiline extended regexp into a single line one, # beacuse `rake routes` breaks on multiline regexes. - Regexp.new(regex.source.gsub(/\(\?#.+?\)/ , '').gsub(/\s*/, ''), regex.options ^ Regexp::EXTENDED).freeze + Regexp.new(regex.source.gsub(/\(\?#.+?\)/, '').gsub(/\s*/, ''), regex.options ^ Regexp::EXTENDED).freeze end end end -- cgit v1.2.3 From efebdba21db9e11b876ecb54db48358e13b08ad3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 25 May 2017 19:31:21 +0800 Subject: Frontend implementation, tests, and changelog --- lib/gitlab/utils.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb index 4c395b4266e..fa182c4deda 100644 --- a/lib/gitlab/utils.rb +++ b/lib/gitlab/utils.rb @@ -21,5 +21,13 @@ module Gitlab nil end + + def boolean_to_yes_no(bool) + if bool + 'Yes' + else + 'No' + end + end end end -- cgit v1.2.3 From bd66bf08b5b9a2cea9320100a91240e93f1c06e5 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 25 May 2017 19:49:46 +0800 Subject: API and doc for protected variables --- lib/api/entities.rb | 1 + lib/api/variables.rb | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 01cc8e8e1ca..b5308aeecf6 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -670,6 +670,7 @@ module API class Variable < Grape::Entity expose :key, :value + expose :protected?, as: :protected end class Pipeline < PipelineBasic diff --git a/lib/api/variables.rb b/lib/api/variables.rb index 5acde41551b..381c4ef50b0 100644 --- a/lib/api/variables.rb +++ b/lib/api/variables.rb @@ -42,6 +42,7 @@ module API params do requires :key, type: String, desc: 'The key of the variable' requires :value, type: String, desc: 'The value of the variable' + optional :protected, type: String, desc: 'Whether the variable is protected' end post ':id/variables' do variable = user_project.variables.create(declared(params, include_parent_namespaces: false).to_h) @@ -59,13 +60,14 @@ module API params do optional :key, type: String, desc: 'The key of the variable' optional :value, type: String, desc: 'The value of the variable' + optional :protected, type: String, desc: 'Whether the variable is protected' end put ':id/variables/:key' do variable = user_project.variables.find_by(key: params[:key]) return not_found!('Variable') unless variable - if variable.update(value: params[:value]) + if variable.update(declared_params(include_missing: false).except(:key)) present variable, with: Entities::Variable else render_validation_error!(variable) -- cgit v1.2.3 From 4ba547809fd8fd228ea463e4f107242d1966c892 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 25 May 2017 08:43:47 -0500 Subject: Cartfile git and binary methods cannot take a GitHub repo --- lib/gitlab/dependency_linker/cartfile_linker.rb | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/dependency_linker/cartfile_linker.rb b/lib/gitlab/dependency_linker/cartfile_linker.rb index f65577588f8..4f69f2c4ab2 100644 --- a/lib/gitlab/dependency_linker/cartfile_linker.rb +++ b/lib/gitlab/dependency_linker/cartfile_linker.rb @@ -6,14 +6,8 @@ module Gitlab private def link_dependencies - link_method_call(%w[github git binary]) do |value| - case value - when %r{\A#{REPO_REGEX}\z} - github_url(value) - when /\A#{URL_REGEX}\z/ - value - end - end + link_method_call('github', REPO_REGEX, &method(:github_url)) + link_method_call(%w[github git binary], URL_REGEX, &:itself) end end end -- cgit v1.2.3 From 41e4072393f0088c75f27d61293318844c62125e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 25 May 2017 08:55:47 -0500 Subject: Add regexp_for_value helper method --- lib/gitlab/dependency_linker/base_linker.rb | 13 +++++++++++++ lib/gitlab/dependency_linker/json_linker.rb | 27 ++++----------------------- lib/gitlab/dependency_linker/method_linker.rb | 25 ++++++++----------------- 3 files changed, 25 insertions(+), 40 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb index 15fa9f40116..7ba0b3c39b7 100644 --- a/lib/gitlab/dependency_linker/base_linker.rb +++ b/lib/gitlab/dependency_linker/base_linker.rb @@ -68,6 +68,19 @@ module Gitlab def highlighted_lines @highlighted_lines ||= highlighted_text.lines end + + def regexp_for_value(value, default: /[^'"]+/) + case value + when Array + Regexp.union(value.map { |v| regexp_for_value(v, default: default) }) + when String + Regexp.escape(value) + when Regexp + value + else + default + end + end end end end diff --git a/lib/gitlab/dependency_linker/json_linker.rb b/lib/gitlab/dependency_linker/json_linker.rb index 021347b6429..1b1ca000977 100644 --- a/lib/gitlab/dependency_linker/json_linker.rb +++ b/lib/gitlab/dependency_linker/json_linker.rb @@ -24,32 +24,13 @@ module Gitlab # link_json('specific_package', '1.0.1', link: :key) # # Will link `specific_package` in `"specific_package": "1.0.1"` def link_json(key, value = nil, link: :value, &url_proc) - key = - case key - when Array - Regexp.union(key.map { |name| Regexp.escape(name) }) - when String - Regexp.escape(key) - when nil - '[^"]+' - else - key - end - - value = - case value - when String - Regexp.escape(value) - when nil - '[^"]+' - else - value - end + key = regexp_for_value(key, default: /[^"]+/) + value = regexp_for_value(value, default: /[^"]+/) if link == :value - value = "(?#{value})" + value = /(?#{value})/ else - key = "(?#{key})" + key = /(?#{key})/ end link_regex(/"#{key}":\s*"#{value}"/, &url_proc) diff --git a/lib/gitlab/dependency_linker/method_linker.rb b/lib/gitlab/dependency_linker/method_linker.rb index eeb7c1587c0..0ffa2a83c93 100644 --- a/lib/gitlab/dependency_linker/method_linker.rb +++ b/lib/gitlab/dependency_linker/method_linker.rb @@ -20,25 +20,16 @@ module Gitlab # # link_method_call('name') # # Will link `package` in `self.name = "package"` - def link_method_call(method_names, value = nil, &url_proc) - method_names = Array(method_names).map { |name| Regexp.escape(name) } - - value = - case value - when String - Regexp.escape(value) - when nil - /[^'"]+/ - else - value - end + def link_method_call(method_name, value = nil, &url_proc) + method_name = regexp_for_value(method_name) + value = regexp_for_value(value) regex = %r{ - #{Regexp.union(method_names)} # Method name - \s* # Whitespace - [(=]? # Opening brace or equals sign - \s* # Whitespace - ['"](?#{value})['"] # Package name in quotes + #{method_name} # Method name + \s* # Whitespace + [(=]? # Opening brace or equals sign + \s* # Whitespace + ['"](?#{value})['"] # Package name in quotes }x link_regex(regex, &url_proc) -- cgit v1.2.3 From 5c921809cd86e1031a6a5075da142fef3bb01d6d Mon Sep 17 00:00:00 2001 From: Ruben Davila Date: Thu, 25 May 2017 10:22:45 -0500 Subject: Bugfix: Always use the default language when generating emails. There was a race condition issue when the application was generating an email and was using a language that was previously being used in other request. --- lib/api/api.rb | 4 ++-- lib/gitlab/i18n.rb | 31 ++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/api/api.rb b/lib/api/api.rb index 52cd7cbe3db..ac113c5200d 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -45,9 +45,9 @@ module API end before { allow_access_with_scope :api } - before { Gitlab::I18n.set_locale(current_user) } + before { Gitlab::I18n.locale = current_user&.preferred_language } - after { Gitlab::I18n.reset_locale } + after { Gitlab::I18n.use_default_locale } rescue_from Gitlab::Access::AccessDeniedError do rack_response({ 'message' => '403 Forbidden' }.to_json, 403) diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index 3411516319f..5ab3eeb3aff 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -12,15 +12,36 @@ module Gitlab AVAILABLE_LANGUAGES.keys end - def set_locale(current_user) - requested_locale = current_user&.preferred_language || ::I18n.default_locale - locale = FastGettext.set_locale(requested_locale) - ::I18n.locale = locale + def locale + FastGettext.locale end - def reset_locale + def locale=(locale_string) + requested_locale = locale_string || ::I18n.default_locale + new_locale = FastGettext.set_locale(requested_locale) + ::I18n.locale = new_locale + end + + def use_default_locale FastGettext.set_locale(::I18n.default_locale) ::I18n.locale = ::I18n.default_locale end + + def with_locale(locale_string) + original_locale = locale + + self.locale = locale_string + yield + ensure + self.locale = original_locale + end + + def with_user_locale(user, &block) + with_locale(user&.preferred_language, &block) + end + + def with_default_locale(&block) + with_locale(::I18n.default_locale, &block) + end end end -- cgit v1.2.3 From eb21f93267f3d911b40cace81a4f63f857a1243a Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 25 May 2017 12:10:34 +0100 Subject: Only use DROP INDEX CONCURRENTLY on postgreql 9.2+ --- lib/gitlab/database/migration_helpers.rb | 35 +++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index e76c9abbe04..a412bb6dbd2 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -42,7 +42,7 @@ module Gitlab 'in the body of your migration class' end - if Database.postgresql? + if supports_drop_index_concurrently? options = options.merge({ algorithm: :concurrently }) disable_statement_timeout end @@ -50,6 +50,39 @@ module Gitlab remove_index(table_name, options.merge({ column: column_name })) end + # Removes an existing index, concurrently when supported + # + # On PostgreSQL this method removes an index concurrently. + # + # Example: + # + # remove_concurrent_index :users, "index_X_by_Y" + # + # See Rails' `remove_index` for more info on the available arguments. + def remove_concurrent_index_by_name(table_name, index_name, options = {}) + if transaction_open? + raise 'remove_concurrent_index_by_name can not be run inside a transaction, ' \ + 'you can disable transactions by calling disable_ddl_transaction! ' \ + 'in the body of your migration class' + end + + if supports_drop_index_concurrently? + options = options.merge({ algorithm: :concurrently }) + disable_statement_timeout + end + + remove_index(table_name, options.merge({ name: index_name })) + end + + # Only available on Postgresql >= 9.2 + def supports_drop_index_concurrently? + return false unless Database.postgresql? + + version = select_one("SELECT current_setting('server_version_num') AS v")['v'].to_i + + version >= 90200 + end + # Adds a foreign key with only minimal locking on the tables involved. # # This method only requires minimal locking when using PostgreSQL. When -- cgit v1.2.3 From a0497a7bc0726dfc7bc1b0f5568f0353436e128b Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Thu, 25 May 2017 20:53:42 +0200 Subject: Move helpers to spec file, use const's instead of helper methods --- lib/gitlab/health_checks/fs_shards_check.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/health_checks/fs_shards_check.rb b/lib/gitlab/health_checks/fs_shards_check.rb index 90612af3d63..e78b7f22e03 100644 --- a/lib/gitlab/health_checks/fs_shards_check.rb +++ b/lib/gitlab/health_checks/fs_shards_check.rb @@ -2,6 +2,9 @@ module Gitlab module HealthChecks class FsShardsCheck extend BaseAbstractCheck + RANDOM_STRING = SecureRandom.hex(1000).freeze + COMMAND_TIMEOUT = '1'.freeze + TIMEOUT_EXECUTABLE = 'timeout'.freeze class << self def readiness @@ -41,9 +44,6 @@ module Gitlab private - RANDOM_STRING = SecureRandom.hex(1000).freeze - COMMAND_TIMEOUT = 1.second - def operation_metrics(ok_metric, latency_metric, operation, **labels) with_timing operation do |result, elapsed| [ @@ -64,12 +64,8 @@ module Gitlab @storage_paths ||= Gitlab.config.repositories.storages end - def with_timeout(args) - %W{timeout #{COMMAND_TIMEOUT.to_i}}.concat(args) - end - def exec_with_timeout(cmd_args, *args, &block) - Gitlab::Popen.popen(with_timeout(cmd_args), *args, &block) + Gitlab::Popen.popen([TIMEOUT_EXECUTABLE, COMMAND_TIMEOUT].concat(cmd_args), *args, &block) end def tmp_file_path(storage_name) -- cgit v1.2.3 From d88a5c1db1c6cca639039188a26c6e6d5bc68831 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 25 May 2017 15:17:57 -0500 Subject: Address feedback --- lib/gitlab/diff/file_collection/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/diff/file_collection/base.rb b/lib/gitlab/diff/file_collection/base.rb index 7330f3377e1..36a7f26e83f 100644 --- a/lib/gitlab/diff/file_collection/base.rb +++ b/lib/gitlab/diff/file_collection/base.rb @@ -2,7 +2,7 @@ module Gitlab module Diff module FileCollection class Base - attr_reader :project, :diff_options, :diff_view, :diff_refs, :fallback_diff_refs + attr_reader :project, :diff_options, :diff_refs, :fallback_diff_refs delegate :count, :size, :real_size, to: :diff_files -- cgit v1.2.3 From 31b02fc210ffcde72a9d7882ab07979ed18a023b Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Thu, 25 May 2017 15:52:39 -0500 Subject: Don't allow spaces in dependency linker value regex --- lib/gitlab/dependency_linker/base_linker.rb | 6 +++--- lib/gitlab/dependency_linker/json_linker.rb | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb index 7ba0b3c39b7..7bbd154eb03 100644 --- a/lib/gitlab/dependency_linker/base_linker.rb +++ b/lib/gitlab/dependency_linker/base_linker.rb @@ -1,8 +1,8 @@ module Gitlab module DependencyLinker class BaseLinker - URL_REGEX = %r{https?://[^'"]+}.freeze - REPO_REGEX = %r{[^/'"]+/[^/'"]+}.freeze + URL_REGEX = %r{https?://[^'" ]+}.freeze + REPO_REGEX = %r{[^/'" ]+/[^/'" ]+}.freeze class_attribute :file_type @@ -69,7 +69,7 @@ module Gitlab @highlighted_lines ||= highlighted_text.lines end - def regexp_for_value(value, default: /[^'"]+/) + def regexp_for_value(value, default: /[^'" ]+/) case value when Array Regexp.union(value.map { |v| regexp_for_value(v, default: default) }) diff --git a/lib/gitlab/dependency_linker/json_linker.rb b/lib/gitlab/dependency_linker/json_linker.rb index 1b1ca000977..a8ef25233d8 100644 --- a/lib/gitlab/dependency_linker/json_linker.rb +++ b/lib/gitlab/dependency_linker/json_linker.rb @@ -24,8 +24,8 @@ module Gitlab # link_json('specific_package', '1.0.1', link: :key) # # Will link `specific_package` in `"specific_package": "1.0.1"` def link_json(key, value = nil, link: :value, &url_proc) - key = regexp_for_value(key, default: /[^"]+/) - value = regexp_for_value(value, default: /[^"]+/) + key = regexp_for_value(key, default: /[^" ]+/) + value = regexp_for_value(value, default: /[^" ]+/) if link == :value value = /(?#{value})/ -- cgit v1.2.3 From 6c17e4f04d06921f8f61bc6aad0ea398dad194f0 Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Tue, 23 May 2017 11:14:43 +0200 Subject: Add API URL to JIRA settings --- lib/api/services.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/services.rb b/lib/api/services.rb index cb07df9e249..47bd9940f77 100644 --- a/lib/api/services.rb +++ b/lib/api/services.rb @@ -304,7 +304,13 @@ module API required: true, name: :url, type: String, - desc: 'The URL to the JIRA project which is being linked to this GitLab project, e.g., https://jira.example.com' + desc: 'The base URL to the JIRA instance web interface which is being linked to this GitLab project. E.g., https://jira.example.com' + }, + { + required: false, + name: :api_url, + type: String, + desc: 'The base URL to the JIRA instance API. Web URL value will be used if not set. E.g., https://jira-api.example.com' }, { required: true, -- cgit v1.2.3 From b172ef2fdc2a12de67bc8228ef156d08b63e9bf6 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Fri, 26 May 2017 15:26:06 +0100 Subject: Restore notifications to MR widget --- lib/gitlab/gon_helper.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index 21f2e6b6970..ab5d9a69b6f 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -13,6 +13,7 @@ module Gitlab gon.sentry_dsn = current_application_settings.clientside_sentry_dsn if current_application_settings.clientside_sentry_enabled gon.gitlab_url = Gitlab.config.gitlab.url gon.revision = Gitlab::REVISION + gon.gitlab_logo = ActionController::Base.helpers.asset_path('gitlab_logo.png') if current_user gon.current_user_id = current_user.id -- cgit v1.2.3 From 39c6dd5b935d79c424bb16ed40d41c06d56a47cf Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 26 May 2017 16:30:45 +0200 Subject: Duplicate gitaly init variables in 'default' file This is needed because these variables depend (directly or indirectly) on the 'app_root' variable which can be changed in the default file. If app_root has a non-standard value, the value of e.g. gitaly_dir generated in the init script becomes invalid. --- lib/support/init.d/gitlab.default.example | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example index 9472c3c992f..b341b5a0309 100644 --- a/lib/support/init.d/gitlab.default.example +++ b/lib/support/init.d/gitlab.default.example @@ -87,4 +87,6 @@ shell_path="/bin/bash" # This variable controls whether the init script starts/stops Gitaly gitaly_enabled=false +gitaly_dir=$(cd $app_root/../gitaly 2> /dev/null && pwd) +gitaly_pid_path="$pid_path/gitaly.pid" gitaly_log="$app_root/log/gitaly.log" -- cgit v1.2.3 From c94db0c2906c5da49acc9addb976b64fd7c7b256 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 26 May 2017 21:55:29 +0800 Subject: Use - as the prefix so we don't conflict with namespaces The decision was made around: https://gitlab.com/gitlab-org/gitlab-ce/issues/26407#note_30624641 --- lib/gitlab/path_regex.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb index 1c0abc9f7cf..9ff6829cd49 100644 --- a/lib/gitlab/path_regex.rb +++ b/lib/gitlab/path_regex.rb @@ -80,6 +80,7 @@ module Gitlab # By rejecting `badges` the router can _count_ on the fact that `badges` will # be preceded by the `namespace/project`. PROJECT_WILDCARD_ROUTES = %w[ + - badges blame blob -- cgit v1.2.3 From 366cf1f5d33184f87b714bdba2a3025b9cb39be1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Sat, 27 May 2017 02:12:35 +0800 Subject: Should escape the routes because we added - --- lib/gitlab/etag_caching/router.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index cc285162b44..d137cc1bae6 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -11,7 +11,7 @@ module Gitlab USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes commit pipelines merge_requests new].freeze RESERVED_WORDS = Gitlab::PathRegex::ILLEGAL_PROJECT_PATH_WORDS - USED_IN_ROUTES - RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS) + RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS.map(&Regexp.method(:escape))) ROUTES = [ Gitlab::EtagCaching::Router::Route.new( %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/noteable/issue/\d+/notes\z), -- cgit v1.2.3 From 13dd82b5de6a2076f33defc9f12bc05f98891423 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Fri, 26 May 2017 20:37:29 +0000 Subject: Add rubocop:disable to gon_helper.rb --- lib/gitlab/gon_helper.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index ab5d9a69b6f..319633656ff 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -1,3 +1,5 @@ +# rubocop:disable Metrics/AbcSize + module Gitlab module GonHelper def add_gon_variables -- cgit v1.2.3 From aed0387f97ec62b184da90bdca0ce40f9dc58b45 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 26 May 2017 18:27:30 -0500 Subject: Consistent diff and blob size limit names --- lib/api/commits.rb | 2 +- lib/api/entities.rb | 6 +-- lib/api/v3/commits.rb | 2 +- lib/api/v3/entities.rb | 2 +- lib/gitlab/diff/file_collection/base.rb | 2 +- lib/gitlab/email/message/repository_push.rb | 2 +- lib/gitlab/git/blob.rb | 1 + lib/gitlab/git/diff.rb | 62 ++++++++++++++--------------- lib/gitlab/git/diff_collection.rb | 20 +++++----- 9 files changed, 50 insertions(+), 49 deletions(-) (limited to 'lib') diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 621b9dcecd9..904993d1606 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -176,7 +176,7 @@ module API } if params[:path] - commit.raw_diffs(all_diffs: true).each do |diff| + commit.raw_diffs(no_limits: true).each do |diff| next unless diff.new_path == params[:path] lines = Gitlab::Diff::Parser.new.parse(diff.diff.each_line) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 8c5e5c91769..9799fe68a76 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -331,7 +331,7 @@ module API class MergeRequestChanges < MergeRequest expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _| - compare.raw_diffs(all_diffs: true).to_a + compare.raw_diffs(no_limits: true).to_a end end @@ -344,7 +344,7 @@ module API expose :commits, using: Entities::RepoCommit expose :diffs, using: Entities::RepoDiff do |compare, _| - compare.raw_diffs(all_diffs: true).to_a + compare.raw_diffs(no_limits: true).to_a end end @@ -548,7 +548,7 @@ module API end expose :diffs, using: Entities::RepoDiff do |compare, options| - compare.diffs(all_diffs: true).to_a + compare.diffs(no_limits: true).to_a end expose :compare_timeout do |compare, options| diff --git a/lib/api/v3/commits.rb b/lib/api/v3/commits.rb index 674de592f0a..ec6c6c7b298 100644 --- a/lib/api/v3/commits.rb +++ b/lib/api/v3/commits.rb @@ -167,7 +167,7 @@ module API } if params[:path] - commit.raw_diffs(all_diffs: true).each do |diff| + commit.raw_diffs(no_limits: true).each do |diff| next unless diff.new_path == params[:path] lines = Gitlab::Diff::Parser.new.parse(diff.diff.each_line) diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index 2e1b243c2db..7fbd4949850 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -226,7 +226,7 @@ module API class MergeRequestChanges < MergeRequest expose :diffs, as: :changes, using: ::API::Entities::RepoDiff do |compare, _| - compare.raw_diffs(all_diffs: true).to_a + compare.raw_diffs(no_limits: true).to_a end end diff --git a/lib/gitlab/diff/file_collection/base.rb b/lib/gitlab/diff/file_collection/base.rb index 79836a2fbab..a6007ebf531 100644 --- a/lib/gitlab/diff/file_collection/base.rb +++ b/lib/gitlab/diff/file_collection/base.rb @@ -7,7 +7,7 @@ module Gitlab delegate :count, :size, :real_size, to: :diff_files def self.default_options - ::Commit.max_diff_options.merge(ignore_whitespace_change: false, no_collapse: false) + ::Commit.max_diff_options.merge(ignore_whitespace_change: false, expanded: false) end def initialize(diffable, project:, diff_options: nil, diff_refs: nil, fallback_diff_refs: nil) diff --git a/lib/gitlab/email/message/repository_push.rb b/lib/gitlab/email/message/repository_push.rb index 6c69cd9e6a9..ea035e33eff 100644 --- a/lib/gitlab/email/message/repository_push.rb +++ b/lib/gitlab/email/message/repository_push.rb @@ -42,7 +42,7 @@ module Gitlab return unless compare # This diff is more moderated in number of files and lines - @diffs ||= compare.diffs(max_files: 30, max_lines: 5000, no_collapse: true).diff_files + @diffs ||= compare.diffs(max_files: 30, max_lines: 5000, expanded: true).diff_files end def diffs_count diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb index c1b31618e0d..6b0a66365a7 100644 --- a/lib/gitlab/git/blob.rb +++ b/lib/gitlab/git/blob.rb @@ -88,6 +88,7 @@ module Gitlab new( id: blob_entry[:oid], name: blob_entry[:name], + size: 0, data: '', path: path, commit_id: sha diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index deade337354..201a115503b 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -15,13 +15,13 @@ module Gitlab alias_method :deleted_file?, :deleted_file alias_method :renamed_file?, :renamed_file - attr_accessor :too_large + attr_accessor :expanded # The maximum size of a diff to display. - DIFF_SIZE_LIMIT = 102400 # 100 KB + SIZE_LIMIT = 100.kilobytes # The maximum size before a diff is collapsed. - DIFF_COLLAPSE_LIMIT = 10240 # 10 KB + COLLAPSE_LIMIT = 10.kilobytes class << self def between(repo, head, base, options = {}, *paths) @@ -152,7 +152,7 @@ module Gitlab :include_untracked_content, :skip_binary_check, :include_typechange, :include_typechange_trees, :ignore_filemode, :recurse_ignored_dirs, :paths, - :max_files, :max_lines, :all_diffs, :no_collapse] + :max_files, :max_lines, :no_limits, :expanded] if default_options actual_defaults = default_options.dup @@ -177,16 +177,18 @@ module Gitlab end end - def initialize(raw_diff, collapse: false) + def initialize(raw_diff, expanded: true) + @expanded = expanded + case raw_diff when Hash init_from_hash(raw_diff) - prune_diff_if_eligible(collapse) + prune_diff_if_eligible when Rugged::Patch, Rugged::Diff::Delta - init_from_rugged(raw_diff, collapse: collapse) + init_from_rugged(raw_diff) when Gitaly::CommitDiffResponse init_from_gitaly(raw_diff) - prune_diff_if_eligible(collapse) + prune_diff_if_eligible when Gitaly::CommitDelta init_from_gitaly(raw_diff) when nil @@ -225,18 +227,12 @@ module Gitlab end def too_large? - if @too_large.nil? - @too_large = @diff.bytesize >= DIFF_SIZE_LIMIT - else - @too_large - end - end + return @too_large if defined?(@too_large) - def collapsible? - @diff.bytesize >= DIFF_COLLAPSE_LIMIT + @too_large = @diff.bytesize >= SIZE_LIMIT end - def prune_large_diff! + def too_large! @diff = '' @line_count = 0 @too_large = true @@ -244,10 +240,11 @@ module Gitlab def collapsed? return @collapsed if defined?(@collapsed) - false + + @collapsed = !expanded && @diff.bytesize >= COLLAPSE_LIMIT end - def prune_collapsed_diff! + def collapse! @diff = '' @line_count = 0 @collapsed = true @@ -255,9 +252,9 @@ module Gitlab private - def init_from_rugged(rugged, collapse: false) + def init_from_rugged(rugged) if rugged.is_a?(Rugged::Patch) - init_from_rugged_patch(rugged, collapse: collapse) + init_from_rugged_patch(rugged) d = rugged.delta else d = rugged @@ -272,10 +269,10 @@ module Gitlab @deleted_file = d.deleted? end - def init_from_rugged_patch(patch, collapse: false) + def init_from_rugged_patch(patch) # Don't bother initializing diffs that are too large. If a diff is # binary we're not going to display anything so we skip the size check. - return if !patch.delta.binary? && prune_large_patch(patch, collapse) + return if !patch.delta.binary? && prune_large_patch(patch) @diff = encode!(strip_diff_headers(patch.to_s)) end @@ -299,29 +296,32 @@ module Gitlab @deleted_file = msg.to_id == BLANK_SHA end - def prune_diff_if_eligible(collapse = false) - prune_large_diff! if too_large? - prune_collapsed_diff! if collapse && collapsible? + def prune_diff_if_eligible + if too_large? + too_large! + elsif collapsed? + collapse! + end end # If the patch surpasses any of the diff limits it calls the appropiate # prune method and returns true. Otherwise returns false. - def prune_large_patch(patch, collapse) + def prune_large_patch(patch) size = 0 patch.each_hunk do |hunk| hunk.each_line do |line| size += line.content.bytesize - if size >= DIFF_SIZE_LIMIT - prune_large_diff! + if size >= SIZE_LIMIT + too_large! return true end end end - if collapse && size >= DIFF_COLLAPSE_LIMIT - prune_collapsed_diff! + if !expanded && size >= COLLAPSE_LIMIT + collapse! return true end diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb index 898a5ae15f2..9b217b9080d 100644 --- a/lib/gitlab/git/diff_collection.rb +++ b/lib/gitlab/git/diff_collection.rb @@ -9,12 +9,12 @@ module Gitlab @iterator = iterator @max_files = options.fetch(:max_files, DEFAULT_LIMITS[:max_files]) @max_lines = options.fetch(:max_lines, DEFAULT_LIMITS[:max_lines]) - @max_bytes = @max_files * 5120 # Average 5 KB per file + @max_bytes = @max_files * 5.kilobytes # Average 5 KB per file @safe_max_files = [@max_files, DEFAULT_LIMITS[:max_files]].min @safe_max_lines = [@max_lines, DEFAULT_LIMITS[:max_lines]].min - @safe_max_bytes = @safe_max_files * 5120 # Average 5 KB per file - @all_diffs = !!options.fetch(:all_diffs, false) - @no_collapse = !!options.fetch(:no_collapse, true) + @safe_max_bytes = @safe_max_files * 5.kilobytes # Average 5 KB per file + @no_limits = !!options.fetch(:no_limits, false) + @expanded = !!options.fetch(:expanded, true) @line_count = 0 @byte_count = 0 @@ -88,23 +88,23 @@ module Gitlab @iterator.each do |raw| @empty = false - if !@all_diffs && i >= @max_files + if !@no_limits && i >= @max_files @overflow = true break end - collapse = !@all_diffs && !@no_collapse + expanded = @no_limits || @expanded - diff = Gitlab::Git::Diff.new(raw, collapse: collapse) + diff = Gitlab::Git::Diff.new(raw, expanded: expanded) - if collapse && over_safe_limits?(i) - diff.prune_collapsed_diff! + if !expanded && over_safe_limits?(i) + diff.collapse! end @line_count += diff.line_count @byte_count += diff.diff.bytesize - if !@all_diffs && (@line_count >= @max_lines || @byte_count >= @max_bytes) + if !@no_limits && (@line_count >= @max_lines || @byte_count >= @max_bytes) # This last Diff instance pushes us over the lines limit. We stop and # discard it. @overflow = true -- cgit v1.2.3 From a7349560b2d13ea7894a462738b3a7687fdbae72 Mon Sep 17 00:00:00 2001 From: blackst0ne Date: Tue, 30 May 2017 15:35:49 +1100 Subject: 'New issue'/'New merge request' dropdowns should show only projects with issues/merge requests feature enabled --- lib/api/projects.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/projects.rb b/lib/api/projects.rb index ed5004e8d1a..d4fe5c023bf 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -58,6 +58,8 @@ module API optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user' optional :starred, type: Boolean, default: false, desc: 'Limit by starred status' optional :membership, type: Boolean, default: false, desc: 'Limit by projects that the current user is a member of' + optional :with_issues_enabled, type: Boolean, default: false, desc: 'Limit by enabled issues feature' + optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature' end params :create_params do @@ -69,11 +71,15 @@ module API options = options.reverse_merge( with: Entities::Project, current_user: current_user, - simple: params[:simple] + simple: params[:simple], + with_issues_enabled: params[:with_issues_enabled], + with_merge_requests_enabled: params[:with_merge_requests_enabled] ) projects = filter_projects(projects) projects = projects.with_statistics if options[:statistics] + projects = projects.with_issues_enabled if options[:with_issues_enabled] + projects = projects.with_merge_requests_enabled if options[:with_merge_requests_enabled] options[:with] = Entities::BasicProjectDetails if options[:simple] present paginate(projects), options -- cgit v1.2.3 From 172932eec8f234fbb665489c00f73d644fa0413e Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Tue, 30 May 2017 11:24:55 +0100 Subject: Fix /unsubscribe slash command creating extra todos The /unsubscribe slash command means that we check if the current user is subscribed to the issuable without having an explicit subscription. That means that we use the UserParser to find references to them in the notes. The UserParser (and all parsers inheriting from BaseParser) use RequestStore to cache ActiveRecord objects, so that we don't need to load the User object each time, if we're parsing references a bunch of times in the same request. However, it was always returning _all_ of the previously cached items, not just the ones matching the IDs passed. This would mean that we did two runs through with UserParser if you were mentioned in a comment, and then mentioned someone else in your comment while using /unsubscribe: 1. Because /unsubscribe was used, we see if you were mentioned in any comments. 2. Because you mentioned someone, we find them - but we would also get back your user, even if you didn't mention yourself. This would have the effect of creating a mention or directly addressed todo for yourself incorrectly. The fix is simple: only return values from the cache matching the IDs passed. --- lib/banzai/reference_parser/base_parser.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb index c2503fa2adc..d99a3bfa625 100644 --- a/lib/banzai/reference_parser/base_parser.rb +++ b/lib/banzai/reference_parser/base_parser.rb @@ -163,14 +163,15 @@ module Banzai # been queried the object is returned from the cache. def collection_objects_for_ids(collection, ids) if RequestStore.active? + ids = ids.map(&:to_i) cache = collection_cache[collection_cache_key(collection)] - to_query = ids.map(&:to_i) - cache.keys + to_query = ids - cache.keys unless to_query.empty? collection.where(id: to_query).each { |row| cache[row.id] = row } end - cache.values + cache.values_at(*ids) else collection.where(id: ids) end -- cgit v1.2.3 From 1f1f5707244bcf4e69ef0fbe01f93e59386d5087 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 30 May 2017 12:48:05 +0200 Subject: Implement CI/CD config attributes for persisted stages --- lib/ci/gitlab_ci_yaml_processor.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index b06474cda7f..17a3cdc714c 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -50,10 +50,20 @@ module Ci end end + def stages_for_ref(ref, tag = false, trigger_request = nil) + stages = @stages.map do |stage| + builds = builds_for_stage_and_ref(stage, ref, tag, trigger_request) + + { name: stage, builds_attributes: builds.to_a } if builds.any? + end + + stages.compact.sort_by { |stage| @stages.index(stage[:name]) } + end + def build_attributes(name) job = @jobs[name.to_sym] || {} - { - stage_idx: @stages.index(job[:stage]), + + { stage_idx: @stages.index(job[:stage]), stage: job[:stage], commands: job[:commands], tag_list: job[:tags] || [], -- cgit v1.2.3 From bf4cc9e1f3ca6e4d828eb2bc1ca22d4f350c9dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Tue, 30 May 2017 14:18:58 +0200 Subject: Don't allow to pass a user to ProjectWiki#http_url_to_repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This partially reverts be25bbc4d2c7e3d5cf3da6f51cb7f7355295ef52. Signed-off-by: Rémy Coutable --- lib/gitlab/url_sanitizer.rb | 6 ------ 1 file changed, 6 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/url_sanitizer.rb b/lib/gitlab/url_sanitizer.rb index 9ce13feb79a..c81dc7e30d0 100644 --- a/lib/gitlab/url_sanitizer.rb +++ b/lib/gitlab/url_sanitizer.rb @@ -18,12 +18,6 @@ module Gitlab false end - def self.http_credentials_for_user(user) - return {} unless user.respond_to?(:username) - - { user: user.username } - end - def initialize(url, credentials: nil) @url = Addressable::URI.parse(url.strip) @credentials = credentials -- cgit v1.2.3 From 805715cc68aabb6992a63356ec7c19940f52c93a Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Tue, 30 May 2017 15:30:45 +0200 Subject: Add stage seed class that represents attributes --- lib/ci/gitlab_ci_yaml_processor.rb | 3 +-- lib/gitlab/ci/stage/seed.rb | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 lib/gitlab/ci/stage/seed.rb (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 17a3cdc714c..aa6c94f26c8 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -81,8 +81,7 @@ module Ci dependencies: job[:dependencies], after_script: job[:after_script], environment: job[:environment] - }.compact - } + }.compact } end def self.validation_message(content) diff --git a/lib/gitlab/ci/stage/seed.rb b/lib/gitlab/ci/stage/seed.rb new file mode 100644 index 00000000000..95237bff5d7 --- /dev/null +++ b/lib/gitlab/ci/stage/seed.rb @@ -0,0 +1,38 @@ +module Gitlab + module Ci + module Stage + class Seed + attr_reader :name, :builds + + def initialize(name:, builds:) + @name = name + @builds = builds + end + + def pipeline=(pipeline) + trigger_request = pipeline.trigger_requests.first + + @builds.each do |attributes| + attributes.merge!( + pipeline: pipeline, + project: pipeline.project, + ref: pipeline.ref, + tag: pipeline.tag, + trigger_request: trigger_request + ) + end + end + + def user=(current_user) + @builds.each do |attributes| + attributes.merge!(user: current_user) + end + end + + def to_attributes + { name: @name, builds_attributes: @builds } + end + end + end + end +end -- cgit v1.2.3 From 28590e8854fd15f1a36befb66c68efbb490f9f04 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 30 May 2017 15:57:11 +0200 Subject: Enable Gitaly by default in GitLab 9.3 --- lib/support/init.d/gitlab | 2 +- lib/support/init.d/gitlab.default.example | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/support/init.d/gitlab b/lib/support/init.d/gitlab index 6e351365de0..c5f93336346 100755 --- a/lib/support/init.d/gitlab +++ b/lib/support/init.d/gitlab @@ -48,7 +48,7 @@ gitlab_pages_pid_path="$pid_path/gitlab-pages.pid" gitlab_pages_options="-pages-domain example.com -pages-root $app_root/shared/pages -listen-proxy 127.0.0.1:8090" gitlab_pages_log="$app_root/log/gitlab-pages.log" shell_path="/bin/bash" -gitaly_enabled=false +gitaly_enabled=true gitaly_dir=$(cd $app_root/../gitaly 2> /dev/null && pwd) gitaly_pid_path="$pid_path/gitaly.pid" gitaly_log="$app_root/log/gitaly.log" diff --git a/lib/support/init.d/gitlab.default.example b/lib/support/init.d/gitlab.default.example index b341b5a0309..295c79fccfc 100644 --- a/lib/support/init.d/gitlab.default.example +++ b/lib/support/init.d/gitlab.default.example @@ -86,7 +86,7 @@ mail_room_pid_path="$pid_path/mail_room.pid" shell_path="/bin/bash" # This variable controls whether the init script starts/stops Gitaly -gitaly_enabled=false +gitaly_enabled=true gitaly_dir=$(cd $app_root/../gitaly 2> /dev/null && pwd) gitaly_pid_path="$pid_path/gitaly.pid" gitaly_log="$app_root/log/gitaly.log" -- cgit v1.2.3 From fbd3b3d8a245072121784df11b7b41d3257b989f Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 12 May 2017 04:12:04 +0900 Subject: Add API support for pipeline schedule --- lib/api/api.rb | 1 + lib/api/entities.rb | 8 +++ lib/api/pipeline_schedules.rb | 127 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 lib/api/pipeline_schedules.rb (limited to 'lib') diff --git a/lib/api/api.rb b/lib/api/api.rb index ac113c5200d..bbdd2039f43 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -110,6 +110,7 @@ module API mount ::API::Notes mount ::API::NotificationSettings mount ::API::Pipelines + mount ::API::PipelineSchedules mount ::API::ProjectHooks mount ::API::Projects mount ::API::ProjectSnippets diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 8c5e5c91769..1f1942b2ec1 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -686,6 +686,14 @@ module API expose :coverage end + class PipelineSchedule < Grape::Entity + expose :id + expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active + expose :created_at, :updated_at, :deleted_at + expose :last_pipeline, using: Entities::Pipeline, if: -> (pipeline_schedule, opts) { pipeline_schedule.last_pipeline.present? } + expose :owner, using: Entities::UserBasic + end + class EnvironmentBasic < Grape::Entity expose :id, :name, :slug, :external_url end diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb new file mode 100644 index 00000000000..32fa5a86fab --- /dev/null +++ b/lib/api/pipeline_schedules.rb @@ -0,0 +1,127 @@ +module API + class PipelineSchedules < Grape::API + include PaginationParams + + params do + requires :id, type: String, desc: 'The ID of a project' + end + resource :projects, requirements: { id: %r{[^/]+} } do + desc 'Get pipeline_schedules list' do + success Entities::PipelineSchedule + end + params do + use :pagination + end + get ':id/pipeline_schedules' do + authenticate! + authorize! :read_pipeline_schedule, user_project + + pipeline_schedules = user_project.pipeline_schedules + + present paginate(pipeline_schedules), with: Entities::PipelineSchedule + end + + desc 'Get specific pipeline_schedule of a project' do + success Entities::PipelineSchedule + end + params do + requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline_schedule ID' + end + get ':id/pipeline_schedules/:pipeline_schedule_id' do + authenticate! + authorize! :read_pipeline_schedule, user_project + + pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) + return not_found!('PipelineSchedule') unless pipeline_schedule + + present pipeline_schedule, with: Entities::PipelineSchedule + end + + desc 'Create a pipeline_schedule' do + success Entities::PipelineSchedule + end + params do + requires :description, type: String, desc: 'The pipeline_schedule description' + requires :ref, type: String, desc: 'The pipeline_schedule ref' + requires :cron, type: String, desc: 'The pipeline_schedule cron' + requires :cron_timezone, type: String, desc: 'The pipeline_schedule cron_timezone' + requires :active, type: Boolean, desc: 'The pipeline_schedule active' + end + post ':id/pipeline_schedules' do + authenticate! + authorize! :create_pipeline_schedule, user_project + + pipeline_schedule = user_project.pipeline_schedules.create( + declared_params(include_missing: false).merge(owner: current_user)) + + if pipeline_schedule.valid? + present pipeline_schedule, with: Entities::PipelineSchedule + else + render_validation_error!(pipeline_schedule) + end + end + + desc 'Update a pipeline_schedule' do + success Entities::PipelineSchedule + end + params do + requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline_schedule ID' + optional :description, type: String, desc: 'The pipeline_schedule description' + optional :ref, type: String, desc: 'The pipeline_schedule ref' + optional :cron, type: String, desc: 'The pipeline_schedule cron' + optional :cron_timezone, type: String, desc: 'The pipeline_schedule cron_timezone' + optional :active, type: Boolean, desc: 'The pipeline_schedule active' + end + put ':id/pipeline_schedules/:pipeline_schedule_id' do + authenticate! + authorize! :create_pipeline_schedule, user_project + + pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) + return not_found!('PipelineSchedule') unless pipeline_schedule + + if pipeline_schedule.update(declared_params(include_missing: false)) + present pipeline_schedule, with: Entities::PipelineSchedule + else + render_validation_error!(pipeline_schedule) + end + end + + desc 'Take ownership of pipeline_schedule' do + success Entities::PipelineSchedule + end + params do + requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline_schedule ID' + end + post ':id/pipeline_schedules/:pipeline_schedule_id/take_ownership' do + authenticate! + authorize! :create_pipeline_schedule, user_project + + pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) + return not_found!('PipelineSchedule') unless pipeline_schedule + + if pipeline_schedule.update(owner: current_user) + status :ok + present pipeline_schedule, with: Entities::PipelineSchedule + else + render_validation_error!(pipeline_schedule) + end + end + + desc 'Delete a pipeline_schedule' do + success Entities::PipelineSchedule + end + params do + requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline_schedule ID' + end + delete ':id/pipeline_schedules/:pipeline_schedule_id' do + authenticate! + authorize! :admin_pipeline_schedule, user_project + + pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) + return not_found!('PipelineSchedule') unless pipeline_schedule + + present pipeline_schedule.destroy, with: Entities::PipelineSchedule + end + end + end +end -- cgit v1.2.3 From 0a11ab48993d092bd730af9b378fbf665b255625 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 13 May 2017 01:48:34 +0900 Subject: Reflect doc to api desc --- lib/api/pipeline_schedules.rb | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 32fa5a86fab..5b3af090e2b 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -6,7 +6,7 @@ module API requires :id, type: String, desc: 'The ID of a project' end resource :projects, requirements: { id: %r{[^/]+} } do - desc 'Get pipeline_schedules list' do + desc 'Get a list of pipeline schedules' do success Entities::PipelineSchedule end params do @@ -21,11 +21,11 @@ module API present paginate(pipeline_schedules), with: Entities::PipelineSchedule end - desc 'Get specific pipeline_schedule of a project' do + desc 'Get a single pipeline schedule' do success Entities::PipelineSchedule end params do - requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline_schedule ID' + requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' end get ':id/pipeline_schedules/:pipeline_schedule_id' do authenticate! @@ -37,15 +37,15 @@ module API present pipeline_schedule, with: Entities::PipelineSchedule end - desc 'Create a pipeline_schedule' do + desc 'Creates a new pipeline schedule' do success Entities::PipelineSchedule end params do - requires :description, type: String, desc: 'The pipeline_schedule description' - requires :ref, type: String, desc: 'The pipeline_schedule ref' - requires :cron, type: String, desc: 'The pipeline_schedule cron' - requires :cron_timezone, type: String, desc: 'The pipeline_schedule cron_timezone' - requires :active, type: Boolean, desc: 'The pipeline_schedule active' + requires :description, type: String, desc: 'The description of pipeline schedule' + requires :ref, type: String, desc: 'The branch/tag name will be triggered' + requires :cron, type: String, desc: 'The cron' + requires :cron_timezone, type: String, desc: 'The timezone' + requires :active, type: Boolean, desc: 'The activation of pipeline schedule' end post ':id/pipeline_schedules' do authenticate! @@ -61,16 +61,16 @@ module API end end - desc 'Update a pipeline_schedule' do + desc 'Updates an existing pipeline schedule' do success Entities::PipelineSchedule end params do - requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline_schedule ID' - optional :description, type: String, desc: 'The pipeline_schedule description' - optional :ref, type: String, desc: 'The pipeline_schedule ref' - optional :cron, type: String, desc: 'The pipeline_schedule cron' - optional :cron_timezone, type: String, desc: 'The pipeline_schedule cron_timezone' - optional :active, type: Boolean, desc: 'The pipeline_schedule active' + requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' + optional :description, type: String, desc: 'The description of pipeline schedule' + optional :ref, type: String, desc: 'The branch/tag name will be triggered' + optional :cron, type: String, desc: 'The cron' + optional :cron_timezone, type: String, desc: 'The timezone' + optional :active, type: Boolean, desc: 'The activation of pipeline schedule' end put ':id/pipeline_schedules/:pipeline_schedule_id' do authenticate! @@ -86,11 +86,11 @@ module API end end - desc 'Take ownership of pipeline_schedule' do + desc 'Update an owner of a pipeline schedule' do success Entities::PipelineSchedule end params do - requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline_schedule ID' + requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' end post ':id/pipeline_schedules/:pipeline_schedule_id/take_ownership' do authenticate! @@ -107,11 +107,11 @@ module API end end - desc 'Delete a pipeline_schedule' do + desc 'Delete a pipeline schedule' do success Entities::PipelineSchedule end params do - requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline_schedule ID' + requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' end delete ':id/pipeline_schedules/:pipeline_schedule_id' do authenticate! -- cgit v1.2.3 From 97bf2401991ab2e9cea956dfb7c9630e2a185683 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 13 May 2017 03:06:05 +0900 Subject: Remove if from last_pipeline in entity --- lib/api/entities.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 1f1942b2ec1..b2bc0a17142 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -690,7 +690,7 @@ module API expose :id expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active expose :created_at, :updated_at, :deleted_at - expose :last_pipeline, using: Entities::Pipeline, if: -> (pipeline_schedule, opts) { pipeline_schedule.last_pipeline.present? } + expose :last_pipeline, using: Entities::Pipeline expose :owner, using: Entities::UserBasic end -- cgit v1.2.3 From 8743f765abc2281c664792f5016747f54d0fb7aa Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 13 May 2017 03:10:16 +0900 Subject: Use CreatePipelineScheduleService --- lib/api/pipeline_schedules.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 5b3af090e2b..6e6bbb29e3a 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -51,8 +51,9 @@ module API authenticate! authorize! :create_pipeline_schedule, user_project - pipeline_schedule = user_project.pipeline_schedules.create( - declared_params(include_missing: false).merge(owner: current_user)) + pipeline_schedule = Ci::CreatePipelineScheduleService + .new(user_project, current_user, declared_params(include_missing: false)) + .execute if pipeline_schedule.valid? present pipeline_schedule, with: Entities::PipelineSchedule -- cgit v1.2.3 From f8cb5fd65a8ed00f38368a6a050c940e72cc6f3e Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 13 May 2017 03:37:09 +0900 Subject: Add own! method on PipleineSchedule --- lib/api/pipeline_schedules.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 6e6bbb29e3a..81b88b17041 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -100,7 +100,7 @@ module API pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) return not_found!('PipelineSchedule') unless pipeline_schedule - if pipeline_schedule.update(owner: current_user) + if pipeline_schedule.own!(current_user) status :ok present pipeline_schedule, with: Entities::PipelineSchedule else -- cgit v1.2.3 From a104e7a2c92d9752e48b2ac776b547809b0036d5 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Tue, 16 May 2017 23:58:08 +0900 Subject: Move authenticate! to before --- lib/api/pipeline_schedules.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 81b88b17041..2319ff639e5 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -2,6 +2,8 @@ module API class PipelineSchedules < Grape::API include PaginationParams + before { authenticate! } + params do requires :id, type: String, desc: 'The ID of a project' end @@ -13,7 +15,6 @@ module API use :pagination end get ':id/pipeline_schedules' do - authenticate! authorize! :read_pipeline_schedule, user_project pipeline_schedules = user_project.pipeline_schedules @@ -28,7 +29,6 @@ module API requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' end get ':id/pipeline_schedules/:pipeline_schedule_id' do - authenticate! authorize! :read_pipeline_schedule, user_project pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) @@ -48,7 +48,6 @@ module API requires :active, type: Boolean, desc: 'The activation of pipeline schedule' end post ':id/pipeline_schedules' do - authenticate! authorize! :create_pipeline_schedule, user_project pipeline_schedule = Ci::CreatePipelineScheduleService @@ -74,7 +73,6 @@ module API optional :active, type: Boolean, desc: 'The activation of pipeline schedule' end put ':id/pipeline_schedules/:pipeline_schedule_id' do - authenticate! authorize! :create_pipeline_schedule, user_project pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) @@ -94,7 +92,6 @@ module API requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' end post ':id/pipeline_schedules/:pipeline_schedule_id/take_ownership' do - authenticate! authorize! :create_pipeline_schedule, user_project pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) @@ -115,7 +112,6 @@ module API requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' end delete ':id/pipeline_schedules/:pipeline_schedule_id' do - authenticate! authorize! :admin_pipeline_schedule, user_project pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) -- cgit v1.2.3 From 94f7595b9a8edcb4ac8480995a067eb4fa3dec7e Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 00:20:11 +0900 Subject: Define last_pipeline in PipelineScheduleEntity --- lib/api/entities.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index b2bc0a17142..93f28e39f82 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -690,7 +690,9 @@ module API expose :id expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active expose :created_at, :updated_at, :deleted_at - expose :last_pipeline, using: Entities::Pipeline + expose :last_pipeline, using: Entities::Pipeline do |pipeline_schedule| + pipeline_schedule.pipelines&.last + end expose :owner, using: Entities::UserBasic end -- cgit v1.2.3 From e828e835e435deab8a62c7c999dca0b774e7a7d6 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 01:33:09 +0900 Subject: avoids N + 1 queries --- lib/api/pipeline_schedules.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 2319ff639e5..9429306fe20 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -17,7 +17,7 @@ module API get ':id/pipeline_schedules' do authorize! :read_pipeline_schedule, user_project - pipeline_schedules = user_project.pipeline_schedules + pipeline_schedules = user_project.pipeline_schedules.preload(:pipelines) present paginate(pipeline_schedules), with: Entities::PipelineSchedule end -- cgit v1.2.3 From df6040bbd41a639b3d0aa339b2dc0e84d67b811b Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 21:26:18 +0900 Subject: zj keen eye2 --- lib/api/pipeline_schedules.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 9429306fe20..58888417888 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -54,7 +54,7 @@ module API .new(user_project, current_user, declared_params(include_missing: false)) .execute - if pipeline_schedule.valid? + if pipeline_schedule.persisted? present pipeline_schedule, with: Entities::PipelineSchedule else render_validation_error!(pipeline_schedule) @@ -98,7 +98,6 @@ module API return not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.own!(current_user) - status :ok present pipeline_schedule, with: Entities::PipelineSchedule else render_validation_error!(pipeline_schedule) -- cgit v1.2.3 From 17b9128b305aefc29fddae3b51d13c61ae7dfef9 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 17 May 2017 22:58:23 +0900 Subject: includes last_pipeline --- lib/api/entities.rb | 4 +--- lib/api/pipeline_schedules.rb | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 93f28e39f82..b2bc0a17142 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -690,9 +690,7 @@ module API expose :id expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active expose :created_at, :updated_at, :deleted_at - expose :last_pipeline, using: Entities::Pipeline do |pipeline_schedule| - pipeline_schedule.pipelines&.last - end + expose :last_pipeline, using: Entities::Pipeline expose :owner, using: Entities::UserBasic end diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 58888417888..27be796356c 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -17,7 +17,7 @@ module API get ':id/pipeline_schedules' do authorize! :read_pipeline_schedule, user_project - pipeline_schedules = user_project.pipeline_schedules.preload(:pipelines) + pipeline_schedules = user_project.pipeline_schedules.includes(last_pipeline: {statuses: :latest}) present paginate(pipeline_schedules), with: Entities::PipelineSchedule end -- cgit v1.2.3 From 20a07d26ff4be9c82271297e516df912109b05aa Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 18 May 2017 17:45:08 +0900 Subject: Include owner for pipeline_schedules. Improve N+1 spec. Use PipelineBasic for small payload. --- lib/api/entities.rb | 2 +- lib/api/pipeline_schedules.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index b2bc0a17142..f0260cf03f3 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -690,7 +690,7 @@ module API expose :id expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active expose :created_at, :updated_at, :deleted_at - expose :last_pipeline, using: Entities::Pipeline + expose :last_pipeline, using: Entities::PipelineBasic expose :owner, using: Entities::UserBasic end diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 27be796356c..c6c22f6e518 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -17,7 +17,7 @@ module API get ':id/pipeline_schedules' do authorize! :read_pipeline_schedule, user_project - pipeline_schedules = user_project.pipeline_schedules.includes(last_pipeline: {statuses: :latest}) + pipeline_schedules = user_project.pipeline_schedules.includes([:owner, last_pipeline: {statuses: :latest}]) present paginate(pipeline_schedules), with: Entities::PipelineSchedule end -- cgit v1.2.3 From 8c40bbbe7d0d1bb930a590f5ca98570bd32ad1f0 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 18 May 2017 17:58:55 +0900 Subject: Switch to preload. Remove unncecessary associations. --- lib/api/pipeline_schedules.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index c6c22f6e518..3b9d5b0d7a6 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -17,7 +17,7 @@ module API get ':id/pipeline_schedules' do authorize! :read_pipeline_schedule, user_project - pipeline_schedules = user_project.pipeline_schedules.includes([:owner, last_pipeline: {statuses: :latest}]) + pipeline_schedules = user_project.pipeline_schedules.preload([:owner, :last_pipeline]) present paginate(pipeline_schedules), with: Entities::PipelineSchedule end -- cgit v1.2.3 From 92bc1ddaf5a256a5e6636bc4a6f8ebd8673ec719 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Thu, 18 May 2017 18:22:41 +0900 Subject: Dryup fetching pipeline_schedule with helper --- lib/api/pipeline_schedules.rb | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 3b9d5b0d7a6..454237d3fbb 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -17,8 +17,6 @@ module API get ':id/pipeline_schedules' do authorize! :read_pipeline_schedule, user_project - pipeline_schedules = user_project.pipeline_schedules.preload([:owner, :last_pipeline]) - present paginate(pipeline_schedules), with: Entities::PipelineSchedule end @@ -31,7 +29,6 @@ module API get ':id/pipeline_schedules/:pipeline_schedule_id' do authorize! :read_pipeline_schedule, user_project - pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) return not_found!('PipelineSchedule') unless pipeline_schedule present pipeline_schedule, with: Entities::PipelineSchedule @@ -75,7 +72,6 @@ module API put ':id/pipeline_schedules/:pipeline_schedule_id' do authorize! :create_pipeline_schedule, user_project - pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) return not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.update(declared_params(include_missing: false)) @@ -94,7 +90,6 @@ module API post ':id/pipeline_schedules/:pipeline_schedule_id/take_ownership' do authorize! :create_pipeline_schedule, user_project - pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) return not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.own!(current_user) @@ -113,11 +108,24 @@ module API delete ':id/pipeline_schedules/:pipeline_schedule_id' do authorize! :admin_pipeline_schedule, user_project - pipeline_schedule = user_project.pipeline_schedules.find(params.delete(:pipeline_schedule_id)) return not_found!('PipelineSchedule') unless pipeline_schedule present pipeline_schedule.destroy, with: Entities::PipelineSchedule end end + + helpers do + def pipeline_schedules + @pipeline_schedules ||= + user_project.pipeline_schedules.preload([:owner, :last_pipeline]) + end + + def pipeline_schedule + @pipeline_schedule ||= + user_project.pipeline_schedules + .preload([:owner, :last_pipeline]) + .find(params.delete(:pipeline_schedule_id)) + end + end end end -- cgit v1.2.3 From f6a8894a5928e1cc37d8301c555fcfd5953cc180 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 19 May 2017 02:42:23 +0900 Subject: Expose last_pipeline only when detailed status --- lib/api/entities.rb | 2 +- lib/api/pipeline_schedules.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index f0260cf03f3..d779cd2a294 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -690,7 +690,7 @@ module API expose :id expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active expose :created_at, :updated_at, :deleted_at - expose :last_pipeline, using: Entities::PipelineBasic + expose :last_pipeline, using: Entities::PipelineBasic, if: { type: :full } expose :owner, using: Entities::UserBasic end diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 454237d3fbb..c013d6f316b 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -31,7 +31,7 @@ module API return not_found!('PipelineSchedule') unless pipeline_schedule - present pipeline_schedule, with: Entities::PipelineSchedule + present pipeline_schedule, with: Entities::PipelineSchedule, type: :full end desc 'Creates a new pipeline schedule' do @@ -52,7 +52,7 @@ module API .execute if pipeline_schedule.persisted? - present pipeline_schedule, with: Entities::PipelineSchedule + present pipeline_schedule, with: Entities::PipelineSchedule, type: :full else render_validation_error!(pipeline_schedule) end @@ -75,7 +75,7 @@ module API return not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.update(declared_params(include_missing: false)) - present pipeline_schedule, with: Entities::PipelineSchedule + present pipeline_schedule, with: Entities::PipelineSchedule, type: :full else render_validation_error!(pipeline_schedule) end @@ -93,7 +93,7 @@ module API return not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.own!(current_user) - present pipeline_schedule, with: Entities::PipelineSchedule + present pipeline_schedule, with: Entities::PipelineSchedule, type: :full else render_validation_error!(pipeline_schedule) end @@ -110,7 +110,7 @@ module API return not_found!('PipelineSchedule') unless pipeline_schedule - present pipeline_schedule.destroy, with: Entities::PipelineSchedule + present pipeline_schedule.destroy, with: Entities::PipelineSchedule, type: :full end end -- cgit v1.2.3 From bfa028e13a41b16b0da2d69359694edbebf9e455 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Fri, 19 May 2017 22:24:31 +0900 Subject: Remove deleted_at from Entity. Use find_by. Remove returns. --- lib/api/entities.rb | 2 +- lib/api/pipeline_schedules.rb | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index d779cd2a294..40ef62fdb14 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -689,7 +689,7 @@ module API class PipelineSchedule < Grape::Entity expose :id expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active - expose :created_at, :updated_at, :deleted_at + expose :created_at, :updated_at expose :last_pipeline, using: Entities::PipelineBasic, if: { type: :full } expose :owner, using: Entities::UserBasic end diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index c013d6f316b..367f6e2fbab 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -29,7 +29,7 @@ module API get ':id/pipeline_schedules/:pipeline_schedule_id' do authorize! :read_pipeline_schedule, user_project - return not_found!('PipelineSchedule') unless pipeline_schedule + not_found!('PipelineSchedule') unless pipeline_schedule present pipeline_schedule, with: Entities::PipelineSchedule, type: :full end @@ -72,7 +72,7 @@ module API put ':id/pipeline_schedules/:pipeline_schedule_id' do authorize! :create_pipeline_schedule, user_project - return not_found!('PipelineSchedule') unless pipeline_schedule + not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.update(declared_params(include_missing: false)) present pipeline_schedule, with: Entities::PipelineSchedule, type: :full @@ -90,7 +90,7 @@ module API post ':id/pipeline_schedules/:pipeline_schedule_id/take_ownership' do authorize! :create_pipeline_schedule, user_project - return not_found!('PipelineSchedule') unless pipeline_schedule + not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.own!(current_user) present pipeline_schedule, with: Entities::PipelineSchedule, type: :full @@ -108,7 +108,7 @@ module API delete ':id/pipeline_schedules/:pipeline_schedule_id' do authorize! :admin_pipeline_schedule, user_project - return not_found!('PipelineSchedule') unless pipeline_schedule + not_found!('PipelineSchedule') unless pipeline_schedule present pipeline_schedule.destroy, with: Entities::PipelineSchedule, type: :full end @@ -124,7 +124,7 @@ module API @pipeline_schedule ||= user_project.pipeline_schedules .preload([:owner, :last_pipeline]) - .find(params.delete(:pipeline_schedule_id)) + .find_by(id: params.delete(:pipeline_schedule_id)) end end end -- cgit v1.2.3 From c91292b61f80626b91d41cc17d0a662f302d6ecd Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 24 May 2017 19:25:13 +0900 Subject: Improve document --- lib/api/pipeline_schedules.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 367f6e2fbab..4b7dd487186 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -8,7 +8,7 @@ module API requires :id, type: String, desc: 'The ID of a project' end resource :projects, requirements: { id: %r{[^/]+} } do - desc 'Get a list of pipeline schedules' do + desc 'Get all pipeline schedules' do success Entities::PipelineSchedule end params do @@ -34,7 +34,7 @@ module API present pipeline_schedule, with: Entities::PipelineSchedule, type: :full end - desc 'Creates a new pipeline schedule' do + desc 'Create a new pipeline schedule' do success Entities::PipelineSchedule end params do @@ -58,7 +58,7 @@ module API end end - desc 'Updates an existing pipeline schedule' do + desc 'Edit a pipeline schedule' do success Entities::PipelineSchedule end params do @@ -81,7 +81,7 @@ module API end end - desc 'Update an owner of a pipeline schedule' do + desc 'Take ownership of a pipeline schedule' do success Entities::PipelineSchedule end params do -- cgit v1.2.3 From b17c8d67d8811e0a440338dc25464d8c90e81179 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 27 May 2017 21:29:01 +0900 Subject: Use PipelineScheduleDetails --- lib/api/entities.rb | 5 ++++- lib/api/pipeline_schedules.rb | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 40ef62fdb14..e10bd230ae2 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -690,10 +690,13 @@ module API expose :id expose :description, :ref, :cron, :cron_timezone, :next_run_at, :active expose :created_at, :updated_at - expose :last_pipeline, using: Entities::PipelineBasic, if: { type: :full } expose :owner, using: Entities::UserBasic end + class PipelineScheduleDetails < PipelineSchedule + expose :last_pipeline, using: Entities::PipelineBasic + end + class EnvironmentBasic < Grape::Entity expose :id, :name, :slug, :external_url end diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 4b7dd487186..5269239b7ed 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -21,7 +21,7 @@ module API end desc 'Get a single pipeline schedule' do - success Entities::PipelineSchedule + success Entities::PipelineScheduleDetails end params do requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' @@ -31,11 +31,11 @@ module API not_found!('PipelineSchedule') unless pipeline_schedule - present pipeline_schedule, with: Entities::PipelineSchedule, type: :full + present pipeline_schedule, with: Entities::PipelineScheduleDetails end desc 'Create a new pipeline schedule' do - success Entities::PipelineSchedule + success Entities::PipelineScheduleDetails end params do requires :description, type: String, desc: 'The description of pipeline schedule' @@ -52,14 +52,14 @@ module API .execute if pipeline_schedule.persisted? - present pipeline_schedule, with: Entities::PipelineSchedule, type: :full + present pipeline_schedule, with: Entities::PipelineScheduleDetails else render_validation_error!(pipeline_schedule) end end desc 'Edit a pipeline schedule' do - success Entities::PipelineSchedule + success Entities::PipelineScheduleDetails end params do requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' @@ -75,14 +75,14 @@ module API not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.update(declared_params(include_missing: false)) - present pipeline_schedule, with: Entities::PipelineSchedule, type: :full + present pipeline_schedule, with: Entities::PipelineScheduleDetails else render_validation_error!(pipeline_schedule) end end desc 'Take ownership of a pipeline schedule' do - success Entities::PipelineSchedule + success Entities::PipelineScheduleDetails end params do requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' @@ -93,14 +93,14 @@ module API not_found!('PipelineSchedule') unless pipeline_schedule if pipeline_schedule.own!(current_user) - present pipeline_schedule, with: Entities::PipelineSchedule, type: :full + present pipeline_schedule, with: Entities::PipelineScheduleDetails else render_validation_error!(pipeline_schedule) end end desc 'Delete a pipeline schedule' do - success Entities::PipelineSchedule + success Entities::PipelineScheduleDetails end params do requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' @@ -110,7 +110,7 @@ module API not_found!('PipelineSchedule') unless pipeline_schedule - present pipeline_schedule.destroy, with: Entities::PipelineSchedule, type: :full + present pipeline_schedule.destroy, with: Entities::PipelineScheduleDetails end end -- cgit v1.2.3 From 63ca126e977666335d7e5f70665815d1289a6f34 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 27 May 2017 22:22:33 +0900 Subject: Improve API with optinal and default. Allow to use scope as a parameter. --- lib/api/pipeline_schedules.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 5269239b7ed..52ad682b972 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -13,11 +13,15 @@ module API end params do use :pagination + optional :scope, type: String, values: %w[active inactive], + desc: 'The scope of pipeline schedules' end get ':id/pipeline_schedules' do authorize! :read_pipeline_schedule, user_project - present paginate(pipeline_schedules), with: Entities::PipelineSchedule + schedules = PipelineSchedulesFinder.new(user_project).execute(scope: params[:scope]) + .preload([:owner, :last_pipeline]) + present paginate(schedules), with: Entities::PipelineSchedule end desc 'Get a single pipeline schedule' do @@ -41,8 +45,8 @@ module API requires :description, type: String, desc: 'The description of pipeline schedule' requires :ref, type: String, desc: 'The branch/tag name will be triggered' requires :cron, type: String, desc: 'The cron' - requires :cron_timezone, type: String, desc: 'The timezone' - requires :active, type: Boolean, desc: 'The activation of pipeline schedule' + optional :cron_timezone, type: String, default: 'UTC', desc: 'The timezone' + optional :active, type: Boolean, default: true, desc: 'The activation of pipeline schedule' end post ':id/pipeline_schedules' do authorize! :create_pipeline_schedule, user_project -- cgit v1.2.3 From 3b61451c46f462b392783b282fe63dbddd8b6c2e Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Sat, 27 May 2017 22:31:22 +0900 Subject: Return 202 for destory. Remove []. Remove def pipeline_schedules from helper. --- lib/api/pipeline_schedules.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 52ad682b972..d9509375698 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -114,20 +114,16 @@ module API not_found!('PipelineSchedule') unless pipeline_schedule + status :accepted present pipeline_schedule.destroy, with: Entities::PipelineScheduleDetails end end helpers do - def pipeline_schedules - @pipeline_schedules ||= - user_project.pipeline_schedules.preload([:owner, :last_pipeline]) - end - def pipeline_schedule @pipeline_schedule ||= user_project.pipeline_schedules - .preload([:owner, :last_pipeline]) + .preload(:owner, :last_pipeline) .find_by(id: params.delete(:pipeline_schedule_id)) end end -- cgit v1.2.3 From 2da420be04ae1fa00b06149c0293a0349a085e99 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 31 May 2017 00:06:37 +0900 Subject: Use update_pipeline_schedule --- lib/api/pipeline_schedules.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index d9509375698..93d89209934 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -74,7 +74,7 @@ module API optional :active, type: Boolean, desc: 'The activation of pipeline schedule' end put ':id/pipeline_schedules/:pipeline_schedule_id' do - authorize! :create_pipeline_schedule, user_project + authorize! :update_pipeline_schedule, user_project not_found!('PipelineSchedule') unless pipeline_schedule @@ -92,7 +92,7 @@ module API requires :pipeline_schedule_id, type: Integer, desc: 'The pipeline schedule id' end post ':id/pipeline_schedules/:pipeline_schedule_id/take_ownership' do - authorize! :create_pipeline_schedule, user_project + authorize! :update_pipeline_schedule, user_project not_found!('PipelineSchedule') unless pipeline_schedule -- cgit v1.2.3 From d9461314ada3135593a53ba61a73dd695ee3a38d Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 30 May 2017 14:50:02 -0500 Subject: Fix Diff#to_hash and #init_from_hash --- lib/gitlab/git/diff.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index 201a115503b..e33fe4b305a 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -17,6 +17,9 @@ module Gitlab attr_accessor :expanded + # We need this accessor because of `to_hash` and `init_from_hash` + attr_accessor :too_large + # The maximum size of a diff to display. SIZE_LIMIT = 100.kilobytes -- cgit v1.2.3 From 98043aeedf1fe3241d8362d8036f28b709e6d468 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Mon, 22 May 2017 16:42:10 +0200 Subject: Copy `filter_projects` helper to V3 The helper will be modified in V4, so copy the original to V4 to keep the current behavior in V3. --- lib/api/v3/helpers.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'lib') diff --git a/lib/api/v3/helpers.rb b/lib/api/v3/helpers.rb index 0f234d4cdad..06af286ef50 100644 --- a/lib/api/v3/helpers.rb +++ b/lib/api/v3/helpers.rb @@ -14,6 +14,33 @@ module API authorize! access_level, merge_request merge_request end + + # project helpers + + def filter_projects(projects) + if params[:membership] + projects = projects.merge(current_user.authorized_projects) + end + + if params[:owned] + projects = projects.merge(current_user.owned_projects) + end + + if params[:starred] + projects = projects.merge(current_user.starred_projects) + end + + if params[:search].present? + projects = projects.search(params[:search]) + end + + if params[:visibility].present? + projects = projects.search_by_visibility(params[:visibility]) + end + + projects = projects.where(archived: params[:archived]) + projects.reorder(params[:order_by] => params[:sort]) + end end end end -- cgit v1.2.3 From 44fdf0a1e314da517d189e356b0e44bb63cf0f4b Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Mon, 22 May 2017 16:47:16 +0200 Subject: Move ProjectsFinder to `present_projects` for simplification To avoid passing parameters double, move all filtering to the `present_projects` helper. --- lib/api/projects.rb | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/api/projects.rb b/lib/api/projects.rb index d4fe5c023bf..fce496308c3 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -67,20 +67,18 @@ module API optional :import_url, type: String, desc: 'URL from which the project is imported' end - def present_projects(projects, options = {}) + def present_projects(options = {}) options = options.reverse_merge( - with: Entities::Project, - current_user: current_user, - simple: params[:simple], - with_issues_enabled: params[:with_issues_enabled], - with_merge_requests_enabled: params[:with_merge_requests_enabled] + with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails, + current_user: current_user ) + projects = ProjectsFinder.new(current_user: current_user).execute projects = filter_projects(projects) - projects = projects.with_statistics if options[:statistics] - projects = projects.with_issues_enabled if options[:with_issues_enabled] - projects = projects.with_merge_requests_enabled if options[:with_merge_requests_enabled] - options[:with] = Entities::BasicProjectDetails if options[:simple] + projects = projects.with_statistics if params[:statistics] + projects = projects.with_issues_enabled if params[:with_issues_enabled] + projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled] + options[:with] = Entities::BasicProjectDetails if params[:simple] present paginate(projects), options end @@ -94,8 +92,7 @@ module API use :statistics_params end get do - entity = current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails - present_projects ProjectsFinder.new(current_user: current_user).execute, with: entity, statistics: params[:statistics] + present_projects end desc 'Create new project' do -- cgit v1.2.3 From 4fda13b68eb7da27be5e74cac6d3d537502b19f7 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Mon, 22 May 2017 16:48:38 +0200 Subject: Build options hash after finding the list of projects Because this order makes more sense and makes the code easier to read. --- lib/api/projects.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/api/projects.rb b/lib/api/projects.rb index fce496308c3..ef09dfa0102 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -68,16 +68,17 @@ module API end def present_projects(options = {}) - options = options.reverse_merge( - with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails, - current_user: current_user - ) - projects = ProjectsFinder.new(current_user: current_user).execute projects = filter_projects(projects) projects = projects.with_statistics if params[:statistics] projects = projects.with_issues_enabled if params[:with_issues_enabled] projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled] + + options = options.reverse_merge( + with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails, + statistics: params[:statistics], + current_user: current_user + ) options[:with] = Entities::BasicProjectDetails if params[:simple] present paginate(projects), options -- cgit v1.2.3 From 07fc79e7c53a4fa7c4dd33835b905dfa8a609ff8 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Tue, 23 May 2017 15:48:13 +0200 Subject: Handle `membership` in ProjectFinder The ProjectFinder supports the `non_public` parameter. This can be used to find only projects the user is member of. --- lib/api/helpers.rb | 4 ---- lib/api/projects.rb | 5 ++++- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 226a7ddd50e..0dc33eb2097 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -257,10 +257,6 @@ module API # project helpers def filter_projects(projects) - if params[:membership] - projects = projects.merge(current_user.authorized_projects) - end - if params[:owned] projects = projects.merge(current_user.owned_projects) end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index ef09dfa0102..bb03480f1ee 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -68,7 +68,10 @@ module API end def present_projects(options = {}) - projects = ProjectsFinder.new(current_user: current_user).execute + finder_params = {} + finder_params[:non_public] = true if params[:membership].present? + + projects = ProjectsFinder.new(current_user: current_user, params: finder_params).execute projects = filter_projects(projects) projects = projects.with_statistics if params[:statistics] projects = projects.with_issues_enabled if params[:with_issues_enabled] -- cgit v1.2.3 From a1deed629e03d8db47deb1bcf795ae8abaf2c847 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Tue, 23 May 2017 22:40:39 +0200 Subject: Use ProjectFinder to filter the projects Instead of trying to do the heavy lifting in the API itself, use the existing features of the ProjectFinder. --- lib/api/helpers.rb | 13 ------------- lib/api/projects.rb | 4 ++++ 2 files changed, 4 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 0dc33eb2097..2855bd7385d 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -261,19 +261,6 @@ module API projects = projects.merge(current_user.owned_projects) end - if params[:starred] - projects = projects.merge(current_user.starred_projects) - end - - if params[:search].present? - projects = projects.search(params[:search]) - end - - if params[:visibility].present? - projects = projects.search_by_visibility(params[:visibility]) - end - - projects = projects.where(archived: params[:archived]) projects.reorder(params[:order_by] => params[:sort]) end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index bb03480f1ee..7610e3cbacc 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -70,6 +70,10 @@ module API def present_projects(options = {}) finder_params = {} finder_params[:non_public] = true if params[:membership].present? + finder_params[:starred] = true if params[:starred].present? + finder_params[:visibility_level] = Gitlab::VisibilityLevel.level_value(params[:visibility]) if params[:visibility] + finder_params[:archived] = params[:archived] + finder_params[:search] = params[:search] if params[:search] projects = ProjectsFinder.new(current_user: current_user, params: finder_params).execute projects = filter_projects(projects) -- cgit v1.2.3 From 0f0b9a8466747f69e210fc27778f96ab8ef628bc Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Wed, 24 May 2017 22:12:40 +0200 Subject: Use helper to construct Finder params The ProjectsFinder and GroupFinder both support the same set of params. And the `/api/v4/projects` and `/api/v4/group/:id/projects` also support the same set of params. But they do not match the Finder params. So use a helper method to transform them. --- lib/api/groups.rb | 2 +- lib/api/helpers.rb | 10 ++++++++++ lib/api/projects.rb | 9 +-------- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/api/groups.rb b/lib/api/groups.rb index ee85b777aff..aacc3356a0e 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -151,7 +151,7 @@ module API end get ":id/projects" do group = find_group!(params[:id]) - projects = GroupProjectsFinder.new(group: group, current_user: current_user).execute + projects = GroupProjectsFinder.new(group: group, current_user: current_user, params: project_finder_params).execute projects = filter_projects(projects) entity = params[:simple] ? Entities::BasicProjectDetails : Entities::Project present paginate(projects), with: entity, current_user: current_user diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 2855bd7385d..17f57cfb8d7 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -264,6 +264,16 @@ module API projects.reorder(params[:order_by] => params[:sort]) end + def project_finder_params + finder_params = {} + finder_params[:non_public] = true if params[:membership].present? + finder_params[:starred] = true if params[:starred].present? + finder_params[:visibility_level] = Gitlab::VisibilityLevel.level_value(params[:visibility]) if params[:visibility] + finder_params[:archived] = params[:archived] + finder_params[:search] = params[:search] if params[:search] + finder_params + end + # file helpers def uploaded_file(field, uploads_path) diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 7610e3cbacc..267dd2a74d7 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -68,14 +68,7 @@ module API end def present_projects(options = {}) - finder_params = {} - finder_params[:non_public] = true if params[:membership].present? - finder_params[:starred] = true if params[:starred].present? - finder_params[:visibility_level] = Gitlab::VisibilityLevel.level_value(params[:visibility]) if params[:visibility] - finder_params[:archived] = params[:archived] - finder_params[:search] = params[:search] if params[:search] - - projects = ProjectsFinder.new(current_user: current_user, params: finder_params).execute + projects = ProjectsFinder.new(current_user: current_user, params: project_finder_params).execute projects = filter_projects(projects) projects = projects.with_statistics if params[:statistics] projects = projects.with_issues_enabled if params[:with_issues_enabled] -- cgit v1.2.3 From db679788e46d55984a4af71034c6db11aed919e4 Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Fri, 26 May 2017 16:31:37 +0200 Subject: Add :owned param to ProjectFinder And use it in the API. --- lib/api/groups.rb | 2 +- lib/api/helpers.rb | 7 ++----- lib/api/projects.rb | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/api/groups.rb b/lib/api/groups.rb index aacc3356a0e..e14a988a153 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -152,7 +152,7 @@ module API get ":id/projects" do group = find_group!(params[:id]) projects = GroupProjectsFinder.new(group: group, current_user: current_user, params: project_finder_params).execute - projects = filter_projects(projects) + projects = reorder_projects(projects) entity = params[:simple] ? Entities::BasicProjectDetails : Entities::Project present paginate(projects), with: entity, current_user: current_user end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 17f57cfb8d7..d61450f8258 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -256,16 +256,13 @@ module API # project helpers - def filter_projects(projects) - if params[:owned] - projects = projects.merge(current_user.owned_projects) - end - + def reorder_projects(projects) projects.reorder(params[:order_by] => params[:sort]) end def project_finder_params finder_params = {} + finder_params[:owned] = true if params[:owned].present? finder_params[:non_public] = true if params[:membership].present? finder_params[:starred] = true if params[:starred].present? finder_params[:visibility_level] = Gitlab::VisibilityLevel.level_value(params[:visibility]) if params[:visibility] diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 267dd2a74d7..1356f959e70 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -69,7 +69,7 @@ module API def present_projects(options = {}) projects = ProjectsFinder.new(current_user: current_user, params: project_finder_params).execute - projects = filter_projects(projects) + projects = reorder_projects(projects) projects = projects.with_statistics if params[:statistics] projects = projects.with_issues_enabled if params[:with_issues_enabled] projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled] -- cgit v1.2.3 From 0c7dd30c78043ea3d4629e1e5739ccfcc7d968fe Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 30 May 2017 16:19:29 -0500 Subject: Make .gitmodules parsing more resilient to syntax errors --- lib/gitlab/git/repository.rb | 46 +++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index b9f1ac144b6..c3bf32ca1cc 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1008,25 +1008,34 @@ module Gitlab def parse_gitmodules(commit, content) results = {} - current = "" - content.split("\n").each do |txt| - if txt =~ /^\s*\[/ - current = txt.match(/(?<=").*(?=")/)[0] - results[current] = {} - else - next unless results[current] - match_data = txt.match(/(\w+)\s*=\s*(.*)/) - next unless match_data - target = match_data[2].chomp - results[current][match_data[1]] = target - - if match_data[1] == "path" + name = nil + entry = nil + content.each_line do |line| + case line.strip + when /\A\[submodule "(?[^"]+)"\]\z/ # Submodule header + name = $~[:name] + entry = results[name] = {} + when /\A(?\w+)\s*=\s*(?.*)\z/ # Key/value pair + key = $~[:key] + value = $~[:value].chomp + + next unless name && entry + + entry[key] = value + + if key == 'path' begin - results[current]["id"] = blob_content(commit, target) + entry['id'] = blob_content(commit, value) rescue InvalidBlobName - results.delete(current) + # The current entry is invalid + results.delete(name) + name = entry = nil end end + when /\A#/ # Comment + next + else # Invalid line + name = entry = nil end end @@ -1086,7 +1095,12 @@ module Gitlab elsif tmp_entry.nil? return nil else - tmp_entry = rugged.lookup(tmp_entry[:oid]) + begin + tmp_entry = rugged.lookup(tmp_entry[:oid]) + rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError + return nil + end + return nil unless tmp_entry.type == :tree tmp_entry = tmp_entry[dir] end -- cgit v1.2.3 From 1e5506d01619780da68fc51ada58188a9070255b Mon Sep 17 00:00:00 2001 From: Toon Claes Date: Tue, 30 May 2017 23:24:17 +0200 Subject: Remove some deprecated methods To avoid the use of slow queries, remove some deprecated methods and encourage the use of ProjectFinder to find projects. --- lib/api/v3/helpers.rb | 2 +- lib/api/v3/projects.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/v3/helpers.rb b/lib/api/v3/helpers.rb index 06af286ef50..d9e76560d03 100644 --- a/lib/api/v3/helpers.rb +++ b/lib/api/v3/helpers.rb @@ -35,7 +35,7 @@ module API end if params[:visibility].present? - projects = projects.search_by_visibility(params[:visibility]) + projects = projects.where(visibility_level: Gitlab::VisibilityLevel.level_value(params[:visibility])) end projects = projects.where(archived: params[:archived]) diff --git a/lib/api/v3/projects.rb b/lib/api/v3/projects.rb index 164612cb8dd..896c00b88e7 100644 --- a/lib/api/v3/projects.rb +++ b/lib/api/v3/projects.rb @@ -147,7 +147,7 @@ module API get '/starred' do authenticate! - present_projects current_user.viewable_starred_projects + present_projects ProjectsFinder.new(current_user: current_user, params: { starred: true }).execute end desc 'Get all projects for admin user' do -- cgit v1.2.3 From 04bb8fe9942f8558124f00e8cdfb50ef7059bf9e Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 30 May 2017 16:40:31 -0500 Subject: Return nil when looking up config for unknown LDAP provider --- lib/gitlab/o_auth/provider.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/o_auth/provider.rb b/lib/gitlab/o_auth/provider.rb index 9ad7a38d505..ac9d66c836d 100644 --- a/lib/gitlab/o_auth/provider.rb +++ b/lib/gitlab/o_auth/provider.rb @@ -22,7 +22,11 @@ module Gitlab def self.config_for(name) name = name.to_s if ldap_provider?(name) - Gitlab::LDAP::Config.new(name).options + if Gitlab::LDAP::Config.valid_provider?(name) + Gitlab::LDAP::Config.new(name).options + else + nil + end else Gitlab.config.omniauth.providers.find { |provider| provider.name == name } end -- cgit v1.2.3 From 870a8bbbdd7456af03b5b4159c6dee4941edb759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Tue, 30 May 2017 22:16:43 -0400 Subject: Allow PostReceivePack to be enabled with Gitaly --- lib/gitlab/workhorse.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index fe37e4da94f..18d8b4f4744 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -31,8 +31,7 @@ module Gitlab feature_enabled = case action.to_s when 'git_receive_pack' - # Disabled for now, see https://gitlab.com/gitlab-org/gitaly/issues/172 - false + Gitlab::GitalyClient.feature_enabled?(:post_receive_pack) when 'git_upload_pack' Gitlab::GitalyClient.feature_enabled?(:post_upload_pack) when 'info_refs' -- cgit v1.2.3 From ce869e3964a40b4cf04a803f5201d940ad61b13c Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 30 May 2017 21:48:30 -0500 Subject: Fix Diff#too_large? and specs --- lib/gitlab/git/diff.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index e33fe4b305a..2462f766f17 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -230,9 +230,11 @@ module Gitlab end def too_large? - return @too_large if defined?(@too_large) - - @too_large = @diff.bytesize >= SIZE_LIMIT + if @too_large.nil? + @too_large = @diff.bytesize >= SIZE_LIMIT + else + @too_large + end end def too_large! -- cgit v1.2.3 From 4464c22d6d23d893494682d309aec3fb31c11ae3 Mon Sep 17 00:00:00 2001 From: Jarka Kadlecova Date: Wed, 3 May 2017 17:26:49 +0200 Subject: Support descriptions for snippets --- lib/api/entities.rb | 4 ++-- lib/api/project_snippets.rb | 2 ++ lib/api/snippets.rb | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 8c5e5c91769..22880066d84 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -224,7 +224,7 @@ module API end class ProjectSnippet < Grape::Entity - expose :id, :title, :file_name + expose :id, :title, :file_name, :description expose :author, using: Entities::UserBasic expose :updated_at, :created_at @@ -234,7 +234,7 @@ module API end class PersonalSnippet < Grape::Entity - expose :id, :title, :file_name + expose :id, :title, :file_name, :description expose :author, using: Entities::UserBasic expose :updated_at, :created_at diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb index 98bc9c28527..64efe82a937 100644 --- a/lib/api/project_snippets.rb +++ b/lib/api/project_snippets.rb @@ -49,6 +49,7 @@ module API requires :title, type: String, desc: 'The title of the snippet' requires :file_name, type: String, desc: 'The file name of the snippet' requires :code, type: String, desc: 'The content of the snippet' + optional :description, type: String, desc: 'The description of a snippet' requires :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the snippet' @@ -77,6 +78,7 @@ module API optional :title, type: String, desc: 'The title of the snippet' optional :file_name, type: String, desc: 'The file name of the snippet' optional :code, type: String, desc: 'The content of the snippet' + optional :description, type: String, desc: 'The description of a snippet' optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the snippet' diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb index 53f5953a8fb..c630c24c339 100644 --- a/lib/api/snippets.rb +++ b/lib/api/snippets.rb @@ -58,6 +58,7 @@ module API requires :title, type: String, desc: 'The title of a snippet' requires :file_name, type: String, desc: 'The name of a snippet file' requires :content, type: String, desc: 'The content of a snippet' + optional :description, type: String, desc: 'The description of a snippet' optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, default: 'internal', @@ -85,6 +86,7 @@ module API optional :title, type: String, desc: 'The title of a snippet' optional :file_name, type: String, desc: 'The name of a snippet file' optional :content, type: String, desc: 'The content of a snippet' + optional :description, type: String, desc: 'The description of a snippet' optional :visibility, type: String, values: Gitlab::VisibilityLevel.string_values, desc: 'The visibility of the snippet' -- cgit v1.2.3 From 0684073d1ea5de0c7e0052b3ccc0cca77f661b56 Mon Sep 17 00:00:00 2001 From: vanadium23 Date: Tue, 30 May 2017 20:41:43 +0300 Subject: Add tag_list param to project api --- lib/api/projects.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/api/projects.rb b/lib/api/projects.rb index d4fe5c023bf..a827fb26b98 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -21,6 +21,7 @@ module API optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access' optional :only_allow_merge_if_pipeline_succeeds, type: Boolean, desc: 'Only allow to merge if builds succeed' optional :only_allow_merge_if_all_discussions_are_resolved, type: Boolean, desc: 'Only allow to merge if all discussions are resolved' + optional :tag_list, type: Array[String], desc: 'The list of tags for a project' end params :optional_params do @@ -231,6 +232,7 @@ module API :request_access_enabled, :shared_runners_enabled, :snippets_enabled, + :tag_list, :visibility, :wiki_enabled ] -- cgit v1.2.3 From 161af17c1b69e7e00aefcd4f540a55755259ceda Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Wed, 24 May 2017 15:13:51 +0200 Subject: Introduce source to pipeline entity --- lib/api/commit_statuses.rb | 9 ++++++++- lib/api/pipelines.rb | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb index 827a38d33da..10f2d5ef6a3 100644 --- a/lib/api/commit_statuses.rb +++ b/lib/api/commit_statuses.rb @@ -68,7 +68,14 @@ module API name = params[:name] || params[:context] || 'default' - pipeline = @project.ensure_pipeline(ref, commit.sha, current_user) + pipeline = @project.pipeline_for(ref, commit.sha) + unless pipeline + pipeline = @project.pipelines.create!( + source: :external, + sha: commit.sha, + ref: ref, + user: current_user) + end status = GenericCommitStatus.running_or_pending.find_or_initialize_by( project: @project, diff --git a/lib/api/pipelines.rb b/lib/api/pipelines.rb index 9117704aa46..e505cae3992 100644 --- a/lib/api/pipelines.rb +++ b/lib/api/pipelines.rb @@ -47,7 +47,7 @@ module API new_pipeline = Ci::CreatePipelineService.new(user_project, current_user, declared_params(include_missing: false)) - .execute(ignore_skip_ci: true, save_on_errors: false) + .execute(:api, ignore_skip_ci: true, save_on_errors: false) if new_pipeline.persisted? present new_pipeline, with: Entities::Pipeline else -- cgit v1.2.3 From 500e5227a08bd603a2943c3c7d2efcaf4a40cc15 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Mon, 13 Feb 2017 00:33:31 +0100 Subject: WIP SystemCheck library for executing checks from a rake task --- lib/system_check.rb | 12 +++++++++++ lib/system_check/base_check.rb | 42 +++++++++++++++++++++++++++++++++++++ lib/system_check/base_executor.rb | 18 ++++++++++++++++ lib/system_check/simple_executor.rb | 34 ++++++++++++++++++++++++++++++ lib/tasks/gitlab/check.rake | 5 +++++ 5 files changed, 111 insertions(+) create mode 100644 lib/system_check.rb create mode 100644 lib/system_check/base_check.rb create mode 100644 lib/system_check/base_executor.rb create mode 100644 lib/system_check/simple_executor.rb (limited to 'lib') diff --git a/lib/system_check.rb b/lib/system_check.rb new file mode 100644 index 00000000000..1d09b57911a --- /dev/null +++ b/lib/system_check.rb @@ -0,0 +1,12 @@ +module SystemCheck + def self.run(component, checks = {}, executor_klass = SimpleExecutor) + unless executor_klass.is_a? BaseExecutor + raise ArgumentError, 'Invalid executor' + end + + executor = executor_klass.new(component) + executor.checks = checks.map do |check| + raise ArgumentError unless check.is_a? BaseCheck + end + end +end diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb new file mode 100644 index 00000000000..6e9f7e509a9 --- /dev/null +++ b/lib/system_check/base_check.rb @@ -0,0 +1,42 @@ +module SystemCheck + class BaseCheck + def check? + raise NotImplementedError + end + + def show_error + raise NotImplementedError + end + + def skip? + false + end + + def skip_message + end + + protected + + def try_fixing_it(*steps) + steps = steps.shift if steps.first.is_a?(Array) + + puts ' Try fixing it:'.color(:blue) + steps.each do |step| + puts " #{step}" + end + end + + def fix_and_rerun + puts ' Please fix the error above and rerun the checks.'.color(:red) + end + + def for_more_information(*sources) + sources = sources.shift if sources.first.is_a?(Array) + + puts ' For more information see:'.color(:blue) + sources.each do |source| + puts ' #{source}' + end + end + end +end diff --git a/lib/system_check/base_executor.rb b/lib/system_check/base_executor.rb new file mode 100644 index 00000000000..18319843dea --- /dev/null +++ b/lib/system_check/base_executor.rb @@ -0,0 +1,18 @@ +module SystemCheck + class BaseExecutor + attr_reader :checks + attr_reader :component + + def initialize(component) + raise ArgumentError unless component.is_a? String + + @component = component + @checks = Set.new + end + + def <<(check) + raise ArgumentError unless check.is_a? BaseCheck + @checks << check + end + end +end diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb new file mode 100644 index 00000000000..2ffe837e326 --- /dev/null +++ b/lib/system_check/simple_executor.rb @@ -0,0 +1,34 @@ +module SystemCheck + class SimpleExecutor < BaseExecutor + def execute + start_checking(component) + + @checks.each do |check| + print "#{check.name}" + if check.skip? + puts "skipped #{'('+skip_message+')' if skip_message}".color(:magenta) + elsif check.check? + puts 'yes'.color(:green) + else + puts 'no'.color(:red) + check.show_error + end + end + + finished_checking(component) + end + + private + + def start_checking(component) + puts "Checking #{component.color(:yellow)} ..." + puts '' + end + + def finished_checking(component) + puts '' + puts "Checking #{component.color(:yellow)} ... #{"Finished".color(:green)}" + puts '' + end + end +end diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index f41c73154f5..88ec9cbc8cc 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -848,10 +848,12 @@ namespace :gitlab do # Helper methods ########################## + # @deprecated Please use SystemChecks def fix_and_rerun puts " Please fix the error above and rerun the checks.".color(:red) end + # @deprecated Please use SystemChecks def for_more_information(*sources) sources = sources.shift if sources.first.is_a?(Array) @@ -861,6 +863,7 @@ namespace :gitlab do end end + # @deprecated Please use SystemChecks def finished_checking(component) puts "" puts "Checking #{component.color(:yellow)} ... #{"Finished".color(:green)}" @@ -883,11 +886,13 @@ namespace :gitlab do Gitlab.config.gitlab.user end + # @deprecated Please use SystemChecks def start_checking(component) puts "Checking #{component.color(:yellow)} ..." puts "" end + # @deprecated Please use SystemChecks def try_fixing_it(*steps) steps = steps.shift if steps.first.is_a?(Array) -- cgit v1.2.3 From f182ea4ea5fe76349a584da12e5d4a9f681a8401 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Mon, 13 Feb 2017 09:45:39 +0100 Subject: Some code-style fixes and documentation --- lib/system_check.rb | 17 +++++++++++++--- lib/system_check/base_check.rb | 40 ++++++++++++++++++++++++++++++++----- lib/system_check/base_executor.rb | 6 ++++++ lib/system_check/simple_executor.rb | 30 +++++++++++++++++++--------- 4 files changed, 76 insertions(+), 17 deletions(-) (limited to 'lib') diff --git a/lib/system_check.rb b/lib/system_check.rb index 1d09b57911a..79603dfc7cb 100644 --- a/lib/system_check.rb +++ b/lib/system_check.rb @@ -1,12 +1,23 @@ +# Library to perform System Checks +# +# Every Check is implemented as its own class inherited from SystemCheck::BaseCheck +# Execution coordination and boilerplate output is done by the SystemCheck::SimpleExecutor +# +# This structure decouples checks from Rake tasks and facilitates unit-testing module SystemCheck - def self.run(component, checks = {}, executor_klass = SimpleExecutor) + # Executes a bunch of checks for specified component + # + # @param [String] component name of the component relative to the checks being executed + # @param [Array] checks classes of corresponding checks to be executed in the same order + # @param [BaseExecutor] executor_klass optionally specifiy a different executor class + def self.run(component, checks = [], executor_klass = SimpleExecutor) unless executor_klass.is_a? BaseExecutor raise ArgumentError, 'Invalid executor' end executor = executor_klass.new(component) - executor.checks = checks.map do |check| - raise ArgumentError unless check.is_a? BaseCheck + checks.each do |check| + executor << check end end end diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb index 6e9f7e509a9..d465711d719 100644 --- a/lib/system_check/base_check.rb +++ b/lib/system_check/base_check.rb @@ -1,41 +1,71 @@ module SystemCheck + # Base class for Checks. You must inherit from here + # and implement the methods below when necessary class BaseCheck + # This is where you should implement the main logic that will return + # a boolean at the end + # + # You should not print any output to STDOUT here, use the specific methods instead + # + # @return [Boolean] whether the check passed or not def check? raise NotImplementedError end + # This is where you should print detailed information for any error found during #check? + # + # You may use helper methods to help format the output: + # + # @see #try_fixing_it + # @see #fix_and_rerun + # @see #for_more_infromation def show_error raise NotImplementedError end + # If skip returns true, than no other method on this check will be executed + # + # @return [Boolean] whether or not this check should be skipped def skip? false end + # If you enabled #skip? here is where you define a custom message explaining why + # + # Do not print anything to STDOUT, return a string. + # + # @return [String] message why this check was skipped def skip_message end protected + # Display a formatted list of instructions on how to fix the issue identified by the #check? + # + # @param [Array] steps one or short sentences with help how to fix the issue def try_fixing_it(*steps) steps = steps.shift if steps.first.is_a?(Array) - puts ' Try fixing it:'.color(:blue) + $stdout.puts ' Try fixing it:'.color(:blue) steps.each do |step| - puts " #{step}" + $stdout.puts " #{step}" end end + # Display a message telling to fix and rerun the checks def fix_and_rerun - puts ' Please fix the error above and rerun the checks.'.color(:red) + $stdout.puts ' Please fix the error above and rerun the checks.'.color(:red) end + # Display a formatted list of references (documentation or links) where to find more information + # + # @param [Array] sources one or more references (documentation or links) def for_more_information(*sources) sources = sources.shift if sources.first.is_a?(Array) - puts ' For more information see:'.color(:blue) + $stdout.puts ' For more information see:'.color(:blue) sources.each do |source| - puts ' #{source}' + $stdout.puts ' #{source}' end end end diff --git a/lib/system_check/base_executor.rb b/lib/system_check/base_executor.rb index 18319843dea..2c2b33461d9 100644 --- a/lib/system_check/base_executor.rb +++ b/lib/system_check/base_executor.rb @@ -1,8 +1,11 @@ module SystemCheck + # @attr_reader [Array] checks classes of corresponding checks to be executed in the same order + # @attr_reader [String] component name of the component relative to the checks being executed class BaseExecutor attr_reader :checks attr_reader :component + # @param [String] component name of the component relative to the checks being executed def initialize(component) raise ArgumentError unless component.is_a? String @@ -10,6 +13,9 @@ module SystemCheck @checks = Set.new end + # Add a check to be executed + # + # @param [BaseCheck] check class def <<(check) raise ArgumentError unless check.is_a? BaseCheck @checks << check diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb index 2ffe837e326..fc07f09dcb2 100644 --- a/lib/system_check/simple_executor.rb +++ b/lib/system_check/simple_executor.rb @@ -1,16 +1,22 @@ module SystemCheck + # Simple Executor is current default executor for GitLab + # It is a simple port from display logic in the old check.rake + # + # There is no concurrency level and the output is progressively + # printed into the STDOUT class SimpleExecutor < BaseExecutor + # Executes defined checks in the specified order and outputs confirmation or error information def execute start_checking(component) @checks.each do |check| - print "#{check.name}" + $stdout.print "#{check.name}" if check.skip? - puts "skipped #{'('+skip_message+')' if skip_message}".color(:magenta) + $stdout.puts "skipped #{'(' + skip_message + ')' if skip_message}".color(:magenta) elsif check.check? - puts 'yes'.color(:green) + $stdout.puts 'yes'.color(:green) else - puts 'no'.color(:red) + $stdout.puts 'no'.color(:red) check.show_error end end @@ -20,15 +26,21 @@ module SystemCheck private + # Prints header content for the series of checks to be executed for this component + # + # @param [String] component name of the component relative to the checks being executed def start_checking(component) - puts "Checking #{component.color(:yellow)} ..." - puts '' + $stdout.puts "Checking #{component.color(:yellow)} ..." + $stdout.puts '' end + # Prints footer content for the series of checks executed for this component + # + # @param [String] component name of the component relative to the checks being executed def finished_checking(component) - puts '' - puts "Checking #{component.color(:yellow)} ... #{"Finished".color(:green)}" - puts '' + $stdout.puts '' + $stdout.puts "Checking #{component.color(:yellow)} ... #{'Finished'.color(:green)}" + $stdout.puts '' end end end -- cgit v1.2.3 From a4460f420bbbac30fbcec3395261c89749b52bbd Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Mon, 13 Feb 2017 12:20:56 +0100 Subject: Fix a few method signature checks --- lib/system_check.rb | 2 +- lib/system_check/base_executor.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/system_check.rb b/lib/system_check.rb index 79603dfc7cb..ba22a40f5af 100644 --- a/lib/system_check.rb +++ b/lib/system_check.rb @@ -11,7 +11,7 @@ module SystemCheck # @param [Array] checks classes of corresponding checks to be executed in the same order # @param [BaseExecutor] executor_klass optionally specifiy a different executor class def self.run(component, checks = [], executor_klass = SimpleExecutor) - unless executor_klass.is_a? BaseExecutor + unless executor_klass < BaseExecutor raise ArgumentError, 'Invalid executor' end diff --git a/lib/system_check/base_executor.rb b/lib/system_check/base_executor.rb index 2c2b33461d9..f76f44f3a28 100644 --- a/lib/system_check/base_executor.rb +++ b/lib/system_check/base_executor.rb @@ -17,7 +17,7 @@ module SystemCheck # # @param [BaseCheck] check class def <<(check) - raise ArgumentError unless check.is_a? BaseCheck + raise ArgumentError unless check < BaseCheck @checks << check end end -- cgit v1.2.3 From bc6d131b74ba4cdf7acadea5a5b7d23f083f47ed Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Mon, 13 Feb 2017 12:21:12 +0100 Subject: Added specs for SystemCheck and custom matcher --- lib/system_check.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/system_check.rb b/lib/system_check.rb index ba22a40f5af..e9cbf6b8258 100644 --- a/lib/system_check.rb +++ b/lib/system_check.rb @@ -15,9 +15,16 @@ module SystemCheck raise ArgumentError, 'Invalid executor' end + prepare(component, checks, executor_klass).execute + end + + def self.prepare(component, checks = [], executor_klass = SimpleExecutor) executor = executor_klass.new(component) checks.each do |check| executor << check end + + executor end + private_class_method :prepare end -- cgit v1.2.3 From 13e88c93956b5b350515b919ef7217a3dccf28ff Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Thu, 25 May 2017 16:16:25 +0200 Subject: Refactor gitlab:app:checks to use SystemCheck --- .../app/database_config_exists_check.rb | 31 ++ lib/system_check/app/git_config_check.rb | 50 +++ lib/system_check/app/git_version_check.rb | 29 ++ lib/system_check/app/gitlab_config_exists_check.rb | 24 + .../app/gitlab_config_not_outdated_check.rb | 32 ++ lib/system_check/app/init_script_exists_check.rb | 27 ++ .../app/init_script_up_to_date_check.rb | 44 ++ lib/system_check/app/log_writable_check.rb | 28 ++ lib/system_check/app/migrations_are_up_check.rb | 20 + .../app/orphaned_group_members_check.rb | 20 + .../app/projects_have_namespace_check.rb | 37 ++ lib/system_check/app/redis_version_check.rb | 25 ++ lib/system_check/app/ruby_version_check.rb | 27 ++ lib/system_check/app/tmp_writable_check.rb | 28 ++ .../app/uploads_directory_exists_check.rb | 21 + .../app/uploads_path_permission_check.rb | 36 ++ .../app/uploads_path_tmp_permission_check.rb | 40 ++ lib/system_check/base_check.rb | 138 ++++-- lib/system_check/helpers.rb | 80 ++++ lib/system_check/simple_executor.rb | 49 +- lib/tasks/gitlab/check.rake | 495 ++------------------- lib/tasks/gitlab/task_helpers.rb | 1 + 22 files changed, 778 insertions(+), 504 deletions(-) create mode 100644 lib/system_check/app/database_config_exists_check.rb create mode 100644 lib/system_check/app/git_config_check.rb create mode 100644 lib/system_check/app/git_version_check.rb create mode 100644 lib/system_check/app/gitlab_config_exists_check.rb create mode 100644 lib/system_check/app/gitlab_config_not_outdated_check.rb create mode 100644 lib/system_check/app/init_script_exists_check.rb create mode 100644 lib/system_check/app/init_script_up_to_date_check.rb create mode 100644 lib/system_check/app/log_writable_check.rb create mode 100644 lib/system_check/app/migrations_are_up_check.rb create mode 100644 lib/system_check/app/orphaned_group_members_check.rb create mode 100644 lib/system_check/app/projects_have_namespace_check.rb create mode 100644 lib/system_check/app/redis_version_check.rb create mode 100644 lib/system_check/app/ruby_version_check.rb create mode 100644 lib/system_check/app/tmp_writable_check.rb create mode 100644 lib/system_check/app/uploads_directory_exists_check.rb create mode 100644 lib/system_check/app/uploads_path_permission_check.rb create mode 100644 lib/system_check/app/uploads_path_tmp_permission_check.rb create mode 100644 lib/system_check/helpers.rb (limited to 'lib') diff --git a/lib/system_check/app/database_config_exists_check.rb b/lib/system_check/app/database_config_exists_check.rb new file mode 100644 index 00000000000..d557cee47b4 --- /dev/null +++ b/lib/system_check/app/database_config_exists_check.rb @@ -0,0 +1,31 @@ +module SystemCheck + module App + class DatabaseConfigExistsCheck < SystemCheck::BaseCheck + set_name 'Database config exists?' + + def check? + database_config_file = Rails.root.join('config', 'database.yml') + + File.exist?(database_config_file) + end + + def show_error + try_fixing_it( + 'Copy config/database.yml. to config/database.yml', + 'Check that the information in config/database.yml is correct' + ) + for_more_information( + see_database_guide, + 'http://guides.rubyonrails.org/getting_started.html#configuring-a-database' + ) + fix_and_rerun + end + + private + + def see_database_guide + 'doc/install/databases.md' + end + end + end +end diff --git a/lib/system_check/app/git_config_check.rb b/lib/system_check/app/git_config_check.rb new file mode 100644 index 00000000000..7f0c792eb35 --- /dev/null +++ b/lib/system_check/app/git_config_check.rb @@ -0,0 +1,50 @@ +module SystemCheck + module App + class GitConfigCheck < SystemCheck::BaseCheck + OPTIONS = { + 'core.autocrlf' => 'input' + }.freeze + + set_name 'Git configured with autocrlf=input?' + + def check? + correct_options = OPTIONS.map do |name, value| + run_command(%W(#{Gitlab.config.git.bin_path} config --global --get #{name})).try(:squish) == value + end + + correct_options.all? + end + + def repair! + auto_fix_git_config(OPTIONS) + end + + def show_error + try_fixing_it( + sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{OPTIONS['core.autocrlf']}\"") + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + end + + private + + # Tries to configure git itself + # + # Returns true if all subcommands were successfull (according to their exit code) + # Returns false if any or all subcommands failed. + def auto_fix_git_config(options) + if !@warned_user_not_gitlab + command_success = options.map do |name, value| + system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value})) + end + + command_success.all? + else + false + end + end + end + end +end diff --git a/lib/system_check/app/git_version_check.rb b/lib/system_check/app/git_version_check.rb new file mode 100644 index 00000000000..3a128f00911 --- /dev/null +++ b/lib/system_check/app/git_version_check.rb @@ -0,0 +1,29 @@ +module SystemCheck + module App + class GitVersionCheck < SystemCheck::BaseCheck + set_name -> { "Git version >= #{self.required_version} ?" } + set_check_pass -> { "yes (#{self.current_version})" } + + def self.required_version + @required_version ||= Gitlab::VersionInfo.new(2, 7, 3) + end + + def self.current_version + @current_version ||= Gitlab::VersionInfo.parse(run_command(%W(#{Gitlab.config.git.bin_path} --version))) + end + + def check? + self.class.current_version.valid? && self.class.required_version <= self.class.current_version + end + + def show_error + puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\"" + + try_fixing_it( + "Update your git to a version >= #{self.class.required_version} from #{self.class.current_version}" + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/gitlab_config_exists_check.rb b/lib/system_check/app/gitlab_config_exists_check.rb new file mode 100644 index 00000000000..247aa0994e4 --- /dev/null +++ b/lib/system_check/app/gitlab_config_exists_check.rb @@ -0,0 +1,24 @@ +module SystemCheck + module App + class GitlabConfigExistsCheck < SystemCheck::BaseCheck + set_name 'GitLab config exists?' + + def check? + gitlab_config_file = Rails.root.join('config', 'gitlab.yml') + + File.exist?(gitlab_config_file) + end + + def show_error + try_fixing_it( + 'Copy config/gitlab.yml.example to config/gitlab.yml', + 'Update config/gitlab.yml to match your setup' + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/gitlab_config_not_outdated_check.rb b/lib/system_check/app/gitlab_config_not_outdated_check.rb new file mode 100644 index 00000000000..8a4d7b29977 --- /dev/null +++ b/lib/system_check/app/gitlab_config_not_outdated_check.rb @@ -0,0 +1,32 @@ +module SystemCheck + module App + class GitlabConfigNotOutdatedCheck < SystemCheck::BaseCheck + set_name 'GitLab config outdated?' + set_check_pass 'no' + set_check_fail 'yes' + set_skip_reason "can't check because of previous errors" + + def skip? + gitlab_config_file = Rails.root.join('config', 'gitlab.yml') + !File.exist?(gitlab_config_file) + end + + def check? + # omniauth or ldap could have been deleted from the file + !Gitlab.config['git_host'] + end + + def show_error + try_fixing_it( + 'Backup your config/gitlab.yml', + 'Copy config/gitlab.yml.example to config/gitlab.yml', + 'Update config/gitlab.yml to match your setup' + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/init_script_exists_check.rb b/lib/system_check/app/init_script_exists_check.rb new file mode 100644 index 00000000000..d246e058e86 --- /dev/null +++ b/lib/system_check/app/init_script_exists_check.rb @@ -0,0 +1,27 @@ +module SystemCheck + module App + class InitScriptExistsCheck < SystemCheck::BaseCheck + set_name 'Init script exists?' + set_skip_reason 'skipped (omnibus-gitlab has no init script)' + + def skip? + omnibus_gitlab? + end + + def check? + script_path = '/etc/init.d/gitlab' + File.exist?(script_path) + end + + def show_error + try_fixing_it( + 'Install the init script' + ) + for_more_information( + see_installation_guide_section 'Install Init Script' + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/init_script_up_to_date_check.rb b/lib/system_check/app/init_script_up_to_date_check.rb new file mode 100644 index 00000000000..28c1451b8d2 --- /dev/null +++ b/lib/system_check/app/init_script_up_to_date_check.rb @@ -0,0 +1,44 @@ +module SystemCheck + module App + class InitScriptUpToDateCheck < SystemCheck::BaseCheck + SCRIPT_PATH = '/etc/init.d/gitlab'.freeze + + set_name 'Init script up-to-date?' + set_skip_reason 'skipped (omnibus-gitlab has no init script)' + + def skip? + omnibus_gitlab? + end + + def multi_check + recipe_path = Rails.root.join('lib/support/init.d/', 'gitlab') + + unless File.exist?(SCRIPT_PATH) + puts "can't check because of previous errors".color(:magenta) + return + end + + recipe_content = File.read(recipe_path) + script_content = File.read(SCRIPT_PATH) + + if recipe_content == script_content + puts 'yes'.color(:green) + else + puts 'no'.color(:red) + show_error + end + end + + + def show_error + try_fixing_it( + 'Re-download the init script' + ) + for_more_information( + see_installation_guide_section 'Install Init Script' + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/log_writable_check.rb b/lib/system_check/app/log_writable_check.rb new file mode 100644 index 00000000000..3e0c436d6ee --- /dev/null +++ b/lib/system_check/app/log_writable_check.rb @@ -0,0 +1,28 @@ +module SystemCheck + module App + class LogWritableCheck < SystemCheck::BaseCheck + set_name 'Log directory writable?' + + def check? + File.writable?(log_path) + end + + def show_error + try_fixing_it( + "sudo chown -R gitlab #{log_path}", + "sudo chmod -R u+rwX #{log_path}" + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + fix_and_rerun + end + + private + + def log_path + Rails.root.join('log') + end + end + end +end diff --git a/lib/system_check/app/migrations_are_up_check.rb b/lib/system_check/app/migrations_are_up_check.rb new file mode 100644 index 00000000000..5eedbacce77 --- /dev/null +++ b/lib/system_check/app/migrations_are_up_check.rb @@ -0,0 +1,20 @@ +module SystemCheck + module App + class MigrationsAreUpCheck < SystemCheck::BaseCheck + set_name 'All migrations up?' + + def check? + migration_status, _ = Gitlab::Popen.popen(%w(bundle exec rake db:migrate:status)) + + migration_status !~ /down\s+\d{14}/ + end + + def show_error + try_fixing_it( + sudo_gitlab('bundle exec rake db:migrate RAILS_ENV=production') + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/orphaned_group_members_check.rb b/lib/system_check/app/orphaned_group_members_check.rb new file mode 100644 index 00000000000..2b46d36fe51 --- /dev/null +++ b/lib/system_check/app/orphaned_group_members_check.rb @@ -0,0 +1,20 @@ +module SystemCheck + module App + class OrphanedGroupMembersCheck < SystemCheck::BaseCheck + set_name 'Database contains orphaned GroupMembers?' + set_check_pass 'no' + set_check_fail 'yes' + + def check? + !GroupMember.where('user_id not in (select id from users)').exists? + end + + def show_error + try_fixing_it( + 'You can delete the orphaned records using something along the lines of:', + sudo_gitlab("bundle exec rails runner -e production 'GroupMember.where(\"user_id NOT IN (SELECT id FROM users)\").delete_all'") + ) + end + end + end +end diff --git a/lib/system_check/app/projects_have_namespace_check.rb b/lib/system_check/app/projects_have_namespace_check.rb new file mode 100644 index 00000000000..d21ae225b0b --- /dev/null +++ b/lib/system_check/app/projects_have_namespace_check.rb @@ -0,0 +1,37 @@ +module SystemCheck + module App + class ProjectsHaveNamespaceCheck < SystemCheck::BaseCheck + set_name 'projects have namespace: ' + set_skip_reason "can't check, you have no projects" + + def skip? + !Project.exists? + end + + def multi_check + puts '' + + Project.find_each(batch_size: 100) do |project| + print sanitized_message(project) + + if project.namespace + puts 'yes'.color(:green) + else + puts 'no'.color(:red) + show_error + end + end + end + + def show_error + try_fixing_it( + "Migrate global projects" + ) + for_more_information( + "doc/update/5.4-to-6.0.md in section \"#global-projects\"" + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/redis_version_check.rb b/lib/system_check/app/redis_version_check.rb new file mode 100644 index 00000000000..a0610e73576 --- /dev/null +++ b/lib/system_check/app/redis_version_check.rb @@ -0,0 +1,25 @@ +module SystemCheck + module App + class RedisVersionCheck < SystemCheck::BaseCheck + MIN_REDIS_VERSION = '2.8.0'.freeze + set_name "Redis version >= #{MIN_REDIS_VERSION}?" + + def check? + redis_version = run_command(%w(redis-cli --version)) + redis_version = redis_version.try(:match, /redis-cli (\d+\.\d+\.\d+)/) + + redis_version && (Gem::Version.new(redis_version[1]) > Gem::Version.new(MIN_REDIS_VERSION)) + end + + def show_error + try_fixing_it( + "Update your redis server to a version >= #{MIN_REDIS_VERSION}" + ) + for_more_information( + 'gitlab-public-wiki/wiki/Trouble-Shooting-Guide in section sidekiq' + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/ruby_version_check.rb b/lib/system_check/app/ruby_version_check.rb new file mode 100644 index 00000000000..37b4d24aa55 --- /dev/null +++ b/lib/system_check/app/ruby_version_check.rb @@ -0,0 +1,27 @@ +module SystemCheck + module App + class RubyVersionCheck < SystemCheck::BaseCheck + set_name -> { "Ruby version >= #{self.required_version} ?" } + set_check_pass -> { "yes (#{self.current_version})" } + + def self.required_version + @required_version ||= Gitlab::VersionInfo.new(2, 1, 0) + end + + def self.current_version + @current_version ||= Gitlab::VersionInfo.parse(run_command(%w(ruby --version))) + end + + def check? + self.class.current_version.valid? && self.class.required_version <= self.class.current_version + end + + def show_error + try_fixing_it( + "Update your ruby to a version >= #{self.class.required_version} from #{self.class.current_version}" + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/tmp_writable_check.rb b/lib/system_check/app/tmp_writable_check.rb new file mode 100644 index 00000000000..99a75e57abf --- /dev/null +++ b/lib/system_check/app/tmp_writable_check.rb @@ -0,0 +1,28 @@ +module SystemCheck + module App + class TmpWritableCheck < SystemCheck::BaseCheck + set_name 'Tmp directory writable?' + + def check? + File.writable?(tmp_path) + end + + def show_error + try_fixing_it( + "sudo chown -R gitlab #{tmp_path}", + "sudo chmod -R u+rwX #{tmp_path}" + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + fix_and_rerun + end + + private + + def tmp_path + Rails.root.join('tmp') + end + end + end +end diff --git a/lib/system_check/app/uploads_directory_exists_check.rb b/lib/system_check/app/uploads_directory_exists_check.rb new file mode 100644 index 00000000000..7026d0ba075 --- /dev/null +++ b/lib/system_check/app/uploads_directory_exists_check.rb @@ -0,0 +1,21 @@ +module SystemCheck + module App + class UploadsDirectoryExistsCheck < SystemCheck::BaseCheck + set_name 'Uploads directory exists?' + + def check? + File.directory?(Rails.root.join('public/uploads')) + end + + def show_error + try_fixing_it( + "sudo -u #{gitlab_user} mkdir #{Rails.root}/public/uploads" + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/uploads_path_permission_check.rb b/lib/system_check/app/uploads_path_permission_check.rb new file mode 100644 index 00000000000..7df6c060254 --- /dev/null +++ b/lib/system_check/app/uploads_path_permission_check.rb @@ -0,0 +1,36 @@ +module SystemCheck + module App + class UploadsPathPermissionCheck < SystemCheck::BaseCheck + set_name 'Uploads directory has correct permissions?' + set_skip_reason 'skipped (no uploads folder found)' + + def skip? + !File.directory?(rails_uploads_path) + end + + def check? + File.stat(uploads_fullpath).mode == 040700 + end + + def show_error + try_fixing_it( + "sudo chmod 700 #{uploads_fullpath}" + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + fix_and_rerun + end + + private + + def rails_uploads_path + Rails.root.join('public/uploads') + end + + def uploads_fullpath + File.realpath(rails_uploads_path) + end + end + end +end diff --git a/lib/system_check/app/uploads_path_tmp_permission_check.rb b/lib/system_check/app/uploads_path_tmp_permission_check.rb new file mode 100644 index 00000000000..b276a81eac1 --- /dev/null +++ b/lib/system_check/app/uploads_path_tmp_permission_check.rb @@ -0,0 +1,40 @@ +module SystemCheck + module App + class UploadsPathTmpPermissionCheck < SystemCheck::BaseCheck + set_name 'Uploads directory tmp has correct permissions?' + set_skip_reason 'skipped (no tmp uploads folder yet)' + + def skip? + !File.directory?(uploads_fullpath) || !Dir.exist?(upload_path_tmp) + end + + def check? + # If tmp upload dir has incorrect permissions, assume others do as well + # Verify drwx------ permissions + File.stat(upload_path_tmp).mode == 040700 && File.owned?(upload_path_tmp) + end + + def show_error + try_fixing_it( + "sudo chown -R #{gitlab_user} #{uploads_fullpath}", + "sudo find #{uploads_fullpath} -type f -exec chmod 0644 {} \\;", + "sudo find #{uploads_fullpath} -type d -not -path #{uploads_fullpath} -exec chmod 0700 {} \\;" + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + fix_and_rerun + end + + private + + def upload_path_tmp + File.join(uploads_fullpath, 'tmp') + end + + def uploads_fullpath + File.realpath(Rails.root.join('public/uploads')) + end + end + end +end diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb index d465711d719..aff830f54d7 100644 --- a/lib/system_check/base_check.rb +++ b/lib/system_check/base_check.rb @@ -2,16 +2,103 @@ module SystemCheck # Base class for Checks. You must inherit from here # and implement the methods below when necessary class BaseCheck + include ::Gitlab::TaskHelpers + include Helpers + + # Define a custom term for when check passed + # + # @param [String] term used when check passed (default: 'yes') + def self.set_check_pass(term) + @check_pass = term + end + + # Define a custom term for when check failed + # + # @param [String] term used when check failed (default: 'no') + def self.set_check_fail(term) + @check_fail = term + end + + # Define the name of the SystemCheck that will be displayed during execution + # + # @param [String] name of the check + def self.set_name(name) + @name = name + end + + # Define the reason why we skipped the SystemCheck + # + # This is only used if subclass implements `#skip?` + # + # @param [String] reason to be displayed + def self.set_skip_reason(reason) + @skip_reason = reason + end + + # Term to be displayed when check passed + # + # @return [String] term when check passed ('yes' if not re-defined in a subclass) + def self.check_pass + call_or_return(@check_pass) || 'yes' + end + + ## Term to be displayed when check failed + # + # @return [String] term when check failed ('no' if not re-defined in a subclass) + def self.check_fail + call_or_return(@check_fail) || 'no' + end + + # Name of the SystemCheck defined by the subclass + # + # @return [String] the name + def self.display_name + call_or_return(@name) || self.name + end + + # Skip reason defined by the subclass + # + # @return [String] the reason + def self.skip_reason + call_or_return(@skip_reason) || 'skipped' + end + + # Does the check support automatically repair routine? + # + # @return [Boolean] whether check implemented `#repair!` method or not + def can_repair? + self.class.instance_methods(false).include?(:repair!) + end + + def can_skip? + self.class.instance_methods(false).include?(:skip?) + end + + def is_multi_check? + self.class.instance_methods(false).include?(:multi_check) + end + + # Execute the check routine + # # This is where you should implement the main logic that will return # a boolean at the end # # You should not print any output to STDOUT here, use the specific methods instead # - # @return [Boolean] whether the check passed or not + # @return [Boolean] whether check passed or failed def check? raise NotImplementedError end + # Execute a custom check that cover multiple unities + # + # When using multi_check you have to provide the output yourself + def multi_check + raise NotImplementedError + end + + # Prints troubleshooting instructions + # # This is where you should print detailed information for any error found during #check? # # You may use helper methods to help format the output: @@ -23,50 +110,21 @@ module SystemCheck raise NotImplementedError end - # If skip returns true, than no other method on this check will be executed - # - # @return [Boolean] whether or not this check should be skipped - def skip? - false - end - - # If you enabled #skip? here is where you define a custom message explaining why - # - # Do not print anything to STDOUT, return a string. - # - # @return [String] message why this check was skipped - def skip_message + # When implemented by a subclass, will attempt to fix the issue automatically + def repair! + raise NotImplementedError end - protected - - # Display a formatted list of instructions on how to fix the issue identified by the #check? + # When implemented by a subclass, will evaluate whether check should be skipped or not # - # @param [Array] steps one or short sentences with help how to fix the issue - def try_fixing_it(*steps) - steps = steps.shift if steps.first.is_a?(Array) - - $stdout.puts ' Try fixing it:'.color(:blue) - steps.each do |step| - $stdout.puts " #{step}" - end - end - - # Display a message telling to fix and rerun the checks - def fix_and_rerun - $stdout.puts ' Please fix the error above and rerun the checks.'.color(:red) + # @return [Boolean] whether or not this check should be skipped + def skip? + raise NotImplementedError end - # Display a formatted list of references (documentation or links) where to find more information - # - # @param [Array] sources one or more references (documentation or links) - def for_more_information(*sources) - sources = sources.shift if sources.first.is_a?(Array) - - $stdout.puts ' For more information see:'.color(:blue) - sources.each do |source| - $stdout.puts ' #{source}' - end + def self.call_or_return(input) + input.respond_to?(:call) ? input.call : input end + private_class_method :call_or_return end end diff --git a/lib/system_check/helpers.rb b/lib/system_check/helpers.rb new file mode 100644 index 00000000000..91454c99838 --- /dev/null +++ b/lib/system_check/helpers.rb @@ -0,0 +1,80 @@ +module SystemCheck + module Helpers + # Display a message telling to fix and rerun the checks + def fix_and_rerun + $stdout.puts ' Please fix the error above and rerun the checks.'.color(:red) + end + + # Display a formatted list of references (documentation or links) where to find more information + # + # @param [Array] sources one or more references (documentation or links) + def for_more_information(*sources) + sources = sources.shift if sources.first.is_a?(Array) + + $stdout.puts ' For more information see:'.color(:blue) + sources.each do |source| + $stdout.puts " #{source}" + end + end + + def see_installation_guide_section(section) + "doc/install/installation.md in section \"#{section}\"" + end + + # @deprecated This will no longer be used when all checks were executed using SystemCheck + def finished_checking(component) + $stdout.puts '' + $stdout.puts "Checking #{component.color(:yellow)} ... #{'Finished'.color(:green)}" + $stdout.puts '' + end + + # @deprecated This will no longer be used when all checks were executed using SystemCheck + def start_checking(component) + $stdout.puts "Checking #{component.color(:yellow)} ..." + $stdout.puts '' + end + + # Display a formatted list of instructions on how to fix the issue identified by the #check? + # + # @param [Array] steps one or short sentences with help how to fix the issue + def try_fixing_it(*steps) + steps = steps.shift if steps.first.is_a?(Array) + + $stdout.puts ' Try fixing it:'.color(:blue) + steps.each do |step| + $stdout.puts " #{step}" + end + end + + def sanitized_message(project) + if should_sanitize? + "#{project.namespace_id.to_s.color(:yellow)}/#{project.id.to_s.color(:yellow)} ... " + else + "#{project.name_with_namespace.color(:yellow)} ... " + end + end + + def should_sanitize? + if ENV['SANITIZE'] == 'true' + true + else + false + end + end + + def omnibus_gitlab? + Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails' + end + + def gitlab_user + Gitlab.config.gitlab.user + end + + def sudo_gitlab(command) + "sudo -u #{gitlab_user} -H #{command}" + end + end +end + + + diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb index fc07f09dcb2..7a5042047ab 100644 --- a/lib/system_check/simple_executor.rb +++ b/lib/system_check/simple_executor.rb @@ -10,20 +10,51 @@ module SystemCheck start_checking(component) @checks.each do |check| - $stdout.print "#{check.name}" - if check.skip? - $stdout.puts "skipped #{'(' + skip_message + ')' if skip_message}".color(:magenta) - elsif check.check? - $stdout.puts 'yes'.color(:green) - else - $stdout.puts 'no'.color(:red) - check.show_error - end + run_check(check) end finished_checking(component) end + # Executes a single check + # + # @param [SystemCheck::BaseCheck] check + def run_check(check) + $stdout.print "#{check.display_name} ... " + + c = check.new + + # When implements a multi check, we don't control the output + if c.is_multi_check? + c.multi_check + return + end + + # When implements skip method, we run it first, and if true, skip the check + if c.can_skip? && c.skip? + $stdout.puts check.skip_reason.color(:magenta) + return + end + + if c.check? + $stdout.puts check.check_pass.color(:green) + else + $stdout.puts check.check_fail.color(:red) + + if c.can_repair? + $stdout.print 'Trying to fix error automatically. ...' + if c.repair! + $stdout.puts 'Success'.color(:green) + return + else + $stdout.puts 'Failed'.color(:red) + end + end + + c.show_error + end + end + private # Prints header content for the series of checks to be executed for this component diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 88ec9cbc8cc..0d177663066 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -1,5 +1,9 @@ +# Temporary hack, until we migrate all checks to SystemCheck format +require 'system_check' +require 'system_check/helpers' + namespace :gitlab do - desc "GitLab | Check the configuration of GitLab and its environment" + desc 'GitLab | Check the configuration of GitLab and its environment' task check: %w{gitlab:gitlab_shell:check gitlab:sidekiq:check gitlab:incoming_email:check @@ -7,331 +11,38 @@ namespace :gitlab do gitlab:app:check} namespace :app do - desc "GitLab | Check the configuration of the GitLab Rails app" + desc 'GitLab | Check the configuration of the GitLab Rails app' task check: :environment do warn_user_is_not_gitlab - start_checking "GitLab" - - check_git_config - check_database_config_exists - check_migrations_are_up - check_orphaned_group_members - check_gitlab_config_exists - check_gitlab_config_not_outdated - check_log_writable - check_tmp_writable - check_uploads - check_init_script_exists - check_init_script_up_to_date - check_projects_have_namespace - check_redis_version - check_ruby_version - check_git_version - check_active_users - - finished_checking "GitLab" - end - - # Checks - ######################## - - def check_git_config - print "Git configured with autocrlf=input? ... " - - options = { - "core.autocrlf" => "input" - } - - correct_options = options.map do |name, value| - run_command(%W(#{Gitlab.config.git.bin_path} config --global --get #{name})).try(:squish) == value - end - - if correct_options.all? - puts "yes".color(:green) - else - print "Trying to fix Git error automatically. ..." - - if auto_fix_git_config(options) - puts "Success".color(:green) - else - puts "Failed".color(:red) - try_fixing_it( - sudo_gitlab("\"#{Gitlab.config.git.bin_path}\" config --global core.autocrlf \"#{options["core.autocrlf"]}\"") - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - end - end - end - - def check_database_config_exists - print "Database config exists? ... " - - database_config_file = Rails.root.join("config", "database.yml") - - if File.exist?(database_config_file) - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "Copy config/database.yml. to config/database.yml", - "Check that the information in config/database.yml is correct" - ) - for_more_information( - see_database_guide, - "http://guides.rubyonrails.org/getting_started.html#configuring-a-database" - ) - fix_and_rerun - end - end - - def check_gitlab_config_exists - print "GitLab config exists? ... " - - gitlab_config_file = Rails.root.join("config", "gitlab.yml") - - if File.exist?(gitlab_config_file) - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "Copy config/gitlab.yml.example to config/gitlab.yml", - "Update config/gitlab.yml to match your setup" - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - fix_and_rerun - end - end - - def check_gitlab_config_not_outdated - print "GitLab config outdated? ... " - - gitlab_config_file = Rails.root.join("config", "gitlab.yml") - unless File.exist?(gitlab_config_file) - puts "can't check because of previous errors".color(:magenta) - end - - # omniauth or ldap could have been deleted from the file - unless Gitlab.config['git_host'] - puts "no".color(:green) - else - puts "yes".color(:red) - try_fixing_it( - "Backup your config/gitlab.yml", - "Copy config/gitlab.yml.example to config/gitlab.yml", - "Update config/gitlab.yml to match your setup" - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - fix_and_rerun - end - end - - def check_init_script_exists - print "Init script exists? ... " - - if omnibus_gitlab? - puts 'skipped (omnibus-gitlab has no init script)'.color(:magenta) - return - end - - script_path = "/etc/init.d/gitlab" - - if File.exist?(script_path) - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "Install the init script" - ) - for_more_information( - see_installation_guide_section "Install Init Script" - ) - fix_and_rerun - end - end - - def check_init_script_up_to_date - print "Init script up-to-date? ... " - - if omnibus_gitlab? - puts 'skipped (omnibus-gitlab has no init script)'.color(:magenta) - return - end - - recipe_path = Rails.root.join("lib/support/init.d/", "gitlab") - script_path = "/etc/init.d/gitlab" - - unless File.exist?(script_path) - puts "can't check because of previous errors".color(:magenta) - return - end - - recipe_content = File.read(recipe_path) - script_content = File.read(script_path) - - if recipe_content == script_content - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "Redownload the init script" - ) - for_more_information( - see_installation_guide_section "Install Init Script" - ) - fix_and_rerun - end - end - - def check_migrations_are_up - print "All migrations up? ... " - migration_status, _ = Gitlab::Popen.popen(%w(bundle exec rake db:migrate:status)) - - unless migration_status =~ /down\s+\d{14}/ - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - sudo_gitlab("bundle exec rake db:migrate RAILS_ENV=production") - ) - fix_and_rerun - end - end - - def check_orphaned_group_members - print "Database contains orphaned GroupMembers? ... " - if GroupMember.where("user_id not in (select id from users)").count > 0 - puts "yes".color(:red) - try_fixing_it( - "You can delete the orphaned records using something along the lines of:", - sudo_gitlab("bundle exec rails runner -e production 'GroupMember.where(\"user_id NOT IN (SELECT id FROM users)\").delete_all'") - ) - else - puts "no".color(:green) - end - end - - def check_log_writable - print "Log directory writable? ... " - - log_path = Rails.root.join("log") - - if File.writable?(log_path) - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "sudo chown -R gitlab #{log_path}", - "sudo chmod -R u+rwX #{log_path}" - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - fix_and_rerun - end - end - - def check_tmp_writable - print "Tmp directory writable? ... " - - tmp_path = Rails.root.join("tmp") - - if File.writable?(tmp_path) - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "sudo chown -R gitlab #{tmp_path}", - "sudo chmod -R u+rwX #{tmp_path}" - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - fix_and_rerun - end - end - - def check_uploads - print "Uploads directory setup correctly? ... " - - unless File.directory?(Rails.root.join('public/uploads')) - puts "no".color(:red) - try_fixing_it( - "sudo -u #{gitlab_user} mkdir #{Rails.root}/public/uploads" - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - fix_and_rerun - return - end - - upload_path = File.realpath(Rails.root.join('public/uploads')) - upload_path_tmp = File.join(upload_path, 'tmp') - - if File.stat(upload_path).mode == 040700 - unless Dir.exist?(upload_path_tmp) - puts 'skipped (no tmp uploads folder yet)'.color(:magenta) - return - end - - # If tmp upload dir has incorrect permissions, assume others do as well - # Verify drwx------ permissions - if File.stat(upload_path_tmp).mode == 040700 && File.owned?(upload_path_tmp) - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "sudo chown -R #{gitlab_user} #{upload_path}", - "sudo find #{upload_path} -type f -exec chmod 0644 {} \\;", - "sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0700 {} \\;" - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - fix_and_rerun - end - else - puts "no".color(:red) - try_fixing_it( - "sudo chmod 700 #{upload_path}" - ) - for_more_information( - see_installation_guide_section "GitLab" - ) - fix_and_rerun - end - end - - def check_redis_version - min_redis_version = "2.8.0" - print "Redis version >= #{min_redis_version}? ... " - - redis_version = run_command(%w(redis-cli --version)) - redis_version = redis_version.try(:match, /redis-cli (\d+\.\d+\.\d+)/) - if redis_version && - (Gem::Version.new(redis_version[1]) > Gem::Version.new(min_redis_version)) - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "Update your redis server to a version >= #{min_redis_version}" - ) - for_more_information( - "gitlab-public-wiki/wiki/Trouble-Shooting-Guide in section sidekiq" - ) - fix_and_rerun - end + checks = [ + SystemCheck::App::GitConfigCheck, + SystemCheck::App::DatabaseConfigExistsCheck, + SystemCheck::App::MigrationsAreUpCheck, + SystemCheck::App::OrphanedGroupMembersCheck, + SystemCheck::App::GitlabConfigExistsCheck, + SystemCheck::App::GitlabConfigNotOutdatedCheck, + SystemCheck::App::LogWritableCheck, + SystemCheck::App::TmpWritableCheck, + SystemCheck::App::UploadsDirectoryExistsCheck, + SystemCheck::App::UploadsPathPermissionCheck, + SystemCheck::App::UploadsPathTmpPermissionCheck, + SystemCheck::App::InitScriptExistsCheck, + SystemCheck::App::InitScriptUpToDateCheck, + SystemCheck::App::ProjectsHaveNamespaceCheck, + SystemCheck::App::RedisVersionCheck, + SystemCheck::App::RubyVersionCheck, + SystemCheck::App::GitVersionCheck + ] + + SystemCheck.run('GitLab', checks) + check_active_users end end namespace :gitlab_shell do + include SystemCheck::Helpers + desc "GitLab | Check the configuration of GitLab Shell" task check: :environment do warn_user_is_not_gitlab @@ -513,33 +224,6 @@ namespace :gitlab do end end - def check_projects_have_namespace - print "projects have namespace: ... " - - unless Project.count > 0 - puts "can't check, you have no projects".color(:magenta) - return - end - puts "" - - Project.find_each(batch_size: 100) do |project| - print sanitized_message(project) - - if project.namespace - puts "yes".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "Migrate global projects" - ) - for_more_information( - "doc/update/5.4-to-6.0.md in section \"#global-projects\"" - ) - fix_and_rerun - end - end - end - # Helper methods ######################## @@ -565,6 +249,8 @@ namespace :gitlab do end namespace :sidekiq do + include SystemCheck::Helpers + desc "GitLab | Check the configuration of Sidekiq" task check: :environment do warn_user_is_not_gitlab @@ -623,6 +309,8 @@ namespace :gitlab do end namespace :incoming_email do + include SystemCheck::Helpers + desc "GitLab | Check the configuration of Reply by email" task check: :environment do warn_user_is_not_gitlab @@ -757,6 +445,8 @@ namespace :gitlab do end namespace :ldap do + include SystemCheck::Helpers + task :check, [:limit] => :environment do |_, args| # Only show up to 100 results because LDAP directories can be very big. # This setting only affects the `rake gitlab:check` script. @@ -812,6 +502,8 @@ namespace :gitlab do end namespace :repo do + include SystemCheck::Helpers + desc "GitLab | Check the integrity of the repositories managed by GitLab" task check: :environment do Gitlab.config.repositories.storages.each do |name, repository_storage| @@ -826,6 +518,8 @@ namespace :gitlab do end namespace :user do + include SystemCheck::Helpers + desc "GitLab | Check the integrity of a specific user's repositories" task :check_repos, [:username] => :environment do |t, args| username = args[:username] || prompt("Check repository integrity for fsername? ".color(:blue)) @@ -848,60 +542,6 @@ namespace :gitlab do # Helper methods ########################## - # @deprecated Please use SystemChecks - def fix_and_rerun - puts " Please fix the error above and rerun the checks.".color(:red) - end - - # @deprecated Please use SystemChecks - def for_more_information(*sources) - sources = sources.shift if sources.first.is_a?(Array) - - puts " For more information see:".color(:blue) - sources.each do |source| - puts " #{source}" - end - end - - # @deprecated Please use SystemChecks - def finished_checking(component) - puts "" - puts "Checking #{component.color(:yellow)} ... #{"Finished".color(:green)}" - puts "" - end - - def see_database_guide - "doc/install/databases.md" - end - - def see_installation_guide_section(section) - "doc/install/installation.md in section \"#{section}\"" - end - - def sudo_gitlab(command) - "sudo -u #{gitlab_user} -H #{command}" - end - - def gitlab_user - Gitlab.config.gitlab.user - end - - # @deprecated Please use SystemChecks - def start_checking(component) - puts "Checking #{component.color(:yellow)} ..." - puts "" - end - - # @deprecated Please use SystemChecks - def try_fixing_it(*steps) - steps = steps.shift if steps.first.is_a?(Array) - - puts " Try fixing it:".color(:blue) - steps.each do |step| - puts " #{step}" - end - end - def check_gitlab_shell required_version = Gitlab::VersionInfo.new(gitlab_shell_major_version, gitlab_shell_minor_version, gitlab_shell_patch_version) current_version = Gitlab::VersionInfo.parse(gitlab_shell_version) @@ -914,65 +554,10 @@ namespace :gitlab do end end - def check_ruby_version - required_version = Gitlab::VersionInfo.new(2, 1, 0) - current_version = Gitlab::VersionInfo.parse(run_command(%w(ruby --version))) - - print "Ruby version >= #{required_version} ? ... " - - if current_version.valid? && required_version <= current_version - puts "yes (#{current_version})".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "Update your ruby to a version >= #{required_version} from #{current_version}" - ) - fix_and_rerun - end - end - - def check_git_version - required_version = Gitlab::VersionInfo.new(2, 7, 3) - current_version = Gitlab::VersionInfo.parse(run_command(%W(#{Gitlab.config.git.bin_path} --version))) - - puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\"" - print "Git version >= #{required_version} ? ... " - - if current_version.valid? && required_version <= current_version - puts "yes (#{current_version})".color(:green) - else - puts "no".color(:red) - try_fixing_it( - "Update your git to a version >= #{required_version} from #{current_version}" - ) - fix_and_rerun - end - end - def check_active_users puts "Active users: #{User.active.count}" end - def omnibus_gitlab? - Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails' - end - - def sanitized_message(project) - if should_sanitize? - "#{project.namespace_id.to_s.color(:yellow)}/#{project.id.to_s.color(:yellow)} ... " - else - "#{project.name_with_namespace.color(:yellow)} ... " - end - end - - def should_sanitize? - if ENV['SANITIZE'] == "true" - true - else - false - end - end - def check_repo_integrity(repo_dir) puts "\nChecking repo at #{repo_dir.color(:yellow)}" diff --git a/lib/tasks/gitlab/task_helpers.rb b/lib/tasks/gitlab/task_helpers.rb index e3c9d3b491c..e38e21b149f 100644 --- a/lib/tasks/gitlab/task_helpers.rb +++ b/lib/tasks/gitlab/task_helpers.rb @@ -113,6 +113,7 @@ module Gitlab end end + # TODO: MIGRATED # Tries to configure git itself # # Returns true if all subcommands were successfull (according to their exit code) -- cgit v1.2.3 From 27e632758feed94d8b3ff065b7c8928a854cecc5 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Fri, 26 May 2017 01:46:30 +0200 Subject: Add ActiveUsers Check --- lib/system_check/app/active_users_check.rb | 17 +++++++++++++++++ lib/tasks/gitlab/check.rake | 8 ++------ 2 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 lib/system_check/app/active_users_check.rb (limited to 'lib') diff --git a/lib/system_check/app/active_users_check.rb b/lib/system_check/app/active_users_check.rb new file mode 100644 index 00000000000..1d72c8d6903 --- /dev/null +++ b/lib/system_check/app/active_users_check.rb @@ -0,0 +1,17 @@ +module SystemCheck + module App + class ActiveUsersCheck < SystemCheck::BaseCheck + set_name 'Active users:' + + def multi_check + active_users = User.active.count + + if active_users > 0 + $stdout.puts active_users.to_s.color(:green) + else + $stdout.puts active_users.to_s.color(:red) + end + end + end + end +end diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 0d177663066..973517c99dd 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -32,11 +32,11 @@ namespace :gitlab do SystemCheck::App::ProjectsHaveNamespaceCheck, SystemCheck::App::RedisVersionCheck, SystemCheck::App::RubyVersionCheck, - SystemCheck::App::GitVersionCheck + SystemCheck::App::GitVersionCheck, + SystemCheck::App::ActiveUsersCheck ] SystemCheck.run('GitLab', checks) - check_active_users end end @@ -554,10 +554,6 @@ namespace :gitlab do end end - def check_active_users - puts "Active users: #{User.active.count}" - end - def check_repo_integrity(repo_dir) puts "\nChecking repo at #{repo_dir.color(:yellow)}" -- cgit v1.2.3 From ecdbde3d95b7abf11bae47d3a3b05693d84c27cc Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Fri, 26 May 2017 01:46:54 +0200 Subject: Improve Specs and some fixes --- lib/system_check/base_check.rb | 4 +++- lib/system_check/simple_executor.rb | 12 ++++++------ lib/tasks/gitlab/task_helpers.rb | 1 - 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb index aff830f54d7..63b7eea5add 100644 --- a/lib/system_check/base_check.rb +++ b/lib/system_check/base_check.rb @@ -1,9 +1,11 @@ +require 'tasks/gitlab/task_helpers' + module SystemCheck # Base class for Checks. You must inherit from here # and implement the methods below when necessary class BaseCheck include ::Gitlab::TaskHelpers - include Helpers + include ::SystemCheck::Helpers # Define a custom term for when check passed # diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb index 7a5042047ab..ad2f549b3fb 100644 --- a/lib/system_check/simple_executor.rb +++ b/lib/system_check/simple_executor.rb @@ -24,17 +24,17 @@ module SystemCheck c = check.new - # When implements a multi check, we don't control the output - if c.is_multi_check? - c.multi_check - return - end - # When implements skip method, we run it first, and if true, skip the check if c.can_skip? && c.skip? $stdout.puts check.skip_reason.color(:magenta) return end + + # When implements a multi check, we don't control the output + if c.is_multi_check? + c.multi_check + return + end if c.check? $stdout.puts check.check_pass.color(:green) diff --git a/lib/tasks/gitlab/task_helpers.rb b/lib/tasks/gitlab/task_helpers.rb index e38e21b149f..e3c9d3b491c 100644 --- a/lib/tasks/gitlab/task_helpers.rb +++ b/lib/tasks/gitlab/task_helpers.rb @@ -113,7 +113,6 @@ module Gitlab end end - # TODO: MIGRATED # Tries to configure git itself # # Returns true if all subcommands were successfull (according to their exit code) -- cgit v1.2.3 From bca5603740f77667dda6355c457ad1791b4fa42e Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Fri, 26 May 2017 02:34:25 +0200 Subject: Fix codestyle --- lib/system_check/app/git_version_check.rb | 2 +- lib/system_check/app/init_script_up_to_date_check.rb | 7 +++---- lib/system_check/app/projects_have_namespace_check.rb | 8 ++++---- lib/system_check/helpers.rb | 3 --- 4 files changed, 8 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/system_check/app/git_version_check.rb b/lib/system_check/app/git_version_check.rb index 3a128f00911..c388682dfb4 100644 --- a/lib/system_check/app/git_version_check.rb +++ b/lib/system_check/app/git_version_check.rb @@ -17,7 +17,7 @@ module SystemCheck end def show_error - puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\"" + $stdout.puts "Your git bin path is \"#{Gitlab.config.git.bin_path}\"" try_fixing_it( "Update your git to a version >= #{self.class.required_version} from #{self.class.current_version}" diff --git a/lib/system_check/app/init_script_up_to_date_check.rb b/lib/system_check/app/init_script_up_to_date_check.rb index 28c1451b8d2..015c7ed1731 100644 --- a/lib/system_check/app/init_script_up_to_date_check.rb +++ b/lib/system_check/app/init_script_up_to_date_check.rb @@ -14,7 +14,7 @@ module SystemCheck recipe_path = Rails.root.join('lib/support/init.d/', 'gitlab') unless File.exist?(SCRIPT_PATH) - puts "can't check because of previous errors".color(:magenta) + $stdout.puts "can't check because of previous errors".color(:magenta) return end @@ -22,14 +22,13 @@ module SystemCheck script_content = File.read(SCRIPT_PATH) if recipe_content == script_content - puts 'yes'.color(:green) + $stdout.puts 'yes'.color(:green) else - puts 'no'.color(:red) + $stdout.puts 'no'.color(:red) show_error end end - def show_error try_fixing_it( 'Re-download the init script' diff --git a/lib/system_check/app/projects_have_namespace_check.rb b/lib/system_check/app/projects_have_namespace_check.rb index d21ae225b0b..c70633a6d4f 100644 --- a/lib/system_check/app/projects_have_namespace_check.rb +++ b/lib/system_check/app/projects_have_namespace_check.rb @@ -9,15 +9,15 @@ module SystemCheck end def multi_check - puts '' + $stdout.puts '' Project.find_each(batch_size: 100) do |project| - print sanitized_message(project) + $stdout.print sanitized_message(project) if project.namespace - puts 'yes'.color(:green) + $stdout.puts 'yes'.color(:green) else - puts 'no'.color(:red) + $stdout.puts 'no'.color(:red) show_error end end diff --git a/lib/system_check/helpers.rb b/lib/system_check/helpers.rb index 91454c99838..0a6be42a7d1 100644 --- a/lib/system_check/helpers.rb +++ b/lib/system_check/helpers.rb @@ -75,6 +75,3 @@ module SystemCheck end end end - - - -- cgit v1.2.3 From 3f187751d40a687ab9b76857c04849bab0f84357 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Tue, 30 May 2017 19:06:58 +0200 Subject: Fixed and improved some existing checks and SystemCheck library --- lib/system_check.rb | 15 ++-------- .../app/database_config_exists_check.rb | 8 +----- lib/system_check/app/git_config_check.rb | 32 ++++++++-------------- .../app/gitlab_config_not_outdated_check.rb | 32 ---------------------- .../app/gitlab_config_up_to_date_check.rb | 30 ++++++++++++++++++++ .../app/projects_have_namespace_check.rb | 2 +- lib/system_check/app/ruby_version_check.rb | 2 +- lib/system_check/base_check.rb | 3 -- lib/system_check/helpers.rb | 13 +++++++-- lib/system_check/simple_executor.rb | 30 ++++++++++---------- lib/tasks/gitlab/check.rake | 2 +- lib/tasks/gitlab/task_helpers.rb | 19 +++++++------ 12 files changed, 85 insertions(+), 103 deletions(-) delete mode 100644 lib/system_check/app/gitlab_config_not_outdated_check.rb create mode 100644 lib/system_check/app/gitlab_config_up_to_date_check.rb (limited to 'lib') diff --git a/lib/system_check.rb b/lib/system_check.rb index e9cbf6b8258..466c39904fa 100644 --- a/lib/system_check.rb +++ b/lib/system_check.rb @@ -9,22 +9,13 @@ module SystemCheck # # @param [String] component name of the component relative to the checks being executed # @param [Array] checks classes of corresponding checks to be executed in the same order - # @param [BaseExecutor] executor_klass optionally specifiy a different executor class - def self.run(component, checks = [], executor_klass = SimpleExecutor) - unless executor_klass < BaseExecutor - raise ArgumentError, 'Invalid executor' - end - - prepare(component, checks, executor_klass).execute - end + def self.run(component, checks = []) + executor = SimpleExecutor.new(component) - def self.prepare(component, checks = [], executor_klass = SimpleExecutor) - executor = executor_klass.new(component) checks.each do |check| executor << check end - executor + executor.execute end - private_class_method :prepare end diff --git a/lib/system_check/app/database_config_exists_check.rb b/lib/system_check/app/database_config_exists_check.rb index d557cee47b4..d1fae192350 100644 --- a/lib/system_check/app/database_config_exists_check.rb +++ b/lib/system_check/app/database_config_exists_check.rb @@ -15,17 +15,11 @@ module SystemCheck 'Check that the information in config/database.yml is correct' ) for_more_information( - see_database_guide, + 'doc/install/databases.md', 'http://guides.rubyonrails.org/getting_started.html#configuring-a-database' ) fix_and_rerun end - - private - - def see_database_guide - 'doc/install/databases.md' - end end end end diff --git a/lib/system_check/app/git_config_check.rb b/lib/system_check/app/git_config_check.rb index 7f0c792eb35..198867f7ac6 100644 --- a/lib/system_check/app/git_config_check.rb +++ b/lib/system_check/app/git_config_check.rb @@ -5,7 +5,7 @@ module SystemCheck 'core.autocrlf' => 'input' }.freeze - set_name 'Git configured with autocrlf=input?' + set_name 'Git configured correctly?' def check? correct_options = OPTIONS.map do |name, value| @@ -15,8 +15,18 @@ module SystemCheck correct_options.all? end + # Tries to configure git itself + # + # Returns true if all subcommands were successful (according to their exit code) + # Returns false if any or all subcommands failed. def repair! - auto_fix_git_config(OPTIONS) + return false unless is_gitlab_user? + + command_success = OPTIONS.map do |name, value| + system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value})) + end + + command_success.all? end def show_error @@ -27,24 +37,6 @@ module SystemCheck see_installation_guide_section 'GitLab' ) end - - private - - # Tries to configure git itself - # - # Returns true if all subcommands were successfull (according to their exit code) - # Returns false if any or all subcommands failed. - def auto_fix_git_config(options) - if !@warned_user_not_gitlab - command_success = options.map do |name, value| - system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value})) - end - - command_success.all? - else - false - end - end end end end diff --git a/lib/system_check/app/gitlab_config_not_outdated_check.rb b/lib/system_check/app/gitlab_config_not_outdated_check.rb deleted file mode 100644 index 8a4d7b29977..00000000000 --- a/lib/system_check/app/gitlab_config_not_outdated_check.rb +++ /dev/null @@ -1,32 +0,0 @@ -module SystemCheck - module App - class GitlabConfigNotOutdatedCheck < SystemCheck::BaseCheck - set_name 'GitLab config outdated?' - set_check_pass 'no' - set_check_fail 'yes' - set_skip_reason "can't check because of previous errors" - - def skip? - gitlab_config_file = Rails.root.join('config', 'gitlab.yml') - !File.exist?(gitlab_config_file) - end - - def check? - # omniauth or ldap could have been deleted from the file - !Gitlab.config['git_host'] - end - - def show_error - try_fixing_it( - 'Backup your config/gitlab.yml', - 'Copy config/gitlab.yml.example to config/gitlab.yml', - 'Update config/gitlab.yml to match your setup' - ) - for_more_information( - see_installation_guide_section 'GitLab' - ) - fix_and_rerun - end - end - end -end diff --git a/lib/system_check/app/gitlab_config_up_to_date_check.rb b/lib/system_check/app/gitlab_config_up_to_date_check.rb new file mode 100644 index 00000000000..c609e48e133 --- /dev/null +++ b/lib/system_check/app/gitlab_config_up_to_date_check.rb @@ -0,0 +1,30 @@ +module SystemCheck + module App + class GitlabConfigUpToDateCheck < SystemCheck::BaseCheck + set_name 'GitLab config up to date?' + set_skip_reason "can't check because of previous errors" + + def skip? + gitlab_config_file = Rails.root.join('config', 'gitlab.yml') + !File.exist?(gitlab_config_file) + end + + def check? + # omniauth or ldap could have been deleted from the file + !Gitlab.config['git_host'] + end + + def show_error + try_fixing_it( + 'Back-up your config/gitlab.yml', + 'Copy config/gitlab.yml.example to config/gitlab.yml', + 'Update config/gitlab.yml to match your setup' + ) + for_more_information( + see_installation_guide_section 'GitLab' + ) + fix_and_rerun + end + end + end +end diff --git a/lib/system_check/app/projects_have_namespace_check.rb b/lib/system_check/app/projects_have_namespace_check.rb index c70633a6d4f..a6ec9f7665c 100644 --- a/lib/system_check/app/projects_have_namespace_check.rb +++ b/lib/system_check/app/projects_have_namespace_check.rb @@ -1,7 +1,7 @@ module SystemCheck module App class ProjectsHaveNamespaceCheck < SystemCheck::BaseCheck - set_name 'projects have namespace: ' + set_name 'Projects have namespace:' set_skip_reason "can't check, you have no projects" def skip? diff --git a/lib/system_check/app/ruby_version_check.rb b/lib/system_check/app/ruby_version_check.rb index 37b4d24aa55..fd82f5f8a4a 100644 --- a/lib/system_check/app/ruby_version_check.rb +++ b/lib/system_check/app/ruby_version_check.rb @@ -5,7 +5,7 @@ module SystemCheck set_check_pass -> { "yes (#{self.current_version})" } def self.required_version - @required_version ||= Gitlab::VersionInfo.new(2, 1, 0) + @required_version ||= Gitlab::VersionInfo.new(2, 3, 3) end def self.current_version diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb index 63b7eea5add..5dcb3f0886b 100644 --- a/lib/system_check/base_check.rb +++ b/lib/system_check/base_check.rb @@ -1,10 +1,7 @@ -require 'tasks/gitlab/task_helpers' - module SystemCheck # Base class for Checks. You must inherit from here # and implement the methods below when necessary class BaseCheck - include ::Gitlab::TaskHelpers include ::SystemCheck::Helpers # Define a custom term for when check passed diff --git a/lib/system_check/helpers.rb b/lib/system_check/helpers.rb index 0a6be42a7d1..cd54baa494f 100644 --- a/lib/system_check/helpers.rb +++ b/lib/system_check/helpers.rb @@ -1,5 +1,9 @@ +require 'tasks/gitlab/task_helpers' + module SystemCheck module Helpers + include ::Gitlab::TaskHelpers + # Display a message telling to fix and rerun the checks def fix_and_rerun $stdout.puts ' Please fix the error above and rerun the checks.'.color(:red) @@ -9,8 +13,6 @@ module SystemCheck # # @param [Array] sources one or more references (documentation or links) def for_more_information(*sources) - sources = sources.shift if sources.first.is_a?(Array) - $stdout.puts ' For more information see:'.color(:blue) sources.each do |source| $stdout.puts " #{source}" @@ -73,5 +75,12 @@ module SystemCheck def sudo_gitlab(command) "sudo -u #{gitlab_user} -H #{command}" end + + def is_gitlab_user? + return @is_gitlab_user unless @is_gitlab_user.nil? + + current_user = run_command(%w(whoami)).chomp + @is_gitlab_user = current_user == gitlab_user + end end end diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb index ad2f549b3fb..c5403693f7a 100644 --- a/lib/system_check/simple_executor.rb +++ b/lib/system_check/simple_executor.rb @@ -18,32 +18,32 @@ module SystemCheck # Executes a single check # - # @param [SystemCheck::BaseCheck] check - def run_check(check) - $stdout.print "#{check.display_name} ... " + # @param [SystemCheck::BaseCheck] check_klass + def run_check(check_klass) + $stdout.print "#{check_klass.display_name} ... " - c = check.new + check = check_klass.new # When implements skip method, we run it first, and if true, skip the check - if c.can_skip? && c.skip? - $stdout.puts check.skip_reason.color(:magenta) + if check.can_skip? && check.skip? + $stdout.puts check_klass.skip_reason.color(:magenta) return end - + # When implements a multi check, we don't control the output - if c.is_multi_check? - c.multi_check + if check.is_multi_check? + check.multi_check return end - if c.check? - $stdout.puts check.check_pass.color(:green) + if check.check? + $stdout.puts check_klass.check_pass.color(:green) else - $stdout.puts check.check_fail.color(:red) + $stdout.puts check_klass.check_fail.color(:red) - if c.can_repair? + if check.can_repair? $stdout.print 'Trying to fix error automatically. ...' - if c.repair! + if check.repair! $stdout.puts 'Success'.color(:green) return else @@ -51,7 +51,7 @@ module SystemCheck end end - c.show_error + check.show_error end end diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake index 973517c99dd..63c5e9b9c83 100644 --- a/lib/tasks/gitlab/check.rake +++ b/lib/tasks/gitlab/check.rake @@ -21,7 +21,7 @@ namespace :gitlab do SystemCheck::App::MigrationsAreUpCheck, SystemCheck::App::OrphanedGroupMembersCheck, SystemCheck::App::GitlabConfigExistsCheck, - SystemCheck::App::GitlabConfigNotOutdatedCheck, + SystemCheck::App::GitlabConfigUpToDateCheck, SystemCheck::App::LogWritableCheck, SystemCheck::App::TmpWritableCheck, SystemCheck::App::UploadsDirectoryExistsCheck, diff --git a/lib/tasks/gitlab/task_helpers.rb b/lib/tasks/gitlab/task_helpers.rb index e3c9d3b491c..e2307e41be1 100644 --- a/lib/tasks/gitlab/task_helpers.rb +++ b/lib/tasks/gitlab/task_helpers.rb @@ -99,16 +99,17 @@ module Gitlab end def warn_user_is_not_gitlab - unless @warned_user_not_gitlab - gitlab_user = Gitlab.config.gitlab.user + return if @warned_user_not_gitlab + + unless is_gitlab_user? current_user = run_command(%w(whoami)).chomp - unless current_user == gitlab_user - puts " Warning ".color(:black).background(:yellow) - puts " You are running as user #{current_user.color(:magenta)}, we hope you know what you are doing." - puts " Things may work\/fail for the wrong reasons." - puts " For correct results you should run this as user #{gitlab_user.color(:magenta)}." - puts "" - end + + puts " Warning ".color(:black).background(:yellow) + puts " You are running as user #{current_user.color(:magenta)}, we hope you know what you are doing." + puts " Things may work\/fail for the wrong reasons." + puts " For correct results you should run this as user #{gitlab_user.color(:magenta)}." + puts "" + @warned_user_not_gitlab = true end end -- cgit v1.2.3 From d219f9a691973708f70d9517765a2ec926d6d903 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Wed, 31 May 2017 11:32:11 +0200 Subject: Fix BasicExecutor specs --- lib/system_check/helpers.rb | 11 ----------- lib/tasks/gitlab/task_helpers.rb | 27 +++++++++++---------------- 2 files changed, 11 insertions(+), 27 deletions(-) (limited to 'lib') diff --git a/lib/system_check/helpers.rb b/lib/system_check/helpers.rb index cd54baa494f..c42ae4fe4c4 100644 --- a/lib/system_check/helpers.rb +++ b/lib/system_check/helpers.rb @@ -68,19 +68,8 @@ module SystemCheck Dir.pwd == '/opt/gitlab/embedded/service/gitlab-rails' end - def gitlab_user - Gitlab.config.gitlab.user - end - def sudo_gitlab(command) "sudo -u #{gitlab_user} -H #{command}" end - - def is_gitlab_user? - return @is_gitlab_user unless @is_gitlab_user.nil? - - current_user = run_command(%w(whoami)).chomp - @is_gitlab_user = current_user == gitlab_user - end end end diff --git a/lib/tasks/gitlab/task_helpers.rb b/lib/tasks/gitlab/task_helpers.rb index e2307e41be1..964aa0fe1bc 100644 --- a/lib/tasks/gitlab/task_helpers.rb +++ b/lib/tasks/gitlab/task_helpers.rb @@ -98,6 +98,17 @@ module Gitlab end end + def gitlab_user + Gitlab.config.gitlab.user + end + + def is_gitlab_user? + return @is_gitlab_user unless @is_gitlab_user.nil? + + current_user = run_command(%w(whoami)).chomp + @is_gitlab_user = current_user == gitlab_user + end + def warn_user_is_not_gitlab return if @warned_user_not_gitlab @@ -114,22 +125,6 @@ module Gitlab end end - # Tries to configure git itself - # - # Returns true if all subcommands were successfull (according to their exit code) - # Returns false if any or all subcommands failed. - def auto_fix_git_config(options) - if !@warned_user_not_gitlab - command_success = options.map do |name, value| - system(*%W(#{Gitlab.config.git.bin_path} config --global #{name} #{value})) - end - - command_success.all? - else - false - end - end - def all_repos Gitlab.config.repositories.storages.each_value do |repository_storage| IO.popen(%W(find #{repository_storage['path']} -mindepth 2 -maxdepth 2 -type d -name *.git)) do |find| -- cgit v1.2.3 From c881425b665b9c0b022dc2e213486aecc320ec7e Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 31 May 2017 14:40:50 +0200 Subject: Refine pipeline stages seeds class --- lib/ci/gitlab_ci_yaml_processor.rb | 2 +- lib/gitlab/ci/stage/seed.rb | 38 ------------------------- lib/gitlab/ci/stage/seeds.rb | 58 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 39 deletions(-) delete mode 100644 lib/gitlab/ci/stage/seed.rb create mode 100644 lib/gitlab/ci/stage/seeds.rb (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index aa6c94f26c8..5e6c3d029c6 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -51,7 +51,7 @@ module Ci end def stages_for_ref(ref, tag = false, trigger_request = nil) - stages = @stages.map do |stage| + stages = @stages.uniq.map do |stage| builds = builds_for_stage_and_ref(stage, ref, tag, trigger_request) { name: stage, builds_attributes: builds.to_a } if builds.any? diff --git a/lib/gitlab/ci/stage/seed.rb b/lib/gitlab/ci/stage/seed.rb deleted file mode 100644 index 95237bff5d7..00000000000 --- a/lib/gitlab/ci/stage/seed.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Gitlab - module Ci - module Stage - class Seed - attr_reader :name, :builds - - def initialize(name:, builds:) - @name = name - @builds = builds - end - - def pipeline=(pipeline) - trigger_request = pipeline.trigger_requests.first - - @builds.each do |attributes| - attributes.merge!( - pipeline: pipeline, - project: pipeline.project, - ref: pipeline.ref, - tag: pipeline.tag, - trigger_request: trigger_request - ) - end - end - - def user=(current_user) - @builds.each do |attributes| - attributes.merge!(user: current_user) - end - end - - def to_attributes - { name: @name, builds_attributes: @builds } - end - end - end - end -end diff --git a/lib/gitlab/ci/stage/seeds.rb b/lib/gitlab/ci/stage/seeds.rb new file mode 100644 index 00000000000..16c436b5d4f --- /dev/null +++ b/lib/gitlab/ci/stage/seeds.rb @@ -0,0 +1,58 @@ +module Gitlab + module Ci + module Stage + class Seeds + Seed = Struct.new(:stage, :jobs) + + def initialize + @stages = [] + end + + def stages + @stages.map(&:stage) + end + + def jobs + @stages.map(&:jobs).flatten + end + + def append_stage(stage, jobs) + @stages << Seed.new({ name: stage }, jobs) + end + + def pipeline=(pipeline) + trigger_request = pipeline.trigger_requests.first + + stages.each do |attributes| + attributes.merge!( + pipeline: pipeline, + project: pipeline.project, + ) + end + + jobs.each do |attributes| + attributes.merge!( + pipeline: pipeline, + project: pipeline.project, + ref: pipeline.ref, + tag: pipeline.tag, + trigger_request: trigger_request + ) + end + end + + def user=(current_user) + jobs.each do |attributes| + attributes.merge!(user: current_user) + end + end + + def to_attributes + @stages.map.with_index do |seed| + seed.stage.merge(builds_attributes: seed.jobs) + end + end + end + end + end +end -- cgit v1.2.3 From c72e21fd9764845a107005562ff8ce1c06cac431 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Wed, 31 May 2017 15:13:40 +0200 Subject: Return stage seeds object from YAML processor --- lib/ci/gitlab_ci_yaml_processor.rb | 12 ++++++------ lib/gitlab/ci/stage/seeds.rb | 6 +++++- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 5e6c3d029c6..4b0e87a945b 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -50,14 +50,14 @@ module Ci end end - def stages_for_ref(ref, tag = false, trigger_request = nil) - stages = @stages.uniq.map do |stage| - builds = builds_for_stage_and_ref(stage, ref, tag, trigger_request) + def stage_seeds(ref:, tag: false, trigger: nil) + Gitlab::Ci::Stage::Seeds.new.tap do |seeds| + @stages.uniq.each do |stage| + builds = builds_for_stage_and_ref(stage, ref, tag, trigger) - { name: stage, builds_attributes: builds.to_a } if builds.any? + seeds.append_stage(stage, builds) if builds.any? + end end - - stages.compact.sort_by { |stage| @stages.index(stage[:name]) } end def build_attributes(name) diff --git a/lib/gitlab/ci/stage/seeds.rb b/lib/gitlab/ci/stage/seeds.rb index 16c436b5d4f..cb5174a166b 100644 --- a/lib/gitlab/ci/stage/seeds.rb +++ b/lib/gitlab/ci/stage/seeds.rb @@ -8,6 +8,10 @@ module Gitlab @stages = [] end + def has_stages? + @stages.any? + end + def stages @stages.map(&:stage) end @@ -48,7 +52,7 @@ module Gitlab end def to_attributes - @stages.map.with_index do |seed| + @stages.map do |seed| seed.stage.merge(builds_attributes: seed.jobs) end end -- cgit v1.2.3 From 563c1ca01cf94e125a5d01669e6e8455da257246 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 30 May 2017 23:38:06 +0300 Subject: Fix: A diff comment on a change at last line of a file shows as two comments in discussion --- lib/gitlab/diff/line.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb index 0a15c6d9358..bd52ae47e9f 100644 --- a/lib/gitlab/diff/line.rb +++ b/lib/gitlab/diff/line.rb @@ -59,6 +59,10 @@ module Gitlab type == 'match' end + def discussable? + !['match', 'new-nonewline', 'old-nonewline'].include?(type) + end + def as_json(opts = nil) { type: type, -- cgit v1.2.3 From ea7269e4c66a51eb4c66b9022ba4c2b35d8ad012 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 31 May 2017 11:19:56 -0500 Subject: Remove entry variable --- lib/gitlab/git/repository.rb | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index c3bf32ca1cc..9d6adbdb4ac 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1006,40 +1006,39 @@ module Gitlab # Parses the contents of a .gitmodules file and returns a hash of # submodule information. def parse_gitmodules(commit, content) - results = {} + modules = {} name = nil - entry = nil content.each_line do |line| case line.strip when /\A\[submodule "(?[^"]+)"\]\z/ # Submodule header name = $~[:name] - entry = results[name] = {} + modules[name] = {} when /\A(?\w+)\s*=\s*(?.*)\z/ # Key/value pair key = $~[:key] value = $~[:value].chomp - next unless name && entry + next unless name && modules[name] - entry[key] = value + modules[name][key] = value if key == 'path' begin - entry['id'] = blob_content(commit, value) + modules[name]['id'] = blob_content(commit, value) rescue InvalidBlobName # The current entry is invalid - results.delete(name) - name = entry = nil + modules.delete(name) + name = nil end end when /\A#/ # Comment next else # Invalid line - name = entry = nil + name = nil end end - results + modules end # Returns true if +commit+ introduced changes to +path+, using commit -- cgit v1.2.3 From 0d4d9a6a63b2ac60ffeeeaef389295919c3119f4 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Wed, 31 May 2017 20:45:00 +0200 Subject: Refactor and move things around to improve in YAGNI perspective --- lib/system_check/base_executor.rb | 24 ------------------------ lib/system_check/simple_executor.rb | 24 +++++++++++++++++++++++- 2 files changed, 23 insertions(+), 25 deletions(-) delete mode 100644 lib/system_check/base_executor.rb (limited to 'lib') diff --git a/lib/system_check/base_executor.rb b/lib/system_check/base_executor.rb deleted file mode 100644 index f76f44f3a28..00000000000 --- a/lib/system_check/base_executor.rb +++ /dev/null @@ -1,24 +0,0 @@ -module SystemCheck - # @attr_reader [Array] checks classes of corresponding checks to be executed in the same order - # @attr_reader [String] component name of the component relative to the checks being executed - class BaseExecutor - attr_reader :checks - attr_reader :component - - # @param [String] component name of the component relative to the checks being executed - def initialize(component) - raise ArgumentError unless component.is_a? String - - @component = component - @checks = Set.new - end - - # Add a check to be executed - # - # @param [BaseCheck] check class - def <<(check) - raise ArgumentError unless check < BaseCheck - @checks << check - end - end -end diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb index c5403693f7a..dc2d4643a01 100644 --- a/lib/system_check/simple_executor.rb +++ b/lib/system_check/simple_executor.rb @@ -4,7 +4,29 @@ module SystemCheck # # There is no concurrency level and the output is progressively # printed into the STDOUT - class SimpleExecutor < BaseExecutor + # + # @attr_reader [Array] checks classes of corresponding checks to be executed in the same order + # @attr_reader [String] component name of the component relative to the checks being executed + class SimpleExecutor + attr_reader :checks + attr_reader :component + + # @param [String] component name of the component relative to the checks being executed + def initialize(component) + raise ArgumentError unless component.is_a? String + + @component = component + @checks = Set.new + end + + # Add a check to be executed + # + # @param [BaseCheck] check class + def <<(check) + raise ArgumentError unless check < BaseCheck + @checks << check + end + # Executes defined checks in the specified order and outputs confirmation or error information def execute start_checking(component) -- cgit v1.2.3 From 04cf618b6ff943527938f64a451a420b494b5a76 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 31 May 2017 14:41:25 -0500 Subject: Change no_limits to limits --- lib/api/commits.rb | 2 +- lib/api/entities.rb | 6 +++--- lib/api/v3/commits.rb | 2 +- lib/api/v3/entities.rb | 2 +- lib/gitlab/git/diff.rb | 2 +- lib/gitlab/git/diff_collection.rb | 8 ++++---- 6 files changed, 11 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 904993d1606..c6fc17cc391 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -176,7 +176,7 @@ module API } if params[:path] - commit.raw_diffs(no_limits: true).each do |diff| + commit.raw_diffs(limits: false).each do |diff| next unless diff.new_path == params[:path] lines = Gitlab::Diff::Parser.new.parse(diff.diff.each_line) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 9799fe68a76..5032bab77b7 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -331,7 +331,7 @@ module API class MergeRequestChanges < MergeRequest expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _| - compare.raw_diffs(no_limits: true).to_a + compare.raw_diffs(limits: false).to_a end end @@ -344,7 +344,7 @@ module API expose :commits, using: Entities::RepoCommit expose :diffs, using: Entities::RepoDiff do |compare, _| - compare.raw_diffs(no_limits: true).to_a + compare.raw_diffs(limits: false).to_a end end @@ -548,7 +548,7 @@ module API end expose :diffs, using: Entities::RepoDiff do |compare, options| - compare.diffs(no_limits: true).to_a + compare.diffs(limits: false).to_a end expose :compare_timeout do |compare, options| diff --git a/lib/api/v3/commits.rb b/lib/api/v3/commits.rb index ec6c6c7b298..5936f4700aa 100644 --- a/lib/api/v3/commits.rb +++ b/lib/api/v3/commits.rb @@ -167,7 +167,7 @@ module API } if params[:path] - commit.raw_diffs(no_limits: true).each do |diff| + commit.raw_diffs(limits: false).each do |diff| next unless diff.new_path == params[:path] lines = Gitlab::Diff::Parser.new.parse(diff.diff.each_line) diff --git a/lib/api/v3/entities.rb b/lib/api/v3/entities.rb index 7fbd4949850..7c5065dee90 100644 --- a/lib/api/v3/entities.rb +++ b/lib/api/v3/entities.rb @@ -226,7 +226,7 @@ module API class MergeRequestChanges < MergeRequest expose :diffs, as: :changes, using: ::API::Entities::RepoDiff do |compare, _| - compare.raw_diffs(no_limits: true).to_a + compare.raw_diffs(limits: false).to_a end end diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index 2462f766f17..ccccca96595 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -155,7 +155,7 @@ module Gitlab :include_untracked_content, :skip_binary_check, :include_typechange, :include_typechange_trees, :ignore_filemode, :recurse_ignored_dirs, :paths, - :max_files, :max_lines, :no_limits, :expanded] + :max_files, :max_lines, :limits, :expanded] if default_options actual_defaults = default_options.dup diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb index 9b217b9080d..334e06a6eca 100644 --- a/lib/gitlab/git/diff_collection.rb +++ b/lib/gitlab/git/diff_collection.rb @@ -13,7 +13,7 @@ module Gitlab @safe_max_files = [@max_files, DEFAULT_LIMITS[:max_files]].min @safe_max_lines = [@max_lines, DEFAULT_LIMITS[:max_lines]].min @safe_max_bytes = @safe_max_files * 5.kilobytes # Average 5 KB per file - @no_limits = !!options.fetch(:no_limits, false) + @enforce_limits = !!options.fetch(:limits, true) @expanded = !!options.fetch(:expanded, true) @line_count = 0 @@ -88,12 +88,12 @@ module Gitlab @iterator.each do |raw| @empty = false - if !@no_limits && i >= @max_files + if @enforce_limits && i >= @max_files @overflow = true break end - expanded = @no_limits || @expanded + expanded = !@enforce_limits || @expanded diff = Gitlab::Git::Diff.new(raw, expanded: expanded) @@ -104,7 +104,7 @@ module Gitlab @line_count += diff.line_count @byte_count += diff.diff.bytesize - if !@no_limits && (@line_count >= @max_lines || @byte_count >= @max_bytes) + if @enforce_limits && (@line_count >= @max_lines || @byte_count >= @max_bytes) # This last Diff instance pushes us over the lines limit. We stop and # discard it. @overflow = true -- cgit v1.2.3 From 47a0276e53de4635df43124607ac1a101d6f1b70 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 23 May 2017 17:10:07 +0200 Subject: Initial implementation for real time job view Added the needed keys and paths to a new entity, BuildDetailsEntity. Not renaming BuildEntity to BuildBasicEntity on explicit request. Most code now has test coverage, but not all. This will be added on later commits on this branch. Resolves gitlab-org/gitlab-ce#31397 --- lib/gitlab/etag_caching/router.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index d137cc1bae6..53f3f442bc3 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -9,7 +9,9 @@ module Gitlab # - Ending in `noteable/issue//notes` for the `issue_notes` route # - Ending in `issues/id`/realtime_changes` for the `issue_title` route USED_IN_ROUTES = %w[noteable issue notes issues realtime_changes - commit pipelines merge_requests new].freeze + commit pipelines merge_requests builds + new].freeze + RESERVED_WORDS = Gitlab::PathRegex::ILLEGAL_PROJECT_PATH_WORDS - USED_IN_ROUTES RESERVED_WORDS_REGEX = Regexp.union(*RESERVED_WORDS.map(&Regexp.method(:escape))) ROUTES = [ @@ -40,6 +42,10 @@ module Gitlab Gitlab::EtagCaching::Router::Route.new( %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/pipelines/\d+\.json\z), 'project_pipeline' + ), + Gitlab::EtagCaching::Router::Route.new( + %r(^(?!.*(#{RESERVED_WORDS_REGEX})).*/builds/\d+\.json\z), + 'project_build' ) ].freeze -- cgit v1.2.3 From 671284ba375109becbfa2a288032cdc7301b157b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Wed, 31 May 2017 21:06:01 +0000 Subject: Add feature toggles through Flipper --- lib/api/api.rb | 1 + lib/api/entities.rb | 22 ++++++++++++++++++++++ lib/api/features.rb | 36 ++++++++++++++++++++++++++++++++++++ lib/feature.rb | 41 +++++++++++++++++++++++++++++++++++++++++ lib/gitlab/gitaly_client.rb | 22 ++++++++++++++++++++-- 5 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 lib/api/features.rb create mode 100644 lib/feature.rb (limited to 'lib') diff --git a/lib/api/api.rb b/lib/api/api.rb index bbdd2039f43..7ae2f3cad40 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -94,6 +94,7 @@ module API mount ::API::DeployKeys mount ::API::Deployments mount ::API::Environments + mount ::API::Features mount ::API::Files mount ::API::Groups mount ::API::Internal diff --git a/lib/api/entities.rb b/lib/api/entities.rb index e10bd230ae2..fc8183a62c1 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -753,6 +753,28 @@ module API expose :impersonation end + class FeatureGate < Grape::Entity + expose :key + expose :value + end + + class Feature < Grape::Entity + expose :name + expose :state + expose :gates, using: FeatureGate do |model| + model.gates.map do |gate| + value = model.gate_values[gate.key] + + # By default all gate values are populated. Only show relevant ones. + if (value.is_a?(Integer) && value.zero?) || (value.is_a?(Set) && value.empty?) + next + end + + { key: gate.key, value: value } + end.compact + end + end + module JobRequest class JobInfo < Grape::Entity expose :name, :stage diff --git a/lib/api/features.rb b/lib/api/features.rb new file mode 100644 index 00000000000..cff0ba2ddff --- /dev/null +++ b/lib/api/features.rb @@ -0,0 +1,36 @@ +module API + class Features < Grape::API + before { authenticated_as_admin! } + + resource :features do + desc 'Get a list of all features' do + success Entities::Feature + end + get do + features = Feature.all + + present features, with: Entities::Feature, current_user: current_user + end + + desc 'Set the gate value for the given feature' do + success Entities::Feature + end + params do + requires :value, type: String, desc: '`true` or `false` to enable/disable, an integer for percentage of time' + end + post ':name' do + feature = Feature.get(params[:name]) + + if %w(0 false).include?(params[:value]) + feature.disable + elsif params[:value] == 'true' + feature.enable + else + feature.enable_percentage_of_time(params[:value].to_i) + end + + present feature, with: Entities::Feature, current_user: current_user + end + end + end +end diff --git a/lib/feature.rb b/lib/feature.rb new file mode 100644 index 00000000000..2e2b343f82c --- /dev/null +++ b/lib/feature.rb @@ -0,0 +1,41 @@ +require 'flipper/adapters/active_record' + +class Feature + # Classes to override flipper table names + class FlipperFeature < Flipper::Adapters::ActiveRecord::Feature + # Using `self.table_name` won't work. ActiveRecord bug? + superclass.table_name = 'features' + end + + class FlipperGate < Flipper::Adapters::ActiveRecord::Gate + superclass.table_name = 'feature_gates' + end + + class << self + def all + flipper.features.to_a + end + + def get(key) + flipper.feature(key) + end + + def persisted?(feature) + # Flipper creates on-memory features when asked for a not-yet-created one. + # If we want to check if a feature has been actually set, we look for it + # on the persisted features list. + all.map(&:name).include?(feature.name) + end + + private + + def flipper + @flipper ||= begin + adapter = Flipper::Adapters::ActiveRecord.new( + feature_class: FlipperFeature, gate_class: FlipperGate) + + Flipper.new(adapter) + end + end + end +end diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index 72466700c05..2343446bf22 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -2,6 +2,12 @@ require 'gitaly' module Gitlab module GitalyClient + module MigrationStatus + DISABLED = 1 + OPT_IN = 2 + OPT_OUT = 3 + end + SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'.freeze MUTEX = Mutex.new @@ -46,8 +52,20 @@ module Gitlab Gitlab.config.gitaly.enabled end - def self.feature_enabled?(feature) - enabled? && ENV["GITALY_#{feature.upcase}"] == '1' + def self.feature_enabled?(feature, status: MigrationStatus::OPT_IN) + return false if !enabled? || status == MigrationStatus::DISABLED + + feature = Feature.get("gitaly_#{feature}") + + # If the feature hasn't been set, turn it on if it's opt-out + return status == MigrationStatus::OPT_OUT unless Feature.persisted?(feature) + + if feature.percentage_of_time_value > 0 + # Probabilistically enable this feature + return Random.rand() * 100 < feature.percentage_of_time_value + end + + feature.enabled? end def self.migrate(feature) -- cgit v1.2.3 From c00d72b6f33d50b1c5cd6948d54b3addf11f9104 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Thu, 1 Jun 2017 11:55:18 +0200 Subject: Rename pipeline methods related to legacy stages --- lib/gitlab/data_builder/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb index 182a30fd74d..e47fb85b5ee 100644 --- a/lib/gitlab/data_builder/pipeline.rb +++ b/lib/gitlab/data_builder/pipeline.rb @@ -22,7 +22,7 @@ module Gitlab sha: pipeline.sha, before_sha: pipeline.before_sha, status: pipeline.status, - stages: pipeline.stages_name, + stages: pipeline.stages_names, created_at: pipeline.created_at, finished_at: pipeline.finished_at, duration: pipeline.duration -- cgit v1.2.3 From e61f38d79eb85a7c601bd146d5b8e48a8b4418e5 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 4 May 2017 23:02:51 +0200 Subject: Fix data inconsistency issue for old artifacts by moving them to a currently used path --- lib/api/jobs.rb | 2 +- lib/api/runner.rb | 2 +- lib/api/v3/builds.rb | 2 +- lib/backup/artifacts.rb | 2 +- lib/ci/api/builds.rb | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb index 0223957fde1..7f94b1afdc4 100644 --- a/lib/api/jobs.rb +++ b/lib/api/jobs.rb @@ -225,7 +225,7 @@ module API end def present_artifacts!(artifacts_file) - if !artifacts_file.file_storage? + if !artifacts_file.local_file? redirect_to(build.artifacts_file.url) elsif artifacts_file.exists? present_file!(artifacts_file.path, artifacts_file.filename) diff --git a/lib/api/runner.rb b/lib/api/runner.rb index 6fbb02cb3aa..ddcc0429de0 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -242,7 +242,7 @@ module API job = authenticate_job! artifacts_file = job.artifacts_file - unless artifacts_file.file_storage? + unless artifacts_file.local_file? return redirect_to job.artifacts_file.url end diff --git a/lib/api/v3/builds.rb b/lib/api/v3/builds.rb index 21935922414..7ce7b43e3bd 100644 --- a/lib/api/v3/builds.rb +++ b/lib/api/v3/builds.rb @@ -226,7 +226,7 @@ module API end def present_artifacts!(artifacts_file) - if !artifacts_file.file_storage? + if !artifacts_file.local_file? redirect_to(build.artifacts_file.url) elsif artifacts_file.exists? present_file!(artifacts_file.path, artifacts_file.filename) diff --git a/lib/backup/artifacts.rb b/lib/backup/artifacts.rb index 51fa3867e67..1f4bda6f588 100644 --- a/lib/backup/artifacts.rb +++ b/lib/backup/artifacts.rb @@ -3,7 +3,7 @@ require 'backup/files' module Backup class Artifacts < Files def initialize - super('artifacts', ArtifactUploader.artifacts_path) + super('artifacts', ArtifactUploader.local_artifacts_store) end def create_files_dir diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb index 67b269b330c..0f2044a54b4 100644 --- a/lib/ci/api/builds.rb +++ b/lib/ci/api/builds.rb @@ -187,7 +187,7 @@ module Ci build = authenticate_build! artifacts_file = build.artifacts_file - unless artifacts_file.file_storage? + unless artifacts_file.local_file? return redirect_to build.artifacts_file.url end -- cgit v1.2.3 From 6185d12c183b539ea06ab3550b2c21045d169ca4 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Thu, 1 Jun 2017 09:52:19 +0200 Subject: Add missing specs --- lib/api/helpers.rb | 10 ++++++++++ lib/api/jobs.rb | 10 ---------- lib/api/runner.rb | 11 +---------- lib/api/v3/builds.rb | 10 ---------- lib/ci/api/builds.rb | 8 ++++---- 5 files changed, 15 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index d61450f8258..81f6fc3201d 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -311,6 +311,16 @@ module API end end + def present_artifacts!(artifacts_file) + return not_found! unless artifacts_file.exists? + + if artifacts_file.file_storage? + present_file!(artifacts_file.path, artifacts_file.filename) + else + redirect_to(artifacts_file.url) + end + end + private def private_token diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb index 7f94b1afdc4..8a67de10bca 100644 --- a/lib/api/jobs.rb +++ b/lib/api/jobs.rb @@ -224,16 +224,6 @@ module API find_build(id) || not_found! end - def present_artifacts!(artifacts_file) - if !artifacts_file.local_file? - redirect_to(build.artifacts_file.url) - elsif artifacts_file.exists? - present_file!(artifacts_file.path, artifacts_file.filename) - else - not_found! - end - end - def filter_builds(builds, scope) return builds if scope.nil? || scope.empty? diff --git a/lib/api/runner.rb b/lib/api/runner.rb index ddcc0429de0..3fd0536dadd 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -241,16 +241,7 @@ module API get '/:id/artifacts' do job = authenticate_job! - artifacts_file = job.artifacts_file - unless artifacts_file.local_file? - return redirect_to job.artifacts_file.url - end - - unless artifacts_file.exists? - not_found! - end - - present_file!(artifacts_file.path, artifacts_file.filename) + present_artifacts!(job.artifacts_file) end end end diff --git a/lib/api/v3/builds.rb b/lib/api/v3/builds.rb index 7ce7b43e3bd..93ad9eb26b8 100644 --- a/lib/api/v3/builds.rb +++ b/lib/api/v3/builds.rb @@ -225,16 +225,6 @@ module API find_build(id) || not_found! end - def present_artifacts!(artifacts_file) - if !artifacts_file.local_file? - redirect_to(build.artifacts_file.url) - elsif artifacts_file.exists? - present_file!(artifacts_file.path, artifacts_file.filename) - else - not_found! - end - end - def filter_builds(builds, scope) return builds if scope.nil? || scope.empty? diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb index 0f2044a54b4..2285ef241d7 100644 --- a/lib/ci/api/builds.rb +++ b/lib/ci/api/builds.rb @@ -187,14 +187,14 @@ module Ci build = authenticate_build! artifacts_file = build.artifacts_file - unless artifacts_file.local_file? - return redirect_to build.artifacts_file.url - end - unless artifacts_file.exists? not_found! end + unless artifacts_file.file_storage? + return redirect_to build.artifacts_file.url + end + present_file!(artifacts_file.path, artifacts_file.filename) end -- cgit v1.2.3 From 9d699a90e3ee74a5b0b7284b33d4be41cb503bf4 Mon Sep 17 00:00:00 2001 From: Ruben Davila Date: Thu, 1 Jun 2017 15:07:56 -0500 Subject: Add new Rake task to simplify the compilation of PO files --- lib/tasks/gettext.rake | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib') diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake index 0aa21a4bd13..b27f7475115 100644 --- a/lib/tasks/gettext.rake +++ b/lib/tasks/gettext.rake @@ -11,4 +11,12 @@ namespace :gettext do "{#{folders}}/**/*.{#{exts}}" ) end + + task :compile do + # See: https://gitlab.com/gitlab-org/gitlab-ce/issues/33014#note_31218998 + FileUtils.touch(File.join(Rails.root, 'locale/gitlab.pot')) + + Rake::Task['gettext:pack'].invoke + Rake::Task['gettext:po_to_json'].invoke + end end -- cgit v1.2.3 From e564fe971f3dacb1a2a38ad984b865ae23e54400 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 1 Jun 2017 21:21:14 +0000 Subject: Rename `Gitlab::Git::EncodingHelper` to `Gitlab::EncodingHelper` --- lib/gitlab/encoding_helper.rb | 62 +++++++++++++++++++++++++++++++++++++ lib/gitlab/git/blame.rb | 2 +- lib/gitlab/git/blob.rb | 2 +- lib/gitlab/git/commit.rb | 2 +- lib/gitlab/git/diff.rb | 2 +- lib/gitlab/git/encoding_helper.rb | 64 --------------------------------------- lib/gitlab/git/ref.rb | 2 +- lib/gitlab/git/tree.rb | 2 +- 8 files changed, 68 insertions(+), 70 deletions(-) create mode 100644 lib/gitlab/encoding_helper.rb delete mode 100644 lib/gitlab/git/encoding_helper.rb (limited to 'lib') diff --git a/lib/gitlab/encoding_helper.rb b/lib/gitlab/encoding_helper.rb new file mode 100644 index 00000000000..dbe28e6bb93 --- /dev/null +++ b/lib/gitlab/encoding_helper.rb @@ -0,0 +1,62 @@ +module Gitlab + module EncodingHelper + extend self + + # This threshold is carefully tweaked to prevent usage of encodings detected + # by CharlockHolmes with low confidence. If CharlockHolmes confidence is low, + # we're better off sticking with utf8 encoding. + # Reason: git diff can return strings with invalid utf8 byte sequences if it + # truncates a diff in the middle of a multibyte character. In this case + # CharlockHolmes will try to guess the encoding and will likely suggest an + # obscure encoding with low confidence. + # There is a lot more info with this merge request: + # https://gitlab.com/gitlab-org/gitlab_git/merge_requests/77#note_4754193 + ENCODING_CONFIDENCE_THRESHOLD = 40 + + def encode!(message) + return nil unless message.respond_to? :force_encoding + + # if message is utf-8 encoding, just return it + message.force_encoding("UTF-8") + return message if message.valid_encoding? + + # return message if message type is binary + detect = CharlockHolmes::EncodingDetector.detect(message) + return message.force_encoding("BINARY") if detect && detect[:type] == :binary + + # force detected encoding if we have sufficient confidence. + if detect && detect[:encoding] && detect[:confidence] > ENCODING_CONFIDENCE_THRESHOLD + message.force_encoding(detect[:encoding]) + end + + # encode and clean the bad chars + message.replace clean(message) + rescue + encoding = detect ? detect[:encoding] : "unknown" + "--broken encoding: #{encoding}" + end + + def encode_utf8(message) + detect = CharlockHolmes::EncodingDetector.detect(message) + if detect + begin + CharlockHolmes::Converter.convert(message, detect[:encoding], 'UTF-8') + rescue ArgumentError => e + Rails.logger.warn("Ignoring error converting #{detect[:encoding]} into UTF8: #{e.message}") + + '' + end + else + clean(message) + end + end + + private + + def clean(message) + message.encode("UTF-16BE", undef: :replace, invalid: :replace, replace: "") + .encode("UTF-8") + .gsub("\0".encode("UTF-8"), "") + end + end +end diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb index 58193391926..66829a03c2e 100644 --- a/lib/gitlab/git/blame.rb +++ b/lib/gitlab/git/blame.rb @@ -1,7 +1,7 @@ module Gitlab module Git class Blame - include Gitlab::Git::EncodingHelper + include Gitlab::EncodingHelper attr_reader :lines, :blames diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb index 6b0a66365a7..d60e607b02b 100644 --- a/lib/gitlab/git/blob.rb +++ b/lib/gitlab/git/blob.rb @@ -2,7 +2,7 @@ module Gitlab module Git class Blob include Linguist::BlobHelper - include Gitlab::Git::EncodingHelper + include Gitlab::EncodingHelper # This number is the maximum amount of data that we want to display to # the user. We load as much as we can for encoding detection diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index 297531db4cc..bb04731f08c 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -2,7 +2,7 @@ module Gitlab module Git class Commit - include Gitlab::Git::EncodingHelper + include Gitlab::EncodingHelper attr_accessor :raw_commit, :head, :refs diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index ccccca96595..0594ac8e213 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -3,7 +3,7 @@ module Gitlab module Git class Diff TimeoutError = Class.new(StandardError) - include Gitlab::Git::EncodingHelper + include Gitlab::EncodingHelper # Diff properties attr_accessor :old_path, :new_path, :a_mode, :b_mode, :diff diff --git a/lib/gitlab/git/encoding_helper.rb b/lib/gitlab/git/encoding_helper.rb deleted file mode 100644 index f918074cb14..00000000000 --- a/lib/gitlab/git/encoding_helper.rb +++ /dev/null @@ -1,64 +0,0 @@ -module Gitlab - module Git - module EncodingHelper - extend self - - # This threshold is carefully tweaked to prevent usage of encodings detected - # by CharlockHolmes with low confidence. If CharlockHolmes confidence is low, - # we're better off sticking with utf8 encoding. - # Reason: git diff can return strings with invalid utf8 byte sequences if it - # truncates a diff in the middle of a multibyte character. In this case - # CharlockHolmes will try to guess the encoding and will likely suggest an - # obscure encoding with low confidence. - # There is a lot more info with this merge request: - # https://gitlab.com/gitlab-org/gitlab_git/merge_requests/77#note_4754193 - ENCODING_CONFIDENCE_THRESHOLD = 40 - - def encode!(message) - return nil unless message.respond_to? :force_encoding - - # if message is utf-8 encoding, just return it - message.force_encoding("UTF-8") - return message if message.valid_encoding? - - # return message if message type is binary - detect = CharlockHolmes::EncodingDetector.detect(message) - return message.force_encoding("BINARY") if detect && detect[:type] == :binary - - # force detected encoding if we have sufficient confidence. - if detect && detect[:encoding] && detect[:confidence] > ENCODING_CONFIDENCE_THRESHOLD - message.force_encoding(detect[:encoding]) - end - - # encode and clean the bad chars - message.replace clean(message) - rescue - encoding = detect ? detect[:encoding] : "unknown" - "--broken encoding: #{encoding}" - end - - def encode_utf8(message) - detect = CharlockHolmes::EncodingDetector.detect(message) - if detect - begin - CharlockHolmes::Converter.convert(message, detect[:encoding], 'UTF-8') - rescue ArgumentError => e - Rails.logger.warn("Ignoring error converting #{detect[:encoding]} into UTF8: #{e.message}") - - '' - end - else - clean(message) - end - end - - private - - def clean(message) - message.encode("UTF-16BE", undef: :replace, invalid: :replace, replace: "") - .encode("UTF-8") - .gsub("\0".encode("UTF-8"), "") - end - end - end -end diff --git a/lib/gitlab/git/ref.rb b/lib/gitlab/git/ref.rb index 37ef6836742..ebf7393dc61 100644 --- a/lib/gitlab/git/ref.rb +++ b/lib/gitlab/git/ref.rb @@ -1,7 +1,7 @@ module Gitlab module Git class Ref - include Gitlab::Git::EncodingHelper + include Gitlab::EncodingHelper # Branch or tag name # without "refs/tags|heads" prefix diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb index d41256d9a84..b9afa05c819 100644 --- a/lib/gitlab/git/tree.rb +++ b/lib/gitlab/git/tree.rb @@ -1,7 +1,7 @@ module Gitlab module Git class Tree - include Gitlab::Git::EncodingHelper + include Gitlab::EncodingHelper attr_accessor :id, :root_id, :name, :path, :type, :mode, :commit_id, :submodule_url -- cgit v1.2.3 From fe0b2f81c7c9680a11288e0cdffc3e80dc1e8d58 Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Fri, 2 Jun 2017 12:16:11 +0200 Subject: Refine implementation of pipeline stage seeds --- lib/ci/gitlab_ci_yaml_processor.rb | 15 +++++---- lib/gitlab/ci/stage/seed.rb | 49 ++++++++++++++++++++++++++++++ lib/gitlab/ci/stage/seeds.rb | 62 -------------------------------------- 3 files changed, 58 insertions(+), 68 deletions(-) create mode 100644 lib/gitlab/ci/stage/seed.rb delete mode 100644 lib/gitlab/ci/stage/seeds.rb (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 4b0e87a945b..22af2671b18 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -50,14 +50,17 @@ module Ci end end - def stage_seeds(ref:, tag: false, trigger: nil) - Gitlab::Ci::Stage::Seeds.new.tap do |seeds| - @stages.uniq.each do |stage| - builds = builds_for_stage_and_ref(stage, ref, tag, trigger) + def stage_seeds(pipeline) + trigger_request = pipeline.trigger_requests.first - seeds.append_stage(stage, builds) if builds.any? - end + seeds = @stages.uniq.map do |stage| + builds = builds_for_stage_and_ref( + stage, pipeline.ref, pipeline.tag?, trigger_request) + + Gitlab::Ci::Stage::Seed.new(pipeline, stage, builds) if builds.any? end + + seeds.compact end def build_attributes(name) diff --git a/lib/gitlab/ci/stage/seed.rb b/lib/gitlab/ci/stage/seed.rb new file mode 100644 index 00000000000..f81f9347b4d --- /dev/null +++ b/lib/gitlab/ci/stage/seed.rb @@ -0,0 +1,49 @@ +module Gitlab + module Ci + module Stage + class Seed + attr_reader :pipeline + delegate :project, to: :pipeline + + def initialize(pipeline, stage, jobs) + @pipeline = pipeline + @stage = { name: stage } + @jobs = jobs.to_a.dup + end + + def user=(current_user) + @jobs.map! do |attributes| + attributes.merge(user: current_user) + end + end + + def stage + @stage.merge(project: project) + end + + def builds + trigger = pipeline.trigger_requests.first + + @jobs.map do |attributes| + attributes.merge(project: project, + ref: pipeline.ref, + tag: pipeline.tag, + trigger_request: trigger) + end + end + + def create! + pipeline.stages.create!(stage).tap do |stage| + builds_attributes = builds.map do |attributes| + attributes.merge(stage_id: stage.id) + end + + pipeline.builds.create!(builds_attributes).each do |build| + yield build if block_given? + end + end + end + end + end + end +end diff --git a/lib/gitlab/ci/stage/seeds.rb b/lib/gitlab/ci/stage/seeds.rb deleted file mode 100644 index cb5174a166b..00000000000 --- a/lib/gitlab/ci/stage/seeds.rb +++ /dev/null @@ -1,62 +0,0 @@ -module Gitlab - module Ci - module Stage - class Seeds - Seed = Struct.new(:stage, :jobs) - - def initialize - @stages = [] - end - - def has_stages? - @stages.any? - end - - def stages - @stages.map(&:stage) - end - - def jobs - @stages.map(&:jobs).flatten - end - - def append_stage(stage, jobs) - @stages << Seed.new({ name: stage }, jobs) - end - - def pipeline=(pipeline) - trigger_request = pipeline.trigger_requests.first - - stages.each do |attributes| - attributes.merge!( - pipeline: pipeline, - project: pipeline.project, - ) - end - - jobs.each do |attributes| - attributes.merge!( - pipeline: pipeline, - project: pipeline.project, - ref: pipeline.ref, - tag: pipeline.tag, - trigger_request: trigger_request - ) - end - end - - def user=(current_user) - jobs.each do |attributes| - attributes.merge!(user: current_user) - end - end - - def to_attributes - @stages.map do |seed| - seed.stage.merge(builds_attributes: seed.jobs) - end - end - end - end - end -end -- cgit v1.2.3 From 578adc9bc603e743d85cc65ed0d8aa3201ccc619 Mon Sep 17 00:00:00 2001 From: Athar Hameed Date: Fri, 2 Jun 2017 14:27:30 +0800 Subject: Fix missing optional path parameter in "Create project for user" API --- lib/api/projects.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/api/projects.rb b/lib/api/projects.rb index d00d4fe1737..17008aa6d0f 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -129,6 +129,7 @@ module API params do requires :name, type: String, desc: 'The name of the project' requires :user_id, type: Integer, desc: 'The ID of a user' + optional :path, type: String, desc: 'The path of the repository' optional :default_branch, type: String, desc: 'The default branch of the project' use :optional_params use :create_params -- cgit v1.2.3 From 23db8409aafc6cdbae165056ec037e31096a8a66 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 1 Jun 2017 10:17:56 +0100 Subject: Skip loading application settings from the database when migrations are pending Various Rails initializers (metrics, sentry, etc) are run before migrations, which can lead to a mismatch between app/models/application_settings.rb and schema. --- lib/gitlab/current_settings.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 82576d197fe..9e14b35b0f8 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -19,7 +19,7 @@ module Gitlab settings = ::ApplicationSetting.last end - settings ||= ::ApplicationSetting.create_from_defaults unless ActiveRecord::Migrator.needs_migration? + settings ||= ::ApplicationSetting.create_from_defaults end settings || in_memory_application_settings @@ -46,7 +46,8 @@ module Gitlab active_db_connection = ActiveRecord::Base.connection.active? rescue false active_db_connection && - ActiveRecord::Base.connection.table_exists?('application_settings') + ActiveRecord::Base.connection.table_exists?('application_settings') && + !ActiveRecord::Migrator.needs_migration? rescue ActiveRecord::NoDatabaseError false end -- cgit v1.2.3 From 4d1e987ec3263feda7a2f3469e31f5839e25731b Mon Sep 17 00:00:00 2001 From: Ahmad Sherif Date: Tue, 30 May 2017 21:30:05 +0200 Subject: Use the new Gitaly CommitDiff RPC --- lib/gitlab/git/diff.rb | 20 ++++++++++---------- lib/gitlab/gitaly_client/commit.rb | 2 +- lib/gitlab/gitaly_client/diff.rb | 21 +++++++++++++++++++++ lib/gitlab/gitaly_client/diff_stitcher.rb | 31 +++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 lib/gitlab/gitaly_client/diff.rb create mode 100644 lib/gitlab/gitaly_client/diff_stitcher.rb (limited to 'lib') diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index ccccca96595..636cac3259d 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -189,7 +189,7 @@ module Gitlab prune_diff_if_eligible when Rugged::Patch, Rugged::Diff::Delta init_from_rugged(raw_diff) - when Gitaly::CommitDiffResponse + when Gitlab::GitalyClient::Diff init_from_gitaly(raw_diff) prune_diff_if_eligible when Gitaly::CommitDelta @@ -290,15 +290,15 @@ module Gitlab end end - def init_from_gitaly(msg) - @diff = msg.raw_chunks.join if msg.respond_to?(:raw_chunks) - @new_path = encode!(msg.to_path.dup) - @old_path = encode!(msg.from_path.dup) - @a_mode = msg.old_mode.to_s(8) - @b_mode = msg.new_mode.to_s(8) - @new_file = msg.from_id == BLANK_SHA - @renamed_file = msg.from_path != msg.to_path - @deleted_file = msg.to_id == BLANK_SHA + def init_from_gitaly(diff) + @diff = diff.patch if diff.respond_to?(:patch) + @new_path = encode!(diff.to_path.dup) + @old_path = encode!(diff.from_path.dup) + @a_mode = diff.old_mode.to_s(8) + @b_mode = diff.new_mode.to_s(8) + @new_file = diff.from_id == BLANK_SHA + @renamed_file = diff.from_path != diff.to_path + @deleted_file = diff.to_id == BLANK_SHA end def prune_diff_if_eligible diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb index 4491903d788..ba3da781dad 100644 --- a/lib/gitlab/gitaly_client/commit.rb +++ b/lib/gitlab/gitaly_client/commit.rb @@ -26,7 +26,7 @@ module Gitlab request_params[:ignore_whitespace_change] = options.fetch(:ignore_whitespace_change, false) response = diff_service_stub.commit_diff(Gitaly::CommitDiffRequest.new(request_params)) - Gitlab::Git::DiffCollection.new(response, options) + Gitlab::Git::DiffCollection.new(GitalyClient::DiffStitcher.new(response), options) end def commit_deltas(commit) diff --git a/lib/gitlab/gitaly_client/diff.rb b/lib/gitlab/gitaly_client/diff.rb new file mode 100644 index 00000000000..1e117b7e74a --- /dev/null +++ b/lib/gitlab/gitaly_client/diff.rb @@ -0,0 +1,21 @@ +module Gitlab + module GitalyClient + class Diff + FIELDS = %i(from_path to_path old_mode new_mode from_id to_id patch).freeze + + attr_accessor(*FIELDS) + + def initialize(params) + params.each do |key, val| + public_send(:"#{key}=", val) + end + end + + def ==(other) + FIELDS.all? do |field| + public_send(field) == other.public_send(field) + end + end + end + end +end diff --git a/lib/gitlab/gitaly_client/diff_stitcher.rb b/lib/gitlab/gitaly_client/diff_stitcher.rb new file mode 100644 index 00000000000..d84e8d752dc --- /dev/null +++ b/lib/gitlab/gitaly_client/diff_stitcher.rb @@ -0,0 +1,31 @@ +module Gitlab + module GitalyClient + class DiffStitcher + include Enumerable + + def initialize(rpc_response) + @rpc_response = rpc_response + end + + def each + current_diff = nil + + @rpc_response.each do |diff_msg| + if current_diff.nil? + diff_params = diff_msg.to_h.slice(*GitalyClient::Diff::FIELDS) + diff_params[:patch] = diff_msg.raw_patch_data + + current_diff = GitalyClient::Diff.new(diff_params) + else + current_diff.patch += diff_msg.raw_patch_data + end + + if diff_msg.end_of_patch + yield current_diff + current_diff = nil + end + end + end + end + end +end -- cgit v1.2.3 From 3d70eeb5bb9dac8073a149547dc3b85c90d65e7d Mon Sep 17 00:00:00 2001 From: Alexander Randa Date: Fri, 31 Mar 2017 12:54:38 +0000 Subject: Implement ability to update deploy keys --- lib/api/deploy_keys.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'lib') diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb index 8a54f7f3f05..7cdee8aced7 100644 --- a/lib/api/deploy_keys.rb +++ b/lib/api/deploy_keys.rb @@ -76,6 +76,27 @@ module API end end + desc 'Update an existing deploy key for a project' do + success Entities::SSHKey + end + params do + requires :key_id, type: Integer, desc: 'The ID of the deploy key' + optional :title, type: String, desc: 'The name of the deploy key' + optional :can_push, type: Boolean, desc: "Can deploy key push to the project's repository" + at_least_one_of :title, :can_push + end + put ":id/deploy_keys/:key_id" do + key = user_project.deploy_keys.find(params.delete(:key_id)) + + authorize!(:update_deploy_key, key) + + if key.update_attributes(declared_params(include_missing: false)) + present key, with: Entities::SSHKey + else + render_validation_error!(key) + end + end + desc 'Enable a deploy key for a project' do detail 'This feature was added in GitLab 8.11' success Entities::SSHKey -- cgit v1.2.3 From 4cfa5ce4a95379a9ebe08f57b170af4b5ee9a9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 2 Jun 2017 19:11:26 +0200 Subject: Enable the Style/PreferredHashMethods cop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- lib/api/helpers.rb | 2 +- lib/api/projects.rb | 4 ++-- lib/api/runner.rb | 2 +- lib/api/time_tracking_endpoints.rb | 2 +- lib/api/v3/projects.rb | 2 +- lib/api/v3/time_tracking_endpoints.rb | 2 +- lib/bitbucket/representation/pull_request_comment.rb | 4 ++-- lib/ci/api/builds.rb | 2 +- lib/gitlab/chat_commands/presenters/base.rb | 4 ++-- lib/gitlab/google_code_import/client.rb | 2 +- lib/gitlab/google_code_import/importer.rb | 18 +++++++++--------- lib/gitlab/route_map.rb | 4 ++-- lib/gitlab/visibility_level.rb | 2 +- lib/gitlab/workhorse.rb | 2 +- 14 files changed, 26 insertions(+), 26 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 81f6fc3201d..2c73a6fdc4e 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -158,7 +158,7 @@ module API params_hash = custom_params || params attrs = {} keys.each do |key| - if params_hash[key].present? || (params_hash.has_key?(key) && params_hash[key] == false) + if params_hash[key].present? || (params_hash.key?(key) && params_hash[key] == false) attrs[key] = params_hash[key] end end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 17008aa6d0f..deac3934d57 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -109,7 +109,7 @@ module API end post do attrs = declared_params(include_missing: false) - attrs[:builds_enabled] = attrs.delete(:jobs_enabled) if attrs.has_key?(:jobs_enabled) + attrs[:builds_enabled] = attrs.delete(:jobs_enabled) if attrs.key?(:jobs_enabled) project = ::Projects::CreateService.new(current_user, attrs).execute if project.saved? @@ -248,7 +248,7 @@ module API authorize! :rename_project, user_project if attrs[:name].present? authorize! :change_visibility_level, user_project if attrs[:visibility].present? - attrs[:builds_enabled] = attrs.delete(:jobs_enabled) if attrs.has_key?(:jobs_enabled) + attrs[:builds_enabled] = attrs.delete(:jobs_enabled) if attrs.key?(:jobs_enabled) result = ::Projects::UpdateService.new(user_project, current_user, attrs).execute diff --git a/lib/api/runner.rb b/lib/api/runner.rb index 3fd0536dadd..4552115b3e2 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -141,7 +141,7 @@ module API patch '/:id/trace' do job = authenticate_job! - error!('400 Missing header Content-Range', 400) unless request.headers.has_key?('Content-Range') + error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range') content_range = request.headers['Content-Range'] content_range = content_range.split('-') diff --git a/lib/api/time_tracking_endpoints.rb b/lib/api/time_tracking_endpoints.rb index 05b4b490e27..df4632346dd 100644 --- a/lib/api/time_tracking_endpoints.rb +++ b/lib/api/time_tracking_endpoints.rb @@ -5,7 +5,7 @@ module API included do helpers do def issuable_name - declared_params.has_key?(:issue_iid) ? 'issue' : 'merge_request' + declared_params.key?(:issue_iid) ? 'issue' : 'merge_request' end def issuable_key diff --git a/lib/api/v3/projects.rb b/lib/api/v3/projects.rb index 896c00b88e7..20976b9dd08 100644 --- a/lib/api/v3/projects.rb +++ b/lib/api/v3/projects.rb @@ -44,7 +44,7 @@ module API end def set_only_allow_merge_if_pipeline_succeeds! - if params.has_key?(:only_allow_merge_if_build_succeeds) + if params.key?(:only_allow_merge_if_build_succeeds) params[:only_allow_merge_if_pipeline_succeeds] = params.delete(:only_allow_merge_if_build_succeeds) end end diff --git a/lib/api/v3/time_tracking_endpoints.rb b/lib/api/v3/time_tracking_endpoints.rb index 81ae4e8137d..d5b90e435ba 100644 --- a/lib/api/v3/time_tracking_endpoints.rb +++ b/lib/api/v3/time_tracking_endpoints.rb @@ -6,7 +6,7 @@ module API included do helpers do def issuable_name - declared_params.has_key?(:issue_id) ? 'issue' : 'merge_request' + declared_params.key?(:issue_id) ? 'issue' : 'merge_request' end def issuable_key diff --git a/lib/bitbucket/representation/pull_request_comment.rb b/lib/bitbucket/representation/pull_request_comment.rb index 4f8efe03bae..c52acbc3ddc 100644 --- a/lib/bitbucket/representation/pull_request_comment.rb +++ b/lib/bitbucket/representation/pull_request_comment.rb @@ -22,11 +22,11 @@ module Bitbucket end def inline? - raw.has_key?('inline') + raw.key?('inline') end def has_parent? - raw.has_key?('parent') + raw.key?('parent') end private diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb index 2285ef241d7..e2e91ce99cd 100644 --- a/lib/ci/api/builds.rb +++ b/lib/ci/api/builds.rb @@ -88,7 +88,7 @@ module Ci patch ":id/trace.txt" do build = authenticate_build! - error!('400 Missing header Content-Range', 400) unless request.headers.has_key?('Content-Range') + error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range') content_range = request.headers['Content-Range'] content_range = content_range.split('-') diff --git a/lib/gitlab/chat_commands/presenters/base.rb b/lib/gitlab/chat_commands/presenters/base.rb index 2700a5a2ad5..05994bee79d 100644 --- a/lib/gitlab/chat_commands/presenters/base.rb +++ b/lib/gitlab/chat_commands/presenters/base.rb @@ -45,9 +45,9 @@ module Gitlab end def format_response(response) - response[:text] = format(response[:text]) if response.has_key?(:text) + response[:text] = format(response[:text]) if response.key?(:text) - if response.has_key?(:attachments) + if response.key?(:attachments) response[:attachments].each do |attachment| attachment[:pretext] = format(attachment[:pretext]) if attachment[:pretext] attachment[:text] = format(attachment[:text]) if attachment[:text] diff --git a/lib/gitlab/google_code_import/client.rb b/lib/gitlab/google_code_import/client.rb index 890bd9a3554..b1dbf554e41 100644 --- a/lib/gitlab/google_code_import/client.rb +++ b/lib/gitlab/google_code_import/client.rb @@ -14,7 +14,7 @@ module Gitlab end def valid? - raw_data.is_a?(Hash) && raw_data["kind"] == "projecthosting#user" && raw_data.has_key?("projects") + raw_data.is_a?(Hash) && raw_data["kind"] == "projecthosting#user" && raw_data.key?("projects") end def repos diff --git a/lib/gitlab/google_code_import/importer.rb b/lib/gitlab/google_code_import/importer.rb index 1b43440673c..ab38c0c3e34 100644 --- a/lib/gitlab/google_code_import/importer.rb +++ b/lib/gitlab/google_code_import/importer.rb @@ -95,7 +95,7 @@ module Gitlab labels = import_issue_labels(raw_issue) assignee_id = nil - if raw_issue.has_key?("owner") + if raw_issue.key?("owner") username = user_map[raw_issue["owner"]["name"]] if username.start_with?("@") @@ -144,7 +144,7 @@ module Gitlab def import_issue_comments(issue, comments) Note.transaction do while raw_comment = comments.shift - next if raw_comment.has_key?("deletedBy") + next if raw_comment.key?("deletedBy") content = format_content(raw_comment["content"]) updates = format_updates(raw_comment["updates"]) @@ -235,15 +235,15 @@ module Gitlab def format_updates(raw_updates) updates = [] - if raw_updates.has_key?("status") + if raw_updates.key?("status") updates << "*Status: #{raw_updates["status"]}*" end - if raw_updates.has_key?("owner") + if raw_updates.key?("owner") updates << "*Owner: #{user_map[raw_updates["owner"]]}*" end - if raw_updates.has_key?("cc") + if raw_updates.key?("cc") cc = raw_updates["cc"].map do |l| deleted = l.start_with?("-") l = l[1..-1] if deleted @@ -255,7 +255,7 @@ module Gitlab updates << "*Cc: #{cc.join(", ")}*" end - if raw_updates.has_key?("labels") + if raw_updates.key?("labels") labels = raw_updates["labels"].map do |l| deleted = l.start_with?("-") l = l[1..-1] if deleted @@ -267,11 +267,11 @@ module Gitlab updates << "*Labels: #{labels.join(", ")}*" end - if raw_updates.has_key?("mergedInto") + if raw_updates.key?("mergedInto") updates << "*Merged into: ##{raw_updates["mergedInto"]}*" end - if raw_updates.has_key?("blockedOn") + if raw_updates.key?("blockedOn") blocked_ons = raw_updates["blockedOn"].map do |raw_blocked_on| format_blocking_updates(raw_blocked_on) end @@ -279,7 +279,7 @@ module Gitlab updates << "*Blocked on: #{blocked_ons.join(", ")}*" end - if raw_updates.has_key?("blocking") + if raw_updates.key?("blocking") blockings = raw_updates["blocking"].map do |raw_blocked_on| format_blocking_updates(raw_blocked_on) end diff --git a/lib/gitlab/route_map.rb b/lib/gitlab/route_map.rb index 36791fae60f..877aa6e6a28 100644 --- a/lib/gitlab/route_map.rb +++ b/lib/gitlab/route_map.rb @@ -25,8 +25,8 @@ module Gitlab def parse_entry(entry) raise FormatError, 'Route map entry is not a hash' unless entry.is_a?(Hash) - raise FormatError, 'Route map entry does not have a source key' unless entry.has_key?('source') - raise FormatError, 'Route map entry does not have a public key' unless entry.has_key?('public') + raise FormatError, 'Route map entry does not have a source key' unless entry.key?('source') + raise FormatError, 'Route map entry does not have a public key' unless entry.key?('public') source_pattern = entry['source'] public_path = entry['public'] diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb index 2e31f4462f9..85da4c8660b 100644 --- a/lib/gitlab/visibility_level.rb +++ b/lib/gitlab/visibility_level.rb @@ -83,7 +83,7 @@ module Gitlab end def valid_level?(level) - options.has_value?(level) + options.value?(level) end def level_name(level) diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index 18d8b4f4744..7f27317775c 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -129,7 +129,7 @@ module Gitlab 'MaxSessionTime' => terminal[:max_session_time] } } - details['Terminal']['CAPem'] = terminal[:ca_pem] if terminal.has_key?(:ca_pem) + details['Terminal']['CAPem'] = terminal[:ca_pem] if terminal.key?(:ca_pem) details end -- cgit v1.2.3 From c890c6aaf2939bc19292947bd8268d724fa7ddce Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 1 Jun 2017 17:14:39 +0100 Subject: Allow users to be hard-deleted from the API --- lib/api/users.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/users.rb b/lib/api/users.rb index 3d83720b7b9..2070dbd8bc7 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -286,13 +286,14 @@ module API end params do requires :id, type: Integer, desc: 'The ID of the user' + optional :hard_delete, type: Boolean, desc: "Whether to remove a user's contributions" end delete ":id" do authenticated_as_admin! user = User.find_by(id: params[:id]) not_found!('User') unless user - DeleteUserWorker.perform_async(current_user.id, user.id) + DeleteUserWorker.perform_async(current_user.id, user.id, hard_delete: params[:hard_delete]) end desc 'Block a user. Available only for admins.' -- cgit v1.2.3 From 5bc099c2de1e05fa4dbe45b59caeced209834178 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Tue, 9 May 2017 09:39:28 +0200 Subject: Prometheus metrics first pass metrics wip --- lib/gitlab/metrics.rb | 65 ++++++++++++++++++++++++++++++-- lib/gitlab/metrics/dummy_metric.rb | 29 ++++++++++++++ lib/gitlab/metrics/prometheus_sampler.rb | 51 +++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 lib/gitlab/metrics/dummy_metric.rb create mode 100644 lib/gitlab/metrics/prometheus_sampler.rb (limited to 'lib') diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb index cb8db2f1e9f..e784ca785f0 100644 --- a/lib/gitlab/metrics.rb +++ b/lib/gitlab/metrics.rb @@ -1,3 +1,5 @@ +require 'prometheus/client' + module Gitlab module Metrics extend Gitlab::CurrentSettings @@ -9,6 +11,7 @@ module Gitlab def self.settings @settings ||= { enabled: current_application_settings[:metrics_enabled], + prometheus_metrics_enabled: true, pool_size: current_application_settings[:metrics_pool_size], timeout: current_application_settings[:metrics_timeout], method_call_threshold: current_application_settings[:metrics_method_call_threshold], @@ -19,10 +22,18 @@ module Gitlab } end - def self.enabled? + def self.prometheus_metrics_enabled? + settings[:prometheus_metrics_enabled] || false + end + + def self.influx_metrics_enabled? settings[:enabled] || false end + def self.enabled? + influx_metrics_enabled? || prometheus_metrics_enabled? || false + end + def self.mri? RUBY_ENGINE == 'ruby' end @@ -38,10 +49,58 @@ module Gitlab @pool end + def self.registry + @registry ||= ::Prometheus::Client.registry + end + + def self.counter(name, docstring, base_labels = {}) + dummy_metric || registry.get(name) || registry.counter(name, docstring, base_labels) + end + + def self.summary(name, docstring, base_labels = {}) + dummy_metric || registry.get(name) || registry.summary(name, docstring, base_labels) + end + + def self.gauge(name, docstring, base_labels = {}) + dummy_metric || registry.get(name) || registry.gauge(name, docstring, base_labels) + end + + def self.histogram(name, docstring, base_labels = {}, buckets = Histogram::DEFAULT_BUCKETS) + dummy_metric || registry.get(name) || registry.histogram(name, docstring, base_labels, buckets) + end + + def self.dummy_metric + unless prometheus_metrics_enabled? + DummyMetric.new + end + end + def self.submit_metrics(metrics) prepared = prepare_metrics(metrics) - pool.with do |connection| + if prometheus_metrics_enabled? + metrics.map do |metric| + known = [:series, :tags,:values, :timestamp] + value = metric&.[](:values)&.[](:value) + handled= [:rails_gc_statistics] + if handled.include? metric[:series].to_sym + next + end + + if metric.keys.any? {|k| !known.include?(k)} || value.nil? + print metric + print "\n" + + {:series=>"rails_gc_statistics", :tags=>{}, :values=>{:count=>0, :heap_allocated_pages=>4245, :heap_sorted_length=>4426, :heap_allocatable_pages=>0, :heap_available_slots=>1730264, :heap_live_slots=>1729935, :heap_free_slots=>329, :heap_final_slots=>0, :heap_marked_slots=>1184216, :heap_swept_slots=>361843, :heap_eden_pages=>4245, :heap_tomb_pages=>0, :total_allocated_pages=>4245, :total_freed_pages=>0, :total_allocated_objects=>15670757, :total_freed_objects=>13940822, :malloc_increase_bytes=>4842256, :malloc_increase_bytes_limit=>29129457, :minor_gc_count=>0, :major_gc_count=>0, :remembered_wb_unprotected_objects=>39905, :remembered_wb_unprotected_objects_limit=>74474, :old_objects=>1078731, :old_objects_limit=>1975860, :oldmalloc_increase_bytes=>4842640, :oldmalloc_increase_bytes_limit=>31509677, :total_time=>0.0}, :timestamp=>1494356175592659968} + + next + end + metric_value = gauge(metric[:series].to_sym, metric[:series]) + metric_value.set(metric[:tags], value) + end + end + + pool&.with do |connection| prepared.each_slice(settings[:packet_size]) do |slice| begin connection.write_points(slice) @@ -148,7 +207,7 @@ module Gitlab # When enabled this should be set before being used as the usual pattern # "@foo ||= bar" is _not_ thread-safe. - if enabled? + if influx_metrics_enabled? @pool = ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do host = settings[:host] port = settings[:port] diff --git a/lib/gitlab/metrics/dummy_metric.rb b/lib/gitlab/metrics/dummy_metric.rb new file mode 100644 index 00000000000..d27bb83854a --- /dev/null +++ b/lib/gitlab/metrics/dummy_metric.rb @@ -0,0 +1,29 @@ +module Gitlab + module Metrics + # Mocks ::Prometheus::Client::Metric and all derived metrics + class DummyMetric + def get(*args) + raise NotImplementedError + end + + def values(*args) + raise NotImplementedError + end + + # counter + def increment(*args) + # noop + end + + # gauge + def set(*args) + # noop + end + + # histogram / summary + def observe(*args) + # noop + end + end + end +end diff --git a/lib/gitlab/metrics/prometheus_sampler.rb b/lib/gitlab/metrics/prometheus_sampler.rb new file mode 100644 index 00000000000..5f90d4f0b66 --- /dev/null +++ b/lib/gitlab/metrics/prometheus_sampler.rb @@ -0,0 +1,51 @@ +module Gitlab + module Metrics + # Class that sends certain metrics to InfluxDB at a specific interval. + # + # This class is used to gather statistics that can't be directly associated + # with a transaction such as system memory usage, garbage collection + # statistics, etc. + class PrometheusSamples + # interval - The sampling interval in seconds. + def initialize(interval = Metrics.settings[:sample_interval]) + interval_half = interval.to_f / 2 + + @interval = interval + @interval_steps = (-interval_half..interval_half).step(0.1).to_a + end + + def start + Thread.new do + Thread.current.abort_on_exception = true + + loop do + sleep(sleep_interval) + + sample + end + end + end + + def sidekiq? + Sidekiq.server? + end + + # Returns the sleep interval with a random adjustment. + # + # The random adjustment is put in place to ensure we: + # + # 1. Don't generate samples at the exact same interval every time (thus + # potentially missing anything that happens in between samples). + # 2. Don't sample data at the same interval two times in a row. + def sleep_interval + while step = @interval_steps.sample + if step != @last_step + @last_step = step + + return @interval + @last_step + end + end + end + end + end +end -- cgit v1.2.3 From c28546177e2b4d5f7f3cc0e5b3a7b404206565fb Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Fri, 19 May 2017 12:49:15 +0200 Subject: Prometheus settings --- lib/api/settings.rb | 1 + lib/gitlab/metrics.rb | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/api/settings.rb b/lib/api/settings.rb index 82f513c984e..25027c3b114 100644 --- a/lib/api/settings.rb +++ b/lib/api/settings.rb @@ -110,6 +110,7 @@ module API optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts" optional :max_pages_size, type: Integer, desc: 'Maximum size of pages in MB' optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)' + optional :prometheus_metrics_enabled, type: Boolean, desc: 'Enable Prometheus metrics' optional :metrics_enabled, type: Boolean, desc: 'Enable the InfluxDB metrics' given metrics_enabled: ->(val) { val } do requires :metrics_host, type: String, desc: 'The InfluxDB host' diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb index e784ca785f0..6f50c0aa028 100644 --- a/lib/gitlab/metrics.rb +++ b/lib/gitlab/metrics.rb @@ -10,15 +10,15 @@ module Gitlab def self.settings @settings ||= { - enabled: current_application_settings[:metrics_enabled], - prometheus_metrics_enabled: true, - pool_size: current_application_settings[:metrics_pool_size], - timeout: current_application_settings[:metrics_timeout], - method_call_threshold: current_application_settings[:metrics_method_call_threshold], - host: current_application_settings[:metrics_host], - port: current_application_settings[:metrics_port], - sample_interval: current_application_settings[:metrics_sample_interval] || 15, - packet_size: current_application_settings[:metrics_packet_size] || 1 + enabled: current_application_settings[:metrics_enabled], + prometheus_metrics_enabled: current_application_settings[:prometheus_metrics_enabled], + pool_size: current_application_settings[:metrics_pool_size], + timeout: current_application_settings[:metrics_timeout], + method_call_threshold: current_application_settings[:metrics_method_call_threshold], + host: current_application_settings[:metrics_host], + port: current_application_settings[:metrics_port], + sample_interval: current_application_settings[:metrics_sample_interval] || 15, + packet_size: current_application_settings[:metrics_packet_size] || 1 } end @@ -31,7 +31,7 @@ module Gitlab end def self.enabled? - influx_metrics_enabled? || prometheus_metrics_enabled? || false + influx_metrics_enabled? || prometheus_metrics_enabled? end def self.mri? -- cgit v1.2.3 From 0f4050430d400daffbc5a68b15d79b896bb8a692 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Fri, 19 May 2017 17:03:10 +0200 Subject: Split metrics from health controller into metrics controller --- lib/gitlab/metrics.rb | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb index 6f50c0aa028..9783d4e3582 100644 --- a/lib/gitlab/metrics.rb +++ b/lib/gitlab/metrics.rb @@ -78,28 +78,6 @@ module Gitlab def self.submit_metrics(metrics) prepared = prepare_metrics(metrics) - if prometheus_metrics_enabled? - metrics.map do |metric| - known = [:series, :tags,:values, :timestamp] - value = metric&.[](:values)&.[](:value) - handled= [:rails_gc_statistics] - if handled.include? metric[:series].to_sym - next - end - - if metric.keys.any? {|k| !known.include?(k)} || value.nil? - print metric - print "\n" - - {:series=>"rails_gc_statistics", :tags=>{}, :values=>{:count=>0, :heap_allocated_pages=>4245, :heap_sorted_length=>4426, :heap_allocatable_pages=>0, :heap_available_slots=>1730264, :heap_live_slots=>1729935, :heap_free_slots=>329, :heap_final_slots=>0, :heap_marked_slots=>1184216, :heap_swept_slots=>361843, :heap_eden_pages=>4245, :heap_tomb_pages=>0, :total_allocated_pages=>4245, :total_freed_pages=>0, :total_allocated_objects=>15670757, :total_freed_objects=>13940822, :malloc_increase_bytes=>4842256, :malloc_increase_bytes_limit=>29129457, :minor_gc_count=>0, :major_gc_count=>0, :remembered_wb_unprotected_objects=>39905, :remembered_wb_unprotected_objects_limit=>74474, :old_objects=>1078731, :old_objects_limit=>1975860, :oldmalloc_increase_bytes=>4842640, :oldmalloc_increase_bytes_limit=>31509677, :total_time=>0.0}, :timestamp=>1494356175592659968} - - next - end - metric_value = gauge(metric[:series].to_sym, metric[:series]) - metric_value.set(metric[:tags], value) - end - end - pool&.with do |connection| prepared.each_slice(settings[:packet_size]) do |slice| begin -- cgit v1.2.3 From 138a5577a9e083933c02675dfa11112693ca7a94 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Fri, 19 May 2017 17:23:34 +0200 Subject: remove prometheus sampler --- lib/gitlab/metrics/prometheus_sampler.rb | 51 -------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 lib/gitlab/metrics/prometheus_sampler.rb (limited to 'lib') diff --git a/lib/gitlab/metrics/prometheus_sampler.rb b/lib/gitlab/metrics/prometheus_sampler.rb deleted file mode 100644 index 5f90d4f0b66..00000000000 --- a/lib/gitlab/metrics/prometheus_sampler.rb +++ /dev/null @@ -1,51 +0,0 @@ -module Gitlab - module Metrics - # Class that sends certain metrics to InfluxDB at a specific interval. - # - # This class is used to gather statistics that can't be directly associated - # with a transaction such as system memory usage, garbage collection - # statistics, etc. - class PrometheusSamples - # interval - The sampling interval in seconds. - def initialize(interval = Metrics.settings[:sample_interval]) - interval_half = interval.to_f / 2 - - @interval = interval - @interval_steps = (-interval_half..interval_half).step(0.1).to_a - end - - def start - Thread.new do - Thread.current.abort_on_exception = true - - loop do - sleep(sleep_interval) - - sample - end - end - end - - def sidekiq? - Sidekiq.server? - end - - # Returns the sleep interval with a random adjustment. - # - # The random adjustment is put in place to ensure we: - # - # 1. Don't generate samples at the exact same interval every time (thus - # potentially missing anything that happens in between samples). - # 2. Don't sample data at the same interval two times in a row. - def sleep_interval - while step = @interval_steps.sample - if step != @last_step - @last_step = step - - return @interval + @last_step - end - end - end - end - end -end -- cgit v1.2.3 From ef9d9ddeb2e063fa8ed1b01e4f82cc9662b919b2 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Mon, 22 May 2017 15:47:04 +0200 Subject: Add tests for metrics behavior --- lib/gitlab/metrics.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb index 9783d4e3582..a41cbd214a1 100644 --- a/lib/gitlab/metrics.rb +++ b/lib/gitlab/metrics.rb @@ -54,23 +54,25 @@ module Gitlab end def self.counter(name, docstring, base_labels = {}) - dummy_metric || registry.get(name) || registry.counter(name, docstring, base_labels) + provide_metric(name) || registry.counter(name, docstring, base_labels) end def self.summary(name, docstring, base_labels = {}) - dummy_metric || registry.get(name) || registry.summary(name, docstring, base_labels) + provide_metric(name) || registry.summary(name, docstring, base_labels) end def self.gauge(name, docstring, base_labels = {}) - dummy_metric || registry.get(name) || registry.gauge(name, docstring, base_labels) + provide_metric(name) || registry.gauge(name, docstring, base_labels) end - def self.histogram(name, docstring, base_labels = {}, buckets = Histogram::DEFAULT_BUCKETS) - dummy_metric || registry.get(name) || registry.histogram(name, docstring, base_labels, buckets) + def self.histogram(name, docstring, base_labels = {}, buckets = ::Prometheus::Client::Histogram::DEFAULT_BUCKETS) + provide_metric(name) || registry.histogram(name, docstring, base_labels, buckets) end - def self.dummy_metric - unless prometheus_metrics_enabled? + def self.provide_metric(name) + if prometheus_metrics_enabled? + registry.get(name) + else DummyMetric.new end end -- cgit v1.2.3 From c134a72cdb7e6de8b70dc60de99cf4edc68a9227 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Mon, 29 May 2017 14:19:43 +0200 Subject: Move Prometheus presentation logic to PrometheusText + Use NullMetrics to mock metrics when unused + Use method_missing in NullMetrics mocking + Update prometheus gem to version that correctly uses transitive dependencies + Ensure correct folders are used in Multiprocess prometheus client tests. + rename Sessions controller's metric --- lib/gitlab/health_checks/prometheus_text.rb | 38 +++++++++++++++++++++++++++++ lib/gitlab/metrics.rb | 2 +- lib/gitlab/metrics/dummy_metric.rb | 29 ---------------------- lib/gitlab/metrics/null_metric.rb | 19 +++++++++++++++ 4 files changed, 58 insertions(+), 30 deletions(-) create mode 100644 lib/gitlab/health_checks/prometheus_text.rb delete mode 100644 lib/gitlab/metrics/dummy_metric.rb create mode 100644 lib/gitlab/metrics/null_metric.rb (limited to 'lib') diff --git a/lib/gitlab/health_checks/prometheus_text.rb b/lib/gitlab/health_checks/prometheus_text.rb new file mode 100644 index 00000000000..a01e6b2be1f --- /dev/null +++ b/lib/gitlab/health_checks/prometheus_text.rb @@ -0,0 +1,38 @@ +module Gitlab::HealthChecks + class PrometheusText + def marshal(metrics) + metrics_with_type_declarations(metrics).join("\n") + end + + private + + def metrics_with_type_declarations(metrics) + type_declaration_added = {} + + metrics.flat_map do |metric| + metric_lines = [] + + unless type_declaration_added.has_key?(metric.name) + type_declaration_added[metric.name] = true + metric_lines << metric_type_declaration(metric) + end + + metric_lines << metric_text(metric) + end + end + + def metric_type_declaration(metric) + "# TYPE #{metric.name} gauge" + end + + def metric_text(metric) + labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || '' + + if labels.empty? + "#{metric.name} #{metric.value}" + else + "#{metric.name}{#{labels}} #{metric.value}" + end + end + end +end diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb index a41cbd214a1..34f6b32f7da 100644 --- a/lib/gitlab/metrics.rb +++ b/lib/gitlab/metrics.rb @@ -73,7 +73,7 @@ module Gitlab if prometheus_metrics_enabled? registry.get(name) else - DummyMetric.new + NullMetric.new end end diff --git a/lib/gitlab/metrics/dummy_metric.rb b/lib/gitlab/metrics/dummy_metric.rb deleted file mode 100644 index d27bb83854a..00000000000 --- a/lib/gitlab/metrics/dummy_metric.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Gitlab - module Metrics - # Mocks ::Prometheus::Client::Metric and all derived metrics - class DummyMetric - def get(*args) - raise NotImplementedError - end - - def values(*args) - raise NotImplementedError - end - - # counter - def increment(*args) - # noop - end - - # gauge - def set(*args) - # noop - end - - # histogram / summary - def observe(*args) - # noop - end - end - end -end diff --git a/lib/gitlab/metrics/null_metric.rb b/lib/gitlab/metrics/null_metric.rb new file mode 100644 index 00000000000..1501cd38676 --- /dev/null +++ b/lib/gitlab/metrics/null_metric.rb @@ -0,0 +1,19 @@ +module Gitlab + module Metrics + # Mocks ::Prometheus::Client::Metric and all derived metrics + class NullMetric + def method_missing(name, *args, &block) + nil + end + + # these methods shouldn't be called when metrics are disabled + def get(*args) + raise NotImplementedError + end + + def values(*args) + raise NotImplementedError + end + end + end +end -- cgit v1.2.3 From ae8f7666e597493ab404f8524c1216a924338291 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Mon, 29 May 2017 23:23:19 +0200 Subject: Add prometheus text formatter + rename controler method to #index from #metrics + remove assertion from nullMetric --- lib/gitlab/health_checks/prometheus_text.rb | 38 ---------------------- lib/gitlab/health_checks/prometheus_text_format.rb | 38 ++++++++++++++++++++++ lib/gitlab/metrics/null_metric.rb | 9 ----- 3 files changed, 38 insertions(+), 47 deletions(-) delete mode 100644 lib/gitlab/health_checks/prometheus_text.rb create mode 100644 lib/gitlab/health_checks/prometheus_text_format.rb (limited to 'lib') diff --git a/lib/gitlab/health_checks/prometheus_text.rb b/lib/gitlab/health_checks/prometheus_text.rb deleted file mode 100644 index a01e6b2be1f..00000000000 --- a/lib/gitlab/health_checks/prometheus_text.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Gitlab::HealthChecks - class PrometheusText - def marshal(metrics) - metrics_with_type_declarations(metrics).join("\n") - end - - private - - def metrics_with_type_declarations(metrics) - type_declaration_added = {} - - metrics.flat_map do |metric| - metric_lines = [] - - unless type_declaration_added.has_key?(metric.name) - type_declaration_added[metric.name] = true - metric_lines << metric_type_declaration(metric) - end - - metric_lines << metric_text(metric) - end - end - - def metric_type_declaration(metric) - "# TYPE #{metric.name} gauge" - end - - def metric_text(metric) - labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || '' - - if labels.empty? - "#{metric.name} #{metric.value}" - else - "#{metric.name}{#{labels}} #{metric.value}" - end - end - end -end diff --git a/lib/gitlab/health_checks/prometheus_text_format.rb b/lib/gitlab/health_checks/prometheus_text_format.rb new file mode 100644 index 00000000000..5fc6f19c37c --- /dev/null +++ b/lib/gitlab/health_checks/prometheus_text_format.rb @@ -0,0 +1,38 @@ +module Gitlab::HealthChecks + class PrometheusTextFormat + def marshal(metrics) + metrics_with_type_declarations(metrics).join("\n") + end + + private + + def metrics_with_type_declarations(metrics) + type_declaration_added = {} + + metrics.flat_map do |metric| + metric_lines = [] + + unless type_declaration_added.has_key?(metric.name) + type_declaration_added[metric.name] = true + metric_lines << metric_type_declaration(metric) + end + + metric_lines << metric_text(metric) + end + end + + def metric_type_declaration(metric) + "# TYPE #{metric.name} gauge" + end + + def metric_text(metric) + labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || '' + + if labels.empty? + "#{metric.name} #{metric.value}" + else + "#{metric.name}{#{labels}} #{metric.value}" + end + end + end +end diff --git a/lib/gitlab/metrics/null_metric.rb b/lib/gitlab/metrics/null_metric.rb index 1501cd38676..3b5a2907195 100644 --- a/lib/gitlab/metrics/null_metric.rb +++ b/lib/gitlab/metrics/null_metric.rb @@ -5,15 +5,6 @@ module Gitlab def method_missing(name, *args, &block) nil end - - # these methods shouldn't be called when metrics are disabled - def get(*args) - raise NotImplementedError - end - - def values(*args) - raise NotImplementedError - end end end end -- cgit v1.2.3 From b668aaf4268d552315152057729f73f5c5d72147 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Tue, 30 May 2017 00:18:46 +0200 Subject: Split the metrics implementation to separate modules for Influx and Prometheus --- lib/gitlab/health_checks/prometheus_text_format.rb | 54 +++--- lib/gitlab/metrics.rb | 196 +-------------------- lib/gitlab/metrics/influx_db.rb | 163 +++++++++++++++++ lib/gitlab/metrics/prometheus.rb | 41 +++++ 4 files changed, 235 insertions(+), 219 deletions(-) create mode 100644 lib/gitlab/metrics/influx_db.rb create mode 100644 lib/gitlab/metrics/prometheus.rb (limited to 'lib') diff --git a/lib/gitlab/health_checks/prometheus_text_format.rb b/lib/gitlab/health_checks/prometheus_text_format.rb index 5fc6f19c37c..e7ec1c516a2 100644 --- a/lib/gitlab/health_checks/prometheus_text_format.rb +++ b/lib/gitlab/health_checks/prometheus_text_format.rb @@ -1,38 +1,40 @@ -module Gitlab::HealthChecks - class PrometheusTextFormat - def marshal(metrics) - metrics_with_type_declarations(metrics).join("\n") - end +module Gitlab + module HealthChecks + class PrometheusTextFormat + def marshal(metrics) + metrics_with_type_declarations(metrics).join("\n") + end - private + private - def metrics_with_type_declarations(metrics) - type_declaration_added = {} + def metrics_with_type_declarations(metrics) + type_declaration_added = {} - metrics.flat_map do |metric| - metric_lines = [] + metrics.flat_map do |metric| + metric_lines = [] - unless type_declaration_added.has_key?(metric.name) - type_declaration_added[metric.name] = true - metric_lines << metric_type_declaration(metric) - end + unless type_declaration_added.has_key?(metric.name) + type_declaration_added[metric.name] = true + metric_lines << metric_type_declaration(metric) + end - metric_lines << metric_text(metric) + metric_lines << metric_text(metric) + end end - end - def metric_type_declaration(metric) - "# TYPE #{metric.name} gauge" - end + def metric_type_declaration(metric) + "# TYPE #{metric.name} gauge" + end - def metric_text(metric) - labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || '' + def metric_text(metric) + labels = metric.labels&.map { |key, value| "#{key}=\"#{value}\"" }&.join(',') || '' - if labels.empty? - "#{metric.name} #{metric.value}" - else - "#{metric.name}{#{labels}} #{metric.value}" + if labels.empty? + "#{metric.name} #{metric.value}" + else + "#{metric.name}{#{labels}} #{metric.value}" + end end end end -end +end \ No newline at end of file diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb index 34f6b32f7da..995715417f8 100644 --- a/lib/gitlab/metrics.rb +++ b/lib/gitlab/metrics.rb @@ -1,200 +1,10 @@ -require 'prometheus/client' - module Gitlab module Metrics - extend Gitlab::CurrentSettings - - RAILS_ROOT = Rails.root.to_s - METRICS_ROOT = Rails.root.join('lib', 'gitlab', 'metrics').to_s - PATH_REGEX = /^#{RAILS_ROOT}\/?/ - - def self.settings - @settings ||= { - enabled: current_application_settings[:metrics_enabled], - prometheus_metrics_enabled: current_application_settings[:prometheus_metrics_enabled], - pool_size: current_application_settings[:metrics_pool_size], - timeout: current_application_settings[:metrics_timeout], - method_call_threshold: current_application_settings[:metrics_method_call_threshold], - host: current_application_settings[:metrics_host], - port: current_application_settings[:metrics_port], - sample_interval: current_application_settings[:metrics_sample_interval] || 15, - packet_size: current_application_settings[:metrics_packet_size] || 1 - } - end - - def self.prometheus_metrics_enabled? - settings[:prometheus_metrics_enabled] || false - end - - def self.influx_metrics_enabled? - settings[:enabled] || false - end + extend Gitlab::Metrics::InfluxDb + extend Gitlab::Metrics::Prometheus def self.enabled? influx_metrics_enabled? || prometheus_metrics_enabled? end - - def self.mri? - RUBY_ENGINE == 'ruby' - end - - def self.method_call_threshold - # This is memoized since this method is called for every instrumented - # method. Loading data from an external cache on every method call slows - # things down too much. - @method_call_threshold ||= settings[:method_call_threshold] - end - - def self.pool - @pool - end - - def self.registry - @registry ||= ::Prometheus::Client.registry - end - - def self.counter(name, docstring, base_labels = {}) - provide_metric(name) || registry.counter(name, docstring, base_labels) - end - - def self.summary(name, docstring, base_labels = {}) - provide_metric(name) || registry.summary(name, docstring, base_labels) - end - - def self.gauge(name, docstring, base_labels = {}) - provide_metric(name) || registry.gauge(name, docstring, base_labels) - end - - def self.histogram(name, docstring, base_labels = {}, buckets = ::Prometheus::Client::Histogram::DEFAULT_BUCKETS) - provide_metric(name) || registry.histogram(name, docstring, base_labels, buckets) - end - - def self.provide_metric(name) - if prometheus_metrics_enabled? - registry.get(name) - else - NullMetric.new - end - end - - def self.submit_metrics(metrics) - prepared = prepare_metrics(metrics) - - pool&.with do |connection| - prepared.each_slice(settings[:packet_size]) do |slice| - begin - connection.write_points(slice) - rescue StandardError - end - end - end - rescue Errno::EADDRNOTAVAIL, SocketError => ex - Gitlab::EnvironmentLogger.error('Cannot resolve InfluxDB address. GitLab Performance Monitoring will not work.') - Gitlab::EnvironmentLogger.error(ex) - end - - def self.prepare_metrics(metrics) - metrics.map do |hash| - new_hash = hash.symbolize_keys - - new_hash[:tags].each do |key, value| - if value.blank? - new_hash[:tags].delete(key) - else - new_hash[:tags][key] = escape_value(value) - end - end - - new_hash - end - end - - def self.escape_value(value) - value.to_s.gsub('=', '\\=') - end - - # Measures the execution time of a block. - # - # Example: - # - # Gitlab::Metrics.measure(:find_by_username_duration) do - # User.find_by_username(some_username) - # end - # - # name - The name of the field to store the execution time in. - # - # Returns the value yielded by the supplied block. - def self.measure(name) - trans = current_transaction - - return yield unless trans - - real_start = Time.now.to_f - cpu_start = System.cpu_time - - retval = yield - - cpu_stop = System.cpu_time - real_stop = Time.now.to_f - - real_time = (real_stop - real_start) * 1000.0 - cpu_time = cpu_stop - cpu_start - - trans.increment("#{name}_real_time", real_time) - trans.increment("#{name}_cpu_time", cpu_time) - trans.increment("#{name}_call_count", 1) - - retval - end - - # Adds a tag to the current transaction (if any) - # - # name - The name of the tag to add. - # value - The value of the tag. - def self.tag_transaction(name, value) - trans = current_transaction - - trans&.add_tag(name, value) - end - - # Sets the action of the current transaction (if any) - # - # action - The name of the action. - def self.action=(action) - trans = current_transaction - - trans&.action = action - end - - # Tracks an event. - # - # See `Gitlab::Metrics::Transaction#add_event` for more details. - def self.add_event(*args) - trans = current_transaction - - trans&.add_event(*args) - end - - # Returns the prefix to use for the name of a series. - def self.series_prefix - @series_prefix ||= Sidekiq.server? ? 'sidekiq_' : 'rails_' - end - - # Allow access from other metrics related middlewares - def self.current_transaction - Transaction.current - end - - # When enabled this should be set before being used as the usual pattern - # "@foo ||= bar" is _not_ thread-safe. - if influx_metrics_enabled? - @pool = ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do - host = settings[:host] - port = settings[:port] - - InfluxDB::Client. - new(udp: { host: host, port: port }) - end - end end -end +end \ No newline at end of file diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb new file mode 100644 index 00000000000..c5d7a2b56b9 --- /dev/null +++ b/lib/gitlab/metrics/influx_db.rb @@ -0,0 +1,163 @@ +module Gitlab + module Metrics + module InfluxDb + include Gitlab::CurrentSettings + + def influx_metrics_enabled? + settings[:enabled] || false + end + + RAILS_ROOT = Rails.root.to_s + METRICS_ROOT = Rails.root.join('lib', 'gitlab', 'metrics').to_s + PATH_REGEX = /^#{RAILS_ROOT}\/?/ + + def settings + @settings ||= { + enabled: current_application_settings[:metrics_enabled], + pool_size: current_application_settings[:metrics_pool_size], + timeout: current_application_settings[:metrics_timeout], + method_call_threshold: current_application_settings[:metrics_method_call_threshold], + host: current_application_settings[:metrics_host], + port: current_application_settings[:metrics_port], + sample_interval: current_application_settings[:metrics_sample_interval] || 15, + packet_size: current_application_settings[:metrics_packet_size] || 1 + } + end + + def mri? + RUBY_ENGINE == 'ruby' + end + + def method_call_threshold + # This is memoized since this method is called for every instrumented + # method. Loading data from an external cache on every method call slows + # things down too much. + @method_call_threshold ||= settings[:method_call_threshold] + end + + def pool + @pool + end + + def submit_metrics(metrics) + prepared = prepare_metrics(metrics) + + pool&.with do |connection| + prepared.each_slice(settings[:packet_size]) do |slice| + begin + connection.write_points(slice) + rescue StandardError + end + end + end + rescue Errno::EADDRNOTAVAIL, SocketError => ex + Gitlab::EnvironmentLogger.error('Cannot resolve InfluxDB address. GitLab Performance Monitoring will not work.') + Gitlab::EnvironmentLogger.error(ex) + end + + def prepare_metrics(metrics) + metrics.map do |hash| + new_hash = hash.symbolize_keys + + new_hash[:tags].each do |key, value| + if value.blank? + new_hash[:tags].delete(key) + else + new_hash[:tags][key] = escape_value(value) + end + end + + new_hash + end + end + + def escape_value(value) + value.to_s.gsub('=', '\\=') + end + + # Measures the execution time of a block. + # + # Example: + # + # Gitlab::Metrics.measure(:find_by_username_duration) do + # User.find_by_username(some_username) + # end + # + # name - The name of the field to store the execution time in. + # + # Returns the value yielded by the supplied block. + def measure(name) + trans = current_transaction + + return yield unless trans + + real_start = Time.now.to_f + cpu_start = System.cpu_time + + retval = yield + + cpu_stop = System.cpu_time + real_stop = Time.now.to_f + + real_time = (real_stop - real_start) * 1000.0 + cpu_time = cpu_stop - cpu_start + + trans.increment("#{name}_real_time", real_time) + trans.increment("#{name}_cpu_time", cpu_time) + trans.increment("#{name}_call_count", 1) + + retval + end + + # Adds a tag to the current transaction (if any) + # + # name - The name of the tag to add. + # value - The value of the tag. + def tag_transaction(name, value) + trans = current_transaction + + trans&.add_tag(name, value) + end + + # Sets the action of the current transaction (if any) + # + # action - The name of the action. + def action=(action) + trans = current_transaction + + trans&.action = action + end + + # Tracks an event. + # + # See `Gitlab::Metrics::Transaction#add_event` for more details. + def add_event(*args) + trans = current_transaction + + trans&.add_event(*args) + end + + # Returns the prefix to use for the name of a series. + def series_prefix + @series_prefix ||= Sidekiq.server? ? 'sidekiq_' : 'rails_' + end + + # Allow access from other metrics related middlewares + def current_transaction + Transaction.current + end + + # When enabled this should be set before being used as the usual pattern + # "@foo ||= bar" is _not_ thread-safe. + if influx_metrics_enabled? + @pool = ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do + host = settings[:host] + port = settings[:port] + + InfluxDB::Client. + new(udp: { host: host, port: port }) + end + end + end + end +end \ No newline at end of file diff --git a/lib/gitlab/metrics/prometheus.rb b/lib/gitlab/metrics/prometheus.rb new file mode 100644 index 00000000000..493da4d779c --- /dev/null +++ b/lib/gitlab/metrics/prometheus.rb @@ -0,0 +1,41 @@ +require 'prometheus/client' + +module Gitlab + module Metrics + module Prometheus + include Gitlab::CurrentSettings + + def prometheus_metrics_enabled? + @prometheus_metrics_enabled ||= current_application_settings[:prometheus_metrics_enabled] || false + end + + def registry + @registry ||= ::Prometheus::Client.registry + end + + def counter(name, docstring, base_labels = {}) + provide_metric(name) || registry.counter(name, docstring, base_labels) + end + + def summary(name, docstring, base_labels = {}) + provide_metric(name) || registry.summary(name, docstring, base_labels) + end + + def gauge(name, docstring, base_labels = {}) + provide_metric(name) || registry.gauge(name, docstring, base_labels) + end + + def histogram(name, docstring, base_labels = {}, buckets = ::Prometheus::Client::Histogram::DEFAULT_BUCKETS) + provide_metric(name) || registry.histogram(name, docstring, base_labels, buckets) + end + + def provide_metric(name) + if prometheus_metrics_enabled? + registry.get(name) + else + NullMetric.new + end + end + end + end +end \ No newline at end of file -- cgit v1.2.3 From 68b946e3c8d3a1e7463cf8923ecd748f33c8ccee Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Thu, 1 Jun 2017 01:46:19 +0200 Subject: Fix circular dependency condition with `current_application_settings` `current_application_settings` used by `influx_metrics_enabled` executed a markdown parsing code that was measured using `Gitlab::Metrics.measure` But since the Gitlab::Metrics::InfluxDb was not yet build so Gitlab::Metrics did not yet have `measure` method. Causing the NoMethodError. However If run was successful at least once then result was cached in a file and this code never executed again. Which caused this issue to only show up in CI preparation step. --- lib/gitlab/metrics/influx_db.rb | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb index c5d7a2b56b9..3a39791edbf 100644 --- a/lib/gitlab/metrics/influx_db.rb +++ b/lib/gitlab/metrics/influx_db.rb @@ -1,7 +1,11 @@ module Gitlab module Metrics module InfluxDb - include Gitlab::CurrentSettings + extend Gitlab::CurrentSettings + extend self + + MUTEX = Mutex.new + private_constant :MUTEX def influx_metrics_enabled? settings[:enabled] || false @@ -35,10 +39,6 @@ module Gitlab @method_call_threshold ||= settings[:method_call_threshold] end - def pool - @pool - end - def submit_metrics(metrics) prepared = prepare_metrics(metrics) @@ -143,21 +143,28 @@ module Gitlab end # Allow access from other metrics related middlewares - def current_transaction + def current_transaction Transaction.current end # When enabled this should be set before being used as the usual pattern # "@foo ||= bar" is _not_ thread-safe. - if influx_metrics_enabled? - @pool = ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do - host = settings[:host] - port = settings[:port] - - InfluxDB::Client. - new(udp: { host: host, port: port }) + def pool + if influx_metrics_enabled? + if @pool.nil? + MUTEX.synchronize do + @pool ||= ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do + host = settings[:host] + port = settings[:port] + + InfluxDB::Client. + new(udp: { host: host, port: port }) + end + end + end + @pool end end end end -end \ No newline at end of file +end -- cgit v1.2.3 From 7b75004d603618d67aa50574bfc80627a6eaf72b Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Thu, 1 Jun 2017 14:38:40 +0200 Subject: Add missing trailing newlines --- lib/gitlab/health_checks/prometheus_text_format.rb | 2 +- lib/gitlab/metrics.rb | 2 +- lib/gitlab/metrics/prometheus.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/health_checks/prometheus_text_format.rb b/lib/gitlab/health_checks/prometheus_text_format.rb index e7ec1c516a2..6b81eeddfc9 100644 --- a/lib/gitlab/health_checks/prometheus_text_format.rb +++ b/lib/gitlab/health_checks/prometheus_text_format.rb @@ -37,4 +37,4 @@ module Gitlab end end end -end \ No newline at end of file +end diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb index 995715417f8..4779755bb22 100644 --- a/lib/gitlab/metrics.rb +++ b/lib/gitlab/metrics.rb @@ -7,4 +7,4 @@ module Gitlab influx_metrics_enabled? || prometheus_metrics_enabled? end end -end \ No newline at end of file +end diff --git a/lib/gitlab/metrics/prometheus.rb b/lib/gitlab/metrics/prometheus.rb index 493da4d779c..60686509332 100644 --- a/lib/gitlab/metrics/prometheus.rb +++ b/lib/gitlab/metrics/prometheus.rb @@ -38,4 +38,4 @@ module Gitlab end end end -end \ No newline at end of file +end -- cgit v1.2.3 From d26573c6e3de535f69437deaf54d5c151ac343c8 Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Fri, 2 Jun 2017 15:55:44 +0200 Subject: Make PrometheusTextFormat return proper output terminated with '\n' remove file dangling after rebase --- lib/gitlab/health_checks/prometheus_text_format.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/health_checks/prometheus_text_format.rb b/lib/gitlab/health_checks/prometheus_text_format.rb index 6b81eeddfc9..462c8e736a0 100644 --- a/lib/gitlab/health_checks/prometheus_text_format.rb +++ b/lib/gitlab/health_checks/prometheus_text_format.rb @@ -2,7 +2,7 @@ module Gitlab module HealthChecks class PrometheusTextFormat def marshal(metrics) - metrics_with_type_declarations(metrics).join("\n") + "#{metrics_with_type_declarations(metrics).join("\n")}\n" end private -- cgit v1.2.3 From 1d3c33b57eeb39df76e78fd37c86532c02aa22ac Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 12 May 2017 17:44:03 +0100 Subject: Increase diff limits to 100 KB for collapse and 200 KB overall This is controlled with the feature flag gitlab_git_diff_size_limit_increase. Both of these limits were basically picked arbitrarily in the first place; disabling the feature flag reverts to the old limits. --- lib/feature.rb | 12 ++++++++++++ lib/gitlab/git/diff.rb | 30 +++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/feature.rb b/lib/feature.rb index 2e2b343f82c..5650a1c1334 100644 --- a/lib/feature.rb +++ b/lib/feature.rb @@ -27,6 +27,18 @@ class Feature all.map(&:name).include?(feature.name) end + def enabled?(key) + get(key).enabled? + end + + def enable(key) + get(key).enable + end + + def disable(key) + get(key).disable + end + private def flipper diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index ccccca96595..6e85b14d5db 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -20,13 +20,25 @@ module Gitlab # We need this accessor because of `to_hash` and `init_from_hash` attr_accessor :too_large - # The maximum size of a diff to display. - SIZE_LIMIT = 100.kilobytes + class << self + # The maximum size of a diff to display. + def size_limit + if Feature.enabled?('gitlab_git_diff_size_limit_increase') + 200.kilobytes + else + 100.kilobytes + end + end - # The maximum size before a diff is collapsed. - COLLAPSE_LIMIT = 10.kilobytes + # The maximum size before a diff is collapsed. + def collapse_limit + if Feature.enabled?('gitlab_git_diff_size_limit_increase') + 100.kilobytes + else + 10.kilobytes + end + end - class << self def between(repo, head, base, options = {}, *paths) straight = options.delete(:straight) || false @@ -231,7 +243,7 @@ module Gitlab def too_large? if @too_large.nil? - @too_large = @diff.bytesize >= SIZE_LIMIT + @too_large = @diff.bytesize >= self.class.size_limit else @too_large end @@ -246,7 +258,7 @@ module Gitlab def collapsed? return @collapsed if defined?(@collapsed) - @collapsed = !expanded && @diff.bytesize >= COLLAPSE_LIMIT + @collapsed = !expanded && @diff.bytesize >= self.class.collapse_limit end def collapse! @@ -318,14 +330,14 @@ module Gitlab hunk.each_line do |line| size += line.content.bytesize - if size >= SIZE_LIMIT + if size >= self.class.size_limit too_large! return true end end end - if !expanded && size >= COLLAPSE_LIMIT + if !expanded && size >= self.class.collapse_limit collapse! return true end -- cgit v1.2.3 From c2516115e391360055f733d40af8aff2af52196b Mon Sep 17 00:00:00 2001 From: Robin Bobbitt Date: Thu, 1 Jun 2017 10:57:41 -0400 Subject: Expose import_status in Projects API --- lib/api/entities.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/api/entities.rb b/lib/api/entities.rb index e3258fdcffe..ea18cd83a0b 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -100,6 +100,8 @@ module API expose :creator_id expose :namespace, using: 'API::Entities::Namespace' expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? } + expose :import_status + expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] } expose :avatar_url do |user, options| user.avatar_url(only_path: false) end -- cgit v1.2.3 From 34841c7e547922ce4c6f8be97a0d0736cbaebf2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Tue, 23 May 2017 20:31:09 +0800 Subject: added Simplified Chinese to I18N --- lib/gitlab/i18n.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index 5ab3eeb3aff..f1a284b1581 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -5,7 +5,8 @@ module Gitlab AVAILABLE_LANGUAGES = { 'en' => 'English', 'es' => 'Español', - 'de' => 'Deutsch' + 'de' => 'Deutsch', + 'zh' => '简体中文' }.freeze def available_locales -- cgit v1.2.3 From 61df40cab9477c3f6172b08651bc303edf4cc84a Mon Sep 17 00:00:00 2001 From: htve Date: Tue, 23 May 2017 12:42:37 +0000 Subject: Update i18n.rb style --- lib/gitlab/i18n.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index f1a284b1581..e9acb1828aa 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -6,7 +6,7 @@ module Gitlab 'en' => 'English', 'es' => 'Español', 'de' => 'Deutsch', - 'zh' => '简体中文' + 'zh' => '简体中文' }.freeze def available_locales -- cgit v1.2.3 From c267a86c234ba7de271244011509bd72c4f789c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Sat, 27 May 2017 10:20:37 +0800 Subject: Change the language name zh to zh_CN --- lib/gitlab/i18n.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index e9acb1828aa..5e61968d892 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -6,7 +6,7 @@ module Gitlab 'en' => 'English', 'es' => 'Español', 'de' => 'Deutsch', - 'zh' => '简体中文' + 'zh_CN' => '简体中文' }.freeze def available_locales -- cgit v1.2.3 From 0f4fa4c7708d39c618e32967f2dc1b8d73ebc946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Sat, 27 May 2017 10:22:01 +0800 Subject: Add translation zh_HK to I18N --- lib/gitlab/i18n.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index 5e61968d892..093a9653988 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -6,7 +6,8 @@ module Gitlab 'en' => 'English', 'es' => 'Español', 'de' => 'Deutsch', - 'zh_CN' => '简体中文' + 'zh_CN' => '简体中文', + 'zh_HK' => '繁體中文(香港)' }.freeze def available_locales -- cgit v1.2.3 From fc6999687095d34609af268cfe34009cd40bb8cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=B6=9B?= Date: Sat, 27 May 2017 10:23:26 +0800 Subject: Add translation zh_TW to I18N --- lib/gitlab/i18n.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index 093a9653988..8bedf477b07 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -7,7 +7,8 @@ module Gitlab 'es' => 'Español', 'de' => 'Deutsch', 'zh_CN' => '简体中文', - 'zh_HK' => '繁體中文(香港)' + 'zh_HK' => '繁體中文(香港)', + 'zh_TW' => '繁體中文(臺灣)' }.freeze def available_locales -- cgit v1.2.3 From 6b9ea6dbd230cd4bc6d0f866f36732bc6059a979 Mon Sep 17 00:00:00 2001 From: Huang Tao Date: Sat, 27 May 2017 03:34:55 +0000 Subject: Update i18n.rb Indent style --- lib/gitlab/i18n.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index 8bedf477b07..f7ac48f7dbd 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -6,9 +6,9 @@ module Gitlab 'en' => 'English', 'es' => 'Español', 'de' => 'Deutsch', - 'zh_CN' => '简体中文', - 'zh_HK' => '繁體中文(香港)', - 'zh_TW' => '繁體中文(臺灣)' + 'zh_CN' => '简体中文', + 'zh_HK' => '繁體中文(香港)', + 'zh_TW' => '繁體中文(臺灣)' }.freeze def available_locales -- cgit v1.2.3 From 0b81b5ace0dd7c5ba3362238d8be41ce178e1ecc Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 31 May 2017 15:55:12 +0200 Subject: Create read_registry scope with JWT auth This is the first commit doing mainly 3 things: 1. create a new scope and allow users to use it 2. Have the JWTController respond correctly on this 3. Updates documentation to suggest usage of PATs There is one gotcha, there will be no support for impersonation tokens, as this seems not needed. Fixes gitlab-org/gitlab-ce#19219 --- lib/gitlab/auth.rb | 42 ++++++++++++++++++++++++++++-------------- lib/gitlab/auth/result.rb | 4 ++++ 2 files changed, 32 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index 099c45dcfb7..f461d0f97f1 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -2,6 +2,8 @@ module Gitlab module Auth MissingPersonalTokenError = Class.new(StandardError) + REGISTRY_SCOPES = [:read_registry].freeze + # Scopes used for GitLab API access API_SCOPES = [:api, :read_user].freeze @@ -11,8 +13,10 @@ module Gitlab # Default scopes for OAuth applications that don't define their own DEFAULT_SCOPES = [:api].freeze + AVAILABLE_SCOPES = (API_SCOPES + REGISTRY_SCOPES).freeze + # Other available scopes - OPTIONAL_SCOPES = (API_SCOPES + OPENID_SCOPES - DEFAULT_SCOPES).freeze + OPTIONAL_SCOPES = (AVAILABLE_SCOPES + OPENID_SCOPES - DEFAULT_SCOPES).freeze class << self def find_for_git_client(login, password, project:, ip:) @@ -26,8 +30,8 @@ module Gitlab build_access_token_check(login, password) || lfs_token_check(login, password) || oauth_access_token_check(login, password) || - user_with_password_for_git(login, password) || personal_access_token_check(password) || + user_with_password_for_git(login, password) || Gitlab::Auth::Result.new rate_limit!(ip, success: result.success?, login: login) @@ -103,15 +107,16 @@ module Gitlab raise Gitlab::Auth::MissingPersonalTokenError if user.two_factor_enabled? - Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, full_authentication_abilities) + Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, full_api_abilities) end def oauth_access_token_check(login, password) if login == "oauth2" && password.present? token = Doorkeeper::AccessToken.by_token(password) + if valid_oauth_token?(token) user = User.find_by(id: token.resource_owner_id) - Gitlab::Auth::Result.new(user, nil, :oauth, full_authentication_abilities) + Gitlab::Auth::Result.new(user, nil, :oauth, full_api_abilities) end end end @@ -121,17 +126,26 @@ module Gitlab token = PersonalAccessTokensFinder.new(state: 'active').find_by(token: password) - if token && valid_api_token?(token) - Gitlab::Auth::Result.new(token.user, nil, :personal_token, full_authentication_abilities) + if token && valid_scoped_token?(token, scopes: AVAILABLE_SCOPES.map(&:to_s)) + Gitlab::Auth::Result.new(token.user, nil, :personal_token, abilities_for_scope(token.scopes)) end end def valid_oauth_token?(token) - token && token.accessible? && valid_api_token?(token) + token && token.accessible? && valid_scoped_token?(token) end - def valid_api_token?(token) - AccessTokenValidationService.new(token).include_any_scope?(['api']) + def valid_scoped_token?(token, scopes: %w[api]) + AccessTokenValidationService.new(token).include_any_scope?(scopes) + end + + def abilities_for_scope(scopes) + abilities = Set.new + + abilities.merge(full_api_abilities) if scopes.include?("api") + abilities << :read_container_image if scopes.include?("read_registry") + + abilities.to_a end def lfs_token_check(login, password) @@ -150,9 +164,9 @@ module Gitlab authentication_abilities = if token_handler.user? - full_authentication_abilities + full_api_abilities else - read_authentication_abilities + read_api_abilities end if Devise.secure_compare(token_handler.token, password) @@ -188,7 +202,7 @@ module Gitlab ] end - def read_authentication_abilities + def read_api_abilities [ :read_project, :download_code, @@ -196,8 +210,8 @@ module Gitlab ] end - def full_authentication_abilities - read_authentication_abilities + [ + def full_api_abilities + read_api_abilities + [ :push_code, :create_container_image ] diff --git a/lib/gitlab/auth/result.rb b/lib/gitlab/auth/result.rb index 39b86c61a18..75451cf8aa9 100644 --- a/lib/gitlab/auth/result.rb +++ b/lib/gitlab/auth/result.rb @@ -15,6 +15,10 @@ module Gitlab def success? actor.present? || type == :ci end + + def failed? + !success? + end end end end -- cgit v1.2.3 From 3801a0df80306a76dc340ca74427a124a1514dbb Mon Sep 17 00:00:00 2001 From: Grzegorz Bizon Date: Mon, 5 Jun 2017 10:34:30 +0200 Subject: Export pipeline stages in import/export feature --- lib/gitlab/import_export/import_export.yml | 1 + lib/gitlab/import_export/relation_factory.rb | 1 + 2 files changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml index d0f3cf2b514..ff2b1d08c3c 100644 --- a/lib/gitlab/import_export/import_export.yml +++ b/lib/gitlab/import_export/import_export.yml @@ -38,6 +38,7 @@ project_tree: - notes: - :author - :events + - :stages - :statuses - :triggers - :pipeline_schedules diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index 19e23a4715f..695852526cb 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -3,6 +3,7 @@ module Gitlab class RelationFactory OVERRIDES = { snippets: :project_snippets, pipelines: 'Ci::Pipeline', + stages: 'Ci::Stage', statuses: 'commit_status', triggers: 'Ci::Trigger', pipeline_schedules: 'Ci::PipelineSchedule', -- cgit v1.2.3 From 158581a447bb4976161eca26ddcb2fccd25888ab Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 2 Jun 2017 14:18:24 +0100 Subject: Refactor the DeleteUserWorker --- lib/api/users.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/api/users.rb b/lib/api/users.rb index 2070dbd8bc7..e8694e90cf2 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -293,7 +293,7 @@ module API user = User.find_by(id: params[:id]) not_found!('User') unless user - DeleteUserWorker.perform_async(current_user.id, user.id, hard_delete: params[:hard_delete]) + user.delete_async(deleted_by: current_user, params: params) end desc 'Block a user. Available only for admins.' -- cgit v1.2.3 From ff8a053d5ddf154cd52c3e21ac24619dbbee0dc7 Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Mon, 15 May 2017 16:13:36 -0700 Subject: Fix Git over HTTP spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * The spec has 7 failures at this point * Specify rendered error messages * Render the GitAccess message rather than “Access denied” * Render the Not Found message provided by GitAccess, instead of a custom one * Expect GitAccess to check the config for whether Git-over-HTTP pull or push is disabled, rather than doing it in the controller * Add more thorough testing for authentication * Dried up a lot of tests * Fixed some broken tests --- lib/gitlab/checks/change_access.rb | 36 +++++++++++++++++++++++++----------- lib/gitlab/git_access.rb | 11 +++++++---- lib/gitlab/git_access_wiki.rb | 6 +++++- 3 files changed, 37 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb index c984eb20606..4b6f8abd61d 100644 --- a/lib/gitlab/checks/change_access.rb +++ b/lib/gitlab/checks/change_access.rb @@ -1,6 +1,20 @@ module Gitlab module Checks class ChangeAccess + ERROR_MESSAGES = { + push_code: 'You are not allowed to push code to this project.', + delete_default_branch: 'The default branch of a project cannot be deleted.', + force_push_protected_branch: 'You are not allowed to force push code to a protected branch on this project.', + non_master_delete_protected_branch: 'You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.', + non_web_delete_protected_branch: 'You can only delete protected branches using the web interface.', + merge_protected_branch: 'You are not allowed to merge code into protected branches on this project.', + push_protected_branch: 'You are not allowed to push code to protected branches on this project.', + change_existing_tags: 'You are not allowed to change existing tags on this project.', + update_protected_tag: 'Protected tags cannot be updated.', + delete_protected_tag: 'Protected tags cannot be deleted.', + create_protected_tag: 'You are not allowed to create this tag as it is protected.' + }.freeze + attr_reader :user_access, :project, :skip_authorization, :protocol def initialize( @@ -32,7 +46,7 @@ module Gitlab def push_checks if user_access.cannot_do_action?(:push_code) - "You are not allowed to push code to this project." + ERROR_MESSAGES[:push_code] end end @@ -40,7 +54,7 @@ module Gitlab return unless @branch_name if deletion? && @branch_name == project.default_branch - return "The default branch of a project cannot be deleted." + return ERROR_MESSAGES[:delete_default_branch] end protected_branch_checks @@ -50,7 +64,7 @@ module Gitlab return unless ProtectedBranch.protected?(project, @branch_name) if forced_push? - return "You are not allowed to force push code to a protected branch on this project." + return ERROR_MESSAGES[:force_push_protected_branch] end if deletion? @@ -62,22 +76,22 @@ module Gitlab def protected_branch_deletion_checks unless user_access.can_delete_branch?(@branch_name) - return 'You are not allowed to delete protected branches from this project. Only a project master or owner can delete a protected branch.' + return ERROR_MESSAGES[:non_master_delete_protected_branch] end unless protocol == 'web' - 'You can only delete protected branches using the web interface.' + ERROR_MESSAGES[:non_web_delete_protected_branch] end end def protected_branch_push_checks if matching_merge_request? unless user_access.can_merge_to_branch?(@branch_name) || user_access.can_push_to_branch?(@branch_name) - "You are not allowed to merge code into protected branches on this project." + ERROR_MESSAGES[:merge_protected_branch] end else unless user_access.can_push_to_branch?(@branch_name) - "You are not allowed to push code to protected branches on this project." + ERROR_MESSAGES[:push_protected_branch] end end end @@ -86,7 +100,7 @@ module Gitlab return unless @tag_name if tag_exists? && user_access.cannot_do_action?(:admin_project) - return "You are not allowed to change existing tags on this project." + return ERROR_MESSAGES[:change_existing_tags] end protected_tag_checks @@ -95,11 +109,11 @@ module Gitlab def protected_tag_checks return unless ProtectedTag.protected?(project, @tag_name) - return "Protected tags cannot be updated." if update? - return "Protected tags cannot be deleted." if deletion? + return ERROR_MESSAGES[:update_protected_tag] if update? + return ERROR_MESSAGES[:delete_protected_tag] if deletion? unless user_access.can_create_tag?(@tag_name) - return "You are not allowed to create this tag as it is protected." + return ERROR_MESSAGES[:create_protected_tag] end end diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 99724db8da2..591f68cd415 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -9,7 +9,10 @@ module Gitlab download: 'You are not allowed to download code from this project.', deploy_key_upload: 'This deploy key does not have write access to this project.', - no_repo: 'A repository for this project does not exist yet.' + no_repo: 'A repository for this project does not exist yet.', + project_not_found: 'The project you were looking for could not be found.', + account_blocked: 'Your account has been blocked.', + command_not_allowed: "The command you're trying to execute is not allowed." }.freeze DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }.freeze @@ -73,19 +76,19 @@ module Gitlab return if deploy_key? if user && !user_access.allowed? - raise UnauthorizedError, "Your account has been blocked." + raise UnauthorizedError, ERROR_MESSAGES[:account_blocked] end end def check_project_accessibility! if project.blank? || !can_read_project? - raise UnauthorizedError, 'The project you were looking for could not be found.' + raise UnauthorizedError, ERROR_MESSAGES[:project_not_found] end end def check_command_existence!(cmd) unless ALL_COMMANDS.include?(cmd) - raise UnauthorizedError, "The command you're trying to execute is not allowed." + raise UnauthorizedError, ERROR_MESSAGES[:command_not_allowed] end end diff --git a/lib/gitlab/git_access_wiki.rb b/lib/gitlab/git_access_wiki.rb index 67eaa5e088d..dccafd2cae8 100644 --- a/lib/gitlab/git_access_wiki.rb +++ b/lib/gitlab/git_access_wiki.rb @@ -1,5 +1,9 @@ module Gitlab class GitAccessWiki < GitAccess + ERROR_MESSAGES = { + write_to_wiki: "You are not allowed to write to this project's wiki." + }.freeze + def guest_can_download_code? Guest.can?(:download_wiki_code, project) end @@ -12,7 +16,7 @@ module Gitlab if user_access.can_do_action?(:create_wiki) build_status_object(true) else - build_status_object(false, "You are not allowed to write to this project's wiki.") + build_status_object(false, ERROR_MESSAGES[:write_to_wiki]) end end end -- cgit v1.2.3 From a738a446f4ade6204c10f016e355da354dbfc01f Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Tue, 16 May 2017 09:02:52 -0700 Subject: Check disabled commands in GitAccess instead --- lib/gitlab/git_access.rb | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 591f68cd415..1d052ac9b33 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -12,7 +12,9 @@ module Gitlab no_repo: 'A repository for this project does not exist yet.', project_not_found: 'The project you were looking for could not be found.', account_blocked: 'Your account has been blocked.', - command_not_allowed: "The command you're trying to execute is not allowed." + command_not_allowed: "The command you're trying to execute is not allowed.", + upload_pack_disabled_in_config: 'The command "git-upload-pack" is not allowed.', + receive_pack_disabled_in_config: 'The command "git-receive-pack" is not allowed.' }.freeze DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }.freeze @@ -33,6 +35,7 @@ module Gitlab check_protocol! check_active_user! check_project_accessibility! + check_command_disabled!(cmd) check_command_existence!(cmd) check_repository_existence! @@ -86,6 +89,16 @@ module Gitlab end end + def check_command_disabled!(cmd) + if http? + if upload_pack?(cmd) && !Gitlab.config.gitlab_shell.upload_pack + raise UnauthorizedError, ERROR_MESSAGES[:upload_pack_disabled_in_config] + elsif receive_pack?(cmd) && !Gitlab.config.gitlab_shell.receive_pack + raise UnauthorizedError, ERROR_MESSAGES[:receive_pack_disabled_in_config] + end + end + end + def check_command_existence!(cmd) unless ALL_COMMANDS.include?(cmd) raise UnauthorizedError, ERROR_MESSAGES[:command_not_allowed] @@ -179,6 +192,18 @@ module Gitlab end || Guest.can?(:read_project, project) end + def http? + protocol == 'http' + end + + def upload_pack?(command) + command == 'git-upload-pack' + end + + def receive_pack?(command) + command == 'git-receive-pack' + end + protected def user -- cgit v1.2.3 From bad08fbea2a32655a6d87f2140840c317cea6c80 Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Tue, 16 May 2017 12:58:46 -0700 Subject: Move CI access logic into GitAccess --- lib/gitlab/git_access.rb | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 1d052ac9b33..1ffac5385c2 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -63,6 +63,11 @@ module Gitlab authentication_abilities.include?(:build_download_code) && user_access.can_do_action?(:build_download_code) end + # Allow generic CI (build without a user) for backwards compatibility + def ci_can_download_code? + authentication_abilities.include?(:build_download_code) && ci? + end + def protocol_allowed? Gitlab::ProtocolAccess.allowed?(protocol) end @@ -115,6 +120,7 @@ module Gitlab return if deploy_key? passed = user_can_download_code? || + ci_can_download_code? || build_can_download_code? || guest_can_download_code? @@ -184,11 +190,17 @@ module Gitlab actor.is_a?(DeployKey) end + def ci? + actor == :ci + end + def can_read_project? - if deploy_key + if deploy_key? deploy_key.has_access_to?(project) elsif user user.can?(:read_project, project) + elsif ci? + true # allow CI (build without a user) for backwards compatibility end || Guest.can?(:read_project, project) end @@ -213,10 +225,12 @@ module Gitlab case actor when User actor - when DeployKey - nil when Key actor.user + when DeployKey + nil + when :ci + nil end end -- cgit v1.2.3 From 23d37382dabe3f7c7f2e11df2731de8e939e0cab Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Fri, 19 May 2017 12:58:45 -0700 Subject: Refactor to let GitAccess errors bubble up No external behavior change. This allows `GitHttpController` to set the HTTP status based on the type of error. Alternatively, we could have added an attribute to GitAccessStatus, but this pattern seemed appropriate. --- lib/api/internal.rb | 38 ++++++++++++++++++++------------------ lib/gitlab/checks/change_access.rb | 32 +++++++++++++++----------------- lib/gitlab/git_access.rb | 9 ++++----- lib/gitlab/git_access_status.rb | 4 ---- lib/gitlab/git_access_wiki.rb | 2 +- 5 files changed, 40 insertions(+), 45 deletions(-) (limited to 'lib') diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 9ebd4841296..3d60d1da114 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -32,29 +32,31 @@ module API actor.update_last_used_at if actor.is_a?(Key) - access_checker = wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess - access_status = access_checker + access_checker_klass = wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess + access_checker = access_checker_klass .new(actor, project, protocol, authentication_abilities: ssh_authentication_abilities) - .check(params[:action], params[:changes]) - response = { status: access_status.status, message: access_status.message } + begin + access_status = access_checker.check(params[:action], params[:changes]) + response = { status: access_status.status, message: access_status.message } + rescue Gitlab::GitAccess::UnauthorizedError, Gitlab::GitAccess::NotFoundError => e + return { status: false, message: e.message } + end - if access_status.status - log_user_activity(actor) + log_user_activity(actor) - # Project id to pass between components that don't share/don't have - # access to the same filesystem mounts - response[:gl_repository] = Gitlab::GlRepository.gl_repository(project, wiki?) + # Project id to pass between components that don't share/don't have + # access to the same filesystem mounts + response[:gl_repository] = Gitlab::GlRepository.gl_repository(project, wiki?) - # Return the repository full path so that gitlab-shell has it when - # handling ssh commands - response[:repository_path] = - if wiki? - project.wiki.repository.path_to_repo - else - project.repository.path_to_repo - end - end + # Return the repository full path so that gitlab-shell has it when + # handling ssh commands + response[:repository_path] = + if wiki? + project.wiki.repository.path_to_repo + else + project.repository.path_to_repo + end response end diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb index 4b6f8abd61d..e9782623be5 100644 --- a/lib/gitlab/checks/change_access.rb +++ b/lib/gitlab/checks/change_access.rb @@ -33,20 +33,18 @@ module Gitlab def exec return GitAccessStatus.new(true) if skip_authorization - error = push_checks || branch_checks || tag_checks + push_checks + branch_checks + tag_checks - if error - GitAccessStatus.new(false, error) - else - GitAccessStatus.new(true) - end + GitAccessStatus.new(true) end protected def push_checks if user_access.cannot_do_action?(:push_code) - ERROR_MESSAGES[:push_code] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:push_code] end end @@ -54,7 +52,7 @@ module Gitlab return unless @branch_name if deletion? && @branch_name == project.default_branch - return ERROR_MESSAGES[:delete_default_branch] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:delete_default_branch] end protected_branch_checks @@ -64,7 +62,7 @@ module Gitlab return unless ProtectedBranch.protected?(project, @branch_name) if forced_push? - return ERROR_MESSAGES[:force_push_protected_branch] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:force_push_protected_branch] end if deletion? @@ -76,22 +74,22 @@ module Gitlab def protected_branch_deletion_checks unless user_access.can_delete_branch?(@branch_name) - return ERROR_MESSAGES[:non_master_delete_protected_branch] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_master_delete_protected_branch] end unless protocol == 'web' - ERROR_MESSAGES[:non_web_delete_protected_branch] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_web_delete_protected_branch] end end def protected_branch_push_checks if matching_merge_request? unless user_access.can_merge_to_branch?(@branch_name) || user_access.can_push_to_branch?(@branch_name) - ERROR_MESSAGES[:merge_protected_branch] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:merge_protected_branch] end else unless user_access.can_push_to_branch?(@branch_name) - ERROR_MESSAGES[:push_protected_branch] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:push_protected_branch] end end end @@ -100,7 +98,7 @@ module Gitlab return unless @tag_name if tag_exists? && user_access.cannot_do_action?(:admin_project) - return ERROR_MESSAGES[:change_existing_tags] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:change_existing_tags] end protected_tag_checks @@ -109,11 +107,11 @@ module Gitlab def protected_tag_checks return unless ProtectedTag.protected?(project, @tag_name) - return ERROR_MESSAGES[:update_protected_tag] if update? - return ERROR_MESSAGES[:delete_protected_tag] if deletion? + raise(GitAccess::UnauthorizedError, ERROR_MESSAGES[:update_protected_tag]) if update? + raise(GitAccess::UnauthorizedError, ERROR_MESSAGES[:delete_protected_tag]) if deletion? unless user_access.can_create_tag?(@tag_name) - return ERROR_MESSAGES[:create_protected_tag] + raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:create_protected_tag] end end diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 1ffac5385c2..f43359d7dbd 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -3,6 +3,7 @@ module Gitlab class GitAccess UnauthorizedError = Class.new(StandardError) + NotFoundError = Class.new(StandardError) ERROR_MESSAGES = { upload: 'You are not allowed to upload code for this project.', @@ -47,8 +48,6 @@ module Gitlab end build_status_object(true) - rescue UnauthorizedError => ex - build_status_object(false, ex.message) end def guest_can_download_code? @@ -90,7 +89,7 @@ module Gitlab def check_project_accessibility! if project.blank? || !can_read_project? - raise UnauthorizedError, ERROR_MESSAGES[:project_not_found] + raise NotFoundError, ERROR_MESSAGES[:project_not_found] end end @@ -234,8 +233,8 @@ module Gitlab end end - def build_status_object(status, message = '') - Gitlab::GitAccessStatus.new(status, message) + def build_status_object(status) + Gitlab::GitAccessStatus.new(status) end end end diff --git a/lib/gitlab/git_access_status.rb b/lib/gitlab/git_access_status.rb index 09bb01be694..94edf80c0f6 100644 --- a/lib/gitlab/git_access_status.rb +++ b/lib/gitlab/git_access_status.rb @@ -7,9 +7,5 @@ module Gitlab @status = status @message = message end - - def to_json(opts = nil) - { status: @status, message: @message }.to_json(opts) - end end end diff --git a/lib/gitlab/git_access_wiki.rb b/lib/gitlab/git_access_wiki.rb index dccafd2cae8..4c87482430f 100644 --- a/lib/gitlab/git_access_wiki.rb +++ b/lib/gitlab/git_access_wiki.rb @@ -16,7 +16,7 @@ module Gitlab if user_access.can_do_action?(:create_wiki) build_status_object(true) else - build_status_object(false, ERROR_MESSAGES[:write_to_wiki]) + raise UnauthorizedError, ERROR_MESSAGES[:write_to_wiki] end end end -- cgit v1.2.3 From e8972c11904c31fc614a31483098814adc38c2ac Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Mon, 22 May 2017 11:28:51 -0700 Subject: Clarify error messages And refactor to self-document a little better. --- lib/gitlab/git_access.rb | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index f43359d7dbd..176b0991971 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -14,8 +14,8 @@ module Gitlab project_not_found: 'The project you were looking for could not be found.', account_blocked: 'Your account has been blocked.', command_not_allowed: "The command you're trying to execute is not allowed.", - upload_pack_disabled_in_config: 'The command "git-upload-pack" is not allowed.', - receive_pack_disabled_in_config: 'The command "git-receive-pack" is not allowed.' + upload_pack_disabled_over_http: 'Pulling over HTTP is not allowed.', + receive_pack_disabled_over_http: 'Pushing over HTTP is not allowed.' }.freeze DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }.freeze @@ -94,12 +94,22 @@ module Gitlab end def check_command_disabled!(cmd) - if http? - if upload_pack?(cmd) && !Gitlab.config.gitlab_shell.upload_pack - raise UnauthorizedError, ERROR_MESSAGES[:upload_pack_disabled_in_config] - elsif receive_pack?(cmd) && !Gitlab.config.gitlab_shell.receive_pack - raise UnauthorizedError, ERROR_MESSAGES[:receive_pack_disabled_in_config] - end + if upload_pack?(cmd) + check_upload_pack_disabled! + elsif receive_pack?(cmd) + check_receive_pack_disabled! + end + end + + def check_upload_pack_disabled! + if http? && upload_pack_disabled_over_http? + raise UnauthorizedError, ERROR_MESSAGES[:upload_pack_disabled_over_http] + end + end + + def check_receive_pack_disabled! + if http? && receive_pack_disabled_over_http? + raise UnauthorizedError, ERROR_MESSAGES[:receive_pack_disabled_over_http] end end @@ -215,6 +225,14 @@ module Gitlab command == 'git-receive-pack' end + def upload_pack_disabled_over_http? + !Gitlab.config.gitlab_shell.upload_pack + end + + def receive_pack_disabled_over_http? + !Gitlab.config.gitlab_shell.receive_pack + end + protected def user -- cgit v1.2.3 From 7d469cf1c1f356d950abc58ecbe6aa4ec15bd72b Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Mon, 22 May 2017 11:48:25 -0700 Subject: Fix would-be regression https://gitlab.com/gitlab-org/gitlab-ce/commit/57e3e942de1adef2c8621905370f07d7da7870c4 I changed it to a separate condition rather than depending on the order of the case-when statements to prevent this mistake again. --- lib/gitlab/git_access.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 176b0991971..75cc69c02f7 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -243,9 +243,7 @@ module Gitlab when User actor when Key - actor.user - when DeployKey - nil + actor.user unless actor.is_a?(DeployKey) when :ci nil end -- cgit v1.2.3 From 0a0f66c816469e197237a6eeaedeb959b5d1c823 Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Mon, 22 May 2017 12:44:59 -0700 Subject: Refactor to remove a special case --- lib/gitlab/ci_access.rb | 9 +++++++++ lib/gitlab/git_access.rb | 12 +++++------- 2 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 lib/gitlab/ci_access.rb (limited to 'lib') diff --git a/lib/gitlab/ci_access.rb b/lib/gitlab/ci_access.rb new file mode 100644 index 00000000000..def1373d8cf --- /dev/null +++ b/lib/gitlab/ci_access.rb @@ -0,0 +1,9 @@ +module Gitlab + # For backwards compatibility, generic CI (which is a build without a user) is + # allowed to :build_download_code without any other checks. + class CiAccess + def can_do_action?(action) + action == :build_download_code + end + end +end diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 75cc69c02f7..f44426d62b8 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -29,7 +29,11 @@ module Gitlab @project = project @protocol = protocol @authentication_abilities = authentication_abilities - @user_access = UserAccess.new(user, project: project) + @user_access = if ci? + CiAccess.new + else + UserAccess.new(user, project: project) + end end def check(cmd, changes) @@ -62,11 +66,6 @@ module Gitlab authentication_abilities.include?(:build_download_code) && user_access.can_do_action?(:build_download_code) end - # Allow generic CI (build without a user) for backwards compatibility - def ci_can_download_code? - authentication_abilities.include?(:build_download_code) && ci? - end - def protocol_allowed? Gitlab::ProtocolAccess.allowed?(protocol) end @@ -129,7 +128,6 @@ module Gitlab return if deploy_key? passed = user_can_download_code? || - ci_can_download_code? || build_can_download_code? || guest_can_download_code? -- cgit v1.2.3 From b50a22894d4503cf99cecb8162696f854e1b3f85 Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Tue, 23 May 2017 11:34:58 -0700 Subject: Refactor construction of response --- lib/api/helpers/internal_helpers.rb | 16 ++++++++++++++++ lib/api/internal.rb | 20 ++++++-------------- 2 files changed, 22 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb index 264df7271a3..d3732d67622 100644 --- a/lib/api/helpers/internal_helpers.rb +++ b/lib/api/helpers/internal_helpers.rb @@ -42,6 +42,22 @@ module API @project, @wiki = Gitlab::RepoPath.parse(params[:project]) end end + + # Project id to pass between components that don't share/don't have + # access to the same filesystem mounts + def gl_repository + Gitlab::GlRepository.gl_repository(project, wiki?) + end + + # Return the repository full path so that gitlab-shell has it when + # handling ssh commands + def repository_path + if wiki? + project.wiki.repository.path_to_repo + else + project.repository.path_to_repo + end + end end end end diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 3d60d1da114..f2d41754afd 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -37,26 +37,18 @@ module API .new(actor, project, protocol, authentication_abilities: ssh_authentication_abilities) begin - access_status = access_checker.check(params[:action], params[:changes]) - response = { status: access_status.status, message: access_status.message } + access_checker.check(params[:action], params[:changes]) rescue Gitlab::GitAccess::UnauthorizedError, Gitlab::GitAccess::NotFoundError => e return { status: false, message: e.message } end log_user_activity(actor) - # Project id to pass between components that don't share/don't have - # access to the same filesystem mounts - response[:gl_repository] = Gitlab::GlRepository.gl_repository(project, wiki?) - - # Return the repository full path so that gitlab-shell has it when - # handling ssh commands - response[:repository_path] = - if wiki? - project.wiki.repository.path_to_repo - else - project.repository.path_to_repo - end + response = { + status: true, + gl_repository: gl_repository, + repository_path: repository_path + } response end -- cgit v1.2.3 From 0e3cfc75a3ae244571385c878d0025bdf7a7d394 Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Tue, 23 May 2017 12:21:57 -0700 Subject: Remove GitAccessStatus (no longer needed) --- lib/gitlab/checks/change_access.rb | 4 ++-- lib/gitlab/git_access.rb | 14 ++++---------- lib/gitlab/git_access_status.rb | 11 ----------- lib/gitlab/git_access_wiki.rb | 6 +++--- 4 files changed, 9 insertions(+), 26 deletions(-) delete mode 100644 lib/gitlab/git_access_status.rb (limited to 'lib') diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb index e9782623be5..b6805230348 100644 --- a/lib/gitlab/checks/change_access.rb +++ b/lib/gitlab/checks/change_access.rb @@ -31,13 +31,13 @@ module Gitlab end def exec - return GitAccessStatus.new(true) if skip_authorization + return true if skip_authorization push_checks branch_checks tag_checks - GitAccessStatus.new(true) + true end protected diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index f44426d62b8..4807dc9a5fb 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -51,7 +51,7 @@ module Gitlab check_push_access!(changes) end - build_status_object(true) + true end def guest_can_download_code? @@ -167,11 +167,9 @@ module Gitlab # Iterate over all changes to find if user allowed all of them to be applied changes_list.each do |change| - status = check_single_change_access(change) - unless status.allowed? - # If user does not have access to make at least one change - cancel all push - raise UnauthorizedError, status.message - end + # If user does not have access to make at least one change, cancel all + # push by allowing the exception to bubble up + check_single_change_access(change) end end @@ -246,9 +244,5 @@ module Gitlab nil end end - - def build_status_object(status) - Gitlab::GitAccessStatus.new(status) - end end end diff --git a/lib/gitlab/git_access_status.rb b/lib/gitlab/git_access_status.rb deleted file mode 100644 index 94edf80c0f6..00000000000 --- a/lib/gitlab/git_access_status.rb +++ /dev/null @@ -1,11 +0,0 @@ -module Gitlab - class GitAccessStatus - attr_accessor :status, :message - alias_method :allowed?, :status - - def initialize(status, message = '') - @status = status - @message = message - end - end -end diff --git a/lib/gitlab/git_access_wiki.rb b/lib/gitlab/git_access_wiki.rb index 4c87482430f..1fe5155c093 100644 --- a/lib/gitlab/git_access_wiki.rb +++ b/lib/gitlab/git_access_wiki.rb @@ -13,11 +13,11 @@ module Gitlab end def check_single_change_access(change) - if user_access.can_do_action?(:create_wiki) - build_status_object(true) - else + unless user_access.can_do_action?(:create_wiki) raise UnauthorizedError, ERROR_MESSAGES[:write_to_wiki] end + + true end end end -- cgit v1.2.3 From d7eee7332b4a3eda49c07dfddc734bed25813f11 Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Tue, 23 May 2017 12:26:46 -0700 Subject: Extract and memoize `user_access` Because it is sometimes never used. --- lib/gitlab/git_access.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb index 4807dc9a5fb..0a19d24eb20 100644 --- a/lib/gitlab/git_access.rb +++ b/lib/gitlab/git_access.rb @@ -22,18 +22,13 @@ module Gitlab PUSH_COMMANDS = %w{ git-receive-pack }.freeze ALL_COMMANDS = DOWNLOAD_COMMANDS + PUSH_COMMANDS - attr_reader :actor, :project, :protocol, :user_access, :authentication_abilities + attr_reader :actor, :project, :protocol, :authentication_abilities def initialize(actor, project, protocol, authentication_abilities:) @actor = actor @project = project @protocol = protocol @authentication_abilities = authentication_abilities - @user_access = if ci? - CiAccess.new - else - UserAccess.new(user, project: project) - end end def check(cmd, changes) @@ -244,5 +239,13 @@ module Gitlab nil end end + + def user_access + @user_access ||= if ci? + CiAccess.new + else + UserAccess.new(user, project: project) + end + end end end -- cgit v1.2.3 From ef4e913597611ee88cfcac226a409f39873eb676 Mon Sep 17 00:00:00 2001 From: Michael Kozono Date: Mon, 5 Jun 2017 10:39:32 -0700 Subject: Remove unnecessary variable --- lib/api/internal.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/api/internal.rb b/lib/api/internal.rb index f2d41754afd..38631953014 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -44,13 +44,11 @@ module API log_user_activity(actor) - response = { + { status: true, gl_repository: gl_repository, repository_path: repository_path } - - response end post "/lfs_authenticate" do -- cgit v1.2.3 From b2800ee0c7c0ca47bb11b21b6b32134ae6f4594e Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Fri, 2 Jun 2017 17:28:54 +0100 Subject: Add a Rake task to aid in rotating otp_key_base --- lib/gitlab/otp_key_rotator.rb | 87 ++++++++++++++++++++++++++++++++++++++++ lib/tasks/gitlab/two_factor.rake | 16 ++++++++ 2 files changed, 103 insertions(+) create mode 100644 lib/gitlab/otp_key_rotator.rb (limited to 'lib') diff --git a/lib/gitlab/otp_key_rotator.rb b/lib/gitlab/otp_key_rotator.rb new file mode 100644 index 00000000000..0d541935bc6 --- /dev/null +++ b/lib/gitlab/otp_key_rotator.rb @@ -0,0 +1,87 @@ +module Gitlab + # The +otp_key_base+ param is used to encrypt the User#otp_secret attribute. + # + # When +otp_key_base+ is changed, it invalidates the current encrypted values + # of User#otp_secret. This class can be used to decrypt all the values with + # the old key, encrypt them with the new key, and and update the database + # with the new values. + # + # For persistence between runs, a CSV file is used with the following columns: + # + # user_id, old_value, new_value + # + # Only the encrypted values are stored in this file. + # + # As users may have their 2FA settings changed at any time, this is only + # guaranteed to be safe if run offline. + class OtpKeyRotator + HEADERS = %w[user_id old_value new_value].freeze + + attr_reader :filename + + # Create a new rotator. +filename+ is used to store values by +calculate!+, + # and to update the database with new and old values in +apply!+ and + # +rollback!+, respectively. + def initialize(filename) + @filename = filename + end + + def rotate!(old_key:, new_key:) + old_key ||= Gitlab::Application.secrets.otp_key_base + + raise ArgumentError.new("Old key is the same as the new key") if old_key == new_key + raise ArgumentError.new("New key is too short! Must be 256 bits") if new_key.size < 64 + + write_csv do |csv| + ActiveRecord::Base.transaction do + User.with_two_factor.in_batches do |relation| + rows = relation.pluck(:id, :encrypted_otp_secret, :encrypted_otp_secret_iv, :encrypted_otp_secret_salt) + rows.each do |row| + user = %i[id ciphertext iv salt].zip(row).to_h + new_value = reencrypt(user, old_key, new_key) + + User.where(id: user[:id]).update_all(encrypted_otp_secret: new_value) + csv << [user[:id], user[:ciphertext], new_value] + end + end + end + end + end + + def rollback! + ActiveRecord::Base.transaction do + CSV.foreach(filename, headers: HEADERS, return_headers: false) do |row| + User.where(id: row['user_id']).update_all(encrypted_otp_secret: row['old_value']) + end + end + end + + private + + attr_reader :old_key, :new_key + + def otp_secret_settings + @otp_secret_settings ||= User.encrypted_attributes[:otp_secret] + end + + def reencrypt(user, old_key, new_key) + original = user[:ciphertext].unpack("m").join + opts = { + iv: user[:iv].unpack("m").join, + salt: user[:salt].unpack("m").join, + algorithm: otp_secret_settings[:algorithm], + insecure_mode: otp_secret_settings[:insecure_mode] + } + + decrypted = Encryptor.decrypt(original, opts.merge(key: old_key)) + encrypted = Encryptor.encrypt(decrypted, opts.merge(key: new_key)) + [encrypted].pack("m") + end + + def write_csv(&blk) + File.open(filename, "w") do |file| + yield CSV.new(file, headers: HEADERS, write_headers: false) + end + end + end +end diff --git a/lib/tasks/gitlab/two_factor.rake b/lib/tasks/gitlab/two_factor.rake index fc0ccc726ed..7728c485e8d 100644 --- a/lib/tasks/gitlab/two_factor.rake +++ b/lib/tasks/gitlab/two_factor.rake @@ -19,5 +19,21 @@ namespace :gitlab do puts "There are currently no users with 2FA enabled.".color(:yellow) end end + + namespace :rotate_key do + def rotator + @rotator ||= Gitlab::OtpKeyRotator.new(ENV['filename']) + end + + desc "Encrypt user OTP secrets with a new encryption key" + task apply: :environment do |t, args| + rotator.rotate!(old_key: ENV['old_key'], new_key: ENV['new_key']) + end + + desc "Rollback to secrets encrypted with the old encryption key" + task rollback: :environment do + rotator.rollback! + end + end end end -- cgit v1.2.3 From 810866ecb6c7be4fdac88dc3b2a6cd9ad49ac7bf Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Thu, 1 Jun 2017 15:27:35 +0100 Subject: backports changed import logic from pull mirroring feature into CE --- lib/tasks/import.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake index bc76d7edc55..50b8e331469 100644 --- a/lib/tasks/import.rake +++ b/lib/tasks/import.rake @@ -37,7 +37,7 @@ class GithubImport end def import! - @project.import_start + @project.force_import_start timings = Benchmark.measure do Github::Import.new(@project, @options).execute -- cgit v1.2.3 From ad3e180ed3d99494414cb1b367f6b4e40ec28b87 Mon Sep 17 00:00:00 2001 From: Mark Fletcher Date: Mon, 29 May 2017 13:49:17 +0800 Subject: Introduce an Events API * Meld the following disparate endpoints: * `/projects/:id/events` * `/events` * `/users/:id/events` + Add result filtering to the above endpoints: * action * target_type * before and after dates --- lib/api/api.rb | 1 + lib/api/events.rb | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/api/projects.rb | 10 ------- lib/api/users.rb | 21 ------------- 4 files changed, 87 insertions(+), 31 deletions(-) create mode 100644 lib/api/events.rb (limited to 'lib') diff --git a/lib/api/api.rb b/lib/api/api.rb index 7ae2f3cad40..88f91c07194 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -94,6 +94,7 @@ module API mount ::API::DeployKeys mount ::API::Deployments mount ::API::Environments + mount ::API::Events mount ::API::Features mount ::API::Files mount ::API::Groups diff --git a/lib/api/events.rb b/lib/api/events.rb new file mode 100644 index 00000000000..ed5df268ae3 --- /dev/null +++ b/lib/api/events.rb @@ -0,0 +1,86 @@ +module API + class Events < Grape::API + include PaginationParams + + helpers do + params :event_filter_params do + optional :action, type: String, values: Event.actions, desc: 'Event action to filter on' + optional :target_type, type: String, values: Event.target_types, desc: 'Event target type to filter on' + optional :before, type: Date, desc: 'Include only events created before this date' + optional :after, type: Date, desc: 'Include only events created after this date' + end + + params :sort_params do + optional :sort, type: String, values: %w[asc desc], default: 'desc', + desc: 'Return events sorted in ascending and descending order' + end + + def present_events(events) + events = events.reorder(created_at: params[:sort]) + + present paginate(events), with: Entities::Event + end + end + + resource :events do + desc "List currently authenticated user's events" do + detail 'This feature was introduced in GitLab 9.3.' + success Entities::Event + end + params do + use :pagination + use :event_filter_params + use :sort_params + end + get do + authenticate! + + events = EventsFinder.new(params.merge(source: current_user, current_user: current_user)).execute.preload(:author, :target) + + present_events(events) + end + end + + params do + requires :id, type: Integer, desc: 'The ID of the user' + end + resource :users do + desc 'Get the contribution events of a specified user' do + detail 'This feature was introduced in GitLab 8.13.' + success Entities::Event + end + params do + use :pagination + use :event_filter_params + use :sort_params + end + get ':id/events' do + user = User.find_by(id: params[:id]) + not_found!('User') unless user + + events = EventsFinder.new(params.merge(source: user, current_user: current_user)).execute.preload(:author, :target) + + present_events(events) + end + end + + params do + requires :id, type: String, desc: 'The ID of a project' + end + resource :projects, requirements: { id: %r{[^/]+} } do + desc "List a Project's visible events" do + success Entities::Event + end + params do + use :pagination + use :event_filter_params + use :sort_params + end + get ":id/events" do + events = EventsFinder.new(params.merge(source: user_project, current_user: current_user)).execute.preload(:author, :target) + + present_events(events) + end + end + end +end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index deac3934d57..56046742e08 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -167,16 +167,6 @@ module API user_can_admin_project: can?(current_user, :admin_project, user_project), statistics: params[:statistics] end - desc 'Get events for a single project' do - success Entities::Event - end - params do - use :pagination - end - get ":id/events" do - present paginate(user_project.events.recent), with: Entities::Event - end - desc 'Fork new project for the current user or provided namespace.' do success Entities::Project end diff --git a/lib/api/users.rb b/lib/api/users.rb index e8694e90cf2..3f87a403a09 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -328,27 +328,6 @@ module API end end - desc 'Get the contribution events of a specified user' do - detail 'This feature was introduced in GitLab 8.13.' - success Entities::Event - end - params do - requires :id, type: Integer, desc: 'The ID of the user' - use :pagination - end - get ':id/events' do - user = User.find_by(id: params[:id]) - not_found!('User') unless user - - events = user.events. - merge(ProjectsFinder.new(current_user: current_user).execute). - references(:project). - with_associations. - recent - - present paginate(events), with: Entities::Event - end - params do requires :user_id, type: Integer, desc: 'The ID of the user' end -- cgit v1.2.3 From 3c15f0eae757817b4d852be6b62abd3d73186d35 Mon Sep 17 00:00:00 2001 From: Mark Fletcher Date: Fri, 2 Jun 2017 11:41:47 +0800 Subject: Accept a username for User-level Events API --- lib/api/events.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/events.rb b/lib/api/events.rb index ed5df268ae3..dabdf579119 100644 --- a/lib/api/events.rb +++ b/lib/api/events.rb @@ -42,7 +42,7 @@ module API end params do - requires :id, type: Integer, desc: 'The ID of the user' + requires :id, type: String, desc: 'The ID or Username of the user' end resource :users do desc 'Get the contribution events of a specified user' do @@ -55,7 +55,7 @@ module API use :sort_params end get ':id/events' do - user = User.find_by(id: params[:id]) + user = find_user(params[:id]) not_found!('User') unless user events = EventsFinder.new(params.merge(source: user, current_user: current_user)).execute.preload(:author, :target) -- cgit v1.2.3 From d919f924bf32220237c389dc913093efead8928c Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 6 Jun 2017 21:42:45 +0800 Subject: Backport https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1942 --- lib/api/groups.rb | 4 +--- lib/api/users.rb | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/api/groups.rb b/lib/api/groups.rb index e14a988a153..ebbaed0cbb7 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -83,7 +83,7 @@ module API group = ::Groups::CreateService.new(current_user, declared_params(include_missing: false)).execute if group.persisted? - present group, with: Entities::Group, current_user: current_user + present group, with: Entities::GroupDetail, current_user: current_user else render_api_error!("Failed to save group #{group.errors.messages}", 400) end @@ -101,8 +101,6 @@ module API optional :name, type: String, desc: 'The name of the group' optional :path, type: String, desc: 'The path of the group' use :optional_params - at_least_one_of :name, :path, :description, :visibility, - :lfs_enabled, :request_access_enabled end put ':id' do group = find_group!(params[:id]) diff --git a/lib/api/users.rb b/lib/api/users.rb index e8694e90cf2..7d78c5a55a9 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -124,10 +124,6 @@ module API optional :name, type: String, desc: 'The name of the user' optional :username, type: String, desc: 'The username of the user' use :optional_attributes - at_least_one_of :email, :password, :name, :username, :skype, :linkedin, - :twitter, :website_url, :organization, :projects_limit, - :extern_uid, :provider, :bio, :location, :admin, - :can_create_group, :confirm, :external end put ":id" do authenticated_as_admin! -- cgit v1.2.3 From 1110def8e21d4927a127783d468fbddf3cc886c7 Mon Sep 17 00:00:00 2001 From: Roman Safronov Date: Tue, 6 Jun 2017 13:55:29 +0000 Subject: Introduce optimistic locking support via optional parameter last_commit_id on File Update API --- lib/api/files.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/api/files.rb b/lib/api/files.rb index e6ea12c5ab7..25b0968a271 100644 --- a/lib/api/files.rb +++ b/lib/api/files.rb @@ -10,7 +10,8 @@ module API file_content: attrs[:content], file_content_encoding: attrs[:encoding], author_email: attrs[:author_email], - author_name: attrs[:author_name] + author_name: attrs[:author_name], + last_commit_sha: attrs[:last_commit_id] } end @@ -46,6 +47,7 @@ module API use :simple_file_params requires :content, type: String, desc: 'File content' optional :encoding, type: String, values: %w[base64], desc: 'File encoding' + optional :last_commit_id, type: String, desc: 'Last known commit id for this file' end end @@ -111,7 +113,12 @@ module API authorize! :push_code, user_project file_params = declared_params(include_missing: false) - result = ::Files::UpdateService.new(user_project, current_user, commit_params(file_params)).execute + + begin + result = ::Files::UpdateService.new(user_project, current_user, commit_params(file_params)).execute + rescue ::Files::UpdateService::FileChangedError => e + render_api_error!(e.message, 400) + end if result[:status] == :success status(200) -- cgit v1.2.3 From 9fcc3e5982311a380681c822df72fe470a5ea1ca Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Tue, 6 Jun 2017 13:18:01 +0200 Subject: Fix test failures --- lib/gitlab/auth.rb | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index f461d0f97f1..da07ba2f2a3 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -107,7 +107,7 @@ module Gitlab raise Gitlab::Auth::MissingPersonalTokenError if user.two_factor_enabled? - Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, full_api_abilities) + Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, full_authentication_abilities) end def oauth_access_token_check(login, password) @@ -116,7 +116,7 @@ module Gitlab if valid_oauth_token?(token) user = User.find_by(id: token.resource_owner_id) - Gitlab::Auth::Result.new(user, nil, :oauth, full_api_abilities) + Gitlab::Auth::Result.new(user, nil, :oauth, full_authentication_abilities) end end end @@ -126,26 +126,23 @@ module Gitlab token = PersonalAccessTokensFinder.new(state: 'active').find_by(token: password) - if token && valid_scoped_token?(token, scopes: AVAILABLE_SCOPES.map(&:to_s)) + if token && valid_scoped_token?(token, AVAILABLE_SCOPES.map(&:to_s)) Gitlab::Auth::Result.new(token.user, nil, :personal_token, abilities_for_scope(token.scopes)) end end def valid_oauth_token?(token) - token && token.accessible? && valid_scoped_token?(token) + token && token.accessible? && valid_scoped_token?(token, ["api"]) end - def valid_scoped_token?(token, scopes: %w[api]) + def valid_scoped_token?(token, scopes) AccessTokenValidationService.new(token).include_any_scope?(scopes) end def abilities_for_scope(scopes) - abilities = Set.new - - abilities.merge(full_api_abilities) if scopes.include?("api") - abilities << :read_container_image if scopes.include?("read_registry") - - abilities.to_a + scopes.map do |scope| + self.public_send(:"#{scope}_scope_authentication_abilities") + end.flatten.uniq end def lfs_token_check(login, password) @@ -164,9 +161,9 @@ module Gitlab authentication_abilities = if token_handler.user? - full_api_abilities + full_authentication_abilities else - read_api_abilities + read_authentication_abilities end if Devise.secure_compare(token_handler.token, password) @@ -202,7 +199,7 @@ module Gitlab ] end - def read_api_abilities + def read_authentication_abilities [ :read_project, :download_code, @@ -210,12 +207,22 @@ module Gitlab ] end - def full_api_abilities - read_api_abilities + [ + def full_authentication_abilities + read_authentication_abilities + [ :push_code, :create_container_image ] end + alias_method :api_scope_authentication_abilities, :full_authentication_abilities + + def read_registry_scope_authentication_abilities + [:read_container_image] + end + + # The currently used auth method doesn't allow any actions for this scope + def read_user_scope_authentication_abilities + [] + end end end end -- cgit v1.2.3 From 6b53add3f93caffa830e3bdbb3d8fd8d674ee3aa Mon Sep 17 00:00:00 2001 From: James Lopez Date: Tue, 6 Jun 2017 16:40:07 +0000 Subject: Fix binary encoding error on MR diffs --- lib/gitlab/encoding_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/encoding_helper.rb b/lib/gitlab/encoding_helper.rb index dbe28e6bb93..781f9c56a42 100644 --- a/lib/gitlab/encoding_helper.rb +++ b/lib/gitlab/encoding_helper.rb @@ -38,7 +38,7 @@ module Gitlab def encode_utf8(message) detect = CharlockHolmes::EncodingDetector.detect(message) - if detect + if detect && detect[:encoding] begin CharlockHolmes::Converter.convert(message, detect[:encoding], 'UTF-8') rescue ArgumentError => e -- cgit v1.2.3 From d93352825ae1b738d1d1922f26308166447b041d Mon Sep 17 00:00:00 2001 From: Paul Charlton Date: Tue, 6 Jun 2017 16:48:10 +0000 Subject: redesign caching of application settings --- lib/gitlab/current_settings.rb | 54 +++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb index 9e14b35b0f8..48735fd197d 100644 --- a/lib/gitlab/current_settings.rb +++ b/lib/gitlab/current_settings.rb @@ -8,39 +8,55 @@ module Gitlab end end - def ensure_application_settings! - return fake_application_settings unless connect_to_db? + delegate :sidekiq_throttling_enabled?, to: :current_application_settings - unless ENV['IN_MEMORY_APPLICATION_SETTINGS'] == 'true' - begin - settings = ::ApplicationSetting.current - # In case Redis isn't running or the Redis UNIX socket file is not available - rescue ::Redis::BaseError, ::Errno::ENOENT - settings = ::ApplicationSetting.last - end + def fake_application_settings + OpenStruct.new(::ApplicationSetting.defaults) + end - settings ||= ::ApplicationSetting.create_from_defaults + private + + def ensure_application_settings! + unless ENV['IN_MEMORY_APPLICATION_SETTINGS'] == 'true' + settings = retrieve_settings_from_database? end settings || in_memory_application_settings end - delegate :sidekiq_throttling_enabled?, to: :current_application_settings + def retrieve_settings_from_database? + settings = retrieve_settings_from_database_cache? + return settings if settings.present? + + return fake_application_settings unless connect_to_db? + + begin + db_settings = ::ApplicationSetting.current + # In case Redis isn't running or the Redis UNIX socket file is not available + rescue ::Redis::BaseError, ::Errno::ENOENT + db_settings = ::ApplicationSetting.last + end + db_settings || ::ApplicationSetting.create_from_defaults + end + + def retrieve_settings_from_database_cache? + begin + settings = ApplicationSetting.cached + rescue ::Redis::BaseError, ::Errno::ENOENT + # In case Redis isn't running or the Redis UNIX socket file is not available + settings = nil + end + settings + end def in_memory_application_settings @in_memory_application_settings ||= ::ApplicationSetting.new(::ApplicationSetting.defaults) - # In case migrations the application_settings table is not created yet, - # we fallback to a simple OpenStruct rescue ActiveRecord::StatementInvalid, ActiveRecord::UnknownAttributeError + # In case migrations the application_settings table is not created yet, + # we fallback to a simple OpenStruct fake_application_settings end - def fake_application_settings - OpenStruct.new(::ApplicationSetting.defaults) - end - - private - def connect_to_db? # When the DBMS is not available, an exception (e.g. PG::ConnectionBad) is raised active_db_connection = ActiveRecord::Base.connection.active? rescue false -- cgit v1.2.3 From 3a5d375e49b808ca203cb40b5f907aafb40f53aa Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Tue, 6 Jun 2017 11:46:28 -0500 Subject: Fix Diff::Position#diff_file for positions on straight diffs --- lib/gitlab/diff/diff_refs.rb | 10 ++++++++++ lib/gitlab/diff/position.rb | 18 ++---------------- lib/gitlab/diff/position_tracer.rb | 2 +- lib/gitlab/git/compare.rb | 2 +- 4 files changed, 14 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/diff/diff_refs.rb b/lib/gitlab/diff/diff_refs.rb index 7948782aecc..371cbe04b9b 100644 --- a/lib/gitlab/diff/diff_refs.rb +++ b/lib/gitlab/diff/diff_refs.rb @@ -37,6 +37,16 @@ module Gitlab def complete? start_sha && head_sha end + + def compare_in(project) + # We're at the initial commit, so just get that as we can't compare to anything. + if Gitlab::Git.blank_ref?(start_sha) + project.commit(head_sha) + else + straight = start_sha == base_sha + CompareService.new(project, head_sha).execute(project, start_sha, straight: straight) + end + end end end end diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb index 4d96778a2b2..f80afb20f0c 100644 --- a/lib/gitlab/diff/position.rb +++ b/lib/gitlab/diff/position.rb @@ -145,23 +145,9 @@ module Gitlab private def find_diff_file(repository) - # We're at the initial commit, so just get that as we can't compare to anything. - compare = - if Gitlab::Git.blank_ref?(start_sha) - Gitlab::Git::Commit.find(repository.raw_repository, head_sha) - else - Gitlab::Git::Compare.new( - repository.raw_repository, - start_sha, - head_sha - ) - end - - diff = compare.diffs(paths: paths).first - - return unless diff + return unless diff_refs.complete? - Gitlab::Diff::File.new(diff, repository: repository, diff_refs: diff_refs) + diff_refs.compare_in(repository.project).diffs(paths: paths, expanded: true).diff_files.first end end end diff --git a/lib/gitlab/diff/position_tracer.rb b/lib/gitlab/diff/position_tracer.rb index dcabb5f7fe5..b68a1636814 100644 --- a/lib/gitlab/diff/position_tracer.rb +++ b/lib/gitlab/diff/position_tracer.rb @@ -216,7 +216,7 @@ module Gitlab def compare(start_sha, head_sha, straight: false) compare = CompareService.new(project, head_sha).execute(project, start_sha, straight: straight) - compare.diffs(paths: paths) + compare.diffs(paths: paths, expanded: true) end def position(diff_file, old_line, new_line) diff --git a/lib/gitlab/git/compare.rb b/lib/gitlab/git/compare.rb index 696a2acd5e3..78e440395a5 100644 --- a/lib/gitlab/git/compare.rb +++ b/lib/gitlab/git/compare.rb @@ -3,7 +3,7 @@ module Gitlab class Compare attr_reader :head, :base, :straight - def initialize(repository, base, head, straight = false) + def initialize(repository, base, head, straight: false) @repository = repository @straight = straight -- cgit v1.2.3 From 223b87d7b1eccfc844631118e454c69a6312004d Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 6 Jun 2017 11:49:36 +0300 Subject: Backport Fix '/unassign' slash command --- lib/gitlab/slash_commands/command_definition.rb | 10 ++++++++-- lib/gitlab/slash_commands/dsl.rb | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/slash_commands/command_definition.rb b/lib/gitlab/slash_commands/command_definition.rb index 12a385f90fd..caab8856014 100644 --- a/lib/gitlab/slash_commands/command_definition.rb +++ b/lib/gitlab/slash_commands/command_definition.rb @@ -48,17 +48,23 @@ module Gitlab end def to_h(opts) + context = OpenStruct.new(opts) + desc = description if desc.respond_to?(:call) - context = OpenStruct.new(opts) desc = context.instance_exec(&desc) rescue '' end + prms = params + if prms.respond_to?(:call) + prms = Array(context.instance_exec(&prms)) rescue params + end + { name: name, aliases: aliases, description: desc, - params: params + params: prms } end diff --git a/lib/gitlab/slash_commands/dsl.rb b/lib/gitlab/slash_commands/dsl.rb index 614bafbe1b2..1b5b4566d81 100644 --- a/lib/gitlab/slash_commands/dsl.rb +++ b/lib/gitlab/slash_commands/dsl.rb @@ -40,8 +40,8 @@ module Gitlab # command :command_key do |arguments| # # Awesome code block # end - def params(*params) - @params = params + def params(*params, &block) + @params = block_given? ? block : params end # Allows to give an explanation of what the command will do when -- cgit v1.2.3 From 280529c7f40db6af7bb0bfd3ef30d330bbafc225 Mon Sep 17 00:00:00 2001 From: Adam Niedzielski Date: Wed, 7 Jun 2017 11:11:26 +0200 Subject: Fix incorrect ETag cache key when relative instance URL is used --- lib/gitlab/etag_caching/middleware.rb | 9 +++++---- lib/gitlab/etag_caching/router.rb | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/etag_caching/middleware.rb b/lib/gitlab/etag_caching/middleware.rb index 270d67dd50c..7f884183bb1 100644 --- a/lib/gitlab/etag_caching/middleware.rb +++ b/lib/gitlab/etag_caching/middleware.rb @@ -6,12 +6,13 @@ module Gitlab end def call(env) - route = Gitlab::EtagCaching::Router.match(env) + request = Rack::Request.new(env) + route = Gitlab::EtagCaching::Router.match(request) return @app.call(env) unless route track_event(:etag_caching_middleware_used, route) - etag, cached_value_present = get_etag(env) + etag, cached_value_present = get_etag(request) if_none_match = env['HTTP_IF_NONE_MATCH'] if if_none_match == etag @@ -27,8 +28,8 @@ module Gitlab private - def get_etag(env) - cache_key = env['PATH_INFO'] + def get_etag(request) + cache_key = request.path store = Gitlab::EtagCaching::Store.new current_value = store.get(cache_key) cached_value_present = current_value.present? diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index ca49eda51fb..dccc66b3918 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -53,8 +53,8 @@ module Gitlab ) ].freeze - def self.match(env) - ROUTES.find { |route| route.regexp.match(env['PATH_INFO']) } + def self.match(request) + ROUTES.find { |route| route.regexp.match(request.path_info) } end end end -- cgit v1.2.3 From 0edc1ef675b2a8eb0c075d0707104bf0751599ef Mon Sep 17 00:00:00 2001 From: Pawel Chojnacki Date: Wed, 7 Jun 2017 14:37:32 +0200 Subject: Use key? instead of has_key? method --- lib/gitlab/health_checks/prometheus_text_format.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/health_checks/prometheus_text_format.rb b/lib/gitlab/health_checks/prometheus_text_format.rb index 462c8e736a0..b3c759b4730 100644 --- a/lib/gitlab/health_checks/prometheus_text_format.rb +++ b/lib/gitlab/health_checks/prometheus_text_format.rb @@ -13,7 +13,7 @@ module Gitlab metrics.flat_map do |metric| metric_lines = [] - unless type_declaration_added.has_key?(metric.name) + unless type_declaration_added.key?(metric.name) type_declaration_added[metric.name] = true metric_lines << metric_type_declaration(metric) end -- cgit v1.2.3 From ed6f6cf2fc627ca9f1b0e8aa1ed6a9f7e6d2d3ab Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Wed, 7 Jun 2017 14:29:49 +0100 Subject: Fix memoization in ContributionsCalendar#activity_dates This doesn't appear to be actually called twice, but having it appear to work but not would be a problem if it was. --- lib/gitlab/contributions_calendar.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb index 15992b77680..060e013183f 100644 --- a/lib/gitlab/contributions_calendar.rb +++ b/lib/gitlab/contributions_calendar.rb @@ -28,7 +28,7 @@ module Gitlab union = Gitlab::SQL::Union.new([repo_events, issue_events, mr_events, note_events]) events = Event.find_by_sql(union.to_sql).map(&:attributes) - @activity_events = events.each_with_object(Hash.new {|h, k| h[k] = 0 }) do |event, activities| + @activity_dates = events.each_with_object(Hash.new {|h, k| h[k] = 0 }) do |event, activities| activities[event["date"]] += event["total_amount"] end end -- cgit v1.2.3 From c085f88fc6a293732cb9f1f96884c0795ff86bd3 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 7 Jun 2017 15:38:12 +0200 Subject: fix backup task to ignore errors per project --- lib/backup/repository.rb | 55 +++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'lib') diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index 6b29600a751..7723f9979b3 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -14,7 +14,7 @@ module Backup # Create namespace dir if missing FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace - if project.empty_repo? + if empty_repo?(project) $progress.puts "[SKIPPED]".color(:cyan) else in_path(path_to_project_repo) do |dir| @@ -23,10 +23,7 @@ module Backup output, status = Gitlab::Popen.popen(cmd) unless status.zero? - puts "[FAILED]".color(:red) - puts "failed: #{cmd.join(' ')}" - puts output - abort 'Backup failed' + progress_warn(project, cmd.join(' '), output) end end @@ -36,10 +33,7 @@ module Backup if status.zero? $progress.puts "[DONE]".color(:green) else - puts "[FAILED]".color(:red) - puts "failed: #{cmd.join(' ')}" - puts output - abort 'Backup failed' + progress_warn(project, cmd.join(' '), output) end end @@ -49,7 +43,7 @@ module Backup if File.exist?(path_to_wiki_repo) $progress.print " * #{wiki.path_with_namespace} ... " - if wiki.repository.empty? + if empty_wiki_repo?(wiki) $progress.puts " [SKIPPED]".color(:cyan) else cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_wiki_repo} bundle create #{path_to_wiki_bundle} --all) @@ -57,10 +51,7 @@ module Backup if status.zero? $progress.puts " [DONE]".color(:green) else - puts " [FAILED]".color(:red) - puts "failed: #{cmd.join(' ')}" - puts output - abort 'Backup failed' + progress_warn(wiki, cmd.join(' '), output) end end end @@ -96,10 +87,7 @@ module Backup if status.zero? $progress.puts "[DONE]".color(:green) else - puts "[FAILED]".color(:red) - puts "failed: #{cmd.join(' ')}" - puts output - abort 'Restore failed' + progress_warn(project, cmd.join(' '), output) end in_path(path_to_tars(project)) do |dir| @@ -107,10 +95,7 @@ module Backup output, status = Gitlab::Popen.popen(cmd) unless status.zero? - puts "[FAILED]".color(:red) - puts "failed: #{cmd.join(' ')}" - puts output - abort 'Restore failed' + progress_warn(project, cmd.join(' '), output) end end @@ -131,10 +116,7 @@ module Backup if status.zero? $progress.puts " [DONE]".color(:green) else - puts " [FAILED]".color(:red) - puts "failed: #{cmd.join(' ')}" - puts output - abort 'Restore failed' + progress_warn(project, cmd.join(' '), output) end end end @@ -201,6 +183,27 @@ module Backup private + def progress_warn(project, cmd, output) + $progress.puts "[WARNING] Executing #{cmd}".color(:orange) + $progress.puts "Ignoring error on #{project.path_with_namespace} - #{output}".color(:orange) + end + + def empty_repo?(project) + project.empty_repo? + rescue => e + $progress.puts "Ignoring error on #{project.full_path} repository - #{e.message}".color(:orange) + + false + end + + def empty_wiki_repo?(wiki) + wiki.repository.empty? + rescue => e + $progress.puts "Ignoring error on #{wiki.path_with_namespace} repository - #{e.message}".color(:orange) + + false + end + def repository_storage_paths_args Gitlab.config.repositories.storages.values.map { |rs| rs['path'] } end -- cgit v1.2.3 From 8acb0f55961500658377a1f941584dddb7952570 Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 7 Jun 2017 16:50:21 +0200 Subject: refactor code and spec --- lib/backup/repository.rb | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'lib') diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index 7723f9979b3..8e6235c2014 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -7,7 +7,7 @@ module Backup prepare Project.find_each(batch_size: 1000) do |project| - $progress.print " * #{project.path_with_namespace} ... " + progress.print " * #{project.path_with_namespace} ... " path_to_project_repo = path_to_repo(project) path_to_project_bundle = path_to_bundle(project) @@ -15,7 +15,7 @@ module Backup FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace if empty_repo?(project) - $progress.puts "[SKIPPED]".color(:cyan) + progress.puts "[SKIPPED]".color(:cyan) else in_path(path_to_project_repo) do |dir| FileUtils.mkdir_p(path_to_tars(project)) @@ -31,7 +31,7 @@ module Backup output, status = Gitlab::Popen.popen(cmd) if status.zero? - $progress.puts "[DONE]".color(:green) + progress.puts "[DONE]".color(:green) else progress_warn(project, cmd.join(' '), output) end @@ -42,14 +42,14 @@ module Backup path_to_wiki_bundle = path_to_bundle(wiki) if File.exist?(path_to_wiki_repo) - $progress.print " * #{wiki.path_with_namespace} ... " + progress.print " * #{wiki.path_with_namespace} ... " if empty_wiki_repo?(wiki) - $progress.puts " [SKIPPED]".color(:cyan) + progress.puts " [SKIPPED]".color(:cyan) else cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_wiki_repo} bundle create #{path_to_wiki_bundle} --all) output, status = Gitlab::Popen.popen(cmd) if status.zero? - $progress.puts " [DONE]".color(:green) + progress.puts " [DONE]".color(:green) else progress_warn(wiki, cmd.join(' '), output) end @@ -71,7 +71,7 @@ module Backup end Project.find_each(batch_size: 1000) do |project| - $progress.print " * #{project.path_with_namespace} ... " + progress.print " * #{project.path_with_namespace} ... " path_to_project_repo = path_to_repo(project) path_to_project_bundle = path_to_bundle(project) @@ -85,7 +85,7 @@ module Backup output, status = Gitlab::Popen.popen(cmd) if status.zero? - $progress.puts "[DONE]".color(:green) + progress.puts "[DONE]".color(:green) else progress_warn(project, cmd.join(' '), output) end @@ -104,7 +104,7 @@ module Backup path_to_wiki_bundle = path_to_bundle(wiki) if File.exist?(path_to_wiki_bundle) - $progress.print " * #{wiki.path_with_namespace} ... " + progress.print " * #{wiki.path_with_namespace} ... " # If a wiki bundle exists, first remove the empty repo # that was initialized with ProjectWiki.new() and then @@ -114,19 +114,19 @@ module Backup output, status = Gitlab::Popen.popen(cmd) if status.zero? - $progress.puts " [DONE]".color(:green) + progress.puts " [DONE]".color(:green) else progress_warn(project, cmd.join(' '), output) end end end - $progress.print 'Put GitLab hooks in repositories dirs'.color(:yellow) + progress.print 'Put GitLab hooks in repositories dirs'.color(:yellow) cmd = %W(#{Gitlab.config.gitlab_shell.path}/bin/create-hooks) + repository_storage_paths_args output, status = Gitlab::Popen.popen(cmd) if status.zero? - $progress.puts " [DONE]".color(:green) + progress.puts " [DONE]".color(:green) else puts " [FAILED]".color(:red) puts "failed: #{cmd}" @@ -184,22 +184,14 @@ module Backup private def progress_warn(project, cmd, output) - $progress.puts "[WARNING] Executing #{cmd}".color(:orange) - $progress.puts "Ignoring error on #{project.path_with_namespace} - #{output}".color(:orange) + progress.puts "[WARNING] Executing #{cmd}".color(:orange) + progress.puts "Ignoring error on #{project.path_with_namespace} - #{output}".color(:orange) end - def empty_repo?(project) - project.empty_repo? + def empty_repo?(project_or_wiki) + project_or_wiki.repository.empty_repo? rescue => e - $progress.puts "Ignoring error on #{project.full_path} repository - #{e.message}".color(:orange) - - false - end - - def empty_wiki_repo?(wiki) - wiki.repository.empty? - rescue => e - $progress.puts "Ignoring error on #{wiki.path_with_namespace} repository - #{e.message}".color(:orange) + progress.puts "Ignoring repository error and continuing backing up project: #{project_or_wiki.path_with_namespace} - #{e.message}".color(:orange) false end @@ -207,5 +199,9 @@ module Backup def repository_storage_paths_args Gitlab.config.repositories.storages.values.map { |rs| rs['path'] } end + + def progress + progress + end end end -- cgit v1.2.3 From a5b920dcf0a5ff6cbef718ea278207916425034e Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 7 Jun 2017 16:54:12 +0200 Subject: fix wiki --- lib/backup/repository.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index 8e6235c2014..e93827211ae 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -43,7 +43,7 @@ module Backup if File.exist?(path_to_wiki_repo) progress.print " * #{wiki.path_with_namespace} ... " - if empty_wiki_repo?(wiki) + if empty_repo?(wiki) progress.puts " [SKIPPED]".color(:cyan) else cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_wiki_repo} bundle create #{path_to_wiki_bundle} --all) -- cgit v1.2.3 From 35a78da27f94e7b77c8487913beceb23db3b66bc Mon Sep 17 00:00:00 2001 From: James Lopez Date: Wed, 7 Jun 2017 17:00:32 +0200 Subject: fix typo --- lib/backup/repository.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index e93827211ae..a1685c77916 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -201,7 +201,7 @@ module Backup end def progress - progress + $progress end end end -- cgit v1.2.3 From 469acd190e497cda8516da0ee481f33e038d7e9e Mon Sep 17 00:00:00 2001 From: Robin Bobbitt Date: Tue, 6 Jun 2017 11:39:54 -0400 Subject: Sync email address from specified omniauth provider --- lib/gitlab/ldap/user.rb | 13 ++++--------- lib/gitlab/o_auth/user.rb | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ldap/user.rb b/lib/gitlab/ldap/user.rb index 2d5e47a6f3b..5e299e26c54 100644 --- a/lib/gitlab/ldap/user.rb +++ b/lib/gitlab/ldap/user.rb @@ -41,11 +41,6 @@ module Gitlab def update_user_attributes if persisted? - if auth_hash.has_email? - gl_user.skip_reconfirmation! - gl_user.email = auth_hash.email - end - # 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) @@ -55,10 +50,6 @@ module Gitlab # For an existing identity with no change in DN, this line changes nothing. identity.extern_uid = auth_hash.uid end - - gl_user.ldap_email = auth_hash.has_email? - - gl_user end def changed? @@ -69,6 +60,10 @@ module Gitlab ldap_config.block_auto_created_users end + def sync_email_from_provider? + true + end + def allowed? Gitlab::LDAP::Access.allowed?(gl_user) end diff --git a/lib/gitlab/o_auth/user.rb b/lib/gitlab/o_auth/user.rb index afd24b4dcc5..7307f8c2c87 100644 --- a/lib/gitlab/o_auth/user.rb +++ b/lib/gitlab/o_auth/user.rb @@ -12,6 +12,7 @@ module Gitlab def initialize(auth_hash) self.auth_hash = auth_hash + update_email end def persisted? @@ -174,6 +175,22 @@ module Gitlab } end + def sync_email_from_provider? + auth_hash.provider.to_s == Gitlab.config.omniauth.sync_email_from_provider.to_s + end + + def update_email + if auth_hash.has_email? && sync_email_from_provider? + if persisted? + gl_user.skip_reconfirmation! + gl_user.email = auth_hash.email + end + + gl_user.external_email = true + gl_user.email_provider = auth_hash.provider + end + end + def log Gitlab::AppLogger end -- cgit v1.2.3 From 6c8e72b4108e5c671970a3965b214c8b1dda53ae Mon Sep 17 00:00:00 2001 From: Filip Krakowski Date: Thu, 1 Jun 2017 11:58:34 +0200 Subject: Add 'schedules' keyword to 'only' and 'except' --- lib/ci/gitlab_ci_yaml_processor.rb | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 22af2671b18..b941a54c85a 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -20,26 +20,26 @@ module Ci raise ValidationError, e.message end - def jobs_for_ref(ref, tag = false, trigger_request = nil) + def jobs_for_ref(ref, tag = false, trigger_request = nil, pipeline_schedule = nil) @jobs.select do |_, job| - process?(job[:only], job[:except], ref, tag, trigger_request) + process?(job[:only], job[:except], ref, tag, trigger_request, pipeline_schedule) end end - def jobs_for_stage_and_ref(stage, ref, tag = false, trigger_request = nil) - jobs_for_ref(ref, tag, trigger_request).select do |_, job| + def jobs_for_stage_and_ref(stage, ref, tag = false, trigger_request = nil, pipeline_schedule = nil) + jobs_for_ref(ref, tag, trigger_request, pipeline_schedule).select do |_, job| job[:stage] == stage end end - def builds_for_ref(ref, tag = false, trigger_request = nil) - jobs_for_ref(ref, tag, trigger_request).map do |name, _| + def builds_for_ref(ref, tag = false, trigger_request = nil, pipeline_schedule = nil) + jobs_for_ref(ref, tag, trigger_request, pipeline_schedule).map do |name, _| build_attributes(name) end end - def builds_for_stage_and_ref(stage, ref, tag = false, trigger_request = nil) - jobs_for_stage_and_ref(stage, ref, tag, trigger_request).map do |name, _| + def builds_for_stage_and_ref(stage, ref, tag = false, trigger_request = nil, pipeline_schedule = nil) + jobs_for_stage_and_ref(stage, ref, tag, trigger_request, pipeline_schedule).map do |name, _| build_attributes(name) end end @@ -193,30 +193,31 @@ module Ci end end - def process?(only_params, except_params, ref, tag, trigger_request) + def process?(only_params, except_params, ref, tag, trigger_request, pipeline_schedule) if only_params.present? - return false unless matching?(only_params, ref, tag, trigger_request) + return false unless matching?(only_params, ref, tag, trigger_request, pipeline_schedule) end if except_params.present? - return false if matching?(except_params, ref, tag, trigger_request) + return false if matching?(except_params, ref, tag, trigger_request, pipeline_schedule) end true end - def matching?(patterns, ref, tag, trigger_request) + def matching?(patterns, ref, tag, trigger_request, pipeline_schedule) patterns.any? do |pattern| - match_ref?(pattern, ref, tag, trigger_request) + match_ref?(pattern, ref, tag, trigger_request, pipeline_schedule) end end - def match_ref?(pattern, ref, tag, trigger_request) + def match_ref?(pattern, ref, tag, trigger_request, pipeline_schedule) pattern, path = pattern.split('@', 2) return false if path && path != self.path return true if tag && pattern == 'tags' return true if !tag && pattern == 'branches' return true if trigger_request.present? && pattern == 'triggers' + return true if pipeline_schedule.present? && pattern == 'schedules' if pattern.first == "/" && pattern.last == "/" Regexp.new(pattern[1...-1]) =~ ref -- cgit v1.2.3 From 8db63b26284d949000316a38676ef6fad970f657 Mon Sep 17 00:00:00 2001 From: Filip Krakowski Date: Thu, 1 Jun 2017 21:55:57 +0200 Subject: Use pipeline.source to determine what triggered a pipeline --- lib/ci/gitlab_ci_yaml_processor.rb | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index b941a54c85a..98600a48d0f 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -20,26 +20,26 @@ module Ci raise ValidationError, e.message end - def jobs_for_ref(ref, tag = false, trigger_request = nil, pipeline_schedule = nil) + def jobs_for_ref(ref, tag = false, source = nil) @jobs.select do |_, job| - process?(job[:only], job[:except], ref, tag, trigger_request, pipeline_schedule) + process?(job[:only], job[:except], ref, tag, source) end end - def jobs_for_stage_and_ref(stage, ref, tag = false, trigger_request = nil, pipeline_schedule = nil) - jobs_for_ref(ref, tag, trigger_request, pipeline_schedule).select do |_, job| + def jobs_for_stage_and_ref(stage, ref, tag = false, source = nil) + jobs_for_ref(ref, tag, source).select do |_, job| job[:stage] == stage end end - def builds_for_ref(ref, tag = false, trigger_request = nil, pipeline_schedule = nil) - jobs_for_ref(ref, tag, trigger_request, pipeline_schedule).map do |name, _| + def builds_for_ref(ref, tag = false, source = nil) + jobs_for_ref(ref, tag, source).map do |name, _| build_attributes(name) end end - def builds_for_stage_and_ref(stage, ref, tag = false, trigger_request = nil, pipeline_schedule = nil) - jobs_for_stage_and_ref(stage, ref, tag, trigger_request, pipeline_schedule).map do |name, _| + def builds_for_stage_and_ref(stage, ref, tag = false, source = nil) + jobs_for_stage_and_ref(stage, ref, tag, source).map do |name, _| build_attributes(name) end end @@ -193,31 +193,31 @@ module Ci end end - def process?(only_params, except_params, ref, tag, trigger_request, pipeline_schedule) + def process?(only_params, except_params, ref, tag, source) if only_params.present? - return false unless matching?(only_params, ref, tag, trigger_request, pipeline_schedule) + return false unless matching?(only_params, ref, tag, source) end if except_params.present? - return false if matching?(except_params, ref, tag, trigger_request, pipeline_schedule) + return false if matching?(except_params, ref, tag, source) end true end - def matching?(patterns, ref, tag, trigger_request, pipeline_schedule) + def matching?(patterns, ref, tag, source) patterns.any? do |pattern| - match_ref?(pattern, ref, tag, trigger_request, pipeline_schedule) + match_ref?(pattern, ref, tag, source) end end - def match_ref?(pattern, ref, tag, trigger_request, pipeline_schedule) + def match_ref?(pattern, ref, tag, source) pattern, path = pattern.split('@', 2) return false if path && path != self.path return true if tag && pattern == 'tags' return true if !tag && pattern == 'branches' - return true if trigger_request.present? && pattern == 'triggers' - return true if pipeline_schedule.present? && pattern == 'schedules' + return true if source == 'trigger' && pattern == 'triggers' + return true if source == 'schedule' && pattern == 'schedules' if pattern.first == "/" && pattern.last == "/" Regexp.new(pattern[1...-1]) =~ ref -- cgit v1.2.3 From ecb54cddd164fbf83288d7903c4692df462bae5e Mon Sep 17 00:00:00 2001 From: Filip Krakowski Date: Fri, 2 Jun 2017 19:02:56 +0200 Subject: Add all sources as special keywords for only and except --- lib/ci/gitlab_ci_yaml_processor.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 98600a48d0f..0b362921b06 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -207,17 +207,15 @@ module Ci def matching?(patterns, ref, tag, source) patterns.any? do |pattern| - match_ref?(pattern, ref, tag, source) + match_ref?(pattern, ref, tag) || match_source?(pattern, source) end end - def match_ref?(pattern, ref, tag, source) + def match_ref?(pattern, ref, tag) pattern, path = pattern.split('@', 2) return false if path && path != self.path return true if tag && pattern == 'tags' return true if !tag && pattern == 'branches' - return true if source == 'trigger' && pattern == 'triggers' - return true if source == 'schedule' && pattern == 'schedules' if pattern.first == "/" && pattern.last == "/" Regexp.new(pattern[1...-1]) =~ ref @@ -225,5 +223,14 @@ module Ci pattern == ref end end + + def match_source?(pattern, source) + return source_to_pattern(source) == pattern + end + + def source_to_pattern(source) + return source if ['api', 'external', 'web'].include? source + return source.pluralize + end end end -- cgit v1.2.3 From 1dd054e1788fa7b308a9088f3bb35808a027e76d Mon Sep 17 00:00:00 2001 From: Filip Krakowski Date: Fri, 2 Jun 2017 19:58:20 +0200 Subject: Fix static-analysis offenses --- lib/ci/gitlab_ci_yaml_processor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 0b362921b06..d236c42929a 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -229,7 +229,7 @@ module Ci end def source_to_pattern(source) - return source if ['api', 'external', 'web'].include? source + return source if %w(api external web).include? source return source.pluralize end end -- cgit v1.2.3 From 7457d076ceb0078e6e9b6cbd9559564bff27b7d0 Mon Sep 17 00:00:00 2001 From: Filip Krakowski Date: Fri, 2 Jun 2017 20:12:44 +0200 Subject: Check if source is nil --- lib/ci/gitlab_ci_yaml_processor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index d236c42929a..feac7c87466 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -229,7 +229,7 @@ module Ci end def source_to_pattern(source) - return source if %w(api external web).include? source + return source if %w(api external web).include?(source) || source.nil? return source.pluralize end end -- cgit v1.2.3 From 1736a2dab6bcab8bb5632e211525bd806bef003a Mon Sep 17 00:00:00 2001 From: Filip Krakowski Date: Mon, 5 Jun 2017 17:15:15 +0200 Subject: Fix change in behavior --- lib/ci/gitlab_ci_yaml_processor.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index feac7c87466..a58af73debb 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -207,15 +207,19 @@ module Ci def matching?(patterns, ref, tag, source) patterns.any? do |pattern| - match_ref?(pattern, ref, tag) || match_source?(pattern, source) + pattern, path = pattern.split('@', 2) + match_path?(path) && match_pattern?(pattern, ref, tag, source) end end - def match_ref?(pattern, ref, tag) - pattern, path = pattern.split('@', 2) - return false if path && path != self.path + def match_path?(path) + return !(path && path != self.path) + end + + def match_pattern?(pattern, ref, tag, source) return true if tag && pattern == 'tags' return true if !tag && pattern == 'branches' + return true if source_to_pattern(source) == pattern if pattern.first == "/" && pattern.last == "/" Regexp.new(pattern[1...-1]) =~ ref @@ -224,10 +228,6 @@ module Ci end end - def match_source?(pattern, source) - return source_to_pattern(source) == pattern - end - def source_to_pattern(source) return source if %w(api external web).include?(source) || source.nil? return source.pluralize -- cgit v1.2.3 From 431d7972b6d0f492bd82004b80d426f2e2cff6a5 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 7 Jun 2017 22:14:36 +0900 Subject: Fix unmatches_path --- lib/ci/gitlab_ci_yaml_processor.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index a58af73debb..738ff474596 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -208,15 +208,15 @@ module Ci def matching?(patterns, ref, tag, source) patterns.any? do |pattern| pattern, path = pattern.split('@', 2) - match_path?(path) && match_pattern?(pattern, ref, tag, source) + unmatches_path?(path) && matches_pattern?(pattern, ref, tag, source) end end - def match_path?(path) - return !(path && path != self.path) + def unmatches_path?(path) + path && path != self.path end - def match_pattern?(pattern, ref, tag, source) + def matches_pattern?(pattern, ref, tag, source) return true if tag && pattern == 'tags' return true if !tag && pattern == 'branches' return true if source_to_pattern(source) == pattern @@ -229,8 +229,11 @@ module Ci end def source_to_pattern(source) - return source if %w(api external web).include?(source) || source.nil? - return source.pluralize + if %w(api external web).include?(source) || source.nil? + source + else + source.pluralize + end end end end -- cgit v1.2.3 From 465e5de5107da7e280902de581ee29c6f0cd1abc Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 7 Jun 2017 22:24:11 +0900 Subject: Fix condition --- lib/ci/gitlab_ci_yaml_processor.rb | 8 +++++--- lib/gitlab/gitaly_client.rb | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 738ff474596..bd3ce40ca4b 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -208,12 +208,14 @@ module Ci def matching?(patterns, ref, tag, source) patterns.any? do |pattern| pattern, path = pattern.split('@', 2) - unmatches_path?(path) && matches_pattern?(pattern, ref, tag, source) + matches_path?(path) && matches_pattern?(pattern, ref, tag, source) end end - def unmatches_path?(path) - path && path != self.path + def matches_path?(path) + return true unless path + + path == self.path end def matches_pattern?(pattern, ref, tag, source) diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index 2343446bf22..598f642415a 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -49,7 +49,8 @@ module Gitlab end def self.enabled? - Gitlab.config.gitaly.enabled + # Gitlab.config.gitaly.enabled + false end def self.feature_enabled?(feature, status: MigrationStatus::OPT_IN) -- cgit v1.2.3 From 835f97a7e26ae7b199d886f35e33255016538134 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 7 Jun 2017 22:26:04 +0900 Subject: Remove source.nil --- lib/ci/gitlab_ci_yaml_processor.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index bd3ce40ca4b..c3fa875bfe6 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -214,7 +214,7 @@ module Ci def matches_path?(path) return true unless path - + path == self.path end @@ -231,10 +231,10 @@ module Ci end def source_to_pattern(source) - if %w(api external web).include?(source) || source.nil? + if %w(api external web).include?(source) source else - source.pluralize + source&.pluralize end end end -- cgit v1.2.3 From 451b684d8474d5c16007d69f462f08f2191820f2 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 7 Jun 2017 22:45:24 +0900 Subject: Use source instead of trigger_requests in stage_seeds --- lib/ci/gitlab_ci_yaml_processor.rb | 4 +--- lib/gitlab/gitaly_client.rb | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index c3fa875bfe6..9a681c65d4b 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -51,11 +51,9 @@ module Ci end def stage_seeds(pipeline) - trigger_request = pipeline.trigger_requests.first - seeds = @stages.uniq.map do |stage| builds = builds_for_stage_and_ref( - stage, pipeline.ref, pipeline.tag?, trigger_request) + stage, pipeline.ref, pipeline.tag?, pipeline.source) Gitlab::Ci::Stage::Seed.new(pipeline, stage, builds) if builds.any? end diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index 598f642415a..2343446bf22 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -49,8 +49,7 @@ module Gitlab end def self.enabled? - # Gitlab.config.gitaly.enabled - false + Gitlab.config.gitaly.enabled end def self.feature_enabled?(feature, status: MigrationStatus::OPT_IN) -- cgit v1.2.3 From 32bfa48ad0b2d930d3a95656774982afed7489f0 Mon Sep 17 00:00:00 2001 From: Shinya Maeda Date: Wed, 7 Jun 2017 22:59:06 +0900 Subject: use squre bracket --- lib/ci/gitlab_ci_yaml_processor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 9a681c65d4b..56ad2c77c7d 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -229,7 +229,7 @@ module Ci end def source_to_pattern(source) - if %w(api external web).include?(source) + if %w[api external web].include?(source) source else source&.pluralize -- cgit v1.2.3 From 32cac597275706930b221b19fb20b29ccebc7130 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Wed, 7 Jun 2017 18:33:50 +0000 Subject: Added more actions and report as abuse to all notes --- lib/gitlab/url_builder.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb index ccb456bcc94..23af9318d1a 100644 --- a/lib/gitlab/url_builder.rb +++ b/lib/gitlab/url_builder.rb @@ -61,7 +61,12 @@ module Gitlab elsif object.for_snippet? snippet = Snippet.find(object.noteable_id) - project_snippet_url(snippet, anchor: dom_id(object)) + + if snippet.is_a?(PersonalSnippet) + snippet_url(snippet, anchor: dom_id(object)) + else + project_snippet_url(snippet, anchor: dom_id(object)) + end end end -- cgit v1.2.3 From bdebe849b8251f390378dd446d9022fca1b2d55c Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Wed, 7 Jun 2017 20:13:44 +0000 Subject: Translate project & repository pages --- lib/gitlab/ci/status/canceled.rb | 4 ++-- lib/gitlab/ci/status/created.rb | 4 ++-- lib/gitlab/ci/status/failed.rb | 4 ++-- lib/gitlab/ci/status/manual.rb | 4 ++-- lib/gitlab/ci/status/pending.rb | 4 ++-- lib/gitlab/ci/status/pipeline/blocked.rb | 4 ++-- lib/gitlab/ci/status/running.rb | 4 ++-- lib/gitlab/ci/status/skipped.rb | 4 ++-- lib/gitlab/ci/status/success.rb | 4 ++-- lib/gitlab/ci/status/success_warning.rb | 4 ++-- lib/gitlab/visibility_level.rb | 6 +++--- 11 files changed, 23 insertions(+), 23 deletions(-) (limited to 'lib') diff --git a/lib/gitlab/ci/status/canceled.rb b/lib/gitlab/ci/status/canceled.rb index 97c121ce7b9..e5fdc1f8136 100644 --- a/lib/gitlab/ci/status/canceled.rb +++ b/lib/gitlab/ci/status/canceled.rb @@ -3,11 +3,11 @@ module Gitlab module Status class Canceled < Status::Core def text - 'canceled' + s_('CiStatusText|canceled') end def label - 'canceled' + s_('CiStatusLabel|canceled') end def icon diff --git a/lib/gitlab/ci/status/created.rb b/lib/gitlab/ci/status/created.rb index 0721bf6ec7c..d188bd286a6 100644 --- a/lib/gitlab/ci/status/created.rb +++ b/lib/gitlab/ci/status/created.rb @@ -3,11 +3,11 @@ module Gitlab module Status class Created < Status::Core def text - 'created' + s_('CiStatusText|created') end def label - 'created' + s_('CiStatusLabel|created') end def icon diff --git a/lib/gitlab/ci/status/failed.rb b/lib/gitlab/ci/status/failed.rb index cb75e9383a8..38e45714c22 100644 --- a/lib/gitlab/ci/status/failed.rb +++ b/lib/gitlab/ci/status/failed.rb @@ -3,11 +3,11 @@ module Gitlab module Status class Failed < Status::Core def text - 'failed' + s_('CiStatusText|failed') end def label - 'failed' + s_('CiStatusLabel|failed') end def icon diff --git a/lib/gitlab/ci/status/manual.rb b/lib/gitlab/ci/status/manual.rb index f8f6c2903ba..a4a7edadac9 100644 --- a/lib/gitlab/ci/status/manual.rb +++ b/lib/gitlab/ci/status/manual.rb @@ -3,11 +3,11 @@ module Gitlab module Status class Manual < Status::Core def text - 'manual' + s_('CiStatusText|manual') end def label - 'manual action' + s_('CiStatusLabel|manual action') end def icon diff --git a/lib/gitlab/ci/status/pending.rb b/lib/gitlab/ci/status/pending.rb index f40cc1314dc..5164260b861 100644 --- a/lib/gitlab/ci/status/pending.rb +++ b/lib/gitlab/ci/status/pending.rb @@ -3,11 +3,11 @@ module Gitlab module Status class Pending < Status::Core def text - 'pending' + s_('CiStatusText|pending') end def label - 'pending' + s_('CiStatusLabel|pending') end def icon diff --git a/lib/gitlab/ci/status/pipeline/blocked.rb b/lib/gitlab/ci/status/pipeline/blocked.rb index 37dfe43fb62..bf7e484ee9b 100644 --- a/lib/gitlab/ci/status/pipeline/blocked.rb +++ b/lib/gitlab/ci/status/pipeline/blocked.rb @@ -4,11 +4,11 @@ module Gitlab module Pipeline class Blocked < Status::Extended def text - 'blocked' + s_('CiStatusText|blocked') end def label - 'waiting for manual action' + s_('CiStatusLabel|waiting for manual action') end def self.matches?(pipeline, user) diff --git a/lib/gitlab/ci/status/running.rb b/lib/gitlab/ci/status/running.rb index 1237cd47dc8..993937e98ca 100644 --- a/lib/gitlab/ci/status/running.rb +++ b/lib/gitlab/ci/status/running.rb @@ -3,11 +3,11 @@ module Gitlab module Status class Running < Status::Core def text - 'running' + s_('CiStatus|running') end def label - 'running' + s_('CiStatus|running') end def icon diff --git a/lib/gitlab/ci/status/skipped.rb b/lib/gitlab/ci/status/skipped.rb index 28005d91503..0c942920b02 100644 --- a/lib/gitlab/ci/status/skipped.rb +++ b/lib/gitlab/ci/status/skipped.rb @@ -3,11 +3,11 @@ module Gitlab module Status class Skipped < Status::Core def text - 'skipped' + s_('CiStatusText|skipped') end def label - 'skipped' + s_('CiStatusLabel|skipped') end def icon diff --git a/lib/gitlab/ci/status/success.rb b/lib/gitlab/ci/status/success.rb index 88f7758a270..d7af98857b0 100644 --- a/lib/gitlab/ci/status/success.rb +++ b/lib/gitlab/ci/status/success.rb @@ -3,11 +3,11 @@ module Gitlab module Status class Success < Status::Core def text - 'passed' + s_('CiStatusText|passed') end def label - 'passed' + s_('CiStatusLabel|passed') end def icon diff --git a/lib/gitlab/ci/status/success_warning.rb b/lib/gitlab/ci/status/success_warning.rb index df6e76b0151..4d7d82e04cf 100644 --- a/lib/gitlab/ci/status/success_warning.rb +++ b/lib/gitlab/ci/status/success_warning.rb @@ -7,11 +7,11 @@ module Gitlab # class SuccessWarning < Status::Extended def text - 'passed' + s_('CiStatusText|passed') end def label - 'passed with warnings' + s_('CiStatusLabel|passed with warnings') end def icon diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb index 85da4c8660b..2b53798e70f 100644 --- a/lib/gitlab/visibility_level.rb +++ b/lib/gitlab/visibility_level.rb @@ -41,9 +41,9 @@ module Gitlab def options { - 'Private' => PRIVATE, - 'Internal' => INTERNAL, - 'Public' => PUBLIC + N_('VisibilityLevel|Private') => PRIVATE, + N_('VisibilityLevel|Internal') => INTERNAL, + N_('VisibilityLevel|Public') => PUBLIC } end -- cgit v1.2.3 From c50cded96e5f6f0eaadf9e49ac98f722f09b8fa8 Mon Sep 17 00:00:00 2001 From: "http://jneen.net/" Date: Wed, 7 Jun 2017 17:49:03 -0700 Subject: remove the rouge copypasta and add notes to refactor --- lib/rouge/lexers/math.rb | 16 ++-------------- lib/rouge/lexers/plantuml.rb | 16 ++-------------- 2 files changed, 4 insertions(+), 28 deletions(-) (limited to 'lib') diff --git a/lib/rouge/lexers/math.rb b/lib/rouge/lexers/math.rb index 80784adfd76..939b23a3421 100644 --- a/lib/rouge/lexers/math.rb +++ b/lib/rouge/lexers/math.rb @@ -1,21 +1,9 @@ module Rouge module Lexers - class Math < Lexer + class Math < PlainText title "A passthrough lexer used for LaTeX input" - desc "A boring lexer that doesn't highlight anything" - + desc "PLEASE REFACTOR - this should be handled by SyntaxHighlightFilter" tag 'math' - mimetypes 'text/plain' - - default_options token: 'Text' - - def token - @token ||= Token[option :token] - end - - def stream_tokens(string, &b) - yield self.token, string - end end end end diff --git a/lib/rouge/lexers/plantuml.rb b/lib/rouge/lexers/plantuml.rb index 7d5700b7f6d..63c461764fc 100644 --- a/lib/rouge/lexers/plantuml.rb +++ b/lib/rouge/lexers/plantuml.rb @@ -1,21 +1,9 @@ module Rouge module Lexers - class Plantuml < Lexer + class Plantuml < PlainText title "A passthrough lexer used for PlantUML input" - desc "A boring lexer that doesn't highlight anything" - + desc "PLEASE REFACTOR - this should be handled by SyntaxHighlightFilter" tag 'plantuml' - mimetypes 'text/plain' - - default_options token: 'Text' - - def token - @token ||= Token[option :token] - end - - def stream_tokens(string, &b) - yield self.token, string - end end end end -- cgit v1.2.3