Ejemplo n.º 1
0
    def _rss_feed(self, repos, public=True):
        if public:
            link = h.canonical_url('public_journal_atom')
            desc = '%s %s %s' % (c.site_name, _('Public Journal'),
                                  'rss feed')
        else:
            link = h.canonical_url('journal_atom')
            desc = '%s %s %s' % (c.site_name, _('Journal'), 'rss feed')

        return self._feed(repos, feeds.RssFeed, link, desc)
Ejemplo n.º 2
0
    def __add_reviewers(self, pr, reviewers, mention_recipients=None):
        #members
        for member in set(reviewers):
            _usr = self._get_user(member)
            reviewer = PullRequestReviewers(_usr, pr)
            Session().add(reviewer)

        revision_data = [(x.raw_id, x.message)
                         for x in map(pr.org_repo.get_changeset, pr.revisions)]

        #notification to reviewers
        pr_url = pr.url(canonical=True)
        threading = [h.canonical_url('pullrequest_show', repo_name=pr.other_repo.repo_name,
                                     pull_request_id=pr.pull_request_id)]
        subject = safe_unicode(
            h.link_to(
              _('%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s') % \
                {'user': pr.author.username,
                 'pr_title': pr.title,
                 'pr_id': pr.pull_request_id},
                pr_url)
            )
        body = pr.description
        _org_ref_type, org_ref_name, _org_rev = pr.org_ref.split(':')
        email_kwargs = {
            'pr_title': pr.title,
            'pr_user_created': h.person(pr.author),
            'pr_repo_url': h.canonical_url('summary_home', repo_name=pr.other_repo.repo_name),
            'pr_url': pr_url,
            'pr_revisions': revision_data,
            'repo_name': pr.other_repo.repo_name,
            'pr_id': pr.pull_request_id,
            'ref': org_ref_name,
            'pr_username': pr.author.username,
            'threading': threading,
            'is_mention': False,
            }
        if reviewers:
            NotificationModel().create(created_by=pr.author, subject=subject, body=body,
                                       recipients=reviewers,
                                       type_=Notification.TYPE_PULL_REQUEST,
                                       email_kwargs=email_kwargs)

        if mention_recipients:
            mention_recipients.discard(None)
            mention_recipients.difference_update(reviewers)
        if mention_recipients:
            email_kwargs['is_mention'] = True
            subject = _('[Mention]') + ' ' + subject

            NotificationModel().create(created_by=pr.author, subject=subject, body=body,
                                       recipients=mention_recipients,
                                       type_=Notification.TYPE_PULL_REQUEST,
                                       email_kwargs=email_kwargs)
Ejemplo n.º 3
0
    def __get_desc(self, cs):
        desc_msg = [(_('%s committed on %s')
                     % (h.person(cs.author), h.fmt_date(cs.date))) + '<br/>']
        #branches, tags, bookmarks
        if cs.branch:
            desc_msg.append('branch: %s<br/>' % cs.branch)
        if h.is_hg(c.db_repo_scm_instance):
            for book in cs.bookmarks:
                desc_msg.append('bookmark: %s<br/>' % book)
        for tag in cs.tags:
            desc_msg.append('tag: %s<br/>' % tag)
        diff_processor, changes = self.__changes(cs)
        # rev link
        _url = h.canonical_url('changeset_home', repo_name=c.db_repo.repo_name,
                   revision=cs.raw_id)
        desc_msg.append('changeset: <a href="%s">%s</a>' % (_url, cs.raw_id[:8]))

        desc_msg.append('<pre>')
        desc_msg.append(h.urlify_text(cs.message))
        desc_msg.append('\n')
        desc_msg.extend(changes)
        if self.include_diff:
            desc_msg.append('\n\n')
            desc_msg.append(diff_processor.as_raw())
        desc_msg.append('</pre>')
        return map(safe_unicode, desc_msg)
Ejemplo n.º 4
0
    def create_registration(self, form_data):
        from kallithea.model.notification import NotificationModel
        import kallithea.lib.helpers as h

        form_data['admin'] = False
        form_data['extern_type'] = User.DEFAULT_AUTH_TYPE
        form_data['extern_name'] = ''
        new_user = self.create(form_data)

        # notification to admins
        subject = _('New user registration')
        body = (
            'New user registration\n'
            '---------------------\n'
            '- Username: {user.username}\n'
            '- Full Name: {user.full_name}\n'
            '- Email: {user.email}\n'
            ).format(user=new_user)
        edit_url = h.canonical_url('edit_user', id=new_user.user_id)
        email_kwargs = {
            'registered_user_url': edit_url,
            'new_username': new_user.username,
            'new_email': new_user.email,
            'new_full_name': new_user.full_name}
        NotificationModel().create(created_by=new_user, subject=subject,
                                   body=body, recipients=None,
                                   type_=NotificationModel.TYPE_REGISTRATION,
                                   email_kwargs=email_kwargs)
