Show More
@@ -533,6 +533,7 b' get_repo_settings' | |||
|
533 | 533 | "hooks_outgoing_pull_logger": true, |
|
534 | 534 | "phases_publish": "True", |
|
535 | 535 | "rhodecode_hg_use_rebase_for_merging": true, |
|
536 | "rhodecode_hg_close_branch_before_merging": false, | |
|
536 | 537 | "rhodecode_pr_merge_enabled": true, |
|
537 | 538 | "rhodecode_use_outdated_comments": true |
|
538 | 539 | } |
@@ -420,7 +420,7 b' class BaseRepository(object):' | |||
|
420 | 420 | |
|
421 | 421 | def merge(self, target_ref, source_repo, source_ref, workspace_id, |
|
422 | 422 | user_name='', user_email='', message='', dry_run=False, |
|
423 | use_rebase=False): | |
|
423 | use_rebase=False, close_branch=False): | |
|
424 | 424 | """ |
|
425 | 425 | Merge the revisions specified in `source_ref` from `source_repo` |
|
426 | 426 | onto the `target_ref` of this repository. |
@@ -445,6 +445,7 b' class BaseRepository(object):' | |||
|
445 | 445 | :param dry_run: If `True` the merge will not take place. |
|
446 | 446 | :param use_rebase: If `True` commits from the source will be rebased |
|
447 | 447 | on top of the target instead of being merged. |
|
448 | :param close_branch: If `True` branch will be close before merging it | |
|
448 | 449 | """ |
|
449 | 450 | if dry_run: |
|
450 | 451 | message = message or 'dry_run_merge_message' |
@@ -465,7 +466,7 b' class BaseRepository(object):' | |||
|
465 | 466 | return self._merge_repo( |
|
466 | 467 | shadow_repository_path, target_ref, source_repo, |
|
467 | 468 | source_ref, message, user_name, user_email, dry_run=dry_run, |
|
468 | use_rebase=use_rebase) | |
|
469 | use_rebase=use_rebase, close_branch=close_branch) | |
|
469 | 470 | except RepositoryError: |
|
470 | 471 | log.exception( |
|
471 | 472 | 'Unexpected failure when running merge, dry-run=%s', |
@@ -475,7 +476,8 b' class BaseRepository(object):' | |||
|
475 | 476 | |
|
476 | 477 | def _merge_repo(self, shadow_repository_path, target_ref, |
|
477 | 478 | source_repo, source_ref, merge_message, |
|
478 |
merger_name, merger_email, dry_run=False, |
|
|
479 | merger_name, merger_email, dry_run=False, | |
|
480 | use_rebase=False, close_branch=False): | |
|
479 | 481 | """Internal implementation of merge.""" |
|
480 | 482 | raise NotImplementedError |
|
481 | 483 |
@@ -849,7 +849,7 b' class GitRepository(BaseRepository):' | |||
|
849 | 849 | def _merge_repo(self, shadow_repository_path, target_ref, |
|
850 | 850 | source_repo, source_ref, merge_message, |
|
851 | 851 | merger_name, merger_email, dry_run=False, |
|
852 | use_rebase=False): | |
|
852 | use_rebase=False, close_branch=False): | |
|
853 | 853 | if target_ref.commit_id != self.branches[target_ref.name]: |
|
854 | 854 | return MergeResponse( |
|
855 | 855 | False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD) |
@@ -646,6 +646,28 b' class MercurialRepository(BaseRepository' | |||
|
646 | 646 | self._remote.update(clean=True) |
|
647 | 647 | raise |
|
648 | 648 | |
|
649 | def _local_close(self, target_ref, user_name, user_email, | |
|
650 | source_ref, close_message=''): | |
|
651 | """ | |
|
652 | Close the branch of the given source_revision | |
|
653 | ||
|
654 | Returns the commit id of the close and a boolean indicating if the | |
|
655 | commit needs to be pushed. | |
|
656 | """ | |
|
657 | self._update(target_ref.commit_id) | |
|
658 | message = close_message or "Closing branch" | |
|
659 | try: | |
|
660 | self._remote.commit( | |
|
661 | message=safe_str(message), | |
|
662 | username=safe_str('%s <%s>' % (user_name, user_email)), | |
|
663 | close_branch=True) | |
|
664 | self._remote.invalidate_vcs_cache() | |
|
665 | return self._identify(), True | |
|
666 | except RepositoryError: | |
|
667 | # Cleanup any commit leftovers | |
|
668 | self._remote.update(clean=True) | |
|
669 | raise | |
|
670 | ||
|
649 | 671 | def _is_the_same_branch(self, target_ref, source_ref): |
|
650 | 672 | return ( |
|
651 | 673 | self._get_branch_name(target_ref) == |
@@ -679,7 +701,7 b' class MercurialRepository(BaseRepository' | |||
|
679 | 701 | def _merge_repo(self, shadow_repository_path, target_ref, |
|
680 | 702 | source_repo, source_ref, merge_message, |
|
681 | 703 | merger_name, merger_email, dry_run=False, |
|
682 | use_rebase=False): | |
|
704 | use_rebase=False, close_branch=False): | |
|
683 | 705 | if target_ref.commit_id not in self._heads(): |
|
684 | 706 | return MergeResponse( |
|
685 | 707 | False, False, None, MergeFailureReason.TARGET_IS_NOT_HEAD) |
@@ -712,26 +734,40 b' class MercurialRepository(BaseRepository' | |||
|
712 | 734 | merge_ref = None |
|
713 | 735 | merge_failure_reason = MergeFailureReason.NONE |
|
714 | 736 | |
|
715 | try: | |
|
716 | merge_commit_id, needs_push = shadow_repo._local_merge( | |
|
717 | target_ref, merge_message, merger_name, merger_email, | |
|
718 | source_ref, use_rebase=use_rebase) | |
|
737 | if close_branch and not use_rebase: | |
|
738 | try: | |
|
739 | close_commit_id, needs_push = shadow_repo._local_close( | |
|
740 | target_ref, merger_name, merger_email, source_ref) | |
|
741 | target_ref.commit_id = close_commit_id | |
|
742 | merge_possible = True | |
|
743 | except RepositoryError: | |
|
744 | log.exception('Failure when doing close branch on hg shadow repo') | |
|
745 | merge_possible = False | |
|
746 | merge_failure_reason = MergeFailureReason.MERGE_FAILED | |
|
747 | else: | |
|
719 | 748 | merge_possible = True |
|
720 | 749 | |
|
721 | # Set a bookmark pointing to the merge commit. This bookmark may be | |
|
722 | # used to easily identify the last successful merge commit in the | |
|
723 | # shadow repository. | |
|
724 | shadow_repo.bookmark('pr-merge', revision=merge_commit_id) | |
|
725 | merge_ref = Reference('book', 'pr-merge', merge_commit_id) | |
|
726 | except SubrepoMergeError: | |
|
727 | log.exception( | |
|
728 | 'Subrepo merge error during local merge on hg shadow repo.') | |
|
729 | merge_possible = False | |
|
730 | merge_failure_reason = MergeFailureReason.SUBREPO_MERGE_FAILED | |
|
731 | except RepositoryError: | |
|
732 | log.exception('Failure when doing local merge on hg shadow repo') | |
|
733 | merge_possible = False | |
|
734 | merge_failure_reason = MergeFailureReason.MERGE_FAILED | |
|
750 | if merge_possible: | |
|
751 | try: | |
|
752 | merge_commit_id, needs_push = shadow_repo._local_merge( | |
|
753 | target_ref, merge_message, merger_name, merger_email, | |
|
754 | source_ref, use_rebase=use_rebase) | |
|
755 | merge_possible = True | |
|
756 | ||
|
757 | # Set a bookmark pointing to the merge commit. This bookmark may be | |
|
758 | # used to easily identify the last successful merge commit in the | |
|
759 | # shadow repository. | |
|
760 | shadow_repo.bookmark('pr-merge', revision=merge_commit_id) | |
|
761 | merge_ref = Reference('book', 'pr-merge', merge_commit_id) | |
|
762 | except SubrepoMergeError: | |
|
763 | log.exception( | |
|
764 | 'Subrepo merge error during local merge on hg shadow repo.') | |
|
765 | merge_possible = False | |
|
766 | merge_failure_reason = MergeFailureReason.SUBREPO_MERGE_FAILED | |
|
767 | except RepositoryError: | |
|
768 | log.exception('Failure when doing local merge on hg shadow repo') | |
|
769 | merge_possible = False | |
|
770 | merge_failure_reason = MergeFailureReason.MERGE_FAILED | |
|
735 | 771 | |
|
736 | 772 | if merge_possible and not dry_run: |
|
737 | 773 | if needs_push: |
@@ -388,7 +388,9 b' class _BaseVcsSettingsForm(formencode.Sc' | |||
|
388 | 388 | extensions_largefiles = v.StringBoolean(if_missing=False) |
|
389 | 389 | extensions_evolve = v.StringBoolean(if_missing=False) |
|
390 | 390 | phases_publish = v.StringBoolean(if_missing=False) |
|
391 | ||
|
391 | 392 | rhodecode_hg_use_rebase_for_merging = v.StringBoolean(if_missing=False) |
|
393 | rhodecode_hg_close_branch_before_merging = v.StringBoolean(if_missing=False) | |
|
392 | 394 | |
|
393 | 395 | # git |
|
394 | 396 | vcs_git_lfs_enabled = v.StringBoolean(if_missing=False) |
@@ -552,6 +552,7 b' class PullRequestModel(BaseModel):' | |||
|
552 | 552 | |
|
553 | 553 | workspace_id = self._workspace_id(pull_request) |
|
554 | 554 | use_rebase = self._use_rebase_for_merging(pull_request) |
|
555 | close_branch = self._close_branch_before_merging(pull_request) | |
|
555 | 556 | |
|
556 | 557 | callback_daemon, extras = prepare_callback_daemon( |
|
557 | 558 | extras, protocol=vcs_settings.HOOKS_PROTOCOL, |
@@ -565,7 +566,8 b' class PullRequestModel(BaseModel):' | |||
|
565 | 566 | merge_state = target_vcs.merge( |
|
566 | 567 | target_ref, source_vcs, pull_request.source_ref_parts, |
|
567 | 568 | workspace_id, user_name=user.username, |
|
568 |
user_email=user.email, message=message, use_rebase=use_rebase |
|
|
569 | user_email=user.email, message=message, use_rebase=use_rebase, | |
|
570 | close_branch=close_branch) | |
|
569 | 571 | return merge_state |
|
570 | 572 | |
|
571 | 573 | def _comment_and_close_pr(self, pull_request, user, merge_state): |
@@ -1249,9 +1251,11 b' class PullRequestModel(BaseModel):' | |||
|
1249 | 1251 | workspace_id = self._workspace_id(pull_request) |
|
1250 | 1252 | source_vcs = pull_request.source_repo.scm_instance() |
|
1251 | 1253 | use_rebase = self._use_rebase_for_merging(pull_request) |
|
1254 | close_branch = self._close_branch_before_merging(pull_request) | |
|
1252 | 1255 | merge_state = target_vcs.merge( |
|
1253 | 1256 | target_reference, source_vcs, pull_request.source_ref_parts, |
|
1254 |
workspace_id, dry_run=True, use_rebase=use_rebase |
|
|
1257 | workspace_id, dry_run=True, use_rebase=use_rebase, | |
|
1258 | close_branch=close_branch) | |
|
1255 | 1259 | |
|
1256 | 1260 | # Do not store the response if there was an unknown error. |
|
1257 | 1261 | if merge_state.failure_reason != MergeFailureReason.UNKNOWN: |
@@ -1416,14 +1420,21 b' class PullRequestModel(BaseModel):' | |||
|
1416 | 1420 | return vcs_diff |
|
1417 | 1421 | |
|
1418 | 1422 | def _is_merge_enabled(self, pull_request): |
|
1423 | return self._get_general_setting( | |
|
1424 | pull_request, 'rhodecode_pr_merge_enabled') | |
|
1425 | ||
|
1426 | def _use_rebase_for_merging(self, pull_request): | |
|
1427 | return self._get_general_setting( | |
|
1428 | pull_request, 'rhodecode_hg_use_rebase_for_merging') | |
|
1429 | ||
|
1430 | def _close_branch_before_merging(self, pull_request): | |
|
1431 | return self._get_general_setting( | |
|
1432 | pull_request, 'rhodecode_hg_close_branch_before_merging') | |
|
1433 | ||
|
1434 | def _get_general_setting(self, pull_request, settings_key, default=False): | |
|
1419 | 1435 | settings_model = VcsSettingsModel(repo=pull_request.target_repo) |
|
1420 | 1436 | settings = settings_model.get_general_settings() |
|
1421 | return settings.get('rhodecode_pr_merge_enabled', False) | |
|
1422 | ||
|
1423 | def _use_rebase_for_merging(self, pull_request): | |
|
1424 | settings_model = VcsSettingsModel(repo=pull_request.target_repo) | |
|
1425 | settings = settings_model.get_general_settings() | |
|
1426 | return settings.get('rhodecode_hg_use_rebase_for_merging', False) | |
|
1437 | return settings.get(settings_key, default) | |
|
1427 | 1438 | |
|
1428 | 1439 | def _log_audit_action(self, action, action_data, user, pull_request): |
|
1429 | 1440 | audit_logger.store( |
@@ -408,7 +408,8 b' class VcsSettingsModel(object):' | |||
|
408 | 408 | GENERAL_SETTINGS = ( |
|
409 | 409 | 'use_outdated_comments', |
|
410 | 410 | 'pr_merge_enabled', |
|
411 |
'hg_use_rebase_for_merging' |
|
|
411 | 'hg_use_rebase_for_merging', | |
|
412 | 'hg_close_branch_before_merging') | |
|
412 | 413 | |
|
413 | 414 | HOOKS_SETTINGS = ( |
|
414 | 415 | ('hooks', 'changegroup.repo_size'), |
@@ -161,6 +161,14 b'' | |||
|
161 | 161 | <span class="help-block">${_('Use rebase instead of creating a merge commit when merging via web interface.')}</span> |
|
162 | 162 | </div> |
|
163 | 163 | |
|
164 | <div class="checkbox"> | |
|
165 | ${h.checkbox('rhodecode_hg_close_branch_before_merging' + suffix, 'True', **kwargs)} | |
|
166 | <label for="rhodecode_hg_close_branch_before_merging{suffix}">${_('Close branch before merging it')}</label> | |
|
167 | </div> | |
|
168 | <div class="label"> | |
|
169 | <span class="help-block">${_('Close branch before merging it into destination branch. No effect when rebase strategy is use.')}</span> | |
|
170 | </div> | |
|
171 | ||
|
164 | 172 | </div> |
|
165 | 173 | </div> |
|
166 | 174 | % endif |
General Comments 0
You need to be logged in to leave comments.
Login now