diff options
author | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2019-07-02 13:14:24 +0000 |
---|---|---|
committer | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2019-07-02 13:14:24 +0000 |
commit | e07ebe66af957c46e7c69329b3ab561bb539351b (patch) | |
tree | 9a4d6d52f94b99aea154ad53000a39d172b18cdb /lib | |
parent | 58786e2086b9d8db5784771f4dbfe8b5c107df18 (diff) | |
parent | 6aeb6996447ead0f6daf71faab85c99e11ab8ae8 (diff) | |
download | gitlab-ce-e07ebe66af957c46e7c69329b3ab561bb539351b.tar.gz |
Merge branch '59177-squash-old-migrations' into 'master'harish-and-cindy-ssl-check-rake-taskharish-and-cindy-ldap-sync-rake-tasks
Squash old migrations
Closes #59177
See merge request gitlab-org/gitlab-ce!30226
Diffstat (limited to 'lib')
7 files changed, 0 insertions, 771 deletions
diff --git a/lib/gitlab/background_migration/create_fork_network_memberships_range.rb b/lib/gitlab/background_migration/create_fork_network_memberships_range.rb deleted file mode 100644 index ccd1f9b4dba..00000000000 --- a/lib/gitlab/background_migration/create_fork_network_memberships_range.rb +++ /dev/null @@ -1,85 +0,0 @@ -# frozen_string_literal: true -# rubocop:disable Style/Documentation - -module Gitlab - module BackgroundMigration - class CreateForkNetworkMembershipsRange - RESCHEDULE_DELAY = 15 - - class ForkedProjectLink < ActiveRecord::Base - self.table_name = 'forked_project_links' - end - - def perform(start_id, end_id) - log("Creating memberships for forks: #{start_id} - #{end_id}") - - insert_members(start_id, end_id) - - if missing_members?(start_id, end_id) - BackgroundMigrationWorker.perform_in(RESCHEDULE_DELAY, "CreateForkNetworkMembershipsRange", [start_id, end_id]) - end - end - - def insert_members(start_id, end_id) - ActiveRecord::Base.connection.execute <<~INSERT_MEMBERS - INSERT INTO fork_network_members (fork_network_id, project_id, forked_from_project_id) - - SELECT fork_network_members.fork_network_id, - forked_project_links.forked_to_project_id, - forked_project_links.forked_from_project_id - - FROM forked_project_links - - INNER JOIN fork_network_members - ON forked_project_links.forked_from_project_id = fork_network_members.project_id - - WHERE forked_project_links.id BETWEEN #{start_id} AND #{end_id} - AND NOT EXISTS ( - SELECT true - FROM fork_network_members existing_members - WHERE existing_members.project_id = forked_project_links.forked_to_project_id - ) - INSERT_MEMBERS - rescue ActiveRecord::RecordNotUnique => e - # `fork_network_member` was created concurrently in another migration - log(e.message) - end - - def missing_members?(start_id, end_id) - count_sql = <<~MISSING_MEMBERS - SELECT COUNT(*) - - FROM forked_project_links - - WHERE NOT EXISTS ( - SELECT true - FROM fork_network_members - WHERE fork_network_members.project_id = forked_project_links.forked_to_project_id - ) - AND EXISTS ( - SELECT true - FROM projects - WHERE forked_project_links.forked_from_project_id = projects.id - ) - AND NOT EXISTS ( - SELECT true - FROM forked_project_links AS parent_links - WHERE parent_links.forked_to_project_id = forked_project_links.forked_from_project_id - AND NOT EXISTS ( - SELECT true - FROM projects - WHERE parent_links.forked_from_project_id = projects.id - ) - ) - AND forked_project_links.id BETWEEN #{start_id} AND #{end_id} - MISSING_MEMBERS - - ForkedProjectLink.count_by_sql(count_sql) > 0 - end - - def log(message) - Rails.logger.info("#{self.class.name} - #{message}") - end - end - end -end diff --git a/lib/gitlab/background_migration/delete_conflicting_redirect_routes_range.rb b/lib/gitlab/background_migration/delete_conflicting_redirect_routes_range.rb deleted file mode 100644 index 21b626dde56..00000000000 --- a/lib/gitlab/background_migration/delete_conflicting_redirect_routes_range.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true -# rubocop:disable Style/Documentation - -module Gitlab - module BackgroundMigration - class DeleteConflictingRedirectRoutesRange - def perform(start_id, end_id) - # No-op. - # See https://gitlab.com/gitlab-com/infrastructure/issues/3460#note_53223252 - end - end - end -end diff --git a/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb b/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb deleted file mode 100644 index 42fcaa87e66..00000000000 --- a/lib/gitlab/background_migration/migrate_events_to_push_event_payloads.rb +++ /dev/null @@ -1,179 +0,0 @@ -# frozen_string_literal: true -# rubocop:disable Style/Documentation - -module Gitlab - module BackgroundMigration - # Class that migrates events for the new push event payloads setup. All - # events are copied to a shadow table, and push events will also have a row - # created in the push_event_payloads table. - class MigrateEventsToPushEventPayloads - class Event < ActiveRecord::Base - self.table_name = 'events' - - serialize :data - - BLANK_REF = ('0' * 40).freeze - TAG_REF_PREFIX = 'refs/tags/'.freeze - MAX_INDEX = 69 - PUSHED = 5 - - def push_event? - action == PUSHED && data.present? - end - - def commit_title - commit = commits.last - - return unless commit && commit[:message] - - index = commit[:message].index("\n") - message = index ? commit[:message][0..index] : commit[:message] - - message.strip.truncate(70) - end - - def commit_from_sha - if create? - nil - else - data[:before] - end - end - - def commit_to_sha - if remove? - nil - else - data[:after] - end - end - - def data - super || {} - end - - def commits - data[:commits] || [] - end - - def commit_count - data[:total_commits_count] || 0 - end - - def ref - data[:ref] - end - - def trimmed_ref_name - if ref_type == :tag - ref[10..-1] - else - ref[11..-1] - end - end - - def create? - data[:before] == BLANK_REF - end - - def remove? - data[:after] == BLANK_REF - end - - def push_action - if create? - :created - elsif remove? - :removed - else - :pushed - end - end - - def ref_type - if ref.start_with?(TAG_REF_PREFIX) - :tag - else - :branch - end - end - end - - class EventForMigration < ActiveRecord::Base - self.table_name = 'events_for_migration' - end - - class PushEventPayload < ActiveRecord::Base - self.table_name = 'push_event_payloads' - - enum action: { - created: 0, - removed: 1, - pushed: 2 - } - - enum ref_type: { - branch: 0, - tag: 1 - } - end - - # start_id - The start ID of the range of events to process - # end_id - The end ID of the range to process. - def perform(start_id, end_id) - return unless migrate? - - find_events(start_id, end_id).each { |event| process_event(event) } - end - - def process_event(event) - ActiveRecord::Base.transaction do - replicate_event(event) - create_push_event_payload(event) if event.push_event? - end - rescue ActiveRecord::InvalidForeignKey => e - # A foreign key error means the associated event was removed. In this - # case we'll just skip migrating the event. - Rails.logger.error("Unable to migrate event #{event.id}: #{e}") - end - - def replicate_event(event) - new_attributes = event.attributes - .with_indifferent_access.except(:title, :data) - - EventForMigration.create!(new_attributes) - end - - def create_push_event_payload(event) - commit_from = pack(event.commit_from_sha) - commit_to = pack(event.commit_to_sha) - - PushEventPayload.create!( - event_id: event.id, - commit_count: event.commit_count, - ref_type: event.ref_type, - action: event.push_action, - commit_from: commit_from, - commit_to: commit_to, - ref: event.trimmed_ref_name, - commit_title: event.commit_title - ) - end - - def find_events(start_id, end_id) - Event - .where('NOT EXISTS (SELECT true FROM events_for_migration WHERE events_for_migration.id = events.id)') - .where(id: start_id..end_id) - end - - def migrate? - Event.table_exists? && PushEventPayload.table_exists? && - EventForMigration.table_exists? - end - - def pack(value) - value ? [value].pack('H*') : nil - end - end - end -end diff --git a/lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb b/lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb deleted file mode 100644 index 48aa369705f..00000000000 --- a/lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb +++ /dev/null @@ -1,319 +0,0 @@ -# frozen_string_literal: true -# rubocop:disable Metrics/MethodLength -# rubocop:disable Metrics/ClassLength -# rubocop:disable Metrics/BlockLength -# rubocop:disable Style/Documentation - -module Gitlab - module BackgroundMigration - class NormalizeLdapExternUidsRange - class Identity < ActiveRecord::Base - self.table_name = 'identities' - end - - # Copied this class to make this migration resilient to future code changes. - # And if the normalize behavior is changed in the future, it must be - # accompanied by another migration. - module Gitlab - module Auth - module LDAP - class DN - FormatError = Class.new(StandardError) - MalformedError = Class.new(FormatError) - UnsupportedError = Class.new(FormatError) - - def self.normalize_value(given_value) - dummy_dn = "placeholder=#{given_value}" - normalized_dn = new(*dummy_dn).to_normalized_s - normalized_dn.sub(/\Aplaceholder=/, '') - end - - ## - # Initialize a DN, escaping as required. Pass in attributes in name/value - # pairs. If there is a left over argument, it will be appended to the dn - # without escaping (useful for a base string). - # - # Most uses of this class will be to escape a DN, rather than to parse it, - # so storing the dn as an escaped String and parsing parts as required - # with a state machine seems sensible. - def initialize(*args) - if args.length > 1 - initialize_array(args) - else - initialize_string(args[0]) - end - end - - ## - # Parse a DN into key value pairs using ASN from - # http://tools.ietf.org/html/rfc2253 section 3. - # rubocop:disable Metrics/AbcSize - # rubocop:disable Metrics/CyclomaticComplexity - # rubocop:disable Metrics/PerceivedComplexity - def each_pair - state = :key - key = StringIO.new - value = StringIO.new - hex_buffer = "" - - @dn.each_char.with_index do |char, dn_index| - case state - when :key then - case char - when 'a'..'z', 'A'..'Z' then - state = :key_normal - key << char - when '0'..'9' then - state = :key_oid - key << char - when ' ' then state = :key - else raise(MalformedError, "Unrecognized first character of an RDN attribute type name \"#{char}\"") - end - when :key_normal then - case char - when '=' then state = :value - when 'a'..'z', 'A'..'Z', '0'..'9', '-', ' ' then key << char - else raise(MalformedError, "Unrecognized RDN attribute type name character \"#{char}\"") - end - when :key_oid then - case char - when '=' then state = :value - when '0'..'9', '.', ' ' then key << char - else raise(MalformedError, "Unrecognized RDN OID attribute type name character \"#{char}\"") - end - when :value then - case char - when '\\' then state = :value_normal_escape - when '"' then state = :value_quoted - when ' ' then state = :value - when '#' then - state = :value_hexstring - value << char - when ',' then - state = :key - yield key.string.strip, rstrip_except_escaped(value.string, dn_index) - key = StringIO.new - value = StringIO.new - else - state = :value_normal - value << char - end - when :value_normal then - case char - when '\\' then state = :value_normal_escape - when ',' then - state = :key - yield key.string.strip, rstrip_except_escaped(value.string, dn_index) - key = StringIO.new - value = StringIO.new - when '+' then raise(UnsupportedError, "Multivalued RDNs are not supported") - else value << char - end - when :value_normal_escape then - case char - when '0'..'9', 'a'..'f', 'A'..'F' then - state = :value_normal_escape_hex - hex_buffer = char - else - state = :value_normal - value << char - end - when :value_normal_escape_hex then - case char - when '0'..'9', 'a'..'f', 'A'..'F' then - state = :value_normal - value << "#{hex_buffer}#{char}".to_i(16).chr - else raise(MalformedError, "Invalid escaped hex code \"\\#{hex_buffer}#{char}\"") - end - when :value_quoted then - case char - when '\\' then state = :value_quoted_escape - when '"' then state = :value_end - else value << char - end - when :value_quoted_escape then - case char - when '0'..'9', 'a'..'f', 'A'..'F' then - state = :value_quoted_escape_hex - hex_buffer = char - else - state = :value_quoted - value << char - end - when :value_quoted_escape_hex then - case char - when '0'..'9', 'a'..'f', 'A'..'F' then - state = :value_quoted - value << "#{hex_buffer}#{char}".to_i(16).chr - else raise(MalformedError, "Expected the second character of a hex pair inside a double quoted value, but got \"#{char}\"") - end - when :value_hexstring then - case char - when '0'..'9', 'a'..'f', 'A'..'F' then - state = :value_hexstring_hex - value << char - when ' ' then state = :value_end - when ',' then - state = :key - yield key.string.strip, rstrip_except_escaped(value.string, dn_index) - key = StringIO.new - value = StringIO.new - else raise(MalformedError, "Expected the first character of a hex pair, but got \"#{char}\"") - end - when :value_hexstring_hex then - case char - when '0'..'9', 'a'..'f', 'A'..'F' then - state = :value_hexstring - value << char - else raise(MalformedError, "Expected the second character of a hex pair, but got \"#{char}\"") - end - when :value_end then - case char - when ' ' then state = :value_end - when ',' then - state = :key - yield key.string.strip, rstrip_except_escaped(value.string, dn_index) - key = StringIO.new - value = StringIO.new - else raise(MalformedError, "Expected the end of an attribute value, but got \"#{char}\"") - end - else raise "Fell out of state machine" - end - end - - # Last pair - raise(MalformedError, 'DN string ended unexpectedly') unless - [:value, :value_normal, :value_hexstring, :value_end].include? state - - yield key.string.strip, rstrip_except_escaped(value.string, @dn.length) - end - - def rstrip_except_escaped(str, dn_index) - str_ends_with_whitespace = str.match(/\s\z/) - - if str_ends_with_whitespace - dn_part_ends_with_escaped_whitespace = @dn[0, dn_index].match(/\\(\s+)\z/) - - if dn_part_ends_with_escaped_whitespace - dn_part_rwhitespace = dn_part_ends_with_escaped_whitespace[1] - num_chars_to_remove = dn_part_rwhitespace.length - 1 - str = str[0, str.length - num_chars_to_remove] - else - str.rstrip! - end - end - - str - end - - ## - # Returns the DN as an array in the form expected by the constructor. - def to_a - a = [] - self.each_pair { |key, value| a << key << value } unless @dn.empty? - a - end - - ## - # Return the DN as an escaped string. - def to_s - @dn - end - - ## - # Return the DN as an escaped and normalized string. - def to_normalized_s - self.class.new(*to_a).to_s.downcase - end - - # https://tools.ietf.org/html/rfc4514 section 2.4 lists these exceptions - # for DN values. All of the following must be escaped in any normal string - # using a single backslash ('\') as escape. The space character is left - # out here because in a "normalized" string, spaces should only be escaped - # if necessary (i.e. leading or trailing space). - NORMAL_ESCAPES = [',', '+', '"', '\\', '<', '>', ';', '='].freeze - - # The following must be represented as escaped hex - HEX_ESCAPES = { - "\n" => '\0a', - "\r" => '\0d' - }.freeze - - # Compiled character class regexp using the keys from the above hash, and - # checking for a space or # at the start, or space at the end, of the - # string. - ESCAPE_RE = Regexp.new("(^ |^#| $|[" + - NORMAL_ESCAPES.map { |e| Regexp.escape(e) }.join + - "])") - - HEX_ESCAPE_RE = Regexp.new("([" + - HEX_ESCAPES.keys.map { |e| Regexp.escape(e) }.join + - "])") - - ## - # Escape a string for use in a DN value - def self.escape(string) - escaped = string.gsub(ESCAPE_RE) { |char| "\\" + char } - escaped.gsub(HEX_ESCAPE_RE) { |char| HEX_ESCAPES[char] } - end - - private - - def initialize_array(args) - buffer = StringIO.new - - args.each_with_index do |arg, index| - if index.even? # key - buffer << "," if index > 0 - buffer << arg - else # value - buffer << "=" - buffer << self.class.escape(arg) - end - end - - @dn = buffer.string - end - - def initialize_string(arg) - @dn = arg.to_s - end - - ## - # Proxy all other requests to the string object, because a DN is mainly - # used within the library as a string - # rubocop:disable GitlabSecurity/PublicSend - def method_missing(method, *args, &block) - @dn.send(method, *args, &block) - end - - ## - # Redefined to be consistent with redefined `method_missing` behavior - def respond_to?(sym, include_private = false) - @dn.respond_to?(sym, include_private) - end - end - end - end - end - - def perform(start_id, end_id) - return unless migrate? - - ldap_identities = Identity.where("provider like 'ldap%'").where(id: start_id..end_id) - ldap_identities.each do |identity| - identity.extern_uid = Gitlab::Auth::LDAP::DN.new(identity.extern_uid).to_normalized_s - unless identity.save - Rails.logger.info "Unable to normalize \"#{identity.extern_uid}\". Skipping." - end - rescue Gitlab::Auth::LDAP::DN::FormatError => e - Rails.logger.info "Unable to normalize \"#{identity.extern_uid}\" due to \"#{e.message}\". Skipping." - end - end - - def migrate? - Identity.table_exists? - end - end - end -end diff --git a/lib/gitlab/background_migration/populate_fork_networks_range.rb b/lib/gitlab/background_migration/populate_fork_networks_range.rb deleted file mode 100644 index aa4f130538c..00000000000 --- a/lib/gitlab/background_migration/populate_fork_networks_range.rb +++ /dev/null @@ -1,128 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module BackgroundMigration - # This background migration is going to create all `fork_networks` and - # the `fork_network_members` for the roots of fork networks based on the - # existing `forked_project_links`. - # - # When the source of a fork is deleted, we will create the fork with the - # target project as the root. This way, when there are forks of the target - # project, they will be joined into the same fork network. - # - # When the `fork_networks` and memberships for the root projects are created - # the `CreateForkNetworkMembershipsRange` migration is scheduled. This - # migration will create the memberships for all remaining forks-of-forks - class PopulateForkNetworksRange - def perform(start_id, end_id) - create_fork_networks_for_existing_projects(start_id, end_id) - create_fork_networks_for_missing_projects(start_id, end_id) - create_fork_networks_memberships_for_root_projects(start_id, end_id) - - delay = BackgroundMigration::CreateForkNetworkMembershipsRange::RESCHEDULE_DELAY - BackgroundMigrationWorker.perform_in( - delay, "CreateForkNetworkMembershipsRange", [start_id, end_id] - ) - end - - def create_fork_networks_for_existing_projects(start_id, end_id) - log("Creating fork networks: #{start_id} - #{end_id}") - ActiveRecord::Base.connection.execute <<~INSERT_NETWORKS - INSERT INTO fork_networks (root_project_id) - SELECT DISTINCT forked_project_links.forked_from_project_id - - FROM forked_project_links - - -- Exclude the forks that are not the first level fork of a project - WHERE NOT EXISTS ( - SELECT true - FROM forked_project_links inner_links - WHERE inner_links.forked_to_project_id = forked_project_links.forked_from_project_id - ) - - /* Exclude the ones that are already created, in case the fork network - was already created for another fork of the project. - */ - AND NOT EXISTS ( - SELECT true - FROM fork_networks - WHERE forked_project_links.forked_from_project_id = fork_networks.root_project_id - ) - - -- Only create a fork network for a root project that still exists - AND EXISTS ( - SELECT true - FROM projects - WHERE projects.id = forked_project_links.forked_from_project_id - ) - AND forked_project_links.id BETWEEN #{start_id} AND #{end_id} - INSERT_NETWORKS - end - - def create_fork_networks_for_missing_projects(start_id, end_id) - log("Creating fork networks with missing root: #{start_id} - #{end_id}") - ActiveRecord::Base.connection.execute <<~INSERT_NETWORKS - INSERT INTO fork_networks (root_project_id) - SELECT DISTINCT forked_project_links.forked_to_project_id - - FROM forked_project_links - - -- Exclude forks that are not the root forks - WHERE NOT EXISTS ( - SELECT true - FROM forked_project_links inner_links - WHERE inner_links.forked_to_project_id = forked_project_links.forked_from_project_id - ) - - /* Exclude the ones that are already created, in case this migration is - re-run - */ - AND NOT EXISTS ( - SELECT true - FROM fork_networks - WHERE forked_project_links.forked_to_project_id = fork_networks.root_project_id - ) - - /* Exclude projects for which the project still exists, those are - Processed in the previous step of this migration - */ - AND NOT EXISTS ( - SELECT true - FROM projects - WHERE projects.id = forked_project_links.forked_from_project_id - ) - AND forked_project_links.id BETWEEN #{start_id} AND #{end_id} - INSERT_NETWORKS - end - - def create_fork_networks_memberships_for_root_projects(start_id, end_id) - log("Creating memberships for root projects: #{start_id} - #{end_id}") - - ActiveRecord::Base.connection.execute <<~INSERT_ROOT - INSERT INTO fork_network_members (fork_network_id, project_id) - SELECT DISTINCT fork_networks.id, fork_networks.root_project_id - - FROM fork_networks - - /* Joining both on forked_from- and forked_to- so we could create the - memberships for forks for which the source was deleted - */ - INNER JOIN forked_project_links - ON forked_project_links.forked_from_project_id = fork_networks.root_project_id - OR forked_project_links.forked_to_project_id = fork_networks.root_project_id - - WHERE NOT EXISTS ( - SELECT true - FROM fork_network_members - WHERE fork_network_members.project_id = fork_networks.root_project_id - ) - AND forked_project_links.id BETWEEN #{start_id} AND #{end_id} - INSERT_ROOT - end - - def log(message) - Rails.logger.info("#{self.class.name} - #{message}") - end - end - end -end diff --git a/lib/gitlab/background_migration/populate_merge_requests_latest_merge_request_diff_id.rb b/lib/gitlab/background_migration/populate_merge_requests_latest_merge_request_diff_id.rb deleted file mode 100644 index dcac355e1b0..00000000000 --- a/lib/gitlab/background_migration/populate_merge_requests_latest_merge_request_diff_id.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true -# rubocop:disable Style/Documentation - -module Gitlab - module BackgroundMigration - class PopulateMergeRequestsLatestMergeRequestDiffId - BATCH_SIZE = 1_000 - - class MergeRequest < ActiveRecord::Base - self.table_name = 'merge_requests' - - include ::EachBatch - end - - def perform(start_id, stop_id) - update = ' - latest_merge_request_diff_id = ( - SELECT MAX(id) - FROM merge_request_diffs - WHERE merge_requests.id = merge_request_diffs.merge_request_id - )'.squish - - MergeRequest - .where(id: start_id..stop_id) - .where(latest_merge_request_diff_id: nil) - .each_batch(of: BATCH_SIZE) do |relation| - - relation.update_all(update) - end - end - end - end -end diff --git a/lib/tasks/migrate/setup_postgresql.rake b/lib/tasks/migrate/setup_postgresql.rake index f69d204c579..cda88c130bb 100644 --- a/lib/tasks/migrate/setup_postgresql.rake +++ b/lib/tasks/migrate/setup_postgresql.rake @@ -1,23 +1,9 @@ desc 'GitLab | Sets up PostgreSQL' task setup_postgresql: :environment do - require Rails.root.join('db/migrate/20151007120511_namespaces_projects_path_lower_indexes') - require Rails.root.join('db/migrate/20151008110232_add_users_lower_username_email_indexes') - require Rails.root.join('db/migrate/20161212142807_add_lower_path_index_to_routes') - require Rails.root.join('db/migrate/20170317203554_index_routes_path_for_like') - require Rails.root.join('db/migrate/20170724214302_add_lower_path_index_to_redirect_routes') - require Rails.root.join('db/migrate/20170503185032_index_redirect_routes_path_for_like') - require Rails.root.join('db/migrate/20171220191323_add_index_on_namespaces_lower_name.rb') require Rails.root.join('db/migrate/20180215181245_users_name_lower_index.rb') require Rails.root.join('db/migrate/20180504195842_project_name_lower_index.rb') require Rails.root.join('db/post_migrate/20180306164012_add_path_index_to_redirect_routes.rb') - NamespacesProjectsPathLowerIndexes.new.up - AddUsersLowerUsernameEmailIndexes.new.up - AddLowerPathIndexToRoutes.new.up - IndexRoutesPathForLike.new.up - AddLowerPathIndexToRedirectRoutes.new.up - IndexRedirectRoutesPathForLike.new.up - AddIndexOnNamespacesLowerName.new.up UsersNameLowerIndex.new.up ProjectNameLowerIndex.new.up AddPathIndexToRedirectRoutes.new.up |