Ejemplo n.º 5
0
    def __get_desc(self, cs):
        desc_msg = [(_('%s committed on %s') %
                     (h.person(cs.author), h.fmt_date(cs.date))) + '<br/>']
        #branches, tags, bookmarks
        if cs.branch:
            desc_msg.append('branch: %s<br/>' % cs.branch)
        if h.is_hg(c.db_repo_scm_instance):
            for book in cs.bookmarks:
                desc_msg.append('bookmark: %s<br/>' % book)
        for tag in cs.tags:
            desc_msg.append('tag: %s<br/>' % tag)
        diff_processor, changes = self.__changes(cs)
        # rev link
        _url = h.canonical_url('changeset_home',
                               repo_name=c.db_repo.repo_name,
                               revision=cs.raw_id)
        desc_msg.append('changeset: <a href="%s">%s</a>' %
                        (_url, cs.raw_id[:8]))

        desc_msg.append('<pre>')
        desc_msg.append(h.urlify_text(cs.message))
        desc_msg.append('\n')
        desc_msg.extend(changes)
        if self.include_diff:
            desc_msg.append('\n\n')
            desc_msg.append(diff_processor.as_raw())
        desc_msg.append('</pre>')
        return map(safe_unicode, desc_msg)
Ejemplo n.º 6
0
    def create_registration(self, form_data):
        from kallithea.model.notification import NotificationModel
        import kallithea.lib.helpers as h

        form_data['admin'] = False
        form_data['extern_name'] = EXTERN_TYPE_INTERNAL
        form_data['extern_type'] = EXTERN_TYPE_INTERNAL
        new_user = self.create(form_data)

        self.sa.add(new_user)
        self.sa.flush()

        # notification to admins
        subject = _('New user registration')
        body = ('New user registration\n'
                '---------------------\n'
                '- Username: %s\n'
                '- Full Name: %s\n'
                '- Email: %s\n')
        body = body % (new_user.username, new_user.full_name, new_user.email)
        edit_url = h.canonical_url('edit_user', id=new_user.user_id)
        email_kwargs = {'registered_user_url': edit_url, 'new_username': new_user.username}
        NotificationModel().create(created_by=new_user, subject=subject,
                                   body=body, recipients=None,
                                   type_=Notification.TYPE_REGISTRATION,
                                   email_kwargs=email_kwargs)
Ejemplo n.º 7
0
    def create_registration(self, form_data):
        from kallithea.model.notification import NotificationModel
        import kallithea.lib.helpers as h

        form_data['admin'] = False
        form_data['extern_type'] = User.DEFAULT_AUTH_TYPE
        form_data['extern_name'] = ''
        new_user = self.create(form_data)

        # notification to admins
        subject = _('New user registration')
        body = (
            u'New user registration\n'
            '---------------------\n'
            '- Username: {user.username}\n'
            '- Full Name: {user.full_name}\n'
            '- Email: {user.email}\n'
            ).format(user=new_user)
        edit_url = h.canonical_url('edit_user', id=new_user.user_id)
        email_kwargs = {
            'registered_user_url': edit_url,
            'new_username': new_user.username,
            'new_email': new_user.email,
            'new_full_name': new_user.full_name}
        NotificationModel().create(created_by=new_user, subject=subject,
                                   body=body, recipients=None,
                                   type_=Notification.TYPE_REGISTRATION,
                                   email_kwargs=email_kwargs)
Ejemplo n.º 8
0
    def reset_password_link(self, data):
        from kallithea.lib.celerylib import tasks, run_task
        from kallithea.model.notification import EmailNotificationModel
        import kallithea.lib.helpers as h

        user_email = data['email']
        user = User.get_by_email(user_email)
        if user:
            log.debug('password reset user found %s' % user)
            link = h.canonical_url('reset_password_confirmation', key=user.api_key)
            reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
            body = EmailNotificationModel().get_email_tmpl(reg_type,
                                                           'txt',
                                                           user=user.short_contact,
                                                           reset_url=link)
            html_body = EmailNotificationModel().get_email_tmpl(reg_type,
                                                           'html',
                                                           user=user.short_contact,
                                                           reset_url=link)
            log.debug('sending email')
            run_task(tasks.send_email, [user_email],
                     _("Password reset link"), body, html_body)
            log.info('send new password mail to %s' % user_email)
        else:
            log.debug("password reset email %s not found" % user_email)

        return True
