diff options
author | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2017-07-24 11:01:34 +0200 |
---|---|---|
committer | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2017-07-24 11:01:34 +0200 |
commit | 0aefb51693747a06a3e9ecd5c7a29e14a5ac0383 (patch) | |
tree | 1e109048dc85bd0d62bb5d5827c7379ea1ea3f87 /lib | |
parent | 5505795ed2e65da20a896b67422a075515552a35 (diff) | |
parent | 883488e0b2adda7dad93334f17f3895f05a7c587 (diff) | |
download | gitlab-ce-0aefb51693747a06a3e9ecd5c7a29e14a5ac0383.tar.gz |
Merge branch 'master' into backstage/gb/migrate-stages-statuses
* master: (97 commits)
Bulk update sidebar UI polish
Fix margin in mini graph for commits box
Add space between words in language dropdown
Fix support for old CI API when image or services are not specified
Short-circuit build coverage extraction for empty regexes
Update VERSION to 9.5.0-pre
Update CHANGELOG.md for 9.4.0
Compress gitlab svg logo
Fix the gcovr coverage regex by removing line separators before scanning
Capitalize Sidekiq word in dev doc
Add 1px to breadcrumbs min height
Update nginx docs
Use custom font SVG for logo
Port spinach tests to rspec feature specs
Merge branch 'fix-re2-infinite-loop-nick' into 'security-9-3'
Copy-edit background migrations guidelines
Add Traditional Chinese in Taiwan translations of Pipeline Schedules
Fix new project selectors in GitLab QA
Reword success to passing for pipeline badges
Rename build to pipeline for status badges
...
Diffstat (limited to 'lib')
43 files changed, 311 insertions, 108 deletions
diff --git a/lib/api/access_requests.rb b/lib/api/access_requests.rb index c9b5f58c557..cdacf9839e5 100644 --- a/lib/api/access_requests.rb +++ b/lib/api/access_requests.rb @@ -68,6 +68,7 @@ module API delete ":id/access_requests/:user_id" do source = find_source(source_type, params[:id]) + status 204 ::Members::DestroyService.new(source, current_user, params) .execute(:requesters) end diff --git a/lib/api/award_emoji.rb b/lib/api/award_emoji.rb index 56f19f89642..5a028fc9d0b 100644 --- a/lib/api/award_emoji.rb +++ b/lib/api/award_emoji.rb @@ -88,6 +88,7 @@ module API unauthorized! unless award.user == current_user || current_user.admin? + status 204 award.destroy end end diff --git a/lib/api/broadcast_messages.rb b/lib/api/broadcast_messages.rb index 395c401203c..9980aec4752 100644 --- a/lib/api/broadcast_messages.rb +++ b/lib/api/broadcast_messages.rb @@ -91,6 +91,7 @@ module API delete ':id' do message = find_message + status 204 message.destroy end end diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb index d5c2f3d5094..42e7c1486b0 100644 --- a/lib/api/deploy_keys.rb +++ b/lib/api/deploy_keys.rb @@ -125,6 +125,7 @@ module API key = user_project.deploy_keys_projects.find_by(deploy_key_id: params[:key_id]) not_found!('Deploy Key') unless key + status 204 key.destroy end end diff --git a/lib/api/environments.rb b/lib/api/environments.rb index 945771d46f3..c774a5c6685 100644 --- a/lib/api/environments.rb +++ b/lib/api/environments.rb @@ -79,6 +79,7 @@ module API environment = user_project.environments.find(params[:environment_id]) + status 204 environment.destroy end diff --git a/lib/api/groups.rb b/lib/api/groups.rb index ebbaed0cbb7..49c3b2278c7 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -125,6 +125,8 @@ module API delete ":id" do group = find_group!(params[:id]) authorize! :admin_group, group + + status 204 ::Groups::DestroyService.new(group, current_user).execute end diff --git a/lib/api/issues.rb b/lib/api/issues.rb index 64be08094ed..14b26f28ebf 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -224,6 +224,7 @@ module API not_found!('Issue') unless issue authorize!(:destroy_issue, issue) + status 204 issue.destroy end diff --git a/lib/api/labels.rb b/lib/api/labels.rb index 20b25529d0c..4520c98d951 100644 --- a/lib/api/labels.rb +++ b/lib/api/labels.rb @@ -56,6 +56,7 @@ module API label = user_project.labels.find_by(title: params[:name]) not_found!('Label') unless label + status 204 label.destroy end diff --git a/lib/api/members.rb b/lib/api/members.rb index c200e46a328..bb970b7cd54 100644 --- a/lib/api/members.rb +++ b/lib/api/members.rb @@ -96,6 +96,7 @@ module API # Ensure that memeber exists source.members.find_by!(user_id: params[:user_id]) + status 204 ::Members::DestroyService.new(source, current_user, declared_params).execute end end diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb index ac33b2b801c..6e2e13e0a24 100644 --- a/lib/api/merge_requests.rb +++ b/lib/api/merge_requests.rb @@ -137,6 +137,7 @@ module API merge_request = find_project_merge_request(params[:merge_request_iid]) authorize!(:destroy_merge_request, merge_request) + status 204 merge_request.destroy end diff --git a/lib/api/notes.rb b/lib/api/notes.rb index 01ca62b593f..65ff89edf65 100644 --- a/lib/api/notes.rb +++ b/lib/api/notes.rb @@ -131,6 +131,7 @@ module API note = user_project.notes.find(params[:note_id]) authorize! :admin_note, note + status 204 ::Notes::DestroyService.new(user_project, current_user).execute(note) end end diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb index 7a345289617..649dd891f56 100644 --- a/lib/api/project_hooks.rb +++ b/lib/api/project_hooks.rb @@ -96,6 +96,7 @@ module API delete ":id/hooks/:hook_id" do hook = user_project.hooks.find(params.delete(:hook_id)) + status 204 hook.destroy end end diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb index 3320eadff0d..f3d905b0068 100644 --- a/lib/api/project_snippets.rb +++ b/lib/api/project_snippets.rb @@ -116,6 +116,7 @@ module API not_found!('Snippet') unless snippet authorize! :admin_project_snippet, snippet + status 204 snippet.destroy end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index c459257158d..89dda88d3f5 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -361,6 +361,7 @@ module API authorize! :remove_fork_project, user_project if user_project.forked? + status 204 user_project.forked_project_link.destroy else not_modified! @@ -405,6 +406,7 @@ module API link = user_project.project_group_links.find_by(group_id: params[:group_id]) not_found!('Group Link') unless link + status 204 link.destroy end diff --git a/lib/api/runner.rb b/lib/api/runner.rb index 4552115b3e2..405d25ca3c1 100644 --- a/lib/api/runner.rb +++ b/lib/api/runner.rb @@ -45,6 +45,7 @@ module API end delete '/' do authenticate_runner! + status 204 Ci::Runner.find_by_token(params[:token]).destroy end diff --git a/lib/api/runners.rb b/lib/api/runners.rb index db6c7c59092..5bf5a18e42f 100644 --- a/lib/api/runners.rb +++ b/lib/api/runners.rb @@ -79,6 +79,7 @@ module API runner = get_runner(params[:id]) authenticate_delete_runner!(runner) + status 204 runner.destroy! end end @@ -134,6 +135,7 @@ module API runner = runner_project.runner forbidden!("Only one project associated with the runner. Please remove the runner instead") if runner.projects.count == 1 + status 204 runner_project.destroy end end diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb index fd634037a77..35ece56c65c 100644 --- a/lib/api/snippets.rb +++ b/lib/api/snippets.rb @@ -123,6 +123,7 @@ module API authorize! :destroy_personal_snippet, snippet + status 204 snippet.destroy end diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb index ed7b23b474a..c0179037440 100644 --- a/lib/api/system_hooks.rb +++ b/lib/api/system_hooks.rb @@ -66,6 +66,7 @@ module API hook = SystemHook.find_by(id: params[:id]) not_found!('System hook') unless hook + status 204 hook.destroy end end diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb index a9f2ca2608e..cb0619105e1 100644 --- a/lib/api/triggers.rb +++ b/lib/api/triggers.rb @@ -142,6 +142,7 @@ module API trigger = user_project.triggers.find(params.delete(:trigger_id)) return not_found!('Trigger') unless trigger + status 204 trigger.destroy end end diff --git a/lib/api/users.rb b/lib/api/users.rb index 81c68ea2658..a590f2692a2 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -235,6 +235,7 @@ module API key = user.keys.find_by(id: params[:key_id]) not_found!('Key') unless key + status 204 key.destroy end @@ -306,6 +307,7 @@ module API user = User.find_by(id: params[:id]) not_found!('User') unless user + status 204 user.delete_async(deleted_by: current_user, params: params) end @@ -406,6 +408,7 @@ module API requires :impersonation_token_id, type: Integer, desc: 'The ID of the impersonation token' end delete ':impersonation_token_id' do + status 204 find_impersonation_token.revoke! end end @@ -483,6 +486,7 @@ module API key = current_user.keys.find_by(id: params[:key_id]) not_found!('Key') unless key + status 204 key.destroy end @@ -534,6 +538,7 @@ module API email = current_user.emails.find_by(id: params[:email_id]) not_found!('Email') unless email + status 204 Emails::DestroyService.new(current_user, email: email.email).execute end diff --git a/lib/api/variables.rb b/lib/api/variables.rb index 7fa528fb2d3..7c0fdd3d1be 100644 --- a/lib/api/variables.rb +++ b/lib/api/variables.rb @@ -88,6 +88,7 @@ module API variable = user_project.variables.find_by(key: params[:key]) not_found!('Variable') unless variable + status 204 variable.destroy end end diff --git a/lib/ci/api/entities.rb b/lib/ci/api/entities.rb index 6b82b2b4f13..31f66dd5a58 100644 --- a/lib/ci/api/entities.rb +++ b/lib/ci/api/entities.rb @@ -52,7 +52,7 @@ module Ci # when old API will be removed (planned for August 2017). model.options.dup.tap do |options| options[:image] = options[:image][:name] if options[:image].is_a?(Hash) - options[:services].map! do |service| + options[:services]&.map! do |service| if service.is_a?(Hash) service[:name] else diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index cf3a0336792..3a4911b23b0 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -83,7 +83,8 @@ module Ci before_script: job[:before_script], script: job[:script], after_script: job[:after_script], - environment: job[:environment] + environment: job[:environment], + retry: job[:retry] }.compact } end diff --git a/lib/gitlab/badge/build/metadata.rb b/lib/gitlab/badge/pipeline/metadata.rb index 2ee35a0d4c1..db1e9f8cfb8 100644 --- a/lib/gitlab/badge/build/metadata.rb +++ b/lib/gitlab/badge/pipeline/metadata.rb @@ -1,8 +1,8 @@ module Gitlab module Badge - module Build + module Pipeline ## - # Class that describes build badge metadata + # Class that describes pipeline badge metadata # class Metadata < Badge::Metadata def initialize(badge) @@ -11,11 +11,11 @@ module Gitlab end def title - 'build status' + 'pipeline status' end def image_url - build_project_badges_url(@project, @ref, format: :svg) + pipeline_project_badges_url(@project, @ref, format: :svg) end def link_url diff --git a/lib/gitlab/badge/build/status.rb b/lib/gitlab/badge/pipeline/status.rb index b762d85b6e5..5fee7a93475 100644 --- a/lib/gitlab/badge/build/status.rb +++ b/lib/gitlab/badge/pipeline/status.rb @@ -1,8 +1,8 @@ module Gitlab module Badge - module Build + module Pipeline ## - # Build status badge + # Pipeline status badge # class Status < Badge::Base attr_reader :project, :ref @@ -15,7 +15,7 @@ module Gitlab end def entity - 'build' + 'pipeline' end def status @@ -25,11 +25,11 @@ module Gitlab end def metadata - @metadata ||= Build::Metadata.new(self) + @metadata ||= Pipeline::Metadata.new(self) end def template - @template ||= Build::Template.new(self) + @template ||= Pipeline::Template.new(self) end end end diff --git a/lib/gitlab/badge/build/template.rb b/lib/gitlab/badge/pipeline/template.rb index bc0e0cd441d..e09db32262d 100644 --- a/lib/gitlab/badge/build/template.rb +++ b/lib/gitlab/badge/pipeline/template.rb @@ -1,12 +1,13 @@ module Gitlab module Badge - module Build + module Pipeline ## - # Class that represents a build badge template. + # Class that represents a pipeline badge template. # # Template object will be passed to badge.svg.erb template. # class Template < Badge::Template + STATUS_RENAME = { 'success' => 'passed' }.freeze STATUS_COLOR = { success: '#4c1', failed: '#e05d44', @@ -27,11 +28,11 @@ module Gitlab end def value_text - @status.to_s + STATUS_RENAME[@status.to_s] || @status.to_s end def key_width - 38 + 62 end def value_width diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb index 176301bcca1..32f5c6ab142 100644 --- a/lib/gitlab/ci/config/entry/job.rb +++ b/lib/gitlab/ci/config/entry/job.rb @@ -11,7 +11,7 @@ module Gitlab ALLOWED_KEYS = %i[tags script only except type image services allow_failure type stage when artifacts cache dependencies before_script - after_script variables environment coverage].freeze + after_script variables environment coverage retry].freeze validations do validates :config, allowed_keys: ALLOWED_KEYS @@ -23,6 +23,9 @@ module Gitlab with_options allow_nil: true do validates :tags, array_of_strings: true validates :allow_failure, boolean: true + validates :retry, numericality: { only_integer: true, + greater_than_or_equal_to: 0, + less_than_or_equal_to: 2 } validates :when, inclusion: { in: %w[on_success on_failure always manual], message: 'should be on_success, on_failure, ' \ @@ -76,9 +79,9 @@ module Gitlab helpers :before_script, :script, :stage, :type, :after_script, :cache, :image, :services, :only, :except, :variables, - :artifacts, :commands, :environment, :coverage + :artifacts, :commands, :environment, :coverage, :retry - attributes :script, :tags, :allow_failure, :when, :dependencies + attributes :script, :tags, :allow_failure, :when, :dependencies, :retry def compose!(deps = nil) super do @@ -142,6 +145,7 @@ module Gitlab environment: environment_defined? ? environment_value : nil, environment_name: environment_defined? ? environment_value[:name] : nil, coverage: coverage_defined? ? coverage_value : nil, + retry: retry_defined? ? retry_value.to_i : nil, artifacts: artifacts_value, after_script: after_script_value, ignore: ignored? } diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb index 5d6977106d6..8503ecf8700 100644 --- a/lib/gitlab/ci/trace/stream.rb +++ b/lib/gitlab/ci/trace/stream.rb @@ -67,13 +67,14 @@ module Gitlab def extract_coverage(regex) return unless valid? - return unless regex + return unless regex.present? regex = Gitlab::UntrustedRegexp.new(regex) match = "" reverse_line do |line| + line.chomp! matches = regex.scan(line) next unless matches.is_a?(Array) next if matches.empty? diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb index e81d19a7a2e..8c8729b6557 100644 --- a/lib/gitlab/data_builder/push.rb +++ b/lib/gitlab/data_builder/push.rb @@ -74,6 +74,8 @@ module Gitlab build(project, user, commits.last&.id, commits.first&.id, ref, commits) end + private + def checkout_sha(repository, newrev, ref) # Checkout sha is nil when we remove branch or tag return if Gitlab::Git.blank_ref?(newrev) diff --git a/lib/gitlab/data_builder/wiki_page.rb b/lib/gitlab/data_builder/wiki_page.rb new file mode 100644 index 00000000000..226974b698c --- /dev/null +++ b/lib/gitlab/data_builder/wiki_page.rb @@ -0,0 +1,22 @@ +module Gitlab + module DataBuilder + module WikiPage + extend self + + def build(wiki_page, user, action) + wiki = wiki_page.wiki + + { + object_kind: wiki_page.class.name.underscore, + user: user.hook_attrs, + project: wiki.project.hook_attrs, + wiki: wiki.hook_attrs, + object_attributes: wiki_page.hook_attrs.merge( + url: Gitlab::UrlBuilder.build(wiki_page), + action: action + ) + } + end + end + end +end diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb index edd7795eef0..85e6db0a689 100644 --- a/lib/gitlab/ee_compat_check.rb +++ b/lib/gitlab/ee_compat_check.rb @@ -237,6 +237,10 @@ module Gitlab branch_name.parameterize << '.patch' end + def patch_url + "https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/#{ENV['CI_JOB_ID']}/artifacts/raw/ee_compat_check/patches/#{ce_patch_name}" + end + def step(desc, cmd = nil) puts "\n=> #{desc}\n" @@ -303,14 +307,11 @@ module Gitlab 2. Apply your branch's patch to EE - # In the CE repo - $ git fetch origin master - $ git diff --binary origin/master...HEAD -- > #{ce_branch}.patch - # In the EE repo $ git fetch origin master $ git checkout -b #{ee_branch_prefix} origin/master - $ git apply --3way path/to/#{ce_branch}.patch + $ wget #{patch_url} + $ git apply --3way #{ce_patch_name} At this point you might have conflicts such as: @@ -324,7 +325,7 @@ module Gitlab If the patch couldn't be applied cleanly, use the following command: # In the EE repo - $ git apply --reject path/to/#{ce_branch}.patch + $ git apply --reject #{ce_patch_name} This option makes git apply the parts of the patch that are applicable, and leave the rejected hunks in corresponding `.rej` files. diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb index 76a562f356e..09511cc6504 100644 --- a/lib/gitlab/git/commit.rb +++ b/lib/gitlab/git/commit.rb @@ -98,17 +98,13 @@ module Gitlab # Commit.between(repo, '29eda46b', 'master') # def between(repo, base, head) - commits = Gitlab::GitalyClient.migrate(:commits_between) do |is_enabled| + Gitlab::GitalyClient.migrate(:commits_between) do |is_enabled| if is_enabled repo.gitaly_commit_client.between(base, head) else - repo.commits_between(base, head) + repo.commits_between(base, head).map { |c| decorate(c) } end end - - commits.map do |commit| - decorate(commit) - end rescue Rugged::ReferenceError [] end @@ -135,6 +131,16 @@ module Gitlab # # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/326 def find_all(repo, options = {}) + Gitlab::GitalyClient.migrate(:find_all_commits) do |is_enabled| + if is_enabled + find_all_by_gitaly(repo, options) + else + find_all_by_rugged(repo, options) + end + end + end + + def find_all_by_rugged(repo, options = {}) actual_options = options.dup allowed_options = [:ref, :max_count, :skip, :order] @@ -173,6 +179,10 @@ module Gitlab [] end + def find_all_by_gitaly(repo, options = {}) + Gitlab::GitalyClient::CommitService.new(repo).find_all_commits(options) + end + def decorate(commit, ref = nil) Gitlab::Git::Commit.new(commit, ref) end @@ -214,11 +224,12 @@ module Gitlab def initialize(raw_commit, head = nil) raise "Nil as raw commit passed" unless raw_commit - if raw_commit.is_a?(Hash) + case raw_commit + when Hash init_from_hash(raw_commit) - elsif raw_commit.is_a?(Rugged::Commit) + when Rugged::Commit init_from_rugged(raw_commit) - elsif raw_commit.is_a?(Gitaly::GitCommit) + when Gitlab::GitalyClient::Commit init_from_gitaly(raw_commit) else raise "Invalid raw commit type: #{raw_commit.class}" @@ -298,7 +309,14 @@ module Gitlab end def parents - raw_commit.parents.map { |c| Gitlab::Git::Commit.new(c) } + case raw_commit + when Rugged::Commit + raw_commit.parents.map { |c| Gitlab::Git::Commit.new(c) } + when Gitlab::GitalyClient::Commit + parent_ids.map { |oid| self.class.find(raw_commit.repository, oid) }.compact + else + raise NotImplementedError, "commit source doesn't support #parents" + end end def stats diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb index cf95f673667..9e00abefd02 100644 --- a/lib/gitlab/git/diff.rb +++ b/lib/gitlab/git/diff.rb @@ -234,6 +234,8 @@ module Gitlab @new_file = diff.from_id == BLANK_SHA @renamed_file = diff.from_path != diff.to_path @deleted_file = diff.to_id == BLANK_SHA + + collapse! if diff.respond_to?(:collapsed) && diff.collapsed end def prune_diff_if_eligible diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb index 0d8fe185ac5..87ed9c3ea26 100644 --- a/lib/gitlab/git/diff_collection.rb +++ b/lib/gitlab/git/diff_collection.rb @@ -7,16 +7,28 @@ module Gitlab DEFAULT_LIMITS = { max_files: 100, max_lines: 5000 }.freeze + attr_reader :limits + + delegate :max_files, :max_lines, :max_bytes, :safe_max_files, :safe_max_lines, :safe_max_bytes, to: :limits + + def self.collection_limits(options = {}) + limits = {} + limits[:max_files] = options.fetch(:max_files, DEFAULT_LIMITS[:max_files]) + limits[:max_lines] = options.fetch(:max_lines, DEFAULT_LIMITS[:max_lines]) + limits[:max_bytes] = limits[:max_files] * 5.kilobytes # Average 5 KB per file + limits[:safe_max_files] = [limits[:max_files], DEFAULT_LIMITS[:max_files]].min + limits[:safe_max_lines] = [limits[:max_lines], DEFAULT_LIMITS[:max_lines]].min + limits[:safe_max_bytes] = limits[:safe_max_files] * 5.kilobytes # Average 5 KB per file + + OpenStruct.new(limits) + end + def initialize(iterator, options = {}) @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 * 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 * 5.kilobytes # Average 5 KB per file + @limits = self.class.collection_limits(options) @enforce_limits = !!options.fetch(:limits, true) @expanded = !!options.fetch(:expanded, true) + @from_gitaly = options.fetch(:from_gitaly, false) @line_count = 0 @byte_count = 0 @@ -26,9 +38,23 @@ module Gitlab end def each(&block) - Gitlab::GitalyClient.migrate(:commit_raw_diffs) do - each_patch(&block) + @array.each(&block) + + return if @overflow + return if @iterator.nil? + + Gitlab::GitalyClient.migrate(:commit_raw_diffs) do |is_enabled| + if is_enabled && @from_gitaly + each_gitaly_patch(&block) + else + each_rugged_patch(&block) + end end + + @populated = true + + # Allow iterator to be garbage-collected. It cannot be reused anyway. + @iterator = nil end def empty? @@ -74,23 +100,32 @@ module Gitlab end def over_safe_limits?(files) - files >= @safe_max_files || @line_count > @safe_max_lines || @byte_count >= @safe_max_bytes + files >= safe_max_files || @line_count > safe_max_lines || @byte_count >= safe_max_bytes end - def each_patch - i = 0 - @array.each do |diff| - yield diff + def each_gitaly_patch + i = @array.length + + @iterator.each do |raw| + diff = Gitlab::Git::Diff.new(raw, expanded: !@enforce_limits || @expanded) + + if raw.overflow_marker + @overflow = true + break + end + + yield @array[i] = diff i += 1 end + end - return if @overflow - return if @iterator.nil? + def each_rugged_patch + i = @array.length @iterator.each do |raw| @empty = false - if @enforce_limits && i >= @max_files + if @enforce_limits && i >= max_files @overflow = true break end @@ -106,7 +141,7 @@ module Gitlab @line_count += diff.line_count @byte_count += diff.diff.bytesize - if @enforce_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 @@ -116,11 +151,6 @@ module Gitlab 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 diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb index 8122ff0e81f..8e959c57c7c 100644 --- a/lib/gitlab/git/tree.rb +++ b/lib/gitlab/git/tree.rb @@ -17,30 +17,13 @@ module Gitlab def where(repository, sha, path = nil) path = nil if path == '' || path == '/' - commit = repository.lookup(sha) - root_tree = commit.tree - - tree = if path - id = find_id_by_path(repository, root_tree.oid, path) - if id - repository.lookup(id) - else - [] - end - else - root_tree - end - - tree.map do |entry| - new( - id: entry[:oid], - root_id: root_tree.oid, - name: entry[:name], - type: entry[:type], - mode: entry[:filemode].to_s(8), - path: path ? File.join(path, entry[:name]) : entry[:name], - commit_id: sha - ) + Gitlab::GitalyClient.migrate(:tree_entries) do |is_enabled| + if is_enabled + client = Gitlab::GitalyClient::CommitService.new(repository) + client.tree_entries(repository, sha, path) + else + tree_entries_from_rugged(repository, sha, path) + end end end @@ -74,6 +57,34 @@ module Gitlab entry[:oid] end end + + def tree_entries_from_rugged(repository, sha, path) + commit = repository.lookup(sha) + root_tree = commit.tree + + tree = if path + id = find_id_by_path(repository, root_tree.oid, path) + if id + repository.lookup(id) + else + [] + end + else + root_tree + end + + tree.map do |entry| + new( + id: entry[:oid], + root_id: root_tree.oid, + name: entry[:name], + type: entry[:type], + mode: entry[:filemode].to_s(8), + path: path ? File.join(path, entry[:name]) : entry[:name], + commit_id: sha + ) + end + end end def initialize(options) diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index 197a94487eb..435e41e36fb 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -86,8 +86,8 @@ module Gitlab feature.enabled? end - def self.migrate(feature) - is_enabled = feature_enabled?(feature) + def self.migrate(feature, status: MigrationStatus::OPT_IN) + is_enabled = feature_enabled?(feature, status: status) metric_name = feature.to_s metric_name += "_gitaly" if is_enabled diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb new file mode 100644 index 00000000000..61fe462d762 --- /dev/null +++ b/lib/gitlab/gitaly_client/commit.rb @@ -0,0 +1,14 @@ +module Gitlab + module GitalyClient + class Commit + attr_reader :repository, :gitaly_commit + + delegate :id, :subject, :body, :author, :committer, :parent_ids, to: :gitaly_commit + + def initialize(repository, gitaly_commit) + @repository = repository + @gitaly_commit = gitaly_commit + end + end + end +end diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb index 8f5738fed06..c6e52b530b3 100644 --- a/lib/gitlab/gitaly_client/commit_service.rb +++ b/lib/gitlab/gitaly_client/commit_service.rb @@ -23,9 +23,13 @@ module Gitlab 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) + request_params[:enforce_limits] = options.fetch(:limits, true) + request_params[:collapse_diffs] = request_params[:enforce_limits] || !options.fetch(:expanded, true) + request_params.merge!(Gitlab::Git::DiffCollection.collection_limits(options).to_h) + request = Gitaly::CommitDiffRequest.new(request_params) response = GitalyClient.call(@repository.storage, :diff_service, :commit_diff, request) - Gitlab::Git::DiffCollection.new(GitalyClient::DiffStitcher.new(response), options) + Gitlab::Git::DiffCollection.new(GitalyClient::DiffStitcher.new(response), options.merge(from_gitaly: true)) end def commit_deltas(commit) @@ -56,6 +60,31 @@ module Gitlab entry end + def tree_entries(repository, revision, path) + request = Gitaly::GetTreeEntriesRequest.new( + repository: @gitaly_repo, + revision: revision, + path: path.presence || '.' + ) + + response = GitalyClient.call(@repository.storage, :commit_service, :get_tree_entries, request) + + response.flat_map do |message| + message.entries.map do |gitaly_tree_entry| + entry_path = gitaly_tree_entry.path.dup + Gitlab::Git::Tree.new( + id: gitaly_tree_entry.oid, + root_id: gitaly_tree_entry.root_oid, + type: gitaly_tree_entry.type.downcase, + mode: gitaly_tree_entry.mode.to_s(8), + name: File.basename(entry_path), + path: entry_path, + commit_id: gitaly_tree_entry.commit_oid + ) + end + end + end + def commit_count(ref) request = Gitaly::CountCommitsRequest.new( repository: @gitaly_repo, @@ -76,6 +105,19 @@ module Gitlab consume_commits_response(response) end + def find_all_commits(opts = {}) + request = Gitaly::FindAllCommitsRequest.new( + repository: @gitaly_repo, + revision: opts[:ref].to_s, + max_count: opts[:max_count].to_i, + skip: opts[:skip].to_i + ) + request.order = opts[:order].upcase if opts[:order].present? + + response = GitalyClient.call(@repository.storage, :commit_service, :find_all_commits, request) + consume_commits_response(response) + end + private def commit_diff_request_params(commit, options = {}) @@ -90,7 +132,12 @@ module Gitlab end def consume_commits_response(response) - response.flat_map { |r| r.commits } + response.flat_map do |message| + message.commits.map do |gitaly_commit| + commit = GitalyClient::Commit.new(@repository, gitaly_commit) + Gitlab::Git::Commit.new(commit) + end + end end end end diff --git a/lib/gitlab/gitaly_client/diff.rb b/lib/gitlab/gitaly_client/diff.rb index 1e117b7e74a..d459c9a88fb 100644 --- a/lib/gitlab/gitaly_client/diff.rb +++ b/lib/gitlab/gitaly_client/diff.rb @@ -1,7 +1,7 @@ module Gitlab module GitalyClient class Diff - FIELDS = %i(from_path to_path old_mode new_mode from_id to_id patch).freeze + FIELDS = %i(from_path to_path old_mode new_mode from_id to_id patch overflow_marker collapsed).freeze attr_accessor(*FIELDS) diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb index a1b896c9511..cc282d1415b 100644 --- a/lib/gitlab/i18n.rb +++ b/lib/gitlab/i18n.rb @@ -7,10 +7,10 @@ module Gitlab 'es' => 'Español', 'de' => 'Deutsch', 'fr' => 'Français', - 'pt_BR' => 'Português(Brasil)', + 'pt_BR' => 'Português (Brasil)', 'zh_CN' => '简体中文', - 'zh_HK' => '繁體中文(香港)', - 'zh_TW' => '繁體中文(臺灣)', + 'zh_HK' => '繁體中文 (香港)', + 'zh_TW' => '繁體中文 (臺灣)', 'bg' => 'български', 'ru' => 'Русский', 'eo' => 'Esperanto', diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb index c1ee20b6977..1adc5ec952a 100644 --- a/lib/gitlab/regex.rb +++ b/lib/gitlab/regex.rb @@ -19,17 +19,23 @@ module Gitlab "It must start with letter, digit, emoji or '_'." end - def container_registry_reference_regex - Gitlab::PathRegex.git_reference_regex - end - ## - # Docker Distribution Registry 2.4.1 repository name rules + # Docker Distribution Registry repository / tag name rules + # + # See https://github.com/docker/distribution/blob/master/reference/regexp.go. # def container_repository_name_regex @container_repository_regex ||= %r{\A[a-z0-9]+(?:[-._/][a-z0-9]+)*\Z} end + ## + # We do not use regexp anchors here because these are not allowed when + # used as a routing constraint. + # + def container_registry_tag_regex + @container_registry_tag_regex ||= /[\w][\w.-]{0,127}/ + end + def environment_name_regex_chars 'a-zA-Z0-9_/\\$\\{\\}\\. -' end diff --git a/lib/gitlab/untrusted_regexp.rb b/lib/gitlab/untrusted_regexp.rb index 8b43f0053d6..187a9e1145f 100644 --- a/lib/gitlab/untrusted_regexp.rb +++ b/lib/gitlab/untrusted_regexp.rb @@ -22,13 +22,33 @@ module Gitlab end def scan(text) - scan_regexp.scan(text).map do |match| - if regexp.number_of_capturing_groups == 0 - match.first - else - match - end + text = text.dup # modified in-place + results = [] + + loop do + match = scan_regexp.match(text) + break unless match + + # Ruby scan returns empty strings, not nil + groups = match.to_a.map(&:to_s) + + results << + if regexp.number_of_capturing_groups.zero? + groups[0] + else + groups[1..-1] + end + + matchsize = match.end(0) + + # No further matches + break unless matchsize.present? + + text.slice!(0, matchsize) + break unless text.present? end + + results end def replace(text, rewrite) @@ -43,7 +63,7 @@ module Gitlab # groups, so work around it def scan_regexp @scan_regexp ||= - if regexp.number_of_capturing_groups == 0 + if regexp.number_of_capturing_groups.zero? RE2::Regexp.new('(' + regexp.source + ')') else regexp diff --git a/lib/tasks/gitlab/task_helpers.rb b/lib/tasks/gitlab/task_helpers.rb index 964aa0fe1bc..28b2d86eed2 100644 --- a/lib/tasks/gitlab/task_helpers.rb +++ b/lib/tasks/gitlab/task_helpers.rb @@ -153,7 +153,6 @@ module Gitlab clone_repo(repo, target_dir) unless Dir.exist?(target_dir) checkout_version(version, target_dir) - reset_to_version(version, target_dir) end def clone_repo(repo, target_dir) @@ -161,12 +160,8 @@ module Gitlab end def checkout_version(version, target_dir) - run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch --quiet]) - run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} checkout --quiet #{version}]) - end - - def reset_to_version(version, target_dir) - run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} reset --hard #{version}]) + run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch --quiet origin #{version}]) + run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} checkout -f --quiet FETCH_HEAD --]) end end end |