changeset 1716:7d1fc253549e beta

notification to commit author + gardening
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 23 Nov 2011 22:46:14 +0200
parents e1e482093077
children 7ff304d3028f
files rhodecode/controllers/api/api.py rhodecode/controllers/changeset.py rhodecode/lib/auth.py rhodecode/lib/db_manage.py rhodecode/lib/helpers.py rhodecode/lib/smtp_mailer.py rhodecode/lib/utils.py rhodecode/model/__init__.py rhodecode/model/comment.py rhodecode/model/db.py rhodecode/model/notification.py rhodecode/model/permission.py rhodecode/model/repo.py rhodecode/model/repo_permission.py rhodecode/model/scm.py rhodecode/model/user.py rhodecode/model/users_group.py
diffstat 17 files changed, 103 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/rhodecode/controllers/api/api.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/controllers/api/api.py	Wed Nov 23 22:46:14 2011 +0200
@@ -67,13 +67,13 @@
             return None
 
         return dict(id=user.user_id,
-                        username=user.username,
-                        firstname=user.name,
-                        lastname=user.lastname,
-                        email=user.email,
-                        active=user.active,
-                        admin=user.admin,
-                        ldap=user.ldap_dn)
+                    username=user.username,
+                    firstname=user.name,
+                    lastname=user.lastname,
+                    email=user.email,
+                    active=user.active,
+                    admin=user.admin,
+                    ldap=user.ldap_dn)
 
     @HasPermissionAllDecorator('hg.admin')
     def get_users(self, apiuser):
@@ -112,7 +112,7 @@
         :param ldap_dn:
         """
 
-        if self.get_user(apiuser, username):
+        if User.get_by_username(username):
             raise JSONRPCError("user %s already exist" % username)
 
         try:
--- a/rhodecode/controllers/changeset.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/controllers/changeset.py	Wed Nov 23 22:46:14 2011 +0200
@@ -280,17 +280,17 @@
                                         revision=revision,
                                         f_path=request.POST.get('f_path'),
                                         line_no=request.POST.get('line'))
-        Session.commit()
+        Session().commit()
         return redirect(h.url('changeset_home', repo_name=repo_name,
                               revision=revision))
 
     @jsonify
-    def delete_comment(self, comment_id):
+    def delete_comment(self, repo_name, comment_id):
         co = ChangesetComment.get(comment_id)
         owner = lambda : co.author.user_id == c.rhodecode_user.user_id
         if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner:
             ChangesetCommentsModel().delete(comment=co)
-            Session.commit()
+            Session().commit()
             return True
         else:
             raise HTTPForbidden()
--- a/rhodecode/lib/auth.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/lib/auth.py	Wed Nov 23 22:46:14 2011 +0200
@@ -54,9 +54,11 @@
 
 
 class PasswordGenerator(object):
-    """This is a simple class for generating password from
-        different sets of characters
-        usage:
+    """
+    This is a simple class for generating password from different sets of 
+    characters
+    usage::
+
         passwd_gen = PasswordGenerator()
         #print 8-letter password containing only big and small letters
             of alphabet
@@ -420,7 +422,8 @@
 
 
 class NotAnonymous(object):
-    """Must be logged in to execute this function else
+    """
+    Must be logged in to execute this function else
     redirect to login page"""
 
     def __call__(self, func):
@@ -497,7 +500,8 @@
 
 
 class HasPermissionAllDecorator(PermsDecorator):
-    """Checks for access permission for all given predicates. All of them
+    """
+    Checks for access permission for all given predicates. All of them
     have to be meet in order to fulfill the request
     """
 
@@ -508,7 +512,8 @@
 
 
 class HasPermissionAnyDecorator(PermsDecorator):
-    """Checks for access permission for any of given predicates. In order to
+    """
+    Checks for access permission for any of given predicates. In order to
     fulfill the request any of predicates must be meet
     """
 
@@ -519,7 +524,8 @@
 
 
 class HasRepoPermissionAllDecorator(PermsDecorator):
-    """Checks for access permission for all given predicates for specific
+    """
+    Checks for access permission for all given predicates for specific
     repository. All of them have to be meet in order to fulfill the request
     """
 
@@ -535,7 +541,8 @@
 
 
 class HasRepoPermissionAnyDecorator(PermsDecorator):
-    """Checks for access permission for any of given predicates for specific
+    """
+    Checks for access permission for any of given predicates for specific
     repository. In order to fulfill the request any of predicates must be meet
     """
 
--- a/rhodecode/lib/db_manage.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/lib/db_manage.py	Wed Nov 23 22:46:14 2011 +0200
@@ -168,7 +168,7 @@
         #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
         for step in upgrade_steps:
             print ('performing upgrade step %s' % step)