Ejemplo n.º 9
0
    def _atom_feed(self, repos, public=True):
        journal = self._get_journal_data(repos)
        if public:
            _link = h.canonical_url('public_journal_atom')
            _desc = '%s %s %s' % (c.site_name, _('public journal'),
                                  'atom feed')
        else:
            _link = h.canonical_url('journal_atom')
            _desc = '%s %s %s' % (c.site_name, _('journal'), 'atom feed')

        feed = Atom1Feed(title=_desc,
                         link=_link,
                         description=_desc,
                         language=self.language,
                         ttl=self.ttl)

        for entry in journal[:self.feed_nr]:
            user = entry.user
            if user is None:
                #fix deleted users
                user = AttributeDict({
                    'short_contact': entry.username,
                    'email': '',
                    'full_contact': ''
                })
            action, action_extra, ico = h.action_parser(entry, feed=True)
            title = "%s - %s %s" % (user.short_contact, action(),
                                    entry.repository.repo_name)
            desc = action_extra()
            _url = None
            if entry.repository is not None:
                _url = h.canonical_url('changelog_home',
                                       repo_name=entry.repository.repo_name)

            feed.add_item(title=title,
                          pubdate=entry.action_date,
                          link=_url or h.canonical_url(''),
                          author_email=user.email,
                          author_name=user.full_contact,
                          description=desc)

        response.content_type = feed.mime_type
        return feed.writeString('utf-8')
Ejemplo n.º 10
0
        def _get_feed_from_cache(key, kind):
            feed = Rss201rev2Feed(
                title=self.title % repo_name,
                link=h.canonical_url('summary_home', repo_name=repo_name),
                description=self.description % repo_name,
                language=self.language,
                ttl=self.ttl
            )

            for cs in reversed(list(c.db_repo_scm_instance[-self.feed_nr:])):
                feed.add_item(title=self._get_title(cs),
                              link=h.canonical_url('changeset_home', repo_name=repo_name,
                                       revision=cs.raw_id),
                              author_name=cs.author,
                              description=''.join(self.__get_desc(cs)),
                              pubdate=cs.date,
                             )

            response.content_type = feed.mime_type
            return feed.writeString('utf-8')
Ejemplo n.º 11
0
    def _rss_feed(self, repos, public=True):
        journal = self._get_journal_data(repos)
        if public:
            _link = h.canonical_url('public_journal_atom')
            _desc = '%s %s %s' % (c.site_name, _('Public Journal'),
                                  'rss feed')
        else:
            _link = h.canonical_url('journal_atom')
            _desc = '%s %s %s' % (c.site_name, _('Journal'), 'rss feed')

        feed = Rss201rev2Feed(title=_desc,
                         link=_link,
                         description=_desc,
                         language=language,
                         ttl=ttl)

        for entry in journal[:feed_nr]:
            user = entry.user
            if user is None:
                #fix deleted users
                user = AttributeDict({'short_contact': entry.username,
                                      'email': '',
                                      'full_contact': ''})
            action, action_extra, ico = h.action_parser(entry, feed=True)
            title = "%s - %s %s" % (user.short_contact, action(),
                                    entry.repository.repo_name)
            desc = action_extra()
            _url = None
            if entry.repository is not None:
                _url = h.canonical_url('changelog_home',
                           repo_name=entry.repository.repo_name)

            feed.add_item(title=title,
                          pubdate=entry.action_date,
                          link=_url or h.canonical_url(''),
                          author_email=user.email,
                          author_name=user.full_contact,
                          description=desc)

        response.content_type = feed.mime_type
        return feed.writeString('utf-8')
Ejemplo n.º 12
0
        def _get_feed_from_cache(key, kind):
            feed = Rss201rev2Feed(
                title=_('%s %s feed') % (c.site_name, repo_name),
                link=h.canonical_url('summary_home', repo_name=repo_name),
                description=_('Changes on %s repository') % repo_name,
                language=language,
                ttl=ttl
            )

            rss_items_per_page = safe_int(CONFIG.get('rss_items_per_page', 20))
            for cs in reversed(list(c.db_repo_scm_instance[-rss_items_per_page:])):
                feed.add_item(title=self._get_title(cs),
                              link=h.canonical_url('changeset_home', repo_name=repo_name,
                                       revision=cs.raw_id),
                              author_name=cs.author,
                              description=''.join(self.__get_desc(cs)),
                              pubdate=cs.date,
                             )

            response.content_type = feed.mime_type
            return feed.writeString('utf-8')
Ejemplo n.º 13
0
        def _get_feed_from_cache(key, kind):
            feed = Rss201rev2Feed(title=self.title % repo_name,
                                  link=h.canonical_url('summary_home',
                                                       repo_name=repo_name),
                                  description=self.description % repo_name,
                                  language=self.language,
                                  ttl=self.ttl)

            for cs in reversed(list(c.db_repo_scm_instance[-self.feed_nr:])):
                feed.add_item(
                    title=self._get_title(cs),
                    link=h.canonical_url('changeset_home',
                                         repo_name=repo_name,
                                         revision=cs.raw_id),
                    author_name=cs.author,
                    description=''.join(self.__get_desc(cs)),
                    pubdate=cs.date,
                )

            response.content_type = feed.mime_type
            return feed.writeString('utf-8')
