示例#1
0
    def post(self, repo_name, pull_request_id):
        pull_request = PullRequest.get_or_404(pull_request_id)
        if pull_request.is_closed():
            raise HTTPForbidden()
        assert pull_request.other_repo.repo_name == repo_name
        #only owner or admin can update it
        owner = pull_request.author.user_id == c.authuser.user_id
        repo_admin = h.HasRepoPermissionAny('repository.admin')(c.repo_name)
        if not (h.HasPermissionAny('hg.admin') or repo_admin or owner):
            raise HTTPForbidden()

        _form = PullRequestPostForm()().to_python(request.POST)
        reviewers_ids = [int(s) for s in _form['review_members']]

        if _form['updaterev']:
            return self.create_update(pull_request, _form['updaterev'],
                                      _form['pullrequest_title'],
                                      _form['pullrequest_desc'], reviewers_ids)

        old_description = pull_request.description
        pull_request.title = _form['pullrequest_title']
        pull_request.description = _form['pullrequest_desc'].strip() or _(
            'No description')
        PullRequestModel().mention_from_description(pull_request,
                                                    old_description)

        PullRequestModel().update_reviewers(pull_request_id, reviewers_ids)

        Session().commit()
        h.flash(_('Pull request updated'), category='success')

        return redirect(pull_request.url())
示例#2
0
    def post(self, repo_name, pull_request_id):
        pull_request = PullRequest.get_or_404(pull_request_id)
        if pull_request.is_closed():
            raise HTTPForbidden()
        assert pull_request.other_repo.repo_name == repo_name
        # only owner or admin can update it
        owner = pull_request.owner_id == request.authuser.user_id
        repo_admin = h.HasRepoPermissionLevel('admin')(c.repo_name)
        if not (h.HasPermissionAny('hg.admin')() or repo_admin or owner):
            raise HTTPForbidden()

        _form = PullRequestPostForm()().to_python(request.POST)

        cur_reviewers = set(pull_request.get_reviewer_users())
        new_reviewers = set(_get_reviewer(s) for s in _form['review_members'])
        old_reviewers = set(
            _get_reviewer(s) for s in _form['org_review_members'])

        other_added = cur_reviewers - old_reviewers
        other_removed = old_reviewers - cur_reviewers

        if other_added:
            h.flash(
                _('Meanwhile, the following reviewers have been added: %s') %
                (', '.join(u.username for u in other_added)),
                category='warning')
        if other_removed:
            h.flash(
                _('Meanwhile, the following reviewers have been removed: %s') %
                (', '.join(u.username for u in other_removed)),
                category='warning')

        if _form['updaterev']:
            return self.create_new_iteration(pull_request, _form['updaterev'],
                                             _form['pullrequest_title'],
                                             _form['pullrequest_desc'],
                                             new_reviewers)

        added_reviewers = new_reviewers - old_reviewers - cur_reviewers
        removed_reviewers = (old_reviewers - new_reviewers) & cur_reviewers

        old_description = pull_request.description
        pull_request.title = _form['pullrequest_title']
        pull_request.description = _form['pullrequest_desc'].strip() or _(
            'No description')
        pull_request.owner = User.get_by_username(_form['owner'])
        user = User.get(request.authuser.user_id)

        PullRequestModel().mention_from_description(user, pull_request,
                                                    old_description)
        PullRequestModel().add_reviewers(user, pull_request, added_reviewers)
        PullRequestModel().remove_reviewers(user, pull_request,
                                            removed_reviewers)

        Session().commit()
        h.flash(_('Pull request updated'), category='success')

        raise HTTPFound(location=pull_request.url())
示例#3
0
 def delete(self, repo_name, pull_request_id):
     pull_request = PullRequest.get_or_404(pull_request_id)
     # only owner can delete it !
     if pull_request.owner_id == request.authuser.user_id:
         PullRequestModel().delete(pull_request)
         Session().commit()
         h.flash(_('Successfully deleted pull request'), category='success')
         raise HTTPFound(location=url('my_pullrequests'))
     raise HTTPForbidden()
