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