Ejemplo n.º 14
0
        def _get_feed_from_cache(key, kind):
            feed = Rss201rev2Feed(
                title=_('%s %s feed') % (c.site_name, repo_name),
                link=h.canonical_url('summary_home', repo_name=repo_name),
                description=_('Changes on %s repository') % repo_name,
                language=language,
                ttl=ttl)

            rss_items_per_page = safe_int(CONFIG.get('rss_items_per_page', 20))
            for cs in reversed(
                    list(c.db_repo_scm_instance[-rss_items_per_page:])):
                feed.add_item(
                    title=self._get_title(cs),
                    link=h.canonical_url('changeset_home',
                                         repo_name=repo_name,
                                         revision=cs.raw_id),
                    author_name=cs.author,
                    description=''.join(self.__get_desc(cs)),
                    pubdate=cs.date,
                )

            response.content_type = feed.mime_type
            return feed.writeString('utf-8')
Ejemplo n.º 15
0
    def _feed(self, repos, feeder, link, desc):
        response.content_type = feeder.content_type
        journal = self._get_journal_data(repos)

        header = dict(
            title=desc,
            link=link,
            description=desc,
        )

        entries=[]
        for entry in journal[:feed_nr]:
            user = entry.user
            if user is None:
                # fix deleted users
                user = AttributeDict({'short_contact': entry.username,
                                      'email': '',
                                      'full_contact': ''})
            action, action_extra, ico = h.action_parser(entry, feed=True)
            title = "%s - %s %s" % (user.short_contact, action(),
                                    entry.repository.repo_name)
            _url = None
            if entry.repository is not None:
                _url = h.canonical_url('changelog_home',
                           repo_name=entry.repository.repo_name)

            entries.append(dict(
                title=title,
                pubdate=entry.action_date,
                link=_url or h.canonical_url(''),
                author_email=user.email,
                author_name=user.full_name_or_username,
                description=action_extra(),
            ))

        return feeder.render(header, entries)
Ejemplo n.º 16
0
    def _get_notification_data(self,
                               repo,
                               comment,
                               user,
                               comment_text,
                               line_no=None,
                               revision=None,
                               pull_request=None,
                               status_change=None,
                               closing_pr=False):
        """
        Get notification data

        :param comment_text:
        :param line:
        :returns: tuple (subj,body,recipients,notification_type,email_kwargs)
        """
        # make notification
        body = comment_text  # text of the comment
        line = ''
        if line_no:
            line = _('on line %s') % line_no

        #changeset
        if revision:
            notification_type = Notification.TYPE_CHANGESET_COMMENT
            cs = repo.scm_instance.get_changeset(revision)
            desc = "%s" % (cs.short_id)

            threading = [
                '%s-rev-%s@%s' %
                (repo.repo_name, revision, h.canonical_hostname())
            ]
            if line_no:  # TODO: url to file _and_ line number
                threading.append('%s-rev-%s-line-%s@%s' %
                                 (repo.repo_name, revision, line_no,
                                  h.canonical_hostname()))
            comment_url = h.canonical_url('changeset_home',
                                          repo_name=repo.repo_name,
                                          revision=revision,
                                          anchor='comment-%s' %
                                          comment.comment_id)
            subj = safe_unicode(
                h.link_to('Re changeset: %(desc)s %(line)s' % \
                          {'desc': desc, 'line': line},
                          comment_url)
            )
            # get the current participants of this changeset
            recipients = ChangesetComment.get_users(revision=revision)
            # add changeset author if it's in kallithea system
            cs_author = User.get_from_cs_author(cs.author)
            if not cs_author:
                #use repo owner if we cannot extract the author correctly
                cs_author = repo.user
            recipients += [cs_author]
            email_kwargs = {
                'status_change':
                status_change,
                'cs_comment_user':
                h.person(user, 'username_and_name'),
                'cs_target_repo':
                h.canonical_url('summary_home', repo_name=repo.repo_name),
                'cs_comment_url':
                comment_url,
                'raw_id':
                revision,
                'message':
                cs.message,
                'repo_name':
                repo.repo_name,
                'short_id':
                h.short_id(revision),
                'branch':
                cs.branch,
                'comment_username':
                user.username,
                'threading':
                threading,
            }
        #pull request
        elif pull_request:
            notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
            desc = comment.pull_request.title
            _org_ref_type, org_ref_name, _org_rev = comment.pull_request.org_ref.split(
                ':')
            threading = [
                '%s-pr-%s@%s' %
                (pull_request.other_repo.repo_name,
                 pull_request.pull_request_id, h.canonical_hostname())
            ]
            if line_no:  # TODO: url to file _and_ line number
                threading.append('%s-pr-%s-line-%s@%s' %
                                 (pull_request.other_repo.repo_name,
                                  pull_request.pull_request_id, line_no,
                                  h.canonical_hostname()))
            comment_url = pull_request.url(canonical=True,
                                           anchor='comment-%s' %
                                           comment.comment_id)
            subj = safe_unicode(
                h.link_to('Re pull request #%(pr_id)s: %(desc)s %(line)s' % \
                          {'desc': desc,
                           'pr_id': comment.pull_request.pull_request_id,
                           'line': line},
                          comment_url)
            )
            # get the current participants of this pull request
            recipients = ChangesetComment.get_users(
                pull_request_id=pull_request.pull_request_id)
            # add pull request author
            recipients += [pull_request.author]

            # add the reviewers to notification
            recipients += [x.user for x in pull_request.reviewers]

            #set some variables for email notification
            email_kwargs = {
                'pr_title':
                pull_request.title,
                'pr_id':
                pull_request.pull_request_id,
                'status_change':
                status_change,
                'closing_pr':
                closing_pr,
                'pr_comment_url':
                comment_url,
                'pr_comment_user':
                h.person(user, 'username_and_name'),
                'pr_target_repo':
                h.canonical_url('summary_home',
                                repo_name=pull_request.other_repo.repo_name),
                'repo_name':
                pull_request.other_repo.repo_name,
                'ref':
                org_ref_name,
                'comment_username':
                user.username,
                'threading':
                threading,
            }

        return subj, body, recipients, notification_type, email_kwargs
