diff options
author | Sean McGivern <sean@mcgivern.me.uk> | 2017-11-23 17:01:47 +0000 |
---|---|---|
committer | Sean McGivern <sean@mcgivern.me.uk> | 2017-11-23 17:01:47 +0000 |
commit | dd11f0e053688fdec404b43ddf97d105e7d02f14 (patch) | |
tree | ed881fe574041287fd8d120e8b6c9c08115c29c7 | |
parent | d22c885743510d5bdc990d7224489ea8e4156f2c (diff) | |
parent | 7a1e93d35b7280db8bc4128862c86223d76a8d6d (diff) | |
download | gitlab-ce-dd11f0e053688fdec404b43ddf97d105e7d02f14.tar.gz |
Merge branch 'dm-cleanup-fetch-and-mirror-methods' into 'master'
Clean up repository fetch and mirror methods
See merge request gitlab-org/gitlab-ce!15424
-rw-r--r-- | app/models/repository.rb | 21 | ||||
-rw-r--r-- | app/services/projects/import_service.rb | 20 | ||||
-rw-r--r-- | lib/gitlab/git/repository.rb | 10 | ||||
-rw-r--r-- | lib/gitlab/git/repository_mirroring.rb | 53 | ||||
-rw-r--r-- | lib/gitlab/github_import.rb | 4 | ||||
-rw-r--r-- | lib/gitlab/github_import/importer/repository_importer.rb | 17 | ||||
-rw-r--r-- | lib/gitlab/legacy_github_import/importer.rb | 4 | ||||
-rw-r--r-- | spec/lib/gitlab/git/repository_spec.rb | 25 | ||||
-rw-r--r-- | spec/lib/gitlab/github_import/importer/repository_importer_spec.rb | 41 |
9 files changed, 77 insertions, 118 deletions
diff --git a/app/models/repository.rb b/app/models/repository.rb index d4ffd7bfc07..165dafd83fd 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -966,6 +966,19 @@ class Repository run_git(args).first.lines.map(&:strip) end + def fetch_as_mirror(url, forced: false, refmap: :all_refs, remote_name: nil) + unless remote_name + remote_name = "tmp-#{SecureRandom.hex}" + tmp_remote_name = true + end + + add_remote(remote_name, url) + set_remote_as_mirror(remote_name, refmap: refmap) + fetch_remote(remote_name, forced: forced) + ensure + remove_remote(remote_name) if tmp_remote_name + end + def fetch_remote(remote, forced: false, ssh_auth: nil, no_tags: false) gitlab_shell.fetch_remote(raw_repository, remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags) end @@ -1063,6 +1076,10 @@ class Repository raw_repository.fetch_ref(source_repository.raw_repository, source_ref: source_ref, target_ref: target_ref) end + def repository_storage_path + @project.repository_storage_path + end + private # TODO Generice finder, later split this on finders by Ref or Oid @@ -1128,10 +1145,6 @@ class Repository raw_repository.run_git_with_timeout(args, Gitlab::Git::Popen::FAST_GIT_PROCESS_TIMEOUT).first.strip end - def repository_storage_path - @project.repository_storage_path - end - def initialize_raw_repository Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', Gitlab::GlRepository.gl_repository(project, is_wiki)) end diff --git a/app/services/projects/import_service.rb b/app/services/projects/import_service.rb index c3b11341b4d..f2d676af5c3 100644 --- a/app/services/projects/import_service.rb +++ b/app/services/projects/import_service.rb @@ -51,10 +51,13 @@ module Projects def import_repository begin - if project.gitea_import? - fetch_repository + refmap = importer_class.try(:refmap) if has_importer? + + if refmap + project.ensure_repository + project.repository.fetch_as_mirror(project.import_url, refmap: refmap) else - clone_repository + gitlab_shell.import_repository(project.repository_storage_path, project.disk_path, project.import_url) end rescue Gitlab::Shell::Error, Gitlab::Git::RepositoryMirroring::RemoteError => e # Expire cache to prevent scenarios such as: @@ -66,17 +69,6 @@ module Projects end end - def clone_repository - gitlab_shell.import_repository(project.repository_storage_path, project.disk_path, project.import_url) - end - - def fetch_repository - project.ensure_repository - project.repository.add_remote(project.import_type, project.import_url) - project.repository.set_remote_as_mirror(project.import_type) - project.repository.fetch_remote(project.import_type, forced: true) - end - def import_data return unless has_importer? diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index ff408c0c4dd..a6e7c410bdd 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1150,10 +1150,12 @@ module Gitlab @has_visible_content = has_local_branches? end - def fetch(remote = 'origin') - args = %W(#{Gitlab.config.git.bin_path} fetch #{remote}) - - popen(args, @path).last.zero? + # Like all public `Gitlab::Git::Repository` methods, this method is part + # of `Repository`'s interface through `method_missing`. + # `Repository` has its own `fetch_remote` which uses `gitlab-shell` and + # takes some extra attributes, so we qualify this method name to prevent confusion. + def fetch_remote_without_shell(remote = 'origin') + run_git(['fetch', remote]).last.zero? end def blob_at(sha, path) diff --git a/lib/gitlab/git/repository_mirroring.rb b/lib/gitlab/git/repository_mirroring.rb index 4500482d68f..392bef69e80 100644 --- a/lib/gitlab/git/repository_mirroring.rb +++ b/lib/gitlab/git/repository_mirroring.rb @@ -1,38 +1,47 @@ module Gitlab module Git module RepositoryMirroring - IMPORT_HEAD_REFS = '+refs/heads/*:refs/heads/*'.freeze - IMPORT_TAG_REFS = '+refs/tags/*:refs/tags/*'.freeze - MIRROR_REMOTE = 'mirror'.freeze + REFMAPS = { + # With `:all_refs`, the repository is equivalent to the result of `git clone --mirror` + all_refs: '+refs/*:refs/*', + heads: '+refs/heads/*:refs/heads/*', + tags: '+refs/tags/*:refs/tags/*' + }.freeze RemoteError = Class.new(StandardError) - def set_remote_as_mirror(remote_name) - # This is used to define repository as equivalent as "git clone --mirror" - rugged.config["remote.#{remote_name}.fetch"] = 'refs/*:refs/*' - rugged.config["remote.#{remote_name}.mirror"] = true - rugged.config["remote.#{remote_name}.prune"] = true - end - - def set_import_remote_as_mirror(remote_name) - # Add first fetch with Rugged so it does not create its own. - rugged.config["remote.#{remote_name}.fetch"] = IMPORT_HEAD_REFS - - add_remote_fetch_config(remote_name, IMPORT_TAG_REFS) + def set_remote_as_mirror(remote_name, refmap: :all_refs) + set_remote_refmap(remote_name, refmap) rugged.config["remote.#{remote_name}.mirror"] = true rugged.config["remote.#{remote_name}.prune"] = true end - def add_remote_fetch_config(remote_name, refspec) - run_git(%W[config --add remote.#{remote_name}.fetch #{refspec}]) + def set_remote_refmap(remote_name, refmap) + Array(refmap).each_with_index do |refspec, i| + refspec = REFMAPS[refspec] || refspec + + # We need multiple `fetch` entries, but Rugged only allows replacing a config, not adding to it. + # To make sure we start from scratch, we set the first using rugged, and use `git` for any others + if i == 0 + rugged.config["remote.#{remote_name}.fetch"] = refspec + else + run_git(%W[config --add remote.#{remote_name}.fetch #{refspec}]) + end + end end - def fetch_mirror(url) - add_remote(MIRROR_REMOTE, url) - set_remote_as_mirror(MIRROR_REMOTE) - fetch(MIRROR_REMOTE) - remove_remote(MIRROR_REMOTE) + # Like all_refs public `Gitlab::Git::Repository` methods, this method is part + # of `Repository`'s interface through `method_missing`. + # `Repository` has its own `fetch_as_mirror` which uses `gitlab-shell` and + # takes some extra attributes, so we qualify this method name to prevent confusion. + def fetch_as_mirror_without_shell(url) + remote_name = "tmp-#{SecureRandom.hex}" + add_remote(remote_name, url) + set_remote_as_mirror(remote_name) + fetch_remote_without_shell(remote_name) + ensure + remove_remote(remote_name) if remote_name end def remote_tags(remote) diff --git a/lib/gitlab/github_import.rb b/lib/gitlab/github_import.rb index d2ae4c1255e..65b5e30c70f 100644 --- a/lib/gitlab/github_import.rb +++ b/lib/gitlab/github_import.rb @@ -1,5 +1,9 @@ module Gitlab module GithubImport + def self.refmap + [:heads, :tags, '+refs/pull/*/head:refs/merge-requests/*/head'] + end + def self.new_client_for(project, token: nil, parallel: true) token_to_use = token || project.import_data&.credentials&.fetch(:user) diff --git a/lib/gitlab/github_import/importer/repository_importer.rb b/lib/gitlab/github_import/importer/repository_importer.rb index 0b67fc8db73..9cf2e7fd871 100644 --- a/lib/gitlab/github_import/importer/repository_importer.rb +++ b/lib/gitlab/github_import/importer/repository_importer.rb @@ -45,27 +45,14 @@ module Gitlab def import_repository project.ensure_repository - configure_repository_remote - - project.repository.fetch_remote('github', forced: true) + refmap = Gitlab::GithubImport.refmap + project.repository.fetch_as_mirror(project.import_url, refmap: refmap, forced: true, remote_name: 'github') true rescue Gitlab::Git::Repository::NoRepository, Gitlab::Shell::Error => e fail_import("Failed to import the repository: #{e.message}") end - def configure_repository_remote - return if project.repository.remote_exists?('github') - - project.repository.add_remote('github', project.import_url) - project.repository.set_import_remote_as_mirror('github') - - project.repository.add_remote_fetch_config( - 'github', - '+refs/pull/*/head:refs/merge-requests/*/head' - ) - end - def import_wiki_repository wiki_path = "#{project.disk_path}.wiki" wiki_url = project.import_url.sub(/\.git\z/, '.wiki.git') diff --git a/lib/gitlab/legacy_github_import/importer.rb b/lib/gitlab/legacy_github_import/importer.rb index 4d096e5a741..0526ef9eb13 100644 --- a/lib/gitlab/legacy_github_import/importer.rb +++ b/lib/gitlab/legacy_github_import/importer.rb @@ -3,6 +3,10 @@ module Gitlab class Importer include Gitlab::ShellAdapter + def self.refmap + Gitlab::GithubImport.refmap + end + attr_reader :errors, :project, :repo, :repo_url def initialize(project) diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 9da33b94c5e..2f49bd1bcf2 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -588,12 +588,12 @@ describe Gitlab::Git::Repository, seed_helper: true do end end - describe '#fetch_mirror' do + describe '#fetch_as_mirror_without_shell' do let(:new_repository) do Gitlab::Git::Repository.new('default', 'my_project.git', '') end - subject { new_repository.fetch_mirror(repository.path) } + subject { new_repository.fetch_as_mirror_without_shell(repository.path) } before do Gitlab::Shell.new.add_repository('default', 'my_project') @@ -1652,15 +1652,15 @@ describe Gitlab::Git::Repository, seed_helper: true do end end - describe '#fetch' do + describe '#fetch_remote_without_shell' do let(:git_path) { Gitlab.config.git.bin_path } let(:remote_name) { 'my_remote' } - subject { repository.fetch(remote_name) } + subject { repository.fetch_remote_without_shell(remote_name) } it 'fetches the remote and returns true if the command was successful' do expect(repository).to receive(:popen) - .with(%W(#{git_path} fetch #{remote_name}), repository.path) + .with(%W(#{git_path} fetch #{remote_name}), repository.path, {}) .and_return(['', 0]) expect(subject).to be(true) @@ -1777,21 +1777,6 @@ describe Gitlab::Git::Repository, seed_helper: true do end end - describe '#fetch' do - let(:git_path) { Gitlab.config.git.bin_path } - let(:remote_name) { 'my_remote' } - - subject { repository.fetch(remote_name) } - - it 'fetches the remote and returns true if the command was successful' do - expect(repository).to receive(:popen) - .with(%W(#{git_path} fetch #{remote_name}), repository.path) - .and_return(['', 0]) - - expect(subject).to be(true) - end - end - describe '#delete_all_refs_except' do let(:repository) do Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') diff --git a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb index 80539807711..168e5d07504 100644 --- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb @@ -164,12 +164,9 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do expect(project) .to receive(:ensure_repository) - expect(importer) - .to receive(:configure_repository_remote) - expect(repository) - .to receive(:fetch_remote) - .with('github', forced: true) + .to receive(:fetch_as_mirror) + .with(project.import_url, refmap: Gitlab::GithubImport.refmap, forced: true, remote_name: 'github') expect(importer.import_repository).to eq(true) end @@ -186,40 +183,6 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do end end - describe '#configure_repository_remote' do - it 'configures the remote details' do - expect(repository) - .to receive(:remote_exists?) - .with('github') - .and_return(false) - - expect(repository) - .to receive(:add_remote) - .with('github', 'foo.git') - - expect(repository) - .to receive(:set_import_remote_as_mirror) - .with('github') - - expect(repository) - .to receive(:add_remote_fetch_config) - - importer.configure_repository_remote - end - - it 'does not configure the remote if already configured' do - expect(repository) - .to receive(:remote_exists?) - .with('github') - .and_return(true) - - expect(repository) - .not_to receive(:add_remote) - - importer.configure_repository_remote - end - end - describe '#import_wiki_repository' do it 'imports the wiki repository' do expect(importer.gitlab_shell) |