##// END OF EJS Templates
tests: fixed merge tests cases
super-admin -
r5177:80d550be default
parent child Browse files
Show More
@@ -1,560 +1,648 b''
1
2 # Copyright (C) 2010-2023 RhodeCode GmbH
1 # Copyright (C) 2010-2023 RhodeCode GmbH
3 #
2 #
4 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
6 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
7 #
6 #
8 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
10 # GNU General Public License for more details.
12 #
11 #
13 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
14 #
16 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
17 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
19
18
20 import datetime
19 import datetime
21 from urllib.error import URLError
20 from urllib.error import URLError
22
21
23 import mock
22 import mock
24 import pytest
23 import pytest
25
24
26 from rhodecode.lib.vcs import backends
25 from rhodecode.lib.vcs import backends
27 from rhodecode.lib.vcs.backends.base import (
26 from rhodecode.lib.vcs.backends.base import (
28 Config, BaseInMemoryCommit, Reference, MergeResponse, MergeFailureReason)
27 Config,
28 BaseInMemoryCommit,
29 Reference,
30 MergeResponse,
31 MergeFailureReason,
32 )
29 from rhodecode.lib.vcs.exceptions import VCSError, RepositoryError
33 from rhodecode.lib.vcs.exceptions import VCSError, RepositoryError
30 from rhodecode.lib.vcs.nodes import FileNode
34 from rhodecode.lib.vcs.nodes import FileNode
31 from rhodecode.tests.vcs.conftest import BackendTestMixin
35 from rhodecode.tests.vcs.conftest import BackendTestMixin
32 from rhodecode.tests import repo_id_generator
36 from rhodecode.tests import repo_id_generator
33
37
34
38
35 @pytest.mark.usefixtures("vcs_repository_support")
39 @pytest.mark.usefixtures("vcs_repository_support")
36 class TestRepositoryBase(BackendTestMixin):
40 class TestRepositoryBase(BackendTestMixin):
37 recreate_repo_per_test = False
41 recreate_repo_per_test = False
38
42
39 def test_init_accepts_unicode_path(self, tmpdir):
43 def test_init_accepts_unicode_path(self, tmpdir):
40 path = str(tmpdir.join(u'unicode Γ€'))
44 path = str(tmpdir.join("unicode Γ€"))
41 self.Backend(path, create=True)
45 self.Backend(path, create=True)
42
46
43 def test_init_accepts_str_path(self, tmpdir):
47 def test_init_accepts_str_path(self, tmpdir):
44 path = str(tmpdir.join('str Γ€'))
48 path = str(tmpdir.join("str Γ€"))
45 self.Backend(path, create=True)
49 self.Backend(path, create=True)
46
50
47 def test_init_fails_if_path_does_not_exist(self, tmpdir):
51 def test_init_fails_if_path_does_not_exist(self, tmpdir):
48 path = str(tmpdir.join('i-do-not-exist'))
52 path = str(tmpdir.join("i-do-not-exist"))
49 with pytest.raises(VCSError):
53 with pytest.raises(VCSError):
50 self.Backend(path)
54 self.Backend(path)
51
55
52 def test_init_fails_if_path_is_not_a_valid_repository(self, tmpdir):
56 def test_init_fails_if_path_is_not_a_valid_repository(self, tmpdir):
53 path = str(tmpdir.mkdir(u'unicode Γ€'))
57 path = str(tmpdir.mkdir("unicode Γ€"))
54 with pytest.raises(VCSError):
58 with pytest.raises(VCSError):
55 self.Backend(path)
59 self.Backend(path)
56
60
57 def test_has_commits_attribute(self):
61 def test_has_commits_attribute(self):
58 assert self.repo.commit_ids
62 assert self.repo.commit_ids
59
63
60 def test_name(self):
64 def test_name(self):
61 assert self.repo.name.startswith('vcs-test')
65 assert self.repo.name.startswith("vcs-test")
62
66
63 @pytest.mark.backends("hg", "git")
67 @pytest.mark.backends("hg", "git")
64 def test_has_default_branch_name(self):
68 def test_has_default_branch_name(self):
65 assert self.repo.DEFAULT_BRANCH_NAME is not None
69 assert self.repo.DEFAULT_BRANCH_NAME is not None
66
70
67 @pytest.mark.backends("svn")
71 @pytest.mark.backends("svn")
68 def test_has_no_default_branch_name(self):
72 def test_has_no_default_branch_name(self):
69 assert self.repo.DEFAULT_BRANCH_NAME is None
73 assert self.repo.DEFAULT_BRANCH_NAME is None
70
74
71 def test_has_empty_commit(self):
75 def test_has_empty_commit(self):
72 assert self.repo.EMPTY_COMMIT_ID is not None
76 assert self.repo.EMPTY_COMMIT_ID is not None
73 assert self.repo.EMPTY_COMMIT is not None
77 assert self.repo.EMPTY_COMMIT is not None
74
78
75 def test_empty_changeset_is_deprecated(self):
79 def test_empty_changeset_is_deprecated(self):
76 def get_empty_changeset(repo):
80 def get_empty_changeset(repo):
77 return repo.EMPTY_CHANGESET
81 return repo.EMPTY_CHANGESET
82
78 pytest.deprecated_call(get_empty_changeset, self.repo)
83 pytest.deprecated_call(get_empty_changeset, self.repo)
79
84
80 def test_bookmarks(self):
85 def test_bookmarks(self):
81 assert len(self.repo.bookmarks) == 0
86 assert len(self.repo.bookmarks) == 0
82
87
83 def test_check_url_on_path(self):
88 def test_check_url_on_path(self):
84 config = Config()
89 config = Config()
85 assert self.Backend.check_url(self.repo.path, config)
90 assert self.Backend.check_url(self.repo.path, config)
86
91
87 def test_check_url_on_remote_url(self):
92 def test_check_url_on_remote_url(self):
88 config = Config()
93 config = Config()
89 url = {
94 url = {
90 'hg': 'https://code.rhodecode.com/rhodecode-vcsserver',
95 "hg": "https://code.rhodecode.com/rhodecode-vcsserver",
91 'svn': 'https://code.rhodecode.com/svn-doc',
96 "svn": "https://code.rhodecode.com/svn-doc",
92 'git': 'https://code.rhodecode.com/appenlight',
97 "git": "https://code.rhodecode.com/appenlight",
93 }[self.repo.alias]
98 }[self.repo.alias]
94
99
95 assert self.Backend.check_url(url, config)
100 assert self.Backend.check_url(url, config)
96
101
97 def test_check_url_invalid(self):
102 def test_check_url_invalid(self):
98 config = Config()
103 config = Config()
99 with pytest.raises(URLError):
104 with pytest.raises(URLError):
100 self.Backend.check_url(self.repo.path + "invalid", config)
105 self.Backend.check_url(self.repo.path + "invalid", config)
101
106
102 def test_get_contact(self):
107 def test_get_contact(self):
103 assert self.repo.contact
108 assert self.repo.contact
104
109
105 def test_get_description(self):
110 def test_get_description(self):
106 assert self.repo.description
111 assert self.repo.description
107
112
108 def test_get_hook_location(self):
113 def test_get_hook_location(self):
109 assert len(self.repo.get_hook_location()) != 0
114 assert len(self.repo.get_hook_location()) != 0
110
115
111 def test_last_change(self, local_dt_to_utc):
116 def test_last_change(self, local_dt_to_utc):
112 assert self.repo.last_change >= local_dt_to_utc(
117 assert self.repo.last_change >= local_dt_to_utc(
113 datetime.datetime(2010, 1, 1, 21, 0))
118 datetime.datetime(2010, 1, 1, 21, 0)
119 )
114
120
115 def test_last_change_in_empty_repository(self, vcsbackend, local_dt_to_utc):
121 def test_last_change_in_empty_repository(self, vcsbackend, local_dt_to_utc):
116 delta = datetime.timedelta(seconds=1)
122 delta = datetime.timedelta(seconds=1)
117
123
118 start = local_dt_to_utc(datetime.datetime.now())
124 start = local_dt_to_utc(datetime.datetime.now())
119 empty_repo = vcsbackend.create_repo()
125 empty_repo = vcsbackend.create_repo()
120 now = local_dt_to_utc(datetime.datetime.now())
126 now = local_dt_to_utc(datetime.datetime.now())
121 assert empty_repo.last_change >= start - delta
127 assert empty_repo.last_change >= start - delta
122 assert empty_repo.last_change <= now + delta
128 assert empty_repo.last_change <= now + delta
123
129
124 def test_repo_equality(self):
130 def test_repo_equality(self):
125 assert self.repo == self.repo
131 assert self.repo == self.repo
126
132
127 def test_repo_equality_broken_object(self):
133 def test_repo_equality_broken_object(self):
128 import copy
134 import copy
135
129 _repo = copy.copy(self.repo)
136 _repo = copy.copy(self.repo)
130 delattr(_repo, 'path')
137 delattr(_repo, "path")
131 assert self.repo != _repo
138 assert self.repo != _repo
132
139
133 def test_repo_equality_other_object(self):
140 def test_repo_equality_other_object(self):
134 class dummy(object):
141 class dummy(object):
135 path = self.repo.path
142 path = self.repo.path
143
136 assert self.repo != dummy()
144 assert self.repo != dummy()
137
145
138 def test_get_commit_is_implemented(self):
146 def test_get_commit_is_implemented(self):
139 self.repo.get_commit()
147 self.repo.get_commit()
140
148
141 def test_get_commits_is_implemented(self):
149 def test_get_commits_is_implemented(self):
142 commit_iter = iter(self.repo.get_commits())
150 commit_iter = iter(self.repo.get_commits())
143 commit = next(commit_iter)
151 commit = next(commit_iter)
144 assert commit.idx == 0
152 assert commit.idx == 0
145
153
146 def test_supports_iteration(self):
154 def test_supports_iteration(self):
147 repo_iter = iter(self.repo)
155 repo_iter = iter(self.repo)
148 commit = next(repo_iter)
156 commit = next(repo_iter)
149 assert commit.idx == 0
157 assert commit.idx == 0
150
158
151 def test_in_memory_commit(self):
159 def test_in_memory_commit(self):
152 imc = self.repo.in_memory_commit
160 imc = self.repo.in_memory_commit
153 assert isinstance(imc, BaseInMemoryCommit)
161 assert isinstance(imc, BaseInMemoryCommit)
154
162
155 @pytest.mark.backends("hg")
163 @pytest.mark.backends("hg")
156 def test__get_url_unicode(self):
164 def test__get_url_unicode(self):
157 url = u'/home/repos/malmΓΆ'
165 url = "/home/repos/malmΓΆ"
158 assert self.repo._get_url(url)
166 assert self.repo._get_url(url)
159
167
160
168
161 @pytest.mark.usefixtures("vcs_repository_support")
169 @pytest.mark.usefixtures("vcs_repository_support")
162 class TestDeprecatedRepositoryAPI(BackendTestMixin):
170 class TestDeprecatedRepositoryAPI(BackendTestMixin):
163 recreate_repo_per_test = False
171 recreate_repo_per_test = False
164
172
165 def test_revisions_is_deprecated(self):
173 def test_revisions_is_deprecated(self):
166 def get_revisions(repo):
174 def get_revisions(repo):
167 return repo.revisions
175 return repo.revisions
176
168 pytest.deprecated_call(get_revisions, self.repo)
177 pytest.deprecated_call(get_revisions, self.repo)
169
178
170 def test_get_changeset_is_deprecated(self):
179 def test_get_changeset_is_deprecated(self):
171 pytest.deprecated_call(self.repo.get_changeset)
180 pytest.deprecated_call(self.repo.get_changeset)
172
181
173 def test_get_changesets_is_deprecated(self):
182 def test_get_changesets_is_deprecated(self):
174 pytest.deprecated_call(self.repo.get_changesets)
183 pytest.deprecated_call(self.repo.get_changesets)
175
184
176 def test_in_memory_changeset_is_deprecated(self):
185 def test_in_memory_changeset_is_deprecated(self):
177 def get_imc(repo):
186 def get_imc(repo):
178 return repo.in_memory_changeset
187 return repo.in_memory_changeset
188
179 pytest.deprecated_call(get_imc, self.repo)
189 pytest.deprecated_call(get_imc, self.repo)
180
190
181
191
182 # TODO: these tests are incomplete, must check the resulting compare result for
192 # TODO: these tests are incomplete, must check the resulting compare result for
183 # correcteness
193 # correcteness
184 class TestRepositoryCompare:
194 class TestRepositoryCompare:
185
195 @pytest.mark.parametrize("merge", [True, False])
186 @pytest.mark.parametrize('merge', [True, False])
187 def test_compare_commits_of_same_repository(self, vcsbackend, merge):
196 def test_compare_commits_of_same_repository(self, vcsbackend, merge):
188 target_repo = vcsbackend.create_repo(number_of_commits=5)
197 target_repo = vcsbackend.create_repo(number_of_commits=5)
189 target_repo.compare(
198 target_repo.compare(
190 target_repo[1].raw_id, target_repo[3].raw_id, target_repo,
199 target_repo[1].raw_id, target_repo[3].raw_id, target_repo, merge=merge
191 merge=merge)
200 )
192
201
193 @pytest.mark.xfail_backends('svn')
202 @pytest.mark.xfail_backends("svn")
194 @pytest.mark.parametrize('merge', [True, False])
203 @pytest.mark.parametrize("merge", [True, False])
195 def test_compare_cloned_repositories(self, vcsbackend, merge):
204 def test_compare_cloned_repositories(self, vcsbackend, merge):
196 target_repo = vcsbackend.create_repo(number_of_commits=5)
205 target_repo = vcsbackend.create_repo(number_of_commits=5)
197 source_repo = vcsbackend.clone_repo(target_repo)
206 source_repo = vcsbackend.clone_repo(target_repo)
198 assert target_repo != source_repo
207 assert target_repo != source_repo
199
208
200 vcsbackend.add_file(source_repo, b'newfile', b'somecontent')
209 vcsbackend.add_file(source_repo, b"newfile", b"somecontent")
201 source_commit = source_repo.get_commit()
210 source_commit = source_repo.get_commit()
202
211
203 target_repo.compare(
212 target_repo.compare(
204 target_repo[1].raw_id, source_repo[3].raw_id, source_repo,
213 target_repo[1].raw_id, source_repo[3].raw_id, source_repo, merge=merge
205 merge=merge)
214 )
206
215
207 @pytest.mark.xfail_backends('svn')
216 @pytest.mark.xfail_backends("svn")
208 @pytest.mark.parametrize('merge', [True, False])
217 @pytest.mark.parametrize("merge", [True, False])
209 def test_compare_unrelated_repositories(self, vcsbackend, merge):
218 def test_compare_unrelated_repositories(self, vcsbackend, merge):
210 orig = vcsbackend.create_repo(number_of_commits=5)
219 orig = vcsbackend.create_repo(number_of_commits=5)
211 unrelated = vcsbackend.create_repo(number_of_commits=5)
220 unrelated = vcsbackend.create_repo(number_of_commits=5)
212 assert orig != unrelated
221 assert orig != unrelated
213
222
214 orig.compare(
223 orig.compare(orig[1].raw_id, unrelated[3].raw_id, unrelated, merge=merge)
215 orig[1].raw_id, unrelated[3].raw_id, unrelated, merge=merge)
216
224
217
225
218 class TestRepositoryGetCommonAncestor:
226 class TestRepositoryGetCommonAncestor:
219
220 def test_get_common_ancestor_from_same_repo_existing(self, vcsbackend):
227 def test_get_common_ancestor_from_same_repo_existing(self, vcsbackend):
221 target_repo = vcsbackend.create_repo(number_of_commits=5)
228 target_repo = vcsbackend.create_repo(number_of_commits=5)
222
229
223 expected_ancestor = target_repo[2].raw_id
230 expected_ancestor = target_repo[2].raw_id
224
231
225 assert target_repo.get_common_ancestor(
232 assert (
226 commit_id1=target_repo[2].raw_id,
233 target_repo.get_common_ancestor(
227 commit_id2=target_repo[4].raw_id,
234 commit_id1=target_repo[2].raw_id,
228 repo2=target_repo
235 commit_id2=target_repo[4].raw_id,
229 ) == expected_ancestor
236 repo2=target_repo,
237 )
238 == expected_ancestor
239 )
230
240
231 assert target_repo.get_common_ancestor(
241 assert (
232 commit_id1=target_repo[4].raw_id,
242 target_repo.get_common_ancestor(
233 commit_id2=target_repo[2].raw_id,
243 commit_id1=target_repo[4].raw_id,
234 repo2=target_repo
244 commit_id2=target_repo[2].raw_id,
235 ) == expected_ancestor
245 repo2=target_repo,
246 )
247 == expected_ancestor
248 )
236
249
237 @pytest.mark.xfail_backends("svn")
250 @pytest.mark.xfail_backends("svn")
238 def test_get_common_ancestor_from_cloned_repo_existing(self, vcsbackend):
251 def test_get_common_ancestor_from_cloned_repo_existing(self, vcsbackend):
239 target_repo = vcsbackend.create_repo(number_of_commits=5)
252 target_repo = vcsbackend.create_repo(number_of_commits=5)
240 source_repo = vcsbackend.clone_repo(target_repo)
253 source_repo = vcsbackend.clone_repo(target_repo)
241 assert target_repo != source_repo
254 assert target_repo != source_repo
242
255
243 vcsbackend.add_file(source_repo, b'newfile', b'somecontent')
256 vcsbackend.add_file(source_repo, b"newfile", b"somecontent")
244 source_commit = source_repo.get_commit()
257 source_commit = source_repo.get_commit()
245
258
246 expected_ancestor = target_repo[4].raw_id
259 expected_ancestor = target_repo[4].raw_id
247
260
248 assert target_repo.get_common_ancestor(
261 assert (
249 commit_id1=target_repo[4].raw_id,
262 target_repo.get_common_ancestor(
250 commit_id2=source_commit.raw_id,
263 commit_id1=target_repo[4].raw_id,
251 repo2=source_repo
264 commit_id2=source_commit.raw_id,
252 ) == expected_ancestor
265 repo2=source_repo,
266 )
267 == expected_ancestor
268 )
253
269
254 assert target_repo.get_common_ancestor(
270 assert (
255 commit_id1=source_commit.raw_id,
271 target_repo.get_common_ancestor(
256 commit_id2=target_repo[4].raw_id,
272 commit_id1=source_commit.raw_id,
257 repo2=target_repo
273 commit_id2=target_repo[4].raw_id,
258 ) == expected_ancestor
274 repo2=target_repo,
275 )
276 == expected_ancestor
277 )
259
278
260 @pytest.mark.xfail_backends("svn")
279 @pytest.mark.xfail_backends("svn")
261 def test_get_common_ancestor_from_unrelated_repo_missing(self, vcsbackend):
280 def test_get_common_ancestor_from_unrelated_repo_missing(self, vcsbackend):
262 original = vcsbackend.create_repo(number_of_commits=5)
281 original = vcsbackend.create_repo(number_of_commits=5)
263 unrelated = vcsbackend.create_repo(number_of_commits=5)
282 unrelated = vcsbackend.create_repo(number_of_commits=5)
264 assert original != unrelated
283 assert original != unrelated
265
284
266 assert original.get_common_ancestor(
285 assert (
267 commit_id1=original[0].raw_id,
286 original.get_common_ancestor(
268 commit_id2=unrelated[0].raw_id,
287 commit_id1=original[0].raw_id,
269 repo2=unrelated
288 commit_id2=unrelated[0].raw_id,
270 ) is None
289 repo2=unrelated,
290 )
291 is None
292 )
271
293
272 assert original.get_common_ancestor(
294 assert (
273 commit_id1=original[-1].raw_id,
295 original.get_common_ancestor(
274 commit_id2=unrelated[-1].raw_id,
296 commit_id1=original[-1].raw_id,
275 repo2=unrelated
297 commit_id2=unrelated[-1].raw_id,
276 ) is None
298 repo2=unrelated,
299 )
300 is None
301 )
277
302
278
303
279 @pytest.mark.backends("git", "hg")
304 @pytest.mark.backends("git", "hg")
280 class TestRepositoryMerge(object):
305 class TestRepositoryMerge(object):
281 def prepare_for_success(self, vcsbackend):
306 def prepare_for_success(self, vcsbackend):
282 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
307 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
283 self.source_repo = vcsbackend.clone_repo(self.target_repo)
308 self.source_repo = vcsbackend.clone_repo(self.target_repo)
284 vcsbackend.add_file(self.target_repo, b'README_MERGE1', b'Version 1')
309 vcsbackend.add_file(self.target_repo, b"README_MERGE1", b"Version 1")
285 vcsbackend.add_file(self.source_repo, b'README_MERGE2', b'Version 2')
310 vcsbackend.add_file(self.source_repo, b"README_MERGE2", b"Version 2")
286 imc = self.source_repo.in_memory_commit
311 imc = self.source_repo.in_memory_commit
287 imc.add(FileNode(b'file_x', content=self.source_repo.name))
312 imc.add(FileNode(b"file_x", content=self.source_repo.name))
288 imc.commit(
313 imc.commit(
289 message=u'Automatic commit from repo merge test',
314 message="Automatic commit from repo merge test",
290 author=u'Automatic <automatic@rhodecode.com>')
315 author="Automatic <automatic@rhodecode.com>",
316 )
291 self.target_commit = self.target_repo.get_commit()
317 self.target_commit = self.target_repo.get_commit()
292 self.source_commit = self.source_repo.get_commit()
318 self.source_commit = self.source_repo.get_commit()
293 # This only works for Git and Mercurial
319 # This only works for Git and Mercurial
294 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
320 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
295 self.target_ref = Reference('branch', default_branch, self.target_commit.raw_id)
321 self.target_ref = Reference("branch", default_branch, self.target_commit.raw_id)
296 self.source_ref = Reference('branch', default_branch, self.source_commit.raw_id)
322 self.source_ref = Reference("branch", default_branch, self.source_commit.raw_id)
297 self.workspace_id = 'test-merge-{}'.format(vcsbackend.alias)
323 self.workspace_id = "test-merge-{}".format(vcsbackend.alias)
298 self.repo_id = repo_id_generator(self.target_repo.path)
324 self.repo_id = repo_id_generator(self.target_repo.path)
299
325
300 def prepare_for_conflict(self, vcsbackend):
326 def prepare_for_conflict(self, vcsbackend):
301 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
327 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
302 self.source_repo = vcsbackend.clone_repo(self.target_repo)
328 self.source_repo = vcsbackend.clone_repo(self.target_repo)
303 vcsbackend.add_file(self.target_repo, b'README_MERGE', b'Version 1')
329 vcsbackend.add_file(self.target_repo, b"README_MERGE", b"Version 1")
304 vcsbackend.add_file(self.source_repo, b'README_MERGE', b'Version 2')
330 vcsbackend.add_file(self.source_repo, b"README_MERGE", b"Version 2")
305 self.target_commit = self.target_repo.get_commit()
331 self.target_commit = self.target_repo.get_commit()
306 self.source_commit = self.source_repo.get_commit()
332 self.source_commit = self.source_repo.get_commit()
307 # This only works for Git and Mercurial
333 # This only works for Git and Mercurial
308 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
334 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
309 self.target_ref = Reference('branch', default_branch, self.target_commit.raw_id)
335 self.target_ref = Reference("branch", default_branch, self.target_commit.raw_id)
310 self.source_ref = Reference('branch', default_branch, self.source_commit.raw_id)
336 self.source_ref = Reference("branch", default_branch, self.source_commit.raw_id)
311 self.workspace_id = 'test-merge-{}'.format(vcsbackend.alias)
337 self.workspace_id = "test-merge-{}".format(vcsbackend.alias)
312 self.repo_id = repo_id_generator(self.target_repo.path)
338 self.repo_id = repo_id_generator(self.target_repo.path)
313
339
314 def test_merge_success(self, vcsbackend):
340 def test_merge_success(self, vcsbackend):
315 self.prepare_for_success(vcsbackend)
341 self.prepare_for_success(vcsbackend)
316
342
317 merge_response = self.target_repo.merge(
343 merge_response = self.target_repo.merge(
318 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
344 self.repo_id,
345 self.workspace_id,
346 self.target_ref,
347 self.source_repo,
319 self.source_ref,
348 self.source_ref,
320 'test user', 'test@rhodecode.com', 'merge message 1',
349 "test user",
321 dry_run=False)
350 "test@rhodecode.com",
351 "merge message 1",
352 dry_run=False,
353 )
322 expected_merge_response = MergeResponse(
354 expected_merge_response = MergeResponse(
323 True, True, merge_response.merge_ref,
355 True, True, merge_response.merge_ref, MergeFailureReason.NONE
324 MergeFailureReason.NONE)
356 )
325 assert merge_response == expected_merge_response
357 assert merge_response == expected_merge_response
326
358
327 target_repo = backends.get_backend(vcsbackend.alias)(
359 target_repo = backends.get_backend(vcsbackend.alias)(self.target_repo.path)
328 self.target_repo.path)
329 target_commits = list(target_repo.get_commits())
360 target_commits = list(target_repo.get_commits())
330 commit_ids = [c.raw_id for c in target_commits[:-1]]
361 commit_ids = [c.raw_id for c in target_commits[:-1]]
331 assert self.source_ref.commit_id in commit_ids
362 assert self.source_ref.commit_id in commit_ids
332 assert self.target_ref.commit_id in commit_ids
363 assert self.target_ref.commit_id in commit_ids
333
364
334 merge_commit = target_commits[-1]
365 merge_commit = target_commits[-1]
335 assert merge_commit.raw_id == merge_response.merge_ref.commit_id
366 assert merge_commit.raw_id == merge_response.merge_ref.commit_id
336 assert merge_commit.message.strip() == 'merge message 1'
367 assert merge_commit.message.strip() == "merge message 1"
337 assert merge_commit.author == 'test user <test@rhodecode.com>'
368 assert merge_commit.author == "test user <test@rhodecode.com>"
338
369
339 # We call it twice so to make sure we can handle updates
370 # We call it twice so to make sure we can handle updates
340 target_ref = Reference(
371 target_ref = Reference(
341 self.target_ref.type, self.target_ref.name,
372 self.target_ref.type,
342 merge_response.merge_ref.commit_id)
373 self.target_ref.name,
374 merge_response.merge_ref.commit_id,
375 )
343
376
344 merge_response = target_repo.merge(
377 merge_response = target_repo.merge(
345 self.repo_id, self.workspace_id, target_ref, self.source_repo, self.source_ref,
378 self.repo_id,
346 'test user', 'test@rhodecode.com', 'merge message 2',
379 self.workspace_id,
347 dry_run=False)
380 target_ref,
381 self.source_repo,
382 self.source_ref,
383 "test user",
384 "test@rhodecode.com",
385 "merge message 2",
386 dry_run=False,
387 )
348 expected_merge_response = MergeResponse(
388 expected_merge_response = MergeResponse(
349 True, True, merge_response.merge_ref,
389 True, True, merge_response.merge_ref, MergeFailureReason.NONE
350 MergeFailureReason.NONE)
390 )
351 assert merge_response == expected_merge_response
391 assert merge_response == expected_merge_response
352
392
353 target_repo = backends.get_backend(
393 target_repo = backends.get_backend(vcsbackend.alias)(self.target_repo.path)
354 vcsbackend.alias)(self.target_repo.path)
394 merge_commit = target_repo.get_commit(merge_response.merge_ref.commit_id)
355 merge_commit = target_repo.get_commit(
395 assert merge_commit.message.strip() == "merge message 1"
356 merge_response.merge_ref.commit_id)
396 assert merge_commit.author == "test user <test@rhodecode.com>"
357 assert merge_commit.message.strip() == 'merge message 1'
358 assert merge_commit.author == 'test user <test@rhodecode.com>'
359
397
360 def test_merge_success_dry_run(self, vcsbackend):
398 def test_merge_success_dry_run(self, vcsbackend):
361 self.prepare_for_success(vcsbackend)
399 self.prepare_for_success(vcsbackend)
362
400
363 merge_response = self.target_repo.merge(
401 merge_response = self.target_repo.merge(
364 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
402 self.repo_id,
365 self.source_ref, dry_run=True)
403 self.workspace_id,
404 self.target_ref,
405 self.source_repo,
406 self.source_ref,
407 dry_run=True,
408 )
366
409
367 # We call it twice so to make sure we can handle updates
410 # We call it twice so to make sure we can handle updates
368 merge_response_update = self.target_repo.merge(
411 merge_response_update = self.target_repo.merge(
369 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
412 self.repo_id,
370 self.source_ref, dry_run=True)
413 self.workspace_id,
414 self.target_ref,
415 self.source_repo,
416 self.source_ref,
417 dry_run=True,
418 )
419
420 assert merge_response.merge_ref
421 assert merge_response_update.merge_ref
371
422
372 # Multiple merges may differ in their commit id. Therefore, we set the
423 # Multiple merges may differ in their commit id. Therefore, we set the
373 # commit id to `None` before comparing the merge responses.
424 # commit id to `None` before comparing the merge responses.
374 new_merge_ref = merge_response.merge_ref.commit_id = None
425 merge_response.merge_ref.commit_id = 'abcdeabcde'
375 merge_response.merge_ref = new_merge_ref
376
426
377 new_update_merge_ref = merge_response_update.merge_ref.commit_id = None
427 merge_response_update.merge_ref.commit_id = 'abcdeabcde'
378 merge_response_update.merge_ref = new_update_merge_ref
379
428
380 assert merge_response == merge_response_update
429 assert merge_response == merge_response_update
381 assert merge_response.possible is True
430 assert merge_response.possible is True
382 assert merge_response.executed is False
431 assert merge_response.executed is False
383 assert merge_response.merge_ref
432 assert merge_response.merge_ref
384 assert merge_response.failure_reason is MergeFailureReason.NONE
433 assert merge_response.failure_reason is MergeFailureReason.NONE
385
434
386 @pytest.mark.parametrize('dry_run', [True, False])
435 @pytest.mark.parametrize("dry_run", [True, False])
387 def test_merge_conflict(self, vcsbackend, dry_run):
436 def test_merge_conflict(self, vcsbackend, dry_run):
388 self.prepare_for_conflict(vcsbackend)
437 self.prepare_for_conflict(vcsbackend)
389
438
390 expected_merge_response = MergeResponse(
439 expected_merge_response = MergeResponse(
391 False, False, None, MergeFailureReason.MERGE_FAILED)
440 False, False, None, MergeFailureReason.MERGE_FAILED
441 )
392
442
393 merge_response = self.target_repo.merge(
443 merge_response = self.target_repo.merge(
394 self.repo_id, self.workspace_id, self.target_ref,
444 self.repo_id,
395 self.source_repo, self.source_ref,
445 self.workspace_id,
396 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run)
446 self.target_ref,
447 self.source_repo,
448 self.source_ref,
449 "test_user",
450 "test@rhodecode.com",
451 "test message",
452 dry_run=dry_run,
453 )
397 assert merge_response == expected_merge_response
454 assert merge_response == expected_merge_response
398
455
399 # We call it twice so to make sure we can handle updates
456 # We call it twice so to make sure we can handle updates
400 merge_response = self.target_repo.merge(
457 merge_response = self.target_repo.merge(
401 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
458 self.repo_id,
459 self.workspace_id,
460 self.target_ref,
461 self.source_repo,
402 self.source_ref,
462 self.source_ref,
403 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run)
463 "test_user",
464 "test@rhodecode.com",
465 "test message",
466 dry_run=dry_run,
467 )
404 assert merge_response == expected_merge_response
468 assert merge_response == expected_merge_response
405
469
406 def test_merge_target_is_not_head(self, vcsbackend):
470 def test_merge_target_is_not_head(self, vcsbackend):
407 self.prepare_for_success(vcsbackend)
471 self.prepare_for_success(vcsbackend)
408 target_ref = Reference(
472 target_ref = Reference(self.target_ref.type, self.target_ref.name, "0" * 40)
409 self.target_ref.type, self.target_ref.name, '0' * 40)
410 expected_merge_response = MergeResponse(
473 expected_merge_response = MergeResponse(
411 False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD,
474 False,
412 metadata={'target_ref': target_ref})
475 False,
476 None,
477 MergeFailureReason.TARGET_IS_NOT_HEAD,
478 metadata={"target_ref": target_ref},
479 )
413 merge_response = self.target_repo.merge(
480 merge_response = self.target_repo.merge(
414 self.repo_id, self.workspace_id, target_ref, self.source_repo,
481 self.repo_id,
415 self.source_ref, dry_run=True)
482 self.workspace_id,
483 target_ref,
484 self.source_repo,
485 self.source_ref,
486 dry_run=True,
487 )
416
488
417 assert merge_response == expected_merge_response
489 assert merge_response == expected_merge_response
418
490
419 def test_merge_missing_source_reference(self, vcsbackend):
491 def test_merge_missing_source_reference(self, vcsbackend):
420 self.prepare_for_success(vcsbackend)
492 self.prepare_for_success(vcsbackend)
421
493
422 source_ref = Reference(
494 source_ref = Reference(
423 self.source_ref.type, 'not_existing', self.source_ref.commit_id)
495 self.source_ref.type, "not_existing", self.source_ref.commit_id
496 )
424 expected_merge_response = MergeResponse(
497 expected_merge_response = MergeResponse(
425 False, False, None, MergeFailureReason.MISSING_SOURCE_REF,
498 False,
426 metadata={'source_ref': source_ref})
499 False,
500 None,
501 MergeFailureReason.MISSING_SOURCE_REF,
502 metadata={"source_ref": source_ref},
503 )
427
504
428 merge_response = self.target_repo.merge(
505 merge_response = self.target_repo.merge(
429 self.repo_id, self.workspace_id, self.target_ref,
506 self.repo_id,
430 self.source_repo, source_ref,
507 self.workspace_id,
431 dry_run=True)
508 self.target_ref,
509 self.source_repo,
510 source_ref,
511 dry_run=True,
512 )
432
513
433 assert merge_response == expected_merge_response
514 assert merge_response == expected_merge_response
434
515
435 def test_merge_raises_exception(self, vcsbackend):
516 def test_merge_raises_exception(self, vcsbackend):
436 self.prepare_for_success(vcsbackend)
517 self.prepare_for_success(vcsbackend)
437 expected_merge_response = MergeResponse(
518 expected_merge_response = MergeResponse(
438 False, False, None, MergeFailureReason.UNKNOWN,
519 False,
439 metadata={'exception': 'ErrorForTest'})
520 False,
521 None,
522 MergeFailureReason.UNKNOWN,
523 metadata={"exception": "ErrorForTest"},
524 )
440
525
441 with mock.patch.object(self.target_repo, '_merge_repo',
526 with mock.patch.object(
442 side_effect=RepositoryError()):
527 self.target_repo, "_merge_repo", side_effect=RepositoryError()
528 ):
443 merge_response = self.target_repo.merge(
529 merge_response = self.target_repo.merge(
444 self.repo_id, self.workspace_id, self.target_ref,
530 self.repo_id,
445 self.source_repo, self.source_ref,
531 self.workspace_id,
446 dry_run=True)
532 self.target_ref,
533 self.source_repo,
534 self.source_ref,
535 dry_run=True,
536 )
447
537
448 assert merge_response == expected_merge_response
538 assert merge_response == expected_merge_response
449
539
450 def test_merge_invalid_user_name(self, vcsbackend):
540 def test_merge_invalid_user_name(self, vcsbackend):
451 repo = vcsbackend.create_repo(number_of_commits=1)
541 repo = vcsbackend.create_repo(number_of_commits=1)
452 ref = Reference('branch', 'master', 'not_used')
542 ref = Reference("branch", "master", "not_used")
453 workspace_id = 'test-errors-in-merge'
543 workspace_id = "test-errors-in-merge"
454 repo_id = repo_id_generator(workspace_id)
544 repo_id = repo_id_generator(workspace_id)
455 with pytest.raises(ValueError):
545 with pytest.raises(ValueError):
456 repo.merge(repo_id, workspace_id, ref, self, ref)
546 repo.merge(repo_id, workspace_id, ref, self, ref)
457
547
458 def test_merge_invalid_user_email(self, vcsbackend):
548 def test_merge_invalid_user_email(self, vcsbackend):
459 repo = vcsbackend.create_repo(number_of_commits=1)
549 repo = vcsbackend.create_repo(number_of_commits=1)
460 ref = Reference('branch', 'master', 'not_used')
550 ref = Reference("branch", "master", "not_used")
461 workspace_id = 'test-errors-in-merge'
551 workspace_id = "test-errors-in-merge"
552 repo_id = repo_id_generator(workspace_id)
553 with pytest.raises(ValueError):
554 repo.merge(repo_id, workspace_id, ref, self, ref, "user name")
555
556 def test_merge_invalid_message(self, vcsbackend):
557 repo = vcsbackend.create_repo(number_of_commits=1)
558 ref = Reference("branch", "master", "not_used")
559 workspace_id = "test-errors-in-merge"
462 repo_id = repo_id_generator(workspace_id)
560 repo_id = repo_id_generator(workspace_id)
463 with pytest.raises(ValueError):
561 with pytest.raises(ValueError):
464 repo.merge(
562 repo.merge(
465 repo_id, workspace_id, ref, self, ref, 'user name')
563 repo_id, workspace_id, ref, self, ref, "user name", "user@email.com"
466
564 )
467 def test_merge_invalid_message(self, vcsbackend):
468 repo = vcsbackend.create_repo(number_of_commits=1)
469 ref = Reference('branch', 'master', 'not_used')
470 workspace_id = 'test-errors-in-merge'
471 repo_id = repo_id_generator(workspace_id)
472 with pytest.raises(ValueError):
473 repo.merge(
474 repo_id, workspace_id, ref, self, ref,
475 'user name', 'user@email.com')
476
565
477
566
478 @pytest.mark.usefixtures("vcs_repository_support")
567 @pytest.mark.usefixtures("vcs_repository_support")
479 class TestRepositoryStrip(BackendTestMixin):
568 class TestRepositoryStrip(BackendTestMixin):
480 recreate_repo_per_test = True
569 recreate_repo_per_test = True
481
570
482 @classmethod
571 @classmethod
483 def _get_commits(cls):
572 def _get_commits(cls):
484 commits = [
573 commits = [
485 {
574 {
486 'message': 'Initial commit',
575 "message": "Initial commit",
487 'author': 'Joe Doe <joe.doe@example.com>',
576 "author": "Joe Doe <joe.doe@example.com>",
488 'date': datetime.datetime(2010, 1, 1, 20),
577 "date": datetime.datetime(2010, 1, 1, 20),
489 'branch': 'master',
578 "branch": "master",
490 'added': [
579 "added": [
491 FileNode(b'foobar', content='foobar'),
580 FileNode(b"foobar", content="foobar"),
492 FileNode(b'foobar2', content='foobar2'),
581 FileNode(b"foobar2", content="foobar2"),
493 ],
582 ],
494 },
583 },
495 ]
584 ]
496 for x in range(10):
585 for x in range(10):
497 commit_data = {
586 commit_data = {
498 'message': 'Changed foobar - commit%s' % x,
587 "message": "Changed foobar - commit%s" % x,
499 'author': 'Jane Doe <jane.doe@example.com>',
588 "author": "Jane Doe <jane.doe@example.com>",
500 'date': datetime.datetime(2010, 1, 1, 21, x),
589 "date": datetime.datetime(2010, 1, 1, 21, x),
501 'branch': 'master',
590 "branch": "master",
502 'changed': [
591 "changed": [
503 FileNode(b'foobar', 'FOOBAR - %s' % x),
592 FileNode(b"foobar", "FOOBAR - %s" % x),
504 ],
593 ],
505 }
594 }
506 commits.append(commit_data)
595 commits.append(commit_data)
507 return commits
596 return commits
508
597
509 @pytest.mark.backends("git", "hg")
598 @pytest.mark.backends("git", "hg")
510 def test_strip_commit(self):
599 def test_strip_commit(self):
511 tip = self.repo.get_commit()
600 tip = self.repo.get_commit()
512 assert tip.idx == 10
601 assert tip.idx == 10
513 self.repo.strip(tip.raw_id, self.repo.DEFAULT_BRANCH_NAME)
602 self.repo.strip(tip.raw_id, self.repo.DEFAULT_BRANCH_NAME)
514
603
515 tip = self.repo.get_commit()
604 tip = self.repo.get_commit()
516 assert tip.idx == 9
605 assert tip.idx == 9
517
606
518 @pytest.mark.backends("git", "hg")
607 @pytest.mark.backends("git", "hg")
519 def test_strip_multiple_commits(self):
608 def test_strip_multiple_commits(self):
520 tip = self.repo.get_commit()
609 tip = self.repo.get_commit()
521 assert tip.idx == 10
610 assert tip.idx == 10
522
611
523 old = self.repo.get_commit(commit_idx=5)
612 old = self.repo.get_commit(commit_idx=5)
524 self.repo.strip(old.raw_id, self.repo.DEFAULT_BRANCH_NAME)
613 self.repo.strip(old.raw_id, self.repo.DEFAULT_BRANCH_NAME)
525
614
526 tip = self.repo.get_commit()
615 tip = self.repo.get_commit()
527 assert tip.idx == 4
616 assert tip.idx == 4
528
617
529
618
530 @pytest.mark.backends('hg', 'git')
619 @pytest.mark.backends("hg", "git")
531 class TestRepositoryPull(object):
620 class TestRepositoryPull(object):
532
533 def test_pull(self, vcsbackend):
621 def test_pull(self, vcsbackend):
534 source_repo = vcsbackend.repo
622 source_repo = vcsbackend.repo
535 target_repo = vcsbackend.create_repo()
623 target_repo = vcsbackend.create_repo()
536 assert len(source_repo.commit_ids) > len(target_repo.commit_ids)
624 assert len(source_repo.commit_ids) > len(target_repo.commit_ids)
537
625
538 target_repo.pull(source_repo.path)
626 target_repo.pull(source_repo.path)
539 # Note: Get a fresh instance, avoids caching trouble
627 # Note: Get a fresh instance, avoids caching trouble
540 target_repo = vcsbackend.backend(target_repo.path)
628 target_repo = vcsbackend.backend(target_repo.path)
541 assert len(source_repo.commit_ids) == len(target_repo.commit_ids)
629 assert len(source_repo.commit_ids) == len(target_repo.commit_ids)
542
630
543 def test_pull_wrong_path(self, vcsbackend):
631 def test_pull_wrong_path(self, vcsbackend):
544 target_repo = vcsbackend.create_repo()
632 target_repo = vcsbackend.create_repo()
545 with pytest.raises(RepositoryError):
633 with pytest.raises(RepositoryError):
546 target_repo.pull(target_repo.path + "wrong")
634 target_repo.pull(target_repo.path + "wrong")
547
635
548 def test_pull_specific_commits(self, vcsbackend):
636 def test_pull_specific_commits(self, vcsbackend):
549 source_repo = vcsbackend.repo
637 source_repo = vcsbackend.repo
550 target_repo = vcsbackend.create_repo()
638 target_repo = vcsbackend.create_repo()
551
639
552 second_commit = source_repo[1].raw_id
640 second_commit = source_repo[1].raw_id
553 if vcsbackend.alias == 'git':
641 if vcsbackend.alias == "git":
554 second_commit_ref = 'refs/test-refs/a'
642 second_commit_ref = "refs/test-refs/a"
555 source_repo.set_refs(second_commit_ref, second_commit)
643 source_repo.set_refs(second_commit_ref, second_commit)
556
644
557 target_repo.pull(source_repo.path, commit_ids=[second_commit])
645 target_repo.pull(source_repo.path, commit_ids=[second_commit])
558 target_repo = vcsbackend.backend(target_repo.path)
646 target_repo = vcsbackend.backend(target_repo.path)
559 assert 2 == len(target_repo.commit_ids)
647 assert 2 == len(target_repo.commit_ids)
560 assert second_commit == target_repo.get_commit().raw_id
648 assert second_commit == target_repo.get_commit().raw_id
General Comments 0
You need to be logged in to leave comments. Login now