Ejemplo n.º 17
0
    def _get_notification_data(self, repo, comment, user, comment_text,
                               line_no=None, revision=None, pull_request=None,
                               status_change=None, closing_pr=False):
        """
        Get notification data

        :param comment_text:
        :param line:
        :returns: tuple (subj,body,recipients,notification_type,email_kwargs)
        """
        # make notification
        body = comment_text  # text of the comment
        line = ''
        if line_no:
            line = _('on line %s') % line_no

        #changeset
        if revision:
            notification_type = Notification.TYPE_CHANGESET_COMMENT
            cs = repo.scm_instance.get_changeset(revision)
            desc = "%s" % (cs.short_id)

            threading = ['%s-rev-%s@%s' % (repo.repo_name, revision, h.canonical_hostname())]
            if line_no: # TODO: url to file _and_ line number
                threading.append('%s-rev-%s-line-%s@%s' % (repo.repo_name, revision, line_no,
                                                           h.canonical_hostname()))
            comment_url = h.canonical_url('changeset_home',
                repo_name=repo.repo_name,
                revision=revision,
                anchor='comment-%s' % comment.comment_id)
            subj = safe_unicode(
                h.link_to('Re changeset: %(desc)s %(line)s' % \
                          {'desc': desc, 'line': line},
                          comment_url)
            )
            # get the current participants of this changeset
            recipients = ChangesetComment.get_users(revision=revision)
            # add changeset author if it's in kallithea system
            cs_author = User.get_from_cs_author(cs.author)
            if not cs_author:
                #use repo owner if we cannot extract the author correctly
                cs_author = repo.user
            recipients += [cs_author]
            email_kwargs = {
                'status_change': status_change,
                'cs_comment_user': h.person(user, 'username_and_name'),
                'cs_target_repo': h.canonical_url('summary_home', repo_name=repo.repo_name),
                'cs_comment_url': comment_url,
                'raw_id': revision,
                'message': cs.message,
                'repo_name': repo.repo_name,
                'short_id': h.short_id(revision),
                'branch': cs.branch,
                'comment_username': user.username,
                'threading': threading,
            }
        #pull request
        elif pull_request:
            notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
            desc = comment.pull_request.title
            _org_ref_type, org_ref_name, _org_rev = comment.pull_request.org_ref.split(':')
            threading = ['%s-pr-%s@%s' % (pull_request.other_repo.repo_name,
                                          pull_request.pull_request_id,
                                          h.canonical_hostname())]
            if line_no: # TODO: url to file _and_ line number
                threading.append('%s-pr-%s-line-%s@%s' % (pull_request.other_repo.repo_name,
                                                          pull_request.pull_request_id, line_no,
                                                          h.canonical_hostname()))
            comment_url = pull_request.url(canonical=True,
                anchor='comment-%s' % comment.comment_id)
            subj = safe_unicode(
                h.link_to('Re pull request #%(pr_id)s: %(desc)s %(line)s' % \
                          {'desc': desc,
                           'pr_id': comment.pull_request.pull_request_id,
                           'line': line},
                          comment_url)
            )
            # get the current participants of this pull request
            recipients = ChangesetComment.get_users(pull_request_id=
                                                pull_request.pull_request_id)
            # add pull request author
            recipients += [pull_request.author]

            # add the reviewers to notification
            recipients += [x.user for x in pull_request.reviewers]

            #set some variables for email notification
            email_kwargs = {
                'pr_title': pull_request.title,
                'pr_id': pull_request.pull_request_id,
                'status_change': status_change,
                'closing_pr': closing_pr,
                'pr_comment_url': comment_url,
                'pr_comment_user': h.person(user, 'username_and_name'),
                'pr_target_repo': h.canonical_url('summary_home',
                                   repo_name=pull_request.other_repo.repo_name),
                'repo_name': pull_request.other_repo.repo_name,
                'ref': org_ref_name,
                'comment_username': user.username,
                'threading': threading,
            }

        return subj, body, recipients, notification_type, email_kwargs
