|
|
# -*- coding: utf-8 -*-
|
|
|
"""
|
|
|
rhodecode.model.comment
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
comments model for RhodeCode
|
|
|
|
|
|
:created_on: Nov 11, 2011
|
|
|
:author: marcink
|
|
|
:copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
|
|
|
:license: GPLv3, see COPYING for more details.
|
|
|
"""
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
# (at your option) any later version.
|
|
|
#
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
# GNU General Public License for more details.
|
|
|
#
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
import logging
|
|
|
import traceback
|
|
|
|
|
|
from pylons.i18n.translation import _
|
|
|
from sqlalchemy.util.compat import defaultdict
|
|
|
|
|
|
from rhodecode.lib import extract_mentioned_users
|
|
|
from rhodecode.lib import helpers as h
|
|
|
from rhodecode.model import BaseModel
|
|
|
from rhodecode.model.db import ChangesetComment, User, Repository, Notification
|
|
|
from rhodecode.model.notification import NotificationModel
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
class ChangesetCommentsModel(BaseModel):
|
|
|
|
|
|
def __get_changeset_comment(self, changeset_comment):
|
|
|
return self._get_instance(ChangesetComment, changeset_comment)
|
|
|
|
|
|
def _extract_mentions(self, s):
|
|
|
user_objects = []
|
|
|
for username in extract_mentioned_users(s):
|
|
|
user_obj = User.get_by_username(username, case_insensitive=True)
|
|
|
if user_obj:
|
|
|
user_objects.append(user_obj)
|
|
|
return user_objects
|
|
|
|
|
|
def create(self, text, repo_id, user_id, revision, f_path=None,
|
|
|
line_no=None):
|
|
|
"""
|
|
|
Creates new comment for changeset
|
|
|
|
|
|
:param text:
|
|
|
:param repo_id:
|
|
|
:param user_id:
|
|
|
:param revision:
|
|
|
:param f_path:
|
|
|
:param line_no:
|
|
|
"""
|
|
|
if text:
|
|
|
repo = Repository.get(repo_id)
|
|
|
cs = repo.scm_instance.get_changeset(revision)
|
|
|
desc = cs.message
|
|
|
author_email = cs.author_email
|
|
|
comment = ChangesetComment()
|
|
|
comment.repo = repo
|
|
|
comment.user_id = user_id
|
|
|
comment.revision = revision
|
|
|
comment.text = text
|
|
|
comment.f_path = f_path
|
|
|
comment.line_no = line_no
|
|
|
|
|
|
self.sa.add(comment)
|
|
|
self.sa.flush()
|
|
|
|
|
|
# make notification
|
|
|
line = ''
|
|
|
if line_no:
|
|
|
line = _('on line %s') % line_no
|
|
|
subj = h.link_to('Re commit: %(commit_desc)s %(line)s' % \
|
|
|
{'commit_desc': desc, 'line': line},
|
|
|
h.url('changeset_home', repo_name=repo.repo_name,
|
|
|
revision=revision,
|
|
|
anchor='comment-%s' % comment.comment_id,
|
|
|
qualified=True,
|
|
|
)
|
|
|
)
|
|
|
body = text
|
|
|
|
|
|
# get the current participants of this changeset
|
|
|
recipients = ChangesetComment.get_users(revision=revision)
|
|
|
|
|
|
# add changeset author if it's in rhodecode system
|
|
|
recipients += [User.get_by_email(author_email)]
|
|
|
|
|
|
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
|
|
|
)
|
|
|
|
|
|
return comment
|
|
|
|
|
|
def delete(self, comment):
|
|
|
"""
|
|
|
Deletes given comment
|
|
|
|
|
|
:param comment_id:
|
|
|
"""
|
|
|
comment = self.__get_changeset_comment(comment)
|
|
|
self.sa.delete(comment)
|
|
|
|
|
|
return comment
|
|
|
|
|
|
def get_comments(self, repo_id, revision):
|
|
|
return ChangesetComment.query()\
|
|
|
.filter(ChangesetComment.repo_id == repo_id)\
|
|
|
.filter(ChangesetComment.revision == revision)\
|
|
|
.filter(ChangesetComment.line_no == None)\
|
|
|
.filter(ChangesetComment.f_path == None).all()
|
|
|
|
|
|
def get_inline_comments(self, repo_id, revision):
|
|
|
comments = self.sa.query(ChangesetComment)\
|
|
|
.filter(ChangesetComment.repo_id == repo_id)\
|
|
|
.filter(ChangesetComment.revision == revision)\
|
|
|
.filter(ChangesetComment.line_no != None)\
|
|
|
.filter(ChangesetComment.f_path != None).all()
|
|
|
|
|
|
paths = defaultdict(lambda: defaultdict(list))
|
|
|
|
|
|
for co in comments:
|
|
|
paths[co.f_path][co.line_no].append(co)
|
|
|
return paths.items()
|
|
|
|