-            callable = getattr(UpgradeSteps(self), 'step_%s' % step)()
+            getattr(UpgradeSteps(self), 'step_%s' % step)()
 
     def fix_repo_paths(self):
         """Fixes a old rhodecode version path into new one without a '*'
--- a/rhodecode/lib/helpers.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/lib/helpers.py	Wed Nov 23 22:46:14 2011 +0200
@@ -10,7 +10,7 @@
 import math
 
 from datetime import datetime
-from pygments.formatters import HtmlFormatter
+from pygments.formatters.html import HtmlFormatter
 from pygments import highlight as code_highlight
 from pylons import url, request, config
 from pylons.i18n.translation import _, ungettext
--- a/rhodecode/lib/smtp_mailer.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/lib/smtp_mailer.py	Wed Nov 23 22:46:14 2011 +0200
@@ -151,7 +151,8 @@
                             'a dict in format {"filename":"filepath"}')
 
     def get_content(self, msg_file):
-        """Get content based on type, if content is a string do open first
+        """
+        Get content based on type, if content is a string do open first
         else just read because it's a probably open file object
 
         :param msg_file:
--- a/rhodecode/lib/utils.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/lib/utils.py	Wed Nov 23 22:46:14 2011 +0200
@@ -389,11 +389,7 @@
     if user is None:
         raise Exception('Missing administrative account !')    
     added = []
-    # fixup groups paths to new format on the fly
-    # TODO: remove this in future
-    for g in RepoGroup.query().all():
-        g.group_name = g.get_new_name(g.name)
-        sa.add(g)    
+
     for name, repo in initial_repo_list.items():
         group = map_groups(name.split(Repository.url_sep()))
         if not rm.get_by_repo_name(name, cache=False):
@@ -485,8 +481,7 @@
     install test repository into tmp dir
     """
     from rhodecode.lib.db_manage import DbManage
-    from rhodecode.tests import HG_REPO, GIT_REPO, NEW_HG_REPO, NEW_GIT_REPO, \
-        HG_FORK, GIT_FORK, TESTS_TMP_PATH
+    from rhodecode.tests import HG_REPO, TESTS_TMP_PATH
     import tarfile
     import shutil
     from os.path import abspath
--- a/rhodecode/model/__init__.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/__init__.py	Wed Nov 23 22:46:14 2011 +0200
@@ -73,7 +73,7 @@
         else:
             self.sa = meta.Session()
 
-    def __get_instance(self, cls, instance):
+    def _get_instance(self, cls, instance):
         """
         Get's instance of given cls using some simple lookup mechanism
         
--- a/rhodecode/model/comment.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/comment.py	Wed Nov 23 22:46:14 2011 +0200
@@ -41,7 +41,7 @@
 class ChangesetCommentsModel(BaseModel):
 
     def __get_changeset_comment(self, changeset_comment):
-        return self.__get_instance(ChangesetComment, changeset_comment)
+        return self._get_instance(ChangesetComment, changeset_comment)
 
     def _extract_mentions(self, s):
         user_objects = []
@@ -65,7 +65,9 @@
         """
         if text:
             repo = Repository.get(repo_id)
-            desc = repo.scm_instance.get_changeset(revision).message
+            cs = repo.scm_instance.get_changeset(revision)
+            desc = cs.message
+            author = cs.author_email
             comment = ChangesetComment()
             comment.repo = repo
             comment.user_id = user_id
@@ -90,11 +92,21 @@
                              )
             body = text
             recipients = ChangesetComment.get_users(revision=revision)
-            recipients += self._extract_mentions(body)
+            # add changeset author
+            recipients += [User.get_by_email(author)]
+
             NotificationModel().create(created_by=user_id, subject=subj,
                                    body=body, recipients=recipients,
                                    type_=Notification.TYPE_CHANGESET_COMMENT)
 
+            mention_recipients = set(self._extract_mentions(body)).difference(recipients)
+            if mention_recipients:
+                subj = _('[Mention]') + ' ' + subj
+                NotificationModel().create(created_by=user_id, subject=subj,
+                                    body = body, recipients = mention_recipients,
+                                    type_=Notification.TYPE_CHANGESET_COMMENT)
+
+            self.sa.commit()
             return comment
 
     def delete(self, comment):
--- a/rhodecode/model/db.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/db.py	Wed Nov 23 22:46:14 2011 +0200
@@ -323,6 +323,15 @@
                                     "get_api_key_%s" % api_key))
         return q.scalar()
 
+    @classmethod
+    def get_by_email(cls, email, cache=False):
+        q = cls.query().filter(cls.email == email)
+
+        if cache:
+            q = q.options(FromCache("sql_cache_short",
+                                    "get_api_key_%s" % email))
+        return q.scalar()
+
     def update_lastlogin(self):
         """Update user lastlogin"""
 