Ejemplo n.º 18
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())
Ejemplo n.º 19
0
    def _get_notification_data(self,
                               repo,
                               comment,
                               author,
                               comment_text,
                               line_no=None,
                               revision=None,
                               pull_request=None,
                               status_change=None,
                               closing_pr=False):
        """
        :returns: tuple (subj,body,recipients,notification_type,email_kwargs)
        """
        # make notification
        body = comment_text  # text of the comment
        line = ''
        if line_no:
            line = _('on line %s') % line_no

        #changeset
        if revision:
            notification_type = Notification.TYPE_CHANGESET_COMMENT
            cs = repo.scm_instance.get_changeset(revision)
            desc = cs.short_id

            threading = [
                '%s-rev-%s@%s' %
                (repo.repo_name, revision, h.canonical_hostname())
            ]
            if line_no:  # TODO: url to file _and_ line number
                threading.append('%s-rev-%s-line-%s@%s' %
                                 (repo.repo_name, revision, line_no,
                                  h.canonical_hostname()))
            comment_url = h.canonical_url('changeset_home',
                                          repo_name=repo.repo_name,
                                          revision=revision,
                                          anchor='comment-%s' %
                                          comment.comment_id)
            subj = safe_unicode(
                h.link_to('Re changeset: %(desc)s %(line)s' % \
                          {'desc': desc, 'line': line},
                          comment_url)
            )
            # get the current participants of this changeset
            recipients = _list_changeset_commenters(revision)
            # add changeset author if it's known locally
            cs_author = User.get_from_cs_author(cs.author)
            if not cs_author:
                #use repo owner if we cannot extract the author correctly
                # FIXME: just use committer name even if not a user
                cs_author = repo.owner
            recipients.append(cs_author)

            email_kwargs = {
                'status_change':
                status_change,
                'cs_comment_user':
                author.full_name_and_username,
                'cs_target_repo':
                h.canonical_url('summary_home', repo_name=repo.repo_name),
                'cs_comment_url':
                comment_url,
                'cs_url':
                h.canonical_url('changeset_home',
                                repo_name=repo.repo_name,
                                revision=revision),
                'raw_id':
                revision,
                'message':
                cs.message,
                'message_short':
                h.shorter(cs.message, 50, firstline=True),
                'cs_author':
                cs_author,
                'repo_name':
                repo.repo_name,
                'short_id':
                h.short_id(revision),
                'branch':
                cs.branch,
                'comment_username':
                author.username,
                'threading':
                threading,
            }
        #pull request
        elif pull_request:
            notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
            desc = comment.pull_request.title
            _org_ref_type, org_ref_name, _org_rev = comment.pull_request.org_ref.split(
                ':')
            _other_ref_type, other_ref_name, _other_rev = comment.pull_request.other_ref.split(
                ':')
            threading = [
                '%s-pr-%s@%s' %
                (pull_request.other_repo.repo_name,
                 pull_request.pull_request_id, h.canonical_hostname())
            ]
            if line_no:  # TODO: url to file _and_ line number
                threading.append('%s-pr-%s-line-%s@%s' %
                                 (pull_request.other_repo.repo_name,
                                  pull_request.pull_request_id, line_no,
                                  h.canonical_hostname()))
            comment_url = pull_request.url(canonical=True,
                                           anchor='comment-%s' %
                                           comment.comment_id)
            subj = safe_unicode(
                h.link_to('Re pull request %(pr_nice_id)s: %(desc)s %(line)s' % \
                          {'desc': desc,
                           'pr_nice_id': comment.pull_request.nice_id(),
                           'line': line},
                          comment_url)
            )
            # get the current participants of this pull request
            recipients = _list_pull_request_commenters(pull_request)
            recipients.append(pull_request.owner)
            recipients += pull_request.get_reviewer_users()

            #set some variables for email notification
            email_kwargs = {
                'pr_title':
                pull_request.title,
                'pr_title_short':
                h.shorter(pull_request.title, 50),
                'pr_nice_id':
                pull_request.nice_id(),
                'status_change':
                status_change,
                'closing_pr':
                closing_pr,
                'pr_comment_url':
                comment_url,
                'pr_url':
                pull_request.url(canonical=True),
                'pr_comment_user':
                author.full_name_and_username,
                'pr_target_repo':
                h.canonical_url('summary_home',
                                repo_name=pull_request.other_repo.repo_name),
                'pr_target_branch':
                other_ref_name,
                'pr_source_repo':
                h.canonical_url('summary_home',
                                repo_name=pull_request.org_repo.repo_name),
                'pr_source_branch':
                org_ref_name,
                'pr_owner':
                pull_request.owner,
                'pr_owner_username':
                pull_request.owner.username,
                'repo_name':
                pull_request.other_repo.repo_name,
                'comment_username':
                author.username,
                'threading':
                threading,
            }

        return subj, body, recipients, notification_type, email_kwargs
