summaryrefslogtreecommitdiff
path: root/db/post_migrate/20161221153951_rename_reserved_project_names.rb
blob: 7e7342d80f9c42d2eb6eee97b7e63774ba083ebd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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