##// END OF EJS Templates
tests: removed use of unicode() calls
super-admin -
r4993:debf4b3b default
parent child Browse files
Show More
@@ -1,256 +1,256 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 time
21 import time
22 import shutil
22 import shutil
23 import datetime
23 import datetime
24
24
25 import pytest
25 import pytest
26
26
27 from rhodecode.lib.vcs.backends import get_backend
27 from rhodecode.lib.vcs.backends import get_backend
28 from rhodecode.lib.vcs.backends.base import Config
28 from rhodecode.lib.vcs.backends.base import Config
29 from rhodecode.lib.vcs.nodes import FileNode
29 from rhodecode.lib.vcs.nodes import FileNode
30 from rhodecode.tests import get_new_dir
30 from rhodecode.tests import get_new_dir
31 from rhodecode.tests.utils import check_skip_backends, check_xfail_backends
31 from rhodecode.tests.utils import check_skip_backends, check_xfail_backends
32
32
33
33
34 @pytest.fixture()
34 @pytest.fixture()
35 def vcs_repository_support(
35 def vcs_repository_support(
36 request, backend_alias, baseapp, _vcs_repo_container):
36 request, backend_alias, baseapp, _vcs_repo_container):
37 """
37 """
38 Provide a test repository for the test run.
38 Provide a test repository for the test run.
39
39
40 Depending on the value of `recreate_repo_per_test` a new repo for each
40 Depending on the value of `recreate_repo_per_test` a new repo for each
41 test will be created.
41 test will be created.
42
42
43 The parameter `--backends` can be used to limit this fixture to specific
43 The parameter `--backends` can be used to limit this fixture to specific
44 backend implementations.
44 backend implementations.
45 """
45 """
46 cls = request.cls
46 cls = request.cls
47
47
48 check_skip_backends(request.node, backend_alias)
48 check_skip_backends(request.node, backend_alias)
49 check_xfail_backends(request.node, backend_alias)
49 check_xfail_backends(request.node, backend_alias)
50
50
51 if _should_create_repo_per_test(cls):
51 if _should_create_repo_per_test(cls):
52 _vcs_repo_container = _create_vcs_repo_container(request)
52 _vcs_repo_container = _create_vcs_repo_container(request)
53
53
54 repo = _vcs_repo_container.get_repo(cls, backend_alias=backend_alias)
54 repo = _vcs_repo_container.get_repo(cls, backend_alias=backend_alias)
55
55
56 # TODO: johbo: Supporting old test class api, think about removing this
56 # TODO: johbo: Supporting old test class api, think about removing this
57 cls.repo = repo
57 cls.repo = repo
58 cls.repo_path = repo.path
58 cls.repo_path = repo.path
59 cls.default_branch = repo.DEFAULT_BRANCH_NAME
59 cls.default_branch = repo.DEFAULT_BRANCH_NAME
60 cls.Backend = cls.backend_class = repo.__class__
60 cls.Backend = cls.backend_class = repo.__class__
61 cls.imc = repo.in_memory_commit
61 cls.imc = repo.in_memory_commit
62
62
63 return backend_alias, repo
63 return backend_alias, repo
64
64
65
65
66 @pytest.fixture(scope='class')
66 @pytest.fixture(scope='class')
67 def _vcs_repo_container(request):
67 def _vcs_repo_container(request):
68 """
68 """
69 Internal fixture intended to help support class based scoping on demand.
69 Internal fixture intended to help support class based scoping on demand.
70 """
70 """
71 return _create_vcs_repo_container(request)
71 return _create_vcs_repo_container(request)
72
72
73
73
74 def _create_vcs_repo_container(request):
74 def _create_vcs_repo_container(request):
75 repo_container = VcsRepoContainer()
75 repo_container = VcsRepoContainer()
76 if not request.config.getoption('--keep-tmp-path'):
76 if not request.config.getoption('--keep-tmp-path'):
77 request.addfinalizer(repo_container.cleanup)
77 request.addfinalizer(repo_container.cleanup)
78 return repo_container
78 return repo_container
79
79
80
80
81 class VcsRepoContainer(object):
81 class VcsRepoContainer(object):
82
82
83 def __init__(self):
83 def __init__(self):
84 self._cleanup_paths = []
84 self._cleanup_paths = []
85 self._repos = {}
85 self._repos = {}
86
86
87 def get_repo(self, test_class, backend_alias):
87 def get_repo(self, test_class, backend_alias):
88 if backend_alias not in self._repos:
88 if backend_alias not in self._repos:
89 repo = _create_empty_repository(test_class, backend_alias)
89 repo = _create_empty_repository(test_class, backend_alias)
90
90
91 self._cleanup_paths.append(repo.path)
91 self._cleanup_paths.append(repo.path)
92 self._repos[backend_alias] = repo
92 self._repos[backend_alias] = repo
93 return self._repos[backend_alias]
93 return self._repos[backend_alias]
94
94
95 def cleanup(self):
95 def cleanup(self):
96 for repo_path in reversed(self._cleanup_paths):
96 for repo_path in reversed(self._cleanup_paths):
97 shutil.rmtree(repo_path)
97 shutil.rmtree(repo_path)
98
98
99
99
100 def _should_create_repo_per_test(cls):
100 def _should_create_repo_per_test(cls):
101 return getattr(cls, 'recreate_repo_per_test', False)
101 return getattr(cls, 'recreate_repo_per_test', False)
102
102
103
103
104 def _create_empty_repository(cls, backend_alias=None):
104 def _create_empty_repository(cls, backend_alias=None):
105 Backend = get_backend(backend_alias or cls.backend_alias)
105 Backend = get_backend(backend_alias or cls.backend_alias)
106 repo_path = get_new_dir(str(time.time()))
106 repo_path = get_new_dir(str(time.time()))
107 repo = Backend(repo_path, create=True)
107 repo = Backend(repo_path, create=True)
108 if hasattr(cls, '_get_commits'):
108 if hasattr(cls, '_get_commits'):
109 commits = cls._get_commits()
109 commits = cls._get_commits()
110 cls.tip = _add_commits_to_repo(repo, commits)
110 cls.tip = _add_commits_to_repo(repo, commits)
111
111
112 return repo
112 return repo
113
113
114
114
115 @pytest.fixture()
115 @pytest.fixture()
116 def config():
116 def config():
117 """
117 """
118 Instance of a repository config.
118 Instance of a repository config.
119
119
120 The instance contains only one value:
120 The instance contains only one value:
121
121
122 - Section: "section-a"
122 - Section: "section-a"
123 - Key: "a-1"
123 - Key: "a-1"
124 - Value: "value-a-1"
124 - Value: "value-a-1"
125
125
126 The intended usage is for cases where a config instance is needed but no
126 The intended usage is for cases where a config instance is needed but no
127 specific content is required.
127 specific content is required.
128 """
128 """
129 config = Config()
129 config = Config()
130 config.set('section-a', 'a-1', 'value-a-1')
130 config.set('section-a', 'a-1', 'value-a-1')
131 return config
131 return config
132
132
133
133
134 def _add_commits_to_repo(repo, commits):
134 def _add_commits_to_repo(repo, commits):
135 imc = repo.in_memory_commit
135 imc = repo.in_memory_commit
136 tip = None
136 tip = None
137
137
138 for commit in commits:
138 for commit in commits:
139 for node in commit.get('added', []):
139 for node in commit.get('added', []):
140 imc.add(FileNode(node.path, content=node.content))
140 imc.add(FileNode(node.path, content=node.content))
141 for node in commit.get('changed', []):
141 for node in commit.get('changed', []):
142 imc.change(FileNode(node.path, content=node.content))
142 imc.change(FileNode(node.path, content=node.content))
143 for node in commit.get('removed', []):
143 for node in commit.get('removed', []):
144 imc.remove(FileNode(node.path))
144 imc.remove(FileNode(node.path))
145
145
146 tip = imc.commit(
146 tip = imc.commit(
147 message=unicode(commit['message']),
147 message=str(commit['message']),
148 author=unicode(commit['author']),
148 author=str(commit['author']),
149 date=commit['date'],
149 date=commit['date'],
150 branch=commit.get('branch'))
150 branch=commit.get('branch'))
151 return tip
151 return tip
152
152
153
153
154 @pytest.fixture()
154 @pytest.fixture()
155 def vcs_repo(request, backend_alias):
155 def vcs_repo(request, backend_alias):
156 Backend = get_backend(backend_alias)
156 Backend = get_backend(backend_alias)
157 repo_path = get_new_dir(str(time.time()))
157 repo_path = get_new_dir(str(time.time()))
158 repo = Backend(repo_path, create=True)
158 repo = Backend(repo_path, create=True)
159
159
160 @request.addfinalizer
160 @request.addfinalizer
161 def cleanup():
161 def cleanup():
162 shutil.rmtree(repo_path)
162 shutil.rmtree(repo_path)
163
163
164 return repo
164 return repo
165
165
166
166
167 @pytest.fixture()
167 @pytest.fixture()
168 def generate_repo_with_commits(vcs_repo):
168 def generate_repo_with_commits(vcs_repo):
169 """
169 """
170 Creates a fabric to generate N comits with some file nodes on a randomly
170 Creates a fabric to generate N comits with some file nodes on a randomly
171 generated repository
171 generated repository
172 """
172 """
173
173
174 def commit_generator(num):
174 def commit_generator(num):
175 start_date = datetime.datetime(2010, 1, 1, 20)
175 start_date = datetime.datetime(2010, 1, 1, 20)
176 for x in range(num):
176 for x in range(num):
177 yield {
177 yield {
178 'message': 'Commit %d' % x,
178 'message': 'Commit %d' % x,
179 'author': 'Joe Doe <joe.doe@example.com>',
179 'author': 'Joe Doe <joe.doe@example.com>',
180 'date': start_date + datetime.timedelta(hours=12 * x),
180 'date': start_date + datetime.timedelta(hours=12 * x),
181 'added': [
181 'added': [
182 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
182 FileNode('file_%d.txt' % x, content='Foobar %d' % x),
183 ],
183 ],
184 'modified': [
184 'modified': [
185 FileNode('file_%d.txt' % x,
185 FileNode('file_%d.txt' % x,
186 content='Foobar %d modified' % (x-1)),
186 content='Foobar %d modified' % (x-1)),
187 ]
187 ]
188 }
188 }
189
189
190 def commit_maker(num=5):
190 def commit_maker(num=5):
191 _add_commits_to_repo(vcs_repo, commit_generator(num))
191 _add_commits_to_repo(vcs_repo, commit_generator(num))
192 return vcs_repo
192 return vcs_repo
193
193
194 return commit_maker
194 return commit_maker
195
195
196
196
197 @pytest.fixture()
197 @pytest.fixture()
198 def hg_repo(request, vcs_repo):
198 def hg_repo(request, vcs_repo):
199 repo = vcs_repo
199 repo = vcs_repo
200
200
201 commits = repo._get_commits()
201 commits = repo._get_commits()
202 _add_commits_to_repo(repo, commits)
202 _add_commits_to_repo(repo, commits)
203
203
204 return repo
204 return repo
205
205
206
206
207 @pytest.fixture()
207 @pytest.fixture()
208 def hg_commit(hg_repo):
208 def hg_commit(hg_repo):
209 return hg_repo.get_commit()
209 return hg_repo.get_commit()
210
210
211
211
212 class BackendTestMixin(object):
212 class BackendTestMixin(object):
213 """
213 """
214 This is a backend independent test case class which should be created
214 This is a backend independent test case class which should be created
215 with ``type`` method.
215 with ``type`` method.
216
216
217 It is required to set following attributes at subclass:
217 It is required to set following attributes at subclass:
218
218
219 - ``backend_alias``: alias of used backend (see ``vcs.BACKENDS``)
219 - ``backend_alias``: alias of used backend (see ``vcs.BACKENDS``)
220 - ``repo_path``: path to the repository which would be created for set of
220 - ``repo_path``: path to the repository which would be created for set of
221 tests
221 tests
222 - ``recreate_repo_per_test``: If set to ``False``, repo would NOT be
222 - ``recreate_repo_per_test``: If set to ``False``, repo would NOT be
223 created
223 created
224 before every single test. Defaults to ``True``.
224 before every single test. Defaults to ``True``.
225 """
225 """
226 recreate_repo_per_test = True
226 recreate_repo_per_test = True
227
227
228 @classmethod
228 @classmethod
229 def _get_commits(cls):
229 def _get_commits(cls):
230 commits = [
230 commits = [
231 {
231 {
232 'message': u'Initial commit',
232 'message': u'Initial commit',
233 'author': u'Joe Doe <joe.doe@example.com>',
233 'author': u'Joe Doe <joe.doe@example.com>',
234 'date': datetime.datetime(2010, 1, 1, 20),
234 'date': datetime.datetime(2010, 1, 1, 20),
235 'added': [
235 'added': [
236 FileNode('foobar', content='Foobar'),
236 FileNode('foobar', content='Foobar'),
237 FileNode('foobar2', content='Foobar II'),
237 FileNode('foobar2', content='Foobar II'),
238 FileNode('foo/bar/baz', content='baz here!'),
238 FileNode('foo/bar/baz', content='baz here!'),
239 ],
239 ],
240 },
240 },
241 {
241 {
242 'message': u'Changes...',
242 'message': u'Changes...',
243 'author': u'Jane Doe <jane.doe@example.com>',
243 'author': u'Jane Doe <jane.doe@example.com>',
244 'date': datetime.datetime(2010, 1, 1, 21),
244 'date': datetime.datetime(2010, 1, 1, 21),
245 'added': [
245 'added': [
246 FileNode('some/new.txt', content='news...'),
246 FileNode('some/new.txt', content='news...'),
247 ],
247 ],
248 'changed': [
248 'changed': [
249 FileNode('foobar', 'Foobar I'),
249 FileNode('foobar', 'Foobar I'),
250 ],
250 ],
251 'removed': [],
251 'removed': [],
252 },
252 },
253 ]
253 ]
254 return commits
254 return commits
255
255
256
256
@@ -1,552 +1,552 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 urllib.error import URLError
22 from urllib.error 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.conftest import BackendTestMixin
32 from rhodecode.tests.vcs.conftest import BackendTestMixin
33 from rhodecode.tests import repo_id_generator
33 from rhodecode.tests import repo_id_generator
34
34
35
35
36 @pytest.mark.usefixtures("vcs_repository_support")
36 @pytest.mark.usefixtures("vcs_repository_support")
37 class TestRepositoryBase(BackendTestMixin):
37 class TestRepositoryBase(BackendTestMixin):
38 recreate_repo_per_test = False
38 recreate_repo_per_test = False
39
39
40 def test_init_accepts_unicode_path(self, tmpdir):
40 def test_init_accepts_unicode_path(self, tmpdir):
41 path = unicode(tmpdir.join(u'unicode Γ€'))
41 path = str(tmpdir.join(u'unicode Γ€'))
42 self.Backend(path, create=True)
42 self.Backend(path, create=True)
43
43
44 def test_init_accepts_str_path(self, tmpdir):
44 def test_init_accepts_str_path(self, tmpdir):
45 path = str(tmpdir.join('str Γ€'))
45 path = str(tmpdir.join('str Γ€'))
46 self.Backend(path, create=True)
46 self.Backend(path, create=True)
47
47
48 def test_init_fails_if_path_does_not_exist(self, tmpdir):
48 def test_init_fails_if_path_does_not_exist(self, tmpdir):
49 path = unicode(tmpdir.join('i-do-not-exist'))
49 path = str(tmpdir.join('i-do-not-exist'))
50 with pytest.raises(VCSError):
50 with pytest.raises(VCSError):
51 self.Backend(path)
51 self.Backend(path)
52
52
53 def test_init_fails_if_path_is_not_a_valid_repository(self, tmpdir):
53 def test_init_fails_if_path_is_not_a_valid_repository(self, tmpdir):
54 path = unicode(tmpdir.mkdir(u'unicode Γ€'))
54 path = str(tmpdir.mkdir(u'unicode Γ€'))
55 with pytest.raises(VCSError):
55 with pytest.raises(VCSError):
56 self.Backend(path)
56 self.Backend(path)
57
57
58 def test_has_commits_attribute(self):
58 def test_has_commits_attribute(self):
59 self.repo.commit_ids
59 self.repo.commit_ids
60
60
61 def test_name(self):
61 def test_name(self):
62 assert self.repo.name.startswith('vcs-test')
62 assert self.repo.name.startswith('vcs-test')
63
63
64 @pytest.mark.backends("hg", "git")
64 @pytest.mark.backends("hg", "git")
65 def test_has_default_branch_name(self):
65 def test_has_default_branch_name(self):
66 assert self.repo.DEFAULT_BRANCH_NAME is not None
66 assert self.repo.DEFAULT_BRANCH_NAME is not None
67
67
68 @pytest.mark.backends("svn")
68 @pytest.mark.backends("svn")
69 def test_has_no_default_branch_name(self):
69 def test_has_no_default_branch_name(self):
70 assert self.repo.DEFAULT_BRANCH_NAME is None
70 assert self.repo.DEFAULT_BRANCH_NAME is None
71
71
72 def test_has_empty_commit(self):
72 def test_has_empty_commit(self):
73 assert self.repo.EMPTY_COMMIT_ID is not None
73 assert self.repo.EMPTY_COMMIT_ID is not None
74 assert self.repo.EMPTY_COMMIT is not None
74 assert self.repo.EMPTY_COMMIT is not None
75
75
76 def test_empty_changeset_is_deprecated(self):
76 def test_empty_changeset_is_deprecated(self):
77 def get_empty_changeset(repo):
77 def get_empty_changeset(repo):
78 return repo.EMPTY_CHANGESET
78 return repo.EMPTY_CHANGESET
79 pytest.deprecated_call(get_empty_changeset, self.repo)
79 pytest.deprecated_call(get_empty_changeset, self.repo)
80
80
81 def test_bookmarks(self):
81 def test_bookmarks(self):
82 assert len(self.repo.bookmarks) == 0
82 assert len(self.repo.bookmarks) == 0
83
83
84 # TODO: Cover two cases: Local repo path, remote URL
84 # TODO: Cover two cases: Local repo path, remote URL
85 def test_check_url(self):
85 def test_check_url(self):
86 config = Config()
86 config = Config()
87 assert self.Backend.check_url(self.repo.path, config)
87 assert self.Backend.check_url(self.repo.path, config)
88
88
89 def test_check_url_invalid(self):
89 def test_check_url_invalid(self):
90 config = Config()
90 config = Config()
91 with pytest.raises(URLError):
91 with pytest.raises(URLError):
92 self.Backend.check_url(self.repo.path + "invalid", config)
92 self.Backend.check_url(self.repo.path + "invalid", config)
93
93
94 def test_get_contact(self):
94 def test_get_contact(self):
95 assert self.repo.contact
95 assert self.repo.contact
96
96
97 def test_get_description(self):
97 def test_get_description(self):
98 assert self.repo.description
98 assert self.repo.description
99
99
100 def test_get_hook_location(self):
100 def test_get_hook_location(self):
101 assert len(self.repo.get_hook_location()) != 0
101 assert len(self.repo.get_hook_location()) != 0
102
102
103 def test_last_change(self, local_dt_to_utc):
103 def test_last_change(self, local_dt_to_utc):
104 assert self.repo.last_change >= local_dt_to_utc(
104 assert self.repo.last_change >= local_dt_to_utc(
105 datetime.datetime(2010, 1, 1, 21, 0))
105 datetime.datetime(2010, 1, 1, 21, 0))
106
106
107 def test_last_change_in_empty_repository(self, vcsbackend, local_dt_to_utc):
107 def test_last_change_in_empty_repository(self, vcsbackend, local_dt_to_utc):
108 delta = datetime.timedelta(seconds=1)
108 delta = datetime.timedelta(seconds=1)
109
109
110 start = local_dt_to_utc(datetime.datetime.now())
110 start = local_dt_to_utc(datetime.datetime.now())
111 empty_repo = vcsbackend.create_repo()
111 empty_repo = vcsbackend.create_repo()
112 now = local_dt_to_utc(datetime.datetime.now())
112 now = local_dt_to_utc(datetime.datetime.now())
113 assert empty_repo.last_change >= start - delta
113 assert empty_repo.last_change >= start - delta
114 assert empty_repo.last_change <= now + delta
114 assert empty_repo.last_change <= now + delta
115
115
116 def test_repo_equality(self):
116 def test_repo_equality(self):
117 assert self.repo == self.repo
117 assert self.repo == self.repo
118
118
119 def test_repo_equality_broken_object(self):
119 def test_repo_equality_broken_object(self):
120 import copy
120 import copy
121 _repo = copy.copy(self.repo)
121 _repo = copy.copy(self.repo)
122 delattr(_repo, 'path')
122 delattr(_repo, 'path')
123 assert self.repo != _repo
123 assert self.repo != _repo
124
124
125 def test_repo_equality_other_object(self):
125 def test_repo_equality_other_object(self):
126 class dummy(object):
126 class dummy(object):
127 path = self.repo.path
127 path = self.repo.path
128 assert self.repo != dummy()
128 assert self.repo != dummy()
129
129
130 def test_get_commit_is_implemented(self):
130 def test_get_commit_is_implemented(self):
131 self.repo.get_commit()
131 self.repo.get_commit()
132
132
133 def test_get_commits_is_implemented(self):
133 def test_get_commits_is_implemented(self):
134 commit_iter = iter(self.repo.get_commits())
134 commit_iter = iter(self.repo.get_commits())
135 commit = next(commit_iter)
135 commit = next(commit_iter)
136 assert commit.idx == 0
136 assert commit.idx == 0
137
137
138 def test_supports_iteration(self):
138 def test_supports_iteration(self):
139 repo_iter = iter(self.repo)
139 repo_iter = iter(self.repo)
140 commit = next(repo_iter)
140 commit = next(repo_iter)
141 assert commit.idx == 0
141 assert commit.idx == 0
142
142
143 def test_in_memory_commit(self):
143 def test_in_memory_commit(self):
144 imc = self.repo.in_memory_commit
144 imc = self.repo.in_memory_commit
145 assert isinstance(imc, BaseInMemoryCommit)
145 assert isinstance(imc, BaseInMemoryCommit)
146
146
147 @pytest.mark.backends("hg")
147 @pytest.mark.backends("hg")
148 def test__get_url_unicode(self):
148 def test__get_url_unicode(self):
149 url = u'/home/repos/malmΓΆ'
149 url = u'/home/repos/malmΓΆ'
150 assert self.repo._get_url(url)
150 assert self.repo._get_url(url)
151
151
152
152
153 @pytest.mark.usefixtures("vcs_repository_support")
153 @pytest.mark.usefixtures("vcs_repository_support")
154 class TestDeprecatedRepositoryAPI(BackendTestMixin):
154 class TestDeprecatedRepositoryAPI(BackendTestMixin):
155 recreate_repo_per_test = False
155 recreate_repo_per_test = False
156
156
157 def test_revisions_is_deprecated(self):
157 def test_revisions_is_deprecated(self):
158 def get_revisions(repo):
158 def get_revisions(repo):
159 return repo.revisions
159 return repo.revisions
160 pytest.deprecated_call(get_revisions, self.repo)
160 pytest.deprecated_call(get_revisions, self.repo)
161
161
162 def test_get_changeset_is_deprecated(self):
162 def test_get_changeset_is_deprecated(self):
163 pytest.deprecated_call(self.repo.get_changeset)
163 pytest.deprecated_call(self.repo.get_changeset)
164
164
165 def test_get_changesets_is_deprecated(self):
165 def test_get_changesets_is_deprecated(self):
166 pytest.deprecated_call(self.repo.get_changesets)
166 pytest.deprecated_call(self.repo.get_changesets)
167
167
168 def test_in_memory_changeset_is_deprecated(self):
168 def test_in_memory_changeset_is_deprecated(self):
169 def get_imc(repo):
169 def get_imc(repo):
170 return repo.in_memory_changeset
170 return repo.in_memory_changeset
171 pytest.deprecated_call(get_imc, self.repo)
171 pytest.deprecated_call(get_imc, self.repo)
172
172
173
173
174 # TODO: these tests are incomplete, must check the resulting compare result for
174 # TODO: these tests are incomplete, must check the resulting compare result for
175 # correcteness
175 # correcteness
176 class TestRepositoryCompare:
176 class TestRepositoryCompare:
177
177
178 @pytest.mark.parametrize('merge', [True, False])
178 @pytest.mark.parametrize('merge', [True, False])
179 def test_compare_commits_of_same_repository(self, vcsbackend, merge):
179 def test_compare_commits_of_same_repository(self, vcsbackend, merge):
180 target_repo = vcsbackend.create_repo(number_of_commits=5)
180 target_repo = vcsbackend.create_repo(number_of_commits=5)
181 target_repo.compare(
181 target_repo.compare(
182 target_repo[1].raw_id, target_repo[3].raw_id, target_repo,
182 target_repo[1].raw_id, target_repo[3].raw_id, target_repo,
183 merge=merge)
183 merge=merge)
184
184
185 @pytest.mark.xfail_backends('svn')
185 @pytest.mark.xfail_backends('svn')
186 @pytest.mark.parametrize('merge', [True, False])
186 @pytest.mark.parametrize('merge', [True, False])
187 def test_compare_cloned_repositories(self, vcsbackend, merge):
187 def test_compare_cloned_repositories(self, vcsbackend, merge):
188 target_repo = vcsbackend.create_repo(number_of_commits=5)
188 target_repo = vcsbackend.create_repo(number_of_commits=5)
189 source_repo = vcsbackend.clone_repo(target_repo)
189 source_repo = vcsbackend.clone_repo(target_repo)
190 assert target_repo != source_repo
190 assert target_repo != source_repo
191
191
192 vcsbackend.add_file(source_repo, 'newfile', 'somecontent')
192 vcsbackend.add_file(source_repo, 'newfile', 'somecontent')
193 source_commit = source_repo.get_commit()
193 source_commit = source_repo.get_commit()
194
194
195 target_repo.compare(
195 target_repo.compare(
196 target_repo[1].raw_id, source_repo[3].raw_id, source_repo,
196 target_repo[1].raw_id, source_repo[3].raw_id, source_repo,
197 merge=merge)
197 merge=merge)
198
198
199 @pytest.mark.xfail_backends('svn')
199 @pytest.mark.xfail_backends('svn')
200 @pytest.mark.parametrize('merge', [True, False])
200 @pytest.mark.parametrize('merge', [True, False])
201 def test_compare_unrelated_repositories(self, vcsbackend, merge):
201 def test_compare_unrelated_repositories(self, vcsbackend, merge):
202 orig = vcsbackend.create_repo(number_of_commits=5)
202 orig = vcsbackend.create_repo(number_of_commits=5)
203 unrelated = vcsbackend.create_repo(number_of_commits=5)
203 unrelated = vcsbackend.create_repo(number_of_commits=5)
204 assert orig != unrelated
204 assert orig != unrelated
205
205
206 orig.compare(
206 orig.compare(
207 orig[1].raw_id, unrelated[3].raw_id, unrelated, merge=merge)
207 orig[1].raw_id, unrelated[3].raw_id, unrelated, merge=merge)
208
208
209
209
210 class TestRepositoryGetCommonAncestor:
210 class TestRepositoryGetCommonAncestor:
211
211
212 def test_get_common_ancestor_from_same_repo_existing(self, vcsbackend):
212 def test_get_common_ancestor_from_same_repo_existing(self, vcsbackend):
213 target_repo = vcsbackend.create_repo(number_of_commits=5)
213 target_repo = vcsbackend.create_repo(number_of_commits=5)
214
214
215 expected_ancestor = target_repo[2].raw_id
215 expected_ancestor = target_repo[2].raw_id
216
216
217 assert target_repo.get_common_ancestor(
217 assert target_repo.get_common_ancestor(
218 commit_id1=target_repo[2].raw_id,
218 commit_id1=target_repo[2].raw_id,
219 commit_id2=target_repo[4].raw_id,
219 commit_id2=target_repo[4].raw_id,
220 repo2=target_repo
220 repo2=target_repo
221 ) == expected_ancestor
221 ) == expected_ancestor
222
222
223 assert target_repo.get_common_ancestor(
223 assert target_repo.get_common_ancestor(
224 commit_id1=target_repo[4].raw_id,
224 commit_id1=target_repo[4].raw_id,
225 commit_id2=target_repo[2].raw_id,
225 commit_id2=target_repo[2].raw_id,
226 repo2=target_repo
226 repo2=target_repo
227 ) == expected_ancestor
227 ) == expected_ancestor
228
228
229 @pytest.mark.xfail_backends("svn")
229 @pytest.mark.xfail_backends("svn")
230 def test_get_common_ancestor_from_cloned_repo_existing(self, vcsbackend):
230 def test_get_common_ancestor_from_cloned_repo_existing(self, vcsbackend):
231 target_repo = vcsbackend.create_repo(number_of_commits=5)
231 target_repo = vcsbackend.create_repo(number_of_commits=5)
232 source_repo = vcsbackend.clone_repo(target_repo)
232 source_repo = vcsbackend.clone_repo(target_repo)
233 assert target_repo != source_repo
233 assert target_repo != source_repo
234
234
235 vcsbackend.add_file(source_repo, 'newfile', 'somecontent')
235 vcsbackend.add_file(source_repo, 'newfile', 'somecontent')
236 source_commit = source_repo.get_commit()
236 source_commit = source_repo.get_commit()
237
237
238 expected_ancestor = target_repo[4].raw_id
238 expected_ancestor = target_repo[4].raw_id
239
239
240 assert target_repo.get_common_ancestor(
240 assert target_repo.get_common_ancestor(
241 commit_id1=target_repo[4].raw_id,
241 commit_id1=target_repo[4].raw_id,
242 commit_id2=source_commit.raw_id,
242 commit_id2=source_commit.raw_id,
243 repo2=source_repo
243 repo2=source_repo
244 ) == expected_ancestor
244 ) == expected_ancestor
245
245
246 assert target_repo.get_common_ancestor(
246 assert target_repo.get_common_ancestor(
247 commit_id1=source_commit.raw_id,
247 commit_id1=source_commit.raw_id,
248 commit_id2=target_repo[4].raw_id,
248 commit_id2=target_repo[4].raw_id,
249 repo2=target_repo
249 repo2=target_repo
250 ) == expected_ancestor
250 ) == expected_ancestor
251
251
252 @pytest.mark.xfail_backends("svn")
252 @pytest.mark.xfail_backends("svn")
253 def test_get_common_ancestor_from_unrelated_repo_missing(self, vcsbackend):
253 def test_get_common_ancestor_from_unrelated_repo_missing(self, vcsbackend):
254 original = vcsbackend.create_repo(number_of_commits=5)
254 original = vcsbackend.create_repo(number_of_commits=5)
255 unrelated = vcsbackend.create_repo(number_of_commits=5)
255 unrelated = vcsbackend.create_repo(number_of_commits=5)
256 assert original != unrelated
256 assert original != unrelated
257
257
258 assert original.get_common_ancestor(
258 assert original.get_common_ancestor(
259 commit_id1=original[0].raw_id,
259 commit_id1=original[0].raw_id,
260 commit_id2=unrelated[0].raw_id,
260 commit_id2=unrelated[0].raw_id,
261 repo2=unrelated
261 repo2=unrelated
262 ) is None
262 ) is None
263
263
264 assert original.get_common_ancestor(
264 assert original.get_common_ancestor(
265 commit_id1=original[-1].raw_id,
265 commit_id1=original[-1].raw_id,
266 commit_id2=unrelated[-1].raw_id,
266 commit_id2=unrelated[-1].raw_id,
267 repo2=unrelated
267 repo2=unrelated
268 ) is None
268 ) is None
269
269
270
270
271 @pytest.mark.backends("git", "hg")
271 @pytest.mark.backends("git", "hg")
272 class TestRepositoryMerge(object):
272 class TestRepositoryMerge(object):
273 def prepare_for_success(self, vcsbackend):
273 def prepare_for_success(self, vcsbackend):
274 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
274 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
275 self.source_repo = vcsbackend.clone_repo(self.target_repo)
275 self.source_repo = vcsbackend.clone_repo(self.target_repo)
276 vcsbackend.add_file(self.target_repo, 'README_MERGE1', 'Version 1')
276 vcsbackend.add_file(self.target_repo, 'README_MERGE1', 'Version 1')
277 vcsbackend.add_file(self.source_repo, 'README_MERGE2', 'Version 2')
277 vcsbackend.add_file(self.source_repo, 'README_MERGE2', 'Version 2')
278 imc = self.source_repo.in_memory_commit
278 imc = self.source_repo.in_memory_commit
279 imc.add(FileNode('file_x', content=self.source_repo.name))
279 imc.add(FileNode('file_x', content=self.source_repo.name))
280 imc.commit(
280 imc.commit(
281 message=u'Automatic commit from repo merge test',
281 message=u'Automatic commit from repo merge test',
282 author=u'Automatic <automatic@rhodecode.com>')
282 author=u'Automatic <automatic@rhodecode.com>')
283 self.target_commit = self.target_repo.get_commit()
283 self.target_commit = self.target_repo.get_commit()
284 self.source_commit = self.source_repo.get_commit()
284 self.source_commit = self.source_repo.get_commit()
285 # This only works for Git and Mercurial
285 # This only works for Git and Mercurial
286 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
286 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
287 self.target_ref = Reference('branch', default_branch, self.target_commit.raw_id)
287 self.target_ref = Reference('branch', default_branch, self.target_commit.raw_id)
288 self.source_ref = Reference('branch', default_branch, self.source_commit.raw_id)
288 self.source_ref = Reference('branch', default_branch, self.source_commit.raw_id)
289 self.workspace_id = 'test-merge-{}'.format(vcsbackend.alias)
289 self.workspace_id = 'test-merge-{}'.format(vcsbackend.alias)
290 self.repo_id = repo_id_generator(self.target_repo.path)
290 self.repo_id = repo_id_generator(self.target_repo.path)
291
291
292 def prepare_for_conflict(self, vcsbackend):
292 def prepare_for_conflict(self, vcsbackend):
293 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
293 self.target_repo = vcsbackend.create_repo(number_of_commits=1)
294 self.source_repo = vcsbackend.clone_repo(self.target_repo)
294 self.source_repo = vcsbackend.clone_repo(self.target_repo)
295 vcsbackend.add_file(self.target_repo, 'README_MERGE', 'Version 1')
295 vcsbackend.add_file(self.target_repo, 'README_MERGE', 'Version 1')
296 vcsbackend.add_file(self.source_repo, 'README_MERGE', 'Version 2')
296 vcsbackend.add_file(self.source_repo, 'README_MERGE', 'Version 2')
297 self.target_commit = self.target_repo.get_commit()
297 self.target_commit = self.target_repo.get_commit()
298 self.source_commit = self.source_repo.get_commit()
298 self.source_commit = self.source_repo.get_commit()
299 # This only works for Git and Mercurial
299 # This only works for Git and Mercurial
300 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
300 default_branch = self.target_repo.DEFAULT_BRANCH_NAME
301 self.target_ref = Reference('branch', default_branch, self.target_commit.raw_id)
301 self.target_ref = Reference('branch', default_branch, self.target_commit.raw_id)
302 self.source_ref = Reference('branch', default_branch, self.source_commit.raw_id)
302 self.source_ref = Reference('branch', default_branch, self.source_commit.raw_id)
303 self.workspace_id = 'test-merge-{}'.format(vcsbackend.alias)
303 self.workspace_id = 'test-merge-{}'.format(vcsbackend.alias)
304 self.repo_id = repo_id_generator(self.target_repo.path)
304 self.repo_id = repo_id_generator(self.target_repo.path)
305
305
306 def test_merge_success(self, vcsbackend):
306 def test_merge_success(self, vcsbackend):
307 self.prepare_for_success(vcsbackend)
307 self.prepare_for_success(vcsbackend)
308
308
309 merge_response = self.target_repo.merge(
309 merge_response = self.target_repo.merge(
310 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
310 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
311 self.source_ref,
311 self.source_ref,
312 'test user', 'test@rhodecode.com', 'merge message 1',
312 'test user', 'test@rhodecode.com', 'merge message 1',
313 dry_run=False)
313 dry_run=False)
314 expected_merge_response = MergeResponse(
314 expected_merge_response = MergeResponse(
315 True, True, merge_response.merge_ref,
315 True, True, merge_response.merge_ref,
316 MergeFailureReason.NONE)
316 MergeFailureReason.NONE)
317 assert merge_response == expected_merge_response
317 assert merge_response == expected_merge_response
318
318
319 target_repo = backends.get_backend(vcsbackend.alias)(
319 target_repo = backends.get_backend(vcsbackend.alias)(
320 self.target_repo.path)
320 self.target_repo.path)
321 target_commits = list(target_repo.get_commits())
321 target_commits = list(target_repo.get_commits())
322 commit_ids = [c.raw_id for c in target_commits[:-1]]
322 commit_ids = [c.raw_id for c in target_commits[:-1]]
323 assert self.source_ref.commit_id in commit_ids
323 assert self.source_ref.commit_id in commit_ids
324 assert self.target_ref.commit_id in commit_ids
324 assert self.target_ref.commit_id in commit_ids
325
325
326 merge_commit = target_commits[-1]
326 merge_commit = target_commits[-1]
327 assert merge_commit.raw_id == merge_response.merge_ref.commit_id
327 assert merge_commit.raw_id == merge_response.merge_ref.commit_id
328 assert merge_commit.message.strip() == 'merge message 1'
328 assert merge_commit.message.strip() == 'merge message 1'
329 assert merge_commit.author == 'test user <test@rhodecode.com>'
329 assert merge_commit.author == 'test user <test@rhodecode.com>'
330
330
331 # We call it twice so to make sure we can handle updates
331 # We call it twice so to make sure we can handle updates
332 target_ref = Reference(
332 target_ref = Reference(
333 self.target_ref.type, self.target_ref.name,
333 self.target_ref.type, self.target_ref.name,
334 merge_response.merge_ref.commit_id)
334 merge_response.merge_ref.commit_id)
335
335
336 merge_response = target_repo.merge(
336 merge_response = target_repo.merge(
337 self.repo_id, self.workspace_id, target_ref, self.source_repo, self.source_ref,
337 self.repo_id, self.workspace_id, target_ref, self.source_repo, self.source_ref,
338 'test user', 'test@rhodecode.com', 'merge message 2',
338 'test user', 'test@rhodecode.com', 'merge message 2',
339 dry_run=False)
339 dry_run=False)
340 expected_merge_response = MergeResponse(
340 expected_merge_response = MergeResponse(
341 True, True, merge_response.merge_ref,
341 True, True, merge_response.merge_ref,
342 MergeFailureReason.NONE)
342 MergeFailureReason.NONE)
343 assert merge_response == expected_merge_response
343 assert merge_response == expected_merge_response
344
344
345 target_repo = backends.get_backend(
345 target_repo = backends.get_backend(
346 vcsbackend.alias)(self.target_repo.path)
346 vcsbackend.alias)(self.target_repo.path)
347 merge_commit = target_repo.get_commit(
347 merge_commit = target_repo.get_commit(
348 merge_response.merge_ref.commit_id)
348 merge_response.merge_ref.commit_id)
349 assert merge_commit.message.strip() == 'merge message 1'
349 assert merge_commit.message.strip() == 'merge message 1'
350 assert merge_commit.author == 'test user <test@rhodecode.com>'
350 assert merge_commit.author == 'test user <test@rhodecode.com>'
351
351
352 def test_merge_success_dry_run(self, vcsbackend):
352 def test_merge_success_dry_run(self, vcsbackend):
353 self.prepare_for_success(vcsbackend)
353 self.prepare_for_success(vcsbackend)
354
354
355 merge_response = self.target_repo.merge(
355 merge_response = self.target_repo.merge(
356 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
356 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
357 self.source_ref, dry_run=True)
357 self.source_ref, dry_run=True)
358
358
359 # We call it twice so to make sure we can handle updates
359 # We call it twice so to make sure we can handle updates
360 merge_response_update = self.target_repo.merge(
360 merge_response_update = self.target_repo.merge(
361 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
361 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
362 self.source_ref, dry_run=True)
362 self.source_ref, dry_run=True)
363
363
364 # Multiple merges may differ in their commit id. Therefore we set the
364 # Multiple merges may differ in their commit id. Therefore we set the
365 # commit id to `None` before comparing the merge responses.
365 # commit id to `None` before comparing the merge responses.
366 new_merge_ref = merge_response.merge_ref._replace(commit_id=None)
366 new_merge_ref = merge_response.merge_ref._replace(commit_id=None)
367 merge_response.merge_ref = new_merge_ref
367 merge_response.merge_ref = new_merge_ref
368
368
369 new_update_merge_ref = merge_response_update.merge_ref._replace(commit_id=None)
369 new_update_merge_ref = merge_response_update.merge_ref._replace(commit_id=None)
370 merge_response_update.merge_ref = new_update_merge_ref
370 merge_response_update.merge_ref = new_update_merge_ref
371
371
372 assert merge_response == merge_response_update
372 assert merge_response == merge_response_update
373 assert merge_response.possible is True
373 assert merge_response.possible is True
374 assert merge_response.executed is False
374 assert merge_response.executed is False
375 assert merge_response.merge_ref
375 assert merge_response.merge_ref
376 assert merge_response.failure_reason is MergeFailureReason.NONE
376 assert merge_response.failure_reason is MergeFailureReason.NONE
377
377
378 @pytest.mark.parametrize('dry_run', [True, False])
378 @pytest.mark.parametrize('dry_run', [True, False])
379 def test_merge_conflict(self, vcsbackend, dry_run):
379 def test_merge_conflict(self, vcsbackend, dry_run):
380 self.prepare_for_conflict(vcsbackend)
380 self.prepare_for_conflict(vcsbackend)
381
381
382 expected_merge_response = MergeResponse(
382 expected_merge_response = MergeResponse(
383 False, False, None, MergeFailureReason.MERGE_FAILED)
383 False, False, None, MergeFailureReason.MERGE_FAILED)
384
384
385 merge_response = self.target_repo.merge(
385 merge_response = self.target_repo.merge(
386 self.repo_id, self.workspace_id, self.target_ref,
386 self.repo_id, self.workspace_id, self.target_ref,
387 self.source_repo, self.source_ref,
387 self.source_repo, self.source_ref,
388 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run)
388 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run)
389 assert merge_response == expected_merge_response
389 assert merge_response == expected_merge_response
390
390
391 # We call it twice so to make sure we can handle updates
391 # We call it twice so to make sure we can handle updates
392 merge_response = self.target_repo.merge(
392 merge_response = self.target_repo.merge(
393 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
393 self.repo_id, self.workspace_id, self.target_ref, self.source_repo,
394 self.source_ref,
394 self.source_ref,
395 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run)
395 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run)
396 assert merge_response == expected_merge_response
396 assert merge_response == expected_merge_response
397
397
398 def test_merge_target_is_not_head(self, vcsbackend):
398 def test_merge_target_is_not_head(self, vcsbackend):
399 self.prepare_for_success(vcsbackend)
399 self.prepare_for_success(vcsbackend)
400 target_ref = Reference(
400 target_ref = Reference(
401 self.target_ref.type, self.target_ref.name, '0' * 40)
401 self.target_ref.type, self.target_ref.name, '0' * 40)
402 expected_merge_response = MergeResponse(
402 expected_merge_response = MergeResponse(
403 False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD,
403 False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD,
404 metadata={'target_ref': target_ref})
404 metadata={'target_ref': target_ref})
405 merge_response = self.target_repo.merge(
405 merge_response = self.target_repo.merge(
406 self.repo_id, self.workspace_id, target_ref, self.source_repo,
406 self.repo_id, self.workspace_id, target_ref, self.source_repo,
407 self.source_ref, dry_run=True)
407 self.source_ref, dry_run=True)
408
408
409 assert merge_response == expected_merge_response
409 assert merge_response == expected_merge_response
410
410
411 def test_merge_missing_source_reference(self, vcsbackend):
411 def test_merge_missing_source_reference(self, vcsbackend):
412 self.prepare_for_success(vcsbackend)
412 self.prepare_for_success(vcsbackend)
413
413
414 source_ref = Reference(
414 source_ref = Reference(
415 self.source_ref.type, 'not_existing', self.source_ref.commit_id)
415 self.source_ref.type, 'not_existing', self.source_ref.commit_id)
416 expected_merge_response = MergeResponse(
416 expected_merge_response = MergeResponse(
417 False, False, None, MergeFailureReason.MISSING_SOURCE_REF,
417 False, False, None, MergeFailureReason.MISSING_SOURCE_REF,
418 metadata={'source_ref': source_ref})
418 metadata={'source_ref': source_ref})
419
419
420 merge_response = self.target_repo.merge(
420 merge_response = self.target_repo.merge(
421 self.repo_id, self.workspace_id, self.target_ref,
421 self.repo_id, self.workspace_id, self.target_ref,
422 self.source_repo, source_ref,
422 self.source_repo, source_ref,
423 dry_run=True)
423 dry_run=True)
424
424
425 assert merge_response == expected_merge_response
425 assert merge_response == expected_merge_response
426
426
427 def test_merge_raises_exception(self, vcsbackend):
427 def test_merge_raises_exception(self, vcsbackend):
428 self.prepare_for_success(vcsbackend)
428 self.prepare_for_success(vcsbackend)
429 expected_merge_response = MergeResponse(
429 expected_merge_response = MergeResponse(
430 False, False, None, MergeFailureReason.UNKNOWN,
430 False, False, None, MergeFailureReason.UNKNOWN,
431 metadata={'exception': 'ErrorForTest'})
431 metadata={'exception': 'ErrorForTest'})
432
432
433 with mock.patch.object(self.target_repo, '_merge_repo',
433 with mock.patch.object(self.target_repo, '_merge_repo',
434 side_effect=RepositoryError()):
434 side_effect=RepositoryError()):
435 merge_response = self.target_repo.merge(
435 merge_response = self.target_repo.merge(
436 self.repo_id, self.workspace_id, self.target_ref,
436 self.repo_id, self.workspace_id, self.target_ref,
437 self.source_repo, self.source_ref,
437 self.source_repo, self.source_ref,
438 dry_run=True)
438 dry_run=True)
439
439
440 assert merge_response == expected_merge_response
440 assert merge_response == expected_merge_response
441
441
442 def test_merge_invalid_user_name(self, vcsbackend):
442 def test_merge_invalid_user_name(self, vcsbackend):
443 repo = vcsbackend.create_repo(number_of_commits=1)
443 repo = vcsbackend.create_repo(number_of_commits=1)
444 ref = Reference('branch', 'master', 'not_used')
444 ref = Reference('branch', 'master', 'not_used')
445 workspace_id = 'test-errors-in-merge'
445 workspace_id = 'test-errors-in-merge'
446 repo_id = repo_id_generator(workspace_id)
446 repo_id = repo_id_generator(workspace_id)
447 with pytest.raises(ValueError):
447 with pytest.raises(ValueError):
448 repo.merge(repo_id, workspace_id, ref, self, ref)
448 repo.merge(repo_id, workspace_id, ref, self, ref)
449
449
450 def test_merge_invalid_user_email(self, vcsbackend):
450 def test_merge_invalid_user_email(self, vcsbackend):
451 repo = vcsbackend.create_repo(number_of_commits=1)
451 repo = vcsbackend.create_repo(number_of_commits=1)
452 ref = Reference('branch', 'master', 'not_used')
452 ref = Reference('branch', 'master', 'not_used')
453 workspace_id = 'test-errors-in-merge'
453 workspace_id = 'test-errors-in-merge'
454 repo_id = repo_id_generator(workspace_id)
454 repo_id = repo_id_generator(workspace_id)
455 with pytest.raises(ValueError):
455 with pytest.raises(ValueError):
456 repo.merge(
456 repo.merge(
457 repo_id, workspace_id, ref, self, ref, 'user name')
457 repo_id, workspace_id, ref, self, ref, 'user name')
458
458
459 def test_merge_invalid_message(self, vcsbackend):
459 def test_merge_invalid_message(self, vcsbackend):
460 repo = vcsbackend.create_repo(number_of_commits=1)
460 repo = vcsbackend.create_repo(number_of_commits=1)
461 ref = Reference('branch', 'master', 'not_used')
461 ref = Reference('branch', 'master', 'not_used')
462 workspace_id = 'test-errors-in-merge'
462 workspace_id = 'test-errors-in-merge'
463 repo_id = repo_id_generator(workspace_id)
463 repo_id = repo_id_generator(workspace_id)
464 with pytest.raises(ValueError):
464 with pytest.raises(ValueError):
465 repo.merge(
465 repo.merge(
466 repo_id, workspace_id, ref, self, ref,
466 repo_id, workspace_id, ref, self, ref,
467 'user name', 'user@email.com')
467 'user name', 'user@email.com')
468
468
469
469
470 @pytest.mark.usefixtures("vcs_repository_support")
470 @pytest.mark.usefixtures("vcs_repository_support")
471 class TestRepositoryStrip(BackendTestMixin):
471 class TestRepositoryStrip(BackendTestMixin):
472 recreate_repo_per_test = True
472 recreate_repo_per_test = True
473
473
474 @classmethod
474 @classmethod
475 def _get_commits(cls):
475 def _get_commits(cls):
476 commits = [
476 commits = [
477 {
477 {
478 'message': 'Initial commit',
478 'message': 'Initial commit',
479 'author': 'Joe Doe <joe.doe@example.com>',
479 'author': 'Joe Doe <joe.doe@example.com>',
480 'date': datetime.datetime(2010, 1, 1, 20),
480 'date': datetime.datetime(2010, 1, 1, 20),
481 'branch': 'master',
481 'branch': 'master',
482 'added': [
482 'added': [
483 FileNode('foobar', content='foobar'),
483 FileNode('foobar', content='foobar'),
484 FileNode('foobar2', content='foobar2'),
484 FileNode('foobar2', content='foobar2'),
485 ],
485 ],
486 },
486 },
487 ]
487 ]
488 for x in range(10):
488 for x in range(10):
489 commit_data = {
489 commit_data = {
490 'message': 'Changed foobar - commit%s' % x,
490 'message': 'Changed foobar - commit%s' % x,
491 'author': 'Jane Doe <jane.doe@example.com>',
491 'author': 'Jane Doe <jane.doe@example.com>',
492 'date': datetime.datetime(2010, 1, 1, 21, x),
492 'date': datetime.datetime(2010, 1, 1, 21, x),
493 'branch': 'master',
493 'branch': 'master',
494 'changed': [
494 'changed': [
495 FileNode('foobar', 'FOOBAR - %s' % x),
495 FileNode('foobar', 'FOOBAR - %s' % x),
496 ],
496 ],
497 }
497 }
498 commits.append(commit_data)
498 commits.append(commit_data)
499 return commits
499 return commits
500
500
501 @pytest.mark.backends("git", "hg")
501 @pytest.mark.backends("git", "hg")
502 def test_strip_commit(self):
502 def test_strip_commit(self):
503 tip = self.repo.get_commit()
503 tip = self.repo.get_commit()
504 assert tip.idx == 10
504 assert tip.idx == 10
505 self.repo.strip(tip.raw_id, self.repo.DEFAULT_BRANCH_NAME)
505 self.repo.strip(tip.raw_id, self.repo.DEFAULT_BRANCH_NAME)
506
506
507 tip = self.repo.get_commit()
507 tip = self.repo.get_commit()
508 assert tip.idx == 9
508 assert tip.idx == 9
509
509
510 @pytest.mark.backends("git", "hg")
510 @pytest.mark.backends("git", "hg")
511 def test_strip_multiple_commits(self):
511 def test_strip_multiple_commits(self):
512 tip = self.repo.get_commit()
512 tip = self.repo.get_commit()
513 assert tip.idx == 10
513 assert tip.idx == 10
514
514
515 old = self.repo.get_commit(commit_idx=5)
515 old = self.repo.get_commit(commit_idx=5)
516 self.repo.strip(old.raw_id, self.repo.DEFAULT_BRANCH_NAME)
516 self.repo.strip(old.raw_id, self.repo.DEFAULT_BRANCH_NAME)
517
517
518 tip = self.repo.get_commit()
518 tip = self.repo.get_commit()
519 assert tip.idx == 4
519 assert tip.idx == 4
520
520
521
521
522 @pytest.mark.backends('hg', 'git')
522 @pytest.mark.backends('hg', 'git')
523 class TestRepositoryPull(object):
523 class TestRepositoryPull(object):
524
524
525 def test_pull(self, vcsbackend):
525 def test_pull(self, vcsbackend):
526 source_repo = vcsbackend.repo
526 source_repo = vcsbackend.repo
527 target_repo = vcsbackend.create_repo()
527 target_repo = vcsbackend.create_repo()
528 assert len(source_repo.commit_ids) > len(target_repo.commit_ids)
528 assert len(source_repo.commit_ids) > len(target_repo.commit_ids)
529
529
530 target_repo.pull(source_repo.path)
530 target_repo.pull(source_repo.path)
531 # Note: Get a fresh instance, avoids caching trouble
531 # Note: Get a fresh instance, avoids caching trouble
532 target_repo = vcsbackend.backend(target_repo.path)
532 target_repo = vcsbackend.backend(target_repo.path)
533 assert len(source_repo.commit_ids) == len(target_repo.commit_ids)
533 assert len(source_repo.commit_ids) == len(target_repo.commit_ids)
534
534
535 def test_pull_wrong_path(self, vcsbackend):
535 def test_pull_wrong_path(self, vcsbackend):
536 target_repo = vcsbackend.create_repo()
536 target_repo = vcsbackend.create_repo()
537 with pytest.raises(RepositoryError):
537 with pytest.raises(RepositoryError):
538 target_repo.pull(target_repo.path + "wrong")
538 target_repo.pull(target_repo.path + "wrong")
539
539
540 def test_pull_specific_commits(self, vcsbackend):
540 def test_pull_specific_commits(self, vcsbackend):
541 source_repo = vcsbackend.repo
541 source_repo = vcsbackend.repo
542 target_repo = vcsbackend.create_repo()
542 target_repo = vcsbackend.create_repo()
543
543
544 second_commit = source_repo[1].raw_id
544 second_commit = source_repo[1].raw_id
545 if vcsbackend.alias == 'git':
545 if vcsbackend.alias == 'git':
546 second_commit_ref = 'refs/test-refs/a'
546 second_commit_ref = 'refs/test-refs/a'
547 source_repo.set_refs(second_commit_ref, second_commit)
547 source_repo.set_refs(second_commit_ref, second_commit)
548
548
549 target_repo.pull(source_repo.path, commit_ids=[second_commit])
549 target_repo.pull(source_repo.path, commit_ids=[second_commit])
550 target_repo = vcsbackend.backend(target_repo.path)
550 target_repo = vcsbackend.backend(target_repo.path)
551 assert 2 == len(target_repo.commit_ids)
551 assert 2 == len(target_repo.commit_ids)
552 assert second_commit == target_repo.get_commit().raw_id
552 assert second_commit == target_repo.get_commit().raw_id
@@ -1,186 +1,186 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 from rhodecode.tests import SVN_REPO, TEST_DIR, TESTS_TMP_PATH
26 from rhodecode.tests import SVN_REPO, TEST_DIR, TESTS_TMP_PATH
27 from rhodecode.lib.vcs.backends.svn.repository import SubversionRepository
27 from rhodecode.lib.vcs.backends.svn.repository import SubversionRepository
28 from rhodecode.lib.vcs.conf import settings
28 from rhodecode.lib.vcs.conf import settings
29 from rhodecode.lib.vcs.exceptions import VCSError
29 from rhodecode.lib.vcs.exceptions import VCSError
30
30
31
31
32 pytestmark = [
32 pytestmark = [
33 pytest.mark.backends("svn"),
33 pytest.mark.backends("svn"),
34 pytest.mark.usefixtures("baseapp"),
34 pytest.mark.usefixtures("baseapp"),
35 ]
35 ]
36
36
37
37
38 @pytest.fixture()
38 @pytest.fixture()
39 def repo(baseapp):
39 def repo(baseapp):
40 repo = SubversionRepository(os.path.join(TESTS_TMP_PATH, SVN_REPO))
40 repo = SubversionRepository(os.path.join(TESTS_TMP_PATH, SVN_REPO))
41 return repo
41 return repo
42
42
43
43
44 @pytest.fixture()
44 @pytest.fixture()
45 def head(repo):
45 def head(repo):
46 return repo.get_commit()
46 return repo.get_commit()
47
47
48
48
49 def test_init_fails_if_path_does_not_exist():
49 def test_init_fails_if_path_does_not_exist():
50 path = os.path.join(TEST_DIR, 'i-do-not-exist')
50 path = os.path.join(TEST_DIR, 'i-do-not-exist')
51 with pytest.raises(VCSError):
51 with pytest.raises(VCSError):
52 SubversionRepository(path)
52 SubversionRepository(path)
53
53
54
54
55 def test_init_fails_if_path_is_not_a_valid_repository(tmpdir):
55 def test_init_fails_if_path_is_not_a_valid_repository(tmpdir):
56 path = unicode(tmpdir.mkdir(u'unicode Γ€'))
56 path = str(tmpdir.mkdir('unicode Γ€'))
57 with pytest.raises(VCSError):
57 with pytest.raises(VCSError):
58 SubversionRepository(path)
58 SubversionRepository(path)
59
59
60
60
61 def test_repo_clone(vcsbackend, reposerver):
61 def test_repo_clone(vcsbackend, reposerver):
62 source = vcsbackend.create_repo(number_of_commits=3)
62 source = vcsbackend.create_repo(number_of_commits=3)
63 reposerver.serve(source)
63 reposerver.serve(source)
64 repo = SubversionRepository(
64 repo = SubversionRepository(
65 vcsbackend.new_repo_path(),
65 vcsbackend.new_repo_path(),
66 create=True,
66 create=True,
67 src_url=reposerver.url)
67 src_url=reposerver.url)
68
68
69 assert source.commit_ids == repo.commit_ids
69 assert source.commit_ids == repo.commit_ids
70 assert source[0].message == repo[0].message
70 assert source[0].message == repo[0].message
71
71
72
72
73 def test_latest_commit(head):
73 def test_latest_commit(head):
74 assert head.raw_id == '393'
74 assert head.raw_id == '393'
75
75
76
76
77 def test_commit_description(head):
77 def test_commit_description(head):
78 assert head.message == """Added a symlink"""
78 assert head.message == """Added a symlink"""
79
79
80
80
81 def test_commit_author(head):
81 def test_commit_author(head):
82 assert head.author == 'marcin'
82 assert head.author == 'marcin'
83
83
84
84
85 @pytest.mark.parametrize("filename, content, mime_type", [
85 @pytest.mark.parametrize("filename, content, mime_type", [
86 ('test.txt', 'Text content\n', None),
86 ('test.txt', 'Text content\n', None),
87 ('test.bin', '\0 binary \0', 'application/octet-stream'),
87 ('test.bin', '\0 binary \0', 'application/octet-stream'),
88 ], ids=['text', 'binary'])
88 ], ids=['text', 'binary'])
89 def test_sets_mime_type_correctly(vcsbackend, filename, content, mime_type):
89 def test_sets_mime_type_correctly(vcsbackend, filename, content, mime_type):
90 repo = vcsbackend.create_repo()
90 repo = vcsbackend.create_repo()
91 vcsbackend.ensure_file(filename, content)
91 vcsbackend.ensure_file(filename, content)
92 file_properties = repo._remote.node_properties(filename, 1)
92 file_properties = repo._remote.node_properties(filename, 1)
93 assert file_properties.get('svn:mime-type') == mime_type
93 assert file_properties.get('svn:mime-type') == mime_type
94
94
95
95
96 def test_slice_access(repo):
96 def test_slice_access(repo):
97 page_size = 5
97 page_size = 5
98 page = 0
98 page = 0
99 start = page * page_size
99 start = page * page_size
100 end = start + page_size - 1
100 end = start + page_size - 1
101
101
102 commits = list(repo[start:end])
102 commits = list(repo[start:end])
103 assert [commit.raw_id for commit in commits] == ['1', '2', '3', '4']
103 assert [commit.raw_id for commit in commits] == ['1', '2', '3', '4']
104
104
105
105
106 def test_walk_changelog_page(repo):
106 def test_walk_changelog_page(repo):
107 page_size = 5
107 page_size = 5
108 page = 0
108 page = 0
109 start = page * page_size
109 start = page * page_size
110 end = start + page_size - 1
110 end = start + page_size - 1
111
111
112 commits = list(repo[start:end])
112 commits = list(repo[start:end])
113 changelog = [
113 changelog = [
114 'r%s, %s, %s' % (c.raw_id, c.author, c.message) for c in commits]
114 'r%s, %s, %s' % (c.raw_id, c.author, c.message) for c in commits]
115
115
116 expexted_messages = [
116 expexted_messages = [
117 'r1, marcin, initial import',
117 'r1, marcin, initial import',
118 'r2, marcin, hg ignore',
118 'r2, marcin, hg ignore',
119 'r3, marcin, Pip standards refactor',
119 'r3, marcin, Pip standards refactor',
120 'r4, marcin, Base repository few new functions added']
120 'r4, marcin, Base repository few new functions added']
121 assert changelog == expexted_messages
121 assert changelog == expexted_messages
122
122
123
123
124 def test_read_full_file_tree(head):
124 def test_read_full_file_tree(head):
125 for topnode, dirs, files in head.walk():
125 for topnode, dirs, files in head.walk():
126 for f in files:
126 for f in files:
127 len(f.content)
127 len(f.content)
128
128
129
129
130 def test_topnode_files_attribute(head):
130 def test_topnode_files_attribute(head):
131 topnode = head.get_node('')
131 topnode = head.get_node('')
132 topnode.files
132 topnode.files
133
133
134
134
135 @pytest.mark.parametrize("filename, content, branch, mime_type", [
135 @pytest.mark.parametrize("filename, content, branch, mime_type", [
136 (u'branches/plain/test.txt', 'Text content\n', 'plain', None),
136 (u'branches/plain/test.txt', 'Text content\n', 'plain', None),
137 (u'branches/uniΓ§ΓΆβˆ‚e/test.bin', '\0 binary \0', u'uniΓ§ΓΆβˆ‚e',
137 (u'branches/uniΓ§ΓΆβˆ‚e/test.bin', '\0 binary \0', u'uniΓ§ΓΆβˆ‚e',
138 'application/octet-stream'),
138 'application/octet-stream'),
139 ], ids=['text', 'binary'])
139 ], ids=['text', 'binary'])
140 def test_unicode_refs(vcsbackend, filename, content, branch, mime_type):
140 def test_unicode_refs(vcsbackend, filename, content, branch, mime_type):
141 repo = vcsbackend.create_repo()
141 repo = vcsbackend.create_repo()
142 vcsbackend.ensure_file(filename, content)
142 vcsbackend.ensure_file(filename, content)
143 with mock.patch(("rhodecode.lib.vcs.backends.svn.repository"
143 with mock.patch(("rhodecode.lib.vcs.backends.svn.repository"
144 ".SubversionRepository._patterns_from_section"),
144 ".SubversionRepository._patterns_from_section"),
145 return_value=['branches/*']):
145 return_value=['branches/*']):
146 assert u'branches/{0}'.format(branch) in repo.branches
146 assert u'branches/{0}'.format(branch) in repo.branches
147
147
148
148
149 def test_compatible_version(monkeypatch, vcsbackend):
149 def test_compatible_version(monkeypatch, vcsbackend):
150 monkeypatch.setattr(settings, 'SVN_COMPATIBLE_VERSION', 'pre-1.8-compatible')
150 monkeypatch.setattr(settings, 'SVN_COMPATIBLE_VERSION', 'pre-1.8-compatible')
151 path = vcsbackend.new_repo_path()
151 path = vcsbackend.new_repo_path()
152 SubversionRepository(path, create=True)
152 SubversionRepository(path, create=True)
153 with open('{}/db/format'.format(path)) as f:
153 with open('{}/db/format'.format(path)) as f:
154 first_line = f.readline().strip()
154 first_line = f.readline().strip()
155 assert first_line == '4'
155 assert first_line == '4'
156
156
157
157
158 def test_invalid_compatible_version(monkeypatch, vcsbackend):
158 def test_invalid_compatible_version(monkeypatch, vcsbackend):
159 monkeypatch.setattr(settings, 'SVN_COMPATIBLE_VERSION', 'i-am-an-invalid-setting')
159 monkeypatch.setattr(settings, 'SVN_COMPATIBLE_VERSION', 'i-am-an-invalid-setting')
160 path = vcsbackend.new_repo_path()
160 path = vcsbackend.new_repo_path()
161 with pytest.raises(Exception):
161 with pytest.raises(Exception):
162 SubversionRepository(path, create=True)
162 SubversionRepository(path, create=True)
163
163
164
164
165 class TestSVNCommit(object):
165 class TestSVNCommit(object):
166
166
167 @pytest.fixture(autouse=True)
167 @pytest.fixture(autouse=True)
168 def prepare(self, repo):
168 def prepare(self, repo):
169 self.repo = repo
169 self.repo = repo
170
170
171 def test_file_history_from_commits(self):
171 def test_file_history_from_commits(self):
172 node = self.repo[10].get_node('setup.py')
172 node = self.repo[10].get_node('setup.py')
173 commit_ids = [commit.raw_id for commit in node.history]
173 commit_ids = [commit.raw_id for commit in node.history]
174 assert ['8'] == commit_ids
174 assert ['8'] == commit_ids
175
175
176 node = self.repo[20].get_node('setup.py')
176 node = self.repo[20].get_node('setup.py')
177 node_ids = [commit.raw_id for commit in node.history]
177 node_ids = [commit.raw_id for commit in node.history]
178 assert ['18',
178 assert ['18',
179 '8'] == node_ids
179 '8'] == node_ids
180
180
181 # special case we check history from commit that has this particular
181 # special case we check history from commit that has this particular
182 # file changed this means we check if it's included as well
182 # file changed this means we check if it's included as well
183 node = self.repo.get_commit('18').get_node('setup.py')
183 node = self.repo.get_commit('18').get_node('setup.py')
184 node_ids = [commit.raw_id for commit in node.history]
184 node_ids = [commit.raw_id for commit in node.history]
185 assert ['18',
185 assert ['18',
186 '8'] == node_ids
186 '8'] == node_ids
General Comments 0
You need to be logged in to leave comments. Login now