Show More
@@ -20,18 +20,23 b'' | |||||
20 |
|
20 | |||
21 | import logging |
|
21 | import logging | |
22 |
|
22 | |||
|
23 | import collections | |||
|
24 | from pyramid.httpexceptions import HTTPFound, HTTPNotFound | |||
23 | from pyramid.view import view_config |
|
25 | from pyramid.view import view_config | |
24 |
|
26 | |||
25 | from rhodecode.apps._base import RepoAppView, DataGridAppView |
|
27 | from rhodecode.apps._base import RepoAppView, DataGridAppView | |
26 | from rhodecode.lib import helpers as h |
|
28 | from rhodecode.lib import helpers as h, diffs, codeblocks | |
27 | from rhodecode.lib import audit_logger |
|
|||
28 | from rhodecode.lib.auth import ( |
|
29 | from rhodecode.lib.auth import ( | |
29 | LoginRequired, HasRepoPermissionAnyDecorator) |
|
30 | LoginRequired, HasRepoPermissionAnyDecorator) | |
30 | from rhodecode.lib.utils import PartialRenderer |
|
31 | from rhodecode.lib.utils import PartialRenderer | |
31 | from rhodecode.lib.utils2 import str2bool |
|
32 | from rhodecode.lib.utils2 import str2bool, safe_int, safe_str | |
|
33 | from rhodecode.lib.vcs.backends.base import EmptyCommit | |||
|
34 | from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError, \ | |||
|
35 | RepositoryRequirementError, NodeDoesNotExistError | |||
32 | from rhodecode.model.comment import CommentsModel |
|
36 | from rhodecode.model.comment import CommentsModel | |
33 | from rhodecode.model.db import PullRequest |
|
37 | from rhodecode.model.db import PullRequest, PullRequestVersion, \ | |
34 | from rhodecode.model.pull_request import PullRequestModel |
|
38 | ChangesetComment, ChangesetStatus | |
|
39 | from rhodecode.model.pull_request import PullRequestModel, MergeCheck | |||
35 |
|
40 | |||
36 | log = logging.getLogger(__name__) |
|
41 | log = logging.getLogger(__name__) | |
37 |
|
42 | |||
@@ -39,11 +44,11 b' log = logging.getLogger(__name__)' | |||||
39 | class RepoPullRequestsView(RepoAppView, DataGridAppView): |
|
44 | class RepoPullRequestsView(RepoAppView, DataGridAppView): | |
40 |
|
45 | |||
41 | def load_default_context(self): |
|
46 | def load_default_context(self): | |
42 | c = self._get_local_tmpl_context() |
|
47 | c = self._get_local_tmpl_context(include_app_defaults=True) | |
43 |
|
||||
44 | # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead |
|
48 | # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead | |
45 | c.repo_info = self.db_repo |
|
49 | c.repo_info = self.db_repo | |
46 |
|
50 | c.REVIEW_STATUS_APPROVED = ChangesetStatus.STATUS_APPROVED | ||
|
51 | c.REVIEW_STATUS_REJECTED = ChangesetStatus.STATUS_REJECTED | |||
47 | self._register_global_c(c) |
|
52 | self._register_global_c(c) | |
48 | return c |
|
53 | return c | |
49 |
|
54 | |||
@@ -182,3 +187,398 b' class RepoPullRequestsView(RepoAppView, ' | |||||
182 | filter_type=filter_type, opened_by=opened_by, statuses=statuses) |
|
187 | filter_type=filter_type, opened_by=opened_by, statuses=statuses) | |
183 |
|
188 | |||
184 | return data |
|
189 | return data | |
|
190 | ||||
|
191 | def _get_pr_version(self, pull_request_id, version=None): | |||
|
192 | pull_request_id = safe_int(pull_request_id) | |||
|
193 | at_version = None | |||
|
194 | ||||
|
195 | if version and version == 'latest': | |||
|
196 | pull_request_ver = PullRequest.get(pull_request_id) | |||
|
197 | pull_request_obj = pull_request_ver | |||
|
198 | _org_pull_request_obj = pull_request_obj | |||
|
199 | at_version = 'latest' | |||
|
200 | elif version: | |||
|
201 | pull_request_ver = PullRequestVersion.get_or_404(version) | |||
|
202 | pull_request_obj = pull_request_ver | |||
|
203 | _org_pull_request_obj = pull_request_ver.pull_request | |||
|
204 | at_version = pull_request_ver.pull_request_version_id | |||
|
205 | else: | |||
|
206 | _org_pull_request_obj = pull_request_obj = PullRequest.get_or_404( | |||
|
207 | pull_request_id) | |||
|
208 | ||||
|
209 | pull_request_display_obj = PullRequest.get_pr_display_object( | |||
|
210 | pull_request_obj, _org_pull_request_obj) | |||
|
211 | ||||
|
212 | return _org_pull_request_obj, pull_request_obj, \ | |||
|
213 | pull_request_display_obj, at_version | |||
|
214 | ||||
|
215 | def _get_diffset(self, source_repo_name, source_repo, | |||
|
216 | source_ref_id, target_ref_id, | |||
|
217 | target_commit, source_commit, diff_limit, fulldiff, | |||
|
218 | file_limit, display_inline_comments): | |||
|
219 | ||||
|
220 | vcs_diff = PullRequestModel().get_diff( | |||
|
221 | source_repo, source_ref_id, target_ref_id) | |||
|
222 | ||||
|
223 | diff_processor = diffs.DiffProcessor( | |||
|
224 | vcs_diff, format='newdiff', diff_limit=diff_limit, | |||
|
225 | file_limit=file_limit, show_full_diff=fulldiff) | |||
|
226 | ||||
|
227 | _parsed = diff_processor.prepare() | |||
|
228 | ||||
|
229 | def _node_getter(commit): | |||
|
230 | def get_node(fname): | |||
|
231 | try: | |||
|
232 | return commit.get_node(fname) | |||
|
233 | except NodeDoesNotExistError: | |||
|
234 | return None | |||
|
235 | ||||
|
236 | return get_node | |||
|
237 | ||||
|
238 | diffset = codeblocks.DiffSet( | |||
|
239 | repo_name=self.db_repo_name, | |||
|
240 | source_repo_name=source_repo_name, | |||
|
241 | source_node_getter=_node_getter(target_commit), | |||
|
242 | target_node_getter=_node_getter(source_commit), | |||
|
243 | comments=display_inline_comments | |||
|
244 | ) | |||
|
245 | diffset = diffset.render_patchset( | |||
|
246 | _parsed, target_commit.raw_id, source_commit.raw_id) | |||
|
247 | ||||
|
248 | return diffset | |||
|
249 | ||||
|
250 | @LoginRequired() | |||
|
251 | @HasRepoPermissionAnyDecorator( | |||
|
252 | 'repository.read', 'repository.write', 'repository.admin') | |||
|
253 | # @view_config( | |||
|
254 | # route_name='pullrequest_show', request_method='GET', | |||
|
255 | # renderer='rhodecode:templates/pullrequests/pullrequest_show.mako') | |||
|
256 | def pull_request_show(self): | |||
|
257 | pull_request_id = safe_int( | |||
|
258 | self.request.matchdict.get('pull_request_id')) | |||
|
259 | c = self.load_default_context() | |||
|
260 | ||||
|
261 | version = self.request.GET.get('version') | |||
|
262 | from_version = self.request.GET.get('from_version') or version | |||
|
263 | merge_checks = self.request.GET.get('merge_checks') | |||
|
264 | c.fulldiff = str2bool(self.request.GET.get('fulldiff')) | |||
|
265 | ||||
|
266 | (pull_request_latest, | |||
|
267 | pull_request_at_ver, | |||
|
268 | pull_request_display_obj, | |||
|
269 | at_version) = self._get_pr_version( | |||
|
270 | pull_request_id, version=version) | |||
|
271 | pr_closed = pull_request_latest.is_closed() | |||
|
272 | ||||
|
273 | if pr_closed and (version or from_version): | |||
|
274 | # not allow to browse versions | |||
|
275 | raise HTTPFound(h.route_path( | |||
|
276 | 'pullrequest_show', repo_name=self.db_repo_name, | |||
|
277 | pull_request_id=pull_request_id)) | |||
|
278 | ||||
|
279 | versions = pull_request_display_obj.versions() | |||
|
280 | ||||
|
281 | c.at_version = at_version | |||
|
282 | c.at_version_num = (at_version | |||
|
283 | if at_version and at_version != 'latest' | |||
|
284 | else None) | |||
|
285 | c.at_version_pos = ChangesetComment.get_index_from_version( | |||
|
286 | c.at_version_num, versions) | |||
|
287 | ||||
|
288 | (prev_pull_request_latest, | |||
|
289 | prev_pull_request_at_ver, | |||
|
290 | prev_pull_request_display_obj, | |||
|
291 | prev_at_version) = self._get_pr_version( | |||
|
292 | pull_request_id, version=from_version) | |||
|
293 | ||||
|
294 | c.from_version = prev_at_version | |||
|
295 | c.from_version_num = (prev_at_version | |||
|
296 | if prev_at_version and prev_at_version != 'latest' | |||
|
297 | else None) | |||
|
298 | c.from_version_pos = ChangesetComment.get_index_from_version( | |||
|
299 | c.from_version_num, versions) | |||
|
300 | ||||
|
301 | # define if we're in COMPARE mode or VIEW at version mode | |||
|
302 | compare = at_version != prev_at_version | |||
|
303 | ||||
|
304 | # pull_requests repo_name we opened it against | |||
|
305 | # ie. target_repo must match | |||
|
306 | if self.db_repo_name != pull_request_at_ver.target_repo.repo_name: | |||
|
307 | raise HTTPNotFound() | |||
|
308 | ||||
|
309 | c.shadow_clone_url = PullRequestModel().get_shadow_clone_url( | |||
|
310 | pull_request_at_ver) | |||
|
311 | ||||
|
312 | c.pull_request = pull_request_display_obj | |||
|
313 | c.pull_request_latest = pull_request_latest | |||
|
314 | ||||
|
315 | if compare or (at_version and not at_version == 'latest'): | |||
|
316 | c.allowed_to_change_status = False | |||
|
317 | c.allowed_to_update = False | |||
|
318 | c.allowed_to_merge = False | |||
|
319 | c.allowed_to_delete = False | |||
|
320 | c.allowed_to_comment = False | |||
|
321 | c.allowed_to_close = False | |||
|
322 | else: | |||
|
323 | can_change_status = PullRequestModel().check_user_change_status( | |||
|
324 | pull_request_at_ver, self._rhodecode_user) | |||
|
325 | c.allowed_to_change_status = can_change_status and not pr_closed | |||
|
326 | ||||
|
327 | c.allowed_to_update = PullRequestModel().check_user_update( | |||
|
328 | pull_request_latest, self._rhodecode_user) and not pr_closed | |||
|
329 | c.allowed_to_merge = PullRequestModel().check_user_merge( | |||
|
330 | pull_request_latest, self._rhodecode_user) and not pr_closed | |||
|
331 | c.allowed_to_delete = PullRequestModel().check_user_delete( | |||
|
332 | pull_request_latest, self._rhodecode_user) and not pr_closed | |||
|
333 | c.allowed_to_comment = not pr_closed | |||
|
334 | c.allowed_to_close = c.allowed_to_merge and not pr_closed | |||
|
335 | ||||
|
336 | c.forbid_adding_reviewers = False | |||
|
337 | c.forbid_author_to_review = False | |||
|
338 | c.forbid_commit_author_to_review = False | |||
|
339 | ||||
|
340 | if pull_request_latest.reviewer_data and \ | |||
|
341 | 'rules' in pull_request_latest.reviewer_data: | |||
|
342 | rules = pull_request_latest.reviewer_data['rules'] or {} | |||
|
343 | try: | |||
|
344 | c.forbid_adding_reviewers = rules.get( | |||
|
345 | 'forbid_adding_reviewers') | |||
|
346 | c.forbid_author_to_review = rules.get( | |||
|
347 | 'forbid_author_to_review') | |||
|
348 | c.forbid_commit_author_to_review = rules.get( | |||
|
349 | 'forbid_commit_author_to_review') | |||
|
350 | except Exception: | |||
|
351 | pass | |||
|
352 | ||||
|
353 | # check merge capabilities | |||
|
354 | _merge_check = MergeCheck.validate( | |||
|
355 | pull_request_latest, user=self._rhodecode_user) | |||
|
356 | c.pr_merge_errors = _merge_check.error_details | |||
|
357 | c.pr_merge_possible = not _merge_check.failed | |||
|
358 | c.pr_merge_message = _merge_check.merge_msg | |||
|
359 | ||||
|
360 | c.pull_request_review_status = _merge_check.review_status | |||
|
361 | if merge_checks: | |||
|
362 | self.request.override_renderer = \ | |||
|
363 | 'rhodecode:templates/pullrequests/pullrequest_merge_checks.mako' | |||
|
364 | return self._get_template_context(c) | |||
|
365 | ||||
|
366 | comments_model = CommentsModel() | |||
|
367 | ||||
|
368 | # reviewers and statuses | |||
|
369 | c.pull_request_reviewers = pull_request_at_ver.reviewers_statuses() | |||
|
370 | allowed_reviewers = [x[0].user_id for x in c.pull_request_reviewers] | |||
|
371 | ||||
|
372 | # GENERAL COMMENTS with versions # | |||
|
373 | q = comments_model._all_general_comments_of_pull_request(pull_request_latest) | |||
|
374 | q = q.order_by(ChangesetComment.comment_id.asc()) | |||
|
375 | general_comments = q | |||
|
376 | ||||
|
377 | # pick comments we want to render at current version | |||
|
378 | c.comment_versions = comments_model.aggregate_comments( | |||
|
379 | general_comments, versions, c.at_version_num) | |||
|
380 | c.comments = c.comment_versions[c.at_version_num]['until'] | |||
|
381 | ||||
|
382 | # INLINE COMMENTS with versions # | |||
|
383 | q = comments_model._all_inline_comments_of_pull_request(pull_request_latest) | |||
|
384 | q = q.order_by(ChangesetComment.comment_id.asc()) | |||
|
385 | inline_comments = q | |||
|
386 | ||||
|
387 | c.inline_versions = comments_model.aggregate_comments( | |||
|
388 | inline_comments, versions, c.at_version_num, inline=True) | |||
|
389 | ||||
|
390 | # inject latest version | |||
|
391 | latest_ver = PullRequest.get_pr_display_object( | |||
|
392 | pull_request_latest, pull_request_latest) | |||
|
393 | ||||
|
394 | c.versions = versions + [latest_ver] | |||
|
395 | ||||
|
396 | # if we use version, then do not show later comments | |||
|
397 | # than current version | |||
|
398 | display_inline_comments = collections.defaultdict( | |||
|
399 | lambda: collections.defaultdict(list)) | |||
|
400 | for co in inline_comments: | |||
|
401 | if c.at_version_num: | |||
|
402 | # pick comments that are at least UPTO given version, so we | |||
|
403 | # don't render comments for higher version | |||
|
404 | should_render = co.pull_request_version_id and \ | |||
|
405 | co.pull_request_version_id <= c.at_version_num | |||
|
406 | else: | |||
|
407 | # showing all, for 'latest' | |||
|
408 | should_render = True | |||
|
409 | ||||
|
410 | if should_render: | |||
|
411 | display_inline_comments[co.f_path][co.line_no].append(co) | |||
|
412 | ||||
|
413 | # load diff data into template context, if we use compare mode then | |||
|
414 | # diff is calculated based on changes between versions of PR | |||
|
415 | ||||
|
416 | source_repo = pull_request_at_ver.source_repo | |||
|
417 | source_ref_id = pull_request_at_ver.source_ref_parts.commit_id | |||
|
418 | ||||
|
419 | target_repo = pull_request_at_ver.target_repo | |||
|
420 | target_ref_id = pull_request_at_ver.target_ref_parts.commit_id | |||
|
421 | ||||
|
422 | if compare: | |||
|
423 | # in compare switch the diff base to latest commit from prev version | |||
|
424 | target_ref_id = prev_pull_request_display_obj.revisions[0] | |||
|
425 | ||||
|
426 | # despite opening commits for bookmarks/branches/tags, we always | |||
|
427 | # convert this to rev to prevent changes after bookmark or branch change | |||
|
428 | c.source_ref_type = 'rev' | |||
|
429 | c.source_ref = source_ref_id | |||
|
430 | ||||
|
431 | c.target_ref_type = 'rev' | |||
|
432 | c.target_ref = target_ref_id | |||
|
433 | ||||
|
434 | c.source_repo = source_repo | |||
|
435 | c.target_repo = target_repo | |||
|
436 | ||||
|
437 | c.commit_ranges = [] | |||
|
438 | source_commit = EmptyCommit() | |||
|
439 | target_commit = EmptyCommit() | |||
|
440 | c.missing_requirements = False | |||
|
441 | ||||
|
442 | source_scm = source_repo.scm_instance() | |||
|
443 | target_scm = target_repo.scm_instance() | |||
|
444 | ||||
|
445 | # try first shadow repo, fallback to regular repo | |||
|
446 | try: | |||
|
447 | commits_source_repo = pull_request_latest.get_shadow_repo() | |||
|
448 | except Exception: | |||
|
449 | log.debug('Failed to get shadow repo', exc_info=True) | |||
|
450 | commits_source_repo = source_scm | |||
|
451 | ||||
|
452 | c.commits_source_repo = commits_source_repo | |||
|
453 | commit_cache = {} | |||
|
454 | try: | |||
|
455 | pre_load = ["author", "branch", "date", "message"] | |||
|
456 | show_revs = pull_request_at_ver.revisions | |||
|
457 | for rev in show_revs: | |||
|
458 | comm = commits_source_repo.get_commit( | |||
|
459 | commit_id=rev, pre_load=pre_load) | |||
|
460 | c.commit_ranges.append(comm) | |||
|
461 | commit_cache[comm.raw_id] = comm | |||
|
462 | ||||
|
463 | # Order here matters, we first need to get target, and then | |||
|
464 | # the source | |||
|
465 | target_commit = commits_source_repo.get_commit( | |||
|
466 | commit_id=safe_str(target_ref_id)) | |||
|
467 | ||||
|
468 | source_commit = commits_source_repo.get_commit( | |||
|
469 | commit_id=safe_str(source_ref_id)) | |||
|
470 | ||||
|
471 | except CommitDoesNotExistError: | |||
|
472 | log.warning( | |||
|
473 | 'Failed to get commit from `{}` repo'.format( | |||
|
474 | commits_source_repo), exc_info=True) | |||
|
475 | except RepositoryRequirementError: | |||
|
476 | log.warning( | |||
|
477 | 'Failed to get all required data from repo', exc_info=True) | |||
|
478 | c.missing_requirements = True | |||
|
479 | ||||
|
480 | c.ancestor = None # set it to None, to hide it from PR view | |||
|
481 | ||||
|
482 | try: | |||
|
483 | ancestor_id = source_scm.get_common_ancestor( | |||
|
484 | source_commit.raw_id, target_commit.raw_id, target_scm) | |||
|
485 | c.ancestor_commit = source_scm.get_commit(ancestor_id) | |||
|
486 | except Exception: | |||
|
487 | c.ancestor_commit = None | |||
|
488 | ||||
|
489 | c.statuses = source_repo.statuses( | |||
|
490 | [x.raw_id for x in c.commit_ranges]) | |||
|
491 | ||||
|
492 | # auto collapse if we have more than limit | |||
|
493 | collapse_limit = diffs.DiffProcessor._collapse_commits_over | |||
|
494 | c.collapse_all_commits = len(c.commit_ranges) > collapse_limit | |||
|
495 | c.compare_mode = compare | |||
|
496 | ||||
|
497 | # diff_limit is the old behavior, will cut off the whole diff | |||
|
498 | # if the limit is applied otherwise will just hide the | |||
|
499 | # big files from the front-end | |||
|
500 | diff_limit = c.visual.cut_off_limit_diff | |||
|
501 | file_limit = c.visual.cut_off_limit_file | |||
|
502 | ||||
|
503 | c.missing_commits = False | |||
|
504 | if (c.missing_requirements | |||
|
505 | or isinstance(source_commit, EmptyCommit) | |||
|
506 | or source_commit == target_commit): | |||
|
507 | ||||
|
508 | c.missing_commits = True | |||
|
509 | else: | |||
|
510 | ||||
|
511 | c.diffset = self._get_diffset( | |||
|
512 | c.source_repo.repo_name, commits_source_repo, | |||
|
513 | source_ref_id, target_ref_id, | |||
|
514 | target_commit, source_commit, | |||
|
515 | diff_limit, c.fulldiff, file_limit, display_inline_comments) | |||
|
516 | ||||
|
517 | c.limited_diff = c.diffset.limited_diff | |||
|
518 | ||||
|
519 | # calculate removed files that are bound to comments | |||
|
520 | comment_deleted_files = [ | |||
|
521 | fname for fname in display_inline_comments | |||
|
522 | if fname not in c.diffset.file_stats] | |||
|
523 | ||||
|
524 | c.deleted_files_comments = collections.defaultdict(dict) | |||
|
525 | for fname, per_line_comments in display_inline_comments.items(): | |||
|
526 | if fname in comment_deleted_files: | |||
|
527 | c.deleted_files_comments[fname]['stats'] = 0 | |||
|
528 | c.deleted_files_comments[fname]['comments'] = list() | |||
|
529 | for lno, comments in per_line_comments.items(): | |||
|
530 | c.deleted_files_comments[fname]['comments'].extend( | |||
|
531 | comments) | |||
|
532 | ||||
|
533 | # this is a hack to properly display links, when creating PR, the | |||
|
534 | # compare view and others uses different notation, and | |||
|
535 | # compare_commits.mako renders links based on the target_repo. | |||
|
536 | # We need to swap that here to generate it properly on the html side | |||
|
537 | c.target_repo = c.source_repo | |||
|
538 | ||||
|
539 | c.commit_statuses = ChangesetStatus.STATUSES | |||
|
540 | ||||
|
541 | c.show_version_changes = not pr_closed | |||
|
542 | if c.show_version_changes: | |||
|
543 | cur_obj = pull_request_at_ver | |||
|
544 | prev_obj = prev_pull_request_at_ver | |||
|
545 | ||||
|
546 | old_commit_ids = prev_obj.revisions | |||
|
547 | new_commit_ids = cur_obj.revisions | |||
|
548 | commit_changes = PullRequestModel()._calculate_commit_id_changes( | |||
|
549 | old_commit_ids, new_commit_ids) | |||
|
550 | c.commit_changes_summary = commit_changes | |||
|
551 | ||||
|
552 | # calculate the diff for commits between versions | |||
|
553 | c.commit_changes = [] | |||
|
554 | mark = lambda cs, fw: list( | |||
|
555 | h.itertools.izip_longest([], cs, fillvalue=fw)) | |||
|
556 | for c_type, raw_id in mark(commit_changes.added, 'a') \ | |||
|
557 | + mark(commit_changes.removed, 'r') \ | |||
|
558 | + mark(commit_changes.common, 'c'): | |||
|
559 | ||||
|
560 | if raw_id in commit_cache: | |||
|
561 | commit = commit_cache[raw_id] | |||
|
562 | else: | |||
|
563 | try: | |||
|
564 | commit = commits_source_repo.get_commit(raw_id) | |||
|
565 | except CommitDoesNotExistError: | |||
|
566 | # in case we fail extracting still use "dummy" commit | |||
|
567 | # for display in commit diff | |||
|
568 | commit = h.AttributeDict( | |||
|
569 | {'raw_id': raw_id, | |||
|
570 | 'message': 'EMPTY or MISSING COMMIT'}) | |||
|
571 | c.commit_changes.append([c_type, commit]) | |||
|
572 | ||||
|
573 | # current user review statuses for each version | |||
|
574 | c.review_versions = {} | |||
|
575 | if self._rhodecode_user.user_id in allowed_reviewers: | |||
|
576 | for co in general_comments: | |||
|
577 | if co.author.user_id == self._rhodecode_user.user_id: | |||
|
578 | # each comment has a status change | |||
|
579 | status = co.status_change | |||
|
580 | if status: | |||
|
581 | _ver_pr = status[0].comment.pull_request_version_id | |||
|
582 | c.review_versions[_ver_pr] = status[0] | |||
|
583 | ||||
|
584 | return self._get_template_context(c) |
@@ -282,7 +282,8 b' class PullrequestsController(BaseRepoCon' | |||||
282 | h.flash(msg, category='error') |
|
282 | h.flash(msg, category='error') | |
283 | return redirect(url('pullrequest_home', repo_name=repo_name)) |
|
283 | return redirect(url('pullrequest_home', repo_name=repo_name)) | |
284 |
|
284 | |||
285 | return redirect(url('pullrequest_show', repo_name=target_repo, |
|
285 | raise HTTPFound( | |
|
286 | h.route_path('pullrequest_show', repo_name=target_repo, | |||
286 |
|
|
287 | pull_request_id=pull_request.pull_request_id)) | |
287 |
|
288 | |||
288 | @LoginRequired() |
|
289 | @LoginRequired() | |
@@ -420,8 +421,8 b' class PullrequestsController(BaseRepoCon' | |||||
420 | scm=pull_request.target_repo.repo_type) |
|
421 | scm=pull_request.target_repo.repo_type) | |
421 | self._merge_pull_request(pull_request, user, extras) |
|
422 | self._merge_pull_request(pull_request, user, extras) | |
422 |
|
423 | |||
423 | return redirect(url( |
|
424 | raise HTTPFound( | |
424 | 'pullrequest_show', |
|
425 | h.route_path('pullrequest_show', | |
425 | repo_name=pull_request.target_repo.repo_name, |
|
426 | repo_name=pull_request.target_repo.repo_name, | |
426 | pull_request_id=pull_request.pull_request_id)) |
|
427 | pull_request_id=pull_request.pull_request_id)) | |
427 |
|
428 | |||
@@ -964,7 +965,9 b' class PullrequestsController(BaseRepoCon' | |||||
964 | Session().commit() |
|
965 | Session().commit() | |
965 |
|
966 | |||
966 | if not request.is_xhr: |
|
967 | if not request.is_xhr: | |
967 | return redirect(h.url('pullrequest_show', repo_name=repo_name, |
|
968 | raise HTTPFound( | |
|
969 | h.route_path('pullrequest_show', | |||
|
970 | repo_name=repo_name, | |||
968 |
|
|
971 | pull_request_id=pull_request_id)) | |
969 |
|
972 | |||
970 | data = { |
|
973 | data = { |
@@ -175,6 +175,7 b' class ActionParser(object):' | |||||
175 | return group_name |
|
175 | return group_name | |
176 |
|
176 | |||
177 | def get_pull_request(self): |
|
177 | def get_pull_request(self): | |
|
178 | from rhodecode.lib import helpers as h | |||
178 | pull_request_id = self.action_params |
|
179 | pull_request_id = self.action_params | |
179 | if self.is_deleted(): |
|
180 | if self.is_deleted(): | |
180 | repo_name = self.user_log.repository_name |
|
181 | repo_name = self.user_log.repository_name | |
@@ -182,7 +183,7 b' class ActionParser(object):' | |||||
182 | repo_name = self.user_log.repository.repo_name |
|
183 | repo_name = self.user_log.repository.repo_name | |
183 | return link_to( |
|
184 | return link_to( | |
184 | _('Pull request #%s') % pull_request_id, |
|
185 | _('Pull request #%s') % pull_request_id, | |
185 |
|
|
186 | h.route_path('pullrequest_show', repo_name=repo_name, | |
186 | pull_request_id=pull_request_id)) |
|
187 | pull_request_id=pull_request_id)) | |
187 |
|
188 | |||
188 | def get_archive_name(self): |
|
189 | def get_archive_name(self): |
@@ -330,6 +330,11 b' def attach_context_attributes(context, r' | |||||
330 |
|
330 | |||
331 | context.rhodecode_instanceid = config.get('instance_id') |
|
331 | context.rhodecode_instanceid = config.get('instance_id') | |
332 |
|
332 | |||
|
333 | context.visual.cut_off_limit_diff = safe_int( | |||
|
334 | config.get('cut_off_limit_diff')) | |||
|
335 | context.visual.cut_off_limit_file = safe_int( | |||
|
336 | config.get('cut_off_limit_file')) | |||
|
337 | ||||
333 | # AppEnlight |
|
338 | # AppEnlight | |
334 | context.appenlight_enabled = str2bool(config.get('appenlight', 'false')) |
|
339 | context.appenlight_enabled = str2bool(config.get('appenlight', 'false')) | |
335 | context.appenlight_api_public_key = config.get( |
|
340 | context.appenlight_api_public_key = config.get( |
@@ -438,8 +438,7 b' class CommentsModel(BaseModel):' | |||||
438 | pull_request_id=pull_request.pull_request_id, |
|
438 | pull_request_id=pull_request.pull_request_id, | |
439 | _anchor='comment-%s' % comment.comment_id) |
|
439 | _anchor='comment-%s' % comment.comment_id) | |
440 | else: |
|
440 | else: | |
441 | return request.route_url( |
|
441 | return request.route_url('pullrequest_show', | |
442 | 'pullrequest_show', |
|
|||
443 | repo_name=safe_str(pull_request.target_repo.repo_name), |
|
442 | repo_name=safe_str(pull_request.target_repo.repo_name), | |
444 | pull_request_id=pull_request.pull_request_id, |
|
443 | pull_request_id=pull_request.pull_request_id, | |
445 | _anchor='comment-%s' % comment.comment_id) |
|
444 | _anchor='comment-%s' % comment.comment_id) |
@@ -997,8 +997,7 b' class PullRequestModel(BaseModel):' | |||||
997 | 'pull_requests_global', |
|
997 | 'pull_requests_global', | |
998 | pull_request_id=pull_request.pull_request_id,) |
|
998 | pull_request_id=pull_request.pull_request_id,) | |
999 | else: |
|
999 | else: | |
1000 | return request.route_url( |
|
1000 | return request.route_url('pullrequest_show', | |
1001 | 'pullrequest_show', |
|
|||
1002 | repo_name=safe_str(pull_request.target_repo.repo_name), |
|
1001 | repo_name=safe_str(pull_request.target_repo.repo_name), | |
1003 | pull_request_id=pull_request.pull_request_id,) |
|
1002 | pull_request_id=pull_request.pull_request_id,) | |
1004 |
|
1003 | |||
@@ -1027,11 +1026,9 b' class PullRequestModel(BaseModel):' | |||||
1027 | pr_source_repo = pull_request_obj.source_repo |
|
1026 | pr_source_repo = pull_request_obj.source_repo | |
1028 | pr_target_repo = pull_request_obj.target_repo |
|
1027 | pr_target_repo = pull_request_obj.target_repo | |
1029 |
|
1028 | |||
1030 | pr_url = h.url( |
|
1029 | pr_url = h.route_url('pullrequest_show', | |
1031 | 'pullrequest_show', |
|
|||
1032 | repo_name=pr_target_repo.repo_name, |
|
1030 | repo_name=pr_target_repo.repo_name, | |
1033 | pull_request_id=pull_request_obj.pull_request_id, |
|
1031 | pull_request_id=pull_request_obj.pull_request_id,) | |
1034 | qualified=True,) |
|
|||
1035 |
|
1032 | |||
1036 | # set some variables for email notification |
|
1033 | # set some variables for email notification | |
1037 | pr_target_repo_url = h.route_url( |
|
1034 | pr_target_repo_url = h.route_url( |
@@ -23,7 +23,7 b'' | |||||
23 | %if c.statuses.get(commit.raw_id): |
|
23 | %if c.statuses.get(commit.raw_id): | |
24 | <div class="changeset-status-ico"> |
|
24 | <div class="changeset-status-ico"> | |
25 | %if c.statuses.get(commit.raw_id)[2]: |
|
25 | %if c.statuses.get(commit.raw_id)[2]: | |
26 |
<a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h. |
|
26 | <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}"> | |
27 | <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div> |
|
27 | <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div> | |
28 | </a> |
|
28 | </a> | |
29 | %else: |
|
29 | %else: |
@@ -61,7 +61,7 b'' | |||||
61 | % else: |
|
61 | % else: | |
62 | <div class="status-change"> |
|
62 | <div class="status-change"> | |
63 | % if comment.pull_request: |
|
63 | % if comment.pull_request: | |
64 |
<a href="${h. |
|
64 | <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id)}"> | |
65 | % if comment.status_change: |
|
65 | % if comment.status_change: | |
66 | ${_('pull request #%s') % comment.pull_request.pull_request_id}: |
|
66 | ${_('pull request #%s') % comment.pull_request.pull_request_id}: | |
67 | % else: |
|
67 | % else: | |
@@ -122,7 +122,7 b'' | |||||
122 | </a> |
|
122 | </a> | |
123 | % else: |
|
123 | % else: | |
124 | <div title="${_('Comment from pull request version {0}').format(pr_index_ver)}"> |
|
124 | <div title="${_('Comment from pull request version {0}').format(pr_index_ver)}"> | |
125 |
<a href="${h. |
|
125 | <a href="${h.route_path('pullrequest_show',repo_name=comment.pull_request.target_repo.repo_name,pull_request_id=comment.pull_request.pull_request_id, version=comment.pull_request_version_id)}"> | |
126 | <code class="pr-version-num"> |
|
126 | <code class="pr-version-num"> | |
127 | ${'v{}'.format(pr_index_ver)} |
|
127 | ${'v{}'.format(pr_index_ver)} | |
128 | </code> |
|
128 | </code> |
@@ -299,7 +299,7 b'' | |||||
299 | </%def> |
|
299 | </%def> | |
300 |
|
300 | |||
301 | <%def name="pullrequest_name(pull_request_id, target_repo_name, short=False)"> |
|
301 | <%def name="pullrequest_name(pull_request_id, target_repo_name, short=False)"> | |
302 |
<a href="${h. |
|
302 | <a href="${h.route_path('pullrequest_show',repo_name=target_repo_name,pull_request_id=pull_request_id)}"> | |
303 | % if short: |
|
303 | % if short: | |
304 | #${pull_request_id} |
|
304 | #${pull_request_id} | |
305 | % else: |
|
305 | % else: |
@@ -18,7 +18,7 b'' | |||||
18 | %if c.statuses.get(cs.raw_id): |
|
18 | %if c.statuses.get(cs.raw_id): | |
19 | <div class="changeset-status-ico shortlog"> |
|
19 | <div class="changeset-status-ico shortlog"> | |
20 | %if c.statuses.get(cs.raw_id)[2]: |
|
20 | %if c.statuses.get(cs.raw_id)[2]: | |
21 |
<a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (c.statuses.get(cs.raw_id)[0], c.statuses.get(cs.raw_id)[2])}" href="${h. |
|
21 | <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (c.statuses.get(cs.raw_id)[0], c.statuses.get(cs.raw_id)[2])}" href="${h.route_path('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}"> | |
22 | <div class="${'flag_status %s' % c.statuses.get(cs.raw_id)[0]}"></div> |
|
22 | <div class="${'flag_status %s' % c.statuses.get(cs.raw_id)[0]}"></div> | |
23 | </a> |
|
23 | </a> | |
24 | %else: |
|
24 | %else: |
General Comments 0
You need to be logged in to leave comments.
Login now