diff options
Diffstat (limited to 'db')
-rw-r--r-- | db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb | 50 | ||||
-rw-r--r-- | db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb | 104 | ||||
-rw-r--r-- | db/schema.rb | 2 |
3 files changed, 155 insertions, 1 deletions
diff --git a/db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb b/db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb new file mode 100644 index 00000000000..da0fcda87a6 --- /dev/null +++ b/db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb @@ -0,0 +1,50 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class RenameUsersWithRenamedNamespace < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + DISALLOWED_ROOT_PATHS = %w[ + abuse_reports + api + autocomplete + explore + health_check + import + invites + jwt + koding + member + notification_settings + oauth + sent_notifications + unicorn_test + uploads + users + ] + + def up + DISALLOWED_ROOT_PATHS.each do |path| + users = Arel::Table.new(:users) + namespaces = Arel::Table.new(:namespaces) + predicate = namespaces[:owner_id].eq(users[:id]) + .and(namespaces[:type].eq(nil)) + .and(users[:username].matches(path)) + update_sql = if Gitlab::Database.postgresql? + "UPDATE users SET username = namespaces.path "\ + "FROM namespaces WHERE #{predicate.to_sql}" + else + "UPDATE users INNER JOIN namespaces "\ + "ON namespaces.owner_id = users.id "\ + "SET username = namespaces.path "\ + "WHERE #{predicate.to_sql}" + end + + connection.execute(update_sql) + end + end + + def down + end +end diff --git a/db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb b/db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb new file mode 100644 index 00000000000..c78beda9d21 --- /dev/null +++ b/db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb @@ -0,0 +1,104 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class FixWronglyRenamedRoutes < ActiveRecord::Migration + include Gitlab::Database::RenameReservedPathsMigration::V1 + + DOWNTIME = false + + disable_ddl_transaction! + + DISALLOWED_ROOT_PATHS = %w[ + - + abuse_reports + api + autocomplete + explore + health_check + import + invites + jwt + koding + member + notification_settings + oauth + sent_notifications + unicorn_test + uploads + users + ] + + FIXED_PATHS = DISALLOWED_ROOT_PATHS.map { |p| "#{p}0" } + + class Route < Gitlab::Database::RenameReservedPathsMigration::V1::MigrationClasses::Route + self.table_name = 'routes' + end + + def routes + @routes ||= Route.arel_table + end + + def namespaces + @namespaces ||= Arel::Table.new(:namespaces) + end + + def wildcard_collection(collection) + collection.map { |word| "#{word}%" } + end + + # The routes that got incorrectly renamed before, still have a namespace that + # contains the correct path. + # This query fetches all rows from the `routes` table that meet the following + # conditions using `api` as an example: + # - route.path ILIKE `api0%` + # - route.source_type = `Namespace` + # - namespace.parent_id IS NULL + # - namespace.path ILIKE `api%` + # - NOT(namespace.path ILIKE `api0%`) + # This gives us all root-routes, that were renamed, but their namespace was not. + # + def wrongly_renamed + Route.joins("INNER JOIN namespaces ON routes.source_id = namespaces.id") + .where( + routes[:source_type].eq('Namespace') + .and(namespaces[:parent_id].eq(nil)) + ) + .where(namespaces[:path].matches_any(wildcard_collection(DISALLOWED_ROOT_PATHS))) + .where.not(namespaces[:path].matches_any(wildcard_collection(FIXED_PATHS))) + .where(routes[:path].matches_any(wildcard_collection(FIXED_PATHS))) + end + + # Using the query above, we just fetch the `route.path` & the `namespace.path` + # `route.path` is the part of the route that is now incorrect + # `namespace.path` is what it should be + # We can use `route.path` to find all the namespaces that need to be fixed + # And we can use `namespace.path` to apply the correct name. + # + def paths_and_corrections + connection.select_all( + wrongly_renamed.select(routes[:path], namespaces[:path].as('namespace_path')).to_sql + ) + end + + # This can be used to limit the `update_in_batches` call to all routes for a + # single namespace, note the `/` that's what went wrong in the initial migration. + # + def routes_in_namespace_query(namespace) + routes[:path].matches_any([namespace, "#{namespace}/%"]) + end + + def up + paths_and_corrections.each do |root_namespace| + wrong_path = root_namespace['path'] + correct_path = root_namespace['namespace_path'] + replace_statement = replace_sql(Route.arel_table[:path], wrong_path, correct_path) + + update_column_in_batches(:routes, :path, replace_statement) do |table, query| + query.where(routes_in_namespace_query(wrong_path)) + end + end + end + + def down + end +end diff --git a/db/schema.rb b/db/schema.rb index 294e0b531eb..d14126401c9 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: 20170516183131) do +ActiveRecord::Schema.define(version: 20170518231126) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" |