Rename projects with reserved path names
We cant have project with name 'project' or 'tree' anymore. This merge request containts a migration that will find and rename all projects using reserved names by adding N digit to the end of the name. Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
This commit is contained in:
parent
79ce691d71
commit
d72b40423c
5 changed files with 128 additions and 3 deletions
|
@ -921,7 +921,7 @@ class Project < ActiveRecord::Base
|
|||
Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present"
|
||||
|
||||
# we currently doesn't support renaming repository if it contains tags in container registry
|
||||
raise Exception.new('Project cannot be renamed, because tags are present in its container registry')
|
||||
raise StandardError.new('Project cannot be renamed, because tags are present in its container registry')
|
||||
end
|
||||
|
||||
if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
|
||||
|
@ -948,7 +948,7 @@ class Project < ActiveRecord::Base
|
|||
|
||||
# if we cannot move namespace directory we should rollback
|
||||
# db changes in order to prevent out of sync between db and fs
|
||||
raise Exception.new('repository cannot be renamed')
|
||||
raise StandardError.new('repository cannot be renamed')
|
||||
end
|
||||
|
||||
Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Rename projects wth reserved names
|
||||
merge_request: 8234
|
||||
author:
|
|
@ -0,0 +1,76 @@
|
|||
class RenameReservedProjectNames < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
include Gitlab::ShellAdapter
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
class Project < ActiveRecord::Base; end
|
||||
|
||||
def up
|
||||
threads = reserved_projects.each_slice(100).map do |slice|
|
||||
Thread.new do
|
||||
rename_projects(slice)
|
||||
end
|
||||
end
|
||||
|
||||
threads.each(&:join)
|
||||
end
|
||||
|
||||
def down
|
||||
# nothing to do here
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def reserved_projects
|
||||
select_all("SELECT p.id, p.path, p.repository_storage, n.path AS namespace_path, n.id AS namespace_id FROM projects p
|
||||
INNER JOIN namespaces n ON n.id = p.namespace_id
|
||||
WHERE p.path IN (
|
||||
'.well-known', 'all', 'assets', 'files', 'groups', 'hooks', 'issues',
|
||||
'merge_requests', 'new', 'profile', 'projects', 'public', 'repository',
|
||||
'robots.txt', 's', 'snippets', 'teams', 'u', 'unsubscribes', 'users',
|
||||
'tree', 'commits', 'wikis', 'new', 'edit', 'create', 'update', 'logs_tree',
|
||||
'preview', 'blob', 'blame', 'raw', 'files', 'create_dir', 'find_file')")
|
||||
end
|
||||
|
||||
def route_exists?(full_path)
|
||||
select_all("SELECT id, path FROM routes WHERE path = '#{quote_string(full_path)}'").present?
|
||||
end
|
||||
|
||||
# Adds number to the end of the path that is not taken by other route
|
||||
def rename_path(namespace_path, path_was)
|
||||
counter = 0
|
||||
path = "#{path_was}#{counter}"
|
||||
|
||||
while route_exists?("#{namespace_path}/#{path}")
|
||||
counter += 1
|
||||
path = "#{path_was}#{counter}"
|
||||
end
|
||||
|
||||
path
|
||||
end
|
||||
|
||||
def rename_projects(projects)
|
||||
projects.each do |row|
|
||||
id = row['id']
|
||||
path_was = row['path']
|
||||
namespace_path = row['namespace_path']
|
||||
path = rename_path(namespace_path, path_was)
|
||||
project = Project.find_by(id: id)
|
||||
|
||||
begin
|
||||
# Because project path update is quite complex operation we can't safely
|
||||
# copy-paste all code from GitLab. As exception we use Rails code here
|
||||
if project &&
|
||||
project.respond_to?(:update_attributes) &&
|
||||
project.update_attributes(path: path) &&
|
||||
project.respond_to?(:rename_repo)
|
||||
|
||||
project.rename_repo
|
||||
end
|
||||
rescue => e
|
||||
Rails.logger.error "Exception when rename project #{id}: #{e.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20161221140236) do
|
||||
ActiveRecord::Schema.define(version: 20161221153951) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
|
45
spec/migrations/rename_reserved_project_names_spec.rb
Normal file
45
spec/migrations/rename_reserved_project_names_spec.rb
Normal file
|
@ -0,0 +1,45 @@
|
|||
# encoding: utf-8
|
||||
|
||||
require 'spec_helper'
|
||||
require Rails.root.join('db', 'post_migrate', '20161221153951_rename_reserved_project_names.rb')
|
||||
|
||||
describe RenameReservedProjectNames do
|
||||
let(:migration) { described_class.new }
|
||||
let!(:project) { create(:project) }
|
||||
|
||||
before do
|
||||
project.path = 'projects'
|
||||
project.save!(validate: false)
|
||||
allow(Thread).to receive(:new).and_yield
|
||||
end
|
||||
|
||||
describe '#up' do
|
||||
context 'when project repository exists' do
|
||||
before { project.create_repository }
|
||||
|
||||
context 'when no exception is raised' do
|
||||
it 'renames project with reserved names' do
|
||||
migration.up
|
||||
|
||||
expect(project.reload.path).to eq('projects0')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when exception is raised during rename' do
|
||||
before do
|
||||
allow(project).to receive(:rename_repo).and_raise(StandardError)
|
||||
end
|
||||
|
||||
it 'captures exception from project rename' do
|
||||
expect { migration.up }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project repository does not exist' do
|
||||
it 'does not raise error' do
|
||||
expect { migration.up }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue