summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2016-12-26 16:14:41 +0200
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2016-12-26 16:14:41 +0200
commitdbfac0de066c4770a15d4e9a96dbc01edf9add3f (patch)
tree2491029249b09b770eee0c2d20c83bdf82b147fd
parent645412b57f558d58418aad278c9a3bf421439e1c (diff)
downloadgitlab-ce-dz-rename-invalid-users.tar.gz
Rename users with namespace ending with .gitdz-rename-invalid-users
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
-rw-r--r--changelogs/unreleased/dz-rename-invalid-users.yml4
-rw-r--r--db/migrate/20161226122833_remove_dot_git_from_usernames.rb87
-rw-r--r--db/schema.rb2
-rw-r--r--spec/migrations/remove_dot_git_from_usernames.rb29
4 files changed, 121 insertions, 1 deletions
diff --git a/changelogs/unreleased/dz-rename-invalid-users.yml b/changelogs/unreleased/dz-rename-invalid-users.yml
new file mode 100644
index 00000000000..f420b069531
--- /dev/null
+++ b/changelogs/unreleased/dz-rename-invalid-users.yml
@@ -0,0 +1,4 @@
+---
+title: Rename users with namespace ending with .git
+merge_request: 8309
+author:
diff --git a/db/migrate/20161226122833_remove_dot_git_from_usernames.rb b/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
new file mode 100644
index 00000000000..809b09feb84
--- /dev/null
+++ b/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
@@ -0,0 +1,87 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class RemoveDotGitFromUsernames < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ include Gitlab::ShellAdapter
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def up
+ invalid_users.each do |user|
+ id = user['id']
+ namespace_id = user['namespace_id']
+ path_was = user['username']
+ path_was_wildcard = quote_string("#{path_was}/%")
+ path = quote_string(rename_path(path_was))
+
+ move_namespace(namespace_id, path_was, path)
+
+ execute "UPDATE routes SET path = '#{path}' WHERE source_type = 'Namespace' AND source_id = #{namespace_id}"
+ execute "UPDATE namespaces SET path = '#{path}' WHERE id = #{namespace_id}"
+ execute "UPDATE users SET username = '#{path}' WHERE id = #{id}"
+
+ select_all("SELECT id, path FROM routes WHERE path LIKE '#{path_was_wildcard}'").each do |route|
+ new_path = "#{path}/#{route['path'].split('/').last}"
+ execute "UPDATE routes SET path = '#{new_path}' WHERE id = #{route['id']}"
+ end
+ end
+ end
+
+ def down
+ # nothing to do here
+ end
+
+ private
+
+ def invalid_users
+ select_all("SELECT u.id, u.username, n.path AS namespace_path, n.id AS namespace_id FROM users u
+ INNER JOIN namespaces n ON n.owner_id = u.id
+ WHERE n.type is NULL AND n.path LIKE '%.git'")
+ end
+
+ def route_exists?(path)
+ select_all("SELECT id, path FROM routes WHERE path = '#{quote_string(path)}'").present?
+ end
+
+ # Accepts invalid path like test.git and returns test_git or
+ # test_git1 if test_git already taken
+ def rename_path(path)
+ # To stay closer with original name and reduce risk of duplicates
+ # we rename suffix instead of removing it
+ path = path.sub(/\.git\z/, '_git')
+
+ counter = 0
+ base = path
+
+ while route_exists?(path)
+ counter += 1
+ path = "#{base}#{counter}"
+ end
+
+ path
+ end
+
+ def move_namespace(namespace_id, path_was, path)
+ repository_storage_paths = select_all("SELECT distinct(repository_storage) FROM projects WHERE namespace_id = #{namespace_id}").map do |row|
+ Gitlab.config.repositories.storages[row['repository_storage']]
+ end.compact
+
+ # Move the namespace directory in all storages paths used by member projects
+ repository_storage_paths.each do |repository_storage_path|
+ # Ensure old directory exists before moving it
+ gitlab_shell.add_namespace(repository_storage_path, path_was)
+
+ unless gitlab_shell.mv_namespace(repository_storage_path, path_was, path)
+ Rails.logger.error "Exception moving path #{repository_storage_path} from #{path_was} to #{path}"
+
+ # 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('namespace directory cannot be moved')
+ end
+ end
+
+ Gitlab::UploadsTransfer.new.rename_namespace(path_was, path)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 05b6c807660..1fcb6bcfe60 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -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: 20161226122833) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
diff --git a/spec/migrations/remove_dot_git_from_usernames.rb b/spec/migrations/remove_dot_git_from_usernames.rb
new file mode 100644
index 00000000000..1b1d2adc463
--- /dev/null
+++ b/spec/migrations/remove_dot_git_from_usernames.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20161226122833_remove_dot_git_from_usernames.rb')
+
+describe RemoveDotGitFromUsernames do
+ let(:user) { create(:user) }
+
+ describe '#up' do
+ let(:migration) { described_class.new }
+
+ before do
+ namespace = user.namespace
+ namespace.path = 'test.git'
+ namespace.save!(validate: false)
+
+ user.username = 'test.git'
+ user.save!(validate: false)
+ end
+
+ it 'renames user with .git in username' do
+ migration.up
+
+ expect(user.reload.username).to eq('test_git')
+ expect(user.namespace.reload.path).to eq('test_git')
+ expect(user.namespace.route.path).to eq('test_git')
+ end
+ end
+end