Changeset - 493646d3146f
[Not reviewed]
beta
0 3 1
Marcin Kuzminski - 13 years ago 2012-09-04 02:18:59
marcin@python-works.com
Nicer email notifications about pull-request
4 files changed with 42 insertions and 11 deletions:
0 comments (0 inline, 0 general)
docs/changelog.rst
Show inline comments
 
.. _changelog:
 

	
 
=========
 
Changelog
 
=========
 

	
 

	
 
1.4.1 (**2012-09-04**)
 
----------------------
 

	
 
:status: in-progress
 
:branch: beta
 

	
 
news
 
++++
 

	
 
- always put a comment about code-review status change even if user send
 
  empty data 
 
- modified_on column saves repository update and it's going to be used
 
  later for light version of main page ref #500
 
- pull request notifications send much nicer emails with details about pull
 
  request
 

	
 
fixes
 
+++++
 

	
 
- fixed migrations of permissions that can lead to inconsistency.
 
  Some users sent feedback that after upgrading from older versions issues with updating
 
  default permissions occured. RhodeCode detects that now and resets default user
 
  permission to initial state if there is a need for that. Also forces users to set
 
  the default value for new forking permission. 
 
  Some users sent feedback that after upgrading from older versions issues 
 
  with updating default permissions occurred. RhodeCode detects that now and
 
  resets default user permission to initial state if there is a need for that.
 
  Also forces users to set the default value for new forking permission. 
 

	
 

	
 
1.4.0 (**2012-09-03**)
 
----------------------
 

	
 
news
 
++++
 
 
 
- new codereview system
 
- email map, allowing users to have multiple email addresses mapped into
 
  their accounts
 
- improved git-hook system. Now all actions for git are logged into journal
 
  including pushed revisions, user and IP address
 
- changed setup-app into setup-rhodecode and added default options to it.
 
- new git repos are created as bare now by default
 
- #464 added links to groups in permission box
 
- #465 mentions autocomplete inside comments boxes
 
- #469 added --update-only option to whoosh to re-index only given list
 
  of repos in index 
 
- rhodecode-api CLI client
 
- new git http protocol replaced buggy dulwich implementation.
 
  Now based on pygrack & gitweb
 
- Improved RSS/ATOM feeds. Discoverable by browsers using proper headers, and 
 
  reformated based on user suggestions. Additional rss/atom feeds for user
 
  journal
 
- various i18n improvements
 
- #478 permissions overview for admin in user edit view
 
- File view now displays small gravatars off all authors of given file
 
- Implemented landing revisions. Each repository will get landing_rev attribute
 
  that defines 'default' revision/branch for generating readme files
 
- Implemented #509, RhodeCode enforces SSL for push/pulling if requested at 
 
  earliest possible call.
 
- Import remote svn repositories to mercurial using hgsubversion.
 
- Fixed #508 RhodeCode now has a option to explicitly set forking permissions
 
- RhodeCode can use alternative server for generating avatar icons
 
- implemented repositories locking. Pull locks, push unlocks. Also can be done
 
  via API calls
 
- #538 form for permissions can handle multiple users at once 
 

	
 
fixes
 
+++++
 

	
 
- improved translations
 
- fixes issue #455 Creating an archive generates an exception on Windows
 
- fixes #448 Download ZIP archive keeps file in /tmp open and results 
 
  in out of disk space
 
- fixes issue #454 Search results under Windows include proceeding
 
  backslash
rhodecode/model/notification.py
Show inline comments
 