示例#4
0
    def show_all(self, repo_name):
        c.from_ = request.GET.get('from_') or ''
        c.closed = request.GET.get('closed') or ''
        c.pull_requests = PullRequestModel().get_all(repo_name,
                                                     from_=c.from_,
                                                     closed=c.closed)
        c.repo_name = repo_name
        p = safe_int(request.GET.get('page', 1), 1)

        c.pullrequests_pager = Page(c.pull_requests, page=p, items_per_page=10)

        if request.environ.get('HTTP_X_PARTIAL_XHR'):
            return render('/pullrequests/pullrequest_data.html')

        return render('/pullrequests/pullrequest_show_all.html')
示例#5
0
def create_cs_pr_comment(repo_name,
                         revision=None,
                         pull_request=None,
                         allowed_to_change_status=True):
    """
    Add a comment to the specified changeset or pull request, using POST values
    from the request.

    Comments can be inline (when a file path and line number is specified in
    POST) or general comments.
    A comment can be accompanied by a review status change (accepted, rejected,
    etc.). Pull requests can be closed or deleted.

    Parameter 'allowed_to_change_status' is used for both status changes and
    closing of pull requests. For deleting of pull requests, more specific
    checks are done.
    """

    assert request.environ.get('HTTP_X_PARTIAL_XHR')
    if pull_request:
        pull_request_id = pull_request.pull_request_id
    else:
        pull_request_id = None

    status = request.POST.get('changeset_status')
    close_pr = request.POST.get('save_close')
    delete = request.POST.get('save_delete')
    f_path = request.POST.get('f_path')
    line_no = request.POST.get('line')

    if (status or close_pr or delete) and (f_path or line_no):
        # status votes and closing is only possible in general comments
        raise HTTPBadRequest()

    if not allowed_to_change_status:
        if status or close_pr:
            h.flash(_('No permission to change status'), 'error')
            raise HTTPForbidden()

    if pull_request and delete == "delete":
        if (pull_request.owner_id == request.authuser.user_id
                or h.HasPermissionAny('hg.admin')()
                or h.HasRepoPermissionLevel('admin')(
                    pull_request.org_repo.repo_name)
                or h.HasRepoPermissionLevel('admin')(
                    pull_request.other_repo.repo_name)
            ) and not pull_request.is_closed():
            PullRequestModel().delete(pull_request)
            Session().commit()
            h.flash(_('Successfully deleted pull request %s') %
                    pull_request_id,
                    category='success')
            return {
                'location': h.url('my_pullrequests'),  # or repo pr list?
            }
        raise HTTPForbidden()

    text = request.POST.get('text', '').strip()

    comment = ChangesetCommentsModel().create(
        text=text,
        repo=c.db_repo.repo_id,
        author=request.authuser.user_id,
        revision=revision,
        pull_request=pull_request_id,
        f_path=f_path or None,
        line_no=line_no or None,
        status_change=ChangesetStatus.get_status_lbl(status)
        if status else None,
        closing_pr=close_pr,
    )

    if status:
        ChangesetStatusModel().set_status(
            c.db_repo.repo_id,
            status,
            request.authuser.user_id,
            comment,
            revision=revision,
            pull_request=pull_request_id,
        )

    if pull_request:
        action = 'user_commented_pull_request:%s' % pull_request_id
    else:
        action = 'user_commented_revision:%s' % revision
    action_logger(request.authuser, action, c.db_repo, request.ip_addr)

    if pull_request and close_pr:
        PullRequestModel().close_pull_request(pull_request_id)
        action_logger(request.authuser,
                      'user_closed_pull_request:%s' % pull_request_id,
                      c.db_repo, request.ip_addr)

    Session().commit()

    data = {
        'target_id': h.safeid(request.POST.get('f_path')),
    }
    if comment is not None:
        c.comment = comment
        data.update(comment.get_dict())
        data.update({
            'rendered_text':
            render('changeset/changeset_comment_block.html')
        })

    return data
