importer_spec.rb 6.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
require 'spec_helper'

describe Gitlab::BareRepositoryImport::Importer, repository: true do
  let!(:admin) { create(:admin) }
  let!(:base_dir) { Dir.mktmpdir + '/' }
  let(:bare_repository) { Gitlab::BareRepositoryImport::Repository.new(base_dir, File.join(base_dir, "#{project_path}.git")) }

  subject(:importer) { described_class.new(admin, bare_repository) }

  before do
    allow(described_class).to receive(:log)
  end

  after do
    FileUtils.rm_rf(base_dir)
  end

  shared_examples 'importing a repository' do
    describe '.execute' do
      it 'creates a project for a repository in storage' do
        FileUtils.mkdir_p(File.join(base_dir, "#{project_path}.git"))
        fake_importer = double

        expect(described_class).to receive(:new).and_return(fake_importer)
        expect(fake_importer).to receive(:create_project_if_needed)

        described_class.execute(base_dir)
      end

      it 'skips wiki repos' do
        repo_dir = File.join(base_dir, 'the-group', 'the-project.wiki.git')
        FileUtils.mkdir_p(File.join(repo_dir))

        expect(described_class).to receive(:log).with(" * Skipping repo #{repo_dir}")
        expect(described_class).not_to receive(:new)

        described_class.execute(base_dir)
      end

      context 'without admin users' do
        let(:admin) { nil }

        it 'raises an error' do
          expect { described_class.execute(base_dir) }.to raise_error(Gitlab::BareRepositoryImport::Importer::NoAdminError)
        end
      end
    end

    describe '#create_project_if_needed' do
      it 'starts an import for a project that did not exist' do
        expect(importer).to receive(:create_project)

        importer.create_project_if_needed
      end

      it 'skips importing when the project already exists' do
        project = create(:project, path: 'a-project', namespace: existing_group)

        expect(importer).not_to receive(:create_project)
        expect(importer).to receive(:log).with(" * #{project.name} (#{project_path}) exists")

        importer.create_project_if_needed
      end

      it 'creates a project with the correct path in the database' do
        importer.create_project_if_needed

        expect(Project.find_by_full_path(project_path)).not_to be_nil
      end

71 72 73 74 75 76
      it 'does not schedule an import' do
        expect_any_instance_of(Project).not_to receive(:import_schedule)

        importer.create_project_if_needed
      end

77
      it 'creates the Git repo on disk with the proper symlink for hooks' do
78
        create_bare_repository("#{project_path}.git")
79 80 81 82

        importer.create_project_if_needed

        project = Project.find_by_full_path(project_path)
83 84
        repo_path = File.join(project.repository_storage_path, project.disk_path + '.git')
        hook_path = File.join(repo_path, 'hooks')
85

86 87 88
        expect(File).to exist(repo_path)
        expect(File.symlink?(hook_path)).to be true
        expect(File.readlink(hook_path)).to eq(Gitlab.config.gitlab_shell.hooks_path)
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
      end

      context 'hashed storage enabled' do
        it 'creates a project with the correct path in the database' do
          stub_application_setting(hashed_storage_enabled: true)

          importer.create_project_if_needed

          expect(Project.find_by_full_path(project_path)).not_to be_nil
        end
      end
    end
  end

  context 'with subgroups', :nested_groups do
    let(:project_path) { 'a-group/a-sub-group/a-project' }

    let(:existing_group) do
      group = create(:group, path: 'a-group')
      create(:group, path: 'a-sub-group', parent: group)
    end

    it_behaves_like 'importing a repository'
  end

  context 'without subgroups' do
    let(:project_path) { 'a-group/a-project' }
    let(:existing_group) { create(:group, path: 'a-group') }

    it_behaves_like 'importing a repository'
  end

  context 'without groups' do
    let(:project_path) { 'a-project' }

    it 'starts an import for a project that did not exist' do
      expect(importer).to receive(:create_project)

      importer.create_project_if_needed
    end

    it 'creates a project with the correct path in the database' do
      importer.create_project_if_needed

      expect(Project.find_by_full_path("#{admin.full_path}/#{project_path}")).not_to be_nil
    end

    it 'creates the Git repo in disk' do
137
      create_bare_repository("#{project_path}.git")
138 139 140 141 142 143

      importer.create_project_if_needed

      project = Project.find_by_full_path("#{admin.full_path}/#{project_path}")

      expect(File).to exist(File.join(project.repository_storage_path, project.disk_path + '.git'))
J
James Lopez 已提交
144
      expect(File).to exist(File.join(project.repository_storage_path, project.disk_path + '.wiki.git'))
145
    end
146 147

    it 'moves an existing project to the correct path' do
148 149 150
      # This is a quick way to get a valid repository instead of copying an
      # existing one. Since it's not persisted, the importer will try to
      # create the project.
151
      project = build(:project, :repository)
152 153 154 155 156 157 158 159 160 161 162
      original_commit_count = project.repository.commit_count

      bare_repo = Gitlab::BareRepositoryImport::Repository.new(project.repository_storage_path, project.repository.path)
      gitlab_importer = described_class.new(admin, bare_repo)

      expect(gitlab_importer).to receive(:create_project).and_call_original

      new_project = gitlab_importer.create_project_if_needed

      expect(new_project.repository.commit_count).to eq(original_commit_count)
    end
163 164 165 166 167 168 169 170 171
  end

  context 'with Wiki' do
    let(:project_path) { 'a-group/a-project' }
    let(:existing_group) { create(:group, path: 'a-group') }

    it_behaves_like 'importing a repository'

    it 'creates the Wiki git repo in disk' do
172 173
      create_bare_repository("#{project_path}.git")
      create_bare_repository("#{project_path}.wiki.git")
174

J
James Lopez 已提交
175
      expect(Projects::CreateService).to receive(:new).with(admin, hash_including(skip_wiki: true,
176
                                                                                  import_type: 'bare_repository')).and_call_original
177

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
      importer.create_project_if_needed

      project = Project.find_by_full_path(project_path)

      expect(File).to exist(File.join(project.repository_storage_path, project.disk_path + '.wiki.git'))
    end
  end

  context 'when subgroups are not available' do
    let(:project_path) { 'a-group/a-sub-group/a-project' }

    before do
      expect(Group).to receive(:supports_nested_groups?) { false }
    end

    describe '#create_project_if_needed' do
      it 'raises an error' do
        expect { importer.create_project_if_needed }.to raise_error('Nested groups are not supported on MySQL')
      end
    end
  end
199 200 201 202 203

  def create_bare_repository(project_path)
    repo_path = File.join(base_dir, project_path)
    Gitlab::Git::Repository.create(repo_path, bare: true)
  end
204
end