Commit 2a246d83 authored by Toon Claes's avatar Toon Claes Committed by Nick Thomas
Browse files

Store hashed storage paths in the database

parent 1c1f74492a9d
# frozen_string_literal: true
module Shardable
extend ActiveSupport::Concern
included do
belongs_to :shard
validates :shard, presence: true
end
def shard_name
shard&.name
end
def shard_name=(name)
self.shard = Shard.by_name(name)
end
end
# frozen_string_literal: true
class PoolRepository < ActiveRecord::Base
belongs_to :shard
validates :shard, presence: true
include Shardable
has_many :member_projects, class_name: 'Project'
after_create :correct_disk_path
def shard_name
shard&.name
end
def shard_name=(name)
self.shard = Shard.by_name(name)
end
private
def correct_disk_path
......
......@@ -186,6 +186,7 @@ class Project < ActiveRecord::Base
has_one :import_state, autosave: true, class_name: 'ProjectImportState', inverse_of: :project
has_one :import_export_upload, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_one :project_repository, inverse_of: :project
# Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
......@@ -1206,6 +1207,13 @@ def check_repository_path_availability
false
end
def track_project_repository
return unless hashed_storage?(:repository)
project_repo = project_repository || build_project_repository
project_repo.update!(shard_name: repository_storage, disk_path: disk_path)
end
def create_repository(force: false)
# Forked import is handled asynchronously
return if forked? && !force
......
# frozen_string_literal: true
class ProjectRepository < ActiveRecord::Base
include Shardable
belongs_to :project, inverse_of: :project_repository
class << self
def find_project(disk_path)
find_by(disk_path: disk_path)&.project
end
end
end
......@@ -86,6 +86,8 @@ def after_create_actions
@project.create_wiki unless skip_wiki?
end
@project.track_project_repository
event_service.create_project(@project, current_user)
system_hook_service.execute_hooks_for(@project, :create)
......
......@@ -30,6 +30,7 @@ def execute
if result
project.write_repository_config
project.track_project_repository
else
rollback_folder_move
project.storage_version = nil
......
---
title: Add model and relation to store repo full path in database
merge_request: 23143
author:
type: added
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class CreateProjectRepositories < ActiveRecord::Migration[5.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
create_table :project_repositories, id: :bigserial do |t|
t.references :shard, null: false, index: true, foreign_key: { on_delete: :restrict }
t.string :disk_path, null: false, index: { unique: true }
t.references :project, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
end
end
end
......@@ -1601,6 +1601,15 @@
t.index ["status"], name: "index_project_mirror_data_on_status", using: :btree
end
create_table "project_repositories", id: :bigserial, force: :cascade do |t|
t.integer "shard_id", null: false
t.string "disk_path", null: false
t.integer "project_id", null: false
t.index ["disk_path"], name: "index_project_repositories_on_disk_path", unique: true, using: :btree
t.index ["project_id"], name: "index_project_repositories_on_project_id", unique: true, using: :btree
t.index ["shard_id"], name: "index_project_repositories_on_shard_id", using: :btree
end
create_table "project_statistics", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "namespace_id", null: false
......@@ -2385,6 +2394,8 @@
add_foreign_key "project_group_links", "projects", name: "fk_daa8cee94c", on_delete: :cascade
add_foreign_key "project_import_data", "projects", name: "fk_ffb9ee3a10", on_delete: :cascade
add_foreign_key "project_mirror_data", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "projects", on_delete: :cascade
add_foreign_key "project_repositories", "shards", on_delete: :restrict
add_foreign_key "project_statistics", "projects", on_delete: :cascade
add_foreign_key "projects", "pool_repositories", name: "fk_6e5c14658a", on_delete: :nullify
add_foreign_key "prometheus_metrics", "projects", on_delete: :cascade
......
......@@ -245,6 +245,7 @@ project:
- protected_branches
- protected_tags
- project_members
- project_repository
- users
- requesters
- deploy_keys_projects
......
# frozen_string_literal: true
require 'spec_helper'
describe PoolRepository do
......
# frozen_string_literal: true
require 'spec_helper'
describe ProjectRepository do
describe 'associations' do
it { is_expected.to belong_to(:shard) }
it { is_expected.to belong_to(:project) }
end
describe '.find_project' do
it 'finds project by disk path' do
project = create(:project)
project.track_project_repository
expect(described_class.find_project(project.disk_path)).to eq(project)
end
it 'returns nil when it does not find the project' do
expect(described_class.find_project('@@unexisting/path/to/project')).to be_nil
end
end
end
......@@ -54,6 +54,7 @@
it { is_expected.to have_one(:gitlab_issue_tracker_service) }
it { is_expected.to have_one(:external_wiki_service) }
it { is_expected.to have_one(:project_feature) }
it { is_expected.to have_one(:project_repository) }
it { is_expected.to have_one(:statistics).class_name('ProjectStatistics') }
it { is_expected.to have_one(:import_data).class_name('ProjectImportData') }
it { is_expected.to have_one(:last_event).class_name('Event') }
......@@ -1618,6 +1619,30 @@ def create_pipeline
end
end
describe '#track_project_repository' do
let(:project) { create(:project, :repository) }
it 'creates a project_repository' do
project.track_project_repository
expect(project.reload.project_repository).to be_present
expect(project.project_repository.disk_path).to eq(project.disk_path)
expect(project.project_repository.shard_name).to eq(project.repository_storage)
end
it 'updates the project_repository' do
project.track_project_repository
allow(project).to receive(:disk_path).and_return('@fancy/new/path')
expect do
project.track_project_repository
end.not_to change(ProjectRepository, :count)
expect(project.reload.project_repository.disk_path).to eq(project.disk_path)
end
end
describe '#create_repository' do
let(:project) { create(:project, :repository) }
let(:shell) { Gitlab::Shell.new }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment