1# frozen_string_literal: true 2 3require 'spec_helper' 4 5RSpec.describe Gitlab::GitalyClient::RepositoryService do 6 using RSpec::Parameterized::TableSyntax 7 8 let(:project) { create(:project) } 9 let(:storage_name) { project.repository_storage } 10 let(:relative_path) { project.disk_path + '.git' } 11 let(:client) { described_class.new(project.repository) } 12 13 describe '#exists?' do 14 it 'sends a repository_exists message' do 15 expect_any_instance_of(Gitaly::RepositoryService::Stub) 16 .to receive(:repository_exists) 17 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 18 .and_return(double(exists: true)) 19 20 client.exists? 21 end 22 end 23 24 describe '#cleanup' do 25 it 'sends a cleanup message' do 26 expect_any_instance_of(Gitaly::RepositoryService::Stub) 27 .to receive(:cleanup) 28 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 29 30 client.cleanup 31 end 32 end 33 34 describe '#garbage_collect' do 35 it 'sends a garbage_collect message' do 36 expect_any_instance_of(Gitaly::RepositoryService::Stub) 37 .to receive(:garbage_collect) 38 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 39 .and_return(double(:garbage_collect_response)) 40 41 client.garbage_collect(true, prune: true) 42 end 43 end 44 45 describe '#repack_full' do 46 it 'sends a repack_full message' do 47 expect_any_instance_of(Gitaly::RepositoryService::Stub) 48 .to receive(:repack_full) 49 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 50 .and_return(double(:repack_full_response)) 51 52 client.repack_full(true) 53 end 54 end 55 56 describe '#repack_incremental' do 57 it 'sends a repack_incremental message' do 58 expect_any_instance_of(Gitaly::RepositoryService::Stub) 59 .to receive(:repack_incremental) 60 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 61 .and_return(double(:repack_incremental_response)) 62 63 client.repack_incremental 64 end 65 end 66 67 describe '#repository_size' do 68 it 'sends a repository_size message' do 69 expect_any_instance_of(Gitaly::RepositoryService::Stub) 70 .to receive(:repository_size) 71 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 72 .and_return(size: 0) 73 74 client.repository_size 75 end 76 end 77 78 describe '#get_object_directory_size' do 79 it 'sends a get_object_directory_size message' do 80 expect_any_instance_of(Gitaly::RepositoryService::Stub) 81 .to receive(:get_object_directory_size) 82 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 83 .and_return(size: 0) 84 85 client.get_object_directory_size 86 end 87 end 88 89 describe '#apply_gitattributes' do 90 let(:revision) { 'master' } 91 92 it 'sends an apply_gitattributes message' do 93 expect_any_instance_of(Gitaly::RepositoryService::Stub) 94 .to receive(:apply_gitattributes) 95 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 96 .and_return(double(:apply_gitattributes_response)) 97 98 client.apply_gitattributes(revision) 99 end 100 end 101 102 describe '#info_attributes' do 103 it 'reads the info attributes' do 104 expect_any_instance_of(Gitaly::RepositoryService::Stub) 105 .to receive(:get_info_attributes) 106 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 107 .and_return([]) 108 109 client.info_attributes 110 end 111 end 112 113 describe '#has_local_branches?' do 114 it 'sends a has_local_branches message' do 115 expect_any_instance_of(Gitaly::RepositoryService::Stub) 116 .to receive(:has_local_branches) 117 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 118 .and_return(double(value: true)) 119 120 expect(client.has_local_branches?).to be(true) 121 end 122 end 123 124 describe '#fetch_remote' do 125 let(:url) { 'https://example.com/git/repo.git' } 126 127 it 'sends a fetch_remote_request message' do 128 expected_request = gitaly_request_with_params( 129 remote_params: Gitaly::Remote.new( 130 url: url, 131 http_authorization_header: "", 132 mirror_refmaps: [] 133 ), 134 ssh_key: '', 135 known_hosts: '', 136 force: false, 137 no_tags: false, 138 no_prune: false, 139 check_tags_changed: false 140 ) 141 142 expect_any_instance_of(Gitaly::RepositoryService::Stub) 143 .to receive(:fetch_remote) 144 .with(expected_request, kind_of(Hash)) 145 .and_return(double(value: true)) 146 147 client.fetch_remote(url, refmap: nil, ssh_auth: nil, forced: false, no_tags: false, timeout: 1, check_tags_changed: false) 148 end 149 150 context 'SSH auth' do 151 where(:ssh_mirror_url, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do 152 false | false | 'key' | 'known_hosts' | {} 153 false | true | 'key' | 'known_hosts' | {} 154 true | false | 'key' | 'known_hosts' | { known_hosts: 'known_hosts' } 155 true | true | 'key' | 'known_hosts' | { ssh_key: 'key', known_hosts: 'known_hosts' } 156 true | true | 'key' | nil | { ssh_key: 'key' } 157 true | true | nil | 'known_hosts' | { known_hosts: 'known_hosts' } 158 true | true | nil | nil | {} 159 true | true | '' | '' | {} 160 end 161 162 with_them do 163 let(:ssh_auth) do 164 double( 165 :ssh_auth, 166 ssh_mirror_url?: ssh_mirror_url, 167 ssh_key_auth?: ssh_key_auth, 168 ssh_private_key: ssh_private_key, 169 ssh_known_hosts: ssh_known_hosts 170 ) 171 end 172 173 it do 174 expected_request = gitaly_request_with_params({ 175 remote_params: Gitaly::Remote.new( 176 url: url, 177 http_authorization_header: "", 178 mirror_refmaps: [] 179 ), 180 ssh_key: '', 181 known_hosts: '', 182 force: false, 183 no_tags: false, 184 no_prune: false 185 }.update(expected_params)) 186 187 expect_any_instance_of(Gitaly::RepositoryService::Stub) 188 .to receive(:fetch_remote) 189 .with(expected_request, kind_of(Hash)) 190 .and_return(double(value: true)) 191 192 client.fetch_remote(url, refmap: nil, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 1) 193 end 194 end 195 end 196 end 197 198 describe '#calculate_checksum' do 199 it 'sends a calculate_checksum message' do 200 expect_any_instance_of(Gitaly::RepositoryService::Stub) 201 .to receive(:calculate_checksum) 202 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 203 .and_return(double(checksum: 0)) 204 205 client.calculate_checksum 206 end 207 end 208 209 describe '#create_from_snapshot' do 210 it 'sends a create_repository_from_snapshot message' do 211 expect_any_instance_of(Gitaly::RepositoryService::Stub) 212 .to receive(:create_repository_from_snapshot) 213 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 214 .and_return(double) 215 216 client.create_from_snapshot('http://example.com?wiki=1', 'Custom xyz') 217 end 218 end 219 220 describe '#raw_changes_between' do 221 it 'sends a create_repository_from_snapshot message' do 222 expect_any_instance_of(Gitaly::RepositoryService::Stub) 223 .to receive(:get_raw_changes) 224 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 225 .and_return(double) 226 227 client.raw_changes_between('deadbeef', 'deadpork') 228 end 229 end 230 231 describe '#search_files_by_regexp' do 232 subject(:result) { client.search_files_by_regexp('master', '.*') } 233 234 before do 235 expect_any_instance_of(Gitaly::RepositoryService::Stub) 236 .to receive(:search_files_by_name) 237 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 238 .and_return([double(files: ['file1.txt']), double(files: ['file2.txt'])]) 239 end 240 241 it 'sends a search_files_by_name message and returns a flatten array' do 242 expect(result).to contain_exactly('file1.txt', 'file2.txt') 243 end 244 end 245 246 describe '#disconnect_alternates' do 247 let(:project) { create(:project, :repository) } 248 let(:repository) { project.repository } 249 let(:repository_path) { File.join(TestEnv.repos_path, repository.relative_path) } 250 let(:pool_repository) { create(:pool_repository) } 251 let(:object_pool) { pool_repository.object_pool } 252 let(:object_pool_service) { Gitlab::GitalyClient::ObjectPoolService.new(object_pool) } 253 254 before do 255 object_pool_service.create(repository) # rubocop:disable Rails/SaveBang 256 object_pool_service.link_repository(repository) 257 end 258 259 it 'deletes the alternates file' do 260 repository.disconnect_alternates 261 262 alternates_file = File.join(repository_path, "objects", "info", "alternates") 263 264 expect(File.exist?(alternates_file)).to be_falsey 265 end 266 267 context 'when called twice' do 268 it "doesn't raise an error" do 269 repository.disconnect_alternates 270 271 expect { repository.disconnect_alternates }.not_to raise_error 272 end 273 end 274 end 275 276 describe '#rename' do 277 it 'sends a rename_repository message' do 278 expect_any_instance_of(Gitaly::RepositoryService::Stub) 279 .to receive(:rename_repository) 280 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 281 .and_return(double(value: true)) 282 283 client.rename('some/new/path') 284 end 285 end 286 287 describe '#remove' do 288 it 'sends a remove_repository message' do 289 expect_any_instance_of(Gitaly::RepositoryService::Stub) 290 .to receive(:remove_repository) 291 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 292 .and_return(double(value: true)) 293 294 client.remove 295 end 296 end 297 298 describe '#replicate' do 299 let(:source_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '', 'group/project') } 300 301 it 'sends a replicate_repository message' do 302 expect_any_instance_of(Gitaly::RepositoryService::Stub) 303 .to receive(:replicate_repository) 304 .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash)) 305 306 client.replicate(source_repository) 307 end 308 end 309 310 describe '#set_full_path' do 311 let(:path) { 'repo/path' } 312 313 it 'sends a set_full_path message' do 314 expect_any_instance_of(Gitaly::RepositoryService::Stub) 315 .to receive(:set_full_path) 316 .with(gitaly_request_with_params(path: path), kind_of(Hash)) 317 .and_return(double) 318 319 client.set_full_path(path) 320 end 321 end 322end 323