示例#6
0
    def create_update(self, old_pull_request, updaterev, title, description, reviewers_ids):
        org_repo = RepoModel()._get_repo(old_pull_request.org_repo.repo_name)
        org_ref_type, org_ref_name, org_rev = old_pull_request.org_ref.split(':')
        new_org_rev = self._get_ref_rev(org_repo, 'rev', updaterev)

        other_repo = RepoModel()._get_repo(old_pull_request.other_repo.repo_name)
        other_ref_type, other_ref_name, other_rev = old_pull_request.other_ref.split(':') # other_rev is ancestor
        #assert other_ref_type == 'branch', other_ref_type # TODO: what if not?
        new_other_rev = self._get_ref_rev(other_repo, other_ref_type, other_ref_name)

        cs_ranges, _cs_ranges_not, ancestor_rev = CompareController._get_changesets(org_repo.scm_instance.alias,
            other_repo.scm_instance, new_other_rev, # org and other "swapped"
            org_repo.scm_instance, new_org_rev)

        old_revisions = set(old_pull_request.revisions)
        revisions = [cs.raw_id for cs in cs_ranges]
        new_revisions = [r for r in revisions if r not in old_revisions]
        lost = old_revisions.difference(revisions)

        infos = ['This is an update of %s "%s".' %
                 (h.canonical_url('pullrequest_show', repo_name=old_pull_request.other_repo.repo_name,
                      pull_request_id=old_pull_request.pull_request_id),
                  old_pull_request.title)]

        if lost:
            infos.append(_('Missing changesets since the previous pull request:'))
            for r in old_pull_request.revisions:
                if r in lost:
                    rev_desc = org_repo.get_changeset(r).message.split('\n')[0]
                    infos.append('  %s "%s"' % (h.short_id(r), rev_desc))

        if new_revisions:
            infos.append(_('New changesets on %s %s since the previous pull request:') % (org_ref_type, org_ref_name))
            for r in reversed(revisions):
                if r in new_revisions:
                    rev_desc = org_repo.get_changeset(r).message.split('\n')[0]
                    infos.append('  %s %s' % (h.short_id(r), h.shorter(rev_desc, 80)))

            if ancestor_rev == other_rev:
                infos.append(_("Ancestor didn't change - show diff since previous version:"))
                infos.append(h.canonical_url('compare_url',
                                 repo_name=org_repo.repo_name, # other_repo is always same as repo_name
                                 org_ref_type='rev', org_ref_name=h.short_id(org_rev), # use old org_rev as base
                                 other_ref_type='rev', other_ref_name=h.short_id(new_org_rev),
                                 )) # note: linear diff, merge or not doesn't matter
            else:
                infos.append(_('This pull request is based on another %s revision and there is no simple diff.') % other_ref_name)
        else:
           infos.append(_('No changes found on %s %s since previous version.') % (org_ref_type, org_ref_name))
           # TODO: fail?

        # hack: ancestor_rev is not an other_ref but we want to show the
        # requested destination and have the exact ancestor
        new_other_ref = '%s:%s:%s' % (other_ref_type, other_ref_name, ancestor_rev)
        new_org_ref = '%s:%s:%s' % (org_ref_type, org_ref_name, new_org_rev)

        try:
            title, old_v = re.match(r'(.*)\(v(\d+)\)\s*$', title).groups()
            v = int(old_v) + 1
        except (AttributeError, ValueError):
            v = 2
        title = '%s (v%s)' % (title.strip(), v)

        # using a mail-like separator, insert new update info at the top of the list
        descriptions = description.replace('\r\n', '\n').split('\n-- \n', 1)
        description = descriptions[0].strip() + '\n\n-- \n' + '\n'.join(infos)
        if len(descriptions) > 1:
            description += '\n\n' + descriptions[1].strip()

        try:
            pull_request = PullRequestModel().create(
                self.authuser.user_id,
                old_pull_request.org_repo.repo_name, new_org_ref,
                old_pull_request.other_repo.repo_name, new_other_ref,
                revisions, reviewers_ids, title, description
            )
        except UserInvalidException as u:
            h.flash(_('Invalid reviewer "%s" specified') % u, category='error')
            raise HTTPBadRequest()
        except Exception:
            h.flash(_('Error occurred while creating pull request'),
                    category='error')
            log.error(traceback.format_exc())
            raise HTTPFound(location=old_pull_request.url())

        ChangesetCommentsModel().create(
            text=_('Closed, replaced by %s .') % pull_request.url(canonical=True),
            repo=old_pull_request.other_repo.repo_id,
            user=c.authuser.user_id,
            pull_request=old_pull_request.pull_request_id,
            closing_pr=True)
        PullRequestModel().close_pull_request(old_pull_request.pull_request_id)

        Session().commit()
        h.flash(_('Pull request update created'),
                category='success')

        raise HTTPFound(location=pull_request.url())
示例#7
0
    def create(self, repo_name):
        repo = RepoModel()._get_repo(repo_name)
        try:
            _form = PullRequestForm(repo.repo_id)().to_python(request.POST)
        except formencode.Invalid as errors:
            log.error(traceback.format_exc())
            log.error(str(errors))
            msg = _('Error creating pull request: %s') % errors.msg
            h.flash(msg, 'error')
            raise HTTPBadRequest

        # heads up: org and other might seem backward here ...
        org_repo_name = _form['org_repo']
        org_ref = _form['org_ref'] # will have merge_rev as rev but symbolic name
        org_repo = RepoModel()._get_repo(org_repo_name)
        (org_ref_type,
         org_ref_name,
         org_rev) = org_ref.split(':')
        if org_ref_type == 'rev':
            org_ref_type = 'branch'
            cs = org_repo.scm_instance.get_changeset(org_rev)
            org_ref = '%s:%s:%s' % (org_ref_type, cs.branch, cs.raw_id)

        other_repo_name = _form['other_repo']
        other_ref = _form['other_ref'] # will have symbolic name and head revision
        other_repo = RepoModel()._get_repo(other_repo_name)
        (other_ref_type,
         other_ref_name,
         other_rev) = other_ref.split(':')

        cs_ranges, _cs_ranges_not, ancestor_rev = \
            CompareController._get_changesets(org_repo.scm_instance.alias,
                                              other_repo.scm_instance, other_rev, # org and other "swapped"
                                              org_repo.scm_instance, org_rev,
                                              )
        if ancestor_rev is None:
            ancestor_rev = org_repo.scm_instance.EMPTY_CHANGESET
        revisions = [cs_.raw_id for cs_ in cs_ranges]

        # hack: ancestor_rev is not an other_rev but we want to show the
        # requested destination and have the exact ancestor
        other_ref = '%s:%s:%s' % (other_ref_type, other_ref_name, ancestor_rev)

        reviewers = _form['review_members']

        title = _form['pullrequest_title']
        if not title:
            if org_repo_name == other_repo_name:
                title = '%s to %s' % (h.short_ref(org_ref_type, org_ref_name),
                                      h.short_ref(other_ref_type, other_ref_name))
            else:
                title = '%s#%s to %s#%s' % (org_repo_name, h.short_ref(org_ref_type, org_ref_name),
                                            other_repo_name, h.short_ref(other_ref_type, other_ref_name))
        description = _form['pullrequest_desc'].strip() or _('No description')
        try:
            pull_request = PullRequestModel().create(
                self.authuser.user_id, org_repo_name, org_ref, other_repo_name,
                other_ref, revisions, reviewers, title, description
            )
            Session().commit()
            h.flash(_('Successfully opened new pull request'),
                    category='success')
        except UserInvalidException as u:
            h.flash(_('Invalid reviewer "%s" specified') % u, category='error')
            raise HTTPBadRequest()
        except Exception:
            h.flash(_('Error occurred while creating pull request'),
                    category='error')
            log.error(traceback.format_exc())
            raise HTTPFound(location=url('pullrequest_home', repo_name=repo_name))

        raise HTTPFound(location=pull_request.url())
示例#8
0
    def __before__(self):
        """
        __before__ is called before controller methods and after __call__
        """
        c.kallithea_version = __version__
        rc_config = Setting.get_app_settings()

        # Visual options
        c.visual = AttributeDict({})

        ## DB stored
        c.visual.show_public_icon = str2bool(rc_config.get('show_public_icon'))
        c.visual.show_private_icon = str2bool(
            rc_config.get('show_private_icon'))
        c.visual.stylify_metatags = str2bool(rc_config.get('stylify_metatags'))
        c.visual.dashboard_items = safe_int(
            rc_config.get('dashboard_items', 100))
        c.visual.admin_grid_items = safe_int(
            rc_config.get('admin_grid_items', 100))
        c.visual.repository_fields = str2bool(
            rc_config.get('repository_fields'))
        c.visual.show_version = str2bool(rc_config.get('show_version'))
        c.visual.use_gravatar = str2bool(rc_config.get('use_gravatar'))
        c.visual.gravatar_url = rc_config.get('gravatar_url')

        c.ga_code = rc_config.get('ga_code')
        # TODO: replace undocumented backwards compatibility hack with db upgrade and rename ga_code
        if c.ga_code and '<' not in c.ga_code:
            c.ga_code = '''<script type="text/javascript">
                var _gaq = _gaq || [];
                _gaq.push(['_setAccount', '%s']);
                _gaq.push(['_trackPageview']);

                (function() {
                    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
                    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
                    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
                    })();
            </script>''' % c.ga_code
        c.site_name = rc_config.get('title')
        c.clone_uri_tmpl = rc_config.get('clone_uri_tmpl')

        ## INI stored
        c.visual.allow_repo_location_change = str2bool(
            config.get('allow_repo_location_change', True))
        c.visual.allow_custom_hooks_settings = str2bool(
            config.get('allow_custom_hooks_settings', True))

        c.instance_id = config.get('instance_id')
        c.issues_url = config.get('bugtracker', url('issues_url'))
        # END CONFIG VARS

        c.repo_name = get_repo_slug(request)  # can be empty
        c.backends = BACKENDS.keys()
        c.unread_notifications = NotificationModel()\
                        .get_unread_cnt_for_user(c.authuser.user_id)

        self.cut_off_limit = safe_int(config.get('cut_off_limit'))

        c.my_pr_count = PullRequestModel().get_pullrequest_cnt_for_user(
            c.authuser.user_id)

        self.sa = meta.Session
        self.scm_model = ScmModel(self.sa)
示例#9
0
    def comment(self, repo_name, pull_request_id):
        pull_request = PullRequest.get_or_404(pull_request_id)

        status = request.POST.get('changeset_status')
        close_pr = request.POST.get('save_close')
        delete = request.POST.get('save_delete')
        f_path = request.POST.get('f_path')
        line_no = request.POST.get('line')

        if (status or close_pr or delete) and (f_path or line_no):
            # status votes and closing is only possible in general comments
            raise HTTPBadRequest()

        allowed_to_change_status = self._get_is_allowed_change_status(pull_request)
        if not allowed_to_change_status:
            if status or close_pr:
                h.flash(_('No permission to change pull request status'), 'error')
                raise HTTPForbidden()

        if delete == "delete":
            if (pull_request.owner_id == request.authuser.user_id or
                h.HasPermissionAny('hg.admin')() or
                h.HasRepoPermissionLevel('admin')(pull_request.org_repo.repo_name) or
                h.HasRepoPermissionLevel('admin')(pull_request.other_repo.repo_name)
                ) and not pull_request.is_closed():
                PullRequestModel().delete(pull_request)
                Session().commit()
                h.flash(_('Successfully deleted pull request %s') % pull_request_id,
                        category='success')
                return {
                   'location': url('my_pullrequests'), # or repo pr list?
                }
                raise HTTPFound(location=url('my_pullrequests')) # or repo pr list?
            raise HTTPForbidden()

        text = request.POST.get('text', '').strip()

        comment = create_comment(
            text,
            status,
            pull_request_id=pull_request_id,
            f_path=f_path,
            line_no=line_no,
            closing_pr=close_pr,
        )

        action_logger(request.authuser,
                      'user_commented_pull_request:%s' % pull_request_id,
                      c.db_repo, request.ip_addr)

        if status:
            ChangesetStatusModel().set_status(
                c.db_repo.repo_id,
                status,
                request.authuser.user_id,
                comment,
                pull_request=pull_request_id
            )

        if close_pr:
            PullRequestModel().close_pull_request(pull_request_id)
            action_logger(request.authuser,
                          'user_closed_pull_request:%s' % pull_request_id,
                          c.db_repo, request.ip_addr)

        Session().commit()

        if not request.environ.get('HTTP_X_PARTIAL_XHR'):
            raise HTTPFound(location=pull_request.url())

        data = {
           'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
        }
        if comment is not None:
            c.comment = comment
            data.update(comment.get_dict())
            data.update({'rendered_text':
                         render('changeset/changeset_comment_block.html')})

        return data
示例#10
0
        other_ref = '%s:%s:%s' % (other_ref_type, other_ref_name, ancestor_rev)

        reviewers = _form['review_members']

        title = _form['pullrequest_title']
        if not title:
            if org_repo_name == other_repo_name:
                title = '%s to %s' % (h.short_ref(org_ref_type, org_ref_name),
                                      h.short_ref(other_ref_type, other_ref_name))
            else:
                title = '%s#%s to %s#%s' % (org_repo_name, h.short_ref(org_ref_type, org_ref_name),
                                            other_repo_name, h.short_ref(other_ref_type, other_ref_name))
        description = _form['pullrequest_desc'].strip() or _('No description')
        try:
            pull_request = PullRequestModel().create(
                self.authuser.user_id, org_repo_name, org_ref, other_repo_name,
                other_ref, revisions, reviewers, title, description
            )
            Session().commit()
            h.flash(_('Successfully opened new pull request'),
                    category='success')
        except Exception:
            h.flash(_('Error occurred while creating pull request'),
                    category='error')
            log.error(traceback.format_exc())
            return redirect(url('pullrequest_home', repo_name=repo_name))

        return redirect(pull_request.url())

    def create_update(self, old_pull_request, updaterev, title, description, reviewers_ids):
        org_repo = RepoModel()._get_repo(old_pull_request.org_repo.repo_name)
        org_ref_type, org_ref_name, org_rev = old_pull_request.org_ref.split(':')
