summaryrefslogtreecommitdiff
path: root/app/services/projects/destroy_service.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/projects/destroy_service.rb')
-rw-r--r--app/services/projects/destroy_service.rb56
1 files changed, 50 insertions, 6 deletions
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index 4b8f955ae69..02769e72229 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -34,6 +34,8 @@ module Projects
system_hook_service.execute_hooks_for(project, :destroy)
log_info("Project \"#{project.full_path}\" was removed")
+ current_user.invalidate_personal_projects_count
+
true
rescue => error
attempt_rollback(project, error.message)
@@ -44,6 +46,20 @@ module Projects
raise
end
+ def attempt_repositories_rollback
+ return unless @project
+
+ flush_caches(@project)
+
+ unless rollback_repository(removal_path(repo_path), repo_path)
+ raise_error('Failed to restore project repository. Please contact the administrator.')
+ end
+
+ unless rollback_repository(removal_path(wiki_path), wiki_path)
+ raise_error('Failed to restore wiki repository. Please contact the administrator.')
+ end
+ end
+
private
def repo_path
@@ -69,22 +85,39 @@ module Projects
return true if params[:skip_repo] == true
# There is a possibility project does not have repository or wiki
- return true unless gitlab_shell.exists?(project.repository_storage_path, path + '.git')
+ return true unless repo_exists?(path)
new_path = removal_path(path)
- if gitlab_shell.mv_repository(project.repository_storage_path, path, new_path)
- log_info("Repository \"#{path}\" moved to \"#{new_path}\"")
+ if mv_repository(path, new_path)
+ log_info(%Q{Repository "#{path}" moved to "#{new_path}" for project "#{project.full_path}"})
project.run_after_commit do
# self is now project
- GitlabShellWorker.perform_in(5.minutes, :remove_repository, self.repository_storage_path, new_path)
+ GitlabShellWorker.perform_in(5.minutes, :remove_repository, self.repository_storage, new_path)
end
else
false
end
end
+ def rollback_repository(old_path, new_path)
+ # There is a possibility project does not have repository or wiki
+ return true unless repo_exists?(old_path)
+
+ mv_repository(old_path, new_path)
+ end
+
+ def repo_exists?(path)
+ gitlab_shell.exists?(project.repository_storage, path + '.git')
+ end
+
+ def mv_repository(from_path, to_path)
+ return true unless gitlab_shell.exists?(project.repository_storage, from_path + '.git')
+
+ gitlab_shell.mv_repository(project.repository_storage, from_path, to_path)
+ end
+
def attempt_rollback(project, message)
return unless project
@@ -102,13 +135,24 @@ module Projects
raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.')
end
+ log_destroy_event
trash_repositories!
- project.team.truncate
+ # Rails attempts to load all related records into memory before
+ # destroying: https://github.com/rails/rails/issues/22510
+ # This ensures we delete records in batches.
+ #
+ # Exclude container repositories because its before_destroy would be
+ # called multiple times, and it doesn't destroy any database records.
+ project.destroy_dependent_associations_in_batches(exclude: [:container_repositories])
project.destroy!
end
end
+ def log_destroy_event
+ log_info("Attempting to destroy #{project.full_path} (#{project.id})")
+ end
+
##
# This method makes sure that we correctly remove registry tags
# for legacy image repository (when repository path equals project path).
@@ -117,7 +161,7 @@ module Projects
return true unless Gitlab.config.registry.enabled
ContainerRepository.build_root_repository(project).tap do |repository|
- return repository.has_tags? ? repository.delete_tags! : true
+ break repository.has_tags? ? repository.delete_tags! : true
end
end