@@ -210,65 +210,66 @@ class NotificationModel(BaseModel):
 
            .filter(UserNotification.user == user).scalar()
 

	
 
    def make_description(self, notification, show_age=True):
 
        """
 
        Creates a human readable description based on properties
 
        of notification object
 
        """
 
        #alias
 
        _n = notification
 
        _map = {
 
            _n.TYPE_CHANGESET_COMMENT: _('commented on commit'),
 
            _n.TYPE_MESSAGE: _('sent message'),
 
            _n.TYPE_MENTION: _('mentioned you'),
 
            _n.TYPE_REGISTRATION: _('registered in RhodeCode'),
 
            _n.TYPE_PULL_REQUEST: _('opened new pull request'),
 
            _n.TYPE_PULL_REQUEST_COMMENT: _('commented on pull request')
 
        }
 

	
 
        # action == _map string
 
        tmpl = "%(user)s %(action)s at %(when)s"
 
        if show_age:
 
            when = h.age(notification.created_on)
 
        else:
 
            when = h.fmt_date(notification.created_on)
 

	
 
        data = dict(
 
            user=notification.created_by_user.username,
 
            action=_map[notification.type_], when=when,
 
        )
 
        return tmpl % data
 

	
 

	
 
class EmailNotificationModel(BaseModel):
 

	
 
    TYPE_CHANGESET_COMMENT = Notification.TYPE_CHANGESET_COMMENT
 
    TYPE_PASSWORD_RESET = 'passoword_link'
 
    TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
 
    TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
 
    TYPE_DEFAULT = 'default'
 

	
 
    def __init__(self):
 
        self._template_root = rhodecode.CONFIG['pylons.paths']['templates'][0]
 
        self._tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
 

	
 
        self.email_types = {
 
         self.TYPE_CHANGESET_COMMENT: 'email_templates/changeset_comment.html',
 
         self.TYPE_PASSWORD_RESET: 'email_templates/password_reset.html',
 
         self.TYPE_REGISTRATION: 'email_templates/registration.html',
 
         self.TYPE_DEFAULT: 'email_templates/default.html'
 
         self.TYPE_DEFAULT: 'email_templates/default.html',
 
         self.TYPE_PULL_REQUEST: 'email_templates/pull_request.html',
 
        }
 

	
 
    def get_email_tmpl(self, type_, **kwargs):
 
        """
 
        return generated template for email based on given type
 

	
 
        :param type_:
 
        """
 

	
 
        base = self.email_types.get(type_, self.email_types[self.TYPE_DEFAULT])
 
        email_template = self._tmpl_lookup.get_template(base)
 
        # translator inject
 
        _kwargs = {'_': _}
 
        _kwargs.update(kwargs)
 
        log.debug('rendering tmpl %s with kwargs %s' % (base, _kwargs))
 
        return email_template.render(**_kwargs)
rhodecode/model/pull_request.py
Show inline comments
 
@@ -34,112 +34,120 @@ from rhodecode.lib import helpers as h
 
from rhodecode.model import BaseModel
 
from rhodecode.model.db import PullRequest, PullRequestReviewers, Notification
 
from rhodecode.model.notification import NotificationModel
 
from rhodecode.lib.utils2 import safe_unicode
 

	
 