示例#11
0
    def comment(self, repo_name, pull_request_id):
        pull_request = PullRequest.get_or_404(pull_request_id)

        status = 0
        close_pr = False
        allowed_to_change_status = self._get_is_allowed_change_status(
            pull_request)
        if allowed_to_change_status:
            status = request.POST.get('changeset_status')
            close_pr = request.POST.get('save_close')
        text = request.POST.get('text', '').strip() or _('No comments.')
        if close_pr:
            text = _('Closing.') + '\n' + text

        comm = ChangesetCommentsModel().create(
            text=text,
            repo=c.db_repo.repo_id,
            user=c.authuser.user_id,
            pull_request=pull_request_id,
            f_path=request.POST.get('f_path'),
            line_no=request.POST.get('line'),
            status_change=(ChangesetStatus.get_status_lbl(status)
                           if status and allowed_to_change_status else None),
            closing_pr=close_pr)

        action_logger(self.authuser,
                      'user_commented_pull_request:%s' % pull_request_id,
                      c.db_repo, self.ip_addr, self.sa)

        if allowed_to_change_status:
            # get status if set !
            if status:
                ChangesetStatusModel().set_status(c.db_repo.repo_id,
                                                  status,
                                                  c.authuser.user_id,
                                                  comm,
                                                  pull_request=pull_request_id)

            if close_pr:
                PullRequestModel().close_pull_request(pull_request_id)
                action_logger(self.authuser,
                              'user_closed_pull_request:%s' % pull_request_id,
                              c.db_repo, self.ip_addr, self.sa)

        Session().commit()

        if not request.environ.get('HTTP_X_PARTIAL_XHR'):
            return redirect(pull_request.url())

        data = {
            'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
        }
        if comm:
            c.co = comm
            data.update(comm.get_dict())
            data.update({
                'rendered_text':
                render('changeset/changeset_comment_block.html')
            })

        return data
