##// END OF EJS Templates
compare: cleanup of as_form handling...
Mads Kiilerich -
r3442:b3680a20 beta
parent child Browse files
Show More
@@ -1,192 +1,192 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.compare
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 compare controller for pylons showing differences between two
7 7 repos, branches, bookmarks or tips
8 8
9 9 :created_on: May 6, 2012
10 10 :author: marcink
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26 import logging
27 27 import traceback
28 28
29 29 from webob.exc import HTTPNotFound
30 30 from pylons import request, response, session, tmpl_context as c, url
31 31 from pylons.controllers.util import abort, redirect
32 32 from pylons.i18n.translation import _
33 33
34 34 from rhodecode.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError
35 35 from rhodecode.lib import helpers as h
36 36 from rhodecode.lib.base import BaseRepoController, render
37 37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
38 38 from rhodecode.lib import diffs
39 39
40 40 from rhodecode.model.db import Repository
41 41 from rhodecode.model.pull_request import PullRequestModel
42 42 from webob.exc import HTTPBadRequest
43 43 from rhodecode.lib.diffs import LimitedDiffContainer
44 44 from rhodecode.lib.vcs.backends.base import EmptyChangeset
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48
49 49 class CompareController(BaseRepoController):
50 50
51 51 @LoginRequired()
52 52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
53 53 'repository.admin')
54 54 def __before__(self):
55 55 super(CompareController, self).__before__()
56 56
57 57 def __get_cs_or_redirect(self, rev, repo, redirect_after=True,
58 58 partial=False):
59 59 """
60 60 Safe way to get changeset if error occur it redirects to changeset with
61 61 proper message. If partial is set then don't do redirect raise Exception
62 62 instead
63 63
64 64 :param rev: revision to fetch
65 65 :param repo: repo instance
66 66 """
67 67
68 68 try:
69 69 type_, rev = rev
70 70 return repo.scm_instance.get_changeset(rev)
71 71 except EmptyRepositoryError, e:
72 72 if not redirect_after:
73 73 return None
74 74 h.flash(h.literal(_('There are no changesets yet')),
75 75 category='warning')
76 76 redirect(url('summary_home', repo_name=repo.repo_name))
77 77
78 78 except RepositoryError, e:
79 79 log.error(traceback.format_exc())
80 80 h.flash(str(e), category='warning')
81 81 if not partial:
82 82 redirect(h.url('summary_home', repo_name=repo.repo_name))
83 83 raise HTTPBadRequest()
84 84
85 85 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
86 86
87 87 org_repo = c.rhodecode_db_repo.repo_name
88 88 org_ref = (org_ref_type, org_ref)
89 89 other_ref = (other_ref_type, other_ref)
90 90 other_repo = request.GET.get('other_repo', org_repo)
91 91 c.fulldiff = fulldiff = request.GET.get('fulldiff')
92 92 rev_start = request.GET.get('rev_start')
93 93 rev_end = request.GET.get('rev_end')
94
95 c.swap_url = h.url('compare_url', as_form=request.GET.get('as_form'),
94 # partial uses compare_cs.html template directly
95 partial = request.environ.get('HTTP_X_PARTIAL_XHR')
96 # as_form puts hidden input field with changeset revisions
97 c.as_form = partial and request.GET.get('as_form')
98 # swap url for compare_diff page - never partial and never as_form
99 c.swap_url = h.url('compare_url',
96 100 repo_name=other_repo,
97 101 org_ref_type=other_ref[0], org_ref=other_ref[1],
98 102 other_repo=org_repo,
99 103 other_ref_type=org_ref[0], other_ref=org_ref[1])
100 104
101 partial = request.environ.get('HTTP_X_PARTIAL_XHR')
102
103 105 org_repo = Repository.get_by_repo_name(org_repo)
104 106 other_repo = Repository.get_by_repo_name(other_repo)
105 107
106 108 self.__get_cs_or_redirect(rev=org_ref, repo=org_repo, partial=partial)
107 109 self.__get_cs_or_redirect(rev=other_ref, repo=other_repo, partial=partial)
108 110
109 111 if org_repo is None:
110 112 log.error('Could not find org repo %s' % org_repo)
111 113 raise HTTPNotFound
112 114 if other_repo is None:
113 115 log.error('Could not find other repo %s' % other_repo)
114 116 raise HTTPNotFound
115 117
116 118 if org_repo != other_repo and h.is_git(org_repo):
117 119 log.error('compare of two remote repos not available for GIT REPOS')
118 120 raise HTTPNotFound
119 121
120 122 if org_repo.scm_instance.alias != other_repo.scm_instance.alias:
121 123 log.error('compare of two different kind of remote repos not available')
122 124 raise HTTPNotFound
123 125
124 126 c.org_repo = org_repo
125 127 c.other_repo = other_repo
126 128 c.org_ref = org_ref[1]
127 129 c.other_ref = other_ref[1]
128 130 c.org_ref_type = org_ref[0]
129 131 c.other_ref_type = other_ref[0]
130 132
131 133 if rev_start and rev_end:
132 134 # swap revs with cherry picked ones, save them for display
133 135 #org_ref = ('rev', rev_start)
134 136 #other_ref = ('rev', rev_end)
135 137 c.org_ref = rev_start[:12]
136 138 c.other_ref = rev_end[:12]
137 139 # get parent of
138 140 # rev start to include it in the diff
139 141 _cs = other_repo.scm_instance.get_changeset(rev_start)
140 142 rev_start = _cs.parents[0].raw_id if _cs.parents else EmptyChangeset().raw_id
141 143 org_ref = ('rev', rev_start)
142 144 other_ref = ('rev', rev_end)
143 145 #if we cherry pick it's not remote, make the other_repo org_repo
144 146 org_repo = other_repo
145 147
146 148 c.cs_ranges, ancestor = PullRequestModel().get_compare_data(
147 149 org_repo, org_ref, other_repo, other_ref)
148 150
149 151 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
150 152 c.cs_ranges])
151 # defines that we need hidden inputs with changesets
152 c.as_form = request.GET.get('as_form', False)
153 153 if partial:
154 154 return render('compare/compare_cs.html')
155 155
156 156 if ancestor and org_repo != other_repo:
157 157 # case we want a simple diff without incoming changesets,
158 158 # previewing what will be merged.
159 159 # Make the diff on the forked repo, with
160 160 # revision that is common ancestor
161 161 log.debug('Using ancestor %s as org_ref instead of %s'
162 162 % (ancestor, org_ref))
163 163 org_ref = ('rev', ancestor)
164 164 org_repo = other_repo
165 165
166 166 diff_limit = self.cut_off_limit if not fulldiff else None
167 167
168 168 _diff = diffs.differ(org_repo, org_ref, other_repo, other_ref)
169 169
170 170 diff_processor = diffs.DiffProcessor(_diff or '', format='gitdiff',
171 171 diff_limit=diff_limit)
172 172 _parsed = diff_processor.prepare()
173 173
174 174 c.limited_diff = False
175 175 if isinstance(_parsed, LimitedDiffContainer):
176 176 c.limited_diff = True
177 177
178 178 c.files = []
179 179 c.changes = {}
180 180 c.lines_added = 0
181 181 c.lines_deleted = 0
182 182 for f in _parsed:
183 183 st = f['stats']
184 184 if st[0] != 'b':
185 185 c.lines_added += st[0]
186 186 c.lines_deleted += st[1]
187 187 fid = h.FID('', f['filename'])
188 188 c.files.append([fid, f['operation'], f['filename'], f['stats']])
189 189 diff = diff_processor.as_html(enable_comments=False, parsed_lines=[f])
190 190 c.changes[fid] = [f['operation'], f['filename'], diff]
191 191
192 192 return render('compare/compare_diff.html')
@@ -1,485 +1,484 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.pullrequests
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 pull requests controller for rhodecode for initializing pull requests
7 7
8 8 :created_on: May 7, 2012
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25 import logging
26 26 import traceback
27 27 import formencode
28 28
29 29 from webob.exc import HTTPNotFound, HTTPForbidden
30 30 from collections import defaultdict
31 31 from itertools import groupby
32 32
33 33 from pylons import request, response, session, tmpl_context as c, url
34 34 from pylons.controllers.util import abort, redirect
35 35 from pylons.i18n.translation import _
36 36
37 37 from rhodecode.lib.compat import json
38 38 from rhodecode.lib.base import BaseRepoController, render
39 39 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\
40 40 NotAnonymous
41 41 from rhodecode.lib import helpers as h
42 42 from rhodecode.lib import diffs
43 43 from rhodecode.lib.utils import action_logger, jsonify
44 44 from rhodecode.lib.vcs.exceptions import EmptyRepositoryError
45 45 from rhodecode.lib.vcs.backends.base import EmptyChangeset
46 46 from rhodecode.lib.diffs import LimitedDiffContainer
47 47 from rhodecode.model.db import User, PullRequest, ChangesetStatus,\
48 48 ChangesetComment
49 49 from rhodecode.model.pull_request import PullRequestModel
50 50 from rhodecode.model.meta import Session
51 51 from rhodecode.model.repo import RepoModel
52 52 from rhodecode.model.comment import ChangesetCommentsModel
53 53 from rhodecode.model.changeset_status import ChangesetStatusModel
54 54 from rhodecode.model.forms import PullRequestForm
55 55
56 56 log = logging.getLogger(__name__)
57 57
58 58
59 59 class PullrequestsController(BaseRepoController):
60 60
61 61 @LoginRequired()
62 62 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
63 63 'repository.admin')
64 64 def __before__(self):
65 65 super(PullrequestsController, self).__before__()
66 66 repo_model = RepoModel()
67 67 c.users_array = repo_model.get_users_js()
68 68 c.users_groups_array = repo_model.get_users_groups_js()
69 69
70 70 def _get_repo_refs(self, repo):
71 71 hist_l = []
72 72
73 73 branches_group = ([('branch:%s:%s' % (k, v), k) for
74 74 k, v in repo.branches.iteritems()], _("Branches"))
75 75 bookmarks_group = ([('book:%s:%s' % (k, v), k) for
76 76 k, v in repo.bookmarks.iteritems()], _("Bookmarks"))
77 77 tags_group = ([('tag:%s:%s' % (k, v), k) for
78 78 k, v in repo.tags.iteritems()
79 79 if k != 'tip'], _("Tags"))
80 80
81 81 tip = repo.tags['tip']
82 82 tipref = 'tag:tip:%s' % tip
83 83 colontip = ':' + tip
84 84 tips = [x[1] for x in branches_group[0] + bookmarks_group[0] + tags_group[0]
85 85 if x[0].endswith(colontip)]
86 86 tags_group[0].append((tipref, 'tip (%s)' % ', '.join(tips)))
87 87
88 88 hist_l.append(bookmarks_group)
89 89 hist_l.append(branches_group)
90 90 hist_l.append(tags_group)
91 91
92 92 return hist_l, tipref
93 93
94 94 def _get_is_allowed_change_status(self, pull_request):
95 95 owner = self.rhodecode_user.user_id == pull_request.user_id
96 96 reviewer = self.rhodecode_user.user_id in [x.user_id for x in
97 97 pull_request.reviewers]
98 98 return (self.rhodecode_user.admin or owner or reviewer)
99 99
100 100 def show_all(self, repo_name):
101 101 c.pull_requests = PullRequestModel().get_all(repo_name)
102 102 c.repo_name = repo_name
103 103 return render('/pullrequests/pullrequest_show_all.html')
104 104
105 105 @NotAnonymous()
106 106 def index(self):
107 107 org_repo = c.rhodecode_db_repo
108 108
109 109 if org_repo.scm_instance.alias != 'hg':
110 110 log.error('Review not available for GIT REPOS')
111 111 raise HTTPNotFound
112 112
113 113 try:
114 114 org_repo.scm_instance.get_changeset()
115 115 except EmptyRepositoryError, e:
116 116 h.flash(h.literal(_('There are no changesets yet')),
117 117 category='warning')
118 118 redirect(url('summary_home', repo_name=org_repo.repo_name))
119 119
120 120 other_repos_info = {}
121 121
122 122 c.org_repos = []
123 123 c.org_repos.append((org_repo.repo_name, org_repo.repo_name))
124 124 c.default_org_repo = org_repo.repo_name
125 125 c.org_refs, c.default_org_ref = self._get_repo_refs(org_repo.scm_instance)
126 126
127 127 c.other_repos = []
128 128 # add org repo to other so we can open pull request against itself
129 129 c.other_repos.extend(c.org_repos)
130 130 c.default_other_repo = org_repo.repo_name
131 131 c.default_other_refs, c.default_other_ref = self._get_repo_refs(org_repo.scm_instance)
132 132 usr_data = lambda usr: dict(user_id=usr.user_id,
133 133 username=usr.username,
134 134 firstname=usr.firstname,
135 135 lastname=usr.lastname,
136 136 gravatar_link=h.gravatar_url(usr.email, 14))
137 137 other_repos_info[org_repo.repo_name] = {
138 138 'user': usr_data(org_repo.user),
139 139 'description': org_repo.description,
140 140 'revs': h.select('other_ref', c.default_other_ref,
141 141 c.default_other_refs, class_='refs')
142 142 }
143 143
144 144 # gather forks and add to this list ... even though it is rare to
145 145 # request forks to pull their parent
146 146 for fork in org_repo.forks:
147 147 c.other_repos.append((fork.repo_name, fork.repo_name))
148 148 refs, default_ref = self._get_repo_refs(fork.scm_instance)
149 149 other_repos_info[fork.repo_name] = {
150 150 'user': usr_data(fork.user),
151 151 'description': fork.description,
152 152 'revs': h.select('other_ref', default_ref, refs, class_='refs')
153 153 }
154 154
155 155 # add parents of this fork also, but only if it's not empty
156 156 if org_repo.parent and org_repo.parent.scm_instance.revisions:
157 157 c.default_other_repo = org_repo.parent.repo_name
158 158 c.default_other_refs, c.default_other_ref = self._get_repo_refs(org_repo.parent.scm_instance)
159 159 c.other_repos.append((org_repo.parent.repo_name, org_repo.parent.repo_name))
160 160 other_repos_info[org_repo.parent.repo_name] = {
161 161 'user': usr_data(org_repo.parent.user),
162 162 'description': org_repo.parent.description,
163 163 'revs': h.select('other_ref', c.default_other_ref,
164 164 c.default_other_refs, class_='refs')
165 165 }
166 166
167 167 c.other_repos_info = json.dumps(other_repos_info)
168 168 # other repo owner
169 169 c.review_members = []
170 170 return render('/pullrequests/pullrequest.html')
171 171
172 172 @NotAnonymous()
173 173 def create(self, repo_name):
174 174 repo = RepoModel()._get_repo(repo_name)
175 175 try:
176 176 _form = PullRequestForm(repo.repo_id)().to_python(request.POST)
177 177 except formencode.Invalid, errors:
178 178 log.error(traceback.format_exc())
179 179 if errors.error_dict.get('revisions'):
180 180 msg = 'Revisions: %s' % errors.error_dict['revisions']
181 181 elif errors.error_dict.get('pullrequest_title'):
182 182 msg = _('Pull request requires a title with min. 3 chars')
183 183 else:
184 184 msg = _('error during creation of pull request')
185 185
186 186 h.flash(msg, 'error')
187 187 return redirect(url('pullrequest_home', repo_name=repo_name))
188 188
189 189 org_repo = _form['org_repo']
190 190 org_ref = _form['org_ref']
191 191 other_repo = _form['other_repo']
192 192 other_ref = _form['other_ref']
193 193 revisions = _form['revisions']
194 194 reviewers = _form['review_members']
195 195
196 196 # if we have cherry picked pull request we don't care what is in
197 197 # org_ref/other_ref
198 198 rev_start = request.POST.get('rev_start')
199 199 rev_end = request.POST.get('rev_end')
200 200
201 201 if rev_start and rev_end:
202 202 # this is swapped to simulate that rev_end is a revision from
203 203 # parent of the fork
204 204 org_ref = 'rev:%s:%s' % (rev_end, rev_end)
205 205 other_ref = 'rev:%s:%s' % (rev_start, rev_start)
206 206
207 207 title = _form['pullrequest_title']
208 208 description = _form['pullrequest_desc']
209 209
210 210 try:
211 211 pull_request = PullRequestModel().create(
212 212 self.rhodecode_user.user_id, org_repo, org_ref, other_repo,
213 213 other_ref, revisions, reviewers, title, description
214 214 )
215 215 Session().commit()
216 216 h.flash(_('Successfully opened new pull request'),
217 217 category='success')
218 218 except Exception:
219 219 h.flash(_('Error occurred during sending pull request'),
220 220 category='error')
221 221 log.error(traceback.format_exc())
222 222 return redirect(url('pullrequest_home', repo_name=repo_name))
223 223
224 224 return redirect(url('pullrequest_show', repo_name=other_repo,
225 225 pull_request_id=pull_request.pull_request_id))
226 226
227 227 @NotAnonymous()
228 228 @jsonify
229 229 def update(self, repo_name, pull_request_id):
230 230 pull_request = PullRequest.get_or_404(pull_request_id)
231 231 if pull_request.is_closed():
232 232 raise HTTPForbidden()
233 233 #only owner or admin can update it
234 234 owner = pull_request.author.user_id == c.rhodecode_user.user_id
235 235 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
236 236 reviewers_ids = map(int, filter(lambda v: v not in [None, ''],
237 237 request.POST.get('reviewers_ids', '').split(',')))
238 238
239 239 PullRequestModel().update_reviewers(pull_request_id, reviewers_ids)
240 240 Session().commit()
241 241 return True
242 242 raise HTTPForbidden()
243 243
244 244 @NotAnonymous()
245 245 @jsonify
246 246 def delete(self, repo_name, pull_request_id):
247 247 pull_request = PullRequest.get_or_404(pull_request_id)
248 248 #only owner can delete it !
249 249 if pull_request.author.user_id == c.rhodecode_user.user_id:
250 250 PullRequestModel().delete(pull_request)
251 251 Session().commit()
252 252 h.flash(_('Successfully deleted pull request'),
253 253 category='success')
254 254 return redirect(url('admin_settings_my_account', anchor='pullrequests'))
255 255 raise HTTPForbidden()
256 256
257 257 def _load_compare_data(self, pull_request, enable_comments=True):
258 258 """
259 259 Load context data needed for generating compare diff
260 260
261 261 :param pull_request:
262 262 :type pull_request:
263 263 """
264 264 rev_start = request.GET.get('rev_start')
265 265 rev_end = request.GET.get('rev_end')
266 266
267 267 org_repo = pull_request.org_repo
268 268 (org_ref_type,
269 269 org_ref_name,
270 270 org_ref_rev) = pull_request.org_ref.split(':')
271 271
272 272 other_repo = org_repo
273 273 (other_ref_type,
274 274 other_ref_name,
275 275 other_ref_rev) = pull_request.other_ref.split(':')
276 276
277 277 # despite opening revisions for bookmarks/branches/tags, we always
278 278 # convert this to rev to prevent changes after book or branch change
279 279 org_ref = ('rev', org_ref_rev)
280 280 other_ref = ('rev', other_ref_rev)
281 281
282 282 c.org_repo = org_repo
283 283 c.other_repo = other_repo
284 284
285 285 c.fulldiff = fulldiff = request.GET.get('fulldiff')
286 286
287 287 c.cs_ranges = [org_repo.get_changeset(x) for x in pull_request.revisions]
288 288
289 289 other_ref = ('rev', getattr(c.cs_ranges[0].parents[0]
290 290 if c.cs_ranges[0].parents
291 291 else EmptyChangeset(), 'raw_id'))
292 292
293 293 c.statuses = org_repo.statuses([x.raw_id for x in c.cs_ranges])
294 # defines that we need hidden inputs with changesets
295 c.as_form = request.GET.get('as_form', False)
296 294
297 295 c.org_ref = org_ref[1]
298 296 c.org_ref_type = org_ref[0]
299 297 c.other_ref = other_ref[1]
300 298 c.other_ref_type = other_ref[0]
301 299
302 300 diff_limit = self.cut_off_limit if not fulldiff else None
303 301
304 302 #we swap org/other ref since we run a simple diff on one repo
305 303 _diff = diffs.differ(org_repo, other_ref, other_repo, org_ref)
306 304
307 305 diff_processor = diffs.DiffProcessor(_diff or '', format='gitdiff',
308 306 diff_limit=diff_limit)
309 307 _parsed = diff_processor.prepare()
310 308
311 309 c.limited_diff = False
312 310 if isinstance(_parsed, LimitedDiffContainer):
313 311 c.limited_diff = True
314 312
315 313 c.files = []
316 314 c.changes = {}
317 315 c.lines_added = 0
318 316 c.lines_deleted = 0
319 317 for f in _parsed:
320 318 st = f['stats']
321 319 if st[0] != 'b':
322 320 c.lines_added += st[0]
323 321 c.lines_deleted += st[1]
324 322 fid = h.FID('', f['filename'])
325 323 c.files.append([fid, f['operation'], f['filename'], f['stats']])
326 324 diff = diff_processor.as_html(enable_comments=enable_comments,
327 325 parsed_lines=[f])
328 326 c.changes[fid] = [f['operation'], f['filename'], diff]
329 327
330 328 def show(self, repo_name, pull_request_id):
331 329 repo_model = RepoModel()
332 330 c.users_array = repo_model.get_users_js()
333 331 c.users_groups_array = repo_model.get_users_groups_js()
334 332 c.pull_request = PullRequest.get_or_404(pull_request_id)
335 333 c.allowed_to_change_status = self._get_is_allowed_change_status(c.pull_request)
336 334 cc_model = ChangesetCommentsModel()
337 335 cs_model = ChangesetStatusModel()
338 336 _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo,
339 337 pull_request=c.pull_request,
340 338 with_revisions=True)
341 339
342 340 cs_statuses = defaultdict(list)
343 341 for st in _cs_statuses:
344 342 cs_statuses[st.author.username] += [st]
345 343
346 344 c.pull_request_reviewers = []
347 345 c.pull_request_pending_reviewers = []
348 346 for o in c.pull_request.reviewers:
349 347 st = cs_statuses.get(o.user.username, None)
350 348 if st:
351 349 sorter = lambda k: k.version
352 350 st = [(x, list(y)[0])
353 351 for x, y in (groupby(sorted(st, key=sorter), sorter))]
354 352 else:
355 353 c.pull_request_pending_reviewers.append(o.user)
356 354 c.pull_request_reviewers.append([o.user, st])
357 355
358 356 # pull_requests repo_name we opened it against
359 357 # ie. other_repo must match
360 358 if repo_name != c.pull_request.other_repo.repo_name:
361 359 raise HTTPNotFound
362 360
363 361 # load compare data into template context
364 362 enable_comments = not c.pull_request.is_closed()
365 363 self._load_compare_data(c.pull_request, enable_comments=enable_comments)
366 364
367 365 # inline comments
368 366 c.inline_cnt = 0
369 367 c.inline_comments = cc_model.get_inline_comments(
370 368 c.rhodecode_db_repo.repo_id,
371 369 pull_request=pull_request_id)
372 370 # count inline comments
373 371 for __, lines in c.inline_comments:
374 372 for comments in lines.values():
375 373 c.inline_cnt += len(comments)
376 374 # comments
377 375 c.comments = cc_model.get_comments(c.rhodecode_db_repo.repo_id,
378 376 pull_request=pull_request_id)
379 377
380 378 try:
381 379 cur_status = c.statuses[c.pull_request.revisions[0]][0]
382 380 except:
383 381 log.error(traceback.format_exc())
384 382 cur_status = 'undefined'
385 383 if c.pull_request.is_closed() and 0:
386 384 c.current_changeset_status = cur_status
387 385 else:
388 386 # changeset(pull-request) status calulation based on reviewers
389 387 c.current_changeset_status = cs_model.calculate_status(
390 388 c.pull_request_reviewers,
391 389 )
392 390 c.changeset_statuses = ChangesetStatus.STATUSES
393 391
392 c.as_form = False
394 393 return render('/pullrequests/pullrequest_show.html')
395 394
396 395 @NotAnonymous()
397 396 @jsonify
398 397 def comment(self, repo_name, pull_request_id):
399 398 pull_request = PullRequest.get_or_404(pull_request_id)
400 399 if pull_request.is_closed():
401 400 raise HTTPForbidden()
402 401
403 402 status = request.POST.get('changeset_status')
404 403 change_status = request.POST.get('change_changeset_status')
405 404 text = request.POST.get('text')
406 405 close_pr = request.POST.get('save_close')
407 406
408 407 allowed_to_change_status = self._get_is_allowed_change_status(pull_request)
409 408 if status and change_status and allowed_to_change_status:
410 409 _def = (_('status change -> %s')
411 410 % ChangesetStatus.get_status_lbl(status))
412 411 if close_pr:
413 412 _def = _('Closing with') + ' ' + _def
414 413 text = text or _def
415 414 comm = ChangesetCommentsModel().create(
416 415 text=text,
417 416 repo=c.rhodecode_db_repo.repo_id,
418 417 user=c.rhodecode_user.user_id,
419 418 pull_request=pull_request_id,
420 419 f_path=request.POST.get('f_path'),
421 420 line_no=request.POST.get('line'),
422 421 status_change=(ChangesetStatus.get_status_lbl(status)
423 422 if status and change_status
424 423 and allowed_to_change_status else None),
425 424 closing_pr=close_pr
426 425 )
427 426
428 427 action_logger(self.rhodecode_user,
429 428 'user_commented_pull_request:%s' % pull_request_id,
430 429 c.rhodecode_db_repo, self.ip_addr, self.sa)
431 430
432 431 if allowed_to_change_status:
433 432 # get status if set !
434 433 if status and change_status:
435 434 ChangesetStatusModel().set_status(
436 435 c.rhodecode_db_repo.repo_id,
437 436 status,
438 437 c.rhodecode_user.user_id,
439 438 comm,
440 439 pull_request=pull_request_id
441 440 )
442 441
443 442 if close_pr:
444 443 if status in ['rejected', 'approved']:
445 444 PullRequestModel().close_pull_request(pull_request_id)
446 445 action_logger(self.rhodecode_user,
447 446 'user_closed_pull_request:%s' % pull_request_id,
448 447 c.rhodecode_db_repo, self.ip_addr, self.sa)
449 448 else:
450 449 h.flash(_('Closing pull request on other statuses than '
451 450 'rejected or approved forbidden'),
452 451 category='warning')
453 452
454 453 Session().commit()
455 454
456 455 if not request.environ.get('HTTP_X_PARTIAL_XHR'):
457 456 return redirect(h.url('pullrequest_show', repo_name=repo_name,
458 457 pull_request_id=pull_request_id))
459 458
460 459 data = {
461 460 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
462 461 }
463 462 if comm:
464 463 c.co = comm
465 464 data.update(comm.get_dict())
466 465 data.update({'rendered_text':
467 466 render('changeset/changeset_comment_block.html')})
468 467
469 468 return data
470 469
471 470 @NotAnonymous()
472 471 @jsonify
473 472 def delete_comment(self, repo_name, comment_id):
474 473 co = ChangesetComment.get(comment_id)
475 474 if co.pull_request.is_closed():
476 475 #don't allow deleting comments on closed pull request
477 476 raise HTTPForbidden()
478 477
479 478 owner = co.author.user_id == c.rhodecode_user.user_id
480 479 if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
481 480 ChangesetCommentsModel().delete(comment=co)
482 481 Session().commit()
483 482 return True
484 483 else:
485 484 raise HTTPForbidden()
@@ -1,445 +1,445 b''
1 1 from rhodecode.tests import *
2 2 from rhodecode.model.repo import RepoModel
3 3 from rhodecode.model.meta import Session
4 4 from rhodecode.model.db import Repository
5 5 from rhodecode.model.scm import ScmModel
6 6 from rhodecode.lib.vcs.backends.base import EmptyChangeset
7 7
8 8
9 9 def _fork_repo(fork_name, vcs_type, parent=None):
10 10 if vcs_type =='hg':
11 11 _REPO = HG_REPO
12 12 elif vcs_type == 'git':
13 13 _REPO = GIT_REPO
14 14
15 15 if parent:
16 16 _REPO = parent
17 17
18 18 form_data = dict(
19 19 repo_name=fork_name,
20 20 repo_name_full=fork_name,
21 21 repo_group=None,
22 22 repo_type=vcs_type,
23 23 description='',
24 24 private=False,
25 25 copy_permissions=False,
26 26 landing_rev='tip',
27 27 update_after_clone=False,
28 28 fork_parent_id=Repository.get_by_repo_name(_REPO),
29 29 )
30 30 RepoModel().create_fork(form_data, cur_user=TEST_USER_ADMIN_LOGIN)
31 31
32 32 Session().commit()
33 33 return Repository.get_by_repo_name(fork_name)
34 34
35 35
36 36 def _commit_change(repo, filename, content, message, vcs_type, parent=None, newfile=False):
37 37 repo = Repository.get_by_repo_name(repo)
38 38 _cs = parent
39 39 if not parent:
40 40 _cs = EmptyChangeset(alias=vcs_type)
41 41
42 42 if newfile:
43 43 cs = ScmModel().create_node(
44 44 repo=repo.scm_instance, repo_name=repo.repo_name,
45 45 cs=_cs, user=TEST_USER_ADMIN_LOGIN,
46 46 author=TEST_USER_ADMIN_LOGIN,
47 47 message=message,
48 48 content=content,
49 49 f_path=filename
50 50 )
51 51 else:
52 52 cs = ScmModel().commit_change(
53 53 repo=repo.scm_instance, repo_name=repo.repo_name,
54 54 cs=parent, user=TEST_USER_ADMIN_LOGIN,
55 55 author=TEST_USER_ADMIN_LOGIN,
56 56 message=message,
57 57 content=content,
58 58 f_path=filename
59 59 )
60 60 return cs
61 61
62 62
63 63 class TestCompareController(TestController):
64 64
65 65 def setUp(self):
66 66 self.r1_id = None
67 67 self.r2_id = None
68 68
69 69 def tearDown(self):
70 70 if self.r2_id:
71 71 RepoModel().delete(self.r2_id)
72 72 if self.r1_id:
73 73 RepoModel().delete(self.r1_id)
74 74 Session().commit()
75 75 Session.remove()
76 76
77 77 def test_compare_forks_on_branch_extra_commits_hg(self):
78 78 self.log_user()
79 79 repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
80 80 description='diff-test',
81 81 owner=TEST_USER_ADMIN_LOGIN)
82 82 Session().commit()
83 83 self.r1_id = repo1.repo_id
84 84 #commit something !
85 85 cs0 = _commit_change(repo1.repo_name, filename='file1', content='line1\n',
86 86 message='commit1', vcs_type='hg', parent=None, newfile=True)
87 87
88 88 #fork this repo
89 89 repo2 = _fork_repo('one-fork', 'hg', parent='one')
90 90 self.r2_id = repo2.repo_id
91 91
92 92 #add two extra commit into fork
93 93 cs1 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\n',
94 94 message='commit2', vcs_type='hg', parent=cs0)
95 95
96 96 cs2 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\nline3\n',
97 97 message='commit3', vcs_type='hg', parent=cs1)
98 98
99 99 rev1 = 'default'
100 100 rev2 = 'default'
101 101
102 102 response = self.app.get(url(controller='compare', action='index',
103 103 repo_name=repo1.repo_name,
104 104 org_ref_type="branch",
105 105 org_ref=rev2,
106 106 other_repo=repo2.repo_name,
107 107 other_ref_type="branch",
108 108 other_ref=rev1,
109 109 ))
110 110
111 111 response.mustcontain('%s@%s -&gt; %s@%s' % (repo1.repo_name, rev2, repo2.repo_name, rev1))
112 112 response.mustcontain("""Showing 2 commits""")
113 113 response.mustcontain("""1 file changed with 2 insertions and 0 deletions""")
114 114
115 115 response.mustcontain("""<div class="message tooltip" title="commit2" style="white-space:normal">commit2</div>""")
116 116 response.mustcontain("""<div class="message tooltip" title="commit3" style="white-space:normal">commit3</div>""")
117 117
118 118 response.mustcontain("""<a href="/%s/changeset/%s">r1:%s</a>""" % (repo2.repo_name, cs1.raw_id, cs1.short_id))
119 119 response.mustcontain("""<a href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id))
120 120 ## files
121 121 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo1.repo_name, rev2, rev1, repo2.repo_name))
122 122 #swap
123 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?as_form=None&amp;other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
123 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
124 124
125 125 def test_compare_forks_on_branch_extra_commits_origin_has_incomming_hg(self):
126 126 self.log_user()
127 127
128 128 repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
129 129 description='diff-test',
130 130 owner=TEST_USER_ADMIN_LOGIN)
131 131 Session().commit()
132 132 self.r1_id = repo1.repo_id
133 133
134 134 #commit something !
135 135 cs0 = _commit_change(repo1.repo_name, filename='file1', content='line1\n',
136 136 message='commit1', vcs_type='hg', parent=None, newfile=True)
137 137
138 138 #fork this repo
139 139 repo2 = _fork_repo('one-fork', 'hg', parent='one')
140 140 self.r2_id = repo2.repo_id
141 141
142 142 #now commit something to origin repo
143 143 cs1_prim = _commit_change(repo1.repo_name, filename='file2', content='line1file2\n',
144 144 message='commit2', vcs_type='hg', parent=cs0, newfile=True)
145 145
146 146 #add two extra commit into fork
147 147 cs1 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\n',
148 148 message='commit2', vcs_type='hg', parent=cs0)
149 149
150 150 cs2 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\nline3\n',
151 151 message='commit3', vcs_type='hg', parent=cs1)
152 152
153 153 rev1 = 'default'
154 154 rev2 = 'default'
155 155
156 156 response = self.app.get(url(controller='compare', action='index',
157 157 repo_name=repo1.repo_name,
158 158 org_ref_type="branch",
159 159 org_ref=rev2,
160 160 other_repo=repo2.repo_name,
161 161 other_ref_type="branch",
162 162 other_ref=rev1,
163 163 ))
164 164 response.mustcontain('%s@%s -&gt; %s@%s' % (repo1.repo_name, rev2, repo2.repo_name, rev1))
165 165 response.mustcontain("""Showing 2 commits""")
166 166 response.mustcontain("""1 file changed with 2 insertions and 0 deletions""")
167 167
168 168 response.mustcontain("""<div class="message tooltip" title="commit2" style="white-space:normal">commit2</div>""")
169 169 response.mustcontain("""<div class="message tooltip" title="commit3" style="white-space:normal">commit3</div>""")
170 170
171 171 response.mustcontain("""<a href="/%s/changeset/%s">r1:%s</a>""" % (repo2.repo_name, cs1.raw_id, cs1.short_id))
172 172 response.mustcontain("""<a href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id))
173 173 ## files
174 174 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo1.repo_name, rev2, rev1, repo2.repo_name))
175 175 #swap
176 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?as_form=None&amp;other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
176 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
177 177
178 178 def test_compare_cherry_pick_changesets_from_bottom(self):
179 179
180 180 # repo1:
181 181 # cs0:
182 182 # cs1:
183 183 # repo1-fork- in which we will cherry pick bottom changesets
184 184 # cs0:
185 185 # cs1:
186 186 # cs2: x
187 187 # cs3: x
188 188 # cs4: x
189 189 # cs5:
190 190 #make repo1, and cs1+cs2
191 191 self.log_user()
192 192
193 193 repo1 = RepoModel().create_repo(repo_name='repo1', repo_type='hg',
194 194 description='diff-test',
195 195 owner=TEST_USER_ADMIN_LOGIN)
196 196 Session().commit()
197 197 self.r1_id = repo1.repo_id
198 198
199 199 #commit something !
200 200 cs0 = _commit_change(repo1.repo_name, filename='file1', content='line1\n',
201 201 message='commit1', vcs_type='hg', parent=None,
202 202 newfile=True)
203 203 cs1 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\n',
204 204 message='commit2', vcs_type='hg', parent=cs0)
205 205 #fork this repo
206 206 repo2 = _fork_repo('repo1-fork', 'hg', parent='repo1')
207 207 self.r2_id = repo2.repo_id
208 208 #now make cs3-6
209 209 cs2 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\nline3\n',
210 210 message='commit3', vcs_type='hg', parent=cs1)
211 211 cs3 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\nline3\nline4\n',
212 212 message='commit4', vcs_type='hg', parent=cs2)
213 213 cs4 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\nline3\nline4\nline5\n',
214 214 message='commit5', vcs_type='hg', parent=cs3)
215 215 cs5 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\nline3\nline4\nline5\nline6\n',
216 216 message='commit6', vcs_type='hg', parent=cs4)
217 217
218 218 rev1 = 'tip'
219 219 rev2 = 'tip'
220 220
221 221 response = self.app.get(url(controller='compare', action='index',
222 222 repo_name=repo2.repo_name,
223 223 org_ref_type="tag",
224 224 org_ref=rev1,
225 225 other_repo=repo1.repo_name,
226 226 other_ref_type="tag",
227 227 other_ref=rev2,
228 228 rev_start=cs2.raw_id,
229 229 rev_end=cs4.raw_id,
230 230 ))
231 231 response.mustcontain('%s@%s -&gt; %s@%s' % (repo2.repo_name, cs2.short_id, repo1.repo_name, cs4.short_id))
232 232 response.mustcontain("""Showing 3 commits""")
233 233 response.mustcontain("""1 file changed with 3 insertions and 0 deletions""")
234 234
235 235 response.mustcontain("""<div class="message tooltip" title="commit3" style="white-space:normal">commit3</div>""")
236 236 response.mustcontain("""<div class="message tooltip" title="commit4" style="white-space:normal">commit4</div>""")
237 237 response.mustcontain("""<div class="message tooltip" title="commit5" style="white-space:normal">commit5</div>""")
238 238
239 239 response.mustcontain("""<a href="/%s/changeset/%s">r2:%s</a>""" % (repo1.repo_name, cs2.raw_id, cs2.short_id))
240 240 response.mustcontain("""<a href="/%s/changeset/%s">r3:%s</a>""" % (repo1.repo_name, cs3.raw_id, cs3.short_id))
241 241 response.mustcontain("""<a href="/%s/changeset/%s">r4:%s</a>""" % (repo1.repo_name, cs4.raw_id, cs4.short_id))
242 242 ## files
243 243 response.mustcontain("""#C--826e8142e6ba">file1</a>""")
244 244
245 245 def test_compare_cherry_pick_changesets_from_top(self):
246 246 # repo1:
247 247 # cs0:
248 248 # cs1:
249 249 # repo1-fork- in which we will cherry pick bottom changesets
250 250 # cs0:
251 251 # cs1:
252 252 # cs2:
253 253 # cs3: x
254 254 # cs4: x
255 255 # cs5: x
256 256 #
257 257 #make repo1, and cs1+cs2
258 258 self.log_user()
259 259 repo1 = RepoModel().create_repo(repo_name='repo1', repo_type='hg',
260 260 description='diff-test',
261 261 owner=TEST_USER_ADMIN_LOGIN)
262 262 Session().commit()
263 263 self.r1_id = repo1.repo_id
264 264
265 265 #commit something !
266 266 cs0 = _commit_change(repo1.repo_name, filename='file1', content='line1\n',
267 267 message='commit1', vcs_type='hg', parent=None,
268 268 newfile=True)
269 269 cs1 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\n',
270 270 message='commit2', vcs_type='hg', parent=cs0)
271 271 #fork this repo
272 272 repo2 = _fork_repo('repo1-fork', 'hg', parent='repo1')
273 273 self.r2_id = repo2.repo_id
274 274 #now make cs3-6
275 275 cs2 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\nline3\n',
276 276 message='commit3', vcs_type='hg', parent=cs1)
277 277 cs3 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\nline3\nline4\n',
278 278 message='commit4', vcs_type='hg', parent=cs2)
279 279 cs4 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\nline3\nline4\nline5\n',
280 280 message='commit5', vcs_type='hg', parent=cs3)
281 281 cs5 = _commit_change(repo1.repo_name, filename='file1', content='line1\nline2\nline3\nline4\nline5\nline6\n',
282 282 message='commit6', vcs_type='hg', parent=cs4)
283 283 rev1 = 'tip'
284 284 rev2 = 'tip'
285 285
286 286 response = self.app.get(url(controller='compare', action='index',
287 287 repo_name=repo2.repo_name,
288 288 org_ref_type="tag",
289 289 org_ref=rev1,
290 290 other_repo=repo1.repo_name,
291 291 other_ref_type="tag",
292 292 other_ref=rev2,
293 293 rev_start=cs3.raw_id,
294 294 rev_end=cs5.raw_id,
295 295 ))
296 296
297 297 response.mustcontain('%s@%s -&gt; %s@%s' % (repo2.repo_name, cs3.short_id, repo1.repo_name, cs5.short_id))
298 298 response.mustcontain("""Showing 3 commits""")
299 299 response.mustcontain("""1 file changed with 3 insertions and 0 deletions""")
300 300
301 301 response.mustcontain("""<div class="message tooltip" title="commit4" style="white-space:normal">commit4</div>""")
302 302 response.mustcontain("""<div class="message tooltip" title="commit5" style="white-space:normal">commit5</div>""")
303 303 response.mustcontain("""<div class="message tooltip" title="commit6" style="white-space:normal">commit6</div>""")
304 304
305 305 response.mustcontain("""<a href="/%s/changeset/%s">r3:%s</a>""" % (repo1.repo_name, cs3.raw_id, cs3.short_id))
306 306 response.mustcontain("""<a href="/%s/changeset/%s">r4:%s</a>""" % (repo1.repo_name, cs4.raw_id, cs4.short_id))
307 307 response.mustcontain("""<a href="/%s/changeset/%s">r5:%s</a>""" % (repo1.repo_name, cs5.raw_id, cs5.short_id))
308 308 ## files
309 309 response.mustcontain("""#C--826e8142e6ba">file1</a>""")
310 310
311 311 def test_compare_cherry_pick_changeset_mixed_branches(self):
312 312 """
313 313
314 314 """
315 315 pass
316 316 #TODO write this tastecase
317 317
318 318 def test_compare_remote_branches_hg(self):
319 319 self.log_user()
320 320
321 321 repo2 = _fork_repo(HG_FORK, 'hg')
322 322 self.r2_id = repo2.repo_id
323 323 rev1 = '56349e29c2af'
324 324 rev2 = '7d4bc8ec6be5'
325 325
326 326 response = self.app.get(url(controller='compare', action='index',
327 327 repo_name=HG_REPO,
328 328 org_ref_type="rev",
329 329 org_ref=rev1,
330 330 other_ref_type="rev",
331 331 other_ref=rev2,
332 332 other_repo=HG_FORK,
333 333 ))
334 334 response.mustcontain('%s@%s -&gt; %s@%s' % (HG_REPO, rev1, HG_FORK, rev2))
335 335 ## outgoing changesets between those revisions
336 336
337 337 response.mustcontain("""<a href="/%s/changeset/2dda4e345facb0ccff1a191052dd1606dba6781d">r4:2dda4e345fac</a>""" % (HG_FORK))
338 338 response.mustcontain("""<a href="/%s/changeset/6fff84722075f1607a30f436523403845f84cd9e">r5:6fff84722075</a>""" % (HG_FORK))
339 339 response.mustcontain("""<a href="/%s/changeset/7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7">r6:%s</a>""" % (HG_FORK, rev2))
340 340
341 341 ## files
342 342 response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s?other_repo=%s#C--9c390eb52cd6">vcs/backends/hg.py</a>""" % (HG_REPO, rev1, rev2, HG_FORK))
343 343 response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s?other_repo=%s#C--41b41c1f2796">vcs/backends/__init__.py</a>""" % (HG_REPO, rev1, rev2, HG_FORK))
344 344 response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s?other_repo=%s#C--2f574d260608">vcs/backends/base.py</a>""" % (HG_REPO, rev1, rev2, HG_FORK))
345 345
346 346 def test_org_repo_new_commits_after_forking_simple_diff(self):
347 347 self.log_user()
348 348
349 349 repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
350 350 description='diff-test',
351 351 owner=TEST_USER_ADMIN_LOGIN)
352 352
353 353 Session().commit()
354 354 self.r1_id = repo1.repo_id
355 355 r1_name = repo1.repo_name
356 356
357 357 #commit something initially !
358 358 cs0 = ScmModel().create_node(
359 359 repo=repo1.scm_instance, repo_name=r1_name,
360 360 cs=EmptyChangeset(alias='hg'), user=TEST_USER_ADMIN_LOGIN,
361 361 author=TEST_USER_ADMIN_LOGIN,
362 362 message='commit1',
363 363 content='line1',
364 364 f_path='file1'
365 365 )
366 366 Session().commit()
367 367 self.assertEqual(repo1.scm_instance.revisions, [cs0.raw_id])
368 368 #fork the repo1
369 369 repo2 = RepoModel().create_repo(repo_name='one-fork', repo_type='hg',
370 370 description='compare-test',
371 371 clone_uri=repo1.repo_full_path,
372 372 owner=TEST_USER_ADMIN_LOGIN, fork_of='one')
373 373 Session().commit()
374 374 self.assertEqual(repo2.scm_instance.revisions, [cs0.raw_id])
375 375 self.r2_id = repo2.repo_id
376 376 r2_name = repo2.repo_name
377 377
378 378 #make 3 new commits in fork
379 379 cs1 = ScmModel().create_node(
380 380 repo=repo2.scm_instance, repo_name=r2_name,
381 381 cs=repo2.scm_instance[-1], user=TEST_USER_ADMIN_LOGIN,
382 382 author=TEST_USER_ADMIN_LOGIN,
383 383 message='commit1-fork',
384 384 content='file1-line1-from-fork',
385 385 f_path='file1-fork'
386 386 )
387 387 cs2 = ScmModel().create_node(
388 388 repo=repo2.scm_instance, repo_name=r2_name,
389 389 cs=cs1, user=TEST_USER_ADMIN_LOGIN,
390 390 author=TEST_USER_ADMIN_LOGIN,
391 391 message='commit2-fork',
392 392 content='file2-line1-from-fork',
393 393 f_path='file2-fork'
394 394 )
395 395 cs3 = ScmModel().create_node(
396 396 repo=repo2.scm_instance, repo_name=r2_name,
397 397 cs=cs2, user=TEST_USER_ADMIN_LOGIN,
398 398 author=TEST_USER_ADMIN_LOGIN,
399 399 message='commit3-fork',
400 400 content='file3-line1-from-fork',
401 401 f_path='file3-fork'
402 402 )
403 403
404 404 #compare !
405 405 rev1 = 'default'
406 406 rev2 = 'default'
407 407
408 408 response = self.app.get(url(controller='compare', action='index',
409 409 repo_name=r2_name,
410 410 org_ref_type="branch",
411 411 org_ref=rev1,
412 412 other_ref_type="branch",
413 413 other_ref=rev2,
414 414 other_repo=r1_name,
415 415 ))
416 416 response.mustcontain('%s@%s -&gt; %s@%s' % (r2_name, rev1, r1_name, rev2))
417 417 response.mustcontain('No files')
418 418 response.mustcontain('No changesets')
419 419
420 420 #add new commit into parent !
421 421 cs0 = ScmModel().create_node(
422 422 repo=repo1.scm_instance, repo_name=r1_name,
423 423 cs=EmptyChangeset(alias='hg'), user=TEST_USER_ADMIN_LOGIN,
424 424 author=TEST_USER_ADMIN_LOGIN,
425 425 message='commit2-parent',
426 426 content='line1-added-after-fork',
427 427 f_path='file2'
428 428 )
429 429 #compare !
430 430 rev1 = 'default'
431 431 rev2 = 'default'
432 432 response = self.app.get(url(controller='compare', action='index',
433 433 repo_name=r2_name,
434 434 org_ref_type="branch",
435 435 org_ref=rev1,
436 436 other_ref_type="branch",
437 437 other_ref=rev2,
438 438 other_repo=r1_name,
439 439 ))
440 440
441 441 response.mustcontain('%s@%s -&gt; %s@%s' % (r2_name, rev1, r1_name, rev2))
442 442
443 443 response.mustcontain("""commit2-parent""")
444 444 response.mustcontain("""1 file changed with 1 insertions and 0 deletions""")
445 445 response.mustcontain("""line1-added-after-fork""")
General Comments 0
You need to be logged in to leave comments. Login now