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