Commit 82b6e537 authored by Stan Hu's avatar Stan Hu

Send project name with Gitaly repository requests

When hashed storage is in use, it's helpful to have the project
name associated with the request.

Closes https://gitlab.com/gitlab-org/gitaly/issues/1394
parent d8e24e9d
......@@ -96,7 +96,8 @@ def object_pool
@object_pool ||= Gitlab::Git::ObjectPool.new(
shard.name,
disk_path + '.git',
source_project.repository.raw)
source_project.repository.raw,
source_project.path_with_namespace)
end
def inspect
......
......@@ -1288,7 +1288,7 @@ def create_repository(force: false)
# Forked import is handled asynchronously
return if forked? && !force
if gitlab_shell.create_repository(repository_storage, disk_path)
if gitlab_shell.create_repository(repository_storage, disk_path, full_path)
repository.after_create
true
else
......
......@@ -60,7 +60,7 @@ def wiki_base_path
def wiki
@wiki ||= begin
gl_repository = Gitlab::GlRepository.gl_repository(project, true)
raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository)
raw_repository = Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', gl_repository, full_path)
create_repo!(raw_repository) unless raw_repository.exists?
......@@ -175,7 +175,7 @@ def hook_attrs
private
def create_repo!(raw_repository)
gitlab_shell.create_repository(project.repository_storage, disk_path)
gitlab_shell.create_repository(project.repository_storage, disk_path, project.full_path)
raise CouldNotCreateWikiError unless raw_repository.exists?
......
......@@ -1104,6 +1104,9 @@ def repository_event(event, tags = {})
end
def initialize_raw_repository
Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', Gitlab::GlRepository.gl_repository(project, is_wiki))
Gitlab::Git::Repository.new(project.repository_storage,
disk_path + '.git',
Gitlab::GlRepository.gl_repository(project, is_wiki),
project.full_path)
end
end
......@@ -73,7 +73,7 @@ def import_repository
project.ensure_repository
project.repository.fetch_as_mirror(project.import_url, refmap: refmap)
else
gitlab_shell.import_repository(project.repository_storage, project.disk_path, project.import_url)
gitlab_shell.import_repository(project.repository_storage, project.disk_path, project.import_url, project.full_path)
end
rescue Gitlab::Shell::Error => e
# Expire cache to prevent scenarios such as:
......
......@@ -15,19 +15,21 @@ def perform(*args)
return target_project.import_state.mark_as_failed(_('Source project cannot be found.'))
end
fork_repository(target_project, source_project.repository_storage, source_project.disk_path)
fork_repository(target_project, source_project)
end
private
def fork_repository(target_project, source_repository_storage_name, source_disk_path)
def fork_repository(target_project, source_project)
return unless start_fork(target_project)
Gitlab::Metrics.add_event(:fork_repository)
result = gitlab_shell.fork_repository(source_repository_storage_name, source_disk_path,
target_project.repository_storage, target_project.disk_path)
raise "Unable to fork project #{target_project.id} for repository #{source_disk_path} -> #{target_project.disk_path}" unless result
result = gitlab_shell.fork_repository(
source_project.repository_storage, source_project.disk_path, source_project.full_path,
target_project.repository_storage, target_project.disk_path, target_project.full_path)
raise "Unable to fork project #{target_project.id} for repository #{source_project.disk_path} -> #{target_project.disk_path}" unless result
target_project.after_import
end
......
......@@ -11,7 +11,7 @@ def up
path = File.join(namespace_path, project['project_path'] + '.git')
begin
repo = Gitlab::Git::Repository.new('default', path, '')
repo = Gitlab::Git::Repository.new('default', path, '', '')
if repo.empty?
print '-'
else
......
......@@ -93,7 +93,7 @@ def restore
progress.puts "Error: #{e}".color(:red)
end
else
restore_repo_success = gitlab_shell.create_repository(project.repository_storage, project.disk_path)
restore_repo_success = gitlab_shell.create_repository(project.repository_storage, project.disk_path, project.full_path)
end
if restore_repo_success
......
......@@ -67,7 +67,7 @@ def import_wiki
disk_path = project.wiki.disk_path
import_url = project.import_url.sub(/\.git\z/, ".git/wiki")
gitlab_shell.import_repository(project.repository_storage, disk_path, import_url)
gitlab_shell.import_repository(project.repository_storage, disk_path, import_url, project.full_path)
rescue StandardError => e
errors << { type: :wiki, errors: e.message }
end
......
......@@ -10,12 +10,13 @@ class ObjectPool
delegate :exists?, :size, to: :repository
delegate :unlink_repository, :delete, to: :object_pool_service
attr_reader :storage, :relative_path, :source_repository
attr_reader :storage, :relative_path, :source_repository, :gl_project_name
def initialize(storage, relative_path, source_repository)
def initialize(storage, relative_path, source_repository, gl_project_name)
@storage = storage
@relative_path = relative_path
@source_repository = source_repository
@gl_project_name = gl_project_name
end
def create
......@@ -31,12 +32,12 @@ def gitaly_object_pool
end
def to_gitaly_repository
Gitlab::GitalyClient::Util.repository(storage, relative_path, GL_REPOSITORY)
Gitlab::GitalyClient::Util.repository(storage, relative_path, GL_REPOSITORY, gl_project_name)
end
# Allows for reusing other RPCs by 'tricking' Gitaly to think its a repository
def repository
@repository ||= Gitlab::Git::Repository.new(storage, relative_path, GL_REPOSITORY)
@repository ||= Gitlab::Git::Repository.new(storage, relative_path, GL_REPOSITORY, gl_project_name)
end
private
......
......@@ -67,7 +67,7 @@ def create_hooks(repo_path, global_hooks_path)
# Relative path of repo
attr_reader :relative_path
attr_reader :storage, :gl_repository, :relative_path
attr_reader :storage, :gl_repository, :relative_path, :gl_project_name
# This remote name has to be stable for all types of repositories that
# can join an object pool. If it's structure ever changes, a migration
......@@ -78,10 +78,11 @@ def create_hooks(repo_path, global_hooks_path)
# This initializer method is only used on the client side (gitlab-ce).
# Gitaly-ruby uses a different initializer.
def initialize(storage, relative_path, gl_repository)
def initialize(storage, relative_path, gl_repository, gl_project_name)
@storage = storage
@relative_path = relative_path
@gl_repository = gl_repository
@gl_project_name = gl_project_name
@name = @relative_path.split("/").last
end
......@@ -872,7 +873,7 @@ def delete_config(*keys)
end
def gitaly_repository
Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository)
Gitlab::GitalyClient::Util.repository(@storage, @relative_path, @gl_repository, @gl_project_name)
end
def gitaly_ref_client
......
......@@ -4,7 +4,7 @@ module Gitlab
module GitalyClient
module Util
class << self
def repository(repository_storage, relative_path, gl_repository)
def repository(repository_storage, relative_path, gl_repository, gl_project_name)
git_env = Gitlab::Git::HookEnv.all(gl_repository)
git_object_directory = git_env['GIT_OBJECT_DIRECTORY_RELATIVE'].presence
git_alternate_object_directories = Array.wrap(git_env['GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE'])
......@@ -14,14 +14,16 @@ def repository(repository_storage, relative_path, gl_repository)
relative_path: relative_path,
gl_repository: gl_repository.to_s,
git_object_directory: git_object_directory.to_s,
git_alternate_object_directories: git_alternate_object_directories
git_alternate_object_directories: git_alternate_object_directories,
gl_project_name: gl_project_name
)
end
def git_repository(gitaly_repository)
Gitlab::Git::Repository.new(gitaly_repository.storage_name,
gitaly_repository.relative_path,
gitaly_repository.gl_repository)
gitaly_repository.gl_repository,
gitaly_repository.gl_project_name)
end
end
end
......
......@@ -59,7 +59,7 @@ def import_repository
def import_wiki_repository
wiki_path = "#{project.disk_path}.wiki"
gitlab_shell.import_repository(project.repository_storage, wiki_path, wiki_url)
gitlab_shell.import_repository(project.repository_storage, wiki_path, wiki_url, project.full_path)
true
rescue Gitlab::Shell::Error => e
......
......@@ -267,7 +267,7 @@ def discard_inserted_comments(comments, last_note)
def import_wiki
unless project.wiki.repository_exists?
wiki = WikiFormatter.new(project)
gitlab_shell.import_repository(project.repository_storage, wiki.disk_path, wiki.import_url)
gitlab_shell.import_repository(project.repository_storage, wiki.disk_path, wiki.import_url, project.wiki.full_path)
end
rescue Gitlab::Shell::Error => e
# GitHub error message when the wiki repo has not been created,
......
......@@ -68,15 +68,16 @@ def generate_and_link_secret_token
#
# storage - the shard key
# name - project disk path
# gl_project_name - project name
#
# Ex.
# create_repository("default", "gitlab/gitlab-ci")
# create_repository("default", "path/to/gitlab-ci", "gitlab/gitlab-ci")
#
def create_repository(storage, name)
def create_repository(storage, name, gl_project_name)
relative_path = name.dup
relative_path << '.git' unless relative_path.end_with?('.git')
repository = Gitlab::Git::Repository.new(storage, relative_path, '')
repository = Gitlab::Git::Repository.new(storage, relative_path, '', gl_project_name)
wrapped_gitaly_errors { repository.gitaly_repository_client.create_repository }
true
......@@ -94,13 +95,13 @@ def create_repository(storage, name)
# Ex.
# import_repository("nfs-file06", "gitlab/gitlab-ci", "https://gitlab.com/gitlab-org/gitlab-test.git")
#
def import_repository(storage, name, url)
def import_repository(storage, name, url, gl_project_name)
if url.start_with?('.', '/')
raise Error.new("don't use disk paths with import_repository: #{url.inspect}")
end
relative_path = "#{name}.git"
cmd = GitalyGitlabProjects.new(storage, relative_path)
cmd = GitalyGitlabProjects.new(storage, relative_path, gl_project_name)
success = cmd.import_project(url, git_timeout)
raise Error, cmd.output unless success
......@@ -132,11 +133,13 @@ def mv_repository(storage, path, new_path)
#
# Ex.
# fork_repository("nfs-file06", "gitlab/gitlab-ci", "nfs-file07", "new-namespace/gitlab-ci")
def fork_repository(forked_from_storage, forked_from_disk_path, forked_to_storage, forked_to_disk_path)
def fork_repository(
forked_from_storage, forked_from_disk_path, forked_from_project_name,
forked_to_storage, forked_to_disk_path, forked_to_project_name)
forked_from_relative_path = "#{forked_from_disk_path}.git"
fork_args = [forked_to_storage, "#{forked_to_disk_path}.git"]
fork_args = [forked_to_storage, "#{forked_to_disk_path}.git", forked_to_project_name]
GitalyGitlabProjects.new(forked_from_storage, forked_from_relative_path).fork_repository(*fork_args)
GitalyGitlabProjects.new(forked_from_storage, forked_from_relative_path, forked_from_project_name).fork_repository(*fork_args)
end
# Removes a repository from file system, using rm_diretory which is an alias
......@@ -397,16 +400,17 @@ def wrapped_gitaly_errors
end
class GitalyGitlabProjects
attr_reader :shard_name, :repository_relative_path, :output
attr_reader :shard_name, :repository_relative_path, :output, :gl_project_name
def initialize(shard_name, repository_relative_path)
def initialize(shard_name, repository_relative_path, gl_project_name)
@shard_name = shard_name
@repository_relative_path = repository_relative_path
@output = ''
@gl_project_name = gl_project_name
end
def import_project(source, _timeout)
raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil)
raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil, gl_project_name)
Gitlab::GitalyClient::RepositoryService.new(raw_repository).import_repository(source)
true
......@@ -415,9 +419,9 @@ def import_project(source, _timeout)
false
end
def fork_repository(new_shard_name, new_repository_relative_path)
target_repository = Gitlab::Git::Repository.new(new_shard_name, new_repository_relative_path, nil)
raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil)
def fork_repository(new_shard_name, new_repository_relative_path, new_project_name)
target_repository = Gitlab::Git::Repository.new(new_shard_name, new_repository_relative_path, nil, new_project_name)
raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil, gl_project_name)
Gitlab::GitalyClient::RepositoryService.new(target_repository).fork_repository(raw_repository)
rescue GRPC::BadStatus => e
......
......@@ -61,7 +61,7 @@
let(:wiki_path) { File.join(root_path, "#{hashed_path}.wiki.git") }
before do
gitlab_shell.create_repository(repository_storage, hashed_path)
gitlab_shell.create_repository(repository_storage, hashed_path, 'group/project')
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
repository = Rugged::Repository.new(repo_path)
repository.config['gitlab.fullpath'] = 'to/repo'
......
......@@ -230,7 +230,8 @@
expect(importer.gitlab_shell).to receive(:import_repository).with(
project.repository_storage,
project.wiki.disk_path,
project.import_url + '/wiki'
project.import_url + '/wiki',
project.full_path
)
importer.execute
......
......@@ -2,7 +2,7 @@
require "spec_helper"
describe Gitlab::Git::Blame, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:blame) do
Gitlab::Git::Blame.new(repository, SeedRepo::Commit::ID, "CONTRIBUTING.md")
end
......
......@@ -3,7 +3,7 @@
require "spec_helper"
describe Gitlab::Git::Blob, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:rugged) do
Rugged::Repository.new(File.join(TestEnv.repos_path, TEST_REPO_PATH))
end
......
require "spec_helper"
describe Gitlab::Git::Branch, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:rugged) do
Rugged::Repository.new(File.join(TestEnv.repos_path, repository.relative_path))
end
......@@ -64,7 +64,7 @@
context 'with active, stale and future branches' do
let(:repository) do
Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project')
end
let(:user) { create(:user) }
......
......@@ -3,7 +3,7 @@
describe Gitlab::Git::Commit, :seed_helper do
include GitHelpers
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:rugged_repo) do
Rugged::Repository.new(File.join(TestEnv.repos_path, TEST_REPO_PATH))
end
......@@ -146,7 +146,7 @@
end
context 'with broken repo' do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_BROKEN_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_BROKEN_REPO_PATH, '', 'group/project') }
it 'returns nil' do
expect(described_class.find(repository, SeedRepo::Commit::ID)).to be_nil
......
require "spec_helper"
describe Gitlab::Git::Compare, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:compare) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: false) }
let(:compare_straight) { Gitlab::Git::Compare.new(repository, SeedRepo::BigCommit::ID, SeedRepo::Commit::ID, straight: true) }
......
require "spec_helper"
describe Gitlab::Git::Diff, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:gitaly_diff) do
Gitlab::GitalyClient::Diff.new(
from_path: '.gitmodules',
......
require 'spec_helper'
describe Gitlab::Git::RemoteRepository, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
subject { described_class.new(repository) }
describe '#empty?' do
using RSpec::Parameterized::TableSyntax
where(:repository, :result) do
Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') | false
Gitlab::Git::Repository.new('default', 'does-not-exist.git', '') | true
Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') | false
Gitlab::Git::Repository.new('default', 'does-not-exist.git', '', 'group/project') | true
end
with_them do
......@@ -44,11 +44,11 @@
using RSpec::Parameterized::TableSyntax
where(:other_repository, :result) do
repository | true
Gitlab::Git::Repository.new(repository.storage, repository.relative_path, '') | true
Gitlab::Git::Repository.new('broken', TEST_REPO_PATH, '') | false
Gitlab::Git::Repository.new(repository.storage, 'wrong/relative-path.git', '') | false
Gitlab::Git::Repository.new('broken', 'wrong/relative-path.git', '') | false
repository | true
Gitlab::Git::Repository.new(repository.storage, repository.relative_path, '', 'group/project') | true
Gitlab::Git::Repository.new('broken', TEST_REPO_PATH, '', 'group/project') | false
Gitlab::Git::Repository.new(repository.storage, 'wrong/relative-path.git', '', 'group/project') | false
Gitlab::Git::Repository.new('broken', 'wrong/relative-path.git', '', 'group/project') | false
end
with_them do
......
......@@ -19,8 +19,8 @@
end
end
let(:mutable_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:mutable_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
let(:repository_path) { File.join(TestEnv.repos_path, repository.relative_path) }
let(:repository_rugged) { Rugged::Repository.new(repository_path) }
let(:storage_path) { TestEnv.repos_path }
......@@ -434,13 +434,13 @@ def submodule_url(path)
describe '#fetch_repository_as_mirror' do
let(:new_repository) do
Gitlab::Git::Repository.new('default', 'my_project.git', '')
Gitlab::Git::Repository.new('default', 'my_project.git', '', 'group/project')
end
subject { new_repository.fetch_repository_as_mirror(repository) }
before do
Gitlab::Shell.new.create_repository('default', 'my_project')
Gitlab::Shell.new.create_repository('default', 'my_project', 'group/project')
end
after do
......@@ -1230,7 +1230,7 @@ def commit_files(commit)
end
describe '#gitattribute' do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_GITATTRIBUTES_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_GITATTRIBUTES_REPO_PATH, '', 'group/project') }
after do
ensure_seeds
......@@ -1249,7 +1249,7 @@ def commit_files(commit)
end
context 'without gitattributes file' do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
it 'returns nil' do
expect(repository.gitattribute("README.md", 'gitlab-language')).to eq(nil)
......@@ -1513,7 +1513,7 @@ def commit_files(commit)
context 'repository does not exist' do
it 'raises NoRepository and does not call Gitaly WriteConfig' do
repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '')
repository = Gitlab::Git::Repository.new('default', 'does/not/exist.git', '', 'group/project')
expect(repository.gitaly_repository_client).not_to receive(:write_config)
......@@ -1803,7 +1803,7 @@ def commit_files(commit)
out: '/dev/null',
err: '/dev/null')
empty_repo = described_class.new('default', 'empty-repo.git', '')
empty_repo = described_class.new('default', 'empty-repo.git', '', 'group/empty-repo')
expect(empty_repo.checksum).to eq '0000000000000000000000000000000000000000'
end
......@@ -1818,13 +1818,13 @@ def commit_files(commit)
File.truncate(File.join(storage_path, 'non-valid.git/HEAD'), 0)
non_valid = described_class.new('default', 'non-valid.git', '')
non_valid = described_class.new('default', 'non-valid.git', '', 'a/non-valid')
expect { non_valid.checksum }.to raise_error(Gitlab::Git::Repository::InvalidRepository)
end
it 'raises Gitlab::Git::Repository::NoRepository error when there is no repo' do
broken_repo = described_class.new('default', 'a/path.git', '')
broken_repo = described_class.new('default', 'a/path.git', '', 'a/path')
expect { broken_repo.checksum }.to raise_error(Gitlab::Git::Repository::NoRepository)
end
......
require "spec_helper"
describe Gitlab::Git::Tag, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
describe '#tags' do
describe 'first tag' do
......
require "spec_helper"
describe Gitlab::Git::Tree, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '', 'group/project') }
context :repo do
let(:tree) { Gitlab::Git::Tree.where(repository, SeedRepo::Commit::ID) }
......
......@@ -33,7 +33,7 @@
end
describe '#fetch_internal_remote' do
let(:remote_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
let(:remote_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project') }
it 'sends an fetch_internal_remote message and returns the result value' do
expect_any_instance_of(Gitaly::RemoteService::Stub)
......
......@@ -7,6 +7,7 @@
let(:gl_repository) { 'project-1' }
let(:git_object_directory) { '.git/objects' }
let(:git_alternate_object_directory) { ['/dir/one', '/dir/two'] }
let(:gl_project_name) { 'namespace/myproject' }
let(:git_env) do
{
'GIT_OBJECT_DIRECTORY_RELATIVE' => git_object_directory,
......@@ -15,7 +16,7 @@
end
subject do
described_class.repository(repository_storage, relative_path, gl_repository)
described_class.repository(repository_storage, relative_path, gl_repository, gl_project_name)
end
it 'creates a Gitaly::Repository with the given data' do
......@@ -27,6 +28,7 @@
expect(subject.gl_repository).to eq(gl_repository)
expect(subject.git_object_directory).to eq(git_object_directory)
expect(subject.git_alternate_object_directories).to eq(git_alternate_object_directory)
expect(subject.gl_project_name).to eq(gl_project_name)
end
end
end
......@@ -15,6 +15,7 @@
repository: repository,
create_wiki: true,