Show More
@@ -302,7 +302,7 b' def merge_pull_request(' | |||||
302 | request.environ, repo_name=target_repo.repo_name, |
|
302 | request.environ, repo_name=target_repo.repo_name, | |
303 | username=apiuser.username, action='push', |
|
303 | username=apiuser.username, action='push', | |
304 | scm=target_repo.repo_type) |
|
304 | scm=target_repo.repo_type) | |
305 | merge_response = PullRequestModel().merge( |
|
305 | merge_response = PullRequestModel().merge_repo( | |
306 | pull_request, apiuser, extras=extras) |
|
306 | pull_request, apiuser, extras=extras) | |
307 | if merge_response.executed: |
|
307 | if merge_response.executed: | |
308 | PullRequestModel().close_pull_request( |
|
308 | PullRequestModel().close_pull_request( |
@@ -618,7 +618,7 b' class TestPullrequestsView(object):' | |||||
618 |
|
618 | |||
619 | model_patcher = mock.patch.multiple( |
|
619 | model_patcher = mock.patch.multiple( | |
620 | PullRequestModel, |
|
620 | PullRequestModel, | |
621 | merge=mock.Mock(return_value=MergeResponse( |
|
621 | merge_repo=mock.Mock(return_value=MergeResponse( | |
622 | True, False, 'STUB_COMMIT_ID', MergeFailureReason.PUSH_FAILED)), |
|
622 | True, False, 'STUB_COMMIT_ID', MergeFailureReason.PUSH_FAILED)), | |
623 | merge_status=mock.Mock(return_value=(True, 'WRONG_MESSAGE'))) |
|
623 | merge_status=mock.Mock(return_value=(True, 'WRONG_MESSAGE'))) | |
624 |
|
624 |
@@ -340,7 +340,8 b' class RepoPullRequestsView(RepoAppView, ' | |||||
340 | # check merge capabilities |
|
340 | # check merge capabilities | |
341 | _merge_check = MergeCheck.validate( |
|
341 | _merge_check = MergeCheck.validate( | |
342 | pull_request_latest, user=self._rhodecode_user, |
|
342 | pull_request_latest, user=self._rhodecode_user, | |
343 |
translator=self.request.translate, |
|
343 | translator=self.request.translate, | |
|
344 | force_shadow_repo_refresh=force_refresh) | |||
344 | c.pr_merge_errors = _merge_check.error_details |
|
345 | c.pr_merge_errors = _merge_check.error_details | |
345 | c.pr_merge_possible = not _merge_check.failed |
|
346 | c.pr_merge_possible = not _merge_check.failed | |
346 | c.pr_merge_message = _merge_check.merge_msg |
|
347 | c.pr_merge_message = _merge_check.merge_msg | |
@@ -1063,7 +1064,7 b' class RepoPullRequestsView(RepoAppView, ' | |||||
1063 |
|
1064 | |||
1064 | def _merge_pull_request(self, pull_request, user, extras): |
|
1065 | def _merge_pull_request(self, pull_request, user, extras): | |
1065 | _ = self.request.translate |
|
1066 | _ = self.request.translate | |
1066 | merge_resp = PullRequestModel().merge(pull_request, user, extras=extras) |
|
1067 | merge_resp = PullRequestModel().merge_repo(pull_request, user, extras=extras) | |
1067 |
|
1068 | |||
1068 | if merge_resp.executed: |
|
1069 | if merge_resp.executed: | |
1069 | log.debug("The merge was successful, closing the pull request.") |
|
1070 | log.debug("The merge was successful, closing the pull request.") |
@@ -204,13 +204,14 b' class SimpleVCS(object):' | |||||
204 |
|
204 | |||
205 | # Only proceed if we got a pull request and if acl repo name from |
|
205 | # Only proceed if we got a pull request and if acl repo name from | |
206 | # URL equals the target repo name of the pull request. |
|
206 | # URL equals the target repo name of the pull request. | |
207 |
if pull_request and |
|
207 | if pull_request and \ | |
208 |
|
|
208 | (acl_repo_name == pull_request.target_repo.repo_name): | |
|
209 | repo_id = pull_request.target_repo.repo_id | |||
209 | # Get file system path to shadow repository. |
|
210 | # Get file system path to shadow repository. | |
210 | workspace_id = PullRequestModel()._workspace_id(pull_request) |
|
211 | workspace_id = PullRequestModel()._workspace_id(pull_request) | |
211 | target_vcs = pull_request.target_repo.scm_instance() |
|
212 | target_vcs = pull_request.target_repo.scm_instance() | |
212 | vcs_repo_name = target_vcs._get_shadow_repository_path( |
|
213 | vcs_repo_name = target_vcs._get_shadow_repository_path( | |
213 | workspace_id) |
|
214 | repo_id, workspace_id) | |
214 |
|
215 | |||
215 | # Store names for later usage. |
|
216 | # Store names for later usage. | |
216 | self.vcs_repo_name = vcs_repo_name |
|
217 | self.vcs_repo_name = vcs_repo_name |
@@ -451,7 +451,7 b' class BaseRepository(object):' | |||||
451 | """ |
|
451 | """ | |
452 | raise NotImplementedError |
|
452 | raise NotImplementedError | |
453 |
|
453 | |||
454 |
def merge(self, target_ref, source_repo, source_ref, |
|
454 | def merge(self, repo_id, workspace_id, target_ref, source_repo, source_ref, | |
455 | user_name='', user_email='', message='', dry_run=False, |
|
455 | user_name='', user_email='', message='', dry_run=False, | |
456 | use_rebase=False, close_branch=False): |
|
456 | use_rebase=False, close_branch=False): | |
457 | """ |
|
457 | """ | |
@@ -465,13 +465,14 b' class BaseRepository(object):' | |||||
465 | 'possible', 'executed', 'source_commit', 'target_commit', |
|
465 | 'possible', 'executed', 'source_commit', 'target_commit', | |
466 | 'merge_commit'. |
|
466 | 'merge_commit'. | |
467 |
|
467 | |||
|
468 | :param repo_id: `repo_id` target repo id. | |||
|
469 | :param workspace_id: `workspace_id` unique identifier. | |||
468 | :param target_ref: `target_ref` points to the commit on top of which |
|
470 | :param target_ref: `target_ref` points to the commit on top of which | |
469 | the `source_ref` should be merged. |
|
471 | the `source_ref` should be merged. | |
470 | :param source_repo: The repository that contains the commits to be |
|
472 | :param source_repo: The repository that contains the commits to be | |
471 | merged. |
|
473 | merged. | |
472 | :param source_ref: `source_ref` points to the topmost commit from |
|
474 | :param source_ref: `source_ref` points to the topmost commit from | |
473 | the `source_repo` which should be merged. |
|
475 | the `source_repo` which should be merged. | |
474 | :param workspace_id: `workspace_id` unique identifier. |
|
|||
475 | :param user_name: Merge commit `user_name`. |
|
476 | :param user_name: Merge commit `user_name`. | |
476 | :param user_email: Merge commit `user_email`. |
|
477 | :param user_email: Merge commit `user_email`. | |
477 | :param message: Merge commit `message`. |
|
478 | :param message: Merge commit `message`. | |
@@ -492,12 +493,9 b' class BaseRepository(object):' | |||||
492 | if not message: |
|
493 | if not message: | |
493 | raise ValueError('message cannot be empty') |
|
494 | raise ValueError('message cannot be empty') | |
494 |
|
495 | |||
495 | shadow_repository_path = self._maybe_prepare_merge_workspace( |
|
|||
496 | workspace_id, target_ref, source_ref) |
|
|||
497 |
|
||||
498 | try: |
|
496 | try: | |
499 | return self._merge_repo( |
|
497 | return self._merge_repo( | |
500 |
|
|
498 | repo_id, workspace_id, target_ref, source_repo, | |
501 | source_ref, message, user_name, user_email, dry_run=dry_run, |
|
499 | source_ref, message, user_name, user_email, dry_run=dry_run, | |
502 | use_rebase=use_rebase, close_branch=close_branch) |
|
500 | use_rebase=use_rebase, close_branch=close_branch) | |
503 | except RepositoryError: |
|
501 | except RepositoryError: | |
@@ -507,14 +505,15 b' class BaseRepository(object):' | |||||
507 | return MergeResponse( |
|
505 | return MergeResponse( | |
508 | False, False, None, MergeFailureReason.UNKNOWN) |
|
506 | False, False, None, MergeFailureReason.UNKNOWN) | |
509 |
|
507 | |||
510 |
def _merge_repo(self, |
|
508 | def _merge_repo(self, repo_id, workspace_id, target_ref, | |
511 | source_repo, source_ref, merge_message, |
|
509 | source_repo, source_ref, merge_message, | |
512 | merger_name, merger_email, dry_run=False, |
|
510 | merger_name, merger_email, dry_run=False, | |
513 | use_rebase=False, close_branch=False): |
|
511 | use_rebase=False, close_branch=False): | |
514 | """Internal implementation of merge.""" |
|
512 | """Internal implementation of merge.""" | |
515 | raise NotImplementedError |
|
513 | raise NotImplementedError | |
516 |
|
514 | |||
517 |
def _maybe_prepare_merge_workspace( |
|
515 | def _maybe_prepare_merge_workspace( | |
|
516 | self, repo_id, workspace_id, target_ref, source_ref): | |||
518 | """ |
|
517 | """ | |
519 | Create the merge workspace. |
|
518 | Create the merge workspace. | |
520 |
|
519 | |||
@@ -522,10 +521,27 b' class BaseRepository(object):' | |||||
522 | """ |
|
521 | """ | |
523 | raise NotImplementedError |
|
522 | raise NotImplementedError | |
524 |
|
523 | |||
525 | def _get_shadow_repository_path(self, workspace_id): |
|
524 | def _get_legacy_shadow_repository_path(self, workspace_id): | |
526 | raise NotImplementedError |
|
525 | """ | |
|
526 | Legacy version that was used before. We still need it for | |||
|
527 | backward compat | |||
|
528 | """ | |||
|
529 | return os.path.join( | |||
|
530 | os.path.dirname(self.path), | |||
|
531 | '.__shadow_%s_%s' % (os.path.basename(self.path), workspace_id)) | |||
527 |
|
532 | |||
528 |
def |
|
533 | def _get_shadow_repository_path(self, repo_id, workspace_id): | |
|
534 | # The name of the shadow repository must start with '.', so it is | |||
|
535 | # skipped by 'rhodecode.lib.utils.get_filesystem_repos'. | |||
|
536 | legacy_repository_path = self._get_legacy_shadow_repository_path(workspace_id) | |||
|
537 | if os.path.exists(legacy_repository_path): | |||
|
538 | return legacy_repository_path | |||
|
539 | else: | |||
|
540 | return os.path.join( | |||
|
541 | os.path.dirname(self.path), | |||
|
542 | '.__shadow_repo_%s_%s' % (repo_id, workspace_id)) | |||
|
543 | ||||
|
544 | def cleanup_merge_workspace(self, repo_id, workspace_id): | |||
529 | """ |
|
545 | """ | |
530 | Remove merge workspace. |
|
546 | Remove merge workspace. | |
531 |
|
547 | |||
@@ -534,7 +550,7 b' class BaseRepository(object):' | |||||
534 |
|
550 | |||
535 | :param workspace_id: `workspace_id` unique identifier. |
|
551 | :param workspace_id: `workspace_id` unique identifier. | |
536 | """ |
|
552 | """ | |
537 | shadow_repository_path = self._get_shadow_repository_path(workspace_id) |
|
553 | shadow_repository_path = self._get_shadow_repository_path(repo_id, workspace_id) | |
538 | shadow_repository_path_del = '{}.{}.delete'.format( |
|
554 | shadow_repository_path_del = '{}.{}.delete'.format( | |
539 | shadow_repository_path, time.time()) |
|
555 | shadow_repository_path, time.time()) | |
540 |
|
556 |
@@ -902,7 +902,19 b' class GitRepository(BaseRepository):' | |||||
902 |
|
902 | |||
903 | return '%s%d' % (prefix, branch_id) |
|
903 | return '%s%d' % (prefix, branch_id) | |
904 |
|
904 | |||
905 | def _merge_repo(self, shadow_repository_path, target_ref, |
|
905 | def _maybe_prepare_merge_workspace( | |
|
906 | self, repo_id, workspace_id, target_ref, source_ref): | |||
|
907 | shadow_repository_path = self._get_shadow_repository_path( | |||
|
908 | repo_id, workspace_id) | |||
|
909 | if not os.path.exists(shadow_repository_path): | |||
|
910 | self._local_clone( | |||
|
911 | shadow_repository_path, target_ref.name, source_ref.name) | |||
|
912 | log.debug( | |||
|
913 | 'Prepared shadow repository in %s', shadow_repository_path) | |||
|
914 | ||||
|
915 | return shadow_repository_path | |||
|
916 | ||||
|
917 | def _merge_repo(self, repo_id, workspace_id, target_ref, | |||
906 | source_repo, source_ref, merge_message, |
|
918 | source_repo, source_ref, merge_message, | |
907 | merger_name, merger_email, dry_run=False, |
|
919 | merger_name, merger_email, dry_run=False, | |
908 | use_rebase=False, close_branch=False): |
|
920 | use_rebase=False, close_branch=False): | |
@@ -912,7 +924,10 b' class GitRepository(BaseRepository):' | |||||
912 | return MergeResponse( |
|
924 | return MergeResponse( | |
913 | False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD) |
|
925 | False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD) | |
914 |
|
926 | |||
915 | shadow_repo = GitRepository(shadow_repository_path) |
|
927 | shadow_repository_path = self._maybe_prepare_merge_workspace( | |
|
928 | repo_id, workspace_id, target_ref, source_ref) | |||
|
929 | shadow_repo = self._get_shadow_instance(shadow_repository_path) | |||
|
930 | ||||
916 | # checkout source, if it's different. Otherwise we could not |
|
931 | # checkout source, if it's different. Otherwise we could not | |
917 | # fetch proper commits for merge testing |
|
932 | # fetch proper commits for merge testing | |
918 | if source_ref.name != target_ref.name: |
|
933 | if source_ref.name != target_ref.name: | |
@@ -929,7 +944,7 b' class GitRepository(BaseRepository):' | |||||
929 |
|
944 | |||
930 | # Need to reload repo to invalidate the cache, or otherwise we cannot |
|
945 | # Need to reload repo to invalidate the cache, or otherwise we cannot | |
931 | # retrieve the last target commit. |
|
946 | # retrieve the last target commit. | |
932 |
shadow_repo = |
|
947 | shadow_repo = self._get_shadow_instance(shadow_repository_path) | |
933 | if target_ref.commit_id != shadow_repo.branches[target_ref.name]: |
|
948 | if target_ref.commit_id != shadow_repo.branches[target_ref.name]: | |
934 | log.warning('Shadow Target ref %s commit mismatch %s vs %s', |
|
949 | log.warning('Shadow Target ref %s commit mismatch %s vs %s', | |
935 | target_ref, target_ref.commit_id, |
|
950 | target_ref, target_ref.commit_id, | |
@@ -989,18 +1004,3 b' class GitRepository(BaseRepository):' | |||||
989 | return MergeResponse( |
|
1004 | return MergeResponse( | |
990 | merge_possible, merge_succeeded, merge_ref, |
|
1005 | merge_possible, merge_succeeded, merge_ref, | |
991 | merge_failure_reason) |
|
1006 | merge_failure_reason) | |
992 |
|
||||
993 | def _get_shadow_repository_path(self, workspace_id): |
|
|||
994 | # The name of the shadow repository must start with '.', so it is |
|
|||
995 | # skipped by 'rhodecode.lib.utils.get_filesystem_repos'. |
|
|||
996 | return os.path.join( |
|
|||
997 | os.path.dirname(self.path), |
|
|||
998 | '.__shadow_%s_%s' % (os.path.basename(self.path), workspace_id)) |
|
|||
999 |
|
||||
1000 | def _maybe_prepare_merge_workspace(self, workspace_id, target_ref, source_ref): |
|
|||
1001 | shadow_repository_path = self._get_shadow_repository_path(workspace_id) |
|
|||
1002 | if not os.path.exists(shadow_repository_path): |
|
|||
1003 | self._local_clone( |
|
|||
1004 | shadow_repository_path, target_ref.name, source_ref.name) |
|
|||
1005 |
|
||||
1006 | return shadow_repository_path |
|
@@ -681,15 +681,10 b' class MercurialRepository(BaseRepository' | |||||
681 | return ref.name |
|
681 | return ref.name | |
682 | return self._remote.ctx_branch(ref.commit_id) |
|
682 | return self._remote.ctx_branch(ref.commit_id) | |
683 |
|
683 | |||
684 | def _get_shadow_repository_path(self, workspace_id): |
|
684 | def _maybe_prepare_merge_workspace( | |
685 | # The name of the shadow repository must start with '.', so it is |
|
685 | self, repo_id, workspace_id, unused_target_ref, unused_source_ref): | |
686 | # skipped by 'rhodecode.lib.utils.get_filesystem_repos'. |
|
686 | shadow_repository_path = self._get_shadow_repository_path( | |
687 | return os.path.join( |
|
687 | repo_id, workspace_id) | |
688 | os.path.dirname(self.path), |
|
|||
689 | '.__shadow_%s_%s' % (os.path.basename(self.path), workspace_id)) |
|
|||
690 |
|
||||
691 | def _maybe_prepare_merge_workspace(self, workspace_id, unused_target_ref, unused_source_ref): |
|
|||
692 | shadow_repository_path = self._get_shadow_repository_path(workspace_id) |
|
|||
693 | if not os.path.exists(shadow_repository_path): |
|
688 | if not os.path.exists(shadow_repository_path): | |
694 | self._local_clone(shadow_repository_path) |
|
689 | self._local_clone(shadow_repository_path) | |
695 | log.debug( |
|
690 | log.debug( | |
@@ -697,7 +692,7 b' class MercurialRepository(BaseRepository' | |||||
697 |
|
692 | |||
698 | return shadow_repository_path |
|
693 | return shadow_repository_path | |
699 |
|
694 | |||
700 |
def _merge_repo(self, |
|
695 | def _merge_repo(self, repo_id, workspace_id, target_ref, | |
701 | source_repo, source_ref, merge_message, |
|
696 | source_repo, source_ref, merge_message, | |
702 | merger_name, merger_email, dry_run=False, |
|
697 | merger_name, merger_email, dry_run=False, | |
703 | use_rebase=False, close_branch=False): |
|
698 | use_rebase=False, close_branch=False): | |
@@ -719,6 +714,8 b' class MercurialRepository(BaseRepository' | |||||
719 | return MergeResponse( |
|
714 | return MergeResponse( | |
720 | False, False, None, MergeFailureReason.MISSING_TARGET_REF) |
|
715 | False, False, None, MergeFailureReason.MISSING_TARGET_REF) | |
721 |
|
716 | |||
|
717 | shadow_repository_path = self._maybe_prepare_merge_workspace( | |||
|
718 | repo_id, workspace_id, target_ref, source_ref) | |||
722 | shadow_repo = self._get_shadow_instance(shadow_repository_path) |
|
719 | shadow_repo = self._get_shadow_instance(shadow_repository_path) | |
723 |
|
720 | |||
724 | log.debug('Pulling in target reference %s', target_ref) |
|
721 | log.debug('Pulling in target reference %s', target_ref) |
@@ -1883,6 +1883,12 b' class Repository(Base, BaseModel):' | |||||
1883 | return os.listdir(diff_cache_dir) |
|
1883 | return os.listdir(diff_cache_dir) | |
1884 | return [] |
|
1884 | return [] | |
1885 |
|
1885 | |||
|
1886 | def shadow_repos(self): | |||
|
1887 | shadow_repos_pattern = '.__shadow_repo_{}'.format(self.repo_id) | |||
|
1888 | return [ | |||
|
1889 | x for x in os.listdir(os.path.dirname(self.repo_full_path)) | |||
|
1890 | if x.startswith(shadow_repos_pattern)] | |||
|
1891 | ||||
1886 | def get_new_name(self, repo_name): |
|
1892 | def get_new_name(self, repo_name): | |
1887 | """ |
|
1893 | """ | |
1888 | returns new full repository name based on assigned group and new new |
|
1894 | returns new full repository name based on assigned group and new new | |
@@ -3762,7 +3768,7 b' class PullRequest(Base, _PullRequestBase' | |||||
3762 | workspace_id = self.workspace_id |
|
3768 | workspace_id = self.workspace_id | |
3763 | vcs_obj = self.target_repo.scm_instance() |
|
3769 | vcs_obj = self.target_repo.scm_instance() | |
3764 | shadow_repository_path = vcs_obj._get_shadow_repository_path( |
|
3770 | shadow_repository_path = vcs_obj._get_shadow_repository_path( | |
3765 | workspace_id) |
|
3771 | self.target_repo.repo_id, workspace_id) | |
3766 | if os.path.isdir(shadow_repository_path): |
|
3772 | if os.path.isdir(shadow_repository_path): | |
3767 | return vcs_obj._get_shadow_instance(shadow_repository_path) |
|
3773 | return vcs_obj._get_shadow_instance(shadow_repository_path) | |
3768 |
|
3774 |
@@ -583,7 +583,7 b' class PullRequestModel(BaseModel):' | |||||
583 |
|
583 | |||
584 | return commit_ids |
|
584 | return commit_ids | |
585 |
|
585 | |||
586 | def merge(self, pull_request, user, extras): |
|
586 | def merge_repo(self, pull_request, user, extras): | |
587 | log.debug("Merging pull request %s", pull_request.pull_request_id) |
|
587 | log.debug("Merging pull request %s", pull_request.pull_request_id) | |
588 | merge_state = self._merge_pull_request(pull_request, user, extras) |
|
588 | merge_state = self._merge_pull_request(pull_request, user, extras) | |
589 | if merge_state.executed: |
|
589 | if merge_state.executed: | |
@@ -616,6 +616,7 b' class PullRequestModel(BaseModel):' | |||||
616 | } |
|
616 | } | |
617 |
|
617 | |||
618 | workspace_id = self._workspace_id(pull_request) |
|
618 | workspace_id = self._workspace_id(pull_request) | |
|
619 | repo_id = pull_request.target_repo.repo_id | |||
619 | use_rebase = self._use_rebase_for_merging(pull_request) |
|
620 | use_rebase = self._use_rebase_for_merging(pull_request) | |
620 | close_branch = self._close_branch_before_merging(pull_request) |
|
621 | close_branch = self._close_branch_before_merging(pull_request) | |
621 |
|
622 | |||
@@ -629,9 +630,10 b' class PullRequestModel(BaseModel):' | |||||
629 | target_vcs.config.set( |
|
630 | target_vcs.config.set( | |
630 | 'rhodecode', 'RC_SCM_DATA', json.dumps(extras)) |
|
631 | 'rhodecode', 'RC_SCM_DATA', json.dumps(extras)) | |
631 | merge_state = target_vcs.merge( |
|
632 | merge_state = target_vcs.merge( | |
632 | target_ref, source_vcs, pull_request.source_ref_parts, |
|
633 | repo_id, workspace_id, target_ref, source_vcs, | |
633 | workspace_id, user_name=user.username, |
|
634 | pull_request.source_ref_parts, | |
634 | user_email=user.email, message=message, use_rebase=use_rebase, |
|
635 | user_name=user.username, user_email=user.email, | |
|
636 | message=message, use_rebase=use_rebase, | |||
635 | close_branch=close_branch) |
|
637 | close_branch=close_branch) | |
636 | return merge_state |
|
638 | return merge_state | |
637 |
|
639 | |||
@@ -1328,11 +1330,13 b' class PullRequestModel(BaseModel):' | |||||
1328 | def _refresh_merge_state(self, pull_request, target_vcs, target_reference): |
|
1330 | def _refresh_merge_state(self, pull_request, target_vcs, target_reference): | |
1329 | workspace_id = self._workspace_id(pull_request) |
|
1331 | workspace_id = self._workspace_id(pull_request) | |
1330 | source_vcs = pull_request.source_repo.scm_instance() |
|
1332 | source_vcs = pull_request.source_repo.scm_instance() | |
|
1333 | repo_id = pull_request.target_repo.repo_id | |||
1331 | use_rebase = self._use_rebase_for_merging(pull_request) |
|
1334 | use_rebase = self._use_rebase_for_merging(pull_request) | |
1332 | close_branch = self._close_branch_before_merging(pull_request) |
|
1335 | close_branch = self._close_branch_before_merging(pull_request) | |
1333 | merge_state = target_vcs.merge( |
|
1336 | merge_state = target_vcs.merge( | |
|
1337 | repo_id, workspace_id, | |||
1334 | target_reference, source_vcs, pull_request.source_ref_parts, |
|
1338 | target_reference, source_vcs, pull_request.source_ref_parts, | |
1335 |
|
|
1339 | dry_run=True, use_rebase=use_rebase, | |
1336 | close_branch=close_branch) |
|
1340 | close_branch=close_branch) | |
1337 |
|
1341 | |||
1338 | # Do not store the response if there was an unknown error. |
|
1342 | # Do not store the response if there was an unknown error. | |
@@ -1398,11 +1402,12 b' class PullRequestModel(BaseModel):' | |||||
1398 |
|
1402 | |||
1399 | def _cleanup_merge_workspace(self, pull_request): |
|
1403 | def _cleanup_merge_workspace(self, pull_request): | |
1400 | # Merging related cleanup |
|
1404 | # Merging related cleanup | |
|
1405 | repo_id = pull_request.target_repo.repo_id | |||
1401 | target_scm = pull_request.target_repo.scm_instance() |
|
1406 | target_scm = pull_request.target_repo.scm_instance() | |
1402 |
workspace_id = |
|
1407 | workspace_id = self._workspace_id(pull_request) | |
1403 |
|
1408 | |||
1404 | try: |
|
1409 | try: | |
1405 | target_scm.cleanup_merge_workspace(workspace_id) |
|
1410 | target_scm.cleanup_merge_workspace(repo_id, workspace_id) | |
1406 | except NotImplementedError: |
|
1411 | except NotImplementedError: | |
1407 | pass |
|
1412 | pass | |
1408 |
|
1413 |
@@ -116,6 +116,13 b' def get_new_dir(title):' | |||||
116 | return get_normalized_path(path) |
|
116 | return get_normalized_path(path) | |
117 |
|
117 | |||
118 |
|
118 | |||
|
119 | def repo_id_generator(name): | |||
|
120 | numeric_hash = 0 | |||
|
121 | for char in name: | |||
|
122 | numeric_hash += (ord(char)) | |||
|
123 | return numeric_hash | |||
|
124 | ||||
|
125 | ||||
119 | @pytest.mark.usefixtures('app', 'index_location') |
|
126 | @pytest.mark.usefixtures('app', 'index_location') | |
120 | class TestController(object): |
|
127 | class TestController(object): | |
121 |
|
128 |
@@ -333,7 +333,7 b' class TestShadowRepoExposure(object):' | |||||
333 | workspace_id = PullRequestModel()._workspace_id(pull_request) |
|
333 | workspace_id = PullRequestModel()._workspace_id(pull_request) | |
334 | target_vcs = pull_request.target_repo.scm_instance() |
|
334 | target_vcs = pull_request.target_repo.scm_instance() | |
335 | vcs_repo_name = target_vcs._get_shadow_repository_path( |
|
335 | vcs_repo_name = target_vcs._get_shadow_repository_path( | |
336 | workspace_id) |
|
336 | pull_request.target_repo.repo_id, workspace_id) | |
337 |
|
337 | |||
338 | assert controller.vcs_repo_name == vcs_repo_name |
|
338 | assert controller.vcs_repo_name == vcs_repo_name | |
339 | assert controller.url_repo_name == shadow_url |
|
339 | assert controller.url_repo_name == shadow_url |
@@ -81,6 +81,7 b' class TestPullRequestModel(object):' | |||||
81 | self.source_commit = self.pull_request.source_ref_parts.commit_id |
|
81 | self.source_commit = self.pull_request.source_ref_parts.commit_id | |
82 | self.target_commit = self.pull_request.target_ref_parts.commit_id |
|
82 | self.target_commit = self.pull_request.target_ref_parts.commit_id | |
83 | self.workspace_id = 'pr-%s' % self.pull_request.pull_request_id |
|
83 | self.workspace_id = 'pr-%s' % self.pull_request.pull_request_id | |
|
84 | self.repo_id = self.pull_request.target_repo.repo_id | |||
84 |
|
85 | |||
85 | @request.addfinalizer |
|
86 | @request.addfinalizer | |
86 | def cleanup_pull_request(): |
|
87 | def cleanup_pull_request(): | |
@@ -135,17 +136,19 b' class TestPullRequestModel(object):' | |||||
135 | assert pr_count == 1 |
|
136 | assert pr_count == 1 | |
136 |
|
137 | |||
137 | def test_delete_calls_cleanup_merge(self, pull_request): |
|
138 | def test_delete_calls_cleanup_merge(self, pull_request): | |
|
139 | repo_id = pull_request.target_repo.repo_id | |||
138 | PullRequestModel().delete(pull_request, pull_request.author) |
|
140 | PullRequestModel().delete(pull_request, pull_request.author) | |
139 |
|
141 | |||
140 | self.workspace_remove_mock.assert_called_once_with( |
|
142 | self.workspace_remove_mock.assert_called_once_with( | |
141 | self.workspace_id) |
|
143 | repo_id, self.workspace_id) | |
142 |
|
144 | |||
143 | def test_close_calls_cleanup_and_hook(self, pull_request): |
|
145 | def test_close_calls_cleanup_and_hook(self, pull_request): | |
144 | PullRequestModel().close_pull_request( |
|
146 | PullRequestModel().close_pull_request( | |
145 | pull_request, pull_request.author) |
|
147 | pull_request, pull_request.author) | |
|
148 | repo_id = pull_request.target_repo.repo_id | |||
146 |
|
149 | |||
147 | self.workspace_remove_mock.assert_called_once_with( |
|
150 | self.workspace_remove_mock.assert_called_once_with( | |
148 | self.workspace_id) |
|
151 | repo_id, self.workspace_id) | |
149 | self.hook_mock.assert_called_with( |
|
152 | self.hook_mock.assert_called_with( | |
150 | self.pull_request, self.pull_request.author, 'close') |
|
153 | self.pull_request, self.pull_request.author, 'close') | |
151 |
|
154 | |||
@@ -161,9 +164,10 b' class TestPullRequestModel(object):' | |||||
161 | assert status is True |
|
164 | assert status is True | |
162 | assert msg.eval() == 'This pull request can be automatically merged.' |
|
165 | assert msg.eval() == 'This pull request can be automatically merged.' | |
163 | self.merge_mock.assert_called_with( |
|
166 | self.merge_mock.assert_called_with( | |
|
167 | self.repo_id, self.workspace_id, | |||
164 | pull_request.target_ref_parts, |
|
168 | pull_request.target_ref_parts, | |
165 | pull_request.source_repo.scm_instance(), |
|
169 | pull_request.source_repo.scm_instance(), | |
166 |
pull_request.source_ref_parts, |
|
170 | pull_request.source_ref_parts, dry_run=True, | |
167 | use_rebase=False, close_branch=False) |
|
171 | use_rebase=False, close_branch=False) | |
168 |
|
172 | |||
169 | assert pull_request._last_merge_source_rev == self.source_commit |
|
173 | assert pull_request._last_merge_source_rev == self.source_commit | |
@@ -190,9 +194,10 b' class TestPullRequestModel(object):' | |||||
190 | msg.eval() == |
|
194 | msg.eval() == | |
191 | 'This pull request cannot be merged because of merge conflicts.') |
|
195 | 'This pull request cannot be merged because of merge conflicts.') | |
192 | self.merge_mock.assert_called_with( |
|
196 | self.merge_mock.assert_called_with( | |
|
197 | self.repo_id, self.workspace_id, | |||
193 | pull_request.target_ref_parts, |
|
198 | pull_request.target_ref_parts, | |
194 | pull_request.source_repo.scm_instance(), |
|
199 | pull_request.source_repo.scm_instance(), | |
195 |
pull_request.source_ref_parts, |
|
200 | pull_request.source_ref_parts, dry_run=True, | |
196 | use_rebase=False, close_branch=False) |
|
201 | use_rebase=False, close_branch=False) | |
197 |
|
202 | |||
198 | assert pull_request._last_merge_source_rev == self.source_commit |
|
203 | assert pull_request._last_merge_source_rev == self.source_commit | |
@@ -222,9 +227,10 b' class TestPullRequestModel(object):' | |||||
222 | 'This pull request cannot be merged because of an unhandled' |
|
227 | 'This pull request cannot be merged because of an unhandled' | |
223 | ' exception.') |
|
228 | ' exception.') | |
224 | self.merge_mock.assert_called_with( |
|
229 | self.merge_mock.assert_called_with( | |
|
230 | self.repo_id, self.workspace_id, | |||
225 | pull_request.target_ref_parts, |
|
231 | pull_request.target_ref_parts, | |
226 | pull_request.source_repo.scm_instance(), |
|
232 | pull_request.source_repo.scm_instance(), | |
227 |
pull_request.source_ref_parts, |
|
233 | pull_request.source_ref_parts, dry_run=True, | |
228 | use_rebase=False, close_branch=False) |
|
234 | use_rebase=False, close_branch=False) | |
229 |
|
235 | |||
230 | assert pull_request._last_merge_source_rev is None |
|
236 | assert pull_request._last_merge_source_rev is None | |
@@ -281,7 +287,7 b' class TestPullRequestModel(object):' | |||||
281 | True, True, merge_ref, MergeFailureReason.NONE) |
|
287 | True, True, merge_ref, MergeFailureReason.NONE) | |
282 |
|
288 | |||
283 | merge_extras['repository'] = pull_request.target_repo.repo_name |
|
289 | merge_extras['repository'] = pull_request.target_repo.repo_name | |
284 | PullRequestModel().merge( |
|
290 | PullRequestModel().merge_repo( | |
285 | pull_request, pull_request.author, extras=merge_extras) |
|
291 | pull_request, pull_request.author, extras=merge_extras) | |
286 |
|
292 | |||
287 | message = ( |
|
293 | message = ( | |
@@ -295,9 +301,10 b' class TestPullRequestModel(object):' | |||||
295 | ) |
|
301 | ) | |
296 | ) |
|
302 | ) | |
297 | self.merge_mock.assert_called_with( |
|
303 | self.merge_mock.assert_called_with( | |
|
304 | self.repo_id, self.workspace_id, | |||
298 | pull_request.target_ref_parts, |
|
305 | pull_request.target_ref_parts, | |
299 | pull_request.source_repo.scm_instance(), |
|
306 | pull_request.source_repo.scm_instance(), | |
300 |
pull_request.source_ref_parts, |
|
307 | pull_request.source_ref_parts, | |
301 | user_name=user.username, user_email=user.email, message=message, |
|
308 | user_name=user.username, user_email=user.email, message=message, | |
302 | use_rebase=False, close_branch=False |
|
309 | use_rebase=False, close_branch=False | |
303 | ) |
|
310 | ) | |
@@ -320,7 +327,7 b' class TestPullRequestModel(object):' | |||||
320 | False, False, merge_ref, MergeFailureReason.MERGE_FAILED) |
|
327 | False, False, merge_ref, MergeFailureReason.MERGE_FAILED) | |
321 |
|
328 | |||
322 | merge_extras['repository'] = pull_request.target_repo.repo_name |
|
329 | merge_extras['repository'] = pull_request.target_repo.repo_name | |
323 | PullRequestModel().merge( |
|
330 | PullRequestModel().merge_repo( | |
324 | pull_request, pull_request.author, extras=merge_extras) |
|
331 | pull_request, pull_request.author, extras=merge_extras) | |
325 |
|
332 | |||
326 | message = ( |
|
333 | message = ( | |
@@ -334,9 +341,10 b' class TestPullRequestModel(object):' | |||||
334 | ) |
|
341 | ) | |
335 | ) |
|
342 | ) | |
336 | self.merge_mock.assert_called_with( |
|
343 | self.merge_mock.assert_called_with( | |
|
344 | self.repo_id, self.workspace_id, | |||
337 | pull_request.target_ref_parts, |
|
345 | pull_request.target_ref_parts, | |
338 | pull_request.source_repo.scm_instance(), |
|
346 | pull_request.source_repo.scm_instance(), | |
339 |
pull_request.source_ref_parts, |
|
347 | pull_request.source_ref_parts, | |
340 | user_name=user.username, user_email=user.email, message=message, |
|
348 | user_name=user.username, user_email=user.email, message=message, | |
341 | use_rebase=False, close_branch=False |
|
349 | use_rebase=False, close_branch=False | |
342 | ) |
|
350 | ) | |
@@ -392,7 +400,7 b' class TestIntegrationMerge(object):' | |||||
392 | Session().commit() |
|
400 | Session().commit() | |
393 |
|
401 | |||
394 | with mock.patch.dict(rhodecode.CONFIG, extra_config, clear=False): |
|
402 | with mock.patch.dict(rhodecode.CONFIG, extra_config, clear=False): | |
395 | merge_state = PullRequestModel().merge( |
|
403 | merge_state = PullRequestModel().merge_repo( | |
396 | pull_request, user_admin, extras=merge_extras) |
|
404 | pull_request, user_admin, extras=merge_extras) | |
397 |
|
405 | |||
398 | assert merge_state.executed |
|
406 | assert merge_state.executed | |
@@ -409,7 +417,7 b' class TestIntegrationMerge(object):' | |||||
409 |
|
417 | |||
410 | with mock.patch('rhodecode.EXTENSIONS.PRE_PUSH_HOOK') as pre_pull: |
|
418 | with mock.patch('rhodecode.EXTENSIONS.PRE_PUSH_HOOK') as pre_pull: | |
411 | pre_pull.side_effect = RepositoryError("Disallow push!") |
|
419 | pre_pull.side_effect = RepositoryError("Disallow push!") | |
412 | merge_status = PullRequestModel().merge( |
|
420 | merge_status = PullRequestModel().merge_repo( | |
413 | pull_request, user_admin, extras=merge_extras) |
|
421 | pull_request, user_admin, extras=merge_extras) | |
414 |
|
422 | |||
415 | assert not merge_status.executed |
|
423 | assert not merge_status.executed | |
@@ -429,7 +437,7 b' class TestIntegrationMerge(object):' | |||||
429 | merge_extras['repository'] = pull_request.target_repo.repo_name |
|
437 | merge_extras['repository'] = pull_request.target_repo.repo_name | |
430 | # TODO: johbo: Needed for sqlite, try to find an automatic way for it |
|
438 | # TODO: johbo: Needed for sqlite, try to find an automatic way for it | |
431 | Session().commit() |
|
439 | Session().commit() | |
432 | merge_status = PullRequestModel().merge( |
|
440 | merge_status = PullRequestModel().merge_repo( | |
433 | pull_request, user_regular, extras=merge_extras) |
|
441 | pull_request, user_regular, extras=merge_extras) | |
434 | assert not merge_status.executed |
|
442 | assert not merge_status.executed | |
435 |
|
443 |
@@ -566,7 +566,7 b' TODO: To be written...' | |||||
566 |
|
566 | |||
567 | def test_maybe_prepare_merge_workspace(self): |
|
567 | def test_maybe_prepare_merge_workspace(self): | |
568 | workspace = self.repo._maybe_prepare_merge_workspace( |
|
568 | workspace = self.repo._maybe_prepare_merge_workspace( | |
569 | 'pr2', Reference('branch', 'master', 'unused'), |
|
569 | 2, 'pr2', Reference('branch', 'master', 'unused'), | |
570 | Reference('branch', 'master', 'unused')) |
|
570 | Reference('branch', 'master', 'unused')) | |
571 |
|
571 | |||
572 | assert os.path.isdir(workspace) |
|
572 | assert os.path.isdir(workspace) | |
@@ -575,13 +575,13 b' TODO: To be written...' | |||||
575 |
|
575 | |||
576 | # Calling it a second time should also succeed |
|
576 | # Calling it a second time should also succeed | |
577 | workspace = self.repo._maybe_prepare_merge_workspace( |
|
577 | workspace = self.repo._maybe_prepare_merge_workspace( | |
578 | 'pr2', Reference('branch', 'master', 'unused'), |
|
578 | 2, 'pr2', Reference('branch', 'master', 'unused'), | |
579 | Reference('branch', 'master', 'unused')) |
|
579 | Reference('branch', 'master', 'unused')) | |
580 | assert os.path.isdir(workspace) |
|
580 | assert os.path.isdir(workspace) | |
581 |
|
581 | |||
582 | def test_maybe_prepare_merge_workspace_different_refs(self): |
|
582 | def test_maybe_prepare_merge_workspace_different_refs(self): | |
583 | workspace = self.repo._maybe_prepare_merge_workspace( |
|
583 | workspace = self.repo._maybe_prepare_merge_workspace( | |
584 | 'pr2', Reference('branch', 'master', 'unused'), |
|
584 | 2, 'pr2', Reference('branch', 'master', 'unused'), | |
585 | Reference('branch', 'develop', 'unused')) |
|
585 | Reference('branch', 'develop', 'unused')) | |
586 |
|
586 | |||
587 | assert os.path.isdir(workspace) |
|
587 | assert os.path.isdir(workspace) | |
@@ -590,22 +590,22 b' TODO: To be written...' | |||||
590 |
|
590 | |||
591 | # Calling it a second time should also succeed |
|
591 | # Calling it a second time should also succeed | |
592 | workspace = self.repo._maybe_prepare_merge_workspace( |
|
592 | workspace = self.repo._maybe_prepare_merge_workspace( | |
593 | 'pr2', Reference('branch', 'master', 'unused'), |
|
593 | 2, 'pr2', Reference('branch', 'master', 'unused'), | |
594 | Reference('branch', 'develop', 'unused')) |
|
594 | Reference('branch', 'develop', 'unused')) | |
595 | assert os.path.isdir(workspace) |
|
595 | assert os.path.isdir(workspace) | |
596 |
|
596 | |||
597 | def test_cleanup_merge_workspace(self): |
|
597 | def test_cleanup_merge_workspace(self): | |
598 | workspace = self.repo._maybe_prepare_merge_workspace( |
|
598 | workspace = self.repo._maybe_prepare_merge_workspace( | |
599 | 'pr3', Reference('branch', 'master', 'unused'), |
|
599 | 2, 'pr3', Reference('branch', 'master', 'unused'), | |
600 | Reference('branch', 'master', 'unused')) |
|
600 | Reference('branch', 'master', 'unused')) | |
601 | self.repo.cleanup_merge_workspace('pr3') |
|
601 | self.repo.cleanup_merge_workspace(2, 'pr3') | |
602 |
|
602 | |||
603 | assert not os.path.exists(workspace) |
|
603 | assert not os.path.exists(workspace) | |
604 |
|
604 | |||
605 | def test_cleanup_merge_workspace_invalid_workspace_id(self): |
|
605 | def test_cleanup_merge_workspace_invalid_workspace_id(self): | |
606 | # No assert: because in case of an inexistent workspace this function |
|
606 | # No assert: because in case of an inexistent workspace this function | |
607 | # should still succeed. |
|
607 | # should still succeed. | |
608 | self.repo.cleanup_merge_workspace('pr4') |
|
608 | self.repo.cleanup_merge_workspace(1, 'pr4') | |
609 |
|
609 | |||
610 | def test_set_refs(self): |
|
610 | def test_set_refs(self): | |
611 | test_ref = 'refs/test-refs/abcde' |
|
611 | test_ref = 'refs/test-refs/abcde' |
@@ -31,7 +31,7 b' from rhodecode.lib.vcs.backends.hg impor' | |||||
31 | from rhodecode.lib.vcs.exceptions import ( |
|
31 | from rhodecode.lib.vcs.exceptions import ( | |
32 | RepositoryError, VCSError, NodeDoesNotExistError, CommitDoesNotExistError) |
|
32 | RepositoryError, VCSError, NodeDoesNotExistError, CommitDoesNotExistError) | |
33 | from rhodecode.lib.vcs.nodes import FileNode, NodeKind, NodeState |
|
33 | from rhodecode.lib.vcs.nodes import FileNode, NodeKind, NodeState | |
34 | from rhodecode.tests import TEST_HG_REPO, TEST_HG_REPO_CLONE |
|
34 | from rhodecode.tests import TEST_HG_REPO, TEST_HG_REPO_CLONE, repo_id_generator | |
35 |
|
35 | |||
36 |
|
36 | |||
37 | pytestmark = pytest.mark.backends("hg") |
|
37 | pytestmark = pytest.mark.backends("hg") | |
@@ -46,7 +46,6 b' def repo_path_generator():' | |||||
46 | i += 1 |
|
46 | i += 1 | |
47 | yield '%s-%d' % (TEST_HG_REPO_CLONE, i) |
|
47 | yield '%s-%d' % (TEST_HG_REPO_CLONE, i) | |
48 |
|
48 | |||
49 |
|
||||
50 | REPO_PATH_GENERATOR = repo_path_generator() |
|
49 | REPO_PATH_GENERATOR = repo_path_generator() | |
51 |
|
50 | |||
52 |
|
51 | |||
@@ -553,7 +552,7 b' TODO: To be written...' | |||||
553 |
|
552 | |||
554 | def test_maybe_prepare_merge_workspace(self): |
|
553 | def test_maybe_prepare_merge_workspace(self): | |
555 | workspace = self.repo._maybe_prepare_merge_workspace( |
|
554 | workspace = self.repo._maybe_prepare_merge_workspace( | |
556 | 'pr2', 'unused', 'unused2') |
|
555 | 1, 'pr2', 'unused', 'unused2') | |
557 |
|
556 | |||
558 | assert os.path.isdir(workspace) |
|
557 | assert os.path.isdir(workspace) | |
559 | workspace_repo = MercurialRepository(workspace) |
|
558 | workspace_repo = MercurialRepository(workspace) | |
@@ -561,20 +560,22 b' TODO: To be written...' | |||||
561 |
|
560 | |||
562 | # Calling it a second time should also succeed |
|
561 | # Calling it a second time should also succeed | |
563 | workspace = self.repo._maybe_prepare_merge_workspace( |
|
562 | workspace = self.repo._maybe_prepare_merge_workspace( | |
564 | 'pr2', 'unused', 'unused2') |
|
563 | 1, 'pr2', 'unused', 'unused2') | |
565 | assert os.path.isdir(workspace) |
|
564 | assert os.path.isdir(workspace) | |
566 |
|
565 | |||
567 | def test_cleanup_merge_workspace(self): |
|
566 | def test_cleanup_merge_workspace(self): | |
568 | workspace = self.repo._maybe_prepare_merge_workspace( |
|
567 | workspace = self.repo._maybe_prepare_merge_workspace( | |
569 | 'pr3', 'unused', 'unused2') |
|
568 | 1, 'pr3', 'unused', 'unused2') | |
570 | self.repo.cleanup_merge_workspace('pr3') |
|
569 | ||
|
570 | assert os.path.isdir(workspace) | |||
|
571 | self.repo.cleanup_merge_workspace(1, 'pr3') | |||
571 |
|
572 | |||
572 | assert not os.path.exists(workspace) |
|
573 | assert not os.path.exists(workspace) | |
573 |
|
574 | |||
574 | def test_cleanup_merge_workspace_invalid_workspace_id(self): |
|
575 | def test_cleanup_merge_workspace_invalid_workspace_id(self): | |
575 | # No assert: because in case of an inexistent workspace this function |
|
576 | # No assert: because in case of an inexistent workspace this function | |
576 | # should still succeed. |
|
577 | # should still succeed. | |
577 | self.repo.cleanup_merge_workspace('pr4') |
|
578 | self.repo.cleanup_merge_workspace(1, 'pr4') | |
578 |
|
579 | |||
579 | def test_merge_target_is_bookmark(self, vcsbackend_hg): |
|
580 | def test_merge_target_is_bookmark(self, vcsbackend_hg): | |
580 | target_repo = vcsbackend_hg.create_repo(number_of_commits=1) |
|
581 | target_repo = vcsbackend_hg.create_repo(number_of_commits=1) | |
@@ -594,10 +595,10 b' TODO: To be written...' | |||||
594 | target_repo.bookmark(bookmark_name) |
|
595 | target_repo.bookmark(bookmark_name) | |
595 | target_ref = Reference('book', bookmark_name, target_commit.raw_id) |
|
596 | target_ref = Reference('book', bookmark_name, target_commit.raw_id) | |
596 | source_ref = Reference('branch', default_branch, source_commit.raw_id) |
|
597 | source_ref = Reference('branch', default_branch, source_commit.raw_id) | |
597 | workspace = 'test-merge' |
|
598 | workspace_id = 'test-merge' | |
598 |
|
599 | repo_id = repo_id_generator(target_repo.path) | ||
599 | merge_response = target_repo.merge( |
|
600 | merge_response = target_repo.merge( | |
600 |
target_ref, source_repo, source_ref, |
|
601 | repo_id, workspace_id, target_ref, source_repo, source_ref, | |
601 | 'test user', 'test@rhodecode.com', 'merge message 1', |
|
602 | 'test user', 'test@rhodecode.com', 'merge message 1', | |
602 | dry_run=False) |
|
603 | dry_run=False) | |
603 | expected_merge_response = MergeResponse( |
|
604 | expected_merge_response = MergeResponse( | |
@@ -638,10 +639,10 b' TODO: To be written...' | |||||
638 | source_repo._update(default_branch) |
|
639 | source_repo._update(default_branch) | |
639 | source_repo.bookmark(bookmark_name) |
|
640 | source_repo.bookmark(bookmark_name) | |
640 | source_ref = Reference('book', bookmark_name, source_commit.raw_id) |
|
641 | source_ref = Reference('book', bookmark_name, source_commit.raw_id) | |
641 | workspace = 'test-merge' |
|
642 | workspace_id = 'test-merge' | |
642 |
|
643 | repo_id = repo_id_generator(target_repo.path) | ||
643 | merge_response = target_repo.merge( |
|
644 | merge_response = target_repo.merge( | |
644 |
target_ref, source_repo, source_ref, |
|
645 | repo_id, workspace_id, target_ref, source_repo, source_ref, | |
645 | 'test user', 'test@rhodecode.com', 'merge message 1', |
|
646 | 'test user', 'test@rhodecode.com', 'merge message 1', | |
646 | dry_run=False) |
|
647 | dry_run=False) | |
647 | expected_merge_response = MergeResponse( |
|
648 | expected_merge_response = MergeResponse( | |
@@ -677,14 +678,15 b' TODO: To be written...' | |||||
677 |
|
678 | |||
678 | target_ref = Reference('branch', default_branch, target_commit.raw_id) |
|
679 | target_ref = Reference('branch', default_branch, target_commit.raw_id) | |
679 | source_ref = Reference('branch', default_branch, source_commit.raw_id) |
|
680 | source_ref = Reference('branch', default_branch, source_commit.raw_id) | |
680 | workspace = 'test-merge' |
|
681 | workspace_id = 'test-merge' | |
681 |
|
682 | |||
682 | assert len(target_repo._heads(branch='default')) == 2 |
|
683 | assert len(target_repo._heads(branch='default')) == 2 | |
683 | expected_merge_response = MergeResponse( |
|
684 | expected_merge_response = MergeResponse( | |
684 | False, False, None, |
|
685 | False, False, None, | |
685 | MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS) |
|
686 | MergeFailureReason.HG_TARGET_HAS_MULTIPLE_HEADS) | |
|
687 | repo_id = repo_id_generator(target_repo.path) | |||
686 | merge_response = target_repo.merge( |
|
688 | merge_response = target_repo.merge( | |
687 |
target_ref, source_repo, source_ref, |
|
689 | repo_id, workspace_id, target_ref, source_repo, source_ref, | |
688 | 'test user', 'test@rhodecode.com', 'merge message 1', |
|
690 | 'test user', 'test@rhodecode.com', 'merge message 1', | |
689 | dry_run=False) |
|
691 | dry_run=False) | |
690 | assert merge_response == expected_merge_response |
|
692 | assert merge_response == expected_merge_response | |
@@ -711,10 +713,11 b' TODO: To be written...' | |||||
711 |
|
713 | |||
712 | target_ref = Reference('branch', default_branch, target_commit.raw_id) |
|
714 | target_ref = Reference('branch', default_branch, target_commit.raw_id) | |
713 | source_ref = Reference('book', bookmark_name, source_commit.raw_id) |
|
715 | source_ref = Reference('book', bookmark_name, source_commit.raw_id) | |
714 | workspace = 'test-merge' |
|
716 | repo_id = repo_id_generator(target_repo.path) | |
|
717 | workspace_id = 'test-merge' | |||
715 |
|
718 | |||
716 | merge_response = target_repo.merge( |
|
719 | merge_response = target_repo.merge( | |
717 |
target_ref, source_repo, source_ref, |
|
720 | repo_id, workspace_id, target_ref, source_repo, source_ref, | |
718 | 'test user', 'test@rhodecode.com', 'merge message 1', |
|
721 | 'test user', 'test@rhodecode.com', 'merge message 1', | |
719 | dry_run=False, use_rebase=True) |
|
722 | dry_run=False, use_rebase=True) | |
720 |
|
723 |
@@ -95,7 +95,7 b' class TestMercurialRemoteRepoInvalidatio' | |||||
95 | references. |
|
95 | references. | |
96 | """ |
|
96 | """ | |
97 | from rhodecode.model.pull_request import PullRequestModel |
|
97 | from rhodecode.model.pull_request import PullRequestModel | |
98 |
|
98 | repo_id = pull_request.target_repo | ||
99 | target_vcs = pull_request.target_repo.scm_instance() |
|
99 | target_vcs = pull_request.target_repo.scm_instance() | |
100 | target_ref = pull_request.target_ref_parts |
|
100 | target_ref = pull_request.target_ref_parts | |
101 | source_ref = pull_request.source_ref_parts |
|
101 | source_ref = pull_request.source_ref_parts | |
@@ -104,7 +104,7 b' class TestMercurialRemoteRepoInvalidatio' | |||||
104 | pr = PullRequestModel() |
|
104 | pr = PullRequestModel() | |
105 | workspace_id = pr._workspace_id(pull_request) |
|
105 | workspace_id = pr._workspace_id(pull_request) | |
106 | shadow_repository_path = target_vcs._maybe_prepare_merge_workspace( |
|
106 | shadow_repository_path = target_vcs._maybe_prepare_merge_workspace( | |
107 | workspace_id, target_ref, source_ref) |
|
107 | repo_id, workspace_id, target_ref, source_ref) | |
108 | shadow_repo = target_vcs._get_shadow_instance(shadow_repository_path) |
|
108 | shadow_repo = target_vcs._get_shadow_instance(shadow_repository_path) | |
109 |
|
109 | |||
110 | # This will populate the cache of the mercurial repository object |
|
110 | # This will populate the cache of the mercurial repository object |
@@ -30,6 +30,7 b' from rhodecode.lib.vcs.backends.base imp' | |||||
30 | from rhodecode.lib.vcs.exceptions import VCSError, RepositoryError |
|
30 | from rhodecode.lib.vcs.exceptions import VCSError, RepositoryError | |
31 | from rhodecode.lib.vcs.nodes import FileNode |
|
31 | from rhodecode.lib.vcs.nodes import FileNode | |
32 | from rhodecode.tests.vcs.conftest import BackendTestMixin |
|
32 | from rhodecode.tests.vcs.conftest import BackendTestMixin | |
|
33 | from rhodecode.tests import repo_id_generator | |||
33 |
|
34 | |||
34 |
|
35 | |||
35 | @pytest.mark.usefixtures("vcs_repository_support") |
|
36 | @pytest.mark.usefixtures("vcs_repository_support") | |
@@ -268,7 +269,7 b' class TestRepositoryGetCommonAncestor:' | |||||
268 |
|
269 | |||
269 |
|
270 | |||
270 | @pytest.mark.backends("git", "hg") |
|
271 | @pytest.mark.backends("git", "hg") | |
271 | class TestRepositoryMerge: |
|
272 | class TestRepositoryMerge(object): | |
272 | def prepare_for_success(self, vcsbackend): |
|
273 | def prepare_for_success(self, vcsbackend): | |
273 | self.target_repo = vcsbackend.create_repo(number_of_commits=1) |
|
274 | self.target_repo = vcsbackend.create_repo(number_of_commits=1) | |
274 | self.source_repo = vcsbackend.clone_repo(self.target_repo) |
|
275 | self.source_repo = vcsbackend.clone_repo(self.target_repo) | |
@@ -287,7 +288,8 b' class TestRepositoryMerge:' | |||||
287 | 'branch', default_branch, self.target_commit.raw_id) |
|
288 | 'branch', default_branch, self.target_commit.raw_id) | |
288 | self.source_ref = Reference( |
|
289 | self.source_ref = Reference( | |
289 | 'branch', default_branch, self.source_commit.raw_id) |
|
290 | 'branch', default_branch, self.source_commit.raw_id) | |
290 | self.workspace = 'test-merge' |
|
291 | self.workspace_id = 'test-merge' | |
|
292 | self.repo_id = repo_id_generator(self.target_repo.path) | |||
291 |
|
293 | |||
292 | def prepare_for_conflict(self, vcsbackend): |
|
294 | def prepare_for_conflict(self, vcsbackend): | |
293 | self.target_repo = vcsbackend.create_repo(number_of_commits=1) |
|
295 | self.target_repo = vcsbackend.create_repo(number_of_commits=1) | |
@@ -302,13 +304,15 b' class TestRepositoryMerge:' | |||||
302 | 'branch', default_branch, self.target_commit.raw_id) |
|
304 | 'branch', default_branch, self.target_commit.raw_id) | |
303 | self.source_ref = Reference( |
|
305 | self.source_ref = Reference( | |
304 | 'branch', default_branch, self.source_commit.raw_id) |
|
306 | 'branch', default_branch, self.source_commit.raw_id) | |
305 | self.workspace = 'test-merge' |
|
307 | self.workspace_id = 'test-merge' | |
|
308 | self.repo_id = repo_id_generator(self.target_repo.path) | |||
306 |
|
309 | |||
307 | def test_merge_success(self, vcsbackend): |
|
310 | def test_merge_success(self, vcsbackend): | |
308 | self.prepare_for_success(vcsbackend) |
|
311 | self.prepare_for_success(vcsbackend) | |
309 |
|
312 | |||
310 | merge_response = self.target_repo.merge( |
|
313 | merge_response = self.target_repo.merge( | |
311 | self.target_ref, self.source_repo, self.source_ref, self.workspace, |
|
314 | self.repo_id, self.workspace_id, self.target_ref, self.source_repo, | |
|
315 | self.source_ref, | |||
312 | 'test user', 'test@rhodecode.com', 'merge message 1', |
|
316 | 'test user', 'test@rhodecode.com', 'merge message 1', | |
313 | dry_run=False) |
|
317 | dry_run=False) | |
314 | expected_merge_response = MergeResponse( |
|
318 | expected_merge_response = MergeResponse( | |
@@ -334,7 +338,7 b' class TestRepositoryMerge:' | |||||
334 | merge_response.merge_ref.commit_id) |
|
338 | merge_response.merge_ref.commit_id) | |
335 |
|
339 | |||
336 | merge_response = target_repo.merge( |
|
340 | merge_response = target_repo.merge( | |
337 |
target_ref, self.source_repo, self.source_ref, |
|
341 | self.repo_id, self.workspace_id, target_ref, self.source_repo, self.source_ref, | |
338 | 'test user', 'test@rhodecode.com', 'merge message 2', |
|
342 | 'test user', 'test@rhodecode.com', 'merge message 2', | |
339 | dry_run=False) |
|
343 | dry_run=False) | |
340 | expected_merge_response = MergeResponse( |
|
344 | expected_merge_response = MergeResponse( | |
@@ -353,13 +357,13 b' class TestRepositoryMerge:' | |||||
353 | self.prepare_for_success(vcsbackend) |
|
357 | self.prepare_for_success(vcsbackend) | |
354 |
|
358 | |||
355 | merge_response = self.target_repo.merge( |
|
359 | merge_response = self.target_repo.merge( | |
356 | self.target_ref, self.source_repo, self.source_ref, self.workspace, |
|
360 | self.repo_id, self.workspace_id, self.target_ref, self.source_repo, | |
357 | dry_run=True) |
|
361 | self.source_ref, dry_run=True) | |
358 |
|
362 | |||
359 | # We call it twice so to make sure we can handle updates |
|
363 | # We call it twice so to make sure we can handle updates | |
360 | merge_response_update = self.target_repo.merge( |
|
364 | merge_response_update = self.target_repo.merge( | |
361 | self.target_ref, self.source_repo, self.source_ref, self.workspace, |
|
365 | self.repo_id, self.workspace_id, self.target_ref, self.source_repo, | |
362 | dry_run=True) |
|
366 | self.source_ref, dry_run=True) | |
363 |
|
367 | |||
364 | # Multiple merges may differ in their commit id. Therefore we set the |
|
368 | # Multiple merges may differ in their commit id. Therefore we set the | |
365 | # commit id to `None` before comparing the merge responses. |
|
369 | # commit id to `None` before comparing the merge responses. | |
@@ -381,13 +385,15 b' class TestRepositoryMerge:' | |||||
381 | False, False, None, MergeFailureReason.MERGE_FAILED) |
|
385 | False, False, None, MergeFailureReason.MERGE_FAILED) | |
382 |
|
386 | |||
383 | merge_response = self.target_repo.merge( |
|
387 | merge_response = self.target_repo.merge( | |
384 | self.target_ref, self.source_repo, self.source_ref, self.workspace, |
|
388 | self.repo_id, self.workspace_id, self.target_ref, | |
|
389 | self.source_repo, self.source_ref, | |||
385 | 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run) |
|
390 | 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run) | |
386 | assert merge_response == expected_merge_response |
|
391 | assert merge_response == expected_merge_response | |
387 |
|
392 | |||
388 | # We call it twice so to make sure we can handle updates |
|
393 | # We call it twice so to make sure we can handle updates | |
389 | merge_response = self.target_repo.merge( |
|
394 | merge_response = self.target_repo.merge( | |
390 | self.target_ref, self.source_repo, self.source_ref, self.workspace, |
|
395 | self.repo_id, self.workspace_id, self.target_ref, self.source_repo, | |
|
396 | self.source_ref, | |||
391 | 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run) |
|
397 | 'test_user', 'test@rhodecode.com', 'test message', dry_run=dry_run) | |
392 | assert merge_response == expected_merge_response |
|
398 | assert merge_response == expected_merge_response | |
393 |
|
399 | |||
@@ -400,8 +406,8 b' class TestRepositoryMerge:' | |||||
400 | self.target_ref.type, self.target_ref.name, '0' * 40) |
|
406 | self.target_ref.type, self.target_ref.name, '0' * 40) | |
401 |
|
407 | |||
402 | merge_response = self.target_repo.merge( |
|
408 | merge_response = self.target_repo.merge( | |
403 | target_ref, self.source_repo, self.source_ref, self.workspace, |
|
409 | self.repo_id, self.workspace_id, target_ref, self.source_repo, | |
404 | dry_run=True) |
|
410 | self.source_ref, dry_run=True) | |
405 |
|
411 | |||
406 | assert merge_response == expected_merge_response |
|
412 | assert merge_response == expected_merge_response | |
407 |
|
413 | |||
@@ -414,7 +420,8 b' class TestRepositoryMerge:' | |||||
414 | self.source_ref.type, 'not_existing', self.source_ref.commit_id) |
|
420 | self.source_ref.type, 'not_existing', self.source_ref.commit_id) | |
415 |
|
421 | |||
416 | merge_response = self.target_repo.merge( |
|
422 | merge_response = self.target_repo.merge( | |
417 | self.target_ref, self.source_repo, source_ref, self.workspace, |
|
423 | self.repo_id, self.workspace_id, self.target_ref, | |
|
424 | self.source_repo, source_ref, | |||
418 | dry_run=True) |
|
425 | dry_run=True) | |
419 |
|
426 | |||
420 | assert merge_response == expected_merge_response |
|
427 | assert merge_response == expected_merge_response | |
@@ -427,29 +434,38 b' class TestRepositoryMerge:' | |||||
427 | with mock.patch.object(self.target_repo, '_merge_repo', |
|
434 | with mock.patch.object(self.target_repo, '_merge_repo', | |
428 | side_effect=RepositoryError()): |
|
435 | side_effect=RepositoryError()): | |
429 | merge_response = self.target_repo.merge( |
|
436 | merge_response = self.target_repo.merge( | |
430 | self.target_ref, self.source_repo, self.source_ref, |
|
437 | self.repo_id, self.workspace_id, self.target_ref, | |
431 |
self. |
|
438 | self.source_repo, self.source_ref, | |
|
439 | dry_run=True) | |||
432 |
|
440 | |||
433 | assert merge_response == expected_merge_response |
|
441 | assert merge_response == expected_merge_response | |
434 |
|
442 | |||
435 | def test_merge_invalid_user_name(self, vcsbackend): |
|
443 | def test_merge_invalid_user_name(self, vcsbackend): | |
436 | repo = vcsbackend.create_repo(number_of_commits=1) |
|
444 | repo = vcsbackend.create_repo(number_of_commits=1) | |
437 | ref = Reference('branch', 'master', 'not_used') |
|
445 | ref = Reference('branch', 'master', 'not_used') | |
|
446 | workspace_id = 'test-errors-in-merge' | |||
|
447 | repo_id = repo_id_generator(workspace_id) | |||
438 | with pytest.raises(ValueError): |
|
448 | with pytest.raises(ValueError): | |
439 |
repo.merge(ref, self, ref |
|
449 | repo.merge(repo_id, workspace_id, ref, self, ref) | |
440 |
|
450 | |||
441 | def test_merge_invalid_user_email(self, vcsbackend): |
|
451 | def test_merge_invalid_user_email(self, vcsbackend): | |
442 | repo = vcsbackend.create_repo(number_of_commits=1) |
|
452 | repo = vcsbackend.create_repo(number_of_commits=1) | |
443 | ref = Reference('branch', 'master', 'not_used') |
|
453 | ref = Reference('branch', 'master', 'not_used') | |
|
454 | workspace_id = 'test-errors-in-merge' | |||
|
455 | repo_id = repo_id_generator(workspace_id) | |||
444 | with pytest.raises(ValueError): |
|
456 | with pytest.raises(ValueError): | |
445 | repo.merge(ref, self, ref, 'workspace_id', 'user name') |
|
457 | repo.merge( | |
|
458 | repo_id, workspace_id, ref, self, ref, 'user name') | |||
446 |
|
459 | |||
447 | def test_merge_invalid_message(self, vcsbackend): |
|
460 | def test_merge_invalid_message(self, vcsbackend): | |
448 | repo = vcsbackend.create_repo(number_of_commits=1) |
|
461 | repo = vcsbackend.create_repo(number_of_commits=1) | |
449 | ref = Reference('branch', 'master', 'not_used') |
|
462 | ref = Reference('branch', 'master', 'not_used') | |
|
463 | workspace_id = 'test-errors-in-merge' | |||
|
464 | repo_id = repo_id_generator(workspace_id) | |||
450 | with pytest.raises(ValueError): |
|
465 | with pytest.raises(ValueError): | |
451 | repo.merge( |
|
466 | repo.merge( | |
452 | ref, self, ref, 'workspace_id', 'user name', 'user@email.com') |
|
467 | repo_id, workspace_id, ref, self, ref, | |
|
468 | 'user name', 'user@email.com') | |||
453 |
|
469 | |||
454 |
|
470 | |||
455 | @pytest.mark.usefixtures("vcs_repository_support") |
|
471 | @pytest.mark.usefixtures("vcs_repository_support") | |
@@ -505,7 +521,7 b' class TestRepositoryStrip(BackendTestMix' | |||||
505 |
|
521 | |||
506 |
|
522 | |||
507 | @pytest.mark.backends('hg', 'git') |
|
523 | @pytest.mark.backends('hg', 'git') | |
508 | class TestRepositoryPull: |
|
524 | class TestRepositoryPull(object): | |
509 |
|
525 | |||
510 | def test_pull(self, vcsbackend): |
|
526 | def test_pull(self, vcsbackend): | |
511 | source_repo = vcsbackend.repo |
|
527 | source_repo = vcsbackend.repo |
General Comments 0
You need to be logged in to leave comments.
Login now