repositories_spec.rb 14.4 KB
Newer Older
1
require 'spec_helper'
2
require 'mime/types'
3

4
describe API::Repositories do
D
Dmitriy Zaporozhets 已提交
5
  include RepoHelpers
J
Fix API  
Jacob Vosmaer 已提交
6
  include WorkhorseHelpers
D
Dmitriy Zaporozhets 已提交
7

8
  let(:user) { create(:user) }
9
  let(:guest) { create(:user).tap { |u| create(:project_member, :guest, user: u, project: project) } }
10
  let!(:project) { create(:project, :repository, creator: user) }
11
  let!(:master) { create(:project_member, :master, user: user, project: project) }
12

13
  describe "GET /projects/:id/repository/tree" do
14
    let(:route) { "/projects/#{project.id}/repository/tree" }
15

16 17 18
    shared_examples_for 'repository tree' do
      it 'returns the repository tree' do
        get api(route, current_user)
19

20
        expect(response).to have_gitlab_http_status(200)
21 22
        expect(response).to include_pagination_headers
        expect(json_response).to be_an Array
23

24 25 26 27
        first_commit = json_response.first
        expect(first_commit['name']).to eq('bar')
        expect(first_commit['type']).to eq('tree')
        expect(first_commit['mode']).to eq('040000')
28 29
      end

30 31
      context 'when ref does not exist' do
        it_behaves_like '404 response' do
32
          let(:request) { get api("#{route}?ref=foo", current_user) }
33
          let(:message) { '404 Tree Not Found' }
34 35 36
        end
      end

37 38 39 40 41
      context 'when repository is disabled' do
        include_context 'disabled repository'

        it_behaves_like '403 response' do
          let(:request) { get api(route, current_user) }
42
        end
43
      end
44

45 46 47
      context 'with recursive=1' do
        it 'returns recursive project paths tree' do
          get api("#{route}?recursive=1", current_user)
48

49 50
          expect(response.status).to eq(200)
          expect(json_response).to be_an Array
51
          expect(response).to include_pagination_headers
52 53 54 55 56
          expect(json_response[4]['name']).to eq('html')
          expect(json_response[4]['path']).to eq('files/html')
          expect(json_response[4]['type']).to eq('tree')
          expect(json_response[4]['mode']).to eq('040000')
        end
57

58 59
        context 'when repository is disabled' do
          include_context 'disabled repository'
60

61 62 63 64 65 66 67
          it_behaves_like '403 response' do
            let(:request) { get api(route, current_user) }
          end
        end

        context 'when ref does not exist' do
          it_behaves_like '404 response' do
68
            let(:request) { get api("#{route}?recursive=1&ref=foo", current_user) }
69 70 71
            let(:message) { '404 Tree Not Found' }
          end
        end
72 73
      end
    end
74

75 76
    context 'when unauthenticated', 'and project is public' do
      it_behaves_like 'repository tree' do
77
        let(:project) { create(:project, :public, :repository) }
78
        let(:current_user) { nil }
79
      end
80
    end
81

82 83 84 85
    context 'when unauthenticated', 'and project is private' do
      it_behaves_like '404 response' do
        let(:request) { get api(route) }
        let(:message) { '404 Project Not Found' }
86
      end
87 88
    end

89 90 91 92 93
    context 'when authenticated', 'as a developer' do
      it_behaves_like 'repository tree' do
        let(:current_user) { user }
      end
    end
94

95 96 97
    context 'when authenticated', 'as a guest' do
      it_behaves_like '403 response' do
        let(:request) { get api(route, guest) }
98 99 100 101
      end
    end
  end

102 103 104 105 106 107 108
  describe "GET /projects/:id/repository/blobs/:sha" do
    let(:route) { "/projects/#{project.id}/repository/blobs/#{sample_blob.oid}" }

    shared_examples_for 'repository blob' do
      it 'returns blob attributes as json' do
        get api(route, current_user)

109
        expect(response).to have_gitlab_http_status(200)
110 111 112 113
        expect(json_response['size']).to eq(111)
        expect(json_response['encoding']).to eq("base64")
        expect(Base64.decode64(json_response['content']).lines.first).to eq("class Commit\n")
        expect(json_response['sha']).to eq(sample_blob.oid)
114
      end
115

116 117 118 119
      context 'when sha does not exist' do
        it_behaves_like '404 response' do
          let(:request) { get api(route.sub(sample_blob.oid, '123456'), current_user) }
          let(:message) { '404 Blob Not Found' }
120 121
        end
      end
122

123 124 125
      context 'when repository is disabled' do
        include_context 'disabled repository'

126
        it_behaves_like '403 response' do
127
          let(:request) { get api(route, current_user) }
128 129
        end
      end
130
    end
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156

    context 'when unauthenticated', 'and project is public' do
      it_behaves_like 'repository blob' do
        let(:project) { create(:project, :public, :repository) }
        let(:current_user) { nil }
      end
    end

    context 'when unauthenticated', 'and project is private' do
      it_behaves_like '404 response' do
        let(:request) { get api(route) }
        let(:message) { '404 Project Not Found' }
      end
    end

    context 'when authenticated', 'as a developer' do
      it_behaves_like 'repository blob' do
        let(:current_user) { user }
      end
    end

    context 'when authenticated', 'as a guest' do
      it_behaves_like '403 response' do
        let(:request) { get api(route, guest) }
      end
    end
157
  end
158

159 160
  describe "GET /projects/:id/repository/blobs/:sha/raw" do
    let(:route) { "/projects/#{project.id}/repository/blobs/#{sample_blob.oid}/raw" }
161

162 163
    shared_examples_for 'repository raw blob' do
      it 'returns the repository raw blob' do
164 165
        expect(Gitlab::Workhorse).to receive(:send_git_blob)

166
        get api(route, current_user)
167

168
        expect(response).to have_gitlab_http_status(200)
169
      end
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

      context 'when sha does not exist' do
        it_behaves_like '404 response' do
          let(:request) { get api(route.sub(sample_blob.oid, '123456'), current_user) }
          let(:message) { '404 Blob Not Found' }
        end
      end

      context 'when repository is disabled' do
        include_context 'disabled repository'

        it_behaves_like '403 response' do
          let(:request) { get api(route, current_user) }
        end
      end
185 186
    end

187
    context 'when unauthenticated', 'and project is public' do
188
      it_behaves_like 'repository raw blob' do
189
        let(:project) { create(:project, :public, :repository) }
190 191 192 193
        let(:current_user) { nil }
      end
    end

194 195 196 197 198 199 200 201
    context 'when unauthenticated', 'and project is private' do
      it_behaves_like '404 response' do
        let(:request) { get api(route) }
        let(:message) { '404 Project Not Found' }
      end
    end

    context 'when authenticated', 'as a developer' do
202 203 204
      it_behaves_like 'repository raw blob' do
        let(:current_user) { user }
      end
T
Thom Gerdes 已提交
205
    end
206

207 208 209 210
    context 'when authenticated', 'as a guest' do
      it_behaves_like '403 response' do
        let(:request) { get api(route, guest) }
      end
211
    end
T
Thom Gerdes 已提交
212 213
  end

214
  describe "GET /projects/:id/repository/archive(.:format)?:sha" do
215 216
    let(:route) { "/projects/#{project.id}/repository/archive" }

217 218
    shared_examples_for 'repository archive' do
      it 'returns the repository archive' do
219
        get api(route, current_user)
220

221
        expect(response).to have_gitlab_http_status(200)
