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