##// END OF EJS Templates
tests: Adapt tests to new merge response object.
Martin Bornhold -
r1053:a4bf20df default
parent child Browse files
Show More
@@ -1,1172 +1,1172 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import os
22 22
23 23 import mock
24 24 import pytest
25 25
26 26 import rhodecode.lib.vcs.conf.settings
27 27 from rhodecode.lib.vcs import backends
28 28 from rhodecode.lib.vcs.backends.base import (
29 29 Reference, MergeResponse, MergeFailureReason)
30 30 from rhodecode.lib.vcs.backends.hg import MercurialRepository, MercurialCommit
31 31 from rhodecode.lib.vcs.exceptions import (
32 32 CommitError, RepositoryError, VCSError, NodeDoesNotExistError,
33 33 CommitDoesNotExistError)
34 34 from rhodecode.lib.vcs.nodes import FileNode, NodeKind, NodeState
35 35 from rhodecode.tests import TEST_HG_REPO, TEST_HG_REPO_CLONE
36 36
37 37
38 38 pytestmark = pytest.mark.backends("hg")
39 39
40 40
41 41 def repo_path_generator():
42 42 """
43 43 Return a different path to be used for cloning repos.
44 44 """
45 45 i = 0
46 46 while True:
47 47 i += 1
48 48 yield '%s-%d' % (TEST_HG_REPO_CLONE, i)
49 49
50 50
51 51 REPO_PATH_GENERATOR = repo_path_generator()
52 52
53 53
54 54 @pytest.fixture(scope='class', autouse=True)
55 55 def repo(request, pylonsapp):
56 56 repo = MercurialRepository(TEST_HG_REPO)
57 57 if request.cls:
58 58 request.cls.repo = repo
59 59 return repo
60 60
61 61
62 62 class TestMercurialRepository:
63 63
64 64 # pylint: disable=protected-access
65 65
66 66 def get_clone_repo(self):
67 67 """
68 68 Return a clone of the base repo.
69 69 """
70 70 clone_path = next(REPO_PATH_GENERATOR)
71 71 repo_clone = MercurialRepository(
72 72 clone_path, create=True, src_url=self.repo.path)
73 73
74 74 return repo_clone
75 75
76 76 def get_empty_repo(self):
77 77 """
78 78 Return an empty repo.
79 79 """
80 80 return MercurialRepository(next(REPO_PATH_GENERATOR), create=True)
81 81
82 82 def test_wrong_repo_path(self):
83 83 wrong_repo_path = '/tmp/errorrepo'
84 84 with pytest.raises(RepositoryError):
85 85 MercurialRepository(wrong_repo_path)
86 86
87 87 def test_unicode_path_repo(self):
88 88 with pytest.raises(VCSError):
89 89 MercurialRepository(u'iShouldFail')
90 90
91 91 def test_unicode_commit_id(self):
92 92 with pytest.raises(CommitDoesNotExistError):
93 93 self.repo.get_commit(u'unicode-commit-id')
94 94 with pytest.raises(CommitDoesNotExistError):
95 95 self.repo.get_commit(u'unΓ­cΓΈde-spéçial-chΓ€rΓ₯cter-commit-id')
96 96
97 97 def test_unicode_bookmark(self):
98 98 self.repo.bookmark(u'unicode-bookmark')
99 99 self.repo.bookmark(u'unΓ­cΓΈde-spéçial-chΓ€rΓ₯cter-bookmark')
100 100
101 101 def test_unicode_branch(self):
102 102 with pytest.raises(KeyError):
103 103 self.repo.branches[u'unicode-branch']
104 104 with pytest.raises(KeyError):
105 105 self.repo.branches[u'unΓ­cΓΈde-spéçial-chΓ€rΓ₯cter-branch']
106 106
107 107 def test_repo_clone(self):
108 108 if os.path.exists(TEST_HG_REPO_CLONE):
109 109 self.fail(
110 110 'Cannot test mercurial clone repo as location %s already '
111 111 'exists. You should manually remove it first.'
112 112 % TEST_HG_REPO_CLONE)
113 113
114 114 repo = MercurialRepository(TEST_HG_REPO)
115 115 repo_clone = MercurialRepository(TEST_HG_REPO_CLONE,
116 116 src_url=TEST_HG_REPO)
117 117 assert len(repo.commit_ids) == len(repo_clone.commit_ids)
118 118 # Checking hashes of commits should be enough
119 119 for commit in repo.get_commits():
120 120 raw_id = commit.raw_id
121 121 assert raw_id == repo_clone.get_commit(raw_id).raw_id
122 122
123 123 def test_repo_clone_with_update(self):
124 124 repo = MercurialRepository(TEST_HG_REPO)
125 125 repo_clone = MercurialRepository(
126 126 TEST_HG_REPO_CLONE + '_w_update',
127 127 src_url=TEST_HG_REPO, update_after_clone=True)
128 128 assert len(repo.commit_ids) == len(repo_clone.commit_ids)
129 129
130 130 # check if current workdir was updated
131 131 assert os.path.isfile(
132 132 os.path.join(TEST_HG_REPO_CLONE + '_w_update', 'MANIFEST.in'))
133 133
134 134 def test_repo_clone_without_update(self):
135 135 repo = MercurialRepository(TEST_HG_REPO)
136 136 repo_clone = MercurialRepository(
137 137 TEST_HG_REPO_CLONE + '_wo_update',
138 138 src_url=TEST_HG_REPO, update_after_clone=False)
139 139 assert len(repo.commit_ids) == len(repo_clone.commit_ids)
140 140 assert not os.path.isfile(
141 141 os.path.join(TEST_HG_REPO_CLONE + '_wo_update', 'MANIFEST.in'))
142 142
143 143 def test_commit_ids(self):
144 144 # there are 21 commits at bitbucket now
145 145 # so we can assume they would be available from now on
146 146 subset = set([
147 147 'b986218ba1c9b0d6a259fac9b050b1724ed8e545',
148 148 '3d8f361e72ab303da48d799ff1ac40d5ac37c67e',
149 149 '6cba7170863a2411822803fa77a0a264f1310b35',
150 150 '56349e29c2af3ac913b28bde9a2c6154436e615b',
151 151 '2dda4e345facb0ccff1a191052dd1606dba6781d',
152 152 '6fff84722075f1607a30f436523403845f84cd9e',
153 153 '7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7',
154 154 '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb',
155 155 'dc5d2c0661b61928834a785d3e64a3f80d3aad9c',
156 156 'be90031137367893f1c406e0a8683010fd115b79',
157 157 'db8e58be770518cbb2b1cdfa69146e47cd481481',
158 158 '84478366594b424af694a6c784cb991a16b87c21',
159 159 '17f8e105dddb9f339600389c6dc7175d395a535c',
160 160 '20a662e756499bde3095ffc9bc0643d1def2d0eb',
161 161 '2e319b85e70a707bba0beff866d9f9de032aa4f9',
162 162 '786facd2c61deb9cf91e9534735124fb8fc11842',
163 163 '94593d2128d38210a2fcd1aabff6dda0d6d9edf8',
164 164 'aa6a0de05b7612707db567078e130a6cd114a9a7',
165 165 'eada5a770da98ab0dd7325e29d00e0714f228d09'
166 166 ])
167 167 assert subset.issubset(set(self.repo.commit_ids))
168 168
169 169 # check if we have the proper order of commits
170 170 org = [
171 171 'b986218ba1c9b0d6a259fac9b050b1724ed8e545',
172 172 '3d8f361e72ab303da48d799ff1ac40d5ac37c67e',
173 173 '6cba7170863a2411822803fa77a0a264f1310b35',
174 174 '56349e29c2af3ac913b28bde9a2c6154436e615b',
175 175 '2dda4e345facb0ccff1a191052dd1606dba6781d',
176 176 '6fff84722075f1607a30f436523403845f84cd9e',
177 177 '7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7',
178 178 '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb',
179 179 'dc5d2c0661b61928834a785d3e64a3f80d3aad9c',
180 180 'be90031137367893f1c406e0a8683010fd115b79',
181 181 'db8e58be770518cbb2b1cdfa69146e47cd481481',
182 182 '84478366594b424af694a6c784cb991a16b87c21',
183 183 '17f8e105dddb9f339600389c6dc7175d395a535c',
184 184 '20a662e756499bde3095ffc9bc0643d1def2d0eb',
185 185 '2e319b85e70a707bba0beff866d9f9de032aa4f9',
186 186 '786facd2c61deb9cf91e9534735124fb8fc11842',
187 187 '94593d2128d38210a2fcd1aabff6dda0d6d9edf8',
188 188 'aa6a0de05b7612707db567078e130a6cd114a9a7',
189 189 'eada5a770da98ab0dd7325e29d00e0714f228d09',
190 190 '2c1885c735575ca478bf9e17b0029dca68824458',
191 191 'd9bcd465040bf869799b09ad732c04e0eea99fe9',
192 192 '469e9c847fe1f6f7a697b8b25b4bc5b48780c1a7',
193 193 '4fb8326d78e5120da2c7468dcf7098997be385da',
194 194 '62b4a097164940bd66030c4db51687f3ec035eed',
195 195 '536c1a19428381cfea92ac44985304f6a8049569',
196 196 '965e8ab3c44b070cdaa5bf727ddef0ada980ecc4',
197 197 '9bb326a04ae5d98d437dece54be04f830cf1edd9',
198 198 'f8940bcb890a98c4702319fbe36db75ea309b475',
199 199 'ff5ab059786ebc7411e559a2cc309dfae3625a3b',
200 200 '6b6ad5f82ad5bb6190037671bd254bd4e1f4bf08',
201 201 'ee87846a61c12153b51543bf860e1026c6d3dcba',
202 202 ]
203 203 assert org == self.repo.commit_ids[:31]
204 204
205 205 def test_iter_slice(self):
206 206 sliced = list(self.repo[:10])
207 207 itered = list(self.repo)[:10]
208 208 assert sliced == itered
209 209
210 210 def test_slicing(self):
211 211 # 4 1 5 10 95
212 212 for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5),
213 213 (10, 20, 10), (5, 100, 95)]:
214 214 indexes = list(self.repo[sfrom:sto])
215 215 assert len(indexes) == size
216 216 assert indexes[0] == self.repo.get_commit(commit_idx=sfrom)
217 217 assert indexes[-1] == self.repo.get_commit(commit_idx=sto - 1)
218 218
219 219 def test_branches(self):
220 220 # TODO: Need more tests here
221 221
222 222 # active branches
223 223 assert 'default' in self.repo.branches
224 224 assert 'stable' in self.repo.branches
225 225
226 226 # closed
227 227 assert 'git' in self.repo._get_branches(closed=True)
228 228 assert 'web' in self.repo._get_branches(closed=True)
229 229
230 230 for name, id in self.repo.branches.items():
231 231 assert isinstance(self.repo.get_commit(id), MercurialCommit)
232 232
233 233 def test_tip_in_tags(self):
234 234 # tip is always a tag
235 235 assert 'tip' in self.repo.tags
236 236
237 237 def test_tip_commit_in_tags(self):
238 238 tip = self.repo.get_commit()
239 239 assert self.repo.tags['tip'] == tip.raw_id
240 240
241 241 def test_initial_commit(self):
242 242 init_commit = self.repo.get_commit(commit_idx=0)
243 243 init_author = init_commit.author
244 244
245 245 assert init_commit.message == 'initial import'
246 246 assert init_author == 'Marcin Kuzminski <marcin@python-blog.com>'
247 247 assert init_author == init_commit.committer
248 248 assert sorted(init_commit._file_paths) == sorted([
249 249 'vcs/__init__.py',
250 250 'vcs/backends/BaseRepository.py',
251 251 'vcs/backends/__init__.py',
252 252 ])
253 253 assert sorted(init_commit._dir_paths) == sorted(
254 254 ['', 'vcs', 'vcs/backends'])
255 255
256 256 assert init_commit._dir_paths + init_commit._file_paths == \
257 257 init_commit._paths
258 258
259 259 with pytest.raises(NodeDoesNotExistError):
260 260 init_commit.get_node(path='foobar')
261 261
262 262 node = init_commit.get_node('vcs/')
263 263 assert hasattr(node, 'kind')
264 264 assert node.kind == NodeKind.DIR
265 265
266 266 node = init_commit.get_node('vcs')
267 267 assert hasattr(node, 'kind')
268 268 assert node.kind == NodeKind.DIR
269 269
270 270 node = init_commit.get_node('vcs/__init__.py')
271 271 assert hasattr(node, 'kind')
272 272 assert node.kind == NodeKind.FILE
273 273
274 274 def test_not_existing_commit(self):
275 275 # rawid
276 276 with pytest.raises(RepositoryError):
277 277 self.repo.get_commit('abcd' * 10)
278 278 # shortid
279 279 with pytest.raises(RepositoryError):
280 280 self.repo.get_commit('erro' * 4)
281 281 # numeric
282 282 with pytest.raises(RepositoryError):
283 283 self.repo.get_commit(commit_idx=self.repo.count() + 1)
284 284
285 285 # Small chance we ever get to this one
286 286 idx = pow(2, 30)
287 287 with pytest.raises(RepositoryError):
288 288 self.repo.get_commit(commit_idx=idx)
289 289
290 290 def test_commit10(self):
291 291 commit10 = self.repo.get_commit(commit_idx=10)
292 292 README = """===
293 293 VCS
294 294 ===
295 295
296 296 Various Version Control System management abstraction layer for Python.
297 297
298 298 Introduction
299 299 ------------
300 300
301 301 TODO: To be written...
302 302
303 303 """
304 304 node = commit10.get_node('README.rst')
305 305 assert node.kind == NodeKind.FILE
306 306 assert node.content == README
307 307
308 308 def test_local_clone(self):
309 309 clone_path = next(REPO_PATH_GENERATOR)
310 310 self.repo._local_clone(clone_path)
311 311 repo_clone = MercurialRepository(clone_path)
312 312
313 313 assert self.repo.commit_ids == repo_clone.commit_ids
314 314
315 315 def test_local_clone_fails_if_target_exists(self):
316 316 with pytest.raises(RepositoryError):
317 317 self.repo._local_clone(self.repo.path)
318 318
319 319 def test_update(self):
320 320 repo_clone = self.get_clone_repo()
321 321 branches = repo_clone.branches
322 322
323 323 repo_clone._update('default')
324 324 assert branches['default'] == repo_clone._identify()
325 325 repo_clone._update('stable')
326 326 assert branches['stable'] == repo_clone._identify()
327 327
328 328 def test_local_pull_branch(self):
329 329 target_repo = self.get_empty_repo()
330 330 source_repo = self.get_clone_repo()
331 331
332 332 default = Reference(
333 333 'branch', 'default', source_repo.branches['default'])
334 334 target_repo._local_pull(source_repo.path, default)
335 335 target_repo = MercurialRepository(target_repo.path)
336 336 assert (target_repo.branches['default'] ==
337 337 source_repo.branches['default'])
338 338
339 339 stable = Reference('branch', 'stable', source_repo.branches['stable'])
340 340 target_repo._local_pull(source_repo.path, stable)
341 341 target_repo = MercurialRepository(target_repo.path)
342 342 assert target_repo.branches['stable'] == source_repo.branches['stable']
343 343
344 344 def test_local_pull_bookmark(self):
345 345 target_repo = self.get_empty_repo()
346 346 source_repo = self.get_clone_repo()
347 347
348 348 commits = list(source_repo.get_commits(branch_name='default'))
349 349 foo1_id = commits[-5].raw_id
350 350 foo1 = Reference('book', 'foo1', foo1_id)
351 351 source_repo._update(foo1_id)
352 352 source_repo.bookmark('foo1')
353 353
354 354 foo2_id = commits[-3].raw_id
355 355 foo2 = Reference('book', 'foo2', foo2_id)
356 356 source_repo._update(foo2_id)
357 357 source_repo.bookmark('foo2')
358 358
359 359 target_repo._local_pull(source_repo.path, foo1)
360 360 target_repo = MercurialRepository(target_repo.path)
361 361 assert target_repo.branches['default'] == commits[-5].raw_id
362 362
363 363 target_repo._local_pull(source_repo.path, foo2)
364 364 target_repo = MercurialRepository(target_repo.path)
365 365 assert target_repo.branches['default'] == commits[-3].raw_id
366 366
367 367 def test_local_pull_commit(self):
368 368 target_repo = self.get_empty_repo()
369 369 source_repo = self.get_clone_repo()
370 370
371 371 commits = list(source_repo.get_commits(branch_name='default'))
372 372 commit_id = commits[-5].raw_id
373 373 commit = Reference('rev', commit_id, commit_id)
374 374 target_repo._local_pull(source_repo.path, commit)
375 375 target_repo = MercurialRepository(target_repo.path)
376 376 assert target_repo.branches['default'] == commit_id
377 377
378 378 commit_id = commits[-3].raw_id
379 379 commit = Reference('rev', commit_id, commit_id)
380 380 target_repo._local_pull(source_repo.path, commit)
381 381 target_repo = MercurialRepository(target_repo.path)
382 382 assert target_repo.branches['default'] == commit_id
383 383
384 384 def test_local_pull_from_same_repo(self):
385 385 reference = Reference('branch', 'default', None)
386 386 with pytest.raises(ValueError):
387 387 self.repo._local_pull(self.repo.path, reference)
388 388
389 389 def test_validate_pull_reference_raises_on_missing_reference(
390 390 self, vcsbackend_hg):
391 391 target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
392 392 reference = Reference(
393 393 'book', 'invalid_reference', 'a' * 40)
394 394
395 395 with pytest.raises(CommitDoesNotExistError):
396 396 target_repo._validate_pull_reference(reference)
397 397
398 398 def test_heads(self):
399 399 assert set(self.repo._heads()) == set(self.repo.branches.values())
400 400
401 401 def test_ancestor(self):
402 402 commits = [
403 403 c.raw_id for c in self.repo.get_commits(branch_name='default')]
404 404 assert self.repo._ancestor(commits[-3], commits[-5]) == commits[-5]
405 405 assert self.repo._ancestor(commits[-5], commits[-3]) == commits[-5]
406 406
407 407 def test_local_push(self):
408 408 target_repo = self.get_empty_repo()
409 409
410 410 revisions = list(self.repo.get_commits(branch_name='default'))
411 411 revision = revisions[-5].raw_id
412 412 self.repo._local_push(revision, target_repo.path)
413 413
414 414 target_repo = MercurialRepository(target_repo.path)
415 415
416 416 assert target_repo.branches['default'] == revision
417 417
418 418 def test_hooks_can_be_enabled_for_local_push(self):
419 419 revision = 'deadbeef'
420 420 repo_path = 'test_group/test_repo'
421 421 with mock.patch.object(self.repo, '_remote') as remote_mock:
422 422 self.repo._local_push(revision, repo_path, enable_hooks=True)
423 423 remote_mock.push.assert_called_once_with(
424 424 [revision], repo_path, hooks=True, push_branches=False)
425 425
426 426 def test_local_merge(self, vcsbackend_hg):
427 427 target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
428 428 source_repo = vcsbackend_hg.clone_repo(target_repo)
429 429 vcsbackend_hg.add_file(target_repo, 'README_MERGE1', 'Version 1')
430 430 target_repo = MercurialRepository(target_repo.path)
431 431 target_rev = target_repo.branches['default']
432 432 target_ref = Reference(
433 433 type='branch', name='default', commit_id=target_rev)
434 434 vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2')
435 435 source_repo = MercurialRepository(source_repo.path)
436 436 source_rev = source_repo.branches['default']
437 437 source_ref = Reference(
438 438 type='branch', name='default', commit_id=source_rev)
439 439
440 440 target_repo._local_pull(source_repo.path, source_ref)
441 441
442 442 merge_message = 'Merge message\n\nDescription:...'
443 443 user_name = 'Albert Einstein'
444 444 user_email = 'albert@einstein.com'
445 445 merge_commit_id, needs_push = target_repo._local_merge(
446 446 target_ref, merge_message, user_name, user_email, source_ref)
447 447 assert needs_push
448 448
449 449 target_repo = MercurialRepository(target_repo.path)
450 450 assert target_repo.commit_ids[-3] == target_rev
451 451 assert target_repo.commit_ids[-2] == source_rev
452 452 last_commit = target_repo.get_commit(merge_commit_id)
453 453 assert last_commit.message.strip() == merge_message
454 454 assert last_commit.author == '%s <%s>' % (user_name, user_email)
455 455
456 456 assert not os.path.exists(
457 457 os.path.join(target_repo.path, '.hg', 'merge', 'state'))
458 458
459 459 def test_local_merge_source_is_fast_forward(self, vcsbackend_hg):
460 460 target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
461 461 source_repo = vcsbackend_hg.clone_repo(target_repo)
462 462 target_rev = target_repo.branches['default']
463 463 target_ref = Reference(
464 464 type='branch', name='default', commit_id=target_rev)
465 465 vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2')
466 466 source_repo = MercurialRepository(source_repo.path)
467 467 source_rev = source_repo.branches['default']
468 468 source_ref = Reference(
469 469 type='branch', name='default', commit_id=source_rev)
470 470
471 471 target_repo._local_pull(source_repo.path, source_ref)
472 472
473 473 merge_message = 'Merge message\n\nDescription:...'
474 474 user_name = 'Albert Einstein'
475 475 user_email = 'albert@einstein.com'
476 476 merge_commit_id, needs_push = target_repo._local_merge(
477 477 target_ref, merge_message, user_name, user_email, source_ref)
478 478 assert merge_commit_id == source_rev
479 479 assert needs_push
480 480
481 481 target_repo = MercurialRepository(target_repo.path)
482 482 assert target_repo.commit_ids[-2] == target_rev
483 483 assert target_repo.commit_ids[-1] == source_rev
484 484
485 485 assert not os.path.exists(
486 486 os.path.join(target_repo.path, '.hg', 'merge', 'state'))
487 487
488 488 def test_local_merge_source_is_integrated(self, vcsbackend_hg):
489 489 target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
490 490 target_rev = target_repo.branches['default']
491 491 target_ref = Reference(
492 492 type='branch', name='default', commit_id=target_rev)
493 493
494 494 merge_message = 'Merge message\n\nDescription:...'
495 495 user_name = 'Albert Einstein'
496 496 user_email = 'albert@einstein.com'
497 497 merge_commit_id, needs_push = target_repo._local_merge(
498 498 target_ref, merge_message, user_name, user_email, target_ref)
499 499 assert merge_commit_id == target_rev
500 500 assert not needs_push
501 501
502 502 target_repo = MercurialRepository(target_repo.path)
503 503 assert target_repo.commit_ids[-1] == target_rev
504 504
505 505 assert not os.path.exists(
506 506 os.path.join(target_repo.path, '.hg', 'merge', 'state'))
507 507
508 508 def test_local_merge_raises_exception_on_conflict(self, vcsbackend_hg):
509 509 target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
510 510 source_repo = vcsbackend_hg.clone_repo(target_repo)
511 511 vcsbackend_hg.add_file(target_repo, 'README_MERGE', 'Version 1')
512 512 target_repo = MercurialRepository(target_repo.path)
513 513 target_rev = target_repo.branches['default']
514 514 target_ref = Reference(
515 515 type='branch', name='default', commit_id=target_rev)
516 516 vcsbackend_hg.add_file(source_repo, 'README_MERGE', 'Version 2')
517 517 source_repo = MercurialRepository(source_repo.path)
518 518 source_rev = source_repo.branches['default']
519 519 source_ref = Reference(
520 520 type='branch', name='default', commit_id=source_rev)
521 521
522 522 target_repo._local_pull(source_repo.path, source_ref)
523 523 with pytest.raises(RepositoryError):
524 524 target_repo._local_merge(
525 525 target_ref, 'merge_message', 'user name', 'user@name.com',
526 526 source_ref)
527 527
528 528 # Check we are not left in an intermediate merge state
529 529 assert not os.path.exists(
530 530 os.path.join(target_repo.path, '.hg', 'merge', 'state'))
531 531
532 532 def test_local_merge_of_two_branches_of_the_same_repo(self, backend_hg):
533 533 commits = [
534 534 {'message': 'a'},
535 535 {'message': 'b', 'branch': 'b'},
536 536 ]
537 537 repo = backend_hg.create_repo(commits)
538 538 commit_ids = backend_hg.commit_ids
539 539 target_ref = Reference(
540 540 type='branch', name='default', commit_id=commit_ids['a'])
541 541 source_ref = Reference(
542 542 type='branch', name='b', commit_id=commit_ids['b'])
543 543 merge_message = 'Merge message\n\nDescription:...'
544 544 user_name = 'Albert Einstein'
545 545 user_email = 'albert@einstein.com'
546 546 vcs_repo = repo.scm_instance()
547 547 merge_commit_id, needs_push = vcs_repo._local_merge(
548 548 target_ref, merge_message, user_name, user_email, source_ref)
549 549 assert merge_commit_id != source_ref.commit_id
550 550 assert needs_push is True
551 551 commit = vcs_repo.get_commit(merge_commit_id)
552 552 assert commit.merge is True
553 553 assert commit.message == merge_message
554 554
555 555 def test_maybe_prepare_merge_workspace(self):
556 556 workspace = self.repo._maybe_prepare_merge_workspace('pr2', 'unused')
557 557
558 558 assert os.path.isdir(workspace)
559 559 workspace_repo = MercurialRepository(workspace)
560 560 assert workspace_repo.branches == self.repo.branches
561 561
562 562 # Calling it a second time should also succeed
563 563 workspace = self.repo._maybe_prepare_merge_workspace('pr2', 'unused')
564 564 assert os.path.isdir(workspace)
565 565
566 566 def test_cleanup_merge_workspace(self):
567 567 workspace = self.repo._maybe_prepare_merge_workspace('pr3', 'unused')
568 568 self.repo.cleanup_merge_workspace('pr3')
569 569
570 570 assert not os.path.exists(workspace)
571 571
572 572 def test_cleanup_merge_workspace_invalid_workspace_id(self):
573 573 # No assert: because in case of an inexistent workspace this function
574 574 # should still succeed.
575 575 self.repo.cleanup_merge_workspace('pr4')
576 576
577 577 def test_merge_target_is_bookmark(self, vcsbackend_hg):
578 578 target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
579 579 source_repo = vcsbackend_hg.clone_repo(target_repo)
580 580 vcsbackend_hg.add_file(target_repo, 'README_MERGE1', 'Version 1')
581 581 vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2')
582 582 imc = source_repo.in_memory_commit
583 583 imc.add(FileNode('file_x', content=source_repo.name))
584 584 imc.commit(
585 585 message=u'Automatic commit from repo merge test',
586 586 author=u'Automatic')
587 587 target_commit = target_repo.get_commit()
588 588 source_commit = source_repo.get_commit()
589 589 default_branch = target_repo.DEFAULT_BRANCH_NAME
590 590 bookmark_name = 'bookmark'
591 591 target_repo._update(default_branch)
592 592 target_repo.bookmark(bookmark_name)
593 593 target_ref = Reference('book', bookmark_name, target_commit.raw_id)
594 594 source_ref = Reference('branch', default_branch, source_commit.raw_id)
595 595 workspace = 'test-merge'
596 596
597 597 merge_response = target_repo.merge(
598 598 target_ref, source_repo, source_ref, workspace,
599 599 'test user', 'test@rhodecode.com', 'merge message 1',
600 600 dry_run=False)
601 601 expected_merge_response = MergeResponse(
602 True, True, merge_response.merge_commit_id,
602 True, True, merge_response.merge_ref,
603 603 MergeFailureReason.NONE)
604 604 assert merge_response == expected_merge_response
605 605
606 606 target_repo = backends.get_backend(vcsbackend_hg.alias)(
607 607 target_repo.path)
608 608 target_commits = list(target_repo.get_commits())
609 609 commit_ids = [c.raw_id for c in target_commits[:-1]]
610 610 assert source_ref.commit_id in commit_ids
611 611 assert target_ref.commit_id in commit_ids
612 612
613 613 merge_commit = target_commits[-1]
614 assert merge_commit.raw_id == merge_response.merge_commit_id
614 assert merge_commit.raw_id == merge_response.merge_ref.commit_id
615 615 assert merge_commit.message.strip() == 'merge message 1'
616 616 assert merge_commit.author == 'test user <test@rhodecode.com>'
617 617
618 618 # Check the bookmark was updated in the target repo
619 619 assert (
620 620 target_repo.bookmarks[bookmark_name] ==
621 merge_response.merge_commit_id)
621 merge_response.merge_ref.commit_id)
622 622
623 623 def test_merge_source_is_bookmark(self, vcsbackend_hg):
624 624 target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
625 625 source_repo = vcsbackend_hg.clone_repo(target_repo)
626 626 imc = source_repo.in_memory_commit
627 627 imc.add(FileNode('file_x', content=source_repo.name))
628 628 imc.commit(
629 629 message=u'Automatic commit from repo merge test',
630 630 author=u'Automatic')
631 631 target_commit = target_repo.get_commit()
632 632 source_commit = source_repo.get_commit()
633 633 default_branch = target_repo.DEFAULT_BRANCH_NAME
634 634 bookmark_name = 'bookmark'
635 635 target_ref = Reference('branch', default_branch, target_commit.raw_id)
636 636 source_repo._update(default_branch)
637 637 source_repo.bookmark(bookmark_name)
638 638 source_ref = Reference('book', bookmark_name, source_commit.raw_id)
639 639 workspace = 'test-merge'
640 640
641 641 merge_response = target_repo.merge(
642 642 target_ref, source_repo, source_ref, workspace,
643 643 'test user', 'test@rhodecode.com', 'merge message 1',
644 644 dry_run=False)
645 645 expected_merge_response = MergeResponse(
646 True, True, merge_response.merge_commit_id,
646 True, True, merge_response.merge_ref,
647 647 MergeFailureReason.NONE)
648 648 assert merge_response == expected_merge_response
649 649
650 650 target_repo = backends.get_backend(vcsbackend_hg.alias)(
651 651 target_repo.path)
652 652 target_commits = list(target_repo.get_commits())
653 653 commit_ids = [c.raw_id for c in target_commits]
654 654 assert source_ref.commit_id == commit_ids[-1]
655 655 assert target_ref.commit_id == commit_ids[-2]
656 656
657 657 def test_merge_target_has_multiple_heads(self, vcsbackend_hg):
658 658 target_repo = vcsbackend_hg.create_repo(number_of_commits=2)
659 659 source_repo = vcsbackend_hg.clone_repo(target_repo)
660 660 vcsbackend_hg.add_file(target_repo, 'README_MERGE1', 'Version 1')
661 661 vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2')
662 662
663 663 # add an extra head to the target repo
664 664 imc = target_repo.in_memory_commit
665 665 imc.add(FileNode('file_x', content='foo'))
666 666 commits = list(target_repo.get_commits())
667 667 imc.commit(
668 668 message=u'Automatic commit from repo merge test',
669 669 author=u'Automatic', parents=commits[0:1])
670 670
671 671 target_commit = target_repo.get_commit()
672 672 source_commit = source_repo.get_commit()
673 673 default_branch = target_repo.DEFAULT_BRANCH_NAME
674 674 target_repo._update(default_branch)
675 675
676 676 target_ref = Reference('branch', default_branch, target_commit.raw_id)
677 677 source_ref = Reference('branch', default_branch, source_commit.raw_id)
678 678 workspace = 'test-merge'
679 679
680 680 assert len(target_repo._heads(branch='default')) == 2
681 681 expected_merge_response = MergeResponse(
682 682 False, False, None,
683 683 MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS)
684 684 merge_response = target_repo.merge(
685 685 target_ref, source_repo, source_ref, workspace,
686 686 'test user', 'test@rhodecode.com', 'merge message 1',
687 687 dry_run=False)
688 688 assert merge_response == expected_merge_response
689 689
690 690 def test_merge_rebase_source_is_updated_bookmark(self, vcsbackend_hg):
691 691 target_repo = vcsbackend_hg.create_repo(number_of_commits=1)
692 692 source_repo = vcsbackend_hg.clone_repo(target_repo)
693 693 vcsbackend_hg.add_file(target_repo, 'README_MERGE1', 'Version 1')
694 694 vcsbackend_hg.add_file(source_repo, 'README_MERGE2', 'Version 2')
695 695 imc = source_repo.in_memory_commit
696 696 imc.add(FileNode('file_x', content=source_repo.name))
697 697 imc.commit(
698 698 message=u'Automatic commit from repo merge test',
699 699 author=u'Automatic')
700 700 target_commit = target_repo.get_commit()
701 701 source_commit = source_repo.get_commit()
702 702
703 703 vcsbackend_hg.add_file(source_repo, 'LICENSE', 'LICENSE Info')
704 704
705 705 default_branch = target_repo.DEFAULT_BRANCH_NAME
706 706 bookmark_name = 'bookmark'
707 707 source_repo._update(default_branch)
708 708 source_repo.bookmark(bookmark_name)
709 709
710 710 target_ref = Reference('branch', default_branch, target_commit.raw_id)
711 711 source_ref = Reference('book', bookmark_name, source_commit.raw_id)
712 712 workspace = 'test-merge'
713 713
714 714 merge_response = target_repo.merge(
715 715 target_ref, source_repo, source_ref, workspace,
716 716 'test user', 'test@rhodecode.com', 'merge message 1',
717 717 dry_run=False, use_rebase=True)
718 718
719 719 expected_merge_response = MergeResponse(
720 True, True, merge_response.merge_commit_id,
720 True, True, merge_response.merge_ref,
721 721 MergeFailureReason.NONE)
722 722 assert merge_response == expected_merge_response
723 723
724 724 target_repo = backends.get_backend(vcsbackend_hg.alias)(
725 725 target_repo.path)
726 726 last_commit = target_repo.get_commit()
727 727 assert last_commit.message == source_commit.message
728 728 assert last_commit.author == source_commit.author
729 729 # This checks that we effectively did a rebase
730 730 assert last_commit.raw_id != source_commit.raw_id
731 731
732 732 # Check the target has only 4 commits: 2 were already in target and
733 733 # only two should have been added
734 734 assert len(target_repo.commit_ids) == 2 + 2
735 735
736 736
737 737 class TestGetShadowInstance(object):
738 738
739 739 @pytest.fixture
740 740 def repo(self, vcsbackend_hg, monkeypatch):
741 741 repo = vcsbackend_hg.repo
742 742 monkeypatch.setattr(repo, 'config', mock.Mock())
743 743 monkeypatch.setattr('rhodecode.lib.vcs.connection.Hg', mock.Mock())
744 744 return repo
745 745
746 746 def test_passes_config(self, repo):
747 747 shadow = repo._get_shadow_instance(repo.path)
748 748 assert shadow.config == repo.config.copy()
749 749
750 750 def test_disables_hooks(self, repo):
751 751 shadow = repo._get_shadow_instance(repo.path)
752 752 shadow.config.clear_section.assert_called_once_with('hooks')
753 753
754 754 def test_allows_to_keep_hooks(self, repo):
755 755 shadow = repo._get_shadow_instance(repo.path, enable_hooks=True)
756 756 assert not shadow.config.clear_section.called
757 757
758 758
759 759 class TestMercurialCommit(object):
760 760
761 761 def _test_equality(self, commit):
762 762 idx = commit.idx
763 763 assert commit == self.repo.get_commit(commit_idx=idx)
764 764
765 765 def test_equality(self):
766 766 indexes = [0, 10, 20]
767 767 commits = [self.repo.get_commit(commit_idx=idx) for idx in indexes]
768 768 for commit in commits:
769 769 self._test_equality(commit)
770 770
771 771 def test_default_commit(self):
772 772 tip = self.repo.get_commit('tip')
773 773 assert tip == self.repo.get_commit()
774 774 assert tip == self.repo.get_commit(commit_id=None)
775 775 assert tip == self.repo.get_commit(commit_idx=None)
776 776 assert tip == list(self.repo[-1:])[0]
777 777
778 778 def test_root_node(self):
779 779 tip = self.repo.get_commit('tip')
780 780 assert tip.root is tip.get_node('')
781 781
782 782 def test_lazy_fetch(self):
783 783 """
784 784 Test if commit's nodes expands and are cached as we walk through
785 785 the commit. This test is somewhat hard to write as order of tests
786 786 is a key here. Written by running command after command in a shell.
787 787 """
788 788 commit = self.repo.get_commit(commit_idx=45)
789 789 assert len(commit.nodes) == 0
790 790 root = commit.root
791 791 assert len(commit.nodes) == 1
792 792 assert len(root.nodes) == 8
793 793 # accessing root.nodes updates commit.nodes
794 794 assert len(commit.nodes) == 9
795 795
796 796 docs = root.get_node('docs')
797 797 # we haven't yet accessed anything new as docs dir was already cached
798 798 assert len(commit.nodes) == 9
799 799 assert len(docs.nodes) == 8
800 800 # accessing docs.nodes updates commit.nodes
801 801 assert len(commit.nodes) == 17
802 802
803 803 assert docs is commit.get_node('docs')
804 804 assert docs is root.nodes[0]
805 805 assert docs is root.dirs[0]
806 806 assert docs is commit.get_node('docs')
807 807
808 808 def test_nodes_with_commit(self):
809 809 commit = self.repo.get_commit(commit_idx=45)
810 810 root = commit.root
811 811 docs = root.get_node('docs')
812 812 assert docs is commit.get_node('docs')
813 813 api = docs.get_node('api')
814 814 assert api is commit.get_node('docs/api')
815 815 index = api.get_node('index.rst')
816 816 assert index is commit.get_node('docs/api/index.rst')
817 817 assert index is commit.get_node(
818 818 'docs').get_node('api').get_node('index.rst')
819 819
820 820 def test_branch_and_tags(self):
821 821 commit0 = self.repo.get_commit(commit_idx=0)
822 822 assert commit0.branch == 'default'
823 823 assert commit0.tags == []
824 824
825 825 commit10 = self.repo.get_commit(commit_idx=10)
826 826 assert commit10.branch == 'default'
827 827 assert commit10.tags == []
828 828
829 829 commit44 = self.repo.get_commit(commit_idx=44)
830 830 assert commit44.branch == 'web'
831 831
832 832 tip = self.repo.get_commit('tip')
833 833 assert 'tip' in tip.tags
834 834
835 835 def test_bookmarks(self):
836 836 commit0 = self.repo.get_commit(commit_idx=0)
837 837 assert commit0.bookmarks == []
838 838
839 839 def _test_file_size(self, idx, path, size):
840 840 node = self.repo.get_commit(commit_idx=idx).get_node(path)
841 841 assert node.is_file()
842 842 assert node.size == size
843 843
844 844 def test_file_size(self):
845 845 to_check = (
846 846 (10, 'setup.py', 1068),
847 847 (20, 'setup.py', 1106),
848 848 (60, 'setup.py', 1074),
849 849
850 850 (10, 'vcs/backends/base.py', 2921),
851 851 (20, 'vcs/backends/base.py', 3936),
852 852 (60, 'vcs/backends/base.py', 6189),
853 853 )
854 854 for idx, path, size in to_check:
855 855 self._test_file_size(idx, path, size)
856 856
857 857 def test_file_history_from_commits(self):
858 858 node = self.repo[10].get_node('setup.py')
859 859 commit_ids = [commit.raw_id for commit in node.history]
860 860 assert ['3803844fdbd3b711175fc3da9bdacfcd6d29a6fb'] == commit_ids
861 861
862 862 node = self.repo[20].get_node('setup.py')
863 863 node_ids = [commit.raw_id for commit in node.history]
864 864 assert ['eada5a770da98ab0dd7325e29d00e0714f228d09',
865 865 '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb'] == node_ids
866 866
867 867 # special case we check history from commit that has this particular
868 868 # file changed this means we check if it's included as well
869 869 node = self.repo.get_commit('eada5a770da98ab0dd7325e29d00e0714f228d09')\
870 870 .get_node('setup.py')
871 871 node_ids = [commit.raw_id for commit in node.history]
872 872 assert ['eada5a770da98ab0dd7325e29d00e0714f228d09',
873 873 '3803844fdbd3b711175fc3da9bdacfcd6d29a6fb'] == node_ids
874 874
875 875 def test_file_history(self):
876 876 # we can only check if those commits are present in the history
877 877 # as we cannot update this test every time file is changed
878 878 files = {
879 879 'setup.py': [7, 18, 45, 46, 47, 69, 77],
880 880 'vcs/nodes.py': [
881 881 7, 8, 24, 26, 30, 45, 47, 49, 56, 57, 58, 59, 60, 61, 73, 76],
882 882 'vcs/backends/hg.py': [
883 883 4, 5, 6, 11, 12, 13, 14, 15, 16, 21, 22, 23, 26, 27, 28, 30,
884 884 31, 33, 35, 36, 37, 38, 39, 40, 41, 44, 45, 47, 48, 49, 53, 54,
885 885 55, 58, 60, 61, 67, 68, 69, 70, 73, 77, 78, 79, 82],
886 886 }
887 887 for path, indexes in files.items():
888 888 tip = self.repo.get_commit(commit_idx=indexes[-1])
889 889 node = tip.get_node(path)
890 890 node_indexes = [commit.idx for commit in node.history]
891 891 assert set(indexes).issubset(set(node_indexes)), (
892 892 "We assumed that %s is subset of commits for which file %s "
893 893 "has been changed, and history of that node returned: %s"
894 894 % (indexes, path, node_indexes))
895 895
896 896 def test_file_annotate(self):
897 897 files = {
898 898 'vcs/backends/__init__.py': {
899 899 89: {
900 900 'lines_no': 31,
901 901 'commits': [
902 902 32, 32, 61, 32, 32, 37, 32, 32, 32, 44,
903 903 37, 37, 37, 37, 45, 37, 44, 37, 37, 37,
904 904 32, 32, 32, 32, 37, 32, 37, 37, 32,
905 905 32, 32
906 906 ]
907 907 },
908 908 20: {
909 909 'lines_no': 1,
910 910 'commits': [4]
911 911 },
912 912 55: {
913 913 'lines_no': 31,
914 914 'commits': [
915 915 32, 32, 45, 32, 32, 37, 32, 32, 32, 44,
916 916 37, 37, 37, 37, 45, 37, 44, 37, 37, 37,
917 917 32, 32, 32, 32, 37, 32, 37, 37, 32,
918 918 32, 32
919 919 ]
920 920 }
921 921 },
922 922 'vcs/exceptions.py': {
923 923 89: {
924 924 'lines_no': 18,
925 925 'commits': [
926 926 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
927 927 16, 16, 17, 16, 16, 18, 18, 18
928 928 ]
929 929 },
930 930 20: {
931 931 'lines_no': 18,
932 932 'commits': [
933 933 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
934 934 16, 16, 17, 16, 16, 18, 18, 18
935 935 ]
936 936 },
937 937 55: {
938 938 'lines_no': 18,
939 939 'commits': [
940 940 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
941 941 17, 16, 16, 18, 18, 18
942 942 ]
943 943 }
944 944 },
945 945 'MANIFEST.in': {
946 946 89: {
947 947 'lines_no': 5,
948 948 'commits': [7, 7, 7, 71, 71]
949 949 },
950 950 20: {
951 951 'lines_no': 3,
952 952 'commits': [7, 7, 7]
953 953 },
954 954 55: {
955 955 'lines_no': 3,
956 956 'commits': [7, 7, 7]
957 957 }
958 958 }
959 959 }
960 960
961 961 for fname, commit_dict in files.items():
962 962 for idx, __ in commit_dict.items():
963 963 commit = self.repo.get_commit(commit_idx=idx)
964 964 l1_1 = [x[1] for x in commit.get_file_annotate(fname)]
965 965 l1_2 = [x[2]().raw_id for x in commit.get_file_annotate(fname)]
966 966 assert l1_1 == l1_2
967 967 l1 = l1_2 = [
968 968 x[2]().idx for x in commit.get_file_annotate(fname)]
969 969 l2 = files[fname][idx]['commits']
970 970 assert l1 == l2, (
971 971 "The lists of commit for %s@commit_id%s"
972 972 "from annotation list should match each other,"
973 973 "got \n%s \nvs \n%s " % (fname, idx, l1, l2))
974 974
975 975 def test_commit_state(self):
976 976 """
977 977 Tests which files have been added/changed/removed at particular commit
978 978 """
979 979
980 980 # commit_id 46ad32a4f974:
981 981 # hg st --rev 46ad32a4f974
982 982 # changed: 13
983 983 # added: 20
984 984 # removed: 1
985 985 changed = set([
986 986 '.hgignore', 'README.rst', 'docs/conf.py', 'docs/index.rst',
987 987 'setup.py', 'tests/test_hg.py', 'tests/test_nodes.py',
988 988 'vcs/__init__.py', 'vcs/backends/__init__.py',
989 989 'vcs/backends/base.py', 'vcs/backends/hg.py', 'vcs/nodes.py',
990 990 'vcs/utils/__init__.py'])
991 991
992 992 added = set([
993 993 'docs/api/backends/hg.rst', 'docs/api/backends/index.rst',
994 994 'docs/api/index.rst', 'docs/api/nodes.rst',
995 995 'docs/api/web/index.rst', 'docs/api/web/simplevcs.rst',
996 996 'docs/installation.rst', 'docs/quickstart.rst', 'setup.cfg',
997 997 'vcs/utils/baseui_config.py', 'vcs/utils/web.py',
998 998 'vcs/web/__init__.py', 'vcs/web/exceptions.py',
999 999 'vcs/web/simplevcs/__init__.py', 'vcs/web/simplevcs/exceptions.py',
1000 1000 'vcs/web/simplevcs/middleware.py', 'vcs/web/simplevcs/models.py',
1001 1001 'vcs/web/simplevcs/settings.py', 'vcs/web/simplevcs/utils.py',
1002 1002 'vcs/web/simplevcs/views.py'])
1003 1003
1004 1004 removed = set(['docs/api.rst'])
1005 1005
1006 1006 commit64 = self.repo.get_commit('46ad32a4f974')
1007 1007 assert set((node.path for node in commit64.added)) == added
1008 1008 assert set((node.path for node in commit64.changed)) == changed
1009 1009 assert set((node.path for node in commit64.removed)) == removed
1010 1010
1011 1011 # commit_id b090f22d27d6:
1012 1012 # hg st --rev b090f22d27d6
1013 1013 # changed: 13
1014 1014 # added: 20
1015 1015 # removed: 1
1016 1016 commit88 = self.repo.get_commit('b090f22d27d6')
1017 1017 assert set((node.path for node in commit88.added)) == set()
1018 1018 assert set((node.path for node in commit88.changed)) == \
1019 1019 set(['.hgignore'])
1020 1020 assert set((node.path for node in commit88.removed)) == set()
1021 1021
1022 1022 #
1023 1023 # 85:
1024 1024 # added: 2 [
1025 1025 # 'vcs/utils/diffs.py', 'vcs/web/simplevcs/views/diffs.py']
1026 1026 # changed: 4 ['vcs/web/simplevcs/models.py', ...]
1027 1027 # removed: 1 ['vcs/utils/web.py']
1028 1028 commit85 = self.repo.get_commit(commit_idx=85)
1029 1029 assert set((node.path for node in commit85.added)) == set([
1030 1030 'vcs/utils/diffs.py',
1031 1031 'vcs/web/simplevcs/views/diffs.py'])
1032 1032 assert set((node.path for node in commit85.changed)) == set([
1033 1033 'vcs/web/simplevcs/models.py',
1034 1034 'vcs/web/simplevcs/utils.py',
1035 1035 'vcs/web/simplevcs/views/__init__.py',
1036 1036 'vcs/web/simplevcs/views/repository.py',
1037 1037 ])
1038 1038 assert set((node.path for node in commit85.removed)) == \
1039 1039 set(['vcs/utils/web.py'])
1040 1040
1041 1041 def test_files_state(self):
1042 1042 """
1043 1043 Tests state of FileNodes.
1044 1044 """
1045 1045 commit = self.repo.get_commit(commit_idx=85)
1046 1046 node = commit.get_node('vcs/utils/diffs.py')
1047 1047 assert node.state, NodeState.ADDED
1048 1048 assert node.added
1049 1049 assert not node.changed
1050 1050 assert not node.not_changed
1051 1051 assert not node.removed
1052 1052
1053 1053 commit = self.repo.get_commit(commit_idx=88)
1054 1054 node = commit.get_node('.hgignore')
1055 1055 assert node.state, NodeState.CHANGED
1056 1056 assert not node.added
1057 1057 assert node.changed
1058 1058 assert not node.not_changed
1059 1059 assert not node.removed
1060 1060
1061 1061 commit = self.repo.get_commit(commit_idx=85)
1062 1062 node = commit.get_node('setup.py')
1063 1063 assert node.state, NodeState.NOT_CHANGED
1064 1064 assert not node.added
1065 1065 assert not node.changed
1066 1066 assert node.not_changed
1067 1067 assert not node.removed
1068 1068
1069 1069 # If node has REMOVED state then trying to fetch it would raise
1070 1070 # CommitError exception
1071 1071 commit = self.repo.get_commit(commit_idx=2)
1072 1072 path = 'vcs/backends/BaseRepository.py'
1073 1073 with pytest.raises(NodeDoesNotExistError):
1074 1074 commit.get_node(path)
1075 1075 # but it would be one of ``removed`` (commit's attribute)
1076 1076 assert path in [rf.path for rf in commit.removed]
1077 1077
1078 1078 def test_commit_message_is_unicode(self):
1079 1079 for cm in self.repo:
1080 1080 assert type(cm.message) == unicode
1081 1081
1082 1082 def test_commit_author_is_unicode(self):
1083 1083 for cm in self.repo:
1084 1084 assert type(cm.author) == unicode
1085 1085
1086 1086 def test_repo_files_content_is_unicode(self):
1087 1087 test_commit = self.repo.get_commit(commit_idx=100)
1088 1088 for node in test_commit.get_node('/'):
1089 1089 if node.is_file():
1090 1090 assert type(node.content) == unicode
1091 1091
1092 1092 def test_wrong_path(self):
1093 1093 # There is 'setup.py' in the root dir but not there:
1094 1094 path = 'foo/bar/setup.py'
1095 1095 with pytest.raises(VCSError):
1096 1096 self.repo.get_commit().get_node(path)
1097 1097
1098 1098 def test_large_file(self):
1099 1099 # TODO: valid large file
1100 1100 tip = self.repo.get_commit()
1101 1101 with pytest.raises(CommitError):
1102 1102 tip.get_largefile_node("invalid")
1103 1103
1104 1104 def test_author_email(self):
1105 1105 assert 'marcin@python-blog.com' == \
1106 1106 self.repo.get_commit('b986218ba1c9').author_email
1107 1107 assert 'lukasz.balcerzak@python-center.pl' == \
1108 1108 self.repo.get_commit('3803844fdbd3').author_email
1109 1109 assert '' == self.repo.get_commit('84478366594b').author_email
1110 1110
1111 1111 def test_author_username(self):
1112 1112 assert 'Marcin Kuzminski' == \
1113 1113 self.repo.get_commit('b986218ba1c9').author_name
1114 1114 assert 'Lukasz Balcerzak' == \
1115 1115 self.repo.get_commit('3803844fdbd3').author_name
1116 1116 assert 'marcink' == \
1117 1117 self.repo.get_commit('84478366594b').author_name
1118 1118
1119 1119
1120 1120 class TestGetBranchName(object):
1121 1121 def test_returns_ref_name_when_type_is_branch(self):
1122 1122 ref = self._create_ref('branch', 'fake-name')
1123 1123 result = self.repo._get_branch_name(ref)
1124 1124 assert result == ref.name
1125 1125
1126 1126 @pytest.mark.parametrize("type_", ("book", "tag"))
1127 1127 def test_queries_remote_when_type_is_not_branch(self, type_):
1128 1128 ref = self._create_ref(type_, 'wrong-fake-name')
1129 1129 with mock.patch.object(self.repo, "_remote") as remote_mock:
1130 1130 remote_mock.ctx_branch.return_value = "fake-name"
1131 1131 result = self.repo._get_branch_name(ref)
1132 1132 assert result == "fake-name"
1133 1133 remote_mock.ctx_branch.assert_called_once_with(ref.commit_id)
1134 1134
1135 1135 def _create_ref(self, type_, name):
1136 1136 ref = mock.Mock()
1137 1137 ref.type = type_
1138 1138 ref.name = 'wrong-fake-name'
1139 1139 ref.commit_id = "deadbeef"
1140 1140 return ref
1141 1141
1142 1142
1143 1143 class TestIsTheSameBranch(object):
1144 1144 def test_returns_true_when_branches_are_equal(self):
1145 1145 source_ref = mock.Mock(name="source-ref")
1146 1146 target_ref = mock.Mock(name="target-ref")
1147 1147 branch_name_patcher = mock.patch.object(
1148 1148 self.repo, "_get_branch_name", return_value="default")
1149 1149 with branch_name_patcher as branch_name_mock:
1150 1150 result = self.repo._is_the_same_branch(source_ref, target_ref)
1151 1151
1152 1152 expected_calls = [mock.call(source_ref), mock.call(target_ref)]
1153 1153 assert branch_name_mock.call_args_list == expected_calls
1154 1154 assert result is True
1155 1155
1156 1156 def test_returns_false_when_branches_are_not_equal(self):
1157 1157 source_ref = mock.Mock(name="source-ref")
1158 1158 source_ref.name = "source-branch"
1159 1159 target_ref = mock.Mock(name="target-ref")
1160 1160 source_ref.name = "target-branch"
1161 1161
1162 1162 def side_effect(ref):
1163 1163 return ref.name
1164 1164
1165 1165 branch_name_patcher = mock.patch.object(
1166 1166 self.repo, "_get_branch_name", side_effect=side_effect)
1167 1167 with branch_name_patcher as branch_name_mock:
1168 1168 result = self.repo._is_the_same_branch(source_ref, target_ref)
1169 1169
1170 1170 expected_calls = [mock.call(source_ref), mock.call(target_ref)]
1171 1171 assert branch_name_mock.call_args_list == expected_calls
1172 1172 assert result is False
@@ -1,522 +1,523 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import datetime
22 22 from urllib2 import URLError
23 23
24 24 import mock
25 25 import pytest
26 26
27 27 from rhodecode.lib.vcs import backends
28 28 from rhodecode.lib.vcs.backends.base import (
29 29 Config, BaseInMemoryCommit, Reference, MergeResponse, MergeFailureReason)
30 30 from rhodecode.lib.vcs.exceptions import VCSError, RepositoryError
31 31 from rhodecode.lib.vcs.nodes import FileNode
32 32 from rhodecode.tests.vcs.base import BackendTestMixin
33 33
34 34
35 35 class TestRepositoryBase(BackendTestMixin):
36 36 recreate_repo_per_test = False
37 37
38 38 def test_init_accepts_unicode_path(self, tmpdir):
39 39 path = unicode(tmpdir.join(u'unicode Γ€'))
40 40 self.Backend(path, create=True)
41 41
42 42 def test_init_accepts_str_path(self, tmpdir):
43 43 path = str(tmpdir.join('str Γ€'))
44 44 self.Backend(path, create=True)
45 45
46 46 def test_init_fails_if_path_does_not_exist(self, tmpdir):
47 47 path = unicode(tmpdir.join('i-do-not-exist'))
48 48 with pytest.raises(VCSError):
49 49 self.Backend(path)
50 50
51 51 def test_init_fails_if_path_is_not_a_valid_repository(self, tmpdir):
52 52 path = unicode(tmpdir.mkdir(u'unicode Γ€'))
53 53 with pytest.raises(VCSError):
54 54 self.Backend(path)
55 55
56 56 def test_has_commits_attribute(self):
57 57 self.repo.commit_ids
58 58
59 59 def test_name(self):
60 60 assert self.repo.name.startswith('vcs-test')
61 61
62 62 @pytest.mark.backends("hg", "git")
63 63 def test_has_default_branch_name(self):
64 64 assert self.repo.DEFAULT_BRANCH_NAME is not None
65 65
66 66 @pytest.mark.backends("svn")
67 67 def test_has_no_default_branch_name(self):
68 68 assert self.repo.DEFAULT_BRANCH_NAME is None
69 69
70 70 def test_has_empty_commit(self):
71 71 assert self.repo.EMPTY_COMMIT_ID is not None
72 72 assert self.repo.EMPTY_COMMIT is not None
73 73
74 74 def test_empty_changeset_is_deprecated(self):
75 75 def get_empty_changeset(repo):
76 76 return repo.EMPTY_CHANGESET
77 77 pytest.deprecated_call(get_empty_changeset, self.repo)
78 78
79 79 def test_bookmarks(self):
80 80 assert len(self.repo.bookmarks) == 0
81 81
82 82 # TODO: Cover two cases: Local repo path, remote URL
83 83 def test_check_url(self):
84 84 config = Config()
85 85 assert self.Backend.check_url(self.repo.path, config)
86 86
87 87 def test_check_url_invalid(self):
88 88 config = Config()
89 89 with pytest.raises(URLError):
90 90 self.Backend.check_url(self.repo.path + "invalid", config)
91 91
92 92 def test_get_contact(self):
93 93 self.repo.contact
94 94
95 95 def test_get_description(self):
96 96 self.repo.description
97 97
98 98 def test_get_hook_location(self):
99 99 assert len(self.repo.get_hook_location()) != 0
100 100
101 101 def test_last_change(self):
102 102 assert self.repo.last_change >= datetime.datetime(2010, 1, 1, 21, 0)
103 103
104 104 def test_last_change_in_empty_repository(self, vcsbackend):
105 105 delta = datetime.timedelta(seconds=1)
106 106 start = datetime.datetime.now()
107 107 empty_repo = vcsbackend.create_repo()
108 108 now = datetime.datetime.now()
109 109 assert empty_repo.last_change >= start - delta
110 110 assert empty_repo.last_change <= now + delta
111 111
112 112 def test_repo_equality(self):
113 113 assert self.repo == self.repo
114 114
115 115 def test_repo_equality_broken_object(self):
116 116 import copy
117 117 _repo = copy.copy(self.repo)
118 118 delattr(_repo, 'path')
119 119 assert self.repo != _repo
120 120
121 121 def test_repo_equality_other_object(self):
122 122 class dummy(object):
123 123 path = self.repo.path
124 124 assert self.repo != dummy()
125 125
126 126 def test_get_commit_is_implemented(self):
127 127 self.repo.get_commit()
128 128
129 129 def test_get_commits_is_implemented(self):
130 130 commit_iter = iter(self.repo.get_commits())
131 131 commit = next(commit_iter)
132 132 assert commit.idx == 0
133 133
134 134 def test_supports_iteration(self):
135 135 repo_iter = iter(self.repo)
136 136 commit = next(repo_iter)
137 137 assert commit.idx == 0
138 138
139 139 def test_in_memory_commit(self):
140 140 imc = self.repo.in_memory_commit
141 141 assert isinstance(imc, BaseInMemoryCommit)
142 142
143 143 @pytest.mark.backends("hg")
144 144 def test__get_url_unicode(self):
145 145 url = u'/home/repos/malmΓΆ'
146 146 assert self.repo._get_url(url)
147 147
148 148
149 149 class TestDeprecatedRepositoryAPI(BackendTestMixin):
150 150 recreate_repo_per_test = False
151 151
152 152 def test_revisions_is_deprecated(self):
153 153 def get_revisions(repo):
154 154 return repo.revisions
155 155 pytest.deprecated_call(get_revisions, self.repo)
156 156
157 157 def test_get_changeset_is_deprecated(self):
158 158 pytest.deprecated_call(self.repo.get_changeset)
159 159
160 160 def test_get_changesets_is_deprecated(self):
161 161 pytest.deprecated_call(self.repo.get_changesets)
162 162
163 163 def test_in_memory_changeset_is_deprecated(self):
164 164 def get_imc(repo):
165 165 return repo.in_memory_changeset
166 166 pytest.deprecated_call(get_imc, self.repo)
167 167
168 168
169 169 # TODO: these tests are incomplete, must check the resulting compare result for
170 170 # correcteness
171 171 class TestRepositoryCompare:
172 172
173 173 @pytest.mark.parametrize('merge', [True, False])
174 174 def test_compare_commits_of_same_repository(self, vcsbackend, merge):
175 175 target_repo = vcsbackend.create_repo(number_of_commits=5)
176 176 target_repo.compare(
177 177 target_repo[1].raw_id, target_repo[3].raw_id, target_repo,
178 178 merge=merge)
179 179
180 180 @pytest.mark.xfail_backends('svn')
181 181 @pytest.mark.parametrize('merge', [True, False])
182 182 def test_compare_cloned_repositories(self, vcsbackend, merge):
183 183 target_repo = vcsbackend.create_repo(number_of_commits=5)
184 184 source_repo = vcsbackend.clone_repo(target_repo)
185 185 assert target_repo != source_repo
186 186
187 187 vcsbackend.add_file(source_repo, 'newfile', 'somecontent')
188 188 source_commit = source_repo.get_commit()
189 189
190 190 target_repo.compare(
191 191 target_repo[1].raw_id, source_repo[3].raw_id, source_repo,
192 192 merge=merge)
193 193
194 194 @pytest.mark.xfail_backends('svn')
195 195 @pytest.mark.parametrize('merge', [True, False])
196 196 def test_compare_unrelated_repositories(self, vcsbackend, merge):
197 197 orig = vcsbackend.create_repo(number_of_commits=5)
198 198 unrelated = vcsbackend.create_repo(number_of_commits=5)
199 199 assert orig != unrelated
200 200
201 201 orig.compare(
202 202 orig[1].raw_id, unrelated[3].raw_id, unrelated, merge=merge)
203 203
204 204
205 205 class TestRepositoryGetCommonAncestor:
206 206
207 207 def test_get_common_ancestor_from_same_repo_existing(self, vcsbackend):
208 208 target_repo = vcsbackend.create_repo(number_of_commits=5)
209 209
210 210 expected_ancestor = target_repo[2].raw_id
211 211
212 212 assert target_repo.get_common_ancestor(
213 213 commit_id1=target_repo[2].raw_id,
214 214 commit_id2=target_repo[4].raw_id,
215 215 repo2=target_repo
216 216 ) == expected_ancestor
217 217
218 218 assert target_repo.get_common_ancestor(
219 219 commit_id1=target_repo[4].raw_id,
220 220 commit_id2=target_repo[2].raw_id,
221 221 repo2=target_repo
222 222 ) == expected_ancestor
223 223
224 224 @pytest.mark.xfail_backends("svn")
225 225 def test_get_common_ancestor_from_cloned_repo_existing(self, vcsbackend):
226 226 target_repo = vcsbackend.create_repo(number_of_commits=5)
227 227 source_repo = vcsbackend.clone_repo(target_repo)
228 228 assert target_repo != source_repo
229 229
230 230 vcsbackend.add_file(source_repo, 'newfile', 'somecontent')
231 231 source_commit = source_repo.get_commit()
232 232
233 233 expected_ancestor = target_repo[4].raw_id
234 234
235 235 assert target_repo.get_common_ancestor(
236 236 commit_id1=target_repo[4].raw_id,
237 237 commit_id2=source_commit.raw_id,
238 238 repo2=source_repo
239 239 ) == expected_ancestor
240 240
241 241 assert target_repo.get_common_ancestor(
242 242 commit_id1=source_commit.raw_id,
243 243 commit_id2=target_repo[4].raw_id,
244 244 repo2=target_repo
245 245 ) == expected_ancestor
246 246
247 247 @pytest.mark.xfail_backends("svn")
248 248 def test_get_common_ancestor_from_unrelated_repo_missing(self, vcsbackend):
249 249 original = vcsbackend.create_repo(number_of_commits=5)
250 250 unrelated = vcsbackend.create_repo(number_of_commits=5)
251 251 assert original != unrelated
252 252
253 253 assert original.get_common_ancestor(
254 254 commit_id1=original[0].raw_id,
255 255 commit_id2=unrelated[0].raw_id,
256 256 repo2=unrelated
257 257 ) == None
258 258
259 259 assert original.get_common_ancestor(
260 260 commit_id1=original[-1].raw_id,
261 261 commit_id2=unrelated[-1].raw_id,
262 262 repo2=unrelated
263 263 ) == None
264 264
265 265
266 266 @pytest.mark.backends("git", "hg")
267 267 class TestRepositoryMerge:
268 268 def prepare_for_success(self, vcsbackend):
269 269 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
270 270 self.source_repo = vcsbackend.clone_repo(self.target_repo)
271 271 vcsbackend.add_file(self.target_repo, 'README_MERGE1', 'Version 1')
272 272 vcsbackend.add_file(self.source_repo, 'README_MERGE2', 'Version 2')
273 273 imc = self.source_repo.in_memory_commit
274 274 imc.add(FileNode('file_x', content=self.source_repo.name))
275 275 imc.commit(
276 276 message=u'Automatic commit from repo merge test',
277 277 author=u'Automatic')
278 278 self.target_commit = self.target_repo.get_commit()
279 279 self.source_commit = self.source_repo.get_commit()
280 280 # This only works for Git and Mercurial
281 281 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
282 282 self.target_ref = Reference(
283 283 'branch', default_branch, self.target_commit.raw_id)
284 284 self.source_ref = Reference(
285 285 'branch', default_branch, self.source_commit.raw_id)
286 286 self.workspace = 'test-merge'
287 287
288 288 def prepare_for_conflict(self, vcsbackend):
289 289 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
290 290 self.source_repo = vcsbackend.clone_repo(self.target_repo)
291 291 vcsbackend.add_file(self.target_repo, 'README_MERGE', 'Version 1')
292 292 vcsbackend.add_file(self.source_repo, 'README_MERGE', 'Version 2')
293 293 self.target_commit = self.target_repo.get_commit()
294 294 self.source_commit = self.source_repo.get_commit()
295 295 # This only works for Git and Mercurial
296 296 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
297 297 self.target_ref = Reference(
298 298 'branch', default_branch, self.target_commit.raw_id)
299 299 self.source_ref = Reference(
300 300 'branch', default_branch, self.source_commit.raw_id)
301 301 self.workspace = 'test-merge'
302 302
303 303 def test_merge_success(self, vcsbackend):
304 304 self.prepare_for_success(vcsbackend)
305 305
306 306 merge_response = self.target_repo.merge(
307 307 self.target_ref, self.source_repo, self.source_ref, self.workspace,
308 308 'test user', 'test@rhodecode.com', 'merge message 1',
309 309 dry_run=False)
310 310 expected_merge_response = MergeResponse(
311 True, True, merge_response.merge_commit_id,
311 True, True, merge_response.merge_ref,
312 312 MergeFailureReason.NONE)
313 313 assert merge_response == expected_merge_response
314 314
315 315 target_repo = backends.get_backend(vcsbackend.alias)(
316 316 self.target_repo.path)
317 317 target_commits = list(target_repo.get_commits())
318 318 commit_ids = [c.raw_id for c in target_commits[:-1]]
319 319 assert self.source_ref.commit_id in commit_ids
320 320 assert self.target_ref.commit_id in commit_ids
321 321
322 322 merge_commit = target_commits[-1]
323 assert merge_commit.raw_id == merge_response.merge_commit_id
323 assert merge_commit.raw_id == merge_response.merge_ref
324 324 assert merge_commit.message.strip() == 'merge message 1'
325 325 assert merge_commit.author == 'test user <test@rhodecode.com>'
326 326
327 327 # We call it twice so to make sure we can handle updates
328 328 target_ref = Reference(
329 329 self.target_ref.type, self.target_ref.name,
330 merge_response.merge_commit_id)
330 merge_response.merge_ref.commit_id)
331 331
332 332 merge_response = target_repo.merge(
333 333 target_ref, self.source_repo, self.source_ref, self.workspace,
334 334 'test user', 'test@rhodecode.com', 'merge message 2',
335 335 dry_run=False)
336 336 expected_merge_response = MergeResponse(
337 True, True, merge_response.merge_commit_id,
337 True, True, merge_response.merge_ref,
338 338 MergeFailureReason.NONE)
339 339 assert merge_response == expected_merge_response
340 340
341 341 target_repo = backends.get_backend(
342 342 vcsbackend.alias)(self.target_repo.path)
343 merge_commit = target_repo.get_commit(merge_response.merge_commit_id)
343 merge_commit = target_repo.get_commit(
344 merge_response.merge_ref.commit_id)
344 345 assert merge_commit.message.strip() == 'merge message 1'
345 346 assert merge_commit.author == 'test user <test@rhodecode.com>'
346 347
347 348 def test_merge_success_dry_run(self, vcsbackend):
348 349 self.prepare_for_success(vcsbackend)
349 350 expected_merge_response = MergeResponse(
350 351 True, False, None, MergeFailureReason.NONE)
351 352
352 353 merge_response = self.target_repo.merge(
353 354 self.target_ref, self.source_repo, self.source_ref, self.workspace,
354 355 dry_run=True)
355 356 assert merge_response == expected_merge_response
356 357
357 358 # We call it twice so to make sure we can handle updates
358 359 merge_response = self.target_repo.merge(
359 360 self.target_ref, self.source_repo, self.source_ref, self.workspace,
360 361 dry_run=True)
361 362 assert merge_response == expected_merge_response
362 363
363 364 @pytest.mark.parametrize('dry_run', [True, False])
364 365 def test_merge_conflict(self, vcsbackend, dry_run):
365 366 self.prepare_for_conflict(vcsbackend)
366 367 expected_merge_response = MergeResponse(
367 368 False, False, None, MergeFailureReason.MERGE_FAILED)
368 369
369 370 merge_response = self.target_repo.merge(
370 371 self.target_ref, self.source_repo, self.source_ref, self.workspace,
371 372 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run)
372 373 assert merge_response == expected_merge_response
373 374
374 375 # We call it twice so to make sure we can handle updates
375 376 merge_response = self.target_repo.merge(
376 377 self.target_ref, self.source_repo, self.source_ref, self.workspace,
377 378 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run)
378 379 assert merge_response == expected_merge_response
379 380
380 381 def test_merge_target_is_not_head(self, vcsbackend):
381 382 self.prepare_for_success(vcsbackend)
382 383 expected_merge_response = MergeResponse(
383 384 False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD)
384 385
385 386 target_ref = Reference(
386 387 self.target_ref.type, self.target_ref.name, '0' * 40)
387 388
388 389 merge_response = self.target_repo.merge(
389 390 target_ref, self.source_repo, self.source_ref, self.workspace,
390 391 dry_run=True)
391 392
392 393 assert merge_response == expected_merge_response
393 394
394 395 def test_merge_missing_commit(self, vcsbackend):
395 396 self.prepare_for_success(vcsbackend)
396 397 expected_merge_response = MergeResponse(
397 398 False, False, None, MergeFailureReason.MISSING_COMMIT)
398 399
399 400 source_ref = Reference(
400 401 self.source_ref.type, 'not_existing', self.source_ref.commit_id)
401 402
402 403 merge_response = self.target_repo.merge(
403 404 self.target_ref, self.source_repo, source_ref, self.workspace,
404 405 dry_run=True)
405 406
406 407 assert merge_response == expected_merge_response
407 408
408 409 def test_merge_raises_exception(self, vcsbackend):
409 410 self.prepare_for_success(vcsbackend)
410 411 expected_merge_response = MergeResponse(
411 412 False, False, None, MergeFailureReason.UNKNOWN)
412 413
413 414 with mock.patch.object(self.target_repo, '_merge_repo',
414 415 side_effect=RepositoryError()):
415 416 merge_response = self.target_repo.merge(
416 417 self.target_ref, self.source_repo, self.source_ref,
417 418 self.workspace, dry_run=True)
418 419
419 420 assert merge_response == expected_merge_response
420 421
421 422 def test_merge_invalid_user_name(self, vcsbackend):
422 423 repo = vcsbackend.create_repo(number_of_commits=1)
423 424 ref = Reference('branch', 'master', 'not_used')
424 425 with pytest.raises(ValueError):
425 426 repo.merge(ref, self, ref, 'workspace_id')
426 427
427 428 def test_merge_invalid_user_email(self, vcsbackend):
428 429 repo = vcsbackend.create_repo(number_of_commits=1)
429 430 ref = Reference('branch', 'master', 'not_used')
430 431 with pytest.raises(ValueError):
431 432 repo.merge(ref, self, ref, 'workspace_id', 'user name')
432 433
433 434 def test_merge_invalid_message(self, vcsbackend):
434 435 repo = vcsbackend.create_repo(number_of_commits=1)
435 436 ref = Reference('branch', 'master', 'not_used')
436 437 with pytest.raises(ValueError):
437 438 repo.merge(
438 439 ref, self, ref, 'workspace_id', 'user name', 'user@email.com')
439 440
440 441
441 442 class TestRepositoryStrip(BackendTestMixin):
442 443 recreate_repo_per_test = True
443 444
444 445 @classmethod
445 446 def _get_commits(cls):
446 447 commits = [
447 448 {
448 449 'message': 'Initial commit',
449 450 'author': 'Joe Doe <joe.doe@example.com>',
450 451 'date': datetime.datetime(2010, 1, 1, 20),
451 452 'branch': 'master',
452 453 'added': [
453 454 FileNode('foobar', content='foobar'),
454 455 FileNode('foobar2', content='foobar2'),
455 456 ],
456 457 },
457 458 ]
458 459 for x in xrange(10):
459 460 commit_data = {
460 461 'message': 'Changed foobar - commit%s' % x,
461 462 'author': 'Jane Doe <jane.doe@example.com>',
462 463 'date': datetime.datetime(2010, 1, 1, 21, x),
463 464 'branch': 'master',
464 465 'changed': [
465 466 FileNode('foobar', 'FOOBAR - %s' % x),
466 467 ],
467 468 }
468 469 commits.append(commit_data)
469 470 return commits
470 471
471 472 @pytest.mark.backends("git", "hg")
472 473 def test_strip_commit(self):
473 474 tip = self.repo.get_commit()
474 475 assert tip.idx == 10
475 476 self.repo.strip(tip.raw_id, self.repo.DEFAULT_BRANCH_NAME)
476 477
477 478 tip = self.repo.get_commit()
478 479 assert tip.idx == 9
479 480
480 481 @pytest.mark.backends("git", "hg")
481 482 def test_strip_multiple_commits(self):
482 483 tip = self.repo.get_commit()
483 484 assert tip.idx == 10
484 485
485 486 old = self.repo.get_commit(commit_idx=5)
486 487 self.repo.strip(old.raw_id, self.repo.DEFAULT_BRANCH_NAME)
487 488
488 489 tip = self.repo.get_commit()
489 490 assert tip.idx == 4
490 491
491 492
492 493 @pytest.mark.backends('hg', 'git')
493 494 class TestRepositoryPull:
494 495
495 496 def test_pull(self, vcsbackend):
496 497 source_repo = vcsbackend.repo
497 498 target_repo = vcsbackend.create_repo()
498 499 assert len(source_repo.commit_ids) > len(target_repo.commit_ids)
499 500
500 501 target_repo.pull(source_repo.path)
501 502 # Note: Get a fresh instance, avoids caching trouble
502 503 target_repo = vcsbackend.backend(target_repo.path)
503 504 assert len(source_repo.commit_ids) == len(target_repo.commit_ids)
504 505
505 506 def test_pull_wrong_path(self, vcsbackend):
506 507 target_repo = vcsbackend.create_repo()
507 508 with pytest.raises(RepositoryError):
508 509 target_repo.pull(target_repo.path + "wrong")
509 510
510 511 def test_pull_specific_commits(self, vcsbackend):
511 512 source_repo = vcsbackend.repo
512 513 target_repo = vcsbackend.create_repo()
513 514
514 515 second_commit = source_repo[1].raw_id
515 516 if vcsbackend.alias == 'git':
516 517 second_commit_ref = 'refs/test-refs/a'
517 518 source_repo.set_refs(second_commit_ref, second_commit)
518 519
519 520 target_repo.pull(source_repo.path, commit_ids=[second_commit])
520 521 target_repo = vcsbackend.backend(target_repo.path)
521 522 assert 2 == len(target_repo.commit_ids)
522 523 assert second_commit == target_repo.get_commit().raw_id
General Comments 0
You need to be logged in to leave comments. Login now