Show More
The requested changes are too big and content was truncated. Show full diff
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
@@ -0,0 +1,37 b'' | |||
|
1 | import logging | |
|
2 | ||
|
3 | from sqlalchemy import * | |
|
4 | ||
|
5 | from rhodecode.model import meta | |
|
6 | from rhodecode.lib.dbmigrate.versions import _reset_base, notify | |
|
7 | ||
|
8 | log = logging.getLogger(__name__) | |
|
9 | ||
|
10 | ||
|
11 | def upgrade(migrate_engine): | |
|
12 | """ | |
|
13 | Upgrade operations go here. | |
|
14 | Don't create your own engine; bind migrate_engine to your metadata | |
|
15 | """ | |
|
16 | _reset_base(migrate_engine) | |
|
17 | from rhodecode.lib.dbmigrate.schema import db_4_13_0_0 as db | |
|
18 | ||
|
19 | pull_request = db.PullRequest.__table__ | |
|
20 | pull_request_version = db.PullRequestVersion.__table__ | |
|
21 | ||
|
22 | repo_state_1 = Column("pull_request_state", String(255), nullable=True) | |
|
23 | repo_state_1.create(table=pull_request) | |
|
24 | ||
|
25 | repo_state_2 = Column("pull_request_state", String(255), nullable=True) | |
|
26 | repo_state_2.create(table=pull_request_version) | |
|
27 | ||
|
28 | fixups(db, meta.Session) | |
|
29 | ||
|
30 | ||
|
31 | def downgrade(migrate_engine): | |
|
32 | meta = MetaData() | |
|
33 | meta.bind = migrate_engine | |
|
34 | ||
|
35 | ||
|
36 | def fixups(models, _SESSION): | |
|
37 | pass |
@@ -0,0 +1,41 b'' | |||
|
1 | import logging | |
|
2 | ||
|
3 | from sqlalchemy import * | |
|
4 | ||
|
5 | from rhodecode.model import meta | |
|
6 | from rhodecode.lib.dbmigrate.versions import _reset_base, notify | |
|
7 | ||
|
8 | log = logging.getLogger(__name__) | |
|
9 | ||
|
10 | ||
|
11 | def upgrade(migrate_engine): | |
|
12 | """ | |
|
13 | Upgrade operations go here. | |
|
14 | Don't create your own engine; bind migrate_engine to your metadata | |
|
15 | """ | |
|
16 | _reset_base(migrate_engine) | |
|
17 | from rhodecode.lib.dbmigrate.schema import db_4_16_0_0 as db | |
|
18 | ||
|
19 | fixups(db, meta.Session) | |
|
20 | ||
|
21 | ||
|
22 | def downgrade(migrate_engine): | |
|
23 | meta = MetaData() | |
|
24 | meta.bind = migrate_engine | |
|
25 | ||
|
26 | ||
|
27 | def fixups(models, _SESSION): | |
|
28 | # move the builtin token to external tokens | |
|
29 | ||
|
30 | log.info('Updating pull request pull_request_state to %s', | |
|
31 | models.PullRequest.STATE_CREATED) | |
|
32 | qry = _SESSION().query(models.PullRequest) | |
|
33 | qry.update({"pull_request_state": models.PullRequest.STATE_CREATED}) | |
|
34 | _SESSION().commit() | |
|
35 | ||
|
36 | log.info('Updating pull_request_version pull_request_state to %s', | |
|
37 | models.PullRequest.STATE_CREATED) | |
|
38 | qry = _SESSION().query(models.PullRequestVersion) | |
|
39 | qry.update({"pull_request_state": models.PullRequest.STATE_CREATED}) | |
|
40 | _SESSION().commit() | |
|
41 |
@@ -18,12 +18,6 b'' | |||
|
18 | 18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
19 | 19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
20 | 20 | |
|
21 | """ | |
|
22 | ||
|
23 | RhodeCode, a web based repository management software | |
|
24 | versioning implementation: http://www.python.org/dev/peps/pep-0386/ | |
|
25 | """ | |
|
26 | ||
|
27 | 21 | import os |
|
28 | 22 | import sys |
|
29 | 23 | import platform |
@@ -51,7 +45,7 b' PYRAMID_SETTINGS = {}' | |||
|
51 | 45 | EXTENSIONS = {} |
|
52 | 46 | |
|
53 | 47 | __version__ = ('.'.join((str(each) for each in VERSION[:3]))) |
|
54 |
__dbversion__ = 9 |
|
|
48 | __dbversion__ = 93 # defines current db version for migrations | |
|
55 | 49 | __platform__ = platform.system() |
|
56 | 50 | __license__ = 'AGPLv3, and Commercial License' |
|
57 | 51 | __author__ = 'RhodeCode GmbH' |
@@ -65,6 +65,7 b' class TestGetPullRequest(object):' | |||
|
65 | 65 | 'title': pull_request.title, |
|
66 | 66 | 'description': pull_request.description, |
|
67 | 67 | 'status': pull_request.status, |
|
68 | 'state': pull_request.pull_request_state, | |
|
68 | 69 | 'created_on': pull_request.created_on, |
|
69 | 70 | 'updated_on': pull_request.updated_on, |
|
70 | 71 | 'commit_ids': pull_request.revisions, |
@@ -29,11 +29,10 b' from rhodecode.api.tests.utils import (' | |||
|
29 | 29 | |
|
30 | 30 | @pytest.mark.usefixtures("testuser_api", "app") |
|
31 | 31 | class TestMergePullRequest(object): |
|
32 | ||
|
32 | 33 | @pytest.mark.backends("git", "hg") |
|
33 | 34 | def test_api_merge_pull_request_merge_failed(self, pr_util, no_notifications): |
|
34 | 35 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
35 | author = pull_request.user_id | |
|
36 | repo = pull_request.target_repo.repo_id | |
|
37 | 36 | pull_request_id = pull_request.pull_request_id |
|
38 | 37 | pull_request_repo = pull_request.target_repo.repo_name |
|
39 | 38 | |
@@ -46,8 +45,7 b' class TestMergePullRequest(object):' | |||
|
46 | 45 | |
|
47 | 46 | # The above api call detaches the pull request DB object from the |
|
48 | 47 | # session because of an unconditional transaction rollback in our |
|
49 | # middleware. Therefore we need to add it back here if we want to use | |
|
50 | # it. | |
|
48 | # middleware. Therefore we need to add it back here if we want to use it. | |
|
51 | 49 | Session().add(pull_request) |
|
52 | 50 | |
|
53 | 51 | expected = 'merge not possible for following reasons: ' \ |
@@ -55,6 +53,29 b' class TestMergePullRequest(object):' | |||
|
55 | 53 | assert_error(id_, expected, given=response.body) |
|
56 | 54 | |
|
57 | 55 | @pytest.mark.backends("git", "hg") |
|
56 | def test_api_merge_pull_request_merge_failed_disallowed_state( | |
|
57 | self, pr_util, no_notifications): | |
|
58 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) | |
|
59 | pull_request_id = pull_request.pull_request_id | |
|
60 | pull_request_repo = pull_request.target_repo.repo_name | |
|
61 | ||
|
62 | pr = PullRequest.get(pull_request_id) | |
|
63 | pr.pull_request_state = pull_request.STATE_UPDATING | |
|
64 | Session().add(pr) | |
|
65 | Session().commit() | |
|
66 | ||
|
67 | id_, params = build_data( | |
|
68 | self.apikey, 'merge_pull_request', | |
|
69 | repoid=pull_request_repo, | |
|
70 | pullrequestid=pull_request_id) | |
|
71 | ||
|
72 | response = api_call(self.app, params) | |
|
73 | expected = 'Operation forbidden because pull request is in state {}, '\ | |
|
74 | 'only state {} is allowed.'.format(PullRequest.STATE_UPDATING, | |
|
75 | PullRequest.STATE_CREATED) | |
|
76 | assert_error(id_, expected, given=response.body) | |
|
77 | ||
|
78 | @pytest.mark.backends("git", "hg") | |
|
58 | 79 | def test_api_merge_pull_request(self, pr_util, no_notifications): |
|
59 | 80 | pull_request = pr_util.create_pull_request(mergeable=True, approved=True) |
|
60 | 81 | author = pull_request.user_id |
@@ -123,8 +144,7 b' class TestMergePullRequest(object):' | |||
|
123 | 144 | assert_error(id_, expected, given=response.body) |
|
124 | 145 | |
|
125 | 146 | @pytest.mark.backends("git", "hg") |
|
126 | def test_api_merge_pull_request_non_admin_with_userid_error(self, | |
|
127 | pr_util): | |
|
147 | def test_api_merge_pull_request_non_admin_with_userid_error(self, pr_util): | |
|
128 | 148 | pull_request = pr_util.create_pull_request(mergeable=True) |
|
129 | 149 | id_, params = build_data( |
|
130 | 150 | self.apikey_regular, 'merge_pull_request', |
@@ -32,7 +32,7 b' from rhodecode.lib.base import vcs_opera' | |||
|
32 | 32 | from rhodecode.lib.utils2 import str2bool |
|
33 | 33 | from rhodecode.model.changeset_status import ChangesetStatusModel |
|
34 | 34 | from rhodecode.model.comment import CommentsModel |
|
35 | from rhodecode.model.db import Session, ChangesetStatus, ChangesetComment | |
|
35 | from rhodecode.model.db import Session, ChangesetStatus, ChangesetComment, PullRequest | |
|
36 | 36 | from rhodecode.model.pull_request import PullRequestModel, MergeCheck |
|
37 | 37 | from rhodecode.model.settings import SettingsModel |
|
38 | 38 | from rhodecode.model.validation_schema import Invalid |
@@ -128,11 +128,15 b' def get_pull_request(request, apiuser, p' | |||
|
128 | 128 | else: |
|
129 | 129 | repo = pull_request.target_repo |
|
130 | 130 | |
|
131 | if not PullRequestModel().check_user_read( | |
|
132 | pull_request, apiuser, api=True): | |
|
131 | if not PullRequestModel().check_user_read(pull_request, apiuser, api=True): | |
|
133 | 132 | raise JSONRPCError('repository `%s` or pull request `%s` ' |
|
134 | 133 | 'does not exist' % (repoid, pullrequestid)) |
|
135 | data = pull_request.get_api_data() | |
|
134 | ||
|
135 | # NOTE(marcink): only calculate and return merge state if the pr state is 'created' | |
|
136 | # otherwise we can lock the repo on calculation of merge state while update/merge | |
|
137 | # is happening. | |
|
138 | merge_state = pull_request.pull_request_state == pull_request.STATE_CREATED | |
|
139 | data = pull_request.get_api_data(with_merge_state=merge_state) | |
|
136 | 140 | return data |
|
137 | 141 | |
|
138 | 142 | |
@@ -283,8 +287,16 b' def merge_pull_request(' | |||
|
283 | 287 | else: |
|
284 | 288 | raise JSONRPCError('userid is not the same as your user') |
|
285 | 289 | |
|
286 | check = MergeCheck.validate( | |
|
287 | pull_request, auth_user=apiuser, translator=request.translate) | |
|
290 | if pull_request.pull_request_state != PullRequest.STATE_CREATED: | |
|
291 | raise JSONRPCError( | |
|
292 | 'Operation forbidden because pull request is in state {}, ' | |
|
293 | 'only state {} is allowed.'.format( | |
|
294 | pull_request.pull_request_state, PullRequest.STATE_CREATED)) | |
|
295 | ||
|
296 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
|
297 | check = MergeCheck.validate( | |
|
298 | pull_request, auth_user=apiuser, | |
|
299 | translator=request.translate) | |
|
288 | 300 | merge_possible = not check.failed |
|
289 | 301 | |
|
290 | 302 | if not merge_possible: |
@@ -302,8 +314,9 b' def merge_pull_request(' | |||
|
302 | 314 | request.environ, repo_name=target_repo.repo_name, |
|
303 | 315 | username=apiuser.username, action='push', |
|
304 | 316 | scm=target_repo.repo_type) |
|
305 | merge_response = PullRequestModel().merge_repo( | |
|
306 | pull_request, apiuser, extras=extras) | |
|
317 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
|
318 | merge_response = PullRequestModel().merge_repo( | |
|
319 | pull_request, apiuser, extras=extras) | |
|
307 | 320 | if merge_response.executed: |
|
308 | 321 | PullRequestModel().close_pull_request( |
|
309 | 322 | pull_request.pull_request_id, apiuser) |
@@ -829,11 +842,18 b' def update_pull_request(' | |||
|
829 | 842 | |
|
830 | 843 | commit_changes = {"added": [], "common": [], "removed": []} |
|
831 | 844 | if str2bool(Optional.extract(update_commits)): |
|
832 | if PullRequestModel().has_valid_update_type(pull_request): | |
|
833 | update_response = PullRequestModel().update_commits( | |
|
834 | pull_request) | |
|
835 | commit_changes = update_response.changes or commit_changes | |
|
836 | Session().commit() | |
|
845 | ||
|
846 | if pull_request.pull_request_state != PullRequest.STATE_CREATED: | |
|
847 | raise JSONRPCError( | |
|
848 | 'Operation forbidden because pull request is in state {}, ' | |
|
849 | 'only state {} is allowed.'.format( | |
|
850 | pull_request.pull_request_state, PullRequest.STATE_CREATED)) | |
|
851 | ||
|
852 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
|
853 | if PullRequestModel().has_valid_update_type(pull_request): | |
|
854 | update_response = PullRequestModel().update_commits(pull_request) | |
|
855 | commit_changes = update_response.changes or commit_changes | |
|
856 | Session().commit() | |
|
837 | 857 | |
|
838 | 858 | reviewers_changes = {"added": [], "removed": []} |
|
839 | 859 | if reviewers: |
@@ -655,20 +655,20 b' class TestPullrequestsView(object):' | |||
|
655 | 655 | |
|
656 | 656 | # create pr from a in source to A in target |
|
657 | 657 | pull_request = PullRequest() |
|
658 | ||
|
658 | 659 | pull_request.source_repo = source |
|
659 | # TODO: johbo: Make sure that we write the source ref this way! | |
|
660 | 660 | pull_request.source_ref = 'branch:{branch}:{commit_id}'.format( |
|
661 | 661 | branch=backend.default_branch_name, commit_id=commit_ids['change']) |
|
662 | ||
|
662 | 663 | pull_request.target_repo = target |
|
663 | ||
|
664 | 664 | pull_request.target_ref = 'branch:{branch}:{commit_id}'.format( |
|
665 | branch=backend.default_branch_name, | |
|
666 | commit_id=commit_ids['ancestor']) | |
|
665 | branch=backend.default_branch_name, commit_id=commit_ids['ancestor']) | |
|
666 | ||
|
667 | 667 | pull_request.revisions = [commit_ids['change']] |
|
668 | 668 | pull_request.title = u"Test" |
|
669 | 669 | pull_request.description = u"Description" |
|
670 | pull_request.author = UserModel().get_by_username( | |
|
671 | TEST_USER_ADMIN_LOGIN) | |
|
670 | pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
|
671 | pull_request.pull_request_state = PullRequest.STATE_CREATED | |
|
672 | 672 | Session().add(pull_request) |
|
673 | 673 | Session().commit() |
|
674 | 674 | pull_request_id = pull_request.pull_request_id |
@@ -679,23 +679,21 b' class TestPullrequestsView(object):' | |||
|
679 | 679 | # update PR |
|
680 | 680 | self.app.post( |
|
681 | 681 | route_path('pullrequest_update', |
|
682 | repo_name=target.repo_name, | |
|
683 | pull_request_id=pull_request_id), | |
|
684 | params={'update_commits': 'true', | |
|
685 | 'csrf_token': csrf_token}) | |
|
682 | repo_name=target.repo_name, pull_request_id=pull_request_id), | |
|
683 | params={'update_commits': 'true', 'csrf_token': csrf_token}) | |
|
684 | ||
|
685 | response = self.app.get( | |
|
686 | route_path('pullrequest_show', | |
|
687 | repo_name=target.repo_name, | |
|
688 | pull_request_id=pull_request.pull_request_id)) | |
|
689 | ||
|
690 | assert response.status_int == 200 | |
|
691 | assert 'Pull request updated to' in response.body | |
|
692 | assert 'with 1 added, 0 removed commits.' in response.body | |
|
686 | 693 | |
|
687 | 694 | # check that we have now both revisions |
|
688 | 695 | pull_request = PullRequest.get(pull_request_id) |
|
689 | assert pull_request.revisions == [ | |
|
690 | commit_ids['change-2'], commit_ids['change']] | |
|
691 | ||
|
692 | # TODO: johbo: this should be a test on its own | |
|
693 | response = self.app.get(route_path( | |
|
694 | 'pullrequest_new', | |
|
695 | repo_name=target.repo_name)) | |
|
696 | assert response.status_int == 200 | |
|
697 | assert 'Pull request updated to' in response.body | |
|
698 | assert 'with 1 added, 0 removed commits.' in response.body | |
|
696 | assert pull_request.revisions == [commit_ids['change-2'], commit_ids['change']] | |
|
699 | 697 | |
|
700 | 698 | def test_update_target_revision(self, backend, csrf_token): |
|
701 | 699 | commits = [ |
@@ -710,21 +708,21 b' class TestPullrequestsView(object):' | |||
|
710 | 708 | |
|
711 | 709 | # create pr from a in source to A in target |
|
712 | 710 | pull_request = PullRequest() |
|
711 | ||
|
713 | 712 | pull_request.source_repo = source |
|
714 | # TODO: johbo: Make sure that we write the source ref this way! | |
|
715 | 713 | pull_request.source_ref = 'branch:{branch}:{commit_id}'.format( |
|
716 | 714 | branch=backend.default_branch_name, commit_id=commit_ids['change']) |
|
715 | ||
|
717 | 716 | pull_request.target_repo = target |
|
718 | # TODO: johbo: Target ref should be branch based, since tip can jump | |
|
719 | # from branch to branch | |
|
720 | 717 | pull_request.target_ref = 'branch:{branch}:{commit_id}'.format( |
|
721 | branch=backend.default_branch_name, | |
|
722 | commit_id=commit_ids['ancestor']) | |
|
718 | branch=backend.default_branch_name, commit_id=commit_ids['ancestor']) | |
|
719 | ||
|
723 | 720 | pull_request.revisions = [commit_ids['change']] |
|
724 | 721 | pull_request.title = u"Test" |
|
725 | 722 | pull_request.description = u"Description" |
|
726 | pull_request.author = UserModel().get_by_username( | |
|
727 | TEST_USER_ADMIN_LOGIN) | |
|
723 | pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
|
724 | pull_request.pull_request_state = PullRequest.STATE_CREATED | |
|
725 | ||
|
728 | 726 | Session().add(pull_request) |
|
729 | 727 | Session().commit() |
|
730 | 728 | pull_request_id = pull_request.pull_request_id |
@@ -737,23 +735,21 b' class TestPullrequestsView(object):' | |||
|
737 | 735 | # update PR |
|
738 | 736 | self.app.post( |
|
739 | 737 | route_path('pullrequest_update', |
|
740 | repo_name=target.repo_name, | |
|
741 | pull_request_id=pull_request_id), | |
|
742 | params={'update_commits': 'true', | |
|
743 | 'csrf_token': csrf_token}, | |
|
738 | repo_name=target.repo_name, | |
|
739 | pull_request_id=pull_request_id), | |
|
740 | params={'update_commits': 'true', 'csrf_token': csrf_token}, | |
|
744 | 741 | status=200) |
|
745 | 742 | |
|
746 | 743 | # check that we have now both revisions |
|
747 | 744 | pull_request = PullRequest.get(pull_request_id) |
|
748 | 745 | assert pull_request.revisions == [commit_ids['change-rebased']] |
|
749 | 746 | assert pull_request.target_ref == 'branch:{branch}:{commit_id}'.format( |
|
750 | branch=backend.default_branch_name, | |
|
751 | commit_id=commit_ids['ancestor-new']) | |
|
747 | branch=backend.default_branch_name, commit_id=commit_ids['ancestor-new']) | |
|
752 | 748 | |
|
753 | # TODO: johbo: This should be a test on its own | |
|
754 | response = self.app.get(route_path( | |
|
755 | 'pullrequest_new', | |
|
756 | repo_name=target.repo_name)) | |
|
749 | response = self.app.get( | |
|
750 | route_path('pullrequest_show', | |
|
751 | repo_name=target.repo_name, | |
|
752 | pull_request_id=pull_request.pull_request_id)) | |
|
757 | 753 | assert response.status_int == 200 |
|
758 | 754 | assert 'Pull request updated to' in response.body |
|
759 | 755 | assert 'with 1 added, 1 removed commits.' in response.body |
@@ -775,17 +771,14 b' class TestPullrequestsView(object):' | |||
|
775 | 771 | # create pr from a in source to A in target |
|
776 | 772 | pull_request = PullRequest() |
|
777 | 773 | pull_request.source_repo = source |
|
778 | # TODO: johbo: Make sure that we write the source ref this way! | |
|
774 | ||
|
779 | 775 | pull_request.source_ref = 'branch:{branch}:{commit_id}'.format( |
|
780 | 776 | branch=backend.default_branch_name, |
|
781 | 777 | commit_id=commit_ids['master-commit-3-change-2']) |
|
782 | 778 | |
|
783 | 779 | pull_request.target_repo = target |
|
784 | # TODO: johbo: Target ref should be branch based, since tip can jump | |
|
785 | # from branch to branch | |
|
786 | 780 | pull_request.target_ref = 'branch:{branch}:{commit_id}'.format( |
|
787 | branch=backend.default_branch_name, | |
|
788 | commit_id=commit_ids['feat-commit-2']) | |
|
781 | branch=backend.default_branch_name, commit_id=commit_ids['feat-commit-2']) | |
|
789 | 782 | |
|
790 | 783 | pull_request.revisions = [ |
|
791 | 784 | commit_ids['feat-commit-1'], |
@@ -793,8 +786,8 b' class TestPullrequestsView(object):' | |||
|
793 | 786 | ] |
|
794 | 787 | pull_request.title = u"Test" |
|
795 | 788 | pull_request.description = u"Description" |
|
796 | pull_request.author = UserModel().get_by_username( | |
|
797 | TEST_USER_ADMIN_LOGIN) | |
|
789 | pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
|
790 | pull_request.pull_request_state = PullRequest.STATE_CREATED | |
|
798 | 791 | Session().add(pull_request) |
|
799 | 792 | Session().commit() |
|
800 | 793 | pull_request_id = pull_request.pull_request_id |
@@ -810,13 +803,10 b' class TestPullrequestsView(object):' | |||
|
810 | 803 | route_path('pullrequest_update', |
|
811 | 804 | repo_name=target.repo_name, |
|
812 | 805 | pull_request_id=pull_request_id), |
|
813 | params={'update_commits': 'true', | |
|
814 | 'csrf_token': csrf_token}, | |
|
806 | params={'update_commits': 'true', 'csrf_token': csrf_token}, | |
|
815 | 807 | status=200) |
|
816 | 808 | |
|
817 | response = self.app.get(route_path( | |
|
818 | 'pullrequest_new', | |
|
819 | repo_name=target.repo_name)) | |
|
809 | response = self.app.get(route_path('pullrequest_new', repo_name=target.repo_name)) | |
|
820 | 810 | assert response.status_int == 200 |
|
821 | 811 | response.mustcontain('Pull request updated to') |
|
822 | 812 | response.mustcontain('with 0 added, 0 removed commits.') |
@@ -836,21 +826,17 b' class TestPullrequestsView(object):' | |||
|
836 | 826 | # create pr from a in source to A in target |
|
837 | 827 | pull_request = PullRequest() |
|
838 | 828 | pull_request.source_repo = source |
|
839 | # TODO: johbo: Make sure that we write the source ref this way! | |
|
829 | ||
|
840 | 830 | pull_request.source_ref = 'branch:{branch}:{commit_id}'.format( |
|
841 | branch=backend.default_branch_name, | |
|
842 | commit_id=commit_ids['change']) | |
|
831 | branch=backend.default_branch_name, commit_id=commit_ids['change']) | |
|
843 | 832 | pull_request.target_repo = target |
|
844 | # TODO: johbo: Target ref should be branch based, since tip can jump | |
|
845 | # from branch to branch | |
|
846 | 833 | pull_request.target_ref = 'branch:{branch}:{commit_id}'.format( |
|
847 | branch=backend.default_branch_name, | |
|
848 | commit_id=commit_ids['ancestor']) | |
|
834 | branch=backend.default_branch_name, commit_id=commit_ids['ancestor']) | |
|
849 | 835 | pull_request.revisions = [commit_ids['change']] |
|
850 | 836 | pull_request.title = u"Test" |
|
851 | 837 | pull_request.description = u"Description" |
|
852 | pull_request.author = UserModel().get_by_username( | |
|
853 | TEST_USER_ADMIN_LOGIN) | |
|
838 | pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
|
839 | pull_request.pull_request_state = PullRequest.STATE_CREATED | |
|
854 | 840 | Session().add(pull_request) |
|
855 | 841 | Session().commit() |
|
856 | 842 | pull_request_id = pull_request.pull_request_id |
@@ -863,10 +849,8 b' class TestPullrequestsView(object):' | |||
|
863 | 849 | # update PR |
|
864 | 850 | self.app.post( |
|
865 | 851 | route_path('pullrequest_update', |
|
866 | repo_name=target.repo_name, | |
|
867 | pull_request_id=pull_request_id), | |
|
868 | params={'update_commits': 'true', | |
|
869 | 'csrf_token': csrf_token}, | |
|
852 | repo_name=target.repo_name, pull_request_id=pull_request_id), | |
|
853 | params={'update_commits': 'true', 'csrf_token': csrf_token}, | |
|
870 | 854 | status=200) |
|
871 | 855 | |
|
872 | 856 | # Expect the target reference to be updated correctly |
@@ -893,13 +877,12 b' class TestPullrequestsView(object):' | |||
|
893 | 877 | pull_request.source_ref = 'branch:{branch}:{commit_id}'.format( |
|
894 | 878 | branch=branch_name, commit_id=commit_ids['new-feature']) |
|
895 | 879 | pull_request.target_ref = 'branch:{branch}:{commit_id}'.format( |
|
896 | branch=backend_git.default_branch_name, | |
|
897 | commit_id=commit_ids['old-feature']) | |
|
880 | branch=backend_git.default_branch_name, commit_id=commit_ids['old-feature']) | |
|
898 | 881 | pull_request.revisions = [commit_ids['new-feature']] |
|
899 | 882 | pull_request.title = u"Test" |
|
900 | 883 | pull_request.description = u"Description" |
|
901 | pull_request.author = UserModel().get_by_username( | |
|
902 | TEST_USER_ADMIN_LOGIN) | |
|
884 | pull_request.author = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
|
885 | pull_request.pull_request_state = PullRequest.STATE_CREATED | |
|
903 | 886 | Session().add(pull_request) |
|
904 | 887 | Session().commit() |
|
905 | 888 |
@@ -273,9 +273,22 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
273 | 273 | route_name='pullrequest_show', request_method='GET', |
|
274 | 274 | renderer='rhodecode:templates/pullrequests/pullrequest_show.mako') |
|
275 | 275 | def pull_request_show(self): |
|
276 | pull_request_id = self.request.matchdict['pull_request_id'] | |
|
276 | _ = self.request.translate | |
|
277 | c = self.load_default_context() | |
|
278 | ||
|
279 | pull_request = PullRequest.get_or_404( | |
|
280 | self.request.matchdict['pull_request_id']) | |
|
281 | pull_request_id = pull_request.pull_request_id | |
|
277 | 282 | |
|
278 | c = self.load_default_context() | |
|
283 | if pull_request.pull_request_state != PullRequest.STATE_CREATED: | |
|
284 | log.debug('show: forbidden because pull request is in state %s', | |
|
285 | pull_request.pull_request_state) | |
|
286 | msg = _(u'Cannot show pull requests in state other than `{}`. ' | |
|
287 | u'Current state is: `{}`').format(PullRequest.STATE_CREATED, | |
|
288 | pull_request.pull_request_state) | |
|
289 | h.flash(msg, category='error') | |
|
290 | raise HTTPFound(h.route_path('pullrequest_show_all', | |
|
291 | repo_name=self.db_repo_name)) | |
|
279 | 292 | |
|
280 | 293 | version = self.request.GET.get('version') |
|
281 | 294 | from_version = self.request.GET.get('from_version') or version |
@@ -919,12 +932,17 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
919 | 932 | source_db_repo = Repository.get_by_repo_name(_form['source_repo']) |
|
920 | 933 | target_db_repo = Repository.get_by_repo_name(_form['target_repo']) |
|
921 | 934 | |
|
935 | if not (source_db_repo or target_db_repo): | |
|
936 | h.flash(_('source_repo or target repo not found'), category='error') | |
|
937 | raise HTTPFound( | |
|
938 | h.route_path('pullrequest_new', repo_name=self.db_repo_name)) | |
|
939 | ||
|
922 | 940 | # re-check permissions again here |
|
923 | 941 | # source_repo we must have read permissions |
|
924 | 942 | |
|
925 | 943 | source_perm = HasRepoPermissionAny( |
|
926 | 'repository.read', | |
|
927 |
|
|
|
944 | 'repository.read', 'repository.write', 'repository.admin')( | |
|
945 | source_db_repo.repo_name) | |
|
928 | 946 | if not source_perm: |
|
929 | 947 | msg = _('Not Enough permissions to source repo `{}`.'.format( |
|
930 | 948 | source_db_repo.repo_name)) |
@@ -938,8 +956,8 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
938 | 956 | # target repo we must have read permissions, and also later on |
|
939 | 957 | # we want to check branch permissions here |
|
940 | 958 | target_perm = HasRepoPermissionAny( |
|
941 | 'repository.read', | |
|
942 |
|
|
|
959 | 'repository.read', 'repository.write', 'repository.admin')( | |
|
960 | target_db_repo.repo_name) | |
|
943 | 961 | if not target_perm: |
|
944 | 962 | msg = _('Not Enough permissions to target repo `{}`.'.format( |
|
945 | 963 | target_db_repo.repo_name)) |
@@ -1042,6 +1060,15 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1042 | 1060 | h.flash(msg, category='error') |
|
1043 | 1061 | return True |
|
1044 | 1062 | |
|
1063 | if pull_request.pull_request_state != PullRequest.STATE_CREATED: | |
|
1064 | log.debug('update: forbidden because pull request is in state %s', | |
|
1065 | pull_request.pull_request_state) | |
|
1066 | msg = _(u'Cannot update pull requests in state other than `{}`. ' | |
|
1067 | u'Current state is: `{}`').format(PullRequest.STATE_CREATED, | |
|
1068 | pull_request.pull_request_state) | |
|
1069 | h.flash(msg, category='error') | |
|
1070 | return True | |
|
1071 | ||
|
1045 | 1072 | # only owner or admin can update it |
|
1046 | 1073 | allowed_to_update = PullRequestModel().check_user_update( |
|
1047 | 1074 | pull_request, self._rhodecode_user) |
@@ -1084,7 +1111,9 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1084 | 1111 | |
|
1085 | 1112 | def _update_commits(self, pull_request): |
|
1086 | 1113 | _ = self.request.translate |
|
1087 | resp = PullRequestModel().update_commits(pull_request) | |
|
1114 | ||
|
1115 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
|
1116 | resp = PullRequestModel().update_commits(pull_request) | |
|
1088 | 1117 | |
|
1089 | 1118 | if resp.executed: |
|
1090 | 1119 | |
@@ -1097,10 +1126,9 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1097 | 1126 | else: |
|
1098 | 1127 | changed = 'nothing' |
|
1099 | 1128 | |
|
1100 | msg = _( | |
|
1101 | u'Pull request updated to "{source_commit_id}" with ' | |
|
1102 | u'{count_added} added, {count_removed} removed commits. ' | |
|
1103 | u'Source of changes: {change_source}') | |
|
1129 | msg = _(u'Pull request updated to "{source_commit_id}" with ' | |
|
1130 | u'{count_added} added, {count_removed} removed commits. ' | |
|
1131 | u'Source of changes: {change_source}') | |
|
1104 | 1132 | msg = msg.format( |
|
1105 | 1133 | source_commit_id=pull_request.source_ref_parts.commit_id, |
|
1106 | 1134 | count_added=len(resp.changes.added), |
@@ -1109,8 +1137,7 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1109 | 1137 | h.flash(msg, category='success') |
|
1110 | 1138 | |
|
1111 | 1139 | channel = '/repo${}$/pr/{}'.format( |
|
1112 | pull_request.target_repo.repo_name, | |
|
1113 | pull_request.pull_request_id) | |
|
1140 | pull_request.target_repo.repo_name, pull_request.pull_request_id) | |
|
1114 | 1141 | message = msg + ( |
|
1115 | 1142 | ' - <a onclick="window.location.reload()">' |
|
1116 | 1143 | '<strong>{}</strong></a>'.format(_('Reload page'))) |
@@ -1143,11 +1170,26 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1143 | 1170 | """ |
|
1144 | 1171 | pull_request = PullRequest.get_or_404( |
|
1145 | 1172 | self.request.matchdict['pull_request_id']) |
|
1173 | _ = self.request.translate | |
|
1174 | ||
|
1175 | if pull_request.pull_request_state != PullRequest.STATE_CREATED: | |
|
1176 | log.debug('show: forbidden because pull request is in state %s', | |
|
1177 | pull_request.pull_request_state) | |
|
1178 | msg = _(u'Cannot merge pull requests in state other than `{}`. ' | |
|
1179 | u'Current state is: `{}`').format(PullRequest.STATE_CREATED, | |
|
1180 | pull_request.pull_request_state) | |
|
1181 | h.flash(msg, category='error') | |
|
1182 | raise HTTPFound( | |
|
1183 | h.route_path('pullrequest_show', | |
|
1184 | repo_name=pull_request.target_repo.repo_name, | |
|
1185 | pull_request_id=pull_request.pull_request_id)) | |
|
1146 | 1186 | |
|
1147 | 1187 | self.load_default_context() |
|
1148 | check = MergeCheck.validate( | |
|
1149 | pull_request, auth_user=self._rhodecode_user, | |
|
1150 | translator=self.request.translate) | |
|
1188 | ||
|
1189 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
|
1190 | check = MergeCheck.validate( | |
|
1191 | pull_request, auth_user=self._rhodecode_user, | |
|
1192 | translator=self.request.translate) | |
|
1151 | 1193 | merge_possible = not check.failed |
|
1152 | 1194 | |
|
1153 | 1195 | for err_type, error_msg in check.errors: |
@@ -1159,8 +1201,9 b' class RepoPullRequestsView(RepoAppView, ' | |||
|
1159 | 1201 | self.request.environ, repo_name=pull_request.target_repo.repo_name, |
|
1160 | 1202 | username=self._rhodecode_db_user.username, action='push', |
|
1161 | 1203 | scm=pull_request.target_repo.repo_type) |
|
1162 | self._merge_pull_request( | |
|
1163 | pull_request, self._rhodecode_db_user, extras) | |
|
1204 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
|
1205 | self._merge_pull_request( | |
|
1206 | pull_request, self._rhodecode_db_user, extras) | |
|
1164 | 1207 | else: |
|
1165 | 1208 | log.debug("Pre-conditions failed, NOT merging.") |
|
1166 | 1209 |
@@ -3538,6 +3538,32 b' class ChangesetStatus(Base, BaseModel):' | |||
|
3538 | 3538 | return data |
|
3539 | 3539 | |
|
3540 | 3540 | |
|
3541 | class _SetState(object): | |
|
3542 | """ | |
|
3543 | Context processor allowing changing state for sensitive operation such as | |
|
3544 | pull request update or merge | |
|
3545 | """ | |
|
3546 | ||
|
3547 | def __init__(self, pull_request, pr_state, back_state=None): | |
|
3548 | self._pr = pull_request | |
|
3549 | self._org_state = back_state or pull_request.pull_request_state | |
|
3550 | self._pr_state = pr_state | |
|
3551 | ||
|
3552 | def __enter__(self): | |
|
3553 | log.debug('StateLock: entering set state context, setting state to: `%s`', | |
|
3554 | self._pr_state) | |
|
3555 | self._pr.pull_request_state = self._pr_state | |
|
3556 | Session().add(self._pr) | |
|
3557 | Session().commit() | |
|
3558 | ||
|
3559 | def __exit__(self, exc_type, exc_val, exc_tb): | |
|
3560 | log.debug('StateLock: exiting set state context, setting state to: `%s`', | |
|
3561 | self._org_state) | |
|
3562 | self._pr.pull_request_state = self._org_state | |
|
3563 | Session().add(self._pr) | |
|
3564 | Session().commit() | |
|
3565 | ||
|
3566 | ||
|
3541 | 3567 | class _PullRequestBase(BaseModel): |
|
3542 | 3568 | """ |
|
3543 | 3569 | Common attributes of pull request and version entries. |
@@ -3548,6 +3574,12 b' class _PullRequestBase(BaseModel):' | |||
|
3548 | 3574 | STATUS_OPEN = u'open' |
|
3549 | 3575 | STATUS_CLOSED = u'closed' |
|
3550 | 3576 | |
|
3577 | # available states | |
|
3578 | STATE_CREATING = u'creating' | |
|
3579 | STATE_UPDATING = u'updating' | |
|
3580 | STATE_MERGING = u'merging' | |
|
3581 | STATE_CREATED = u'created' | |
|
3582 | ||
|
3551 | 3583 | title = Column('title', Unicode(255), nullable=True) |
|
3552 | 3584 | description = Column( |
|
3553 | 3585 | 'description', UnicodeText().with_variant(UnicodeText(10240), 'mysql'), |
@@ -3563,6 +3595,8 b' class _PullRequestBase(BaseModel):' | |||
|
3563 | 3595 | 'updated_on', DateTime(timezone=False), nullable=False, |
|
3564 | 3596 | default=datetime.datetime.now) |
|
3565 | 3597 | |
|
3598 | pull_request_state = Column("pull_request_state", String(255), nullable=True) | |
|
3599 | ||
|
3566 | 3600 | @declared_attr |
|
3567 | 3601 | def user_id(cls): |
|
3568 | 3602 | return Column( |
@@ -3737,6 +3771,7 b' class _PullRequestBase(BaseModel):' | |||
|
3737 | 3771 | 'title': pull_request.title, |
|
3738 | 3772 | 'description': pull_request.description, |
|
3739 | 3773 | 'status': pull_request.status, |
|
3774 | 'state': pull_request.pull_request_state, | |
|
3740 | 3775 | 'created_on': pull_request.created_on, |
|
3741 | 3776 | 'updated_on': pull_request.updated_on, |
|
3742 | 3777 | 'commit_ids': pull_request.revisions, |
@@ -3777,6 +3812,20 b' class _PullRequestBase(BaseModel):' | |||
|
3777 | 3812 | |
|
3778 | 3813 | return data |
|
3779 | 3814 | |
|
3815 | def set_state(self, pull_request_state, final_state=None): | |
|
3816 | """ | |
|
3817 | # goes from initial state to updating to initial state. | |
|
3818 | # initial state can be changed by specifying back_state= | |
|
3819 | with pull_request_obj.set_state(PullRequest.STATE_UPDATING): | |
|
3820 | pull_request.merge() | |
|
3821 | ||
|
3822 | :param pull_request_state: | |
|
3823 | :param final_state: | |
|
3824 | ||
|
3825 | """ | |
|
3826 | ||
|
3827 | return _SetState(self, pull_request_state, back_state=final_state) | |
|
3828 | ||
|
3780 | 3829 | |
|
3781 | 3830 | class PullRequest(Base, _PullRequestBase): |
|
3782 | 3831 | __tablename__ = 'pull_requests' |
@@ -138,7 +138,7 b' class PullRequestModel(BaseModel):' | |||
|
138 | 138 | |
|
139 | 139 | def _prepare_get_all_query(self, repo_name, source=False, statuses=None, |
|
140 | 140 | opened_by=None, order_by=None, |
|
141 | order_dir='desc'): | |
|
141 | order_dir='desc', only_created=True): | |
|
142 | 142 | repo = None |
|
143 | 143 | if repo_name: |
|
144 | 144 | repo = self._get_repo(repo_name) |
@@ -159,6 +159,10 b' class PullRequestModel(BaseModel):' | |||
|
159 | 159 | if opened_by: |
|
160 | 160 | q = q.filter(PullRequest.user_id.in_(opened_by)) |
|
161 | 161 | |
|
162 | # only get those that are in "created" state | |
|
163 | if only_created: | |
|
164 | q = q.filter(PullRequest.pull_request_state == PullRequest.STATE_CREATED) | |
|
165 | ||
|
162 | 166 | if order_by: |
|
163 | 167 | order_map = { |
|
164 | 168 | 'name_raw': PullRequest.pull_request_id, |
@@ -429,7 +433,7 b' class PullRequestModel(BaseModel):' | |||
|
429 | 433 | pull_request.description_renderer = description_renderer |
|
430 | 434 | pull_request.author = created_by_user |
|
431 | 435 | pull_request.reviewer_data = reviewer_data |
|
432 | ||
|
436 | pull_request.pull_request_state = pull_request.STATE_CREATING | |
|
433 | 437 | Session().add(pull_request) |
|
434 | 438 | Session().flush() |
|
435 | 439 | |
@@ -497,9 +501,16 b' class PullRequestModel(BaseModel):' | |||
|
497 | 501 | # that for large repos could be long resulting in long row locks |
|
498 | 502 | Session().commit() |
|
499 | 503 | |
|
500 | # prepare workspace, and run initial merge simulation | |
|
501 | MergeCheck.validate( | |
|
502 | pull_request, auth_user=auth_user, translator=translator) | |
|
504 | # prepare workspace, and run initial merge simulation. Set state during that | |
|
505 | # operation | |
|
506 | pull_request = PullRequest.get(pull_request.pull_request_id) | |
|
507 | ||
|
508 | # set as merging, for simulation, and if finished to created so we mark | |
|
509 | # simulation is working fine | |
|
510 | with pull_request.set_state(PullRequest.STATE_MERGING, | |
|
511 | final_state=PullRequest.STATE_CREATED): | |
|
512 | MergeCheck.validate( | |
|
513 | pull_request, auth_user=auth_user, translator=translator) | |
|
503 | 514 | |
|
504 | 515 | self.notify_reviewers(pull_request, reviewer_ids) |
|
505 | 516 | self._trigger_pull_request_hook( |
@@ -653,9 +664,8 b' class PullRequestModel(BaseModel):' | |||
|
653 | 664 | target_ref_id = pull_request.target_ref_parts.commit_id |
|
654 | 665 | |
|
655 | 666 | if not self.has_valid_update_type(pull_request): |
|
656 | log.debug( | |
|
657 |
|
|
|
658 | pull_request, source_ref_type) | |
|
667 | log.debug("Skipping update of pull request %s due to ref type: %s", | |
|
668 | pull_request, source_ref_type) | |
|
659 | 669 | return UpdateResponse( |
|
660 | 670 | executed=False, |
|
661 | 671 | reason=UpdateFailureReason.WRONG_REF_TYPE, |
@@ -801,8 +811,7 b' class PullRequestModel(BaseModel):' | |||
|
801 | 811 | pull_request.source_ref_parts.commit_id, |
|
802 | 812 | pull_request_version.pull_request_version_id) |
|
803 | 813 | Session().commit() |
|
804 | self._trigger_pull_request_hook( | |
|
805 | pull_request, pull_request.author, 'update') | |
|
814 | self._trigger_pull_request_hook(pull_request, pull_request.author, 'update') | |
|
806 | 815 | |
|
807 | 816 | return UpdateResponse( |
|
808 | 817 | executed=True, reason=UpdateFailureReason.NONE, |
@@ -814,6 +823,7 b' class PullRequestModel(BaseModel):' | |||
|
814 | 823 | version.title = pull_request.title |
|
815 | 824 | version.description = pull_request.description |
|
816 | 825 | version.status = pull_request.status |
|
826 | version.pull_request_state = pull_request.pull_request_state | |
|
817 | 827 | version.created_on = datetime.datetime.now() |
|
818 | 828 | version.updated_on = pull_request.updated_on |
|
819 | 829 | version.user_id = pull_request.user_id |
@@ -1614,8 +1624,7 b' class MergeCheck(object):' | |||
|
1614 | 1624 | |
|
1615 | 1625 | msg = _('Pull request reviewer approval is pending.') |
|
1616 | 1626 | |
|
1617 | merge_check.push_error( | |
|
1618 | 'warning', msg, cls.REVIEW_CHECK, review_status) | |
|
1627 | merge_check.push_error('warning', msg, cls.REVIEW_CHECK, review_status) | |
|
1619 | 1628 | |
|
1620 | 1629 | if fail_early: |
|
1621 | 1630 | return merge_check |
@@ -1624,7 +1633,7 b' class MergeCheck(object):' | |||
|
1624 | 1633 | todos = CommentsModel().get_unresolved_todos(pull_request) |
|
1625 | 1634 | if todos: |
|
1626 | 1635 | log.debug("MergeCheck: cannot merge, {} " |
|
1627 |
"unresolved |
|
|
1636 | "unresolved TODOs left.".format(len(todos))) | |
|
1628 | 1637 | |
|
1629 | 1638 | if len(todos) == 1: |
|
1630 | 1639 | msg = _('Cannot merge, {} TODO still not resolved.').format( |
@@ -1645,8 +1654,7 b' class MergeCheck(object):' | |||
|
1645 | 1654 | merge_check.merge_possible = merge_status |
|
1646 | 1655 | merge_check.merge_msg = msg |
|
1647 | 1656 | if not merge_status: |
|
1648 | log.debug( | |
|
1649 | "MergeCheck: cannot merge, pull request merge not possible.") | |
|
1657 | log.debug("MergeCheck: cannot merge, pull request merge not possible.") | |
|
1650 | 1658 | merge_check.push_error('warning', msg, cls.MERGE_CHECK, None) |
|
1651 | 1659 | |
|
1652 | 1660 | if fail_early: |
@@ -1677,6 +1685,7 b' class MergeCheck(object):' | |||
|
1677 | 1685 | close_branch = model._close_branch_before_merging(pull_request) |
|
1678 | 1686 | if close_branch: |
|
1679 | 1687 | repo_type = pull_request.target_repo.repo_type |
|
1688 | close_msg = '' | |
|
1680 | 1689 | if repo_type == 'hg': |
|
1681 | 1690 | close_msg = _('Source branch will be closed after merge.') |
|
1682 | 1691 | elif repo_type == 'git': |
@@ -1689,6 +1698,7 b' class MergeCheck(object):' | |||
|
1689 | 1698 | |
|
1690 | 1699 | return merge_details |
|
1691 | 1700 | |
|
1701 | ||
|
1692 | 1702 | ChangeTuple = collections.namedtuple( |
|
1693 | 1703 | 'ChangeTuple', ['added', 'common', 'removed', 'total']) |
|
1694 | 1704 |
@@ -257,8 +257,7 b' class TestPullRequestModel(object):' | |||
|
257 | 257 | def has_largefiles(self, repo): |
|
258 | 258 | return repo == pull_request.source_repo |
|
259 | 259 | |
|
260 | patcher = mock.patch.object( | |
|
261 | PullRequestModel, '_has_largefiles', has_largefiles) | |
|
260 | patcher = mock.patch.object(PullRequestModel, '_has_largefiles', has_largefiles) | |
|
262 | 261 | with patcher: |
|
263 | 262 | status, msg = PullRequestModel().merge_status(pull_request) |
|
264 | 263 | |
@@ -270,8 +269,7 b' class TestPullRequestModel(object):' | |||
|
270 | 269 | def has_largefiles(self, repo): |
|
271 | 270 | return repo == pull_request.target_repo |
|
272 | 271 | |
|
273 | patcher = mock.patch.object( | |
|
274 | PullRequestModel, '_has_largefiles', has_largefiles) | |
|
272 | patcher = mock.patch.object(PullRequestModel, '_has_largefiles', has_largefiles) | |
|
275 | 273 | with patcher: |
|
276 | 274 | status, msg = PullRequestModel().merge_status(pull_request) |
|
277 | 275 | |
@@ -314,9 +312,50 b' class TestPullRequestModel(object):' | |||
|
314 | 312 | self.pull_request, self.pull_request.author, 'merge') |
|
315 | 313 | |
|
316 | 314 | pull_request = PullRequest.get(pull_request.pull_request_id) |
|
317 | assert ( | |
|
318 | pull_request.merge_rev == | |
|
319 | '6126b7bfcc82ad2d3deaee22af926b082ce54cc6') | |
|
315 | assert pull_request.merge_rev == '6126b7bfcc82ad2d3deaee22af926b082ce54cc6' | |
|
316 | ||
|
317 | def test_merge_with_status_lock(self, pull_request, merge_extras): | |
|
318 | user = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) | |
|
319 | merge_ref = Reference( | |
|
320 | 'type', 'name', '6126b7bfcc82ad2d3deaee22af926b082ce54cc6') | |
|
321 | self.merge_mock.return_value = MergeResponse( | |
|
322 | True, True, merge_ref, MergeFailureReason.NONE) | |
|
323 | ||
|
324 | merge_extras['repository'] = pull_request.target_repo.repo_name | |
|
325 | ||
|
326 | with pull_request.set_state(PullRequest.STATE_UPDATING): | |
|
327 | assert pull_request.pull_request_state == PullRequest.STATE_UPDATING | |
|
328 | PullRequestModel().merge_repo( | |
|
329 | pull_request, pull_request.author, extras=merge_extras) | |
|
330 | ||
|
331 | assert pull_request.pull_request_state == PullRequest.STATE_CREATED | |
|
332 | ||
|
333 | message = ( | |
|
334 | u'Merge pull request #{pr_id} from {source_repo} {source_ref_name}' | |
|
335 | u'\n\n {pr_title}'.format( | |
|
336 | pr_id=pull_request.pull_request_id, | |
|
337 | source_repo=safe_unicode( | |
|
338 | pull_request.source_repo.scm_instance().name), | |
|
339 | source_ref_name=pull_request.source_ref_parts.name, | |
|
340 | pr_title=safe_unicode(pull_request.title) | |
|
341 | ) | |
|
342 | ) | |
|
343 | self.merge_mock.assert_called_with( | |
|
344 | self.repo_id, self.workspace_id, | |
|
345 | pull_request.target_ref_parts, | |
|
346 | pull_request.source_repo.scm_instance(), | |
|
347 | pull_request.source_ref_parts, | |
|
348 | user_name=user.short_contact, user_email=user.email, message=message, | |
|
349 | use_rebase=False, close_branch=False | |
|
350 | ) | |
|
351 | self.invalidation_mock.assert_called_once_with( | |
|
352 | pull_request.target_repo.repo_name) | |
|
353 | ||
|
354 | self.hook_mock.assert_called_with( | |
|
355 | self.pull_request, self.pull_request.author, 'merge') | |
|
356 | ||
|
357 | pull_request = PullRequest.get(pull_request.pull_request_id) | |
|
358 | assert pull_request.merge_rev == '6126b7bfcc82ad2d3deaee22af926b082ce54cc6' | |
|
320 | 359 | |
|
321 | 360 | def test_merge_failed(self, pull_request, merge_extras): |
|
322 | 361 | user = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN) |
General Comments 0
You need to be logged in to leave comments.
Login now