diff options
-rw-r--r-- | app/models/repository.rb | 67 | ||||
-rw-r--r-- | app/services/files/multi_service.rb | 15 | ||||
-rw-r--r-- | db/fixtures/development/22_labeled_issues_seed.rb | 112 | ||||
-rw-r--r-- | lib/gitlab/git/index.rb | 12 | ||||
-rw-r--r-- | lib/gitlab/git/repository.rb | 36 | ||||
-rw-r--r-- | spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb | 32 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 46 | ||||
-rw-r--r-- | spec/services/files/multi_service_spec.rb | 4 |
8 files changed, 86 insertions, 238 deletions
diff --git a/app/models/repository.rb b/app/models/repository.rb index 7b8f5794a87..9c879e2006b 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -783,34 +783,30 @@ class Repository end def create_dir(user, path, **options) - options[:user] = user options[:actions] = [{ action: :create_dir, file_path: path }] - multi_action(**options) + multi_action(user, **options) end def create_file(user, path, content, **options) - options[:user] = user options[:actions] = [{ action: :create, file_path: path, content: content }] - multi_action(**options) + multi_action(user, **options) end def update_file(user, path, content, **options) previous_path = options.delete(:previous_path) action = previous_path && previous_path != path ? :move : :update - options[:user] = user options[:actions] = [{ action: action, file_path: path, previous_path: previous_path, content: content }] - multi_action(**options) + multi_action(user, **options) end def delete_file(user, path, **options) - options[:user] = user options[:actions] = [{ action: :delete, file_path: path }] - multi_action(**options) + multi_action(user, **options) end def with_cache_hooks @@ -824,59 +820,14 @@ class Repository result.newrev end - def with_branch(user, *args) - with_cache_hooks do - Gitlab::Git::OperationService.new(user, raw_repository).with_branch(*args) do |start_commit| - yield start_commit - end - end - end - - # rubocop:disable Metrics/ParameterLists - def multi_action( - user:, branch_name:, message:, actions:, - author_email: nil, author_name: nil, - start_branch_name: nil, start_project: project) - - with_branch( - user, - branch_name, - start_branch_name: start_branch_name, - start_repository: start_project.repository.raw_repository) do |start_commit| - - index = Gitlab::Git::Index.new(raw_repository) - - if start_commit - index.read_tree(start_commit.rugged_commit.tree) - parents = [start_commit.sha] - else - parents = [] - end + def multi_action(user, **options) + start_project = options.delete(:start_project) - actions.each do |options| - index.public_send(options.delete(:action), options) # rubocop:disable GitlabSecurity/PublicSend - end - - options = { - tree: index.write_tree, - message: message, - parents: parents - } - options.merge!(get_committer_and_author(user, email: author_email, name: author_name)) - - create_commit(options) + if start_project + options[:start_repository] = start_project.repository.raw_repository end - end - # rubocop:enable Metrics/ParameterLists - def get_committer_and_author(user, email: nil, name: nil) - committer = user_to_committer(user) - author = Gitlab::Git.committer_hash(email: email, name: name) || committer - - { - author: author, - committer: committer - } + with_cache_hooks { raw.multi_action(user, **options) } end def can_be_merged?(source_sha, target_branch) diff --git a/app/services/files/multi_service.rb b/app/services/files/multi_service.rb index 98a3e83c130..a03c59f569d 100644 --- a/app/services/files/multi_service.rb +++ b/app/services/files/multi_service.rb @@ -4,7 +4,7 @@ module Files def create_commit! repository.multi_action( - user: current_user, + current_user, message: @commit_message, branch_name: @branch_name, actions: params[:actions], @@ -13,6 +13,8 @@ module Files start_project: @start_project, start_branch_name: @start_branch ) + rescue ArgumentError => e + raise_error(e) end private @@ -20,16 +22,7 @@ module Files def validate! super - params[:actions].each do |action| - validate_action!(action) - validate_file_status!(action) - end - end - - def validate_action!(action) - unless Gitlab::Git::Index::ACTIONS.include?(action[:action].to_s) - raise_error("Unknown action '#{action[:action]}'") - end + params[:actions].each { |action| validate_file_status!(action) } end def validate_file_status!(action) diff --git a/db/fixtures/development/22_labeled_issues_seed.rb b/db/fixtures/development/22_labeled_issues_seed.rb deleted file mode 100644 index 3e4485c7a73..00000000000 --- a/db/fixtures/development/22_labeled_issues_seed.rb +++ /dev/null @@ -1,112 +0,0 @@ -# Creates a project with labeled issues for a user. -# Run this single seed file using: rake db:seed_fu FILTER=labeled USER_ID=74. -# If an USER_ID is not provided it will use the last created user. -require './spec/support/sidekiq' - -class Gitlab::Seeder::LabeledIssues - include ::Gitlab::Utils - - def initialize(user) - @user = user - end - - def seed! - Sidekiq::Testing.inline! do - group = create_group - puts '.' - - create_projects(group) - puts '.' - - create_labels(group) - puts '.' - - create_issues(group) - puts '.' - end - - print '.' - end - - private - - def create_group - group_name = "group_of_#{@user.name}#{SecureRandom.hex(4)}" - - group = Group.new( - name: group_name, - path: group_name, - description: FFaker::Lorem.sentence - ) - - group.save - - group.add_owner(@user) - - group - end - - def create_projects(group) - 5.times do - project_name = "project_#{SecureRandom.hex(6)}" - params = { - namespace_id: group.id, - name: project_name, - description: FFaker::Lorem.sentence, - visibility_level: Gitlab::VisibilityLevel.values.sample - } - - Projects::CreateService.new(@user, params).execute - end - end - - def create_labels(group) - group.projects.each do |project| - 5.times do - label_title = FFaker::Vehicle.model - Labels::CreateService.new(title: label_title).execute(project: project) - end - end - - 10.times do - label_title = FFaker::Product.brand - Labels::CreateService.new(title: label_title).execute(group: group) - end - end - - def create_issues(group) - # Get only group labels - group_labels = - LabelsFinder.new(@user, group_id: group.id).execute.where.not(group_id: nil) - - group.projects.each do |project| - label_ids = project.labels.pluck(:id).sample(5) - label_ids.push(*group.labels.sample(4)) - - 50.times do - issue_params = { - title: FFaker::Lorem.sentence(6), - description: FFaker::Lorem.sentence, - state: 'opened', - label_ids: label_ids - - } - - Issues::CreateService.new(project, @user, issue_params).execute if project.project_feature.present? - end - end - end -end - -Gitlab::Seeder.quiet do - user_id = ENV['USER_ID'] - - user = - if user_id.present? - User.find(user_id) - else - User.last - end - - Gitlab::Seeder::LabeledIssues.new(user).seed! -end diff --git a/lib/gitlab/git/index.rb b/lib/gitlab/git/index.rb index db532600d1b..d94082a3e30 100644 --- a/lib/gitlab/git/index.rb +++ b/lib/gitlab/git/index.rb @@ -10,6 +10,7 @@ module Gitlab DEFAULT_MODE = 0o100644 ACTIONS = %w(create create_dir update move delete).freeze + ACTION_OPTIONS = %i(file_path previous_path content encoding).freeze attr_reader :repository, :raw_index @@ -20,6 +21,11 @@ module Gitlab delegate :read_tree, :get, to: :raw_index + def apply(action, options) + validate_action!(action) + public_send(action, options.slice(*ACTION_OPTIONS)) # rubocop:disable GitlabSecurity/PublicSend + end + def write_tree raw_index.write_tree(repository.rugged) end @@ -140,6 +146,12 @@ module Gitlab rescue Rugged::IndexError => e raise IndexError, e.message end + + def validate_action!(action) + unless ACTIONS.include?(action.to_s) + raise ArgumentError, "Unknown action '#{action}'" + end + end end end end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index e8b1788e140..84105501d1e 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1300,6 +1300,42 @@ module Gitlab success || gitlab_projects_error end + # rubocop:disable Metrics/ParameterLists + def multi_action( + user, branch_name:, message:, actions:, + author_email: nil, author_name: nil, + start_branch_name: nil, start_repository: self) + + OperationService.new(user, self).with_branch( + branch_name, + start_branch_name: start_branch_name, + start_repository: start_repository + ) do |start_commit| + index = Gitlab::Git::Index.new(self) + parents = [] + + if start_commit + index.read_tree(start_commit.rugged_commit.tree) + parents = [start_commit.sha] + end + + actions.each { |opts| index.apply(opts.delete(:action), opts) } + + committer = user_to_committer(user) + author = Gitlab::Git.committer_hash(email: author_email, name: author_name) || committer + options = { + tree: index.write_tree, + message: message, + parents: parents, + author: author, + committer: committer + } + + create_commit(options) + end + end + # rubocop:enable Metrics/ParameterLists + def gitaly_repository Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository) end diff --git a/spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb b/spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb index 57ee2adaaff..c81ec887ded 100644 --- a/spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb +++ b/spec/migrations/migrate_gcp_clusters_to_new_clusters_architectures_spec.rb @@ -33,7 +33,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do let(:encrypted_gcp_token) { "'encrypted_gcp_token'" } let(:encrypted_gcp_token_iv) { "'encrypted_gcp_token_iv'" } - let(:cluster) { Clusters::Cluster.last } + let(:cluster) { described_class::Cluster.last } let(:cluster_id) { cluster.id } before do @@ -46,12 +46,12 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do it 'correctly migrate to new clusters architectures' do migrate! - expect(Clusters::Cluster.count).to eq(1) - expect(Clusters::Project.count).to eq(1) - expect(Clusters::Providers::Gcp.count).to eq(1) - expect(Clusters::Platforms::Kubernetes.count).to eq(1) + expect(described_class::Cluster.count).to eq(1) + expect(described_class::ClustersProject.count).to eq(1) + expect(described_class::ProvidersGcp.count).to eq(1) + expect(described_class::PlatformsKubernetes.count).to eq(1) - expect(cluster.user).to eq(user) + expect(cluster.user_id).to eq(user.id) expect(cluster.enabled).to be_truthy expect(cluster.name).to eq(gcp_cluster_name.delete!("'")) expect(cluster.provider_type).to eq('gcp') @@ -59,7 +59,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do expect(cluster.project_ids).to include(project.id) - expect(cluster.provider_gcp.cluster).to eq(cluster) + expect(cluster.provider_gcp.cluster_id).to eq(cluster.id) expect(cluster.provider_gcp.status).to eq(status) expect(cluster.provider_gcp.status_reason).to eq(tr(status_reason)) expect(cluster.provider_gcp.gcp_project_id).to eq(tr(gcp_project_id)) @@ -71,7 +71,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do expect(cluster.provider_gcp.encrypted_access_token).to eq(tr(encrypted_gcp_token)) expect(cluster.provider_gcp.encrypted_access_token_iv).to eq(tr(encrypted_gcp_token_iv)) - expect(cluster.platform_kubernetes.cluster).to eq(cluster) + expect(cluster.platform_kubernetes.cluster_id).to eq(cluster.id) expect(cluster.platform_kubernetes.api_url).to be_nil expect(cluster.platform_kubernetes.ca_cert).to be_nil expect(cluster.platform_kubernetes.namespace).to eq(tr(project_namespace)) @@ -109,7 +109,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do let(:encrypted_gcp_token) { "'encrypted_gcp_token'" } let(:encrypted_gcp_token_iv) { "'encrypted_gcp_token_iv'" } - let(:cluster) { Clusters::Cluster.last } + let(:cluster) { described_class::Cluster.last } let(:cluster_id) { cluster.id } before do @@ -122,12 +122,12 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do it 'correctly migrate to new clusters architectures' do migrate! - expect(Clusters::Cluster.count).to eq(1) - expect(Clusters::Project.count).to eq(1) - expect(Clusters::Providers::Gcp.count).to eq(1) - expect(Clusters::Platforms::Kubernetes.count).to eq(1) + expect(described_class::Cluster.count).to eq(1) + expect(described_class::ClustersProject.count).to eq(1) + expect(described_class::ProvidersGcp.count).to eq(1) + expect(described_class::PlatformsKubernetes.count).to eq(1) - expect(cluster.user).to eq(user) + expect(cluster.user_id).to eq(user.id) expect(cluster.enabled).to be_truthy expect(cluster.name).to eq(tr(gcp_cluster_name)) expect(cluster.provider_type).to eq('gcp') @@ -135,7 +135,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do expect(cluster.project_ids).to include(project.id) - expect(cluster.provider_gcp.cluster).to eq(cluster) + expect(cluster.provider_gcp.cluster_id).to eq(cluster.id) expect(cluster.provider_gcp.status).to eq(status) expect(cluster.provider_gcp.status_reason).to eq(tr(status_reason)) expect(cluster.provider_gcp.gcp_project_id).to eq(tr(gcp_project_id)) @@ -147,7 +147,7 @@ describe MigrateGcpClustersToNewClustersArchitectures, :migration do expect(cluster.provider_gcp.encrypted_access_token).to eq(tr(encrypted_gcp_token)) expect(cluster.provider_gcp.encrypted_access_token_iv).to eq(tr(encrypted_gcp_token_iv)) - expect(cluster.platform_kubernetes.cluster).to eq(cluster) + expect(cluster.platform_kubernetes.cluster_id).to eq(cluster.id) expect(cluster.platform_kubernetes.api_url).to eq('https://' + tr(endpoint)) expect(cluster.platform_kubernetes.ca_cert).to eq(tr(ca_cert)) expect(cluster.platform_kubernetes.namespace).to eq(tr(project_namespace)) diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 48a75c9885b..c0db2c1b386 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -582,38 +582,6 @@ describe Repository do end end - describe '#get_committer_and_author' do - it 'returns the committer and author data' do - options = repository.get_committer_and_author(user) - expect(options[:committer][:email]).to eq(user.email) - expect(options[:author][:email]).to eq(user.email) - end - - context 'when the email/name are given' do - it 'returns an object containing the email/name' do - options = repository.get_committer_and_author(user, email: author_email, name: author_name) - expect(options[:author][:email]).to eq(author_email) - expect(options[:author][:name]).to eq(author_name) - end - end - - context 'when the email is given but the name is not' do - it 'returns the committer as the author' do - options = repository.get_committer_and_author(user, email: author_email) - expect(options[:author][:email]).to eq(user.email) - expect(options[:author][:name]).to eq(user.name) - end - end - - context 'when the name is given but the email is not' do - it 'returns nil' do - options = repository.get_committer_and_author(user, name: author_name) - expect(options[:author][:email]).to eq(user.email) - expect(options[:author][:name]).to eq(user.name) - end - end - end - describe "search_files_by_content" do let(:results) { repository.search_files_by_content('feature', 'master') } subject { results } @@ -1112,16 +1080,16 @@ describe Repository do allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, '']) end - it 'expires branch cache' do - expect(repository).not_to receive(:expire_exists_cache) - expect(repository).not_to receive(:expire_root_ref_cache) - expect(repository).not_to receive(:expire_emptiness_caches) - expect(repository).to receive(:expire_branches_cache) - - repository.with_branch(user, 'new-feature') do + subject do + Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch('new-feature') do new_rev end end + + it 'returns branch_created as true' do + expect(subject).not_to be_repo_created + expect(subject).to be_branch_created + end end context 'when repository is empty' do diff --git a/spec/services/files/multi_service_spec.rb b/spec/services/files/multi_service_spec.rb index 2b79609930c..b9971776b33 100644 --- a/spec/services/files/multi_service_spec.rb +++ b/spec/services/files/multi_service_spec.rb @@ -41,7 +41,7 @@ describe Files::MultiService do describe '#execute' do context 'with a valid action' do - it 'returns a hash with the :success status ' do + it 'returns a hash with the :success status' do results = subject.execute expect(results[:status]).to eq(:success) @@ -51,7 +51,7 @@ describe Files::MultiService do context 'with an invalid action' do let(:action) { 'rename' } - it 'returns a hash with the :error status ' do + it 'returns a hash with the :error status' do results = subject.execute expect(results[:status]).to eq(:error) |