from rhodecode.lib.vcs.utils.hgcompat import discovery, localrepo, scmutil
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class PullRequestModel(BaseModel):
 

	
 
    cls = PullRequest
 

	
 
    def __get_pull_request(self, pull_request):
 
        return self._get_instance(PullRequest, pull_request)
 

	
 
    def get_all(self, repo):
 
        repo = self._get_repo(repo)
 
        return PullRequest.query().filter(PullRequest.other_repo == repo).all()
 

	
 
    def create(self, created_by, org_repo, org_ref, other_repo,
 
               other_ref, revisions, reviewers, title, description=None):
 

	
 
        created_by_user = self._get_user(created_by)
 
        org_repo = self._get_repo(org_repo)
 
        other_repo = self._get_repo(other_repo)
 

	
 
        new = PullRequest()
 
        new.org_repo = org_repo
 
        new.org_ref = org_ref
 
        new.other_repo = other_repo
 
        new.other_ref = other_ref
 
        new.revisions = revisions
 
        new.title = title
 
        new.description = description
 
        new.author = created_by_user
 
        self.sa.add(new)
 
        Session().flush()
 
        #members
 
        for member in reviewers:
 
            _usr = self._get_user(member)
 
            reviewer = PullRequestReviewers(_usr, new)
 
            self.sa.add(reviewer)
 

	
 
        #notification to reviewers
 
        notif = NotificationModel()
 

	
 
        pr_url = h.url('pullrequest_show', repo_name=other_repo.repo_name,
 
                       pull_request_id=new.pull_request_id,
 
                       qualified=True,
 
        )
 
        subject = safe_unicode(
 
            h.link_to(
 
              _('%(user)s wants you to review pull request #%(pr_id)s') % \
 
                {'user': created_by_user.username,
 
                 'pr_id': new.pull_request_id},
 
              h.url('pullrequest_show', repo_name=other_repo.repo_name,
 
                    pull_request_id=new.pull_request_id,
 
                    qualified=True,
 
              )
 
                pr_url
 
            )
 
        )
 
        body = description
 
        kwargs = {
 
            'pr_title': title,
 
            'pr_user_created': h.person(created_by_user.email),
 
            'pr_repo_url': h.url('summary_home', repo_name=other_repo.repo_name,
 
                                 qualified=True,),
 
            'pr_url': pr_url,
 
            'pr_revisions': revisions
 
        }
 
        notif.create(created_by=created_by_user, subject=subject, body=body,
 
                     recipients=reviewers,
 
                     type_=Notification.TYPE_PULL_REQUEST,)
 

	
 
                     type_=Notification.TYPE_PULL_REQUEST, email_kwargs=kwargs)
 
        return new
 

	
 
    def update_reviewers(self, pull_request, reviewers_ids):
 
        reviewers_ids = set(reviewers_ids)
 
        pull_request = self.__get_pull_request(pull_request)
 
        current_reviewers = PullRequestReviewers.query()\
 
                            .filter(PullRequestReviewers.pull_request==
 
                                   pull_request)\
 
                            .all()
 
        current_reviewers_ids = set([x.user.user_id for x in current_reviewers])
 

	
 
        to_add = reviewers_ids.difference(current_reviewers_ids)
 
        to_remove = current_reviewers_ids.difference(reviewers_ids)
 

	
 
        log.debug("Adding %s reviewers" % to_add)
 
        log.debug("Removing %s reviewers" % to_remove)
 

	
 
        for uid in to_add:
 
            _usr = self._get_user(uid)
 
            reviewer = PullRequestReviewers(_usr, pull_request)
 
            self.sa.add(reviewer)
 

	
 
        for uid in to_remove:
 
            reviewer = PullRequestReviewers.query()\
 
                    .filter(PullRequestReviewers.user_id==uid,
 
                            PullRequestReviewers.pull_request==pull_request)\
 
                    .scalar()
 
            if reviewer:
 
                self.sa.delete(reviewer)
 

	
 
    def delete(self, pull_request):
 
        pull_request = self.__get_pull_request(pull_request)
 
        Session().delete(pull_request)
 

	
 
    def close_pull_request(self, pull_request):
 
        pull_request = self.__get_pull_request(pull_request)
 
        pull_request.status = PullRequest.STATUS_CLOSED
 
        pull_request.updated_on = datetime.datetime.now()
 
        self.sa.add(pull_request)
 

	
 
    def _get_changesets(self, org_repo, org_ref, other_repo, other_ref,
 
                        discovery_data):
 
        """
 
        Returns a list of changesets that are incoming from org_repo@org_ref
 
        to other_repo@other_ref
 

	
 
        :param org_repo:
 
        :type org_repo:
rhodecode/templates/email_templates/pull_request.html
Show inline comments
 
new file 100644
 
## -*- coding: utf-8 -*-
 
<%inherit file="main.html"/>
 
            
 
User <b>${pr_user_created}</b> opened pull request for repository 
 
${pr_repo_url} and wants you to review changes.
 

	
 
<div>title: ${pr_title}</div>
 
<div>description:</div>
 
<p>
 
${body}
 
</p>
 

	
 
<div>revisions for reviewing</div>
 
<ul>
 
%for r in pr_revisions:
 
    <li>${r}</li>
 
%endfor
 
</ul>
 

	
 
View this pull request here: ${pr_url}
0 comments (0 inline, 0 general)