--- a/rhodecode/model/notification.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/notification.py	Wed Nov 23 22:46:14 2011 +0200
@@ -36,19 +36,15 @@
 
 log = logging.getLogger(__name__)
 
+
 class NotificationModel(BaseModel):
 
 
     def __get_user(self, user):
-        if isinstance(user, User):
-            return user
-        elif isinstance(user, basestring):
+        if isinstance(user, basestring):
             return User.get_by_username(username=user)
-        elif isinstance(user, int):
-            return User.get(user)
         else:
-            raise Exception('Unsupported user must be one of int,'
-                            'str or User object')
+            return self._get_instance(User, user)
 
     def __get_notification(self, notification):
         if isinstance(notification, Notification):
@@ -82,7 +78,9 @@
 
         recipients_objs = []
         for u in recipients:
-            recipients_objs.append(self.__get_user(u))
+            obj = self.__get_user(u)
+            if obj:
+                recipients_objs.append(obj)
         recipients_objs = set(recipients_objs)
         return Notification.create(created_by=created_by_obj, subject=subject,
                             body=body, recipients=recipients_objs,
--- a/rhodecode/model/permission.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/permission.py	Wed Nov 23 22:46:14 2011 +0200
@@ -33,16 +33,17 @@
 from rhodecode.model import BaseModel
 from rhodecode.model.db import User, Permission, UserToPerm, UserRepoToPerm
 
-
 log = logging.getLogger(__name__)
 
 
 class PermissionModel(BaseModel):
-    """Permissions model for RhodeCode
+    """
+    Permissions model for RhodeCode
     """
 
     def get_permission(self, permission_id, cache=False):
-        """Get's permissions by id
+        """
+        Get's permissions by id
 
         :param permission_id: id of permission to get from database
         :param cache: use Cache for this query
@@ -54,7 +55,8 @@
         return perm.get(permission_id)
 
     def get_permission_by_name(self, name, cache=False):
-        """Get's permissions by given name
+        """
+        Get's permissions by given name
 
         :param name: name to fetch
         :param cache: Use cache for this query
@@ -78,7 +80,7 @@
                             ' your database' % len(u2p))
 
         try:
-            #stage 1 change defaults
+            # stage 1 change defaults
             for p in u2p:
                 if p.permission.permission_name.startswith('repository.'):
                     p.permission = self.get_permission_by_name(
@@ -103,7 +105,7 @@
                                          form_result['default_perm'])
                     self.sa.add(r2p)
 
-            #stage 3 set anonymous access
+            # stage 3 set anonymous access
             if perm_user.username == 'default':
                 perm_user.active = bool(form_result['anonymous'])
                 self.sa.add(perm_user)
--- a/rhodecode/model/repo.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/repo.py	Wed Nov 23 22:46:14 2011 +0200
@@ -28,8 +28,6 @@
 import traceback
 from datetime import datetime
 
-from sqlalchemy.orm import joinedload, make_transient
-
 from vcs.utils.lazy import LazyProperty
 from vcs.backends import get_backend
 
@@ -39,7 +37,6 @@
 from rhodecode.model import BaseModel
 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
     Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup
-from rhodecode.model.user import UserModel
 
 log = logging.getLogger(__name__)
 
@@ -48,7 +45,8 @@
 
     @LazyProperty
     def repos_path(self):
-        """Get's the repositories root path from database
+        """
+        Get's the repositories root path from database
         """
 
         q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
@@ -141,10 +139,11 @@
             # update permissions
             for member, perm, member_type in form_data['perms_updates']:
                 if member_type == 'user':
+                    _member = User.get_by_username(member)
                     r2p = self.sa.query(UserRepoToPerm)\
-                            .filter(UserRepoToPerm.user == User.get_by_username(member))\
-                            .filter(UserRepoToPerm.repository == cur_repo)\
-                            .one()
+                        .filter(UserRepoToPerm.user == _member)\
+                        .filter(UserRepoToPerm.repository == cur_repo)\
+                        .one()
 
                     r2p.permission = self.sa.query(Permission)\
                                         .filter(Permission.permission_name ==
@@ -316,8 +315,8 @@
             obj = self.sa.query(UsersGroupRepoToPerm)\
                 .filter(UsersGroupRepoToPerm.repository \
                         == self.get_by_repo_name(repo_name))\
-                .filter(UsersGroupRepoToPerm.users_group_id \
- == form_data['users_group_id']).one()
+                .filter(UsersGroupRepoToPerm.users_group_id
+                        == form_data['users_group_id']).one()
             self.sa.delete(obj)
             self.sa.commit()
         except:
@@ -351,7 +350,8 @@
         from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
 
         if new_parent_id:
-            paths = RepoGroup.get(new_parent_id).full_path.split(RepoGroup.url_sep())
+            paths = RepoGroup.get(new_parent_id)\
+                .full_path.split(RepoGroup.url_sep())
             new_parent_path = os.sep.join(paths)
         else:
             new_parent_path = ''
--- a/rhodecode/model/repo_permission.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/repo_permission.py	Wed Nov 23 22:46:14 2011 +0200
@@ -24,12 +24,14 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import logging
-from rhodecode.model.db import BaseModel, UserRepoToPerm, Permission
-from rhodecode.model.meta import Session
+from rhodecode.model import BaseModel
+from rhodecode.model.db import UserRepoToPerm, Permission
 
 log = logging.getLogger(__name__)
 
+
 class RepositoryPermissionModel(BaseModel):
+
     def get_user_permission(self, repository, user):
         return UserRepoToPerm.query() \
                 .filter(UserRepoToPerm.user == user) \
@@ -47,14 +49,14 @@
             p.user = user
             p.repository = repository
             p.permission = permission
-            Session.add(p)
-        Session.commit()
+            self.sa.add(p)
+        self.sa.commit()
 
     def delete_user_permission(self, repository, user):
         current = self.get_user_permission(repository, user)
         if current:
-            Session.delete(current)
-            Session.commit()
+            self.sa.delete(current)
+            self.sa.commit()
 
     def update_or_delete_user_permission(self, repository, user, permission):
         if permission:
--- a/rhodecode/model/scm.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/scm.py	Wed Nov 23 22:46:14 2011 +0200
@@ -27,8 +27,6 @@
 import traceback
 import logging
 
-from sqlalchemy.exc import DatabaseError
-
 from vcs import get_backend
 from vcs.exceptions import RepositoryError
 from vcs.utils.lazy import LazyProperty
@@ -119,12 +117,14 @@
             yield tmp_d
 
 class ScmModel(BaseModel):
-    """Generic Scm Model
+    """
+    Generic Scm Model
     """
 
     @LazyProperty
     def repos_path(self):
-        """Get's the repositories root path from database
+        """
+        Get's the repositories root path from database
         """
 
         q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
@@ -132,7 +132,8 @@
         return q.ui_value
 
     def repo_scan(self, repos_path=None):
-        """Listing of repositories in given path. This path should not be a
+        """
+        Listing of repositories in given path. This path should not be a
         repository itself. Return a dictionary of repository objects
 
         :param repos_path: path to directory containing repositories
@@ -147,11 +148,11 @@
         repos_list = {}
 
         for name, path in get_filesystem_repos(repos_path, recursive=True):
-            
+
             # name need to be decomposed and put back together using the /
             # since this is internal storage separator for rhodecode
             name = Repository.url_sep().join(name.split(os.sep))
-            
+
             try:
                 if name in repos_list:
                     raise RepositoryError('Duplicate repository name %s '
@@ -198,7 +199,7 @@
         :param repo_name: this repo that should invalidation take place
         """
         CacheInvalidation.set_invalidate(repo_name)
-        CacheInvalidation.set_invalidate(repo_name+"_README")
+        CacheInvalidation.set_invalidate(repo_name + "_README")
 
     def toggle_following_repo(self, follow_repo_id, user_id):
 
--- a/rhodecode/model/user.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/user.py	Wed Nov 23 22:46:14 2011 +0200
@@ -50,6 +50,7 @@
 
 
 class UserModel(BaseModel):
+
     def get(self, user_id, cache=False):
         user = self.sa.query(User)
         if cache:
--- a/rhodecode/model/users_group.py	Wed Nov 23 22:26:54 2011 +0200
+++ b/rhodecode/model/users_group.py	Wed Nov 23 22:46:14 2011 +0200
@@ -26,22 +26,21 @@
 import logging
 import traceback
 
-from rhodecode.lib.caching_query import FromCache
-
 from rhodecode.model import BaseModel
 from rhodecode.model.db import UsersGroupMember, UsersGroup
 
 log = logging.getLogger(__name__)
 
+
 class UsersGroupModel(BaseModel):
 
     def __get_users_group(self, users_group):
-        return self.__get_instance(UsersGroup, users_group)
+        return self._get_instance(UsersGroup, users_group)
 
-    def get(self, users_group_id, cache = False):
+    def get(self, users_group_id, cache=False):
         return UsersGroup.get(users_group_id)
 
-    def get_by_name(self, name, cache = False, case_insensitive = False):
+    def get_by_name(self, name, cache=False, case_insensitive=False):
         return UsersGroup.get_by_group_name(name, cache, case_insensitive)
 
     def create(self, form_data):