Commit e37a043d authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Get rid of skipping callbacks in production code. Dont trigger gitolite more...

Get rid of skipping callbacks in production code. Dont trigger gitolite more than once on import in group
parent 151ada76
...@@ -99,11 +99,10 @@ class ProjectsController < ProjectResourceController ...@@ -99,11 +99,10 @@ class ProjectsController < ProjectResourceController
def destroy def destroy
return access_denied! unless can?(current_user, :remove_project, project) return access_denied! unless can?(current_user, :remove_project, project)
# Disable the UsersProject update_repository call, otherwise it will be # Delete team first in order to prevent multiple gitolite calls
# called once for every person removed from the project project.truncate_team
UsersProject.skip_callback(:destroy, :after, :update_repository)
project.destroy project.destroy
UsersProject.set_callback(:destroy, :after, :update_repository)
respond_to do |format| respond_to do |format|
format.html { redirect_to root_path } format.html { redirect_to root_path }
......
...@@ -13,9 +13,11 @@ ...@@ -13,9 +13,11 @@
class Group < Namespace class Group < Namespace
def add_users_to_project_teams(user_ids, project_access) def add_users_to_project_teams(user_ids, project_access)
projects.each do |project| UsersProject.add_users_into_projects(
project.add_users_ids_to_team(user_ids, project_access) projects.map(&:id),
end user_ids,
project_access
)
end end
def users def users
......
...@@ -23,11 +23,13 @@ class UsersProject < ActiveRecord::Base ...@@ -23,11 +23,13 @@ class UsersProject < ActiveRecord::Base
belongs_to :user belongs_to :user
belongs_to :project belongs_to :project
after_save :update_repository attr_accessor :skip_git
after_destroy :update_repository
after_save :update_repository, unless: :skip_git?
after_destroy :update_repository, unless: :skip_git?
validates :user, presence: true validates :user, presence: true
validates :user_id, uniqueness: { :scope => [:project_id], message: "already exists in project" } validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true validates :project_access, inclusion: { in: [GUEST, REPORTER, DEVELOPER, MASTER] }, presence: true
validates :project, presence: true validates :project, presence: true
...@@ -36,76 +38,84 @@ class UsersProject < ActiveRecord::Base ...@@ -36,76 +38,84 @@ class UsersProject < ActiveRecord::Base
scope :in_project, ->(project) { where(project_id: project.id) } scope :in_project, ->(project) { where(project_id: project.id) }
class << self class << self
def import_team(source_project, target_project) def add_users_into_projects(project_ids, user_ids, project_access)
UsersProject.without_repository_callback do UsersProject.transaction do
UsersProject.transaction do project_ids.each do |project_id|
team = source_project.users_projects.all user_ids.each do |user_id|
users_project = UsersProject.new(project_access: project_access, user_id: user_id)
team.each do |tm| users_project.project_id = project_id
# Skip if user already present in team users_project.skip_git = true
next if target_project.users.include?(tm.user) users_project.save
new_tm = tm.dup
new_tm.id = nil
new_tm.project_id = target_project.id
new_tm.save
end end
end end
Gitlab::Gitolite.new.update_repositories(Project.where(id: project_ids))
end end
target_project.update_repository
true true
rescue rescue
false false
end end
def without_repository_callback def import_team(source_project, target_project)
UsersProject.skip_callback(:destroy, :after, :update_repository) source_team = source_project.users_projects.all
yield target_team = target_project.users_projects.all
UsersProject.set_callback(:destroy, :after, :update_repository) target_user_ids = target_team.map(&:user_id)
source_team.reject! do |tm|
# Skip if user already present in team
target_user_ids.include?(tm.user_id)
end
source_team.map! do |tm|
new_tm = tm.dup
new_tm.id = nil
new_tm.project_id = target_project.id
new_tm.skip_git = true
new_tm
end
UsersProject.transaction do
source_team.each do |tm|
tm.save
end
target_project.update_repository
end
true
rescue
false
end end
def bulk_delete(project, user_ids) def bulk_delete(project, user_ids)
UsersProject.transaction do UsersProject.transaction do
UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project| UsersProject.where(user_id: user_ids, project_id: project.id).each do |users_project|
users_project.skip_git = true
users_project.destroy users_project.destroy
end end
project.update_repository
end end
end end
def bulk_update(project, user_ids, project_access) def bulk_update(project, user_ids, project_access)
UsersProject.transaction do UsersProject.transaction do
UsersProject.where(:user_id => user_ids, :project_id => project.id).each do |users_project| UsersProject.where(user_id: user_ids, project_id: project.id).each do |users_project|
users_project.project_access = project_access users_project.project_access = project_access
users_project.skip_git = true
users_project.save users_project.save
end end
project.update_repository
end end
end end
# TODO: depreceate in future in favor of add_users_into_projects
def bulk_import(project, user_ids, project_access) def bulk_import(project, user_ids, project_access)
UsersProject.transaction do add_users_into_projects([project.id], user_ids, project_access)
user_ids.each do |user_id|
users_project = UsersProject.new(
project_access: project_access,
user_id: user_id
)
users_project.project = project
users_project.save
end
end
end end
# TODO: depreceate in future in favor of add_users_into_projects
def user_bulk_import(user, project_ids, project_access) def user_bulk_import(user, project_ids, project_access)
UsersProject.transaction do add_users_into_projects(project_ids, [user.id], project_access)
project_ids.each do |project_id|
users_project = UsersProject.new(
project_access: project_access,
)
users_project.project_id = project_id
users_project.user_id = user.id
users_project.save
end
end
end end
def access_roles def access_roles
...@@ -133,4 +143,8 @@ class UsersProject < ActiveRecord::Base ...@@ -133,4 +143,8 @@ class UsersProject < ActiveRecord::Base
def repo_access_human def repo_access_human
self.class.access_roles.invert[self.project_access] self.class.access_roles.invert[self.project_access]
end end
def skip_git?
!!@skip_git
end
end end
...@@ -34,19 +34,20 @@ module Team ...@@ -34,19 +34,20 @@ module Team
# with same access role by user ids # with same access role by user ids
def add_users_ids_to_team(users_ids, access_role) def add_users_ids_to_team(users_ids, access_role)
UsersProject.bulk_import(self, users_ids, access_role) UsersProject.bulk_import(self, users_ids, access_role)
self.update_repository
end end
# Update multiple project users # Update multiple project users
# to same access role by user ids # to same access role by user ids
def update_users_ids_to_role(users_ids, access_role) def update_users_ids_to_role(users_ids, access_role)
UsersProject.bulk_update(self, users_ids, access_role) UsersProject.bulk_update(self, users_ids, access_role)
self.update_repository
end end
# Delete multiple users from project by user ids # Delete multiple users from project by user ids
def delete_users_ids_from_team(users_ids) def delete_users_ids_from_team(users_ids)
UsersProject.bulk_delete(self, users_ids) UsersProject.bulk_delete(self, users_ids)
self.update_repository end
def truncate_team
UsersProject.bulk_delete(self, self.users.map(&:id))
end end
end end
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%h6 1. Choose people you want in the team %h6 1. Choose people you want in the team
.clearfix .clearfix
= f.label :user_ids, "People" = f.label :user_ids, "People"
.input= select_tag(:user_ids, options_from_collection_for_select(User.active, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true}) .input= select_tag(:user_ids, options_from_collection_for_select(User.active.order('name ASC'), :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true})
%h6 2. Set access level for them %h6 2. Set access level for them
.clearfix .clearfix
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%h6 1. Choose people you want in the team %h6 1. Choose people you want in the team
.clearfix .clearfix
= f.label :user_ids, "People" = f.label :user_ids, "People"
.input= select_tag(:user_ids, options_from_collection_for_select(User.not_in_project(@project).all, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true}) .input= select_tag(:user_ids, options_from_collection_for_select(User.not_in_project(@project).order('name').all, :id, :name), {data: {placeholder: "Select users"}, class: "chosen xxlarge", multiple: true})
%h6 2. Set access level for them %h6 2. Set access level for them
.clearfix .clearfix
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
%p.slead Choose project you want to use as team source: %p.slead Choose project you want to use as team source:
.padded .padded
= label_tag :source_project_id, "Project" = label_tag :source_project_id, "Project"
.input= select_tag(:source_project_id, options_from_collection_for_select(current_user.projects, :id, :name), prompt: "Select project", class: "chosen xxlarge", required: true) .input= select_tag(:source_project_id, options_from_collection_for_select(current_user.authorized_projects, :id, :name_with_namespace), prompt: "Select project", class: "chosen xxlarge", required: true)
.actions .actions
= submit_tag 'Import', class: "btn save-btn" = submit_tag 'Import', class: "btn save-btn"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment