Files
@ 0c3fa09671cd
Branch filter:
Location: kallithea/rhodecode/model/pull_request.py - annotation
0c3fa09671cd
10.2 KiB
text/x-python
fixes #682 Translation difficult for multi-line text
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | f29469677319 f29469677319 58c529332e7e 58c529332e7e f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 3bf057a7f7e8 58c529332e7e bf96fd1920c1 7b092b919f4f f29469677319 f29469677319 7b092b919f4f f29469677319 f29469677319 7b092b919f4f f29469677319 f29469677319 f29469677319 69420c48a0e6 69420c48a0e6 3bf057a7f7e8 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 17893d61792a 17893d61792a 58c529332e7e 58c529332e7e 58c529332e7e 1bc579bcd67a 1bc579bcd67a 1bc579bcd67a 1bc579bcd67a f29469677319 f29469677319 1c2ba03c42b4 1bc579bcd67a 1c2ba03c42b4 1c2ba03c42b4 f29469677319 f29469677319 1c2ba03c42b4 f29469677319 1c2ba03c42b4 f29469677319 f29469677319 f29469677319 f29469677319 1bc579bcd67a f29469677319 1c2ba03c42b4 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 1bc579bcd67a 493646d3146f 493646d3146f 493646d3146f 493646d3146f f29469677319 f29469677319 f29469677319 f29469677319 f29469677319 493646d3146f f29469677319 f29469677319 f29469677319 493646d3146f 493646d3146f 493646d3146f 493646d3146f 493646d3146f 493646d3146f 493646d3146f 493646d3146f 1c2ba03c42b4 f29469677319 493646d3146f f29469677319 3bf057a7f7e8 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 3f50a5e8fc4d 49a4864b11c1 49a4864b11c1 49a4864b11c1 49a4864b11c1 58c529332e7e 58c529332e7e 58c529332e7e 58c529332e7e 58c529332e7e 58c529332e7e bf96fd1920c1 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 c2a206162062 3bf057a7f7e8 3bf057a7f7e8 2b6939a77052 c2a206162062 c2a206162062 c2a206162062 c2a206162062 c2a206162062 c2a206162062 69420c48a0e6 4a5c56da2603 c2a206162062 4a5c56da2603 69420c48a0e6 3bf057a7f7e8 c2a206162062 c2a206162062 c2a206162062 5deb16cd2802 5deb16cd2802 5deb16cd2802 5deb16cd2802 5deb16cd2802 5deb16cd2802 3bf057a7f7e8 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 f79320e47e99 bf96fd1920c1 bf96fd1920c1 16af24982e30 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 f79320e47e99 bf96fd1920c1 16af24982e30 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 16af24982e30 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 16af24982e30 bf96fd1920c1 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 2b6939a77052 2b6939a77052 2b6939a77052 2b6939a77052 2b6939a77052 2b6939a77052 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 4a5c56da2603 2b6939a77052 2b6939a77052 3bf057a7f7e8 2b6939a77052 2b6939a77052 c2a206162062 c2a206162062 4a5c56da2603 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 bf96fd1920c1 bf96fd1920c1 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 3bf057a7f7e8 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 bf96fd1920c1 2b6939a77052 3bf057a7f7e8 | # -*- coding: utf-8 -*-
"""
rhodecode.model.pull_request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pull request model for RhodeCode
:created_on: Jun 6, 2012
:author: marcink
:copyright: (C) 2012-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 binascii
import datetime
import re
from pylons.i18n.translation import _
from rhodecode.model.meta import Session
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, \
findcommonoutgoing
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},
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, 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, alias, 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:
:param org_ref:
:param other_repo:
:param other_ref:
:param tmp:
"""
changesets = []
#case two independent repos
common, incoming, rheads = discovery_data
if org_repo != other_repo:
revs = [
org_repo._repo.lookup(org_ref[1]),
org_repo._repo.lookup(other_ref[1]),
]
obj = findcommonoutgoing(org_repo._repo,
localrepo.locallegacypeer(other_repo._repo.local()),
revs,
force=True)
revs = obj.missing
for cs in map(binascii.hexlify, revs):
_cs = org_repo.get_changeset(cs)
changesets.append(_cs)
# in case we have revisions filter out the ones not in given range
if org_ref[0] == 'rev' and other_ref[0] == 'rev':
revs = [x.raw_id for x in changesets]
start = org_ref[1]
stop = other_ref[1]
changesets = changesets[revs.index(start):revs.index(stop) + 1]
else:
#no remote compare do it on the same repository
if alias == 'hg':
_revset_predicates = {
'branch': 'branch',
'book': 'bookmark',
'tag': 'tag',
'rev': 'id',
}
revs = [
"ancestors(%s('%s')) and not ancestors(%s('%s'))" % (
_revset_predicates[other_ref[0]], other_ref[1],
_revset_predicates[org_ref[0]], org_ref[1],
)
]
out = scmutil.revrange(org_repo._repo, revs)
for cs in (out):
changesets.append(org_repo.get_changeset(cs))
elif alias == 'git':
so, se = org_repo.run_git_command(
'log --reverse --pretty="format: %%H" -s -p %s..%s' % (org_ref[1],
other_ref[1])
)
ids = re.findall(r'[0-9a-fA-F]{40}', so)
for cs in (ids):
changesets.append(org_repo.get_changeset(cs))
return changesets
def _get_discovery(self, org_repo, org_ref, other_repo, other_ref):
"""
Get's mercurial discovery data used to calculate difference between
repos and refs
:param org_repo:
:type org_repo:
:param org_ref:
:type org_ref:
:param other_repo:
:type other_repo:
:param other_ref:
:type other_ref:
"""
_org_repo = org_repo._repo
org_rev_type, org_rev = org_ref
_other_repo = other_repo._repo
other_rev_type, other_rev = other_ref
log.debug('Doing discovery for %s@%s vs %s@%s' % (
org_repo, org_ref, other_repo, other_ref)
)
#log.debug('Filter heads are %s[%s]' % ('', org_ref[1]))
org_peer = localrepo.locallegacypeer(_org_repo.local())
tmp = discovery.findcommonincoming(
repo=_other_repo, # other_repo we check for incoming
remote=org_peer, # org_repo source for incoming
# heads=[_other_repo[other_rev].node(),
# _org_repo[org_rev].node()],
force=True
)
return tmp
def get_compare_data(self, org_repo, org_ref, other_repo, other_ref):
"""
Returns a tuple of incomming changesets, and discoverydata cache for
mercurial repositories
:param org_repo:
:type org_repo:
:param org_ref:
:type org_ref:
:param other_repo:
:type other_repo:
:param other_ref:
:type other_ref:
"""
if len(org_ref) != 2 or not isinstance(org_ref, (list, tuple)):
raise Exception('org_ref must be a two element list/tuple')
if len(other_ref) != 2 or not isinstance(org_ref, (list, tuple)):
raise Exception('other_ref must be a two element list/tuple')
org_repo_scm = org_repo.scm_instance
other_repo_scm = other_repo.scm_instance
alias = org_repo.scm_instance.alias
discovery_data = [None, None, None]
if alias == 'hg':
discovery_data = self._get_discovery(org_repo_scm, org_ref,
other_repo_scm, other_ref)
cs_ranges = self._get_changesets(alias,
org_repo_scm, org_ref,
other_repo_scm, other_ref,
discovery_data)
return cs_ranges, discovery_data
|