Ejemplo n.º 20
0
    def add_reviewers(self, user, pr, reviewers, mention_recipients=None):
        """Add reviewer and send notification to them.
        """
        reviewers = set(reviewers)
        _assert_valid_reviewers(reviewers)
        if mention_recipients is not None:
            mention_recipients = set(mention_recipients) - reviewers
            _assert_valid_reviewers(mention_recipients)

        #members
        for reviewer in reviewers:
            prr = PullRequestReviewer(reviewer, pr)
            Session().add(prr)

        #notification to reviewers
        pr_url = pr.url(canonical=True)
        threading = ['%s-pr-%s@%s' % (pr.other_repo.repo_name,
                                      pr.pull_request_id,
                                      h.canonical_hostname())]
        subject = safe_unicode(
            h.link_to(
              _('%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s') % \
                {'user': user.username,
                 'pr_title': pr.title,
                 'pr_nice_id': pr.nice_id()},
                pr_url)
            )
        body = pr.description
        _org_ref_type, org_ref_name, _org_rev = pr.org_ref.split(':')
        _other_ref_type, other_ref_name, _other_rev = pr.other_ref.split(':')
        revision_data = [(x.raw_id, x.message)
                         for x in map(pr.org_repo.get_changeset, pr.revisions)]
        email_kwargs = {
            'pr_title': pr.title,
            'pr_title_short': h.shorter(pr.title, 50),
            'pr_user_created': user.full_name_and_username,
            'pr_repo_url': h.canonical_url('summary_home', repo_name=pr.other_repo.repo_name),
            'pr_url': pr_url,
            'pr_revisions': revision_data,
            'repo_name': pr.other_repo.repo_name,
            'org_repo_name': pr.org_repo.repo_name,
            'pr_nice_id': pr.nice_id(),
            'pr_target_repo': h.canonical_url('summary_home',
                               repo_name=pr.other_repo.repo_name),
            'pr_target_branch': other_ref_name,
            'pr_source_repo': h.canonical_url('summary_home',
                               repo_name=pr.org_repo.repo_name),
            'pr_source_branch': org_ref_name,
            'pr_owner': pr.owner,
            'pr_owner_username': pr.owner.username,
            'pr_username': user.username,
            'threading': threading,
            'is_mention': False,
            }
        if reviewers:
            NotificationModel().create(created_by=user, subject=subject, body=body,
                                       recipients=reviewers,
                                       type_=Notification.TYPE_PULL_REQUEST,
                                       email_kwargs=email_kwargs)

        if mention_recipients:
            email_kwargs['is_mention'] = True
            subject = _('[Mention]') + ' ' + subject
            # FIXME: this subject is wrong and unused!
            NotificationModel().create(created_by=user, subject=subject, body=body,
                                       recipients=mention_recipients,
                                       type_=Notification.TYPE_PULL_REQUEST,
                                       email_kwargs=email_kwargs)
Ejemplo n.º 21
0
    def _get_notification_data(self, repo, comment, author, comment_text,
                               line_no=None, revision=None, pull_request=None,
                               status_change=None, closing_pr=False):
        """
        :returns: tuple (subj,body,recipients,notification_type,email_kwargs)
        """
        # make notification
        body = comment_text  # text of the comment
        line = ''
        if line_no:
            line = _('on line %s') % line_no

        #changeset
        if revision:
            notification_type = Notification.TYPE_CHANGESET_COMMENT
            cs = repo.scm_instance.get_changeset(revision)
            desc = cs.short_id

            threading = ['%s-rev-%s@%s' % (repo.repo_name, revision, h.canonical_hostname())]
            if line_no: # TODO: url to file _and_ line number
                threading.append('%s-rev-%s-line-%s@%s' % (repo.repo_name, revision, line_no,
                                                           h.canonical_hostname()))
            comment_url = h.canonical_url('changeset_home',
                repo_name=repo.repo_name,
                revision=revision,
                anchor='comment-%s' % comment.comment_id)
            subj = safe_unicode(
                h.link_to('Re changeset: %(desc)s %(line)s' % \
                          {'desc': desc, 'line': line},
                          comment_url)
            )
            # get the current participants of this changeset
            recipients = _list_changeset_commenters(revision)
            # add changeset author if it's known locally
            cs_author = User.get_from_cs_author(cs.author)
            if not cs_author:
                #use repo owner if we cannot extract the author correctly
                # FIXME: just use committer name even if not a user
                cs_author = repo.owner
            recipients.append(cs_author)

            email_kwargs = {
                'status_change': status_change,
                'cs_comment_user': author.full_name_and_username,
                'cs_target_repo': h.canonical_url('summary_home', repo_name=repo.repo_name),
                'cs_comment_url': comment_url,
                'cs_url': h.canonical_url('changeset_home', repo_name=repo.repo_name, revision=revision),
                'raw_id': revision,
                'message': cs.message,
                'message_short': h.shorter(cs.message, 50, firstline=True),
                'cs_author': cs_author,
                'repo_name': repo.repo_name,
                'short_id': h.short_id(revision),
                'branch': cs.branch,
                'comment_username': author.username,
                'threading': threading,
            }
        #pull request
        elif pull_request:
            notification_type = Notification.TYPE_PULL_REQUEST_COMMENT
            desc = comment.pull_request.title
            _org_ref_type, org_ref_name, _org_rev = comment.pull_request.org_ref.split(':')
            _other_ref_type, other_ref_name, _other_rev = comment.pull_request.other_ref.split(':')
            threading = ['%s-pr-%s@%s' % (pull_request.other_repo.repo_name,
                                          pull_request.pull_request_id,
                                          h.canonical_hostname())]
            if line_no: # TODO: url to file _and_ line number
                threading.append('%s-pr-%s-line-%s@%s' % (pull_request.other_repo.repo_name,
                                                          pull_request.pull_request_id, line_no,
                                                          h.canonical_hostname()))
            comment_url = pull_request.url(canonical=True,
                anchor='comment-%s' % comment.comment_id)
            subj = safe_unicode(
                h.link_to('Re pull request %(pr_nice_id)s: %(desc)s %(line)s' % \
                          {'desc': desc,
                           'pr_nice_id': comment.pull_request.nice_id(),
                           'line': line},
                          comment_url)
            )
            # get the current participants of this pull request
            recipients = _list_pull_request_commenters(pull_request)
            recipients.append(pull_request.owner)
            recipients += pull_request.get_reviewer_users()

            #set some variables for email notification
            email_kwargs = {
                'pr_title': pull_request.title,
                'pr_title_short': h.shorter(pull_request.title, 50),
                'pr_nice_id': pull_request.nice_id(),
                'status_change': status_change,
                'closing_pr': closing_pr,
                'pr_comment_url': comment_url,
                'pr_url': pull_request.url(canonical=True),
                'pr_comment_user': author.full_name_and_username,
                'pr_target_repo': h.canonical_url('summary_home',
                                   repo_name=pull_request.other_repo.repo_name),
                'pr_target_branch': other_ref_name,
                'pr_source_repo': h.canonical_url('summary_home',
                                   repo_name=pull_request.org_repo.repo_name),
                'pr_source_branch': org_ref_name,
                'pr_owner': pull_request.owner,
                'pr_owner_username': pull_request.owner.username,
                'repo_name': pull_request.other_repo.repo_name,
                'comment_username': author.username,
                'threading': threading,
            }

        return subj, body, recipients, notification_type, email_kwargs
Ejemplo n.º 22
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())
Ejemplo n.º 23
0
    def __init__(self, old_pull_request, new_org_rev, new_other_rev, title, description, owner, reviewers):
        self.old_pull_request = old_pull_request

        org_repo = old_pull_request.org_repo
        org_ref_type, org_ref_name, org_rev = old_pull_request.org_ref.split(':')

        other_repo = old_pull_request.other_repo
        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_org_ref = '%s:%s:%s' % (org_ref_type, org_ref_name, new_org_rev)
        new_other_ref = '%s:%s:%s' % (other_ref_type, other_ref_name, new_other_rev)

        self.create_action = CreatePullRequestAction(org_repo, other_repo, new_org_ref, new_other_ref, None, None, owner, reviewers)

        # Generate complete title/description

        old_revisions = set(old_pull_request.revisions)
        revisions = self.create_action.revisions
        new_revisions = [r for r in revisions if r not in old_revisions]
        lost = old_revisions.difference(revisions)

        infos = ['This is a new iteration 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 iteration:'))
            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 iteration:') % (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 self.create_action.other_ref == old_pull_request.other_ref:
                infos.append(_("Ancestor didn't change - diff since previous iteration:"))
                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 iteration 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 iteration.') % (org_ref_type, org_ref_name))
           # TODO: fail?

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

        # using a mail-like separator, insert new iteration info in description with latest first
        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()
        self.create_action.description = description

        if not CreatePullRequestIterationAction.is_user_authorized(self.old_pull_request):
            raise CreatePullRequestAction.Unauthorized(_('You are not authorized to create the pull request'))