Show More
@@ -66,113 +66,10 b' log = logging.getLogger(__name__)' | |||
|
66 | 66 | |
|
67 | 67 | |
|
68 | 68 | class PullrequestsController(BaseRepoController): |
|
69 | ||
|
69 | 70 | def __before__(self): |
|
70 | 71 | super(PullrequestsController, self).__before__() |
|
71 | 72 | |
|
72 | def _load_compare_data(self, pull_request, inline_comments): | |
|
73 | """ | |
|
74 | Load context data needed for generating compare diff | |
|
75 | ||
|
76 | :param pull_request: object related to the request | |
|
77 | :param enable_comments: flag to determine if comments are included | |
|
78 | """ | |
|
79 | source_repo = pull_request.source_repo | |
|
80 | source_ref_id = pull_request.source_ref_parts.commit_id | |
|
81 | ||
|
82 | target_repo = pull_request.target_repo | |
|
83 | target_ref_id = pull_request.target_ref_parts.commit_id | |
|
84 | ||
|
85 | # despite opening commits for bookmarks/branches/tags, we always | |
|
86 | # convert this to rev to prevent changes after bookmark or branch change | |
|
87 | c.source_ref_type = 'rev' | |
|
88 | c.source_ref = source_ref_id | |
|
89 | ||
|
90 | c.target_ref_type = 'rev' | |
|
91 | c.target_ref = target_ref_id | |
|
92 | ||
|
93 | c.source_repo = source_repo | |
|
94 | c.target_repo = target_repo | |
|
95 | ||
|
96 | c.fulldiff = bool(request.GET.get('fulldiff')) | |
|
97 | ||
|
98 | # diff_limit is the old behavior, will cut off the whole diff | |
|
99 | # if the limit is applied otherwise will just hide the | |
|
100 | # big files from the front-end | |
|
101 | diff_limit = self.cut_off_limit_diff | |
|
102 | file_limit = self.cut_off_limit_file | |
|
103 | ||
|
104 | pre_load = ["author", "branch", "date", "message"] | |
|
105 | ||
|
106 | c.commit_ranges = [] | |
|
107 | source_commit = EmptyCommit() | |
|
108 | target_commit = EmptyCommit() | |
|
109 | c.missing_requirements = False | |
|
110 | try: | |
|
111 | c.commit_ranges = [ | |
|
112 | source_repo.get_commit(commit_id=rev, pre_load=pre_load) | |
|
113 | for rev in pull_request.revisions] | |
|
114 | ||
|
115 | c.statuses = source_repo.statuses( | |
|
116 | [x.raw_id for x in c.commit_ranges]) | |
|
117 | ||
|
118 | target_commit = source_repo.get_commit( | |
|
119 | commit_id=safe_str(target_ref_id)) | |
|
120 | source_commit = source_repo.get_commit( | |
|
121 | commit_id=safe_str(source_ref_id)) | |
|
122 | except RepositoryRequirementError: | |
|
123 | c.missing_requirements = True | |
|
124 | ||
|
125 | # auto collapse if we have more than limit | |
|
126 | collapse_limit = diffs.DiffProcessor._collapse_commits_over | |
|
127 | c.collapse_all_commits = len(c.commit_ranges) > collapse_limit | |
|
128 | ||
|
129 | c.changes = {} | |
|
130 | c.missing_commits = False | |
|
131 | if (c.missing_requirements or | |
|
132 | isinstance(source_commit, EmptyCommit) or | |
|
133 | source_commit == target_commit): | |
|
134 | _parsed = [] | |
|
135 | c.missing_commits = True | |
|
136 | else: | |
|
137 | vcs_diff = PullRequestModel().get_diff(pull_request) | |
|
138 | diff_processor = diffs.DiffProcessor( | |
|
139 | vcs_diff, format='newdiff', diff_limit=diff_limit, | |
|
140 | file_limit=file_limit, show_full_diff=c.fulldiff) | |
|
141 | ||
|
142 | _parsed = diff_processor.prepare() | |
|
143 | c.limited_diff = isinstance(_parsed, diffs.LimitedDiffContainer) | |
|
144 | ||
|
145 | included_files = {} | |
|
146 | for f in _parsed: | |
|
147 | included_files[f['filename']] = f['stats'] | |
|
148 | ||
|
149 | c.deleted_files = [fname for fname in inline_comments if | |
|
150 | fname not in included_files] | |
|
151 | ||
|
152 | c.deleted_files_comments = collections.defaultdict(dict) | |
|
153 | for fname, per_line_comments in inline_comments.items(): | |
|
154 | if fname in c.deleted_files: | |
|
155 | c.deleted_files_comments[fname]['stats'] = 0 | |
|
156 | c.deleted_files_comments[fname]['comments'] = list() | |
|
157 | for lno, comments in per_line_comments.items(): | |
|
158 | c.deleted_files_comments[fname]['comments'].extend(comments) | |
|
159 | ||
|
160 | def _node_getter(commit): | |
|
161 | def get_node(fname): | |
|
162 | try: | |
|
163 | return commit.get_node(fname) | |
|
164 | except NodeDoesNotExistError: | |
|
165 | return None | |
|
166 | return get_node | |
|
167 | ||
|
168 | c.diffset = codeblocks.DiffSet( | |
|
169 | repo_name=c.repo_name, | |
|
170 | source_repo_name=c.source_repo.repo_name, | |
|
171 | source_node_getter=_node_getter(target_commit), | |
|
172 | target_node_getter=_node_getter(source_commit), | |
|
173 | comments=inline_comments | |
|
174 | ).render_patchset(_parsed, target_commit.raw_id, source_commit.raw_id) | |
|
175 | ||
|
176 | 73 | def _extract_ordering(self, request): |
|
177 | 74 | column_index = safe_int(request.GET.get('order[0][column]')) |
|
178 | 75 | order_dir = request.GET.get('order[0][dir]', 'desc') |
@@ -693,71 +590,53 b' class PullrequestsController(BaseRepoCon' | |||
|
693 | 590 | |
|
694 | 591 | pull_request_display_obj = PullRequest.get_pr_display_object( |
|
695 | 592 | pull_request_obj, _org_pull_request_obj) |
|
593 | ||
|
696 | 594 | return _org_pull_request_obj, pull_request_obj, \ |
|
697 | 595 | pull_request_display_obj, at_version |
|
698 | 596 | |
|
699 | def _get_pr_version_changes(self, version, pull_request_latest): | |
|
700 | """ | |
|
701 | Generate changes commits, and diff data based on the current pr version | |
|
702 | """ | |
|
703 | ||
|
704 | #TODO(marcink): save those changes as JSON metadata for chaching later. | |
|
705 | ||
|
706 | # fake the version to add the "initial" state object | |
|
707 | pull_request_initial = PullRequest.get_pr_display_object( | |
|
708 | pull_request_latest, pull_request_latest, | |
|
709 | internal_methods=['get_commit', 'versions']) | |
|
710 | pull_request_initial.revisions = [] | |
|
711 | pull_request_initial.source_repo.get_commit = types.MethodType( | |
|
712 | lambda *a, **k: EmptyCommit(), pull_request_initial) | |
|
713 | pull_request_initial.source_repo.scm_instance = types.MethodType( | |
|
714 | lambda *a, **k: EmptyRepository(), pull_request_initial) | |
|
715 | ||
|
716 | _changes_versions = [pull_request_latest] + \ | |
|
717 | list(reversed(c.versions)) + \ | |
|
718 | [pull_request_initial] | |
|
719 | ||
|
720 | if version == 'latest': | |
|
721 | index = 0 | |
|
722 | else: | |
|
723 | for pos, prver in enumerate(_changes_versions): | |
|
724 | ver = getattr(prver, 'pull_request_version_id', -1) | |
|
725 | if ver == safe_int(version): | |
|
726 | index = pos | |
|
727 | break | |
|
728 | else: | |
|
729 | index = 0 | |
|
730 | ||
|
731 | cur_obj = _changes_versions[index] | |
|
732 | prev_obj = _changes_versions[index + 1] | |
|
733 | ||
|
734 | old_commit_ids = set(prev_obj.revisions) | |
|
735 | new_commit_ids = set(cur_obj.revisions) | |
|
736 | ||
|
737 | changes = PullRequestModel()._calculate_commit_id_changes( | |
|
738 | old_commit_ids, new_commit_ids) | |
|
739 | ||
|
740 | old_diff_data, new_diff_data = PullRequestModel()._generate_update_diffs( | |
|
741 | cur_obj, prev_obj) | |
|
742 | file_changes = PullRequestModel()._calculate_file_changes( | |
|
743 | old_diff_data, new_diff_data) | |
|
744 | return changes, file_changes | |
|
745 | ||
|
746 | 597 | @LoginRequired() |
|
747 | 598 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
748 | 599 | 'repository.admin') |
|
749 | 600 | def show(self, repo_name, pull_request_id): |
|
750 | 601 | pull_request_id = safe_int(pull_request_id) |
|
751 | 602 | version = request.GET.get('version') |
|
603 | from_version = request.GET.get('from_version') or version | |
|
752 | 604 | merge_checks = request.GET.get('merge_checks') |
|
605 | c.fulldiff = str2bool(request.GET.get('fulldiff')) | |
|
606 | ||
|
607 | # register for JS templates | |
|
608 | c.template_context['pull_request_data']['pull_request_id'] = \ | |
|
609 | pull_request_id | |
|
753 | 610 | |
|
754 | 611 | (pull_request_latest, |
|
755 | 612 | pull_request_at_ver, |
|
756 | 613 | pull_request_display_obj, |
|
757 |
at_version) = self._get_pr_version( |
|
|
614 | at_version) = self._get_pr_version( | |
|
615 | pull_request_id, version=version) | |
|
616 | versions = pull_request_display_obj.versions() | |
|
617 | ||
|
618 | c.at_version = at_version | |
|
619 | c.at_version_num = (at_version | |
|
620 | if at_version and at_version != 'latest' | |
|
621 | else None) | |
|
622 | c.at_version_pos = ChangesetComment.get_index_from_version( | |
|
623 | c.at_version_num, versions) | |
|
758 | 624 | |
|
759 | c.template_context['pull_request_data']['pull_request_id'] = \ | |
|
760 |
|
|
|
625 | (prev_pull_request_latest, | |
|
626 | prev_pull_request_at_ver, | |
|
627 | prev_pull_request_display_obj, | |
|
628 | prev_at_version) = self._get_pr_version( | |
|
629 | pull_request_id, version=from_version) | |
|
630 | ||
|
631 | c.from_version = prev_at_version | |
|
632 | c.from_version_num = (prev_at_version | |
|
633 | if prev_at_version and prev_at_version != 'latest' | |
|
634 | else None) | |
|
635 | c.from_version_pos = ChangesetComment.get_index_from_version( | |
|
636 | c.from_version_num, versions) | |
|
637 | ||
|
638 | # define if we're in COMPARE mode or VIEW at version mode | |
|
639 | compare = at_version != prev_at_version | |
|
761 | 640 | |
|
762 | 641 | # pull_requests repo_name we opened it against |
|
763 | 642 | # ie. target_repo must match |
@@ -767,12 +646,12 b' class PullrequestsController(BaseRepoCon' | |||
|
767 | 646 | c.shadow_clone_url = PullRequestModel().get_shadow_clone_url( |
|
768 | 647 | pull_request_at_ver) |
|
769 | 648 | |
|
770 |
c.ancestor = None # |
|
|
649 | c.ancestor = None # empty ancestor hidden in display | |
|
771 | 650 | c.pull_request = pull_request_display_obj |
|
772 | 651 | c.pull_request_latest = pull_request_latest |
|
773 | 652 | |
|
774 | 653 | pr_closed = pull_request_latest.is_closed() |
|
775 | if at_version and not at_version == 'latest': | |
|
654 | if compare or (at_version and not at_version == 'latest'): | |
|
776 | 655 | c.allowed_to_change_status = False |
|
777 | 656 | c.allowed_to_update = False |
|
778 | 657 | c.allowed_to_merge = False |
@@ -789,35 +668,50 b' class PullrequestsController(BaseRepoCon' | |||
|
789 | 668 | pull_request_latest, c.rhodecode_user) and not pr_closed |
|
790 | 669 | c.allowed_to_comment = not pr_closed |
|
791 | 670 | |
|
792 | cc_model = CommentsModel() | |
|
671 | # check merge capabilities | |
|
672 | _merge_check = MergeCheck.validate( | |
|
673 | pull_request_latest, user=c.rhodecode_user) | |
|
674 | c.pr_merge_errors = _merge_check.error_details | |
|
675 | c.pr_merge_possible = not _merge_check.failed | |
|
676 | c.pr_merge_message = _merge_check.merge_msg | |
|
793 | 677 | |
|
678 | if merge_checks: | |
|
679 | return render('/pullrequests/pullrequest_merge_checks.mako') | |
|
680 | ||
|
681 | comments_model = CommentsModel() | |
|
682 | ||
|
683 | # reviewers and statuses | |
|
794 | 684 | c.pull_request_reviewers = pull_request_at_ver.reviewers_statuses() |
|
685 | allowed_reviewers = [x[0].user_id for x in c.pull_request_reviewers] | |
|
795 | 686 | c.pull_request_review_status = pull_request_at_ver.calculated_review_status() |
|
796 | 687 | |
|
797 | c.versions = pull_request_display_obj.versions() | |
|
798 | c.at_version = at_version | |
|
799 | c.at_version_num = at_version if at_version and at_version != 'latest' else None | |
|
800 | c.at_version_pos = ChangesetComment.get_index_from_version( | |
|
801 | c.at_version_num, c.versions) | |
|
802 | ||
|
803 | 688 | # GENERAL COMMENTS with versions # |
|
804 |
q = c |
|
|
689 | q = comments_model._all_general_comments_of_pull_request(pull_request_latest) | |
|
690 | q = q.order_by(ChangesetComment.comment_id.asc()) | |
|
805 | 691 | general_comments = q.order_by(ChangesetComment.pull_request_version_id.asc()) |
|
806 | 692 | |
|
807 | 693 | # pick comments we want to render at current version |
|
808 |
c.comment_versions = c |
|
|
809 |
general_comments, |
|
|
694 | c.comment_versions = comments_model.aggregate_comments( | |
|
695 | general_comments, versions, c.at_version_num) | |
|
810 | 696 | c.comments = c.comment_versions[c.at_version_num]['until'] |
|
811 | 697 | |
|
812 | 698 | # INLINE COMMENTS with versions # |
|
813 |
q = c |
|
|
699 | q = comments_model._all_inline_comments_of_pull_request(pull_request_latest) | |
|
700 | q = q.order_by(ChangesetComment.comment_id.asc()) | |
|
814 | 701 | inline_comments = q.order_by(ChangesetComment.pull_request_version_id.asc()) |
|
815 |
c.inline_versions = c |
|
|
816 |
inline_comments, |
|
|
702 | c.inline_versions = comments_model.aggregate_comments( | |
|
703 | inline_comments, versions, c.at_version_num, inline=True) | |
|
704 | ||
|
705 | # inject latest version | |
|
706 | latest_ver = PullRequest.get_pr_display_object( | |
|
707 | pull_request_latest, pull_request_latest) | |
|
708 | ||
|
709 | c.versions = versions + [latest_ver] | |
|
817 | 710 | |
|
818 | 711 | # if we use version, then do not show later comments |
|
819 | 712 | # than current version |
|
820 |
display_inline_comments = collections.defaultdict( |
|
|
713 | display_inline_comments = collections.defaultdict( | |
|
714 | lambda: collections.defaultdict(list)) | |
|
821 | 715 | for co in inline_comments: |
|
822 | 716 | if c.at_version_num: |
|
823 | 717 | # pick comments that are at least UPTO given version, so we |
@@ -831,17 +725,126 b' class PullrequestsController(BaseRepoCon' | |||
|
831 | 725 | if should_render: |
|
832 | 726 | display_inline_comments[co.f_path][co.line_no].append(co) |
|
833 | 727 | |
|
834 | _merge_check = MergeCheck.validate( | |
|
835 | pull_request_latest, user=c.rhodecode_user) | |
|
836 | c.pr_merge_errors = _merge_check.error_details | |
|
837 | c.pr_merge_possible = not _merge_check.failed | |
|
838 | c.pr_merge_message = _merge_check.merge_msg | |
|
728 | # load diff data into template context, if we use compare mode then | |
|
729 | # diff is calculated based on changes between versions of PR | |
|
730 | ||
|
731 | source_repo = pull_request_at_ver.source_repo | |
|
732 | source_ref_id = pull_request_at_ver.source_ref_parts.commit_id | |
|
733 | ||
|
734 | target_repo = pull_request_at_ver.target_repo | |
|
735 | target_ref_id = pull_request_at_ver.target_ref_parts.commit_id | |
|
736 | ||
|
737 | if compare: | |
|
738 | # in compare switch the diff base to latest commit from prev version | |
|
739 | target_ref_id = prev_pull_request_display_obj.revisions[0] | |
|
740 | ||
|
741 | # despite opening commits for bookmarks/branches/tags, we always | |
|
742 | # convert this to rev to prevent changes after bookmark or branch change | |
|
743 | c.source_ref_type = 'rev' | |
|
744 | c.source_ref = source_ref_id | |
|
745 | ||
|
746 | c.target_ref_type = 'rev' | |
|
747 | c.target_ref = target_ref_id | |
|
748 | ||
|
749 | c.source_repo = source_repo | |
|
750 | c.target_repo = target_repo | |
|
751 | ||
|
752 | # diff_limit is the old behavior, will cut off the whole diff | |
|
753 | # if the limit is applied otherwise will just hide the | |
|
754 | # big files from the front-end | |
|
755 | diff_limit = self.cut_off_limit_diff | |
|
756 | file_limit = self.cut_off_limit_file | |
|
757 | ||
|
758 | c.commit_ranges = [] | |
|
759 | source_commit = EmptyCommit() | |
|
760 | target_commit = EmptyCommit() | |
|
761 | c.missing_requirements = False | |
|
762 | ||
|
763 | # try first shadow repo, fallback to regular repo | |
|
764 | try: | |
|
765 | commits_source_repo = pull_request_latest.get_shadow_repo() | |
|
766 | except Exception: | |
|
767 | log.debug('Failed to get shadow repo', exc_info=True) | |
|
768 | commits_source_repo = source_repo.scm_instance() | |
|
769 | ||
|
770 | c.commits_source_repo = commits_source_repo | |
|
771 | commit_cache = {} | |
|
772 | try: | |
|
773 | pre_load = ["author", "branch", "date", "message"] | |
|
774 | show_revs = pull_request_at_ver.revisions | |
|
775 | for rev in show_revs: | |
|
776 | comm = commits_source_repo.get_commit( | |
|
777 | commit_id=rev, pre_load=pre_load) | |
|
778 | c.commit_ranges.append(comm) | |
|
779 | commit_cache[comm.raw_id] = comm | |
|
839 | 780 | |
|
840 | if merge_checks: | |
|
841 | return render('/pullrequests/pullrequest_merge_checks.mako') | |
|
781 | target_commit = commits_source_repo.get_commit( | |
|
782 | commit_id=safe_str(target_ref_id)) | |
|
783 | source_commit = commits_source_repo.get_commit( | |
|
784 | commit_id=safe_str(source_ref_id)) | |
|
785 | except CommitDoesNotExistError: | |
|
786 | pass | |
|
787 | except RepositoryRequirementError: | |
|
788 | log.warning( | |
|
789 | 'Failed to get all required data from repo', exc_info=True) | |
|
790 | c.missing_requirements = True | |
|
791 | ||
|
792 | c.statuses = source_repo.statuses( | |
|
793 | [x.raw_id for x in c.commit_ranges]) | |
|
794 | ||
|
795 | # auto collapse if we have more than limit | |
|
796 | collapse_limit = diffs.DiffProcessor._collapse_commits_over | |
|
797 | c.collapse_all_commits = len(c.commit_ranges) > collapse_limit | |
|
798 | c.compare_mode = compare | |
|
799 | ||
|
800 | c.missing_commits = False | |
|
801 | if (c.missing_requirements or isinstance(source_commit, EmptyCommit) | |
|
802 | or source_commit == target_commit): | |
|
803 | ||
|
804 | c.missing_commits = True | |
|
805 | else: | |
|
806 | vcs_diff = PullRequestModel().get_diff( | |
|
807 | commits_source_repo, source_ref_id, target_ref_id) | |
|
808 | ||
|
809 | diff_processor = diffs.DiffProcessor( | |
|
810 | vcs_diff, format='newdiff', diff_limit=diff_limit, | |
|
811 | file_limit=file_limit, show_full_diff=c.fulldiff) | |
|
842 | 812 | |
|
843 | # load compare data into template context | |
|
844 | self._load_compare_data(pull_request_at_ver, display_inline_comments) | |
|
813 | _parsed = diff_processor.prepare() | |
|
814 | c.limited_diff = isinstance(_parsed, diffs.LimitedDiffContainer) | |
|
815 | ||
|
816 | def _node_getter(commit): | |
|
817 | def get_node(fname): | |
|
818 | try: | |
|
819 | return commit.get_node(fname) | |
|
820 | except NodeDoesNotExistError: | |
|
821 | return None | |
|
822 | ||
|
823 | return get_node | |
|
824 | ||
|
825 | diffset = codeblocks.DiffSet( | |
|
826 | repo_name=c.repo_name, | |
|
827 | source_repo_name=c.source_repo.repo_name, | |
|
828 | source_node_getter=_node_getter(target_commit), | |
|
829 | target_node_getter=_node_getter(source_commit), | |
|
830 | comments=display_inline_comments | |
|
831 | ) | |
|
832 | c.diffset = diffset.render_patchset( | |
|
833 | _parsed, target_commit.raw_id, source_commit.raw_id) | |
|
834 | ||
|
835 | # calculate removed files that are bound to comments | |
|
836 | comment_deleted_files = [ | |
|
837 | fname for fname in display_inline_comments | |
|
838 | if fname not in c.diffset.file_stats] | |
|
839 | ||
|
840 | c.deleted_files_comments = collections.defaultdict(dict) | |
|
841 | for fname, per_line_comments in display_inline_comments.items(): | |
|
842 | if fname in comment_deleted_files: | |
|
843 | c.deleted_files_comments[fname]['stats'] = 0 | |
|
844 | c.deleted_files_comments[fname]['comments'] = list() | |
|
845 | for lno, comments in per_line_comments.items(): | |
|
846 | c.deleted_files_comments[fname]['comments'].extend( | |
|
847 | comments) | |
|
845 | 848 | |
|
846 | 849 | # this is a hack to properly display links, when creating PR, the |
|
847 | 850 | # compare view and others uses different notation, and |
@@ -856,21 +859,55 b' class PullrequestsController(BaseRepoCon' | |||
|
856 | 859 | statuses = ChangesetStatus.STATUSES |
|
857 | 860 | c.commit_statuses = statuses |
|
858 | 861 | |
|
859 |
c.changes = |
|
|
860 |
c. |
|
|
862 | c.show_version_changes = not pr_closed | |
|
863 | if c.show_version_changes: | |
|
864 | cur_obj = pull_request_at_ver | |
|
865 | prev_obj = prev_pull_request_at_ver | |
|
866 | ||
|
867 | old_commit_ids = prev_obj.revisions | |
|
868 | new_commit_ids = cur_obj.revisions | |
|
869 | commit_changes = PullRequestModel()._calculate_commit_id_changes( | |
|
870 | old_commit_ids, new_commit_ids) | |
|
871 | c.commit_changes_summary = commit_changes | |
|
872 | ||
|
873 | # calculate the diff for commits between versions | |
|
874 | c.commit_changes = [] | |
|
875 | mark = lambda cs, fw: list( | |
|
876 | h.itertools.izip_longest([], cs, fillvalue=fw)) | |
|
877 | for c_type, raw_id in mark(commit_changes.added, 'a') \ | |
|
878 | + mark(commit_changes.removed, 'r') \ | |
|
879 | + mark(commit_changes.common, 'c'): | |
|
861 | 880 | |
|
862 | c.show_version_changes = 1 # control flag, not used yet | |
|
881 | if raw_id in commit_cache: | |
|
882 | commit = commit_cache[raw_id] | |
|
883 | else: | |
|
884 | try: | |
|
885 | commit = commits_source_repo.get_commit(raw_id) | |
|
886 | except CommitDoesNotExistError: | |
|
887 | # in case we fail extracting still use "dummy" commit | |
|
888 | # for display in commit diff | |
|
889 | commit = h.AttributeDict( | |
|
890 | {'raw_id': raw_id, | |
|
891 | 'message': 'EMPTY or MISSING COMMIT'}) | |
|
892 | c.commit_changes.append([c_type, commit]) | |
|
863 | 893 | |
|
864 | if at_version and c.show_version_changes: | |
|
865 | c.changes, c.file_changes = self._get_pr_version_changes( | |
|
866 | version, pull_request_latest) | |
|
894 | # current user review statuses for each version | |
|
895 | c.review_versions = {} | |
|
896 | if c.rhodecode_user.user_id in allowed_reviewers: | |
|
897 | for co in general_comments: | |
|
898 | if co.author.user_id == c.rhodecode_user.user_id: | |
|
899 | # each comment has a status change | |
|
900 | status = co.status_change | |
|
901 | if status: | |
|
902 | _ver_pr = status[0].comment.pull_request_version_id | |
|
903 | c.review_versions[_ver_pr] = status[0] | |
|
867 | 904 | |
|
868 | 905 | return render('/pullrequests/pullrequest_show.mako') |
|
869 | 906 | |
|
870 | 907 | @LoginRequired() |
|
871 | 908 | @NotAnonymous() |
|
872 |
@HasRepoPermissionAnyDecorator( |
|
|
873 | 'repository.admin') | |
|
909 | @HasRepoPermissionAnyDecorator( | |
|
910 | 'repository.read', 'repository.write', 'repository.admin') | |
|
874 | 911 | @auth.CSRFRequired() |
|
875 | 912 | @jsonify |
|
876 | 913 | def comment(self, repo_name, pull_request_id): |
@@ -382,6 +382,7 b' class DiffSet(object):' | |||
|
382 | 382 | lines_deleted=0, |
|
383 | 383 | changed_files=0, |
|
384 | 384 | files=[], |
|
385 | file_stats={}, | |
|
385 | 386 | limited_diff=isinstance(patchset, LimitedDiffContainer), |
|
386 | 387 | repo_name=self.repo_name, |
|
387 | 388 | source_repo_name=self.source_repo_name, |
@@ -389,6 +390,7 b' class DiffSet(object):' | |||
|
389 | 390 | target_ref=target_ref, |
|
390 | 391 | )) |
|
391 | 392 | for patch in patchset: |
|
393 | diffset.file_stats[patch['filename']] = patch['stats'] | |
|
392 | 394 | filediff = self.render_patch(patch) |
|
393 | 395 | filediff.diffset = diffset |
|
394 | 396 | diffset.files.append(filediff) |
@@ -37,6 +37,7 b' import time' | |||
|
37 | 37 | import string |
|
38 | 38 | import hashlib |
|
39 | 39 | import pygments |
|
40 | import itertools | |
|
40 | 41 | |
|
41 | 42 | from datetime import datetime |
|
42 | 43 | from functools import partial |
@@ -3028,7 +3028,7 b' class ChangesetStatus(Base, BaseModel):' | |||
|
3028 | 3028 | pull_request = relationship('PullRequest', lazy='joined') |
|
3029 | 3029 | |
|
3030 | 3030 | def __unicode__(self): |
|
3031 | return u"<%s('%s[%s]:%s')>" % ( | |
|
3031 | return u"<%s('%s[v%s]:%s')>" % ( | |
|
3032 | 3032 | self.__class__.__name__, |
|
3033 | 3033 | self.status, self.version, self.author |
|
3034 | 3034 | ) |
@@ -3254,7 +3254,6 b' class PullRequest(Base, _PullRequestBase' | |||
|
3254 | 3254 | cascade="all, delete, delete-orphan", |
|
3255 | 3255 | lazy='dynamic') |
|
3256 | 3256 | |
|
3257 | ||
|
3258 | 3257 | @classmethod |
|
3259 | 3258 | def get_pr_display_object(cls, pull_request_obj, org_pull_request_obj, |
|
3260 | 3259 | internal_methods=None): |
@@ -3290,6 +3289,10 b' class PullRequest(Base, _PullRequestBase' | |||
|
3290 | 3289 | def is_closed(self): |
|
3291 | 3290 | return pull_request_obj.is_closed() |
|
3292 | 3291 | |
|
3292 | @property | |
|
3293 | def pull_request_version_id(self): | |
|
3294 | return getattr(pull_request_obj, 'pull_request_version_id', None) | |
|
3295 | ||
|
3293 | 3296 | attrs = StrictAttributeDict(pull_request_obj.get_api_data()) |
|
3294 | 3297 | |
|
3295 | 3298 | attrs.author = StrictAttributeDict( |
@@ -235,7 +235,7 b' class NotificationModel(BaseModel):' | |||
|
235 | 235 | .filter(UserNotification.notification == notification)\ |
|
236 | 236 | .filter(UserNotification.user == user).scalar() |
|
237 | 237 | |
|
238 | def make_description(self, notification, show_age=True): | |
|
238 | def make_description(self, notification, show_age=True, translate=None): | |
|
239 | 239 | """ |
|
240 | 240 | Creates a human readable description based on properties |
|
241 | 241 | of notification object |
@@ -273,6 +273,8 b' class NotificationModel(BaseModel):' | |||
|
273 | 273 | if show_age: |
|
274 | 274 | template = templates[0] |
|
275 | 275 | date_or_age = h.age(notification.created_on) |
|
276 | if translate: | |
|
277 | date_or_age = translate(date_or_age) | |
|
276 | 278 | else: |
|
277 | 279 | template = templates[1] |
|
278 | 280 | date_or_age = h.format_date(notification.created_on) |
@@ -50,7 +50,7 b' from rhodecode.model.changeset_status im' | |||
|
50 | 50 | from rhodecode.model.comment import CommentsModel |
|
51 | 51 | from rhodecode.model.db import ( |
|
52 | 52 | PullRequest, PullRequestReviewers, ChangesetStatus, |
|
53 | PullRequestVersion, ChangesetComment) | |
|
53 | PullRequestVersion, ChangesetComment, Repository) | |
|
54 | 54 | from rhodecode.model.meta import Session |
|
55 | 55 | from rhodecode.model.notification import NotificationModel, \ |
|
56 | 56 | EmailNotificationModel |
@@ -728,13 +728,23 b' class PullRequestModel(BaseModel):' | |||
|
728 | 728 | return version |
|
729 | 729 | |
|
730 | 730 | def _generate_update_diffs(self, pull_request, pull_request_version): |
|
731 | ||
|
731 | 732 | diff_context = ( |
|
732 | 733 | self.DIFF_CONTEXT + |
|
733 | 734 | CommentsModel.needed_extra_diff_context()) |
|
735 | ||
|
736 | source_repo = pull_request_version.source_repo | |
|
737 | source_ref_id = pull_request_version.source_ref_parts.commit_id | |
|
738 | target_ref_id = pull_request_version.target_ref_parts.commit_id | |
|
734 | 739 | old_diff = self._get_diff_from_pr_or_version( |
|
735 |
|
|
|
740 | source_repo, source_ref_id, target_ref_id, context=diff_context) | |
|
741 | ||
|
742 | source_repo = pull_request.source_repo | |
|
743 | source_ref_id = pull_request.source_ref_parts.commit_id | |
|
744 | target_ref_id = pull_request.target_ref_parts.commit_id | |
|
745 | ||
|
736 | 746 | new_diff = self._get_diff_from_pr_or_version( |
|
737 |
|
|
|
747 | source_repo, source_ref_id, target_ref_id, context=diff_context) | |
|
738 | 748 | |
|
739 | 749 | old_diff_data = diffs.DiffProcessor(old_diff) |
|
740 | 750 | old_diff_data.prepare() |
@@ -768,10 +778,11 b' class PullRequestModel(BaseModel):' | |||
|
768 | 778 | Session().add(comment) |
|
769 | 779 | |
|
770 | 780 | def _calculate_commit_id_changes(self, old_ids, new_ids): |
|
771 |
added = new_ids |
|
|
772 | common = old_ids.intersection(new_ids) | |
|
773 |
removed = old_ids |
|
|
774 | return ChangeTuple(added, common, removed) | |
|
781 | added = [x for x in new_ids if x not in old_ids] | |
|
782 | common = [x for x in new_ids if x in old_ids] | |
|
783 | removed = [x for x in old_ids if x not in new_ids] | |
|
784 | total = new_ids | |
|
785 | return ChangeTuple(added, common, removed, total) | |
|
775 | 786 | |
|
776 | 787 | def _calculate_file_changes(self, old_diff_data, new_diff_data): |
|
777 | 788 | |
@@ -1261,20 +1272,20 b' class PullRequestModel(BaseModel):' | |||
|
1261 | 1272 | raise EmptyRepositoryError() |
|
1262 | 1273 | return groups, selected |
|
1263 | 1274 | |
|
1264 |
def get_diff(self, |
|
|
1265 | pull_request = self.__get_pull_request(pull_request) | |
|
1266 | return self._get_diff_from_pr_or_version(pull_request, context=context) | |
|
1275 | def get_diff(self, source_repo, source_ref_id, target_ref_id, context=DIFF_CONTEXT): | |
|
1276 | return self._get_diff_from_pr_or_version( | |
|
1277 | source_repo, source_ref_id, target_ref_id, context=context) | |
|
1267 | 1278 | |
|
1268 |
def _get_diff_from_pr_or_version( |
|
|
1269 | source_repo = pr_or_version.source_repo | |
|
1270 | ||
|
1271 | # we swap org/other ref since we run a simple diff on one repo | |
|
1272 | target_ref_id = pr_or_version.target_ref_parts.commit_id | |
|
1273 | source_ref_id = pr_or_version.source_ref_parts.commit_id | |
|
1279 | def _get_diff_from_pr_or_version( | |
|
1280 | self, source_repo, source_ref_id, target_ref_id, context): | |
|
1274 | 1281 | target_commit = source_repo.get_commit( |
|
1275 | 1282 | commit_id=safe_str(target_ref_id)) |
|
1276 |
source_commit = source_repo.get_commit( |
|
|
1283 | source_commit = source_repo.get_commit( | |
|
1284 | commit_id=safe_str(source_ref_id)) | |
|
1285 | if isinstance(source_repo, Repository): | |
|
1277 | 1286 | vcs_repo = source_repo.scm_instance() |
|
1287 | else: | |
|
1288 | vcs_repo = source_repo | |
|
1278 | 1289 | |
|
1279 | 1290 | # TODO: johbo: In the context of an update, we cannot reach |
|
1280 | 1291 | # the old commit anymore with our normal mechanisms. It needs |
@@ -1403,7 +1414,7 b' class MergeCheck(object):' | |||
|
1403 | 1414 | |
|
1404 | 1415 | |
|
1405 | 1416 | ChangeTuple = namedtuple('ChangeTuple', |
|
1406 | ['added', 'common', 'removed']) | |
|
1417 | ['added', 'common', 'removed', 'total']) | |
|
1407 | 1418 | |
|
1408 | 1419 | FileChangeTuple = namedtuple('FileChangeTuple', |
|
1409 | 1420 | ['added', 'modified', 'removed']) |
@@ -1393,6 +1393,14 b' table.integrations {' | |||
|
1393 | 1393 | } |
|
1394 | 1394 | } |
|
1395 | 1395 | |
|
1396 | .subtitle-compare { | |
|
1397 | margin: -15px 0px 0px 0px; | |
|
1398 | } | |
|
1399 | ||
|
1400 | .comments-summary-td { | |
|
1401 | border-top: 1px dashed @grey5; | |
|
1402 | } | |
|
1403 | ||
|
1396 | 1404 | // new entry in group_members |
|
1397 | 1405 | .td-author-new-entry { |
|
1398 | 1406 | background-color: rgba(red(@alert1), green(@alert1), blue(@alert1), 0.3); |
@@ -1422,6 +1430,57 b' table.integrations {' | |||
|
1422 | 1430 | margin-left: 5px; |
|
1423 | 1431 | } |
|
1424 | 1432 | |
|
1433 | .compare_view_commits { | |
|
1434 | .color-a { | |
|
1435 | color: @alert1; | |
|
1436 | } | |
|
1437 | ||
|
1438 | .color-c { | |
|
1439 | color: @color3; | |
|
1440 | } | |
|
1441 | ||
|
1442 | .color-r { | |
|
1443 | color: @color5; | |
|
1444 | } | |
|
1445 | ||
|
1446 | .color-a-bg { | |
|
1447 | background-color: @alert1; | |
|
1448 | } | |
|
1449 | ||
|
1450 | .color-c-bg { | |
|
1451 | background-color: @alert3; | |
|
1452 | } | |
|
1453 | ||
|
1454 | .color-r-bg { | |
|
1455 | background-color: @alert2; | |
|
1456 | } | |
|
1457 | ||
|
1458 | .color-a-border { | |
|
1459 | border: 1px solid @alert1; | |
|
1460 | } | |
|
1461 | ||
|
1462 | .color-c-border { | |
|
1463 | border: 1px solid @alert3; | |
|
1464 | } | |
|
1465 | ||
|
1466 | .color-r-border { | |
|
1467 | border: 1px solid @alert2; | |
|
1468 | } | |
|
1469 | ||
|
1470 | .commit-change-indicator { | |
|
1471 | width: 15px; | |
|
1472 | height: 15px; | |
|
1473 | position: relative; | |
|
1474 | left: 15px; | |
|
1475 | } | |
|
1476 | ||
|
1477 | .commit-change-content { | |
|
1478 | text-align: center; | |
|
1479 | vertical-align: middle; | |
|
1480 | line-height: 15px; | |
|
1481 | } | |
|
1482 | } | |
|
1483 | ||
|
1425 | 1484 | .compare_view_files { |
|
1426 | 1485 | width: 100%; |
|
1427 | 1486 | |
@@ -1663,9 +1722,26 b' BIN_FILENODE = 7' | |||
|
1663 | 1722 | } |
|
1664 | 1723 | |
|
1665 | 1724 | .pr-versions { |
|
1725 | font-size: 1.1em; | |
|
1726 | ||
|
1727 | table { | |
|
1728 | padding: 0px 5px; | |
|
1729 | } | |
|
1730 | ||
|
1731 | td { | |
|
1732 | line-height: 15px; | |
|
1733 | } | |
|
1734 | ||
|
1735 | .flag_status { | |
|
1736 | margin: 0; | |
|
1737 | } | |
|
1738 | ||
|
1739 | .compare-radio-button { | |
|
1666 | 1740 | position: relative; |
|
1667 |
top: |
|
|
1668 | } | |
|
1741 | top: -3px; | |
|
1742 | } | |
|
1743 | } | |
|
1744 | ||
|
1669 | 1745 | |
|
1670 | 1746 | #close_pull_request { |
|
1671 | 1747 | margin-right: 0px; |
@@ -315,13 +315,35 b'' | |||
|
315 | 315 | var cid = target_expand.data('commitId'); |
|
316 | 316 | |
|
317 | 317 | if (target_expand.hasClass('open')){ |
|
318 | $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'}); | |
|
319 | $('#t-'+cid).css({'height': 'auto', 'line-height': '.9em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'}); | |
|
318 | $('#c-' + cid).css({ | |
|
319 | 'height': '1.5em', | |
|
320 | 'white-space': 'nowrap', | |
|
321 | 'text-overflow': 'ellipsis', | |
|
322 | 'overflow': 'hidden' | |
|
323 | }); | |
|
324 | $('#t-' + cid).css({ | |
|
325 | 'height': 'auto', | |
|
326 | 'line-height': '.9em', | |
|
327 | 'text-overflow': 'ellipsis', | |
|
328 | 'overflow': 'hidden', | |
|
329 | 'white-space': 'nowrap' | |
|
330 | }); | |
|
320 | 331 | target_expand.removeClass('open'); |
|
321 | 332 | } |
|
322 | 333 | else { |
|
323 | $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'}); | |
|
324 | $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'}); | |
|
334 | $('#c-' + cid).css({ | |
|
335 | 'height': 'auto', | |
|
336 | 'white-space': 'pre-line', | |
|
337 | 'text-overflow': 'initial', | |
|
338 | 'overflow': 'visible' | |
|
339 | }); | |
|
340 | $('#t-' + cid).css({ | |
|
341 | 'height': 'auto', | |
|
342 | 'max-height': 'none', | |
|
343 | 'text-overflow': 'initial', | |
|
344 | 'overflow': 'visible', | |
|
345 | 'white-space': 'normal' | |
|
346 | }); | |
|
325 | 347 | target_expand.addClass('open'); |
|
326 | 348 | } |
|
327 | 349 | // redraw the graph |
@@ -134,13 +134,6 b' collapse_all = len(diffset.files) > coll' | |||
|
134 | 134 | '%(num)s files changed: %(linesadd)s inserted, %(linesdel)s deleted', diffset.changed_files) % {'num': diffset.changed_files, 'linesadd': diffset.lines_added, 'linesdel': diffset.lines_deleted}} |
|
135 | 135 | %endif |
|
136 | 136 | |
|
137 | <% at_ver = getattr(c, 'at_version_pos', None) %> | |
|
138 | % if at_ver: | |
|
139 | <div class="pull-right"> | |
|
140 | ${_('Showing changes at version %d') % at_ver} | |
|
141 | </div> | |
|
142 | % endif | |
|
143 | ||
|
144 | 137 | </h2> |
|
145 | 138 | </div> |
|
146 | 139 |
@@ -1,4 +1,5 b'' | |||
|
1 | 1 | <%inherit file="/base/base.mako"/> |
|
2 | <%namespace name="base" file="/base/base.mako"/> | |
|
2 | 3 | |
|
3 | 4 | <%def name="title()"> |
|
4 | 5 | ${_('%s Pull Request #%s') % (c.repo_name, c.pull_request.pull_request_id)} |
@@ -166,46 +167,22 b'' | |||
|
166 | 167 | |
|
167 | 168 | <div class="field"> |
|
168 | 169 |
|
|
169 |
|
|
|
170 | <label>${_('Versions')}:</label> | |
|
170 | 171 |
|
|
171 | 172 | |
|
173 | <% outdated_comm_count_ver = len(c.inline_versions[None]['outdated']) %> | |
|
174 | <% general_outdated_comm_count_ver = len(c.comment_versions[None]['outdated']) %> | |
|
175 | ||
|
172 | 176 | <div class="pr-versions"> |
|
173 | 177 | % if c.show_version_changes: |
|
178 | <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %> | |
|
179 | <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %> | |
|
180 | <div id="show-pr-versions" class="input btn btn-link" onclick="return versionController.toggleVersionView(this)" | |
|
181 | data-toggle-on="${ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))}" | |
|
182 | data-toggle-off="${_('Hide all versions of this pull request')}"> | |
|
183 | ${ungettext('{} version available for this pull request, show it.', '{} versions available for this pull request, show them.', len(c.versions)).format(len(c.versions))} | |
|
184 | </div> | |
|
174 | 185 | <table> |
|
175 | ## CURRENTLY SELECT PR VERSION | |
|
176 | <tr class="version-pr" style="display: ${'' if c.at_version_num is None else 'none'}"> | |
|
177 | <td> | |
|
178 | % if c.at_version_num is None: | |
|
179 | <i class="icon-ok link"></i> | |
|
180 | % else: | |
|
181 | <i class="icon-comment"></i> | |
|
182 | <code> | |
|
183 | ${len(c.comment_versions[None]['at'])}/${len(c.inline_versions[None]['at'])} | |
|
184 | </code> | |
|
185 | % endif | |
|
186 | </td> | |
|
187 | <td> | |
|
188 | <code> | |
|
189 | % if c.versions: | |
|
190 | <a href="${h.url.current(version='latest')}">${_('latest')}</a> | |
|
191 | % else: | |
|
192 | ${_('initial')} | |
|
193 | % endif | |
|
194 | </code> | |
|
195 | </td> | |
|
196 | <td> | |
|
197 | <code>${c.pull_request_latest.source_ref_parts.commit_id[:6]}</code> | |
|
198 | </td> | |
|
199 | <td> | |
|
200 | ${_('created')} ${h.age_component(c.pull_request_latest.updated_on)} | |
|
201 | </td> | |
|
202 | <td align="right"> | |
|
203 | % if c.versions and c.at_version_num in [None, 'latest']: | |
|
204 | <span id="show-pr-versions" class="btn btn-link" onclick="$('.version-pr').show(); $(this).hide(); return false">${_('Show all versions')}</span> | |
|
205 | % endif | |
|
206 | </td> | |
|
207 | </tr> | |
|
208 | ||
|
209 | 186 | ## SHOW ALL VERSIONS OF PR |
|
210 | 187 | <% ver_pr = None %> |
|
211 | 188 | |
@@ -213,46 +190,52 b'' | |||
|
213 | 190 | <% ver_pos = data[0] %> |
|
214 | 191 | <% ver = data[1] %> |
|
215 | 192 | <% ver_pr = ver.pull_request_version_id %> |
|
193 | <% display_row = '' if c.at_version and (c.at_version_num == ver_pr or c.from_version_num == ver_pr) else 'none' %> | |
|
216 | 194 | |
|
217 |
<tr class="version-pr" style="display: ${ |
|
|
195 | <tr class="version-pr" style="display: ${display_row}"> | |
|
196 | <td> | |
|
197 | <code> | |
|
198 | <a href="${h.url.current(version=ver_pr or 'latest')}">v${ver_pos}</a> | |
|
199 | </code> | |
|
200 | </td> | |
|
218 | 201 | <td> |
|
219 | % if c.at_version_num == ver_pr: | |
|
220 | <i class="icon-ok link"></i> | |
|
221 |
|
|
|
202 | <input ${'checked="checked"' if c.from_version_num == ver_pr else ''} class="compare-radio-button" type="radio" name="ver_source" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/> | |
|
203 | <input ${'checked="checked"' if c.at_version_num == ver_pr else ''} class="compare-radio-button" type="radio" name="ver_target" value="${ver_pr or 'latest'}" data-ver-pos="${ver_pos}"/> | |
|
204 | </td> | |
|
205 | <td> | |
|
206 | <% review_status = c.review_versions[ver_pr].status if ver_pr in c.review_versions else 'not_reviewed' %> | |
|
207 | <div class="${'flag_status %s' % review_status} tooltip pull-left" title="${_('Your review status at this version')}"> | |
|
208 | </div> | |
|
209 | </td> | |
|
210 | <td> | |
|
211 | % if c.at_version_num != ver_pr: | |
|
222 | 212 | <i class="icon-comment"></i> |
|
223 | <code class="tooltip" title="${_('Comment from pull request version {0}, general:{1} inline{2}').format(ver_pos, len(c.comment_versions[ver_pr]['at']), len(c.inline_versions[ver_pr]['at']))}"> | |
|
213 | <code class="tooltip" title="${_('Comment from pull request version {0}, general:{1} inline:{2}').format(ver_pos, len(c.comment_versions[ver_pr]['at']), len(c.inline_versions[ver_pr]['at']))}"> | |
|
224 | 214 | ${len(c.comment_versions[ver_pr]['at'])}/${len(c.inline_versions[ver_pr]['at'])} |
|
225 | 215 | </code> |
|
226 | 216 | % endif |
|
227 | 217 | </td> |
|
228 | 218 | <td> |
|
229 |
|
|
|
230 | <a href="${h.url.current(version=ver_pr)}">v${ver_pos}</a> | |
|
231 | </code> | |
|
219 | ##<code>${ver.source_ref_parts.commit_id[:6]}</code> | |
|
232 | 220 | </td> |
|
233 | 221 | <td> |
|
234 | <code>${ver.source_ref_parts.commit_id[:6]}</code> | |
|
235 | </td> | |
|
236 | <td> | |
|
237 | ${_('created')} ${h.age_component(ver.updated_on)} | |
|
238 | </td> | |
|
239 | <td align="right"> | |
|
240 | % if c.at_version_num == ver_pr: | |
|
241 | <span id="show-pr-versions" class="btn btn-link" onclick="$('.version-pr').show(); $(this).hide(); return false">${_('Show all versions')}</span> | |
|
242 | % endif | |
|
222 | ${h.age_component(ver.updated_on)} | |
|
243 | 223 | </td> |
|
244 | 224 | </tr> |
|
245 | 225 | % endfor |
|
246 | 226 |
|
|
247 | ## show comment/inline comments summary | |
|
248 | 227 |
|
|
249 | <td> | |
|
228 | <td colspan="5"> | |
|
229 | <button id="show-version-diff" onclick="return versionController.showVersionDiff()" class="btn btn-sm" style="display: none" data-label-text="${_('show changes between versions')}"> | |
|
230 | ${_('show changes between versions')} | |
|
231 | </button> | |
|
250 | 232 | </td> |
|
233 | </tr> | |
|
251 | 234 | |
|
252 | <td colspan="4" style="border-top: 1px dashed #dbd9da"> | |
|
253 | <% outdated_comm_count_ver = len(c.inline_versions[c.at_version_num]['outdated']) %> | |
|
254 | <% general_outdated_comm_count_ver = len(c.comment_versions[c.at_version_num]['outdated']) %> | |
|
255 | ||
|
235 | ## show comment/inline comments summary | |
|
236 | <%def name="comments_summary()"> | |
|
237 | <tr> | |
|
238 | <td colspan="6" class="comments-summary-td"> | |
|
256 | 239 | |
|
257 | 240 | % if c.at_version: |
|
258 | 241 | <% inline_comm_count_ver = len(c.inline_versions[c.at_version_num]['display']) %> |
@@ -264,6 +247,7 b'' | |||
|
264 | 247 | ${_('Comments for this pull request')}: |
|
265 | 248 | % endif |
|
266 | 249 | |
|
250 | ||
|
267 | 251 | %if general_comm_count_ver: |
|
268 | 252 | <a href="#comments">${_("%d General ") % general_comm_count_ver}</a> |
|
269 | 253 | %else: |
@@ -285,37 +269,18 b'' | |||
|
285 | 269 | %endif |
|
286 | 270 | </td> |
|
287 | 271 | </tr> |
|
288 | ||
|
289 |
|
|
|
290 | <td></td> | |
|
291 | <td colspan="4"> | |
|
292 | % if c.at_version: | |
|
293 | <pre> | |
|
294 | Changed commits: | |
|
295 | * added: ${len(c.changes.added)} | |
|
296 | * removed: ${len(c.changes.removed)} | |
|
297 | ||
|
298 | % if not (c.file_changes.added+c.file_changes.modified+c.file_changes.removed): | |
|
299 | No file changes found | |
|
300 | % else: | |
|
301 | Changed files: | |
|
302 | %for file_name in c.file_changes.added: | |
|
303 | * A <a href="#${'a_' + h.FID('', file_name)}">${file_name}</a> | |
|
304 | %endfor | |
|
305 | %for file_name in c.file_changes.modified: | |
|
306 | * M <a href="#${'a_' + h.FID('', file_name)}">${file_name}</a> | |
|
307 | %endfor | |
|
308 | %for file_name in c.file_changes.removed: | |
|
309 | * R ${file_name} | |
|
310 | %endfor | |
|
311 | % endif | |
|
312 | </pre> | |
|
313 | % endif | |
|
314 | </td> | |
|
315 | </tr> | |
|
272 | </%def> | |
|
273 | ${comments_summary()} | |
|
316 | 274 | </table> |
|
317 | 275 | % else: |
|
276 | <div class="input"> | |
|
318 | 277 | ${_('Pull request versions not available')}. |
|
278 | </div> | |
|
279 | <div> | |
|
280 | <table> | |
|
281 | ${comments_summary()} | |
|
282 | </table> | |
|
283 | </div> | |
|
319 | 284 | % endif |
|
320 | 285 | </div> |
|
321 | 286 | </div> |
@@ -426,7 +391,15 b' Changed files:' | |||
|
426 | 391 | </div> |
|
427 | 392 | </div> |
|
428 | 393 | % endif |
|
394 | ||
|
429 | 395 |
|
|
396 | % if not c.compare_mode: | |
|
397 | ||
|
398 | % if c.at_version_pos: | |
|
399 | <h4> | |
|
400 | ${_('Showing changes at v%d, commenting is disabled.') % c.at_version_pos} | |
|
401 | </h4> | |
|
402 | % endif | |
|
430 | 403 | |
|
431 | 404 | <div class="pull-left"> |
|
432 | 405 | <div class="btn-group"> |
@@ -453,11 +426,113 b' Changed files:' | |||
|
453 | 426 | % endif |
|
454 | 427 | |
|
455 | 428 | </div> |
|
456 | ||
|
429 | % endif | |
|
457 | 430 |
|
|
458 | 431 | |
|
459 | 432 | % if not c.missing_commits: |
|
433 | % if c.compare_mode: | |
|
434 | % if c.at_version: | |
|
435 | <h4> | |
|
436 | ${_('Commits and changes between v{ver_from} and {ver_to} of this pull request, commenting is disabled').format(ver_from=c.from_version_pos, ver_to=c.at_version_pos if c.at_version_pos else 'latest')}: | |
|
437 | </h4> | |
|
438 | ||
|
439 | <div class="subtitle-compare"> | |
|
440 | ${_('commits added: {}, removed: {}').format(len(c.commit_changes_summary.added), len(c.commit_changes_summary.removed))} | |
|
441 | </div> | |
|
442 | ||
|
443 | <div class="container"> | |
|
444 | <table class="rctable compare_view_commits"> | |
|
445 | <tr> | |
|
446 | <th></th> | |
|
447 | <th>${_('Time')}</th> | |
|
448 | <th>${_('Author')}</th> | |
|
449 | <th>${_('Commit')}</th> | |
|
450 | <th></th> | |
|
451 | <th>${_('Description')}</th> | |
|
452 | </tr> | |
|
453 | ||
|
454 | % for c_type, commit in c.commit_changes: | |
|
455 | % if c_type in ['a', 'r']: | |
|
456 | <% | |
|
457 | if c_type == 'a': | |
|
458 | cc_title = _('Commit added in displayed changes') | |
|
459 | elif c_type == 'r': | |
|
460 | cc_title = _('Commit removed in displayed changes') | |
|
461 | else: | |
|
462 | cc_title = '' | |
|
463 | %> | |
|
464 | <tr id="row-${commit.raw_id}" commit_id="${commit.raw_id}" class="compare_select"> | |
|
465 | <td> | |
|
466 | <div class="commit-change-indicator color-${c_type}-border"> | |
|
467 | <div class="commit-change-content color-${c_type} tooltip" title="${cc_title}"> | |
|
468 | ${c_type.upper()} | |
|
469 | </div> | |
|
470 | </div> | |
|
471 | </td> | |
|
472 | <td class="td-time"> | |
|
473 | ${h.age_component(commit.date)} | |
|
474 | </td> | |
|
475 | <td class="td-user"> | |
|
476 | ${base.gravatar_with_user(commit.author, 16)} | |
|
477 | </td> | |
|
478 | <td class="td-hash"> | |
|
479 | <code> | |
|
480 | <a href="${h.url('changeset_home', repo_name=c.target_repo.repo_name, revision=commit.raw_id)}"> | |
|
481 | r${commit.revision}:${h.short_id(commit.raw_id)} | |
|
482 | </a> | |
|
483 | ${h.hidden('revisions', commit.raw_id)} | |
|
484 | </code> | |
|
485 | </td> | |
|
486 | <td class="expand_commit" data-commit-id="${commit.raw_id}" title="${_( 'Expand commit message')}"> | |
|
487 | <div class="show_more_col"> | |
|
488 | <i class="show_more"></i> | |
|
489 | </div> | |
|
490 | </td> | |
|
491 | <td class="mid td-description"> | |
|
492 | <div class="log-container truncate-wrap"> | |
|
493 | <div class="message truncate" id="c-${commit.raw_id}" data-message-raw="${commit.message}"> | |
|
494 | ${h.urlify_commit_message(commit.message, c.repo_name)} | |
|
495 | </div> | |
|
496 | </div> | |
|
497 | </td> | |
|
498 | </tr> | |
|
499 | % endif | |
|
500 | % endfor | |
|
501 | </table> | |
|
502 | </div> | |
|
503 | ||
|
504 | <script> | |
|
505 | $('.expand_commit').on('click',function(e){ | |
|
506 | var target_expand = $(this); | |
|
507 | var cid = target_expand.data('commitId'); | |
|
508 | ||
|
509 | if (target_expand.hasClass('open')){ | |
|
510 | $('#c-'+cid).css({ | |
|
511 | 'height': '1.5em', | |
|
512 | 'white-space': 'nowrap', | |
|
513 | 'text-overflow': 'ellipsis', | |
|
514 | 'overflow':'hidden' | |
|
515 | }); | |
|
516 | target_expand.removeClass('open'); | |
|
517 | } | |
|
518 | else { | |
|
519 | $('#c-'+cid).css({ | |
|
520 | 'height': 'auto', | |
|
521 | 'white-space': 'pre-line', | |
|
522 | 'text-overflow': 'initial', | |
|
523 | 'overflow':'visible' | |
|
524 | }); | |
|
525 | target_expand.addClass('open'); | |
|
526 | } | |
|
527 | }); | |
|
528 | </script> | |
|
529 | ||
|
530 | % endif | |
|
531 | ||
|
532 | % else: | |
|
460 | 533 | <%include file="/compare/compare_commits.mako" /> |
|
534 | % endif | |
|
535 | ||
|
461 | 536 | <div class="cs_files"> |
|
462 | 537 | <%namespace name="cbdiffs" file="/codeblocks/diffs.mako"/> |
|
463 | 538 | ${cbdiffs.render_diffset_menu()} |
@@ -528,6 +603,107 b' Changed files:' | |||
|
528 | 603 | } |
|
529 | 604 | } |
|
530 | 605 | |
|
606 | VersionController = function() { | |
|
607 | var self = this; | |
|
608 | this.$verSource = $('input[name=ver_source]'); | |
|
609 | this.$verTarget = $('input[name=ver_target]'); | |
|
610 | ||
|
611 | this.adjustRadioSelectors = function (curNode) { | |
|
612 | var getVal = function(item) { | |
|
613 | if (item == 'latest'){ | |
|
614 | return Number.MAX_SAFE_INTEGER | |
|
615 | } | |
|
616 | else { | |
|
617 | return parseInt(item) | |
|
618 | } | |
|
619 | }; | |
|
620 | ||
|
621 | var curVal = getVal($(curNode).val()); | |
|
622 | $.each(self.$verSource, function(index, value){ | |
|
623 | var elVal = getVal($(value).val()); | |
|
624 | if(elVal > curVal){ | |
|
625 | $(value).attr('disabled', 'disabled'); | |
|
626 | $(value).removeAttr('checked'); | |
|
627 | } | |
|
628 | else{ | |
|
629 | $(value).removeAttr('disabled'); | |
|
630 | } | |
|
631 | }); | |
|
632 | ||
|
633 | self.setLockAction(false, $(curNode).data('verPos')); | |
|
634 | }; | |
|
635 | ||
|
636 | ||
|
637 | this.attachVersionListener = function () { | |
|
638 | self.$verTarget.change(function(e){ | |
|
639 | self.adjustRadioSelectors(this) | |
|
640 | }); | |
|
641 | self.$verSource.change(function(e){ | |
|
642 | self.adjustRadioSelectors(self.$verTarget.filter(':checked')) | |
|
643 | }); | |
|
644 | }; | |
|
645 | ||
|
646 | this.init = function () { | |
|
647 | ||
|
648 | var curNode = self.$verTarget.filter(':checked'); | |
|
649 | self.adjustRadioSelectors(curNode); | |
|
650 | self.setLockAction(true); | |
|
651 | self.attachVersionListener(); | |
|
652 | ||
|
653 | }; | |
|
654 | ||
|
655 | this.setLockAction = function (state, selectedVersion) { | |
|
656 | if(state){ | |
|
657 | $('#show-version-diff').attr('disabled','disabled') | |
|
658 | $('#show-version-diff').addClass('disabled') | |
|
659 | $('#show-version-diff').html($('#show-version-diff').data('labelText')); | |
|
660 | } | |
|
661 | else{ | |
|
662 | $('#show-version-diff').removeAttr('disabled'); | |
|
663 | $('#show-version-diff').removeClass('disabled') | |
|
664 | //$('#show-version-diff').html(_gettext('show changes for v') + selectedVersion) | |
|
665 | } | |
|
666 | ||
|
667 | }; | |
|
668 | ||
|
669 | this.showVersionDiff = function(){ | |
|
670 | var target = self.$verTarget.filter(':checked'); | |
|
671 | var source = self.$verSource.filter(':checked'); | |
|
672 | ||
|
673 | if (target.val() && source.val()) { | |
|
674 | var params = { | |
|
675 | 'pull_request_id': ${c.pull_request.pull_request_id}, | |
|
676 | 'repo_name': templateContext.repo_name, | |
|
677 | 'version': target.val(), | |
|
678 | 'from_version': source.val() | |
|
679 | }; | |
|
680 | window.location = pyroutes.url('pullrequest_show', params) | |
|
681 | } | |
|
682 | ||
|
683 | return false; | |
|
684 | }; | |
|
685 | ||
|
686 | this.toggleVersionView = function (elem) { | |
|
687 | ||
|
688 | if ($('#show-version-diff').is(':visible')) { | |
|
689 | $('.version-pr').hide(); | |
|
690 | $('#show-version-diff').hide(); | |
|
691 | $(elem).html($(elem).data('toggleOn')) | |
|
692 | } else { | |
|
693 | $('.version-pr').show(); | |
|
694 | $('#show-version-diff').show(); | |
|
695 | $(elem).html($(elem).data('toggleOff')) | |
|
696 | } | |
|
697 | ||
|
698 | return false | |
|
699 | } | |
|
700 | ||
|
701 | }; | |
|
702 | ||
|
703 | versionController = new VersionController(); | |
|
704 | versionController.init(); | |
|
705 | ||
|
706 | ||
|
531 | 707 | $(function(){ |
|
532 | 708 | ReviewerAutoComplete('user'); |
|
533 | 709 | // custom code mirror |
General Comments 0
You need to be logged in to leave comments.
Login now