Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-10-03 12:10:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-03 12:10:16 +0300
commit49bd8609775923402610f4c7f7c1f8aa1efdfe7e (patch)
treeb91150090cc5b23d1b6cd79ee038b2b93a8ab385 /lib/gitlab/database
parent9e7d45afd74a71be22c2413f4857d4389e360a42 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib/gitlab/database')
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1.rb42
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb99
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb196
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb106
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb78
5 files changed, 0 insertions, 521 deletions
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1.rb
deleted file mode 100644
index 2314246da55..00000000000
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-# This module can be included in migrations to make it easier to rename paths
-# of `Namespace` & `Project` models certain paths would become `reserved`.
-#
-# If the way things are stored on the filesystem related to namespaces and
-# projects ever changes. Don't update this module, or anything nested in `V1`,
-# since it needs to keep functioning for all migrations using it using the state
-# that the data is in at the time. Instead, create a `V2` module that implements
-# the new way of reserving paths.
-module Gitlab
- module Database
- module RenameReservedPathsMigration
- module V1
- def self.included(kls)
- kls.include(MigrationHelpers)
- end
-
- def rename_wildcard_paths(one_or_more_paths)
- rename_child_paths(one_or_more_paths)
- paths = Array(one_or_more_paths)
- RenameProjects.new(paths, self).rename_projects
- end
-
- def rename_child_paths(one_or_more_paths)
- paths = Array(one_or_more_paths)
- RenameNamespaces.new(paths, self).rename_namespaces(type: :child)
- end
-
- def rename_root_paths(paths)
- paths = Array(paths)
- RenameNamespaces.new(paths, self).rename_namespaces(type: :top_level)
- end
-
- def revert_renames
- RenameProjects.new([], self).revert_renames
- RenameNamespaces.new([], self).revert_renames
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
deleted file mode 100644
index f1dc3ed74fe..00000000000
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- module RenameReservedPathsMigration
- module V1
- module MigrationClasses
- module Routable
- def full_path
- if route && route.path.present?
- @full_path ||= route.path # rubocop:disable Gitlab/ModuleWithInstanceVariables
- else
- update_route if persisted?
-
- build_full_path
- end
- end
-
- def build_full_path
- if parent && path
- parent.full_path + '/' + path
- else
- path
- end
- end
-
- def update_route
- prepare_route
- route.save
- end
-
- def prepare_route
- route || build_route(source: self)
- route.path = build_full_path
- @full_path = nil # rubocop:disable Gitlab/ModuleWithInstanceVariables
- end
- end
-
- class Namespace < ActiveRecord::Base
- include MigrationClasses::Routable
- self.table_name = 'namespaces'
- self.inheritance_column = :_type_disabled
- belongs_to :parent,
- class_name: "#{MigrationClasses.name}::Namespace"
- has_one :route, as: :source
- has_many :children,
- class_name: "#{MigrationClasses.name}::Namespace",
- foreign_key: :parent_id
-
- # Overridden to have the correct `source_type` for the `route` relation
- def self.name
- 'Namespace'
- end
-
- def kind
- type == 'Group' ? 'group' : 'user'
- end
- end
-
- class User < ActiveRecord::Base
- self.table_name = 'users'
- end
-
- class Route < ActiveRecord::Base
- self.table_name = 'routes'
- belongs_to :source, polymorphic: true
- end
-
- class Project < ActiveRecord::Base
- include MigrationClasses::Routable
- has_one :route, as: :source
- self.table_name = 'projects'
-
- HASHED_STORAGE_FEATURES = {
- repository: 1,
- attachments: 2
- }.freeze
-
- def repository_storage_path
- Gitlab.config.repositories.storages[repository_storage].legacy_disk_path
- end
-
- # Overridden to have the correct `source_type` for the `route` relation
- def self.name
- 'Project'
- end
-
- def hashed_storage?(feature)
- raise ArgumentError, "Invalid feature" unless HASHED_STORAGE_FEATURES.include?(feature)
- return false unless respond_to?(:storage_version)
-
- self.storage_version && self.storage_version >= HASHED_STORAGE_FEATURES[feature]
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb
deleted file mode 100644
index 2c9d0d6c0d1..00000000000
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb
+++ /dev/null
@@ -1,196 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- module RenameReservedPathsMigration
- module V1
- class RenameBase
- attr_reader :paths, :migration
-
- delegate :update_column_in_batches,
- :execute,
- :replace_sql,
- :quote_string,
- :say,
- to: :migration
-
- def initialize(paths, migration)
- @paths = paths
- @migration = migration
- end
-
- def path_patterns
- @path_patterns ||= paths.flat_map { |path| ["%/#{path}", path] }
- end
-
- def rename_path_for_routable(routable)
- old_path = routable.path
- old_full_path = routable.full_path
- # Only remove the last occurrence of the path name to get the parent namespace path
- namespace_path = remove_last_occurrence(old_full_path, old_path)
- new_path = rename_path(namespace_path, old_path)
- new_full_path = join_routable_path(namespace_path, new_path)
-
- perform_rename(routable, old_full_path, new_full_path)
-
- [old_full_path, new_full_path]
- end
-
- def perform_rename(routable, old_full_path, new_full_path)
- # skips callbacks & validations
- new_path = new_full_path.split('/').last
- routable.class.where(id: routable)
- .update_all(path: new_path)
-
- rename_routes(old_full_path, new_full_path)
- end
-
- def rename_routes(old_full_path, new_full_path)
- routes = Route.arel_table
-
- quoted_old_full_path = quote_string(old_full_path)
- quoted_old_wildcard_path = quote_string("#{old_full_path}/%")
-
- filter =
- "routes.id IN "\
- "( SELECT routes.id FROM routes WHERE lower(routes.path) = lower('#{quoted_old_full_path}') "\
- "UNION SELECT routes.id FROM routes WHERE routes.path ILIKE '#{quoted_old_wildcard_path}' )"
-
- replace_statement = replace_sql(Route.arel_table[:path],
- old_full_path,
- new_full_path)
-
- update = Arel::UpdateManager.new
- .table(routes)
- .set([[routes[:path], replace_statement]])
- .where(Arel::Nodes::SqlLiteral.new(filter))
-
- execute(update.to_sql)
- end
-
- def rename_path(namespace_path, path_was)
- counter = 0
- path = "#{path_was}#{counter}"
-
- while route_exists?(join_routable_path(namespace_path, path))
- counter += 1
- path = "#{path_was}#{counter}"
- end
-
- path
- end
-
- def remove_last_occurrence(string, pattern)
- string.reverse.sub(pattern.reverse, "").reverse
- end
-
- def join_routable_path(namespace_path, top_level)
- if namespace_path.present?
- File.join(namespace_path, top_level)
- else
- top_level
- end
- end
-
- def route_exists?(full_path)
- MigrationClasses::Route.where(Route.arel_table[:path].matches(full_path)).any?
- end
-
- def move_pages(old_path, new_path)
- move_folders(pages_dir, old_path, new_path)
- end
-
- def move_uploads(old_path, new_path)
- return unless file_storage?
-
- move_folders(uploads_dir, old_path, new_path)
- end
-
- def move_folders(directory, old_relative_path, new_relative_path)
- old_path = File.join(directory, old_relative_path)
- unless File.directory?(old_path)
- say "#{old_path} doesn't exist, skipping"
- return
- end
-
- new_path = File.join(directory, new_relative_path)
- FileUtils.mv(old_path, new_path)
- end
-
- def remove_cached_html_for_projects(project_ids)
- project_ids.each do |project_id|
- update_column_in_batches(:projects, :description_html, nil) do |table, query|
- query.where(table[:id].eq(project_id))
- end
-
- update_column_in_batches(:issues, :description_html, nil) do |table, query|
- query.where(table[:project_id].eq(project_id))
- end
-
- update_column_in_batches(:merge_requests, :description_html, nil) do |table, query|
- query.where(table[:target_project_id].eq(project_id))
- end
-
- update_column_in_batches(:notes, :note_html, nil) do |table, query|
- query.where(table[:project_id].eq(project_id))
- end
-
- update_column_in_batches(:milestones, :description_html, nil) do |table, query|
- query.where(table[:project_id].eq(project_id))
- end
- end
- end
-
- def track_rename(type, old_path, new_path)
- key = redis_key_for_type(type)
- Gitlab::Redis::SharedState.with do |redis|
- redis.lpush(key, [old_path, new_path].to_json)
- redis.expire(key, 2.weeks.to_i)
- end
- say "tracked rename: #{key}: #{old_path} -> #{new_path}"
- end
-
- def reverts_for_type(type)
- key = redis_key_for_type(type)
-
- Gitlab::Redis::SharedState.with do |redis|
- failed_reverts = []
-
- while rename_info = redis.lpop(key)
- path_before_rename, path_after_rename = Gitlab::Json.parse(rename_info)
- say "renaming #{type} from #{path_after_rename} back to #{path_before_rename}"
- begin
- yield(path_before_rename, path_after_rename)
- rescue StandardError => e
- failed_reverts << rename_info
- say "Renaming #{type} from #{path_after_rename} back to "\
- "#{path_before_rename} failed. Review the error and try "\
- "again by running the `down` action. \n"\
- "#{e.message}: \n #{e.backtrace.join("\n")}"
- end
- end
-
- failed_reverts.each { |rename_info| redis.lpush(key, rename_info) }
- end
- end
-
- def redis_key_for_type(type)
- "rename:#{migration.name}:#{type}"
- end
-
- def file_storage?
- CarrierWave::Uploader::Base.storage == CarrierWave::Storage::File
- end
-
- def uploads_dir
- File.join(CarrierWave.root, "uploads")
- end
-
- def pages_dir
- Settings.pages.path
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb
deleted file mode 100644
index 72ae2849911..00000000000
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- module RenameReservedPathsMigration
- module V1
- class RenameNamespaces < RenameBase
- include Gitlab::ShellAdapter
-
- def rename_namespaces(type:)
- namespaces_for_paths(type: type).each do |namespace|
- rename_namespace(namespace)
- end
- end
-
- def namespaces_for_paths(type:)
- namespaces = case type
- when :child
- MigrationClasses::Namespace.where.not(parent_id: nil)
- when :top_level
- MigrationClasses::Namespace.where(parent_id: nil)
- end
- with_paths = MigrationClasses::Route.arel_table[:path]
- .matches_any(path_patterns)
- namespaces.joins(:route).where(with_paths)
- .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/420046")
- end
-
- def rename_namespace(namespace)
- old_full_path, new_full_path = rename_path_for_routable(namespace)
-
- track_rename('namespace', old_full_path, new_full_path)
-
- rename_namespace_dependencies(namespace, old_full_path, new_full_path)
- end
-
- def rename_namespace_dependencies(namespace, old_full_path, new_full_path)
- move_repositories(namespace, old_full_path, new_full_path)
- move_uploads(old_full_path, new_full_path)
- move_pages(old_full_path, new_full_path)
- rename_user(old_full_path, new_full_path) if namespace.kind == 'user'
- remove_cached_html_for_projects(projects_for_namespace(namespace).map(&:id))
- end
-
- def revert_renames
- reverts_for_type('namespace') do |path_before_rename, current_path|
- matches_path = MigrationClasses::Route.arel_table[:path].matches(current_path)
- namespace = MigrationClasses::Namespace.joins(:route)
- .allow_cross_joins_across_databases(url: "https://gitlab.com/gitlab-org/gitlab/-/issues/420046")
- .find_by(matches_path)&.becomes(MigrationClasses::Namespace) # rubocop: disable Cop/AvoidBecomes
-
- if namespace
- perform_rename(namespace, current_path, path_before_rename)
-
- rename_namespace_dependencies(namespace, current_path, path_before_rename)
- else
- say "Couldn't rename namespace from #{current_path} back to #{path_before_rename}, "\
- "namespace was renamed, or no longer exists at the expected path"
- end
- end
- end
-
- def rename_user(old_username, new_username)
- MigrationClasses::User.where(username: old_username)
- .update_all(username: new_username)
- end
-
- def move_repositories(namespace, old_full_path, new_full_path)
- repo_shards_for_namespace(namespace).each do |repository_storage|
- # Ensure old directory exists before moving it
- Gitlab::GitalyClient::NamespaceService.allow do
- gitlab_shell.add_namespace(repository_storage, old_full_path)
-
- unless gitlab_shell.mv_namespace(repository_storage, old_full_path, new_full_path)
- message = "Exception moving on shard #{repository_storage} from #{old_full_path} to #{new_full_path}"
- Gitlab::AppLogger.error message
- end
- end
- end
- end
-
- def repo_shards_for_namespace(namespace)
- projects_for_namespace(namespace).distinct.select(:repository_storage)
- .map(&:repository_storage)
- end
-
- def projects_for_namespace(namespace)
- namespace_ids = child_ids_for_parent(namespace, ids: [namespace.id])
- namespace_or_children = MigrationClasses::Project
- .arel_table[:namespace_id]
- .in(namespace_ids)
- MigrationClasses::Project.where(namespace_or_children)
- end
-
- def child_ids_for_parent(namespace, ids: [])
- namespace.children.each do |child|
- ids << child.id
- child_ids_for_parent(child, ids: ids) if child.children.any?
- end
- ids
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb
deleted file mode 100644
index 155e35b64f4..00000000000
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Database
- module RenameReservedPathsMigration
- module V1
- class RenameProjects < RenameBase
- include Gitlab::ShellAdapter
-
- def rename_projects
- projects_for_paths.each do |project|
- rename_project(project)
- end
-
- remove_cached_html_for_projects(projects_for_paths.map(&:id))
- end
-
- def rename_project(project)
- old_full_path, new_full_path = rename_path_for_routable(project)
-
- track_rename('project', old_full_path, new_full_path)
-
- move_project_folders(project, old_full_path, new_full_path)
- end
-
- def move_project_folders(project, old_full_path, new_full_path)
- unless project.hashed_storage?(:repository)
- move_repository(project, old_full_path, new_full_path)
- move_repository(project, "#{old_full_path}.wiki", "#{new_full_path}.wiki")
- end
-
- move_uploads(old_full_path, new_full_path) unless project.hashed_storage?(:attachments)
- move_pages(old_full_path, new_full_path)
- end
-
- def revert_renames
- reverts_for_type('project') do |path_before_rename, current_path|
- matches_path = MigrationClasses::Route.arel_table[:path].matches(current_path)
- project = MigrationClasses::Project.joins(:route)
- .allow_cross_joins_across_databases(url:
- 'https://gitlab.com/gitlab-org/gitlab/-/issues/421843')
- .find_by(matches_path)
-
- if project
- perform_rename(project, current_path, path_before_rename)
-
- move_project_folders(project, current_path, path_before_rename)
- else
- say "Couldn't rename project from #{current_path} back to "\
- "#{path_before_rename}, project was renamed or no longer "\
- "exists at the expected path."
-
- end
- end
- end
-
- def move_repository(project, old_path, new_path)
- unless gitlab_shell.mv_repository(project.repository_storage,
- old_path,
- new_path)
- Gitlab::AppLogger.error "Error moving #{old_path} to #{new_path}"
- end
- end
-
- def projects_for_paths
- return @projects_for_paths if @projects_for_paths
-
- with_paths = MigrationClasses::Route.arel_table[:path]
- .matches_any(path_patterns)
-
- @projects_for_paths = MigrationClasses::Project.joins(:route).where(with_paths)
- .allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/421843')
- end
- end
- end
- end
- end
-end