##// END OF EJS Templates
vcs: don't use deprecated get_changeset[s] methods.
dan -
r3112:f3f66eb3 default
parent child Browse files
Show More
@@ -1,81 +1,81 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import pytest
22 22
23 23 from rhodecode.model.db import ChangesetStatus
24 24 from rhodecode.api.tests.utils import (
25 25 build_data, api_call, assert_error, assert_ok)
26 26
27 27
28 28 @pytest.mark.usefixtures("testuser_api", "app")
29 29 class TestCommentCommit(object):
30 30 def test_api_comment_commit_on_empty_repo(self, backend):
31 31 repo = backend.create_repo()
32 32 id_, params = build_data(
33 33 self.apikey, 'comment_commit', repoid=repo.repo_name,
34 34 commit_id='tip', message='message', status_change=None)
35 35 response = api_call(self.app, params)
36 36 expected = 'There are no commits yet'
37 37 assert_error(id_, expected, given=response.body)
38 38
39 39 @pytest.mark.parametrize("commit_id, expected_err", [
40 40 ('abcabca', {'hg': 'Commit {commit} does not exist for {repo}',
41 41 'git': 'Commit {commit} does not exist for {repo}',
42 42 'svn': 'Commit id {commit} not understood.'}),
43 43 ('idontexist', {'hg': 'Commit {commit} does not exist for {repo}',
44 44 'git': 'Commit {commit} does not exist for {repo}',
45 45 'svn': 'Commit id {commit} not understood.'}),
46 46 ])
47 47 def test_api_comment_commit_wrong_hash(self, backend, commit_id, expected_err):
48 48 repo_name = backend.repo.repo_name
49 49 id_, params = build_data(
50 50 self.apikey, 'comment_commit', repoid=repo_name,
51 51 commit_id=commit_id, message='message', status_change=None)
52 52 response = api_call(self.app, params)
53 53
54 54 expected_err = expected_err[backend.alias]
55 55 expected_err = expected_err.format(
56 56 repo=backend.repo.scm_instance(), commit=commit_id)
57 57 assert_error(id_, expected_err, given=response.body)
58 58
59 59 @pytest.mark.parametrize("status_change, message, commit_id", [
60 60 (None, 'Hallo', 'tip'),
61 61 (ChangesetStatus.STATUS_APPROVED, 'Approved', 'tip'),
62 62 (ChangesetStatus.STATUS_REJECTED, 'Rejected', 'tip'),
63 63 ])
64 64 def test_api_comment_commit(
65 65 self, backend, status_change, message, commit_id,
66 66 no_notifications):
67 67
68 commit_id = backend.repo.scm_instance().get_changeset(commit_id).raw_id
68 commit_id = backend.repo.scm_instance().get_commit(commit_id).raw_id
69 69
70 70 id_, params = build_data(
71 71 self.apikey, 'comment_commit', repoid=backend.repo_name,
72 72 commit_id=commit_id, message=message, status=status_change)
73 73 response = api_call(self.app, params)
74 74 repo = backend.repo.scm_instance()
75 75 expected = {
76 76 'msg': 'Commented on commit `%s` for repository `%s`' % (
77 repo.get_changeset().raw_id, backend.repo_name),
77 repo.get_commit().raw_id, backend.repo_name),
78 78 'status_change': status_change,
79 79 'success': True
80 80 }
81 81 assert_ok(id_, expected, given=response.body)
@@ -1,113 +1,113 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2017-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 from pyramid.view import view_config
23 23
24 24 from rhodecode.apps._base import RepoAppView
25 25 from rhodecode.lib import audit_logger
26 26 from rhodecode.lib import helpers as h
27 27 from rhodecode.lib.auth import (
28 28 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
29 29 from rhodecode.lib.ext_json import json
30 30
31 31 log = logging.getLogger(__name__)
32 32
33 33
34 34 class StripView(RepoAppView):
35 35 def load_default_context(self):
36 36 c = self._get_local_tmpl_context()
37 37
38 38
39 39 return c
40 40
41 41 @LoginRequired()
42 42 @HasRepoPermissionAnyDecorator('repository.admin')
43 43 @view_config(
44 44 route_name='edit_repo_strip', request_method='GET',
45 45 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
46 46 def strip(self):
47 47 c = self.load_default_context()
48 48 c.active = 'strip'
49 49 c.strip_limit = 10
50 50
51 51 return self._get_template_context(c)
52 52
53 53 @LoginRequired()
54 54 @HasRepoPermissionAnyDecorator('repository.admin')
55 55 @CSRFRequired()
56 56 @view_config(
57 57 route_name='strip_check', request_method='POST',
58 58 renderer='json', xhr=True)
59 59 def strip_check(self):
60 60 from rhodecode.lib.vcs.backends.base import EmptyCommit
61 61 data = {}
62 62 rp = self.request.POST
63 63 for i in range(1, 11):
64 64 chset = 'changeset_id-%d' % (i,)
65 65 check = rp.get(chset)
66 66
67 67 if check:
68 data[i] = self.db_repo.get_changeset(rp[chset])
68 data[i] = self.db_repo.get_commit(rp[chset])
69 69 if isinstance(data[i], EmptyCommit):
70 70 data[i] = {'rev': None, 'commit': h.escape(rp[chset])}
71 71 else:
72 72 data[i] = {'rev': data[i].raw_id, 'branch': data[i].branch,
73 73 'author': h.escape(data[i].author),
74 74 'comment': h.escape(data[i].message)}
75 75 else:
76 76 break
77 77 return data
78 78
79 79 @LoginRequired()
80 80 @HasRepoPermissionAnyDecorator('repository.admin')
81 81 @CSRFRequired()
82 82 @view_config(
83 83 route_name='strip_execute', request_method='POST',
84 84 renderer='json', xhr=True)
85 85 def strip_execute(self):
86 86 from rhodecode.model.scm import ScmModel
87 87
88 88 c = self.load_default_context()
89 89 user = self._rhodecode_user
90 90 rp = self.request.POST
91 91 data = {}
92 92 for idx in rp:
93 93 commit = json.loads(rp[idx])
94 94 # If someone put two times the same branch
95 95 if commit['branch'] in data.keys():
96 96 continue
97 97 try:
98 98 ScmModel().strip(
99 99 repo=self.db_repo,
100 100 commit_id=commit['rev'], branch=commit['branch'])
101 101 log.info('Stripped commit %s from repo `%s` by %s',
102 102 commit['rev'], self.db_repo_name, user)
103 103 data[commit['rev']] = True
104 104
105 105 audit_logger.store_web(
106 106 'repo.commit.strip', action_data={'commit_id': commit['rev']},
107 107 repo=self.db_repo, user=self._rhodecode_user, commit=True)
108 108
109 109 except Exception as e:
110 110 data[commit['rev']] = False
111 111 log.debug('Stripped commit %s from repo `%s` failed by %s, exeption %s',
112 112 commit['rev'], self.db_repo_name, user, e.message)
113 113 return data
@@ -1,356 +1,356 b''
1 1 # Copyright (C) 2016-2018 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
16 16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18
19 19 import collections
20 20 import logging
21 21 import datetime
22 22
23 23 from rhodecode.translation import lazy_ugettext
24 24 from rhodecode.model.db import User, Repository, Session
25 25 from rhodecode.events.base import RhodeCodeIntegrationEvent
26 26 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
27 27
28 28 log = logging.getLogger(__name__)
29 29
30 30
31 31 def _commits_as_dict(event, commit_ids, repos):
32 32 """
33 33 Helper function to serialize commit_ids
34 34
35 35 :param event: class calling this method
36 36 :param commit_ids: commits to get
37 37 :param repos: list of repos to check
38 38 """
39 39 from rhodecode.lib.utils2 import extract_mentioned_users
40 40 from rhodecode.lib.helpers import (
41 41 urlify_commit_message, process_patterns, chop_at_smart)
42 42 from rhodecode.model.repo import RepoModel
43 43
44 44 if not repos:
45 45 raise Exception('no repo defined')
46 46
47 47 if not isinstance(repos, (tuple, list)):
48 48 repos = [repos]
49 49
50 50 if not commit_ids:
51 51 return []
52 52
53 53 needed_commits = list(commit_ids)
54 54
55 55 commits = []
56 56 reviewers = []
57 57 for repo in repos:
58 58 if not needed_commits:
59 59 return commits # return early if we have the commits we need
60 60
61 61 vcs_repo = repo.scm_instance(cache=False)
62 62
63 63 try:
64 64 # use copy of needed_commits since we modify it while iterating
65 65 for commit_id in list(needed_commits):
66 66 if commit_id.startswith('tag=>'):
67 67 raw_id = commit_id[5:]
68 68 cs_data = {
69 69 'raw_id': commit_id, 'short_id': commit_id,
70 70 'branch': None,
71 71 'git_ref_change': 'tag_add',
72 72 'message': 'Added new tag {}'.format(raw_id),
73 73 'author': event.actor.full_contact,
74 74 'date': datetime.datetime.now(),
75 75 'refs': {
76 76 'branches': [],
77 77 'bookmarks': [],
78 78 'tags': []
79 79 }
80 80 }
81 81 commits.append(cs_data)
82 82
83 83 elif commit_id.startswith('delete_branch=>'):
84 84 raw_id = commit_id[15:]
85 85 cs_data = {
86 86 'raw_id': commit_id, 'short_id': commit_id,
87 87 'branch': None,
88 88 'git_ref_change': 'branch_delete',
89 89 'message': 'Deleted branch {}'.format(raw_id),
90 90 'author': event.actor.full_contact,
91 91 'date': datetime.datetime.now(),
92 92 'refs': {
93 93 'branches': [],
94 94 'bookmarks': [],
95 95 'tags': []
96 96 }
97 97 }
98 98 commits.append(cs_data)
99 99
100 100 else:
101 101 try:
102 cs = vcs_repo.get_changeset(commit_id)
102 cs = vcs_repo.get_commit(commit_id)
103 103 except CommitDoesNotExistError:
104 104 continue # maybe its in next repo
105 105
106 106 cs_data = cs.__json__()
107 107 cs_data['refs'] = cs._get_refs()
108 108
109 109 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
110 110 cs_data['reviewers'] = reviewers
111 111 cs_data['url'] = RepoModel().get_commit_url(
112 112 repo, cs_data['raw_id'], request=event.request)
113 113 cs_data['permalink_url'] = RepoModel().get_commit_url(
114 114 repo, cs_data['raw_id'], request=event.request,
115 115 permalink=True)
116 116 urlified_message, issues_data = process_patterns(
117 117 cs_data['message'], repo.repo_name)
118 118 cs_data['issues'] = issues_data
119 119 cs_data['message_html'] = urlify_commit_message(
120 120 cs_data['message'], repo.repo_name)
121 121 cs_data['message_html_title'] = chop_at_smart(
122 122 cs_data['message'], '\n', suffix_if_chopped='...')
123 123 commits.append(cs_data)
124 124
125 125 needed_commits.remove(commit_id)
126 126
127 127 except Exception:
128 128 log.exception('Failed to extract commits data')
129 129 # we don't send any commits when crash happens, only full list
130 130 # matters we short circuit then.
131 131 return []
132 132
133 133 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
134 134 if missing_commits:
135 135 log.error('Inconsistent repository state. '
136 136 'Missing commits: %s', ', '.join(missing_commits))
137 137
138 138 return commits
139 139
140 140
141 141 def _issues_as_dict(commits):
142 142 """ Helper function to serialize issues from commits """
143 143 issues = {}
144 144 for commit in commits:
145 145 for issue in commit['issues']:
146 146 issues[issue['id']] = issue
147 147 return issues
148 148
149 149
150 150 class RepoEvent(RhodeCodeIntegrationEvent):
151 151 """
152 152 Base class for events acting on a repository.
153 153
154 154 :param repo: a :class:`Repository` instance
155 155 """
156 156
157 157 def __init__(self, repo):
158 158 super(RepoEvent, self).__init__()
159 159 self.repo = repo
160 160
161 161 def as_dict(self):
162 162 from rhodecode.model.repo import RepoModel
163 163 data = super(RepoEvent, self).as_dict()
164 164
165 165 extra_fields = collections.OrderedDict()
166 166 for field in self.repo.extra_fields:
167 167 extra_fields[field.field_key] = field.field_value
168 168
169 169 data.update({
170 170 'repo': {
171 171 'repo_id': self.repo.repo_id,
172 172 'repo_name': self.repo.repo_name,
173 173 'repo_type': self.repo.repo_type,
174 174 'url': RepoModel().get_url(
175 175 self.repo, request=self.request),
176 176 'permalink_url': RepoModel().get_url(
177 177 self.repo, request=self.request, permalink=True),
178 178 'extra_fields': extra_fields
179 179 }
180 180 })
181 181 return data
182 182
183 183
184 184 class RepoPreCreateEvent(RepoEvent):
185 185 """
186 186 An instance of this class is emitted as an :term:`event` before a repo is
187 187 created.
188 188 """
189 189 name = 'repo-pre-create'
190 190 display_name = lazy_ugettext('repository pre create')
191 191
192 192
193 193 class RepoCreateEvent(RepoEvent):
194 194 """
195 195 An instance of this class is emitted as an :term:`event` whenever a repo is
196 196 created.
197 197 """
198 198 name = 'repo-create'
199 199 display_name = lazy_ugettext('repository created')
200 200
201 201
202 202 class RepoPreDeleteEvent(RepoEvent):
203 203 """
204 204 An instance of this class is emitted as an :term:`event` whenever a repo is
205 205 created.
206 206 """
207 207 name = 'repo-pre-delete'
208 208 display_name = lazy_ugettext('repository pre delete')
209 209
210 210
211 211 class RepoDeleteEvent(RepoEvent):
212 212 """
213 213 An instance of this class is emitted as an :term:`event` whenever a repo is
214 214 created.
215 215 """
216 216 name = 'repo-delete'
217 217 display_name = lazy_ugettext('repository deleted')
218 218
219 219
220 220 class RepoVCSEvent(RepoEvent):
221 221 """
222 222 Base class for events triggered by the VCS
223 223 """
224 224 def __init__(self, repo_name, extras):
225 225 self.repo = Repository.get_by_repo_name(repo_name)
226 226 if not self.repo:
227 227 raise Exception('repo by this name %s does not exist' % repo_name)
228 228 self.extras = extras
229 229 super(RepoVCSEvent, self).__init__(self.repo)
230 230
231 231 @property
232 232 def actor(self):
233 233 if self.extras.get('username'):
234 234 return User.get_by_username(self.extras['username'])
235 235
236 236 @property
237 237 def actor_ip(self):
238 238 if self.extras.get('ip'):
239 239 return self.extras['ip']
240 240
241 241 @property
242 242 def server_url(self):
243 243 if self.extras.get('server_url'):
244 244 return self.extras['server_url']
245 245
246 246 @property
247 247 def request(self):
248 248 return self.extras.get('request') or self.get_request()
249 249
250 250
251 251 class RepoPrePullEvent(RepoVCSEvent):
252 252 """
253 253 An instance of this class is emitted as an :term:`event` before commits
254 254 are pulled from a repo.
255 255 """
256 256 name = 'repo-pre-pull'
257 257 display_name = lazy_ugettext('repository pre pull')
258 258
259 259
260 260 class RepoPullEvent(RepoVCSEvent):
261 261 """
262 262 An instance of this class is emitted as an :term:`event` after commits
263 263 are pulled from a repo.
264 264 """
265 265 name = 'repo-pull'
266 266 display_name = lazy_ugettext('repository pull')
267 267
268 268
269 269 class RepoPrePushEvent(RepoVCSEvent):
270 270 """
271 271 An instance of this class is emitted as an :term:`event` before commits
272 272 are pushed to a repo.
273 273 """
274 274 name = 'repo-pre-push'
275 275 display_name = lazy_ugettext('repository pre push')
276 276
277 277
278 278 class RepoPushEvent(RepoVCSEvent):
279 279 """
280 280 An instance of this class is emitted as an :term:`event` after commits
281 281 are pushed to a repo.
282 282
283 283 :param extras: (optional) dict of data from proxied VCS actions
284 284 """
285 285 name = 'repo-push'
286 286 display_name = lazy_ugettext('repository push')
287 287
288 288 def __init__(self, repo_name, pushed_commit_ids, extras):
289 289 super(RepoPushEvent, self).__init__(repo_name, extras)
290 290 self.pushed_commit_ids = pushed_commit_ids
291 291 self.new_refs = extras.new_refs
292 292
293 293 def as_dict(self):
294 294 data = super(RepoPushEvent, self).as_dict()
295 295
296 296 def branch_url(branch_name):
297 297 return '{}/changelog?branch={}'.format(
298 298 data['repo']['url'], branch_name)
299 299
300 300 def tag_url(tag_name):
301 301 return '{}/files/{}/'.format(
302 302 data['repo']['url'], tag_name)
303 303
304 304 commits = _commits_as_dict(
305 305 self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
306 306
307 307 last_branch = None
308 308 for commit in reversed(commits):
309 309 commit['branch'] = commit['branch'] or last_branch
310 310 last_branch = commit['branch']
311 311 issues = _issues_as_dict(commits)
312 312
313 313 branches = set()
314 314 tags = set()
315 315 for commit in commits:
316 316 if commit['refs']['tags']:
317 317 for tag in commit['refs']['tags']:
318 318 tags.add(tag)
319 319 if commit['branch']:
320 320 branches.add(commit['branch'])
321 321
322 322 # maybe we have branches in new_refs ?
323 323 try:
324 324 branches = branches.union(set(self.new_refs['branches']))
325 325 except Exception:
326 326 pass
327 327
328 328 branches = [
329 329 {
330 330 'name': branch,
331 331 'url': branch_url(branch)
332 332 }
333 333 for branch in branches
334 334 ]
335 335
336 336 # maybe we have branches in new_refs ?
337 337 try:
338 338 tags = tags.union(set(self.new_refs['tags']))
339 339 except Exception:
340 340 pass
341 341
342 342 tags = [
343 343 {
344 344 'name': tag,
345 345 'url': tag_url(tag)
346 346 }
347 347 for tag in tags
348 348 ]
349 349
350 350 data['push'] = {
351 351 'commits': commits,
352 352 'issues': issues,
353 353 'branches': branches,
354 354 'tags': tags,
355 355 }
356 356 return data
@@ -1,196 +1,196 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import os
22 22 import stat
23 23 import sys
24 24
25 25 import pytest
26 26 from mock import Mock, patch, DEFAULT
27 27
28 28 import rhodecode
29 29 from rhodecode.model import db, scm
30 30 from rhodecode.tests import no_newline_id_generator
31 31
32 32
33 33 def test_scm_instance_config(backend):
34 34 repo = backend.create_repo()
35 35 with patch.multiple('rhodecode.model.db.Repository',
36 36 _get_instance=DEFAULT,
37 37 _get_instance_cached=DEFAULT) as mocks:
38 38 repo.scm_instance()
39 39 mocks['_get_instance'].assert_called_with(
40 40 config=None, cache=False)
41 41
42 42 config = {'some': 'value'}
43 43 repo.scm_instance(config=config)
44 44 mocks['_get_instance'].assert_called_with(
45 45 config=config, cache=False)
46 46
47 47 with patch.dict(rhodecode.CONFIG, {'vcs_full_cache': 'true'}):
48 48 repo.scm_instance(config=config)
49 49 mocks['_get_instance_cached'].assert_called()
50 50
51 51
52 52 def test__get_instance_config(backend):
53 53 repo = backend.create_repo()
54 54 vcs_class = Mock()
55 55 with patch.multiple('rhodecode.lib.vcs.backends',
56 56 get_scm=DEFAULT,
57 57 get_backend=DEFAULT) as mocks:
58 58 mocks['get_scm'].return_value = backend.alias
59 59 mocks['get_backend'].return_value = vcs_class
60 60 with patch('rhodecode.model.db.Repository._config') as config_mock:
61 61 repo._get_instance()
62 62 vcs_class.assert_called_with(
63 63 repo_path=repo.repo_full_path, config=config_mock,
64 64 create=False, with_wire={'cache': True})
65 65
66 66 new_config = {'override': 'old_config'}
67 67 repo._get_instance(config=new_config)
68 68 vcs_class.assert_called_with(
69 69 repo_path=repo.repo_full_path, config=new_config, create=False,
70 70 with_wire={'cache': True})
71 71
72 72
73 73 def test_mark_for_invalidation_config(backend):
74 74 repo = backend.create_repo()
75 75 with patch('rhodecode.model.db.Repository.update_commit_cache') as _mock:
76 76 scm.ScmModel().mark_for_invalidation(repo.repo_name)
77 77 _, kwargs = _mock.call_args
78 78 assert kwargs['config'].__dict__ == repo._config.__dict__
79 79
80 80
81 81 def test_mark_for_invalidation_with_delete_updates_last_commit(backend):
82 82 commits = [{'message': 'A'}, {'message': 'B'}]
83 83 repo = backend.create_repo(commits=commits)
84 84 scm.ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
85 85 assert repo.changeset_cache['revision'] == 1
86 86
87 87
88 88 def test_mark_for_invalidation_with_delete_updates_last_commit_empty(backend):
89 89 repo = backend.create_repo()
90 90 scm.ScmModel().mark_for_invalidation(repo.repo_name, delete=True)
91 91 assert repo.changeset_cache['revision'] == -1
92 92
93 93
94 94 def test_strip_with_multiple_heads(backend_hg):
95 95 commits = [
96 96 {'message': 'A'},
97 97 {'message': 'a'},
98 98 {'message': 'b'},
99 99 {'message': 'B', 'parents': ['A']},
100 100 {'message': 'a1'},
101 101 ]
102 102 repo = backend_hg.create_repo(commits=commits)
103 103 commit_ids = backend_hg.commit_ids
104 104
105 105 model = scm.ScmModel()
106 106 model.strip(repo, commit_ids['b'], branch=None)
107 107
108 108 vcs_repo = repo.scm_instance()
109 rest_commit_ids = [c.raw_id for c in vcs_repo.get_changesets()]
109 rest_commit_ids = [c.raw_id for c in vcs_repo.get_commits()]
110 110 assert len(rest_commit_ids) == 4
111 111 assert commit_ids['b'] not in rest_commit_ids
112 112
113 113
114 114 def test_strip_with_single_heads(backend_hg):
115 115 commits = [
116 116 {'message': 'A'},
117 117 {'message': 'a'},
118 118 {'message': 'b'},
119 119 ]
120 120 repo = backend_hg.create_repo(commits=commits)
121 121 commit_ids = backend_hg.commit_ids
122 122
123 123 model = scm.ScmModel()
124 124 model.strip(repo, commit_ids['b'], branch=None)
125 125
126 126 vcs_repo = repo.scm_instance()
127 rest_commit_ids = [c.raw_id for c in vcs_repo.get_changesets()]
127 rest_commit_ids = [c.raw_id for c in vcs_repo.get_commits()]
128 128 assert len(rest_commit_ids) == 2
129 129 assert commit_ids['b'] not in rest_commit_ids
130 130
131 131
132 132 def test_get_nodes_returns_unicode_flat(backend_random):
133 133 repo = backend_random.repo
134 134 directories, files = scm.ScmModel().get_nodes(
135 135 repo.repo_name, repo.get_commit(commit_idx=0).raw_id,
136 136 flat=True)
137 137 assert_contains_only_unicode(directories)
138 138 assert_contains_only_unicode(files)
139 139
140 140
141 141 def test_get_nodes_returns_unicode_non_flat(backend_random):
142 142 repo = backend_random.repo
143 143 directories, files = scm.ScmModel().get_nodes(
144 144 repo.repo_name, repo.get_commit(commit_idx=0).raw_id,
145 145 flat=False)
146 146 # johbo: Checking only the names for now, since that is the critical
147 147 # part.
148 148 assert_contains_only_unicode([d['name'] for d in directories])
149 149 assert_contains_only_unicode([f['name'] for f in files])
150 150
151 151
152 152 def test_get_nodes_max_file_bytes(backend_random):
153 153 repo = backend_random.repo
154 154 max_file_bytes = 10
155 155 directories, files = scm.ScmModel().get_nodes(
156 156 repo.repo_name, repo.get_commit(commit_idx=0).raw_id, content=True,
157 157 extended_info=True, flat=False)
158 158 assert any(file['content'] and len(file['content']) > max_file_bytes
159 159 for file in files)
160 160
161 161 directories, files = scm.ScmModel().get_nodes(
162 162 repo.repo_name, repo.get_commit(commit_idx=0).raw_id, content=True,
163 163 extended_info=True, flat=False, max_file_bytes=max_file_bytes)
164 164 assert all(
165 165 file['content'] is None if file['size'] > max_file_bytes else True
166 166 for file in files)
167 167
168 168
169 169 def assert_contains_only_unicode(structure):
170 170 assert structure
171 171 for value in structure:
172 172 assert isinstance(value, unicode)
173 173
174 174
175 175 @pytest.mark.backends("hg", "git")
176 176 def test_get_non_unicode_reference(backend):
177 177 model = scm.ScmModel()
178 178 non_unicode_list = ["Adını".decode("cp1254")]
179 179
180 180 def scm_instance():
181 181 return Mock(
182 182 branches=non_unicode_list, bookmarks=non_unicode_list,
183 183 tags=non_unicode_list, alias=backend.alias)
184 184
185 185 repo = Mock(__class__=db.Repository, scm_instance=scm_instance)
186 186 choices, __ = model.get_repo_landing_revs(translator=lambda s: s, repo=repo)
187 187 if backend.alias == 'hg':
188 188 valid_choices = [
189 189 'rev:tip', u'branch:Ad\xc4\xb1n\xc4\xb1',
190 190 u'book:Ad\xc4\xb1n\xc4\xb1', u'tag:Ad\xc4\xb1n\xc4\xb1']
191 191 else:
192 192 valid_choices = [
193 193 'rev:tip', u'branch:Ad\xc4\xb1n\xc4\xb1',
194 194 u'tag:Ad\xc4\xb1n\xc4\xb1']
195 195
196 196 assert choices == valid_choices
General Comments 0
You need to be logged in to leave comments. Login now