diff --git a/rhodecode/apps/repository/views/repo_pull_requests.py b/rhodecode/apps/repository/views/repo_pull_requests.py --- a/rhodecode/apps/repository/views/repo_pull_requests.py +++ b/rhodecode/apps/repository/views/repo_pull_requests.py @@ -400,6 +400,8 @@ class RepoPullRequestsView(RepoAppView, c.pr_merge_errors = _merge_check.error_details c.pr_merge_possible = not _merge_check.failed c.pr_merge_message = _merge_check.merge_msg + c.pr_merge_source_commit = _merge_check.source_commit + c.pr_merge_target_commit = _merge_check.target_commit c.pr_merge_info = MergeCheck.get_merge_conditions( pull_request_latest, translator=self.request.translate) diff --git a/rhodecode/lib/vcs/backends/base.py b/rhodecode/lib/vcs/backends/base.py --- a/rhodecode/lib/vcs/backends/base.py +++ b/rhodecode/lib/vcs/backends/base.py @@ -231,6 +231,14 @@ class MergeResponse(object): return data +class TargetRefMissing(ValueError): + pass + + +class SourceRefMissing(ValueError): + pass + + class BaseRepository(object): """ Base Repository for final backends diff --git a/rhodecode/model/pull_request.py b/rhodecode/model/pull_request.py --- a/rhodecode/model/pull_request.py +++ b/rhodecode/model/pull_request.py @@ -35,7 +35,6 @@ import collections from pyramid import compat from pyramid.threadlocal import get_current_request -from rhodecode import events from rhodecode.translation import lazy_ugettext from rhodecode.lib import helpers as h, hooks_utils, diffs from rhodecode.lib import audit_logger @@ -43,9 +42,10 @@ from rhodecode.lib.compat import Ordered from rhodecode.lib.hooks_daemon import prepare_callback_daemon from rhodecode.lib.markup_renderer import ( DEFAULT_COMMENTS_RENDERER, RstTemplateRenderer) -from rhodecode.lib.utils2 import safe_unicode, safe_str, md5_safe +from rhodecode.lib.utils2 import safe_unicode, safe_str, md5_safe, AttributeDict, safe_int from rhodecode.lib.vcs.backends.base import ( - Reference, MergeResponse, MergeFailureReason, UpdateFailureReason) + Reference, MergeResponse, MergeFailureReason, UpdateFailureReason, + TargetRefMissing, SourceRefMissing) from rhodecode.lib.vcs.conf import settings as vcs_settings from rhodecode.lib.vcs.exceptions import ( CommitDoesNotExistError, EmptyRepositoryError) @@ -681,6 +681,38 @@ class PullRequestModel(BaseModel): source_ref_type = pull_request.source_ref_parts.type return source_ref_type in self.REF_TYPES + def get_flow_commits(self, pull_request): + + # source repo + source_ref_name = pull_request.source_ref_parts.name + source_ref_type = pull_request.source_ref_parts.type + source_ref_id = pull_request.source_ref_parts.commit_id + source_repo = pull_request.source_repo.scm_instance() + + try: + if source_ref_type in self.REF_TYPES: + source_commit = source_repo.get_commit(source_ref_name) + else: + source_commit = source_repo.get_commit(source_ref_id) + except CommitDoesNotExistError: + raise SourceRefMissing() + + # target repo + target_ref_name = pull_request.target_ref_parts.name + target_ref_type = pull_request.target_ref_parts.type + target_ref_id = pull_request.target_ref_parts.commit_id + target_repo = pull_request.target_repo.scm_instance() + + try: + if target_ref_type in self.REF_TYPES: + target_commit = target_repo.get_commit(target_ref_name) + else: + target_commit = target_repo.get_commit(target_ref_id) + except CommitDoesNotExistError: + raise TargetRefMissing() + + return source_commit, target_commit + def update_commits(self, pull_request, updating_user): """ Get the updated list of commits for the pull request @@ -707,31 +739,22 @@ class PullRequestModel(BaseModel): old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, source_changed=False, target_changed=False) - # source repo - source_repo = pull_request.source_repo.scm_instance() - try: - source_commit = source_repo.get_commit(commit_id=source_ref_name) - except CommitDoesNotExistError: + source_commit, target_commit = self.get_flow_commits(pull_request) + except SourceRefMissing: return UpdateResponse( executed=False, reason=UpdateFailureReason.MISSING_SOURCE_REF, old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, source_changed=False, target_changed=False) - - source_changed = source_ref_id != source_commit.raw_id - - # target repo - target_repo = pull_request.target_repo.scm_instance() - - try: - target_commit = target_repo.get_commit(commit_id=target_ref_name) - except CommitDoesNotExistError: + except TargetRefMissing: return UpdateResponse( executed=False, reason=UpdateFailureReason.MISSING_TARGET_REF, old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, source_changed=False, target_changed=False) + + source_changed = source_ref_id != source_commit.raw_id target_changed = target_ref_id != target_commit.raw_id if not (source_changed or target_changed): @@ -761,17 +784,8 @@ class PullRequestModel(BaseModel): ver.pull_request_version_id if ver else None pull_request_version = pull_request - try: - if target_ref_type in self.REF_TYPES: - target_commit = target_repo.get_commit(target_ref_name) - else: - target_commit = target_repo.get_commit(target_ref_id) - except CommitDoesNotExistError: - return UpdateResponse( - executed=False, - reason=UpdateFailureReason.MISSING_TARGET_REF, - old=pull_request, new=None, common_ancestor_id=None, commit_changes=None, - source_changed=source_changed, target_changed=target_changed) + source_repo = pull_request.source_repo.scm_instance() + target_repo = pull_request.target_repo.scm_instance() # re-compute commit ids old_commit_ids = pull_request.revisions @@ -1736,6 +1750,8 @@ class MergeCheck(object): self.failed = None self.errors = [] self.error_details = OrderedDict() + self.source_commit = AttributeDict() + self.target_commit = AttributeDict() def __repr__(self): return ''.format( @@ -1766,8 +1782,7 @@ class MergeCheck(object): return merge_check # permissions to merge - user_allowed_to_merge = PullRequestModel().check_user_merge( - pull_request, auth_user) + user_allowed_to_merge = PullRequestModel().check_user_merge(pull_request, auth_user) if not user_allowed_to_merge: log.debug("MergeCheck: cannot merge, approval is pending.") @@ -1837,6 +1852,23 @@ class MergeCheck(object): merge_check.merge_msg = msg merge_check.merge_response = merge_response + source_ref_id = pull_request.source_ref_parts.commit_id + target_ref_id = pull_request.target_ref_parts.commit_id + + try: + source_commit, target_commit = PullRequestModel().get_flow_commits(pull_request) + merge_check.source_commit.changed = source_ref_id != source_commit.raw_id + merge_check.source_commit.ref_spec = pull_request.source_ref_parts + merge_check.source_commit.current_raw_id = source_commit.raw_id + merge_check.source_commit.previous_raw_id = source_ref_id + + merge_check.target_commit.changed = target_ref_id != target_commit.raw_id + merge_check.target_commit.ref_spec = pull_request.target_ref_parts + merge_check.target_commit.current_raw_id = target_commit.raw_id + merge_check.target_commit.previous_raw_id = target_ref_id + except (SourceRefMissing, TargetRefMissing): + pass + if not merge_status: log.debug("MergeCheck: cannot merge, pull request merge not possible.") merge_check.push_error('warning', msg, cls.MERGE_CHECK, None) diff --git a/rhodecode/templates/pullrequests/pullrequest_show.mako b/rhodecode/templates/pullrequests/pullrequest_show.mako --- a/rhodecode/templates/pullrequests/pullrequest_show.mako +++ b/rhodecode/templates/pullrequests/pullrequest_show.mako @@ -471,6 +471,16 @@ + % elif c.pr_merge_source_commit.changed: +
+
+
+ % if c.pr_merge_source_commit.changed: + ${_('There are new changes for {}:{} in source repository, please consider updating this pull request.').format(c.pr_merge_source_commit.ref_spec.type, c.pr_merge_source_commit.ref_spec.name)} + % endif +
+
+
% endif