Show More
@@ -320,7 +320,7 b' class TestCreatePullRequestApi(object):' | |||
|
320 | 320 | id_, params = build_data( |
|
321 | 321 | self.apikey_regular, 'create_pull_request', **data) |
|
322 | 322 | response = api_call(self.app, params) |
|
323 | expected_message = 'no commits found' | |
|
323 | expected_message = 'no commits found for merge between specified references' | |
|
324 | 324 | assert_error(id_, expected_message, given=response.body) |
|
325 | 325 | |
|
326 | 326 | @pytest.mark.backends("git", "hg") |
@@ -29,6 +29,7 b' from rhodecode.api.tests.utils import (' | |||
|
29 | 29 | |
|
30 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 31 | class TestGetPullRequest(object): |
|
32 | ||
|
32 | 33 | @pytest.mark.backends("git", "hg") |
|
33 | 34 | def test_api_get_pull_requests(self, pr_util): |
|
34 | 35 | pull_request = pr_util.create_pull_request() |
@@ -40,6 +41,7 b' class TestGetPullRequest(object):' | |||
|
40 | 41 | target_ref=pull_request.target_ref, |
|
41 | 42 | revisions=pull_request.revisions, |
|
42 | 43 | reviewers=(), |
|
44 | observers=(), | |
|
43 | 45 | title=pull_request.title, |
|
44 | 46 | description=pull_request.description, |
|
45 | 47 | ) |
@@ -51,6 +51,7 b' class TestUpdatePullRequest(object):' | |||
|
51 | 51 | "pull_request": response.json['result']['pull_request'], |
|
52 | 52 | "updated_commits": {"added": [], "common": [], "removed": []}, |
|
53 | 53 | "updated_reviewers": {"added": [], "removed": []}, |
|
54 | "updated_observers": {"added": [], "removed": []}, | |
|
54 | 55 | } |
|
55 | 56 | |
|
56 | 57 | response_json = response.json['result'] |
@@ -111,6 +112,7 b' class TestUpdatePullRequest(object):' | |||
|
111 | 112 | "total": total_commits, |
|
112 | 113 | "removed": []}, |
|
113 | 114 | "updated_reviewers": {"added": [], "removed": []}, |
|
115 | "updated_observers": {"added": [], "removed": []}, | |
|
114 | 116 | } |
|
115 | 117 | |
|
116 | 118 | assert_ok(id_, expected, response.body) |
@@ -122,7 +124,7 b' class TestUpdatePullRequest(object):' | |||
|
122 | 124 | b = user_util.create_user() |
|
123 | 125 | c = user_util.create_user() |
|
124 | 126 | new_reviewers = [ |
|
125 | {'username': b.username,'reasons': ['updated via API'], | |
|
127 | {'username': b.username, 'reasons': ['updated via API'], | |
|
126 | 128 | 'mandatory':False}, |
|
127 | 129 | {'username': c.username, 'reasons': ['updated via API'], |
|
128 | 130 | 'mandatory':False}, |
@@ -132,7 +134,7 b' class TestUpdatePullRequest(object):' | |||
|
132 | 134 | removed = [a.username] |
|
133 | 135 | |
|
134 | 136 | pull_request = pr_util.create_pull_request( |
|
135 | reviewers=[(a.username, ['added via API'], False, [])]) | |
|
137 | reviewers=[(a.username, ['added via API'], False, 'reviewer', [])]) | |
|
136 | 138 | |
|
137 | 139 | id_, params = build_data( |
|
138 | 140 | self.apikey, 'update_pull_request', |
@@ -146,6 +148,7 b' class TestUpdatePullRequest(object):' | |||
|
146 | 148 | "pull_request": response.json['result']['pull_request'], |
|
147 | 149 | "updated_commits": {"added": [], "common": [], "removed": []}, |
|
148 | 150 | "updated_reviewers": {"added": added, "removed": removed}, |
|
151 | "updated_observers": {"added": [], "removed": []}, | |
|
149 | 152 | } |
|
150 | 153 | |
|
151 | 154 | assert_ok(id_, expected, response.body) |
@@ -30,9 +30,11 b' from rhodecode.lib import channelstream' | |||
|
30 | 30 | from rhodecode.lib.auth import (HasRepoPermissionAnyApi) |
|
31 | 31 | from rhodecode.lib.base import vcs_operation_context |
|
32 | 32 | from rhodecode.lib.utils2 import str2bool |
|
33 | from rhodecode.lib.vcs.backends.base import unicode_to_reference | |
|
33 | 34 | from rhodecode.model.changeset_status import ChangesetStatusModel |
|
34 | 35 | from rhodecode.model.comment import CommentsModel |
|
35 | from rhodecode.model.db import Session, ChangesetStatus, ChangesetComment, PullRequest | |
|
36 | from rhodecode.model.db import ( | |
|
37 | Session, ChangesetStatus, ChangesetComment, PullRequest, PullRequestReviewers) | |
|
36 | 38 | from rhodecode.model.pull_request import PullRequestModel, MergeCheck |
|
37 | 39 | from rhodecode.model.settings import SettingsModel |
|
38 | 40 | from rhodecode.model.validation_schema import Invalid |
@@ -600,7 +602,7 b' def comment_pull_request(' | |||
|
600 | 602 | extra_recipients=extra_recipients, |
|
601 | 603 | send_email=send_email |
|
602 | 604 | ) |
|
603 |
is_inline = |
|
|
605 | is_inline = comment.is_inline | |
|
604 | 606 | |
|
605 | 607 | if allowed_to_change_status and status: |
|
606 | 608 | old_calculated_status = pull_request.calculated_review_status() |
@@ -646,12 +648,26 b' def comment_pull_request(' | |||
|
646 | 648 | |
|
647 | 649 | return data |
|
648 | 650 | |
|
651 | def _reviewers_validation(obj_list): | |
|
652 | schema = ReviewerListSchema() | |
|
653 | try: | |
|
654 | reviewer_objects = schema.deserialize(obj_list) | |
|
655 | except Invalid as err: | |
|
656 | raise JSONRPCValidationError(colander_exc=err) | |
|
657 | ||
|
658 | # validate users | |
|
659 | for reviewer_object in reviewer_objects: | |
|
660 | user = get_user_or_error(reviewer_object['username']) | |
|
661 | reviewer_object['user_id'] = user.user_id | |
|
662 | return reviewer_objects | |
|
663 | ||
|
649 | 664 | |
|
650 | 665 | @jsonrpc_method() |
|
651 | 666 | def create_pull_request( |
|
652 | 667 | request, apiuser, source_repo, target_repo, source_ref, target_ref, |
|
653 | 668 | owner=Optional(OAttr('apiuser')), title=Optional(''), description=Optional(''), |
|
654 |
description_renderer=Optional(''), |
|
|
669 | description_renderer=Optional(''), | |
|
670 | reviewers=Optional(None), observers=Optional(None)): | |
|
655 | 671 | """ |
|
656 | 672 | Creates a new pull request. |
|
657 | 673 | |
@@ -689,6 +705,13 b' def create_pull_request(' | |||
|
689 | 705 | Accepts username strings or objects of the format: |
|
690 | 706 | |
|
691 | 707 | [{'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}] |
|
708 | :param observers: Set the new pull request observers list. | |
|
709 | Reviewer defined by review rules will be added automatically to the | |
|
710 | defined list. This feature is only available in RhodeCode EE | |
|
711 | :type observers: Optional(list) | |
|
712 | Accepts username strings or objects of the format: | |
|
713 | ||
|
714 | [{'username': 'nick', 'reasons': ['original author']}] | |
|
692 | 715 | """ |
|
693 | 716 | |
|
694 | 717 | source_db_repo = get_repo_or_error(source_repo) |
@@ -702,38 +725,39 b' def create_pull_request(' | |||
|
702 | 725 | full_source_ref = resolve_ref_or_error(source_ref, source_db_repo) |
|
703 | 726 | full_target_ref = resolve_ref_or_error(target_ref, target_db_repo) |
|
704 | 727 | |
|
705 |
|
|
|
706 |
|
|
|
728 | get_commit_or_error(full_source_ref, source_db_repo) | |
|
729 | get_commit_or_error(full_target_ref, target_db_repo) | |
|
707 | 730 | |
|
708 | 731 | reviewer_objects = Optional.extract(reviewers) or [] |
|
732 | observer_objects = Optional.extract(observers) or [] | |
|
709 | 733 | |
|
710 | 734 | # serialize and validate passed in given reviewers |
|
711 | 735 | if reviewer_objects: |
|
712 | schema = ReviewerListSchema() | |
|
713 | try: | |
|
714 | reviewer_objects = schema.deserialize(reviewer_objects) | |
|
715 | except Invalid as err: | |
|
716 | raise JSONRPCValidationError(colander_exc=err) | |
|
736 | reviewer_objects = _reviewers_validation(reviewer_objects) | |
|
717 | 737 | |
|
718 | # validate users | |
|
719 |
|
|
|
720 | user = get_user_or_error(reviewer_object['username']) | |
|
721 | reviewer_object['user_id'] = user.user_id | |
|
738 | if observer_objects: | |
|
739 | observer_objects = _reviewers_validation(reviewer_objects) | |
|
722 | 740 | |
|
723 | 741 | get_default_reviewers_data, validate_default_reviewers, validate_observers = \ |
|
724 | 742 | PullRequestModel().get_reviewer_functions() |
|
725 | 743 | |
|
744 | source_ref_obj = unicode_to_reference(full_source_ref) | |
|
745 | target_ref_obj = unicode_to_reference(full_target_ref) | |
|
746 | ||
|
726 | 747 | # recalculate reviewers logic, to make sure we can validate this |
|
727 | 748 | default_reviewers_data = get_default_reviewers_data( |
|
728 | 749 | owner, |
|
729 | source_repo, | |
|
730 | Reference(source_type, source_name, source_commit_id), | |
|
731 | target_repo, | |
|
732 | Reference(target_type, target_name, target_commit_id) | |
|
750 | source_db_repo, | |
|
751 | source_ref_obj, | |
|
752 | target_db_repo, | |
|
753 | target_ref_obj, | |
|
733 | 754 | ) |
|
734 | 755 | |
|
735 | # now MERGE our given with the calculated | |
|
736 | reviewer_objects = default_reviewers_data['reviewers'] + reviewer_objects | |
|
756 | # now MERGE our given with the calculated from the default rules | |
|
757 | just_reviewers = [ | |
|
758 | x for x in default_reviewers_data['reviewers'] | |
|
759 | if x['role'] == PullRequestReviewers.ROLE_REVIEWER] | |
|
760 | reviewer_objects = just_reviewers + reviewer_objects | |
|
737 | 761 | |
|
738 | 762 | try: |
|
739 | 763 | reviewers = validate_default_reviewers( |
@@ -741,9 +765,21 b' def create_pull_request(' | |||
|
741 | 765 | except ValueError as e: |
|
742 | 766 | raise JSONRPCError('Reviewers Validation: {}'.format(e)) |
|
743 | 767 | |
|
768 | # now MERGE our given with the calculated from the default rules | |
|
769 | just_observers = [ | |
|
770 | x for x in default_reviewers_data['reviewers'] | |
|
771 | if x['role'] == PullRequestReviewers.ROLE_OBSERVER] | |
|
772 | observer_objects = just_observers + observer_objects | |
|
773 | ||
|
774 | try: | |
|
775 | observers = validate_observers( | |
|
776 | observer_objects, default_reviewers_data) | |
|
777 | except ValueError as e: | |
|
778 | raise JSONRPCError('Observer Validation: {}'.format(e)) | |
|
779 | ||
|
744 | 780 | title = Optional.extract(title) |
|
745 | 781 | if not title: |
|
746 |
title_source_ref = source_ref. |
|
|
782 | title_source_ref = source_ref_obj.name | |
|
747 | 783 | title = PullRequestModel().generate_pullrequest_title( |
|
748 | 784 | source=source_repo, |
|
749 | 785 | source_ref=title_source_ref, |
@@ -752,20 +788,17 b' def create_pull_request(' | |||
|
752 | 788 | |
|
753 | 789 | diff_info = default_reviewers_data['diff_info'] |
|
754 | 790 | common_ancestor_id = diff_info['ancestor'] |
|
755 | commits = diff_info['commits'] | |
|
791 | # NOTE(marcink): reversed is consistent with how we open it in the WEB interface | |
|
792 | commits = [commit['commit_id'] for commit in reversed(diff_info['commits'])] | |
|
756 | 793 | |
|
757 | 794 | if not common_ancestor_id: |
|
758 | raise JSONRPCError('no common ancestor found') | |
|
795 | raise JSONRPCError('no common ancestor found between specified references') | |
|
759 | 796 | |
|
760 | 797 | if not commits: |
|
761 | raise JSONRPCError('no commits found') | |
|
762 | ||
|
763 | # NOTE(marcink): reversed is consistent with how we open it in the WEB interface | |
|
764 | revisions = [commit.raw_id for commit in reversed(commits)] | |
|
798 | raise JSONRPCError('no commits found for merge between specified references') | |
|
765 | 799 | |
|
766 | 800 | # recalculate target ref based on ancestor |
|
767 | target_ref_type, target_ref_name, __ = full_target_ref.split(':') | |
|
768 | full_target_ref = ':'.join((target_ref_type, target_ref_name, common_ancestor_id)) | |
|
801 | full_target_ref = ':'.join((target_ref_obj.type, target_ref_obj.name, common_ancestor_id)) | |
|
769 | 802 | |
|
770 | 803 | # fetch renderer, if set fallback to plain in case of PR |
|
771 | 804 | rc_config = SettingsModel().get_all_settings() |
@@ -780,8 +813,9 b' def create_pull_request(' | |||
|
780 | 813 | target_repo=target_repo, |
|
781 | 814 | target_ref=full_target_ref, |
|
782 | 815 | common_ancestor_id=common_ancestor_id, |
|
783 |
revisions= |
|
|
816 | revisions=commits, | |
|
784 | 817 | reviewers=reviewers, |
|
818 | observers=observers, | |
|
785 | 819 | title=title, |
|
786 | 820 | description=description, |
|
787 | 821 | description_renderer=description_renderer, |
@@ -801,7 +835,7 b' def create_pull_request(' | |||
|
801 | 835 | def update_pull_request( |
|
802 | 836 | request, apiuser, pullrequestid, repoid=Optional(None), |
|
803 | 837 | title=Optional(''), description=Optional(''), description_renderer=Optional(''), |
|
804 | reviewers=Optional(None), update_commits=Optional(None)): | |
|
838 | reviewers=Optional(None), observers=Optional(None), update_commits=Optional(None)): | |
|
805 | 839 | """ |
|
806 | 840 | Updates a pull request. |
|
807 | 841 | |
@@ -823,7 +857,11 b' def update_pull_request(' | |||
|
823 | 857 | Accepts username strings or objects of the format: |
|
824 | 858 | |
|
825 | 859 | [{'username': 'nick', 'reasons': ['original author'], 'mandatory': <bool>}] |
|
860 | :param observers: Update pull request observers list with new value. | |
|
861 | :type observers: Optional(list) | |
|
862 | Accepts username strings or objects of the format: | |
|
826 | 863 | |
|
864 | [{'username': 'nick', 'reasons': ['should be aware about this PR']}] | |
|
827 | 865 | :param update_commits: Trigger update of commits for this pull request |
|
828 | 866 | :type: update_commits: Optional(bool) |
|
829 | 867 | |
@@ -841,6 +879,12 b' def update_pull_request(' | |||
|
841 | 879 | ], |
|
842 | 880 | "removed": [] |
|
843 | 881 | }, |
|
882 | "updated_observers": { | |
|
883 | "added": [ | |
|
884 | "username" | |
|
885 | ], | |
|
886 | "removed": [] | |
|
887 | }, | |
|
844 | 888 | "updated_commits": { |
|
845 | 889 | "added": [ |
|
846 | 890 | "<sha1_hash>" |
@@ -872,30 +916,7 b' def update_pull_request(' | |||
|
872 | 916 | pullrequestid,)) |
|
873 | 917 | |
|
874 | 918 | reviewer_objects = Optional.extract(reviewers) or [] |
|
875 | ||
|
876 | if reviewer_objects: | |
|
877 | schema = ReviewerListSchema() | |
|
878 | try: | |
|
879 | reviewer_objects = schema.deserialize(reviewer_objects) | |
|
880 | except Invalid as err: | |
|
881 | raise JSONRPCValidationError(colander_exc=err) | |
|
882 | ||
|
883 | # validate users | |
|
884 | for reviewer_object in reviewer_objects: | |
|
885 | user = get_user_or_error(reviewer_object['username']) | |
|
886 | reviewer_object['user_id'] = user.user_id | |
|
887 | ||
|
888 | get_default_reviewers_data, get_validated_reviewers, validate_observers = \ | |
|
889 | PullRequestModel().get_reviewer_functions() | |
|
890 | ||
|
891 | # re-use stored rules | |
|
892 | reviewer_rules = pull_request.reviewer_data | |
|
893 | try: | |
|
894 | reviewers = get_validated_reviewers(reviewer_objects, reviewer_rules) | |
|
895 | except ValueError as e: | |
|
896 | raise JSONRPCError('Reviewers Validation: {}'.format(e)) | |
|
897 | else: | |
|
898 | reviewers = [] | |
|
919 | observer_objects = Optional.extract(observers) or [] | |
|
899 | 920 | |
|
900 | 921 | title = Optional.extract(title) |
|
901 | 922 | description = Optional.extract(description) |
@@ -935,12 +956,41 b' def update_pull_request(' | |||
|
935 | 956 | commits_changed = True |
|
936 | 957 | |
|
937 | 958 | # Update reviewers |
|
959 | # serialize and validate passed in given reviewers | |
|
960 | if reviewer_objects: | |
|
961 | reviewer_objects = _reviewers_validation(reviewer_objects) | |
|
962 | ||
|
963 | if observer_objects: | |
|
964 | observer_objects = _reviewers_validation(reviewer_objects) | |
|
965 | ||
|
966 | # re-use stored rules | |
|
967 | default_reviewers_data = pull_request.reviewer_data | |
|
968 | ||
|
969 | __, validate_default_reviewers, validate_observers = \ | |
|
970 | PullRequestModel().get_reviewer_functions() | |
|
971 | ||
|
972 | if reviewer_objects: | |
|
973 | try: | |
|
974 | reviewers = validate_default_reviewers(reviewer_objects, default_reviewers_data) | |
|
975 | except ValueError as e: | |
|
976 | raise JSONRPCError('Reviewers Validation: {}'.format(e)) | |
|
977 | else: | |
|
978 | reviewers = [] | |
|
979 | ||
|
980 | if observer_objects: | |
|
981 | try: | |
|
982 | observers = validate_default_reviewers(reviewer_objects, default_reviewers_data) | |
|
983 | except ValueError as e: | |
|
984 | raise JSONRPCError('Observer Validation: {}'.format(e)) | |
|
985 | else: | |
|
986 | observers = [] | |
|
987 | ||
|
938 | 988 | reviewers_changed = False |
|
939 | 989 | reviewers_changes = {"added": [], "removed": []} |
|
940 | 990 | if reviewers: |
|
941 | 991 | old_calculated_status = pull_request.calculated_review_status() |
|
942 | 992 | added_reviewers, removed_reviewers = \ |
|
943 | PullRequestModel().update_reviewers(pull_request, reviewers, apiuser) | |
|
993 | PullRequestModel().update_reviewers(pull_request, reviewers, apiuser.get_instance()) | |
|
944 | 994 | |
|
945 | 995 | reviewers_changes['added'] = sorted( |
|
946 | 996 | [get_user_or_error(n).username for n in added_reviewers]) |
@@ -957,6 +1007,18 b' def update_pull_request(' | |||
|
957 | 1007 | reviewers_changed = True |
|
958 | 1008 | |
|
959 | 1009 | observers_changed = False |
|
1010 | observers_changes = {"added": [], "removed": []} | |
|
1011 | if observers: | |
|
1012 | added_observers, removed_observers = \ | |
|
1013 | PullRequestModel().update_observers(pull_request, observers, apiuser.get_instance()) | |
|
1014 | ||
|
1015 | observers_changes['added'] = sorted( | |
|
1016 | [get_user_or_error(n).username for n in added_observers]) | |
|
1017 | observers_changes['removed'] = sorted( | |
|
1018 | [get_user_or_error(n).username for n in removed_observers]) | |
|
1019 | Session().commit() | |
|
1020 | ||
|
1021 | reviewers_changed = True | |
|
960 | 1022 | |
|
961 | 1023 | # push changed to channelstream |
|
962 | 1024 | if commits_changed or reviewers_changed or observers_changed: |
@@ -966,11 +1028,11 b' def update_pull_request(' | |||
|
966 | 1028 | request, pr_broadcast_channel, apiuser, msg) |
|
967 | 1029 | |
|
968 | 1030 | data = { |
|
969 | 'msg': 'Updated pull request `{}`'.format( | |
|
970 | pull_request.pull_request_id), | |
|
1031 | 'msg': 'Updated pull request `{}`'.format(pull_request.pull_request_id), | |
|
971 | 1032 | 'pull_request': pull_request.get_api_data(), |
|
972 | 1033 | 'updated_commits': commit_changes, |
|
973 | 'updated_reviewers': reviewers_changes | |
|
1034 | 'updated_reviewers': reviewers_changes, | |
|
1035 | 'updated_observers': observers_changes, | |
|
974 | 1036 | } |
|
975 | 1037 | |
|
976 | 1038 | return data |
@@ -1653,7 +1653,7 b' def comment_commit(' | |||
|
1653 | 1653 | extra_recipients=extra_recipients, |
|
1654 | 1654 | send_email=send_email |
|
1655 | 1655 | ) |
|
1656 |
is_inline = |
|
|
1656 | is_inline = comment.is_inline | |
|
1657 | 1657 | |
|
1658 | 1658 | if status: |
|
1659 | 1659 | # also do a status change |
@@ -523,7 +523,9 b' class TestPullrequestsView(object):' | |||
|
523 | 523 | pull_request = pr_util.create_pull_request() |
|
524 | 524 | pull_request_id = pull_request.pull_request_id |
|
525 | 525 | PullRequestModel().update_reviewers( |
|
526 | pull_request_id, [(1, ['reason'], False, []), (2, ['reason2'], False, [])], | |
|
526 | pull_request_id, [ | |
|
527 | (1, ['reason'], False, 'reviewer', []), | |
|
528 | (2, ['reason2'], False, 'reviewer', [])], | |
|
527 | 529 | pull_request.author) |
|
528 | 530 | author = pull_request.user_id |
|
529 | 531 | repo = pull_request.target_repo.repo_id |
@@ -906,12 +908,13 b' class TestPullrequestsView(object):' | |||
|
906 | 908 | |
|
907 | 909 | # Change reviewers and check that a notification was made |
|
908 | 910 | PullRequestModel().update_reviewers( |
|
909 |
pull_request.pull_request_id, [ |
|
|
911 | pull_request.pull_request_id, [ | |
|
912 | (1, [], False, 'reviewer', []) | |
|
913 | ], | |
|
910 | 914 | pull_request.author) |
|
911 | 915 | assert len(notifications.all()) == 2 |
|
912 | 916 | |
|
913 | def test_create_pull_request_stores_ancestor_commit_id(self, backend, | |
|
914 | csrf_token): | |
|
917 | def test_create_pull_request_stores_ancestor_commit_id(self, backend, csrf_token): | |
|
915 | 918 | commits = [ |
|
916 | 919 | {'message': 'ancestor', |
|
917 | 920 | 'added': [FileNode('file_A', content='content_of_ancestor')]}, |
@@ -413,7 +413,7 b' class RepoCommitsView(RepoAppView):' | |||
|
413 | 413 | resolves_comment_id=resolves_comment_id, |
|
414 | 414 | auth_user=self._rhodecode_user |
|
415 | 415 | ) |
|
416 |
is_inline = |
|
|
416 | is_inline = comment.is_inline | |
|
417 | 417 | |
|
418 | 418 | # get status if set ! |
|
419 | 419 | if status: |
@@ -40,7 +40,8 b' from rhodecode.lib.auth import (' | |||
|
40 | 40 | LoginRequired, HasRepoPermissionAny, HasRepoPermissionAnyDecorator, |
|
41 | 41 | NotAnonymous, CSRFRequired) |
|
42 | 42 | from rhodecode.lib.utils2 import str2bool, safe_str, safe_unicode, safe_int, aslist |
|
43 |
from rhodecode.lib.vcs.backends.base import |
|
|
43 | from rhodecode.lib.vcs.backends.base import ( | |
|
44 | EmptyCommit, UpdateFailureReason, unicode_to_reference) | |
|
44 | 45 | from rhodecode.lib.vcs.exceptions import ( |
|
45 | 46 | CommitDoesNotExistError, RepositoryRequirementError, EmptyRepositoryError) |
|
46 | 47 | from rhodecode.model.changeset_status import ChangesetStatusModel |
@@ -1146,16 +1147,17 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1146 | 1147 | source_scm = source_db_repo.scm_instance() |
|
1147 | 1148 | target_scm = target_db_repo.scm_instance() |
|
1148 | 1149 | |
|
1149 | source_commit = source_scm.get_commit(source_ref.split(':')[-1]) | |
|
1150 | target_commit = target_scm.get_commit(target_ref.split(':')[-1]) | |
|
1150 | source_ref_obj = unicode_to_reference(source_ref) | |
|
1151 | target_ref_obj = unicode_to_reference(target_ref) | |
|
1152 | ||
|
1153 | source_commit = source_scm.get_commit(source_ref_obj.commit_id) | |
|
1154 | target_commit = target_scm.get_commit(target_ref_obj.commit_id) | |
|
1151 | 1155 | |
|
1152 | 1156 | ancestor = source_scm.get_common_ancestor( |
|
1153 | 1157 | source_commit.raw_id, target_commit.raw_id, target_scm) |
|
1154 | 1158 | |
|
1155 | source_ref_type, source_ref_name, source_commit_id = _form['target_ref'].split(':') | |
|
1156 | target_ref_type, target_ref_name, target_commit_id = _form['source_ref'].split(':') | |
|
1157 | 1159 | # recalculate target ref based on ancestor |
|
1158 | target_ref = ':'.join((target_ref_type, target_ref_name, ancestor)) | |
|
1160 | target_ref = ':'.join((target_ref_obj.type, target_ref_obj.name, ancestor)) | |
|
1159 | 1161 | |
|
1160 | 1162 | get_default_reviewers_data, validate_default_reviewers, validate_observers = \ |
|
1161 | 1163 | PullRequestModel().get_reviewer_functions() |
@@ -1164,16 +1166,16 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1164 | 1166 | reviewer_rules = get_default_reviewers_data( |
|
1165 | 1167 | self._rhodecode_db_user, |
|
1166 | 1168 | source_db_repo, |
|
1167 | Reference(source_ref_type, source_ref_name, source_commit_id), | |
|
1169 | source_ref_obj, | |
|
1168 | 1170 | target_db_repo, |
|
1169 | Reference(target_ref_type, target_ref_name, target_commit_id), | |
|
1171 | target_ref_obj, | |
|
1170 | 1172 | include_diff_info=False) |
|
1171 | 1173 | |
|
1172 | 1174 | reviewers = validate_default_reviewers(_form['review_members'], reviewer_rules) |
|
1173 | 1175 | observers = validate_observers(_form['observer_members'], reviewer_rules) |
|
1174 | 1176 | |
|
1175 | 1177 | pullrequest_title = _form['pullrequest_title'] |
|
1176 |
title_source_ref = source_ref. |
|
|
1178 | title_source_ref = source_ref_obj.name | |
|
1177 | 1179 | if not pullrequest_title: |
|
1178 | 1180 | pullrequest_title = PullRequestModel().generate_pullrequest_title( |
|
1179 | 1181 | source=source_repo, |
@@ -1371,7 +1373,7 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1371 | 1373 | |
|
1372 | 1374 | old_calculated_status = pull_request.calculated_review_status() |
|
1373 | 1375 | PullRequestModel().update_reviewers( |
|
1374 | pull_request, reviewers, self._rhodecode_user) | |
|
1376 | pull_request, reviewers, self._rhodecode_db_user) | |
|
1375 | 1377 | |
|
1376 | 1378 | Session().commit() |
|
1377 | 1379 | |
@@ -1396,7 +1398,7 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1396 | 1398 | return |
|
1397 | 1399 | |
|
1398 | 1400 | PullRequestModel().update_observers( |
|
1399 | pull_request, observers, self._rhodecode_user) | |
|
1401 | pull_request, observers, self._rhodecode_db_user) | |
|
1400 | 1402 | |
|
1401 | 1403 | Session().commit() |
|
1402 | 1404 | msg = _('Pull request observers updated.') |
@@ -1563,6 +1565,7 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1563 | 1565 | pull_request, self._rhodecode_user, self.db_repo, message=text, |
|
1564 | 1566 | auth_user=self._rhodecode_user) |
|
1565 | 1567 | Session().flush() |
|
1568 | is_inline = comment.is_inline | |
|
1566 | 1569 | |
|
1567 | 1570 | PullRequestModel().trigger_pull_request_hook( |
|
1568 | 1571 | pull_request, self._rhodecode_user, 'comment', |
@@ -1596,7 +1599,7 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1596 | 1599 | resolves_comment_id=resolves_comment_id, |
|
1597 | 1600 | auth_user=self._rhodecode_user |
|
1598 | 1601 | ) |
|
1599 |
is_inline = |
|
|
1602 | is_inline = comment.is_inline | |
|
1600 | 1603 | |
|
1601 | 1604 | if allowed_to_change_status: |
|
1602 | 1605 | # calculate old status before we change it |
@@ -73,6 +73,29 b' class Reference(_Reference):' | |||
|
73 | 73 | return self.name |
|
74 | 74 | |
|
75 | 75 | |
|
76 | def unicode_to_reference(raw): | |
|
77 | """ | |
|
78 | Convert a unicode (or string) to a reference object. | |
|
79 | If unicode evaluates to False it returns None. | |
|
80 | """ | |
|
81 | if raw: | |
|
82 | refs = raw.split(':') | |
|
83 | return Reference(*refs) | |
|
84 | else: | |
|
85 | return None | |
|
86 | ||
|
87 | ||
|
88 | def reference_to_unicode(ref): | |
|
89 | """ | |
|
90 | Convert a reference object to unicode. | |
|
91 | If reference is None it returns None. | |
|
92 | """ | |
|
93 | if ref: | |
|
94 | return u':'.join(ref) | |
|
95 | else: | |
|
96 | return None | |
|
97 | ||
|
98 | ||
|
76 | 99 | class MergeFailureReason(object): |
|
77 | 100 | """ |
|
78 | 101 | Enumeration with all the reasons why the server side merge could fail. |
@@ -56,7 +56,8 b' from webhelpers2.text import remove_form' | |||
|
56 | 56 | |
|
57 | 57 | from rhodecode.translation import _ |
|
58 | 58 | from rhodecode.lib.vcs import get_vcs_instance, VCSError |
|
59 |
from rhodecode.lib.vcs.backends.base import |
|
|
59 | from rhodecode.lib.vcs.backends.base import ( | |
|
60 | EmptyCommit, Reference, unicode_to_reference, reference_to_unicode) | |
|
60 | 61 | from rhodecode.lib.utils2 import ( |
|
61 | 62 | str2bool, safe_str, get_commit_safe, safe_unicode, sha1_safe, |
|
62 | 63 | time_to_datetime, aslist, Optional, safe_int, get_clone_url, AttributeDict, |
@@ -4248,26 +4249,11 b' class _PullRequestBase(BaseModel):' | |||
|
4248 | 4249 | |
|
4249 | 4250 | @staticmethod |
|
4250 | 4251 | def unicode_to_reference(raw): |
|
4251 | """ | |
|
4252 | Convert a unicode (or string) to a reference object. | |
|
4253 | If unicode evaluates to False it returns None. | |
|
4254 | """ | |
|
4255 | if raw: | |
|
4256 | refs = raw.split(':') | |
|
4257 | return Reference(*refs) | |
|
4258 | else: | |
|
4259 | return None | |
|
4252 | return unicode_to_reference(raw) | |
|
4260 | 4253 | |
|
4261 | 4254 | @staticmethod |
|
4262 | 4255 | def reference_to_unicode(ref): |
|
4263 | """ | |
|
4264 | Convert a reference object to unicode. | |
|
4265 | If reference is None it returns None. | |
|
4266 | """ | |
|
4267 | if ref: | |
|
4268 | return u':'.join(ref) | |
|
4269 | else: | |
|
4270 | return None | |
|
4256 | return reference_to_unicode(ref) | |
|
4271 | 4257 | |
|
4272 | 4258 | def get_api_data(self, with_merge_state=True): |
|
4273 | 4259 | from rhodecode.model.pull_request import PullRequestModel |
@@ -4543,6 +4529,9 b' class PullRequestVersion(Base, _PullRequ' | |||
|
4543 | 4529 | @property |
|
4544 | 4530 | def reviewers(self): |
|
4545 | 4531 | return self.pull_request.reviewers |
|
4532 | @property | |
|
4533 | def reviewers(self): | |
|
4534 | return self.pull_request.reviewers | |
|
4546 | 4535 | |
|
4547 | 4536 | @property |
|
4548 | 4537 | def versions(self): |
@@ -4561,7 +4550,7 b' class PullRequestVersion(Base, _PullRequ' | |||
|
4561 | 4550 | def reviewers_statuses(self): |
|
4562 | 4551 | return self.pull_request.reviewers_statuses() |
|
4563 | 4552 | |
|
4564 | def observer(self): | |
|
4553 | def observers(self): | |
|
4565 | 4554 | return self.pull_request.observers() |
|
4566 | 4555 | |
|
4567 | 4556 |
@@ -1342,7 +1342,7 b' class PullRequestModel(BaseModel):' | |||
|
1342 | 1342 | 'repo.pull_request.reviewer.delete', {'old_data': user_data}, |
|
1343 | 1343 | user, pull_request) |
|
1344 | 1344 | |
|
1345 |
self.notify_reviewers(pull_request, ids_to_add, user |
|
|
1345 | self.notify_reviewers(pull_request, ids_to_add, user) | |
|
1346 | 1346 | return ids_to_add, ids_to_remove |
|
1347 | 1347 | |
|
1348 | 1348 | def update_observers(self, pull_request, observer_data, user): |
@@ -1425,7 +1425,7 b' class PullRequestModel(BaseModel):' | |||
|
1425 | 1425 | 'repo.pull_request.observer.delete', {'old_data': user_data}, |
|
1426 | 1426 | user, pull_request) |
|
1427 | 1427 | |
|
1428 |
self.notify_observers(pull_request, ids_to_add, user |
|
|
1428 | self.notify_observers(pull_request, ids_to_add, user) | |
|
1429 | 1429 | return ids_to_add, ids_to_remove |
|
1430 | 1430 | |
|
1431 | 1431 | def get_url(self, pull_request, request=None, permalink=False): |
@@ -21,12 +21,17 b'' | |||
|
21 | 21 | import colander |
|
22 | 22 | from rhodecode.model.validation_schema import validators, preparers, types |
|
23 | 23 | |
|
24 | DEFAULT_ROLE = 'reviewer' | |
|
25 | VALID_ROLES = ['reviewer', 'observer'] | |
|
26 | ||
|
24 | 27 | |
|
25 | 28 | class ReviewerSchema(colander.MappingSchema): |
|
26 | 29 | username = colander.SchemaNode(types.StrOrIntType()) |
|
27 | 30 | reasons = colander.SchemaNode(colander.List(), missing=['no reason specified']) |
|
28 | 31 | mandatory = colander.SchemaNode(colander.Boolean(), missing=False) |
|
29 | 32 | rules = colander.SchemaNode(colander.List(), missing=[]) |
|
33 | role = colander.SchemaNode(colander.String(), missing=DEFAULT_ROLE, | |
|
34 | validator=colander.OneOf(VALID_ROLES)) | |
|
30 | 35 | |
|
31 | 36 | |
|
32 | 37 | class ReviewerListSchema(colander.SequenceSchema): |
@@ -97,6 +97,7 b'' | |||
|
97 | 97 | <li>The server is being restarted.</li> |
|
98 | 98 | <li>The server is overloaded.</li> |
|
99 | 99 | <li>The link may be incorrect.</li> |
|
100 | <li><a onclick="window.location.reload()">Reload page</a></li> | |
|
100 | 101 | </ul> |
|
101 | 102 | </div> |
|
102 | 103 | <div class="inner-column"> |
@@ -122,7 +122,7 b' class TestPullRequestModel(object):' | |||
|
122 | 122 | |
|
123 | 123 | def test_get_awaiting_my_review(self, pull_request): |
|
124 | 124 | PullRequestModel().update_reviewers( |
|
125 | pull_request, [(pull_request.author, ['author'], False, [])], | |
|
125 | pull_request, [(pull_request.author, ['author'], False, 'reviewer', [])], | |
|
126 | 126 | pull_request.author) |
|
127 | 127 | Session().commit() |
|
128 | 128 | |
@@ -133,7 +133,7 b' class TestPullRequestModel(object):' | |||
|
133 | 133 | |
|
134 | 134 | def test_count_awaiting_my_review(self, pull_request): |
|
135 | 135 | PullRequestModel().update_reviewers( |
|
136 | pull_request, [(pull_request.author, ['author'], False, [])], | |
|
136 | pull_request, [(pull_request.author, ['author'], False, 'reviewer', [])], | |
|
137 | 137 | pull_request.author) |
|
138 | 138 | Session().commit() |
|
139 | 139 |
@@ -43,8 +43,8 b' from rhodecode.lib.utils2 import Attribu' | |||
|
43 | 43 | from rhodecode.model.changeset_status import ChangesetStatusModel |
|
44 | 44 | from rhodecode.model.comment import CommentsModel |
|
45 | 45 | from rhodecode.model.db import ( |
|
46 |
PullRequest, Repository, RhodeCodeSetting, ChangesetStatus, |
|
|
47 | UserGroup, RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi) | |
|
46 | PullRequest, PullRequestReviewers, Repository, RhodeCodeSetting, ChangesetStatus, | |
|
47 | RepoGroup, UserGroup, RepoRhodeCodeUi, RepoRhodeCodeSetting, RhodeCodeUi) | |
|
48 | 48 | from rhodecode.model.meta import Session |
|
49 | 49 | from rhodecode.model.pull_request import PullRequestModel |
|
50 | 50 | from rhodecode.model.repo import RepoModel |
@@ -968,7 +968,7 b' class PRTestUtility(object):' | |||
|
968 | 968 | def create_pull_request( |
|
969 | 969 | self, commits=None, target_head=None, source_head=None, |
|
970 | 970 | revisions=None, approved=False, author=None, mergeable=False, |
|
971 | enable_notifications=True, name_suffix=u'', reviewers=None, | |
|
971 | enable_notifications=True, name_suffix=u'', reviewers=None, observers=None, | |
|
972 | 972 | title=u"Test", description=u"Description"): |
|
973 | 973 | self.set_mergeable(mergeable) |
|
974 | 974 | if not enable_notifications: |
@@ -1005,6 +1005,7 b' class PRTestUtility(object):' | |||
|
1005 | 1005 | 'target_ref': self._default_branch_reference(target_head), |
|
1006 | 1006 | 'revisions': [self.commit_ids[r] for r in revisions], |
|
1007 | 1007 | 'reviewers': reviewers or self._get_reviewers(), |
|
1008 | 'observers': observers or self._get_observers(), | |
|
1008 | 1009 | 'title': title, |
|
1009 | 1010 | 'description': description, |
|
1010 | 1011 | } |
@@ -1037,9 +1038,15 b' class PRTestUtility(object):' | |||
|
1037 | 1038 | return reference |
|
1038 | 1039 | |
|
1039 | 1040 | def _get_reviewers(self): |
|
1041 | role = PullRequestReviewers.ROLE_REVIEWER | |
|
1040 | 1042 | return [ |
|
1041 | (TEST_USER_REGULAR_LOGIN, ['default1'], False, []), | |
|
1042 | (TEST_USER_REGULAR2_LOGIN, ['default2'], False, []), | |
|
1043 | (TEST_USER_REGULAR_LOGIN, ['default1'], False, role, []), | |
|
1044 | (TEST_USER_REGULAR2_LOGIN, ['default2'], False, role, []), | |
|
1045 | ] | |
|
1046 | ||
|
1047 | def _get_observers(self): | |
|
1048 | return [ | |
|
1049 | ||
|
1043 | 1050 | ] |
|
1044 | 1051 | |
|
1045 | 1052 | def update_source_repository(self, head=None): |
General Comments 0
You need to be logged in to leave comments.
Login now