示例#12
0
    def create_update(self, old_pull_request, updaterev, title, description,
                      reviewers_ids):
        org_repo = RepoModel()._get_repo(old_pull_request.org_repo.repo_name)
        org_ref_type, org_ref_name, org_rev = old_pull_request.org_ref.split(
            ':')
        new_org_rev = self._get_ref_rev(org_repo, 'rev', updaterev)

        other_repo = RepoModel()._get_repo(
            old_pull_request.other_repo.repo_name)
        other_ref_type, other_ref_name, other_rev = old_pull_request.other_ref.split(
            ':')  # other_rev is ancestor
        #assert other_ref_type == 'branch', other_ref_type # TODO: what if not?
        new_other_rev = self._get_ref_rev(other_repo, other_ref_type,
                                          other_ref_name)

        cs_ranges, _cs_ranges_not, ancestor_rev = CompareController._get_changesets(
            org_repo.scm_instance.alias,
            other_repo.scm_instance,
            new_other_rev,  # org and other "swapped"
            org_repo.scm_instance,
            new_org_rev)

        old_revisions = set(old_pull_request.revisions)
        revisions = [cs.raw_id for cs in cs_ranges]
        new_revisions = [r for r in revisions if r not in old_revisions]
        lost = old_revisions.difference(revisions)

        infos = [
            'This is an update of %s "%s".' %
            (h.canonical_url('pullrequest_show',
                             repo_name=old_pull_request.other_repo.repo_name,
                             pull_request_id=old_pull_request.pull_request_id),
             old_pull_request.title)
        ]

        if lost:
            infos.append(
                _('Missing changesets since the previous pull request:'))
            for r in old_pull_request.revisions:
                if r in lost:
                    rev_desc = org_repo.get_changeset(r).message.split('\n')[0]
                    infos.append('  %s "%s"' % (h.short_id(r), rev_desc))

        if new_revisions:
            infos.append(
                _('New changesets on %s %s since the previous pull request:') %
                (org_ref_type, org_ref_name))
            for r in reversed(revisions):
                if r in new_revisions:
                    rev_desc = org_repo.get_changeset(r).message.split('\n')[0]
                    infos.append('  %s %s' %
                                 (h.short_id(r), h.shorter(rev_desc, 80)))

            if ancestor_rev == other_rev:
                infos.append(
                    _("Ancestor didn't change - show diff since previous version:"
                      ))
                infos.append(
                    h.canonical_url(
                        'compare_url',
                        repo_name=org_repo.
                        repo_name,  # other_repo is always same as repo_name
                        org_ref_type='rev',
                        org_ref_name=h.short_id(
                            org_rev),  # use old org_rev as base
                        other_ref_type='rev',
                        other_ref_name=h.short_id(new_org_rev),
                    ))  # note: linear diff, merge or not doesn't matter
            else:
                infos.append(
                    _('This pull request is based on another %s revision and there is no simple diff.'
                      ) % other_ref_name)
        else:
            infos.append(
                _('No changes found on %s %s since previous version.') %
                (org_ref_type, org_ref_name))
            # TODO: fail?

        # hack: ancestor_rev is not an other_ref but we want to show the
        # requested destination and have the exact ancestor
        new_other_ref = '%s:%s:%s' % (other_ref_type, other_ref_name,
                                      ancestor_rev)
        new_org_ref = '%s:%s:%s' % (org_ref_type, org_ref_name, new_org_rev)

        try:
            title, old_v = re.match(r'(.*)\(v(\d+)\)\s*$', title).groups()
            v = int(old_v) + 1
        except (AttributeError, ValueError):
            v = 2
        title = '%s (v%s)' % (title.strip(), v)

        # using a mail-like separator, insert new update info at the top of the list
        descriptions = description.replace('\r\n', '\n').split('\n-- \n', 1)
        description = descriptions[0].strip() + '\n\n-- \n' + '\n'.join(infos)
        if len(descriptions) > 1:
            description += '\n\n' + descriptions[1].strip()

        try:
            pull_request = PullRequestModel().create(
                self.authuser.user_id, old_pull_request.org_repo.repo_name,
                new_org_ref, old_pull_request.other_repo.repo_name,
                new_other_ref, revisions, reviewers_ids, title, description)
        except Exception:
            h.flash(_('Error occurred while creating pull request'),
                    category='error')
            log.error(traceback.format_exc())
            return redirect(old_pull_request.url())

        ChangesetCommentsModel().create(
            text=_('Closed, replaced by %s .') %
            pull_request.url(canonical=True),
            repo=old_pull_request.other_repo.repo_id,
            user=c.authuser.user_id,
            pull_request=old_pull_request.pull_request_id,
            closing_pr=True)
        PullRequestModel().close_pull_request(old_pull_request.pull_request_id)

        Session().commit()
        h.flash(_('Pull request update created'), category='success')

        return redirect(pull_request.url())
示例#13
0
        title = _form['pullrequest_title']
        if not title:
            if org_repo_name == other_repo_name:
                title = '%s to %s' % (h.short_ref(
                    org_ref_type,
                    org_ref_name), h.short_ref(other_ref_type, other_ref_name))
            else:
                title = '%s#%s to %s#%s' % (
                    org_repo_name, h.short_ref(org_ref_type,
                                               org_ref_name), other_repo_name,
                    h.short_ref(other_ref_type, other_ref_name))
        description = _form['pullrequest_desc'].strip() or _('No description')
        try:
            pull_request = PullRequestModel().create(
                self.authuser.user_id, org_repo_name, org_ref, other_repo_name,
                other_ref, revisions, reviewers, title, description)
            Session().commit()
            h.flash(_('Successfully opened new pull request'),
                    category='success')
        except Exception:
            h.flash(_('Error occurred while creating pull request'),
                    category='error')
            log.error(traceback.format_exc())
            return redirect(url('pullrequest_home', repo_name=repo_name))

        return redirect(pull_request.url())

    def create_update(self, old_pull_request, updaterev, title, description,
                      reviewers_ids):
        org_repo = RepoModel()._get_repo(old_pull_request.org_repo.repo_name)