Read about our upcoming Code of Conduct on this issue

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 # frozen_string_literal: true
class PoolRepository < ActiveRecord::Base class PoolRepository < ActiveRecord::Base
belongs_to :shard include Shardable
validates :shard, presence: true
has_many :member_projects, class_name: 'Project' has_many :member_projects, class_name: 'Project'
after_create :correct_disk_path after_create :correct_disk_path
def shard_name
shard&.name
end
def shard_name=(name)
self.shard = Shard.by_name(name)
end
private private
def correct_disk_path def correct_disk_path
......
...@@ -186,6 +186,7 @@ class Project < ActiveRecord::Base ...@@ -186,6 +186,7 @@ class Project < ActiveRecord::Base
has_one :import_state, autosave: true, class_name: 'ProjectImportState', inverse_of: :project 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 :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 # Merge Requests for target project should be removed with it
has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
...@@ -1206,6 +1207,13 @@ def check_repository_path_availability ...@@ -1206,6 +1207,13 @@ def check_repository_path_availability
false false
end 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) def create_repository(force: false)
# Forked import is handled asynchronously # Forked import is handled asynchronously
return if forked? && !force 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 ...@@ -86,6 +86,8 @@ def after_create_actions
@project.create_wiki unless skip_wiki? @project.create_wiki unless skip_wiki?
end end
@project.track_project_repository
event_service.create_project(@project, current_user) event_service.create_project(@project, current_user)
system_hook_service.execute_hooks_for(@project, :create) system_hook_service.execute_hooks_for(@project, :create)
......
...@@ -30,6 +30,7 @@ def execute ...@@ -30,6 +30,7 @@ def execute
if result if result
project.write_repository_config project.write_repository_config
project.track_project_repository
else else
rollback_folder_move rollback_folder_move
project.storage_version = nil 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 @@ ...@@ -1601,6 +1601,15 @@
t.index ["status"], name: "index_project_mirror_data_on_status", using: :btree t.index ["status"], name: "index_project_mirror_data_on_status", using: :btree
end 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| create_table "project_statistics", force: :cascade do |t|
t.integer "project_id", null: false t.integer "project_id", null: false
t.integer "namespace_id", null: false t.integer "namespace_id", null: false
...@@ -2385,6 +2394,8 @@ ...@@ -2385,6 +2394,8 @@
add_foreign_key "project_group_links", "projects", name: "fk_daa8cee94c", on_delete: :cascade 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_import_data", "projects", name: "fk_ffb9ee3a10", on_delete: :cascade
add_foreign_key "project_mirror_data", "projects", 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 "project_statistics", "projects", on_delete: :cascade
add_foreign_key "projects", "pool_repositories", name: "fk_6e5c14658a", on_delete: :nullify add_foreign_key "projects", "pool_repositories", name: "fk_6e5c14658a", on_delete: :nullify
add_foreign_key "prometheus_metrics", "projects", on_delete: :cascade add_foreign_key "prometheus_metrics", "projects", on_delete: :cascade
......
...@@ -245,6 +245,7 @@ project: ...@@ -245,6 +245,7 @@ project:
- protected_branches - protected_branches
- protected_tags - protected_tags
- project_members - project_members
- project_repository
- users - users
- requesters - requesters
- deploy_keys_projects - deploy_keys_projects
......
# frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
describe PoolRepository do 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 @@ ...@@ -54,6 +54,7 @@
it { is_expected.to have_one(:gitlab_issue_tracker_service) } 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(:external_wiki_service) }
it { is_expected.to have_one(:project_feature) } 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(:statistics).class_name('ProjectStatistics') }
it { is_expected.to have_one(:import_data).class_name('ProjectImportData') } it { is_expected.to have_one(:import_data).class_name('ProjectImportData') }
it { is_expected.to have_one(:last_event).class_name('Event') } it { is_expected.to have_one(:last_event).class_name('Event') }
...@@ -1618,6 +1619,30 @@ def create_pipeline ...@@ -1618,6 +1619,30 @@ def create_pipeline
end end
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 describe '#create_repository' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
let(:shell) { Gitlab::Shell.new } 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