Migration to write fullpath in all repository configs
In https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/16027 it was added to write `gitlab.fullpath` in the git config of all repositories. But this only writes them on move or migrate to hashed storage. This adds a migration that writes the fullpath to all the repositories. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/41776
This commit is contained in:
parent
6c83c2d8b9
commit
ffdb3f26e7
3 changed files with 211 additions and 0 deletions
5
changelogs/unreleased/tc-backfill-full-path-config.yml
Normal file
5
changelogs/unreleased/tc-backfill-full-path-config.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Migration to write fullpath in all repository configs
|
||||
merge_request: 22322
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,136 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class BackfillStoreProjectFullPathInRepo < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
class Repository
|
||||
attr_reader :storage
|
||||
|
||||
def initialize(storage, relative_path)
|
||||
@storage = storage
|
||||
@relative_path = relative_path
|
||||
end
|
||||
|
||||
def gitaly_repository
|
||||
Gitaly::Repository.new(storage_name: @storage, relative_path: @relative_path)
|
||||
end
|
||||
end
|
||||
|
||||
module Storage
|
||||
class HashedProject
|
||||
attr_accessor :project
|
||||
|
||||
ROOT_PATH_PREFIX = '@hashed'.freeze
|
||||
|
||||
def initialize(project)
|
||||
@project = project
|
||||
end
|
||||
|
||||
def disk_path
|
||||
"#{ROOT_PATH_PREFIX}/#{disk_hash[0..1]}/#{disk_hash[2..3]}/#{disk_hash}"
|
||||
end
|
||||
|
||||
def disk_hash
|
||||
@disk_hash ||= Digest::SHA2.hexdigest(project.id.to_s) if project.id
|
||||
end
|
||||
end
|
||||
|
||||
class LegacyProject
|
||||
attr_accessor :project
|
||||
|
||||
def initialize(project)
|
||||
@project = project
|
||||
end
|
||||
|
||||
def disk_path
|
||||
project.full_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Routable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def full_path
|
||||
@full_path ||= build_full_path
|
||||
end
|
||||
|
||||
def build_full_path
|
||||
if parent && path
|
||||
parent.full_path + '/' + path
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Namespace < ActiveRecord::Base
|
||||
self.table_name = 'namespaces'
|
||||
|
||||
include Routable
|
||||
|
||||
belongs_to :parent, class_name: "Namespace"
|
||||
end
|
||||
|
||||
class Project < ActiveRecord::Base
|
||||
self.table_name = 'projects'
|
||||
|
||||
include Routable
|
||||
include EachBatch
|
||||
|
||||
FULLPATH_CONFIG_KEY = 'gitlab.fullpath'
|
||||
|
||||
belongs_to :namespace
|
||||
delegate :disk_path, to: :storage
|
||||
alias_method :parent, :namespace
|
||||
|
||||
def add_fullpath_config
|
||||
entries = { FULLPATH_CONFIG_KEY => full_path }
|
||||
|
||||
repository_service.set_config(entries)
|
||||
end
|
||||
|
||||
def remove_fullpath_config
|
||||
repository_service.delete_config([FULLPATH_CONFIG_KEY])
|
||||
end
|
||||
|
||||
def storage
|
||||
@storage ||=
|
||||
if hashed_storage?
|
||||
Storage::HashedProject.new(self)
|
||||
else
|
||||
Storage::LegacyProject.new(self)
|
||||
end
|
||||
end
|
||||
|
||||
def hashed_storage?
|
||||
self.storage_version && self.storage_version >= 1
|
||||
end
|
||||
|
||||
def repository
|
||||
@repository ||= Repository.new(repository_storage, disk_path + '.git')
|
||||
end
|
||||
|
||||
def repository_service
|
||||
@repository_service ||= Gitlab::GitalyClient::RepositoryService.new(repository)
|
||||
end
|
||||
end
|
||||
|
||||
def up
|
||||
Project.each_batch do |batch|
|
||||
batch.each do |project|
|
||||
project.add_fullpath_config
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
Project.each_batch do |batch|
|
||||
batch.each do |project|
|
||||
project.remove_fullpath_config
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,70 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
require Rails.root.join('db', 'post_migrate', '20181010133639_backfill_store_project_full_path_in_repo.rb')
|
||||
|
||||
describe BackfillStoreProjectFullPathInRepo, :migration do
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:projects) { table(:projects) }
|
||||
let(:group) { namespaces.create!(name: 'foo', path: 'foo') }
|
||||
let(:subgroup) { namespaces.create!(name: 'bar', path: 'bar', parent_id: group.id) }
|
||||
|
||||
subject(:migration) { described_class.new }
|
||||
|
||||
describe '#up' do
|
||||
shared_examples_for 'writes the full path to git config' do
|
||||
it 'writes the git config' do
|
||||
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService)
|
||||
.to receive(:set_config).with('gitlab.fullpath' => expected_path)
|
||||
|
||||
migration.up
|
||||
end
|
||||
|
||||
context 'legacy storage' do
|
||||
it 'finds the repository at the correct location' do
|
||||
Project.find(project.id).create_repository
|
||||
|
||||
expect { migration.up }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'hashed storage' do
|
||||
it 'finds the repository at the correct location' do
|
||||
project.update_attribute(:storage_version, 1)
|
||||
|
||||
Project.find(project.id).create_repository
|
||||
|
||||
expect { migration.up }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'project in group' do
|
||||
let!(:project) { projects.create!(namespace_id: group.id, name: 'baz', path: 'baz') }
|
||||
let(:expected_path) { 'foo/baz' }
|
||||
|
||||
it_behaves_like 'writes the full path to git config'
|
||||
end
|
||||
|
||||
context 'project in subgroup' do
|
||||
let!(:project) { projects.create!(namespace_id: subgroup.id, name: 'baz', path: 'baz') }
|
||||
let(:expected_path) { 'foo/bar/baz' }
|
||||
|
||||
it_behaves_like 'writes the full path to git config'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#down' do
|
||||
context 'project in group' do
|
||||
let!(:project) { projects.create!(namespace_id: group.id, name: 'baz', path: 'baz') }
|
||||
|
||||
it 'deletes the gitlab full config value' do
|
||||
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService)
|
||||
.to receive(:delete_config).with(['gitlab.fullpath'])
|
||||
|
||||
migration.down
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue