##// END OF EJS Templates
tests: fixed some git tests for lfs modules
super-admin -
r5151:3cdc843a default
parent child Browse files
Show More
@@ -1,1300 +1,1304 b''
1 1
2 2 # Copyright (C) 2010-2023 RhodeCode GmbH
3 3 #
4 4 # This program is free software: you can redistribute it and/or modify
5 5 # it under the terms of the GNU Affero General Public License, version 3
6 6 # (only), as published by the Free Software Foundation.
7 7 #
8 8 # This program is distributed in the hope that it will be useful,
9 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 11 # GNU General Public License for more details.
12 12 #
13 13 # You should have received a copy of the GNU Affero General Public License
14 14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 15 #
16 16 # This program is dual-licensed. If you wish to learn more about the
17 17 # RhodeCode Enterprise Edition, including its added features, Support services,
18 18 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 19
20 20 import datetime
21 21 import mock
22 22 import os
23 23 import sys
24 24 import shutil
25 25
26 26 import pytest
27 27
28 28 from rhodecode.lib.utils import make_db_config
29 29 from rhodecode.lib.vcs.backends.base import Reference
30 30 from rhodecode.lib.vcs.backends.git import (
31 31 GitRepository, GitCommit, discover_git_version)
32 32 from rhodecode.lib.vcs.exceptions import (
33 33 RepositoryError, VCSError, NodeDoesNotExistError)
34 34 from rhodecode.lib.vcs.nodes import (
35 35 NodeKind, FileNode, DirNode, NodeState, SubModuleNode)
36 36 from rhodecode.tests import TEST_GIT_REPO, TEST_GIT_REPO_CLONE, get_new_dir
37 37 from rhodecode.tests.vcs.conftest import BackendTestMixin
38 38
39 39
40 40 pytestmark = pytest.mark.backends("git")
41 41
42 42
43 43 DIFF_FROM_REMOTE = br"""diff --git a/foobar b/foobar
44 44 new file mode 100644
45 45 index 0000000..f6ea049
46 46 --- /dev/null
47 47 +++ b/foobar
48 48 @@ -0,0 +1 @@
49 49 +foobar
50 50 \ No newline at end of file
51 51 diff --git a/foobar2 b/foobar2
52 52 new file mode 100644
53 53 index 0000000..e8c9d6b
54 54 --- /dev/null
55 55 +++ b/foobar2
56 56 @@ -0,0 +1 @@
57 57 +foobar2
58 58 \ No newline at end of file
59 59 """
60 60
61 61
62 62 def callable_get_diff(*args, **kwargs):
63 63 return DIFF_FROM_REMOTE
64 64
65 65
66 66 class TestGitRepository(object):
67 67
68 68 @pytest.fixture(autouse=True)
69 69 def prepare(self, request, baseapp):
70 70 self.repo = GitRepository(TEST_GIT_REPO, bare=True)
71 71 self.repo.count()
72 72
73 73 def get_clone_repo(self, tmpdir):
74 74 """
75 75 Return a non bare clone of the base repo.
76 76 """
77 77 clone_path = str(tmpdir.join('clone-repo'))
78 78 repo_clone = GitRepository(
79 79 clone_path, create=True, src_url=self.repo.path, bare=False)
80 80
81 81 return repo_clone
82 82
83 83 def get_empty_repo(self, tmpdir, bare=False):
84 84 """
85 85 Return a non bare empty repo.
86 86 """
87 87 clone_path = str(tmpdir.join('empty-repo'))
88 88 return GitRepository(clone_path, create=True, bare=bare)
89 89
90 90 def test_wrong_repo_path(self):
91 91 wrong_repo_path = '/tmp/errorrepo_git'
92 92 with pytest.raises(RepositoryError):
93 93 GitRepository(wrong_repo_path)
94 94
95 95 def test_repo_clone(self, tmp_path_factory):
96 96 repo = GitRepository(TEST_GIT_REPO)
97 97 clone_path = '{}_{}'.format(tmp_path_factory.mktemp('_'), TEST_GIT_REPO_CLONE)
98 98 repo_clone = GitRepository(
99 99 clone_path,
100 100 src_url=TEST_GIT_REPO, create=True, do_workspace_checkout=True)
101 101
102 102 assert len(repo.commit_ids) == len(repo_clone.commit_ids)
103 103 # Checking hashes of commits should be enough
104 104 for commit in repo.get_commits():
105 105 raw_id = commit.raw_id
106 106 assert raw_id == repo_clone.get_commit(raw_id).raw_id
107 107
108 108 def test_repo_clone_without_create(self):
109 109 with pytest.raises(RepositoryError):
110 110 GitRepository(
111 111 TEST_GIT_REPO_CLONE + '_wo_create', src_url=TEST_GIT_REPO)
112 112
113 113 def test_repo_clone_with_update(self, tmp_path_factory):
114 114 repo = GitRepository(TEST_GIT_REPO)
115 115 clone_path = '{}_{}_update'.format(tmp_path_factory.mktemp('_'), TEST_GIT_REPO_CLONE)
116 116
117 117 repo_clone = GitRepository(
118 118 clone_path,
119 119 create=True, src_url=TEST_GIT_REPO, do_workspace_checkout=True)
120 120 assert len(repo.commit_ids) == len(repo_clone.commit_ids)
121 121
122 122 # check if current workdir was updated
123 123 fpath = os.path.join(clone_path, 'MANIFEST.in')
124 124 assert os.path.isfile(fpath)
125 125
126 126 def test_repo_clone_without_update(self, tmp_path_factory):
127 127 repo = GitRepository(TEST_GIT_REPO)
128 128 clone_path = '{}_{}_without_update'.format(tmp_path_factory.mktemp('_'), TEST_GIT_REPO_CLONE)
129 129 repo_clone = GitRepository(
130 130 clone_path,
131 131 create=True, src_url=TEST_GIT_REPO, do_workspace_checkout=False)
132 132 assert len(repo.commit_ids) == len(repo_clone.commit_ids)
133 133 # check if current workdir was *NOT* updated
134 134 fpath = os.path.join(clone_path, 'MANIFEST.in')
135 135 # Make sure it's not bare repo
136 136 assert not repo_clone.bare
137 137 assert not os.path.isfile(fpath)
138 138
139 139 def test_repo_clone_into_bare_repo(self, tmp_path_factory):
140 140 repo = GitRepository(TEST_GIT_REPO)
141 141 clone_path = '{}_{}_bare.git'.format(tmp_path_factory.mktemp('_'), TEST_GIT_REPO_CLONE)
142 142 repo_clone = GitRepository(
143 143 clone_path, create=True, src_url=repo.path, bare=True)
144 144 assert repo_clone.bare
145 145
146 146 def test_create_repo_is_not_bare_by_default(self):
147 147 repo = GitRepository(get_new_dir('not-bare-by-default'), create=True)
148 148 assert not repo.bare
149 149
150 150 def test_create_bare_repo(self):
151 151 repo = GitRepository(get_new_dir('bare-repo'), create=True, bare=True)
152 152 assert repo.bare
153 153
154 154 def test_update_server_info(self):
155 155 self.repo._update_server_info()
156 156
157 157 def test_fetch(self, vcsbackend_git):
158 158 # Note: This is a git specific part of the API, it's only implemented
159 159 # by the git backend.
160 160 source_repo = vcsbackend_git.repo
161 161 target_repo = vcsbackend_git.create_repo(bare=True)
162 162 target_repo.fetch(source_repo.path)
163 163 # Note: Get a fresh instance, avoids caching trouble
164 164 target_repo = vcsbackend_git.backend(target_repo.path)
165 165 assert len(source_repo.commit_ids) == len(target_repo.commit_ids)
166 166
167 167 def test_commit_ids(self):
168 168 # there are 112 commits (by now)
169 169 # so we can assume they would be available from now on
170 170 subset = {'c1214f7e79e02fc37156ff215cd71275450cffc3',
171 171 '38b5fe81f109cb111f549bfe9bb6b267e10bc557',
172 172 'fa6600f6848800641328adbf7811fd2372c02ab2',
173 173 '102607b09cdd60e2793929c4f90478be29f85a17',
174 174 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
175 175 '2d1028c054665b962fa3d307adfc923ddd528038',
176 176 'd7e0d30fbcae12c90680eb095a4f5f02505ce501',
177 177 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
178 178 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
179 179 '8430a588b43b5d6da365400117c89400326e7992',
180 180 'd955cd312c17b02143c04fa1099a352b04368118',
181 181 'f67b87e5c629c2ee0ba58f85197e423ff28d735b',
182 182 'add63e382e4aabc9e1afdc4bdc24506c269b7618',
183 183 'f298fe1189f1b69779a4423f40b48edf92a703fc',
184 184 'bd9b619eb41994cac43d67cf4ccc8399c1125808',
185 185 '6e125e7c890379446e98980d8ed60fba87d0f6d1',
186 186 'd4a54db9f745dfeba6933bf5b1e79e15d0af20bd',
187 187 '0b05e4ed56c802098dfc813cbe779b2f49e92500',
188 188 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
189 189 '45223f8f114c64bf4d6f853e3c35a369a6305520',
190 190 'ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
191 191 'f5ea29fc42ef67a2a5a7aecff10e1566699acd68',
192 192 '27d48942240f5b91dfda77accd2caac94708cc7d',
193 193 '622f0eb0bafd619d2560c26f80f09e3b0b0d78af',
194 194 'e686b958768ee96af8029fe19c6050b1a8dd3b2b'}
195 195 assert subset.issubset(set(self.repo.commit_ids))
196 196
197 197 def test_slicing(self):
198 198 # 4 1 5 10 95
199 199 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
200 200 (10, 20, 10), (5, 100, 95)]:
201 201 commit_ids = list(self.repo[sfrom:sto])
202 202 assert len(commit_ids) == size
203 203 assert commit_ids[0] == self.repo.get_commit(commit_idx=sfrom)
204 204 assert commit_ids[-1] == self.repo.get_commit(commit_idx=sto - 1)
205 205
206 206 def test_branches(self):
207 207 # TODO: Need more tests here
208 208 # Removed (those are 'remotes' branches for cloned repo)
209 209 # assert 'master' in self.repo.branches
210 210 # assert 'gittree' in self.repo.branches
211 211 # assert 'web-branch' in self.repo.branches
212 212 for __, commit_id in self.repo.branches.items():
213 213 assert isinstance(self.repo.get_commit(commit_id), GitCommit)
214 214
215 215 def test_tags(self):
216 216 # TODO: Need more tests here
217 217 assert 'v0.1.1' in self.repo.tags
218 218 assert 'v0.1.2' in self.repo.tags
219 219 for __, commit_id in self.repo.tags.items():
220 220 assert isinstance(self.repo.get_commit(commit_id), GitCommit)
221 221
222 222 def _test_single_commit_cache(self, commit_id):
223 223 commit = self.repo.get_commit(commit_id)
224 224 assert commit_id in self.repo.commits
225 225 assert commit is self.repo.commits[commit_id]
226 226
227 227 def test_initial_commit(self):
228 228 commit_id = self.repo.commit_ids[0]
229 229 init_commit = self.repo.get_commit(commit_id)
230 230 init_author = init_commit.author
231 231
232 232 assert init_commit.message == 'initial import\n'
233 233 assert init_author == 'Marcin Kuzminski <marcin@python-blog.com>'
234 234 assert init_author == init_commit.committer
235 235 for path in ('vcs/__init__.py',
236 236 'vcs/backends/BaseRepository.py',
237 237 'vcs/backends/__init__.py'):
238 238 assert isinstance(init_commit.get_node(path), FileNode)
239 239 for path in ('', 'vcs', 'vcs/backends'):
240 240 assert isinstance(init_commit.get_node(path), DirNode)
241 241
242 242 with pytest.raises(NodeDoesNotExistError):
243 243 init_commit.get_node(path='foobar')
244 244
245 245 node = init_commit.get_node('vcs/')
246 246 assert hasattr(node, 'kind')
247 247 assert node.kind == NodeKind.DIR
248 248
249 249 node = init_commit.get_node('vcs')
250 250 assert hasattr(node, 'kind')
251 251 assert node.kind == NodeKind.DIR
252 252
253 253 node = init_commit.get_node('vcs/__init__.py')
254 254 assert hasattr(node, 'kind')
255 255 assert node.kind == NodeKind.FILE
256 256
257 257 def test_not_existing_commit(self):
258 258 with pytest.raises(RepositoryError):
259 259 self.repo.get_commit('f' * 40)
260 260
261 261 def test_commit10(self):
262 262
263 263 commit10 = self.repo.get_commit(self.repo.commit_ids[9])
264 264 README = """===
265 265 VCS
266 266 ===
267 267
268 268 Various Version Control System management abstraction layer for Python.
269 269
270 270 Introduction
271 271 ------------
272 272
273 273 TODO: To be written...
274 274
275 275 """
276 276 node = commit10.get_node('README.rst')
277 277 assert node.kind == NodeKind.FILE
278 278 assert node.str_content == README
279 279
280 280 def test_head(self):
281 281 assert self.repo.head == self.repo.get_commit().raw_id
282 282
283 283 def test_checkout_with_create(self, tmpdir):
284 284 repo_clone = self.get_clone_repo(tmpdir)
285 285
286 286 new_branch = 'new_branch'
287 287 assert repo_clone._current_branch() == 'master'
288 288 assert set(repo_clone.branches) == {'master'}
289 289 repo_clone._checkout(new_branch, create=True)
290 290
291 291 # Branches is a lazy property so we need to recrete the Repo object.
292 292 repo_clone = GitRepository(repo_clone.path)
293 293 assert set(repo_clone.branches) == {'master', new_branch}
294 294 assert repo_clone._current_branch() == new_branch
295 295
296 296 def test_checkout(self, tmpdir):
297 297 repo_clone = self.get_clone_repo(tmpdir)
298 298
299 299 repo_clone._checkout('new_branch', create=True)
300 300 repo_clone._checkout('master')
301 301
302 302 assert repo_clone._current_branch() == 'master'
303 303
304 304 def test_checkout_same_branch(self, tmpdir):
305 305 repo_clone = self.get_clone_repo(tmpdir)
306 306
307 307 repo_clone._checkout('master')
308 308 assert repo_clone._current_branch() == 'master'
309 309
310 310 def test_checkout_branch_already_exists(self, tmpdir):
311 311 repo_clone = self.get_clone_repo(tmpdir)
312 312
313 313 with pytest.raises(RepositoryError):
314 314 repo_clone._checkout('master', create=True)
315 315
316 316 def test_checkout_bare_repo(self):
317 317 with pytest.raises(RepositoryError):
318 318 self.repo._checkout('master')
319 319
320 320 def test_current_branch_bare_repo(self):
321 321 with pytest.raises(RepositoryError):
322 322 self.repo._current_branch()
323 323
324 324 def test_current_branch_empty_repo(self, tmpdir):
325 325 repo = self.get_empty_repo(tmpdir)
326 326 assert repo._current_branch() is None
327 327
328 328 def test_local_clone(self, tmp_path_factory):
329 329 clone_path = str(tmp_path_factory.mktemp('test-local-clone'))
330 330 self.repo._local_clone(clone_path, 'master')
331 331 repo_clone = GitRepository(clone_path)
332 332
333 333 assert self.repo.commit_ids == repo_clone.commit_ids
334 334
335 335 def test_local_clone_with_specific_branch(self, tmpdir):
336 336 source_repo = self.get_clone_repo(tmpdir)
337 337
338 338 # Create a new branch in source repo
339 339 new_branch_commit = source_repo.commit_ids[-3]
340 340 source_repo._checkout(new_branch_commit)
341 341 source_repo._checkout('new_branch', create=True)
342 342
343 343 clone_path = str(tmpdir.join('git-clone-path-1'))
344 344 source_repo._local_clone(clone_path, 'new_branch')
345 345 repo_clone = GitRepository(clone_path)
346 346
347 347 assert source_repo.commit_ids[:-3 + 1] == repo_clone.commit_ids
348 348
349 349 clone_path = str(tmpdir.join('git-clone-path-2'))
350 350 source_repo._local_clone(clone_path, 'master')
351 351 repo_clone = GitRepository(clone_path)
352 352
353 353 assert source_repo.commit_ids == repo_clone.commit_ids
354 354
355 355 def test_local_clone_fails_if_target_exists(self):
356 356 with pytest.raises(RepositoryError):
357 357 self.repo._local_clone(self.repo.path, 'master')
358 358
359 359 def test_local_fetch(self, tmpdir):
360 360 target_repo = self.get_empty_repo(tmpdir)
361 361 source_repo = self.get_clone_repo(tmpdir)
362 362
363 363 # Create a new branch in source repo
364 364 master_commit = source_repo.commit_ids[-1]
365 365 new_branch_commit = source_repo.commit_ids[-3]
366 366 source_repo._checkout(new_branch_commit)
367 367 source_repo._checkout('new_branch', create=True)
368 368
369 369 target_repo._local_fetch(source_repo.path, 'new_branch')
370 370 assert target_repo._last_fetch_heads() == [new_branch_commit]
371 371
372 372 target_repo._local_fetch(source_repo.path, 'master')
373 373 assert target_repo._last_fetch_heads() == [master_commit]
374 374
375 375 def test_local_fetch_from_bare_repo(self, tmpdir):
376 376 target_repo = self.get_empty_repo(tmpdir)
377 377 target_repo._local_fetch(self.repo.path, 'master')
378 378
379 379 master_commit = self.repo.commit_ids[-1]
380 380 assert target_repo._last_fetch_heads() == [master_commit]
381 381
382 382 def test_local_fetch_from_same_repo(self):
383 383 with pytest.raises(ValueError):
384 384 self.repo._local_fetch(self.repo.path, 'master')
385 385
386 386 def test_local_fetch_branch_does_not_exist(self, tmpdir):
387 387 target_repo = self.get_empty_repo(tmpdir)
388 388
389 389 with pytest.raises(RepositoryError):
390 390 target_repo._local_fetch(self.repo.path, 'new_branch')
391 391
392 392 def test_local_pull(self, tmpdir):
393 393 target_repo = self.get_empty_repo(tmpdir)
394 394 source_repo = self.get_clone_repo(tmpdir)
395 395
396 396 # Create a new branch in source repo
397 397 master_commit = source_repo.commit_ids[-1]
398 398 new_branch_commit = source_repo.commit_ids[-3]
399 399 source_repo._checkout(new_branch_commit)
400 400 source_repo._checkout('new_branch', create=True)
401 401
402 402 target_repo._local_pull(source_repo.path, 'new_branch')
403 403 target_repo = GitRepository(target_repo.path)
404 404 assert target_repo.head == new_branch_commit
405 405
406 406 target_repo._local_pull(source_repo.path, 'master')
407 407 target_repo = GitRepository(target_repo.path)
408 408 assert target_repo.head == master_commit
409 409
410 410 def test_local_pull_in_bare_repo(self):
411 411 with pytest.raises(RepositoryError):
412 412 self.repo._local_pull(self.repo.path, 'master')
413 413
414 414 def test_local_merge(self, tmpdir):
415 415 target_repo = self.get_empty_repo(tmpdir)
416 416 source_repo = self.get_clone_repo(tmpdir)
417 417
418 418 # Create a new branch in source repo
419 419 master_commit = source_repo.commit_ids[-1]
420 420 new_branch_commit = source_repo.commit_ids[-3]
421 421 source_repo._checkout(new_branch_commit)
422 422 source_repo._checkout('new_branch', create=True)
423 423
424 424 # This is required as one cannot do a -ff-only merge in an empty repo.
425 425 target_repo._local_pull(source_repo.path, 'new_branch')
426 426
427 427 target_repo._local_fetch(source_repo.path, 'master')
428 428 merge_message = 'Merge message\n\nDescription:...'
429 429 user_name = 'Albert Einstein'
430 430 user_email = 'albert@einstein.com'
431 431 target_repo._local_merge(merge_message, user_name, user_email,
432 432 target_repo._last_fetch_heads())
433 433
434 434 target_repo = GitRepository(target_repo.path)
435 435 assert target_repo.commit_ids[-2] == master_commit
436 436 last_commit = target_repo.get_commit(target_repo.head)
437 437 assert last_commit.message.strip() == merge_message
438 438 assert last_commit.author == '%s <%s>' % (user_name, user_email)
439 439
440 440 assert not os.path.exists(
441 441 os.path.join(target_repo.path, '.git', 'MERGE_HEAD'))
442 442
443 443 def test_local_merge_raises_exception_on_conflict(self, vcsbackend_git):
444 444 target_repo = vcsbackend_git.create_repo(number_of_commits=1)
445 445 vcsbackend_git.ensure_file(b'README', b'I will conflict with you!!!')
446 446
447 447 target_repo._local_fetch(self.repo.path, 'master')
448 448 with pytest.raises(RepositoryError):
449 449 target_repo._local_merge(
450 450 'merge_message', 'user name', 'user@name.com',
451 451 target_repo._last_fetch_heads())
452 452
453 453 # Check we are not left in an intermediate merge state
454 454 assert not os.path.exists(
455 455 os.path.join(target_repo.path, '.git', 'MERGE_HEAD'))
456 456
457 457 def test_local_merge_into_empty_repo(self, tmpdir):
458 458 target_repo = self.get_empty_repo(tmpdir)
459 459
460 460 # This is required as one cannot do a -ff-only merge in an empty repo.
461 461 target_repo._local_fetch(self.repo.path, 'master')
462 462 with pytest.raises(RepositoryError):
463 463 target_repo._local_merge(
464 464 'merge_message', 'user name', 'user@name.com',
465 465 target_repo._last_fetch_heads())
466 466
467 467 def test_local_merge_in_bare_repo(self):
468 468 with pytest.raises(RepositoryError):
469 469 self.repo._local_merge(
470 470 'merge_message', 'user name', 'user@name.com', None)
471 471
472 472 def test_local_push_non_bare(self, tmpdir):
473 473 target_repo = self.get_empty_repo(tmpdir)
474 474
475 475 pushed_branch = 'pushed_branch'
476 476 self.repo._local_push('master', target_repo.path, pushed_branch)
477 477 # Fix the HEAD of the target repo, or otherwise GitRepository won't
478 478 # report any branches.
479 479 with open(os.path.join(target_repo.path, '.git', 'HEAD'), 'w') as f:
480 480 f.write('ref: refs/heads/%s' % pushed_branch)
481 481
482 482 target_repo = GitRepository(target_repo.path)
483 483
484 484 assert (target_repo.branches[pushed_branch] ==
485 485 self.repo.branches['master'])
486 486
487 487 def test_local_push_bare(self, tmpdir):
488 488 target_repo = self.get_empty_repo(tmpdir, bare=True)
489 489
490 490 pushed_branch = 'pushed_branch'
491 491 self.repo._local_push('master', target_repo.path, pushed_branch)
492 492 # Fix the HEAD of the target repo, or otherwise GitRepository won't
493 493 # report any branches.
494 494 with open(os.path.join(target_repo.path, 'HEAD'), 'w') as f:
495 495 f.write('ref: refs/heads/%s' % pushed_branch)
496 496
497 497 target_repo = GitRepository(target_repo.path)
498 498
499 499 assert (target_repo.branches[pushed_branch] ==
500 500 self.repo.branches['master'])
501 501
502 502 def test_local_push_non_bare_target_branch_is_checked_out(self, tmpdir):
503 503 target_repo = self.get_clone_repo(tmpdir)
504 504
505 505 pushed_branch = 'pushed_branch'
506 506 # Create a new branch in source repo
507 507 new_branch_commit = target_repo.commit_ids[-3]
508 508 target_repo._checkout(new_branch_commit)
509 509 target_repo._checkout(pushed_branch, create=True)
510 510
511 511 self.repo._local_push('master', target_repo.path, pushed_branch)
512 512
513 513 target_repo = GitRepository(target_repo.path)
514 514
515 515 assert (target_repo.branches[pushed_branch] ==
516 516 self.repo.branches['master'])
517 517
518 518 def test_local_push_raises_exception_on_conflict(self, vcsbackend_git):
519 519 target_repo = vcsbackend_git.create_repo(number_of_commits=1)
520 520 with pytest.raises(RepositoryError):
521 521 self.repo._local_push('master', target_repo.path, 'master')
522 522
523 523 def test_hooks_can_be_enabled_via_env_variable_for_local_push(self, tmpdir):
524 524 target_repo = self.get_empty_repo(tmpdir, bare=True)
525 525
526 526 with mock.patch.object(self.repo, 'run_git_command') as run_mock:
527 527 self.repo._local_push(
528 528 'master', target_repo.path, 'master', enable_hooks=True)
529 529 env = run_mock.call_args[1]['extra_env']
530 530 assert 'RC_SKIP_HOOKS' not in env
531 531
532 532 def _add_failing_hook(self, repo_path, hook_name, bare=False):
533 533 path_components = (
534 534 ['hooks', hook_name] if bare else ['.git', 'hooks', hook_name])
535 535 hook_path = os.path.join(repo_path, *path_components)
536 536 with open(hook_path, 'w') as f:
537 537 script_lines = [
538 538 '#!%s' % sys.executable,
539 539 'import os',
540 540 'import sys',
541 541 'if os.environ.get("RC_SKIP_HOOKS"):',
542 542 ' sys.exit(0)',
543 543 'sys.exit(1)',
544 544 ]
545 545 f.write('\n'.join(script_lines))
546 546 os.chmod(hook_path, 0o755)
547 547
548 548 def test_local_push_does_not_execute_hook(self, tmpdir):
549 549 target_repo = self.get_empty_repo(tmpdir)
550 550
551 551 pushed_branch = 'pushed_branch'
552 552 self._add_failing_hook(target_repo.path, 'pre-receive')
553 553 self.repo._local_push('master', target_repo.path, pushed_branch)
554 554 # Fix the HEAD of the target repo, or otherwise GitRepository won't
555 555 # report any branches.
556 556 with open(os.path.join(target_repo.path, '.git', 'HEAD'), 'w') as f:
557 557 f.write('ref: refs/heads/%s' % pushed_branch)
558 558
559 559 target_repo = GitRepository(target_repo.path)
560 560
561 561 assert (target_repo.branches[pushed_branch] ==
562 562 self.repo.branches['master'])
563 563
564 564 def test_local_push_executes_hook(self, tmpdir):
565 565 target_repo = self.get_empty_repo(tmpdir, bare=True)
566 566 self._add_failing_hook(target_repo.path, 'pre-receive', bare=True)
567 567 with pytest.raises(RepositoryError):
568 568 self.repo._local_push(
569 569 'master', target_repo.path, 'master', enable_hooks=True)
570 570
571 571 def test_maybe_prepare_merge_workspace(self):
572 572 workspace = self.repo._maybe_prepare_merge_workspace(
573 573 2, 'pr2', Reference('branch', 'master', 'unused'),
574 574 Reference('branch', 'master', 'unused'))
575 575
576 576 assert os.path.isdir(workspace)
577 577 workspace_repo = GitRepository(workspace)
578 578 assert workspace_repo.branches == self.repo.branches
579 579
580 580 # Calling it a second time should also succeed
581 581 workspace = self.repo._maybe_prepare_merge_workspace(
582 582 2, 'pr2', Reference('branch', 'master', 'unused'),
583 583 Reference('branch', 'master', 'unused'))
584 584 assert os.path.isdir(workspace)
585 585
586 586 def test_maybe_prepare_merge_workspace_different_refs(self):
587 587 workspace = self.repo._maybe_prepare_merge_workspace(
588 588 2, 'pr2', Reference('branch', 'master', 'unused'),
589 589 Reference('branch', 'develop', 'unused'))
590 590
591 591 assert os.path.isdir(workspace)
592 592 workspace_repo = GitRepository(workspace)
593 593 assert workspace_repo.branches == self.repo.branches
594 594
595 595 # Calling it a second time should also succeed
596 596 workspace = self.repo._maybe_prepare_merge_workspace(
597 597 2, 'pr2', Reference('branch', 'master', 'unused'),
598 598 Reference('branch', 'develop', 'unused'))
599 599 assert os.path.isdir(workspace)
600 600
601 601 def test_cleanup_merge_workspace(self):
602 602 workspace = self.repo._maybe_prepare_merge_workspace(
603 603 2, 'pr3', Reference('branch', 'master', 'unused'),
604 604 Reference('branch', 'master', 'unused'))
605 605 self.repo.cleanup_merge_workspace(2, 'pr3')
606 606
607 607 assert not os.path.exists(workspace)
608 608
609 609 def test_cleanup_merge_workspace_invalid_workspace_id(self):
610 610 # No assert: because in case of an inexistent workspace this function
611 611 # should still succeed.
612 612 self.repo.cleanup_merge_workspace(1, 'pr4')
613 613
614 614 def test_set_refs(self):
615 615 test_ref = 'refs/test-refs/abcde'
616 616 test_commit_id = 'ecb86e1f424f2608262b130db174a7dfd25a6623'
617 617
618 618 self.repo.set_refs(test_ref, test_commit_id)
619 619 stdout, _ = self.repo.run_git_command(['show-ref'])
620 620 assert test_ref in stdout
621 621 assert test_commit_id in stdout
622 622
623 623 def test_remove_ref(self):
624 624 test_ref = 'refs/test-refs/abcde'
625 625 test_commit_id = 'ecb86e1f424f2608262b130db174a7dfd25a6623'
626 626 self.repo.set_refs(test_ref, test_commit_id)
627 627 stdout, _ = self.repo.run_git_command(['show-ref'])
628 628 assert test_ref in stdout
629 629 assert test_commit_id in stdout
630 630
631 631 self.repo.remove_ref(test_ref)
632 632 stdout, _ = self.repo.run_git_command(['show-ref'])
633 633 assert test_ref not in stdout
634 634 assert test_commit_id not in stdout
635 635
636 636
637 637 class TestGitCommit(object):
638 638
639 639 @pytest.fixture(autouse=True)
640 640 def prepare(self):
641 641 self.repo = GitRepository(TEST_GIT_REPO)
642 642
643 643 def test_default_commit(self):
644 644 tip = self.repo.get_commit()
645 645 assert tip == self.repo.get_commit(None)
646 646 assert tip == self.repo.get_commit('tip')
647 647
648 648 def test_root_node(self):
649 649 tip = self.repo.get_commit()
650 650 assert tip.root is tip.get_node('')
651 651
652 652 def test_lazy_fetch(self):
653 653 """
654 654 Test if commit's nodes expands and are cached as we walk through
655 655 the commit. This test is somewhat hard to write as order of tests
656 656 is a key here. Written by running command after command in a shell.
657 657 """
658 658 commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
659 659 assert commit_id in self.repo.commit_ids
660 660 commit = self.repo.get_commit(commit_id)
661 661 assert len(commit.nodes) == 0
662 662 root = commit.root
663 663 assert len(commit.nodes) == 1
664 664 assert len(root.nodes) == 8
665 665 # accessing root.nodes updates commit.nodes
666 666 assert len(commit.nodes) == 9
667 667
668 668 docs = root.get_node('docs')
669 669 # we haven't yet accessed anything new as docs dir was already cached
670 670 assert len(commit.nodes) == 9
671 671 assert len(docs.nodes) == 8
672 672 # accessing docs.nodes updates commit.nodes
673 673 assert len(commit.nodes) == 17
674 674
675 675 assert docs is commit.get_node('docs')
676 676 assert docs is root.nodes[0]
677 677 assert docs is root.dirs[0]
678 678 assert docs is commit.get_node('docs')
679 679
680 680 def test_nodes_with_commit(self):
681 681 commit_id = '2a13f185e4525f9d4b59882791a2d397b90d5ddc'
682 682 commit = self.repo.get_commit(commit_id)
683 683 root = commit.root
684 684 docs = root.get_node('docs')
685 685 assert docs is commit.get_node('docs')
686 686 api = docs.get_node('api')
687 687 assert api is commit.get_node('docs/api')
688 688 index = api.get_node('index.rst')
689 689 assert index is commit.get_node('docs/api/index.rst')
690 690 assert index is commit.get_node('docs')\
691 691 .get_node('api')\
692 692 .get_node('index.rst')
693 693
694 694 def test_branch_and_tags(self):
695 695 """
696 696 rev0 = self.repo.commit_ids[0]
697 697 commit0 = self.repo.get_commit(rev0)
698 698 assert commit0.branch == 'master'
699 699 assert commit0.tags == []
700 700
701 701 rev10 = self.repo.commit_ids[10]
702 702 commit10 = self.repo.get_commit(rev10)
703 703 assert commit10.branch == 'master'
704 704 assert commit10.tags == []
705 705
706 706 rev44 = self.repo.commit_ids[44]
707 707 commit44 = self.repo.get_commit(rev44)
708 708 assert commit44.branch == 'web-branch'
709 709
710 710 tip = self.repo.get_commit('tip')
711 711 assert 'tip' in tip.tags
712 712 """
713 713 # Those tests would fail - branches are now going
714 714 # to be changed at main API in order to support git backend
715 715 pass
716 716
717 717 def test_file_size(self):
718 718 to_check = (
719 719 ('c1214f7e79e02fc37156ff215cd71275450cffc3',
720 720 'vcs/backends/BaseRepository.py', 502),
721 721 ('d7e0d30fbcae12c90680eb095a4f5f02505ce501',
722 722 'vcs/backends/hg.py', 854),
723 723 ('6e125e7c890379446e98980d8ed60fba87d0f6d1',
724 724 'setup.py', 1068),
725 725
726 726 ('d955cd312c17b02143c04fa1099a352b04368118',
727 727 'vcs/backends/base.py', 2921),
728 728 ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e',
729 729 'vcs/backends/base.py', 3936),
730 730 ('f50f42baeed5af6518ef4b0cb2f1423f3851a941',
731 731 'vcs/backends/base.py', 6189),
732 732 )
733 733 for commit_id, path, size in to_check:
734 734 node = self.repo.get_commit(commit_id).get_node(path)
735 735 assert node.is_file()
736 736 assert node.size == size
737 737
738 738 def test_file_history_from_commits(self):
739 739 node = self.repo[10].get_node('setup.py')
740 740 commit_ids = [commit.raw_id for commit in node.history]
741 741 assert ['ff7ca51e58c505fec0dd2491de52c622bb7a806b'] == commit_ids
742 742
743 743 node = self.repo[20].get_node('setup.py')
744 744 node_ids = [commit.raw_id for commit in node.history]
745 745 assert ['191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
746 746 'ff7ca51e58c505fec0dd2491de52c622bb7a806b'] == node_ids
747 747
748 748 # special case we check history from commit that has this particular
749 749 # file changed this means we check if it's included as well
750 750 node = self.repo.get_commit('191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e') \
751 751 .get_node('setup.py')
752 752 node_ids = [commit.raw_id for commit in node.history]
753 753 assert ['191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
754 754 'ff7ca51e58c505fec0dd2491de52c622bb7a806b'] == node_ids
755 755
756 756 def test_file_history(self):
757 757 # we can only check if those commits are present in the history
758 758 # as we cannot update this test every time file is changed
759 759 files = {
760 760 'setup.py': [
761 761 '54386793436c938cff89326944d4c2702340037d',
762 762 '51d254f0ecf5df2ce50c0b115741f4cf13985dab',
763 763 '998ed409c795fec2012b1c0ca054d99888b22090',
764 764 '5e0eb4c47f56564395f76333f319d26c79e2fb09',
765 765 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
766 766 '7cb3fd1b6d8c20ba89e2264f1c8baebc8a52d36e',
767 767 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
768 768 '191caa5b2c81ed17c0794bf7bb9958f4dcb0b87e',
769 769 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
770 770 ],
771 771 'vcs/nodes.py': [
772 772 '33fa3223355104431402a888fa77a4e9956feb3e',
773 773 'fa014c12c26d10ba682fadb78f2a11c24c8118e1',
774 774 'e686b958768ee96af8029fe19c6050b1a8dd3b2b',
775 775 'ab5721ca0a081f26bf43d9051e615af2cc99952f',
776 776 'c877b68d18e792a66b7f4c529ea02c8f80801542',
777 777 '4313566d2e417cb382948f8d9d7c765330356054',
778 778 '6c2303a793671e807d1cfc70134c9ca0767d98c2',
779 779 '54386793436c938cff89326944d4c2702340037d',
780 780 '54000345d2e78b03a99d561399e8e548de3f3203',
781 781 '1c6b3677b37ea064cb4b51714d8f7498f93f4b2b',
782 782 '2d03ca750a44440fb5ea8b751176d1f36f8e8f46',
783 783 '2a08b128c206db48c2f0b8f70df060e6db0ae4f8',
784 784 '30c26513ff1eb8e5ce0e1c6b477ee5dc50e2f34b',
785 785 'ac71e9503c2ca95542839af0ce7b64011b72ea7c',
786 786 '12669288fd13adba2a9b7dd5b870cc23ffab92d2',
787 787 '5a0c84f3e6fe3473e4c8427199d5a6fc71a9b382',
788 788 '12f2f5e2b38e6ff3fbdb5d722efed9aa72ecb0d5',
789 789 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
790 790 'f50f42baeed5af6518ef4b0cb2f1423f3851a941',
791 791 'd7e390a45f6aa96f04f5e7f583ad4f867431aa25',
792 792 'f15c21f97864b4f071cddfbf2750ec2e23859414',
793 793 'e906ef056cf539a4e4e5fc8003eaf7cf14dd8ade',
794 794 'ea2b108b48aa8f8c9c4a941f66c1a03315ca1c3b',
795 795 '84dec09632a4458f79f50ddbbd155506c460b4f9',
796 796 '0115510b70c7229dbc5dc49036b32e7d91d23acd',
797 797 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
798 798 '3bf1c5868e570e39569d094f922d33ced2fa3b2b',
799 799 'b8d04012574729d2c29886e53b1a43ef16dd00a1',
800 800 '6970b057cffe4aab0a792aa634c89f4bebf01441',
801 801 'dd80b0f6cf5052f17cc738c2951c4f2070200d7f',
802 802 'ff7ca51e58c505fec0dd2491de52c622bb7a806b',
803 803 ],
804 804 'vcs/backends/git.py': [
805 805 '4cf116ad5a457530381135e2f4c453e68a1b0105',
806 806 '9a751d84d8e9408e736329767387f41b36935153',
807 807 'cb681fb539c3faaedbcdf5ca71ca413425c18f01',
808 808 '428f81bb652bcba8d631bce926e8834ff49bdcc6',
809 809 '180ab15aebf26f98f714d8c68715e0f05fa6e1c7',
810 810 '2b8e07312a2e89e92b90426ab97f349f4bce2a3a',
811 811 '50e08c506174d8645a4bb517dd122ac946a0f3bf',
812 812 '54000345d2e78b03a99d561399e8e548de3f3203',
813 813 ],
814 814 }
815 815 for path, commit_ids in files.items():
816 816 node = self.repo.get_commit(commit_ids[0]).get_node(path)
817 817 node_ids = [commit.raw_id for commit in node.history]
818 818 assert set(commit_ids).issubset(set(node_ids)), (
819 819 "We assumed that %s is subset of commit_ids for which file %s "
820 820 "has been changed, and history of that node returned: %s"
821 821 % (commit_ids, path, node_ids))
822 822
823 823 def test_file_annotate(self):
824 824 files = {
825 825 'vcs/backends/__init__.py': {
826 826 'c1214f7e79e02fc37156ff215cd71275450cffc3': {
827 827 'lines_no': 1,
828 828 'commits': [
829 829 'c1214f7e79e02fc37156ff215cd71275450cffc3',
830 830 ],
831 831 },
832 832 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647': {
833 833 'lines_no': 21,
834 834 'commits': [
835 835 '49d3fd156b6f7db46313fac355dca1a0b94a0017',
836 836 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
837 837 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
838 838 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
839 839 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
840 840 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
841 841 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
842 842 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
843 843 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
844 844 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
845 845 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
846 846 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
847 847 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
848 848 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
849 849 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
850 850 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
851 851 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
852 852 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
853 853 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
854 854 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
855 855 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
856 856 ],
857 857 },
858 858 'e29b67bd158580fc90fc5e9111240b90e6e86064': {
859 859 'lines_no': 32,
860 860 'commits': [
861 861 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
862 862 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
863 863 '5eab1222a7cd4bfcbabc218ca6d04276d4e27378',
864 864 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
865 865 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
866 866 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
867 867 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
868 868 '54000345d2e78b03a99d561399e8e548de3f3203',
869 869 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
870 870 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
871 871 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
872 872 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
873 873 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
874 874 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
875 875 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
876 876 '2a13f185e4525f9d4b59882791a2d397b90d5ddc',
877 877 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
878 878 '78c3f0c23b7ee935ec276acb8b8212444c33c396',
879 879 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
880 880 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
881 881 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
882 882 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
883 883 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
884 884 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
885 885 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
886 886 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
887 887 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
888 888 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
889 889 '992f38217b979d0b0987d0bae3cc26dac85d9b19',
890 890 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
891 891 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
892 892 '16fba1ae9334d79b66d7afed2c2dfbfa2ae53647',
893 893 ],
894 894 },
895 895 },
896 896 }
897 897
898 898 for fname, commit_dict in files.items():
899 899 for commit_id, __ in commit_dict.items():
900 900 commit = self.repo.get_commit(commit_id)
901 901
902 902 l1_1 = [x[1] for x in commit.get_file_annotate(fname)]
903 903 l1_2 = [x[2]().raw_id for x in commit.get_file_annotate(fname)]
904 904 assert l1_1 == l1_2
905 905 l1 = l1_1
906 906 l2 = files[fname][commit_id]['commits']
907 907 assert l1 == l2, (
908 908 "The lists of commit_ids for %s@commit_id %s"
909 909 "from annotation list should match each other, "
910 910 "got \n%s \nvs \n%s " % (fname, commit_id, l1, l2))
911 911
912 912 def test_files_state(self):
913 913 """
914 914 Tests state of FileNodes.
915 915 """
916 916 node = self.repo\
917 917 .get_commit('e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0')\
918 918 .get_node('vcs/utils/diffs.py')
919 919 assert node.state, NodeState.ADDED
920 920 assert node.added
921 921 assert not node.changed
922 922 assert not node.not_changed
923 923 assert not node.removed
924 924
925 925 node = self.repo\
926 926 .get_commit('33fa3223355104431402a888fa77a4e9956feb3e')\
927 927 .get_node('.hgignore')
928 928 assert node.state, NodeState.CHANGED
929 929 assert not node.added
930 930 assert node.changed
931 931 assert not node.not_changed
932 932 assert not node.removed
933 933
934 934 node = self.repo\
935 935 .get_commit('e29b67bd158580fc90fc5e9111240b90e6e86064')\
936 936 .get_node('setup.py')
937 937 assert node.state, NodeState.NOT_CHANGED
938 938 assert not node.added
939 939 assert not node.changed
940 940 assert node.not_changed
941 941 assert not node.removed
942 942
943 943 # If node has REMOVED state then trying to fetch it would raise
944 944 # CommitError exception
945 945 commit = self.repo.get_commit(
946 946 'fa6600f6848800641328adbf7811fd2372c02ab2')
947 947 path = 'vcs/backends/BaseRepository.py'
948 948 with pytest.raises(NodeDoesNotExistError):
949 949 commit.get_node(path)
950 950 # but it would be one of ``removed`` (commit's attribute)
951 951 assert path in [rf.path for rf in commit.removed]
952 952
953 953 commit = self.repo.get_commit(
954 954 '54386793436c938cff89326944d4c2702340037d')
955 955 changed = [
956 956 'setup.py', 'tests/test_nodes.py', 'vcs/backends/hg.py',
957 957 'vcs/nodes.py']
958 958 assert set(changed) == set([f.path for f in commit.changed])
959 959
960 960 def test_unicode_branch_refs(self):
961 961 unicode_branches = {
962 962 'refs/heads/unicode': '6c0ce52b229aa978889e91b38777f800e85f330b',
963 963 u'refs/heads/uniΓ§ΓΆβˆ‚e': 'ΓΌrl',
964 964 }
965 965 with mock.patch(
966 966 ("rhodecode.lib.vcs.backends.git.repository"
967 967 ".GitRepository._refs"),
968 968 unicode_branches):
969 969 branches = self.repo.branches
970 970
971 971 assert 'unicode' in branches
972 972 assert u'uniΓ§ΓΆβˆ‚e' in branches
973 973
974 974 def test_unicode_tag_refs(self):
975 975 unicode_tags = {
976 976 'refs/tags/unicode': '6c0ce52b229aa978889e91b38777f800e85f330b',
977 977 u'refs/tags/uniΓ§ΓΆβˆ‚e': '6c0ce52b229aa978889e91b38777f800e85f330b',
978 978 }
979 979 with mock.patch(
980 980 ("rhodecode.lib.vcs.backends.git.repository"
981 981 ".GitRepository._refs"),
982 982 unicode_tags):
983 983 tags = self.repo.tags
984 984
985 985 assert 'unicode' in tags
986 986 assert u'uniΓ§ΓΆβˆ‚e' in tags
987 987
988 988 def test_commit_message_is_unicode(self):
989 989 for commit in self.repo:
990 990 assert type(commit.message) == str
991 991
992 992 def test_commit_author_is_unicode(self):
993 993 for commit in self.repo:
994 994 assert type(commit.author) == str
995 995
996 996 def test_repo_files_content_types(self):
997 997 commit = self.repo.get_commit()
998 998 for node in commit.get_node('/'):
999 999 if node.is_file():
1000 1000 assert type(node.content) == bytes
1001 1001 assert type(node.str_content) == str
1002 1002
1003 1003 def test_wrong_path(self):
1004 1004 # There is 'setup.py' in the root dir but not there:
1005 1005 path = 'foo/bar/setup.py'
1006 1006 tip = self.repo.get_commit()
1007 1007 with pytest.raises(VCSError):
1008 1008 tip.get_node(path)
1009 1009
1010 1010 @pytest.mark.parametrize("author_email, commit_id", [
1011 1011 ('marcin@python-blog.com', 'c1214f7e79e02fc37156ff215cd71275450cffc3'),
1012 1012 ('lukasz.balcerzak@python-center.pl',
1013 1013 'ff7ca51e58c505fec0dd2491de52c622bb7a806b'),
1014 1014 ('none@none', '8430a588b43b5d6da365400117c89400326e7992'),
1015 1015 ])
1016 1016 def test_author_email(self, author_email, commit_id):
1017 1017 commit = self.repo.get_commit(commit_id)
1018 1018 assert author_email == commit.author_email
1019 1019
1020 1020 @pytest.mark.parametrize("author, commit_id", [
1021 1021 ('Marcin Kuzminski', 'c1214f7e79e02fc37156ff215cd71275450cffc3'),
1022 1022 ('Lukasz Balcerzak', 'ff7ca51e58c505fec0dd2491de52c622bb7a806b'),
1023 1023 ('marcink', '8430a588b43b5d6da365400117c89400326e7992'),
1024 1024 ])
1025 1025 def test_author_username(self, author, commit_id):
1026 1026 commit = self.repo.get_commit(commit_id)
1027 1027 assert author == commit.author_name
1028 1028
1029 1029
1030 1030 class TestLargeFileRepo(object):
1031 1031
1032 1032 def test_large_file(self, backend_git):
1033 1033 conf = make_db_config()
1034 1034 repo = backend_git.create_test_repo('largefiles', conf)
1035 1035
1036 1036 tip = repo.scm_instance().get_commit()
1037 1037
1038 1038 # extract stored LF node into the origin cache
1039 1039 lfs_store = os.path.join(repo.repo_path, repo.repo_name, 'lfs_store')
1040 1040
1041 1041 oid = '7b331c02e313c7599d5a90212e17e6d3cb729bd2e1c9b873c302a63c95a2f9bf'
1042 1042 oid_path = os.path.join(lfs_store, oid)
1043 1043 oid_destination = os.path.join(
1044 1044 conf.get('vcs_git_lfs', 'store_location'), oid)
1045 1045 shutil.copy(oid_path, oid_destination)
1046 1046
1047 1047 node = tip.get_node('1MB.zip')
1048 1048
1049 1049 lf_node = node.get_largefile_node()
1050 1050
1051 1051 assert lf_node.is_largefile() is True
1052 1052 assert lf_node.size == 1024000
1053 1053 assert lf_node.name == '1MB.zip'
1054 1054
1055 1055
1056 1056 @pytest.mark.usefixtures("vcs_repository_support")
1057 1057 class TestGitSpecificWithRepo(BackendTestMixin):
1058 1058
1059 1059 @classmethod
1060 1060 def _get_commits(cls):
1061 1061 return [
1062 1062 {
1063 1063 'message': 'Initial',
1064 1064 'author': 'Joe Doe <joe.doe@example.com>',
1065 1065 'date': datetime.datetime(2010, 1, 1, 20),
1066 1066 'added': [
1067 1067 FileNode(b'foobar/static/js/admin/base.js', content=b'base'),
1068 1068 FileNode(b'foobar/static/admin', content=b'admin', mode=0o120000), # this is a link
1069 1069 FileNode(b'foo', content=b'foo'),
1070 1070 ],
1071 1071 },
1072 1072 {
1073 1073 'message': 'Second',
1074 1074 'author': 'Joe Doe <joe.doe@example.com>',
1075 1075 'date': datetime.datetime(2010, 1, 1, 22),
1076 1076 'added': [
1077 1077 FileNode(b'foo2', content=b'foo2'),
1078 1078 ],
1079 1079 },
1080 1080 ]
1081 1081
1082 1082 def test_paths_slow_traversing(self):
1083 1083 commit = self.repo.get_commit()
1084 1084 assert commit.get_node('foobar').get_node('static').get_node('js')\
1085 1085 .get_node('admin').get_node('base.js').content == b'base'
1086 1086
1087 1087 def test_paths_fast_traversing(self):
1088 1088 commit = self.repo.get_commit()
1089 1089 assert commit.get_node('foobar/static/js/admin/base.js').content == b'base'
1090 1090
1091 1091 def test_get_diff_runs_git_command_with_hashes(self):
1092 1092 comm1 = self.repo[0]
1093 1093 comm2 = self.repo[1]
1094 1094
1095 1095 with mock.patch.object(self.repo, '_remote', return_value=mock.Mock()) as remote_mock:
1096 1096 remote_mock.diff = mock.MagicMock(side_effect=callable_get_diff)
1097 1097 self.repo.get_diff(comm1, comm2)
1098 1098
1099 1099 remote_mock.diff.assert_called_once_with(
1100 1100 comm1.raw_id, comm2.raw_id,
1101 1101 file_filter=None, opt_ignorews=False, context=3)
1102 1102
1103 1103 def test_get_diff_runs_git_command_with_str_hashes(self):
1104 1104 comm2 = self.repo[1]
1105 1105
1106 1106 with mock.patch.object(self.repo, '_remote', return_value=mock.Mock()) as remote_mock:
1107 1107 remote_mock.diff = mock.MagicMock(side_effect=callable_get_diff)
1108 1108 self.repo.get_diff(self.repo.EMPTY_COMMIT, comm2)
1109 1109
1110 1110 remote_mock.diff.assert_called_once_with(
1111 1111 self.repo.EMPTY_COMMIT.raw_id, comm2.raw_id,
1112 1112 file_filter=None, opt_ignorews=False, context=3)
1113 1113
1114 1114 def test_get_diff_runs_git_command_with_path_if_its_given(self):
1115 1115 comm1 = self.repo[0]
1116 1116 comm2 = self.repo[1]
1117 1117
1118 1118 with mock.patch.object(self.repo, '_remote', return_value=mock.Mock()) as remote_mock:
1119 1119 remote_mock.diff = mock.MagicMock(side_effect=callable_get_diff)
1120 1120 self.repo.get_diff(comm1, comm2, 'foo')
1121 1121
1122 1122 remote_mock.diff.assert_called_once_with(
1123 1123 self.repo._lookup_commit(0), comm2.raw_id,
1124 1124 file_filter='foo', opt_ignorews=False, context=3)
1125 1125
1126 1126
1127 1127 @pytest.mark.usefixtures("vcs_repository_support")
1128 1128 class TestGitRegression(BackendTestMixin):
1129 1129
1130 1130 @classmethod
1131 1131 def _get_commits(cls):
1132 1132 return [
1133 1133 {
1134 1134 'message': 'Initial',
1135 1135 'author': 'Joe Doe <joe.doe@example.com>',
1136 1136 'date': datetime.datetime(2010, 1, 1, 20),
1137 1137 'added': [
1138 1138 FileNode(b'bot/__init__.py', content=b'base'),
1139 1139 FileNode(b'bot/templates/404.html', content=b'base'),
1140 1140 FileNode(b'bot/templates/500.html', content=b'base'),
1141 1141 ],
1142 1142 },
1143 1143 {
1144 1144 'message': 'Second',
1145 1145 'author': 'Joe Doe <joe.doe@example.com>',
1146 1146 'date': datetime.datetime(2010, 1, 1, 22),
1147 1147 'added': [
1148 1148 FileNode(b'bot/build/migrations/1.py', content=b'foo2'),
1149 1149 FileNode(b'bot/build/migrations/2.py', content=b'foo2'),
1150 1150 FileNode(b'bot/build/static/templates/f.html', content=b'foo2'),
1151 1151 FileNode(b'bot/build/static/templates/f1.html', content=b'foo2'),
1152 1152 FileNode(b'bot/build/templates/err.html', content=b'foo2'),
1153 1153 FileNode(b'bot/build/templates/err2.html', content=b'foo2'),
1154 1154 ],
1155 1155 },
1156 1156 ]
1157 1157
1158 1158 @pytest.mark.parametrize("path, expected_paths", [
1159 1159 ('bot', [
1160 1160 'bot/build',
1161 1161 'bot/templates',
1162 1162 'bot/__init__.py']),
1163 1163 ('bot/build', [
1164 1164 'bot/build/migrations',
1165 1165 'bot/build/static',
1166 1166 'bot/build/templates']),
1167 1167 ('bot/build/static', [
1168 1168 'bot/build/static/templates']),
1169 1169 ('bot/build/static/templates', [
1170 1170 'bot/build/static/templates/f.html',
1171 1171 'bot/build/static/templates/f1.html']),
1172 1172 ('bot/build/templates', [
1173 1173 'bot/build/templates/err.html',
1174 1174 'bot/build/templates/err2.html']),
1175 1175 ('bot/templates/', [
1176 1176 'bot/templates/404.html',
1177 1177 'bot/templates/500.html']),
1178 1178 ])
1179 1179 def test_similar_paths(self, path, expected_paths):
1180 1180 commit = self.repo.get_commit()
1181 1181 paths = [n.path for n in commit.get_nodes(path)]
1182 1182 assert paths == expected_paths
1183 1183
1184 1184
1185 1185 class TestDiscoverGitVersion(object):
1186 1186
1187 1187 def test_returns_git_version(self, baseapp):
1188 1188 version = discover_git_version()
1189 1189 assert version
1190 1190
1191 1191 def test_returns_empty_string_without_vcsserver(self):
1192 1192 mock_connection = mock.Mock()
1193 1193 mock_connection.discover_git_version = mock.Mock(
1194 1194 side_effect=Exception)
1195 1195 with mock.patch('rhodecode.lib.vcs.connection.Git', mock_connection):
1196 1196 version = discover_git_version()
1197 1197 assert version == ''
1198 1198
1199 1199
1200 1200 class TestGetSubmoduleUrl(object):
1201 1201 def test_submodules_file_found(self):
1202 1202 commit = GitCommit(repository=mock.Mock(), raw_id='abcdef12', idx=1)
1203 1203 node = mock.Mock()
1204
1204 1205 with mock.patch.object(
1205 1206 commit, 'get_node', return_value=node) as get_node_mock:
1206 node.content = (
1207 node.str_content = (
1207 1208 '[submodule "subrepo1"]\n'
1208 1209 '\tpath = subrepo1\n'
1209 1210 '\turl = https://code.rhodecode.com/dulwich\n'
1210 1211 )
1211 1212 result = commit._get_submodule_url('subrepo1')
1212 1213 get_node_mock.assert_called_once_with('.gitmodules')
1213 1214 assert result == 'https://code.rhodecode.com/dulwich'
1214 1215
1215 1216 def test_complex_submodule_path(self):
1216 1217 commit = GitCommit(repository=mock.Mock(), raw_id='abcdef12', idx=1)
1217 1218 node = mock.Mock()
1219
1218 1220 with mock.patch.object(
1219 1221 commit, 'get_node', return_value=node) as get_node_mock:
1220 node.content = (
1222 node.str_content = (
1221 1223 '[submodule "complex/subrepo/path"]\n'
1222 1224 '\tpath = complex/subrepo/path\n'
1223 1225 '\turl = https://code.rhodecode.com/dulwich\n'
1224 1226 )
1225 1227 result = commit._get_submodule_url('complex/subrepo/path')
1226 1228 get_node_mock.assert_called_once_with('.gitmodules')
1227 1229 assert result == 'https://code.rhodecode.com/dulwich'
1228 1230
1229 1231 def test_submodules_file_not_found(self):
1230 1232 commit = GitCommit(repository=mock.Mock(), raw_id='abcdef12', idx=1)
1231 1233 with mock.patch.object(
1232 1234 commit, 'get_node', side_effect=NodeDoesNotExistError):
1233 1235 result = commit._get_submodule_url('complex/subrepo/path')
1234 1236 assert result is None
1235 1237
1236 1238 def test_path_not_found(self):
1237 1239 commit = GitCommit(repository=mock.Mock(), raw_id='abcdef12', idx=1)
1238 1240 node = mock.Mock()
1241
1239 1242 with mock.patch.object(
1240 1243 commit, 'get_node', return_value=node) as get_node_mock:
1241 node.content = (
1244 node.str_content = (
1242 1245 '[submodule "subrepo1"]\n'
1243 1246 '\tpath = subrepo1\n'
1244 1247 '\turl = https://code.rhodecode.com/dulwich\n'
1245 1248 )
1246 1249 result = commit._get_submodule_url('subrepo2')
1247 1250 get_node_mock.assert_called_once_with('.gitmodules')
1248 1251 assert result is None
1249 1252
1250 1253 def test_returns_cached_values(self):
1251 1254 commit = GitCommit(repository=mock.Mock(), raw_id='abcdef12', idx=1)
1252 1255 node = mock.Mock()
1256
1253 1257 with mock.patch.object(
1254 1258 commit, 'get_node', return_value=node) as get_node_mock:
1255 node.content = (
1259 node.str_content = (
1256 1260 '[submodule "subrepo1"]\n'
1257 1261 '\tpath = subrepo1\n'
1258 1262 '\turl = https://code.rhodecode.com/dulwich\n'
1259 1263 )
1260 1264 for _ in range(3):
1261 1265 commit._get_submodule_url('subrepo1')
1262 1266 get_node_mock.assert_called_once_with('.gitmodules')
1263 1267
1264 1268 def test_get_node_returns_a_link(self):
1265 1269 repository = mock.Mock()
1266 1270 repository.alias = 'git'
1267 1271 commit = GitCommit(repository=repository, raw_id='abcdef12', idx=1)
1268 1272 submodule_url = 'https://code.rhodecode.com/dulwich'
1269 1273 get_id_patch = mock.patch.object(
1270 1274 commit, '_get_tree_id_for_path', return_value=(1, 'link'))
1271 1275 get_submodule_patch = mock.patch.object(
1272 1276 commit, '_get_submodule_url', return_value=submodule_url)
1273 1277
1274 1278 with get_id_patch, get_submodule_patch as submodule_mock:
1275 1279 node = commit.get_node('/abcde')
1276 1280
1277 1281 submodule_mock.assert_called_once_with('/abcde')
1278 1282 assert type(node) == SubModuleNode
1279 1283 assert node.url == submodule_url
1280 1284
1281 1285 def test_get_nodes_returns_links(self):
1282 1286 repository = mock.MagicMock()
1283 1287 repository.alias = 'git'
1284 1288 repository._remote.tree_items.return_value = [
1285 1289 ('subrepo', 'stat', 1, 'link')
1286 1290 ]
1287 1291 commit = GitCommit(repository=repository, raw_id='abcdef12', idx=1)
1288 1292 submodule_url = 'https://code.rhodecode.com/dulwich'
1289 1293 get_id_patch = mock.patch.object(
1290 1294 commit, '_get_tree_id_for_path', return_value=(1, 'tree'))
1291 1295 get_submodule_patch = mock.patch.object(
1292 1296 commit, '_get_submodule_url', return_value=submodule_url)
1293 1297
1294 1298 with get_id_patch, get_submodule_patch as submodule_mock:
1295 1299 nodes = commit.get_nodes('/abcde')
1296 1300
1297 1301 submodule_mock.assert_called_once_with('/abcde/subrepo')
1298 1302 assert len(nodes) == 1
1299 1303 assert type(nodes[0]) == SubModuleNode
1300 1304 assert nodes[0].url == submodule_url
General Comments 0
You need to be logged in to leave comments. Login now