222 223 224 225 226 227 228 229 230 231 232

        repo_name = project.repository.name.gsub("\.git", "")
        type, params = workhorse_send_data

        expect(type).to eq('git-archive')
        expect(params['ArchivePath']).to match(/#{repo_name}\-[^\.]+\.tar.gz/)
      end

      it 'returns the repository archive archive.zip' do
        get api("/projects/#{project.id}/repository/archive.zip", user)

233
        expect(response).to have_gitlab_http_status(200)
234 235 236 237 238 239 240 241 242 243 244

        repo_name = project.repository.name.gsub("\.git", "")
        type, params = workhorse_send_data

        expect(type).to eq('git-archive')
        expect(params['ArchivePath']).to match(/#{repo_name}\-[^\.]+\.zip/)
      end

      it 'returns the repository archive archive.tar.bz2' do
        get api("/projects/#{project.id}/repository/archive.tar.bz2", user)

245
        expect(response).to have_gitlab_http_status(200)
246 247 248 249 250 251 252

        repo_name = project.repository.name.gsub("\.git", "")
        type, params = workhorse_send_data

        expect(type).to eq('git-archive')
        expect(params['ArchivePath']).to match(/#{repo_name}\-[^\.]+\.tar.bz2/)
      end
253 254 255 256 257 258 259

      context 'when sha does not exist' do
        it_behaves_like '404 response' do
          let(:request) { get api("#{route}?sha=xxx", current_user) }
          let(:message) { '404 File Not Found' }
        end
      end
260 261
    end

262
    context 'when unauthenticated', 'and project is public' do
263
      it_behaves_like 'repository archive' do
264
        let(:project) { create(:project, :public, :repository) }
265 266
        let(:current_user) { nil }
      end
267 268
    end

269 270 271 272 273 274 275 276
    context 'when unauthenticated', 'and project is private' do
      it_behaves_like '404 response' do
        let(:request) { get api(route) }
        let(:message) { '404 Project Not Found' }
      end
    end

    context 'when authenticated', 'as a developer' do
277 278 279
      it_behaves_like 'repository archive' do
        let(:current_user) { user }
      end
280 281
    end

282 283 284 285
    context 'when authenticated', 'as a guest' do
      it_behaves_like '403 response' do
        let(:request) { get api(route, guest) }
      end
286 287
    end
  end
288

289
  describe 'GET /projects/:id/repository/compare' do
290 291
    let(:route) { "/projects/#{project.id}/repository/compare" }

292 293
    shared_examples_for 'repository compare' do
      it "compares branches" do
294
        get api(route, current_user), from: 'master', to: 'feature'
295

296
        expect(response).to have_gitlab_http_status(200)
297 298 299 300 301
        expect(json_response['commits']).to be_present
        expect(json_response['diffs']).to be_present
      end

      it "compares tags" do
302
        get api(route, current_user), from: 'v1.0.0', to: 'v1.1.0'
303

304
        expect(response).to have_gitlab_http_status(200)
305 306 307 308 309
        expect(json_response['commits']).to be_present
        expect(json_response['diffs']).to be_present
      end

      it "compares commits" do
310
        get api(route, current_user), from: sample_commit.id, to: sample_commit.parent_id
311

312
        expect(response).to have_gitlab_http_status(200)
313 314 315 316
        expect(json_response['commits']).to be_empty
        expect(json_response['diffs']).to be_empty
        expect(json_response['compare_same_ref']).to be_falsey
      end
317

318
      it "compares commits in reverse order" do
319
        get api(route, current_user), from: sample_commit.parent_id, to: sample_commit.id
320

321
        expect(response).to have_gitlab_http_status(200)
322 323 324 325 326
        expect(json_response['commits']).to be_present
        expect(json_response['diffs']).to be_present
      end

      it "compares same refs" do
327
        get api(route, current_user), from: 'master', to: 'master'
328

329
        expect(response).to have_gitlab_http_status(200)
330 331 332 333
        expect(json_response['commits']).to be_empty
        expect(json_response['diffs']).to be_empty
        expect(json_response['compare_same_ref']).to be_truthy
      end
334 335
    end

336
    context 'when unauthenticated', 'and project is public' do
337
      it_behaves_like 'repository compare' do
338
        let(:project) { create(:project, :public, :repository) }
339 340
        let(:current_user) { nil }
      end
341 342
    end

343 344 345 346 347 348 349 350
    context 'when unauthenticated', 'and project is private' do
      it_behaves_like '404 response' do
        let(:request) { get api(route) }
        let(:message) { '404 Project Not Found' }
      end
    end

    context 'when authenticated', 'as a developer' do
351 352 353
      it_behaves_like 'repository compare' do
        let(:current_user) { user }
      end
354
    end
355 356 357 358 359 360

    context 'when authenticated', 'as a guest' do
      it_behaves_like '403 response' do
        let(:request) { get api(route, guest) }
      end
    end
361
  end
362 363

  describe 'GET /projects/:id/repository/contributors' do
364 365
    let(:route) { "/projects/#{project.id}/repository/contributors" }

366 367
    shared_examples_for 'repository contributors' do
      it 'returns valid data' do
368
        get api(route, current_user)
369

370
        expect(response).to have_gitlab_http_status(200)
371
        expect(response).to include_pagination_headers
372 373 374 375 376 377 378 379 380
        expect(json_response).to be_an Array

        first_contributor = json_response.first
        expect(first_contributor['email']).to eq('tiagonbotelho@hotmail.com')
        expect(first_contributor['name']).to eq('tiagonbotelho')
        expect(first_contributor['commits']).to eq(1)
        expect(first_contributor['additions']).to eq(0)
        expect(first_contributor['deletions']).to eq(0)
      end
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402

      context 'using sorting' do
        context 'by commits desc' do
          it 'returns the repository contribuors sorted by commits desc' do
            get api(route, current_user), { order_by: 'commits', sort: 'desc' }

            expect(response).to have_gitlab_http_status(200)
            expect(response).to match_response_schema('contributors')
            expect(json_response.first['commits']).to be > json_response.last['commits']
          end
        end

        context 'by name desc' do
          it 'returns the repository contribuors sorted by name asc case insensitive' do
            get api(route, current_user), { order_by: 'name', sort: 'asc' }

            expect(response).to have_gitlab_http_status(200)
            expect(response).to match_response_schema('contributors')
            expect(json_response.first['name'].downcase).to be < json_response.last['name'].downcase
          end
        end
      end
403 404
    end

405
    context 'when unauthenticated', 'and project is public' do
406
      it_behaves_like 'repository contributors' do
407
        let(:project) { create(:project, :public, :repository) }
408 409 410 411
        let(:current_user) { nil }
      end
    end

412 413 414 415 416 417 418 419
    context 'when unauthenticated', 'and project is private' do
      it_behaves_like '404 response' do
        let(:request) { get api(route) }
        let(:message) { '404 Project Not Found' }
      end
    end

    context 'when authenticated', 'as a developer' do
420 421 422
      it_behaves_like 'repository contributors' do
        let(:current_user) { user }
      end
423
    end
424 425 426 427 428 429

    context 'when authenticated', 'as a guest' do
      it_behaves_like '403 response' do
        let(:request) { get api(route, guest) }
      end
    end
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444

    # Regression: https://gitlab.com/gitlab-org/gitlab-ce/issues/45363
    describe 'Links header contains working URLs when no `order_by` nor `sort` is given' do
      let(:project) { create(:project, :public, :repository) }
      let(:current_user) { nil }

      it 'returns `Link` header that includes URLs with default value for `order_by` & `sort`' do
        get api(route, current_user)

        first_link_url = response.headers['Link'].split(';').first

        expect(first_link_url).to include('order_by=commits')
        expect(first_link_url).to include('sort=asc')
      end
    end
445
  end
446
end