##// END OF EJS Templates
fix order of pull-requests in show all page
marcink -
r3262:14e9a06c beta
parent child Browse files
Show More
@@ -1,252 +1,255 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.pull_request
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 pull request model for RhodeCode
7 7
8 8 :created_on: Jun 6, 2012
9 9 :author: marcink
10 10 :copyright: (C) 2012-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import binascii
28 28 import datetime
29 29 import re
30 30
31 31 from pylons.i18n.translation import _
32 32
33 33 from rhodecode.model.meta import Session
34 34 from rhodecode.lib import helpers as h
35 35 from rhodecode.model import BaseModel
36 36 from rhodecode.model.db import PullRequest, PullRequestReviewers, Notification,\
37 37 ChangesetStatus
38 38 from rhodecode.model.notification import NotificationModel
39 39 from rhodecode.lib.utils2 import safe_unicode
40 40
41 41 from rhodecode.lib.vcs.utils.hgcompat import discovery, localrepo, scmutil, \
42 42 findcommonoutgoing
43 43
44 44 log = logging.getLogger(__name__)
45 45
46 46
47 47 class PullRequestModel(BaseModel):
48 48
49 49 cls = PullRequest
50 50
51 51 def __get_pull_request(self, pull_request):
52 52 return self._get_instance(PullRequest, pull_request)
53 53
54 54 def get_all(self, repo):
55 55 repo = self._get_repo(repo)
56 return PullRequest.query().filter(PullRequest.other_repo == repo).all()
56 return PullRequest.query()\
57 .filter(PullRequest.other_repo == repo)\
58 .order_by(PullRequest.created_on)\
59 .all()
57 60
58 61 def create(self, created_by, org_repo, org_ref, other_repo, other_ref,
59 62 revisions, reviewers, title, description=None):
60 63 from rhodecode.model.changeset_status import ChangesetStatusModel
61 64
62 65 created_by_user = self._get_user(created_by)
63 66 org_repo = self._get_repo(org_repo)
64 67 other_repo = self._get_repo(other_repo)
65 68
66 69 new = PullRequest()
67 70 new.org_repo = org_repo
68 71 new.org_ref = org_ref
69 72 new.other_repo = other_repo
70 73 new.other_ref = other_ref
71 74 new.revisions = revisions
72 75 new.title = title
73 76 new.description = description
74 77 new.author = created_by_user
75 78 self.sa.add(new)
76 79 Session().flush()
77 80 #members
78 81 for member in reviewers:
79 82 _usr = self._get_user(member)
80 83 reviewer = PullRequestReviewers(_usr, new)
81 84 self.sa.add(reviewer)
82 85
83 86 #reset state to under-review
84 87 ChangesetStatusModel().set_status(
85 88 repo=org_repo,
86 89 status=ChangesetStatus.STATUS_UNDER_REVIEW,
87 90 user=created_by_user,
88 91 pull_request=new
89 92 )
90 93
91 94 #notification to reviewers
92 95 notif = NotificationModel()
93 96
94 97 pr_url = h.url('pullrequest_show', repo_name=other_repo.repo_name,
95 98 pull_request_id=new.pull_request_id,
96 99 qualified=True,
97 100 )
98 101 subject = safe_unicode(
99 102 h.link_to(
100 103 _('%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s') % \
101 104 {'user': created_by_user.username,
102 105 'pr_title': new.title,
103 106 'pr_id': new.pull_request_id},
104 107 pr_url
105 108 )
106 109 )
107 110 body = description
108 111 kwargs = {
109 112 'pr_title': title,
110 113 'pr_user_created': h.person(created_by_user.email),
111 114 'pr_repo_url': h.url('summary_home', repo_name=other_repo.repo_name,
112 115 qualified=True,),
113 116 'pr_url': pr_url,
114 117 'pr_revisions': revisions
115 118 }
116 119 notif.create(created_by=created_by_user, subject=subject, body=body,
117 120 recipients=reviewers,
118 121 type_=Notification.TYPE_PULL_REQUEST, email_kwargs=kwargs)
119 122 return new
120 123
121 124 def update_reviewers(self, pull_request, reviewers_ids):
122 125 reviewers_ids = set(reviewers_ids)
123 126 pull_request = self.__get_pull_request(pull_request)
124 127 current_reviewers = PullRequestReviewers.query()\
125 128 .filter(PullRequestReviewers.pull_request==
126 129 pull_request)\
127 130 .all()
128 131 current_reviewers_ids = set([x.user.user_id for x in current_reviewers])
129 132
130 133 to_add = reviewers_ids.difference(current_reviewers_ids)
131 134 to_remove = current_reviewers_ids.difference(reviewers_ids)
132 135
133 136 log.debug("Adding %s reviewers" % to_add)
134 137 log.debug("Removing %s reviewers" % to_remove)
135 138
136 139 for uid in to_add:
137 140 _usr = self._get_user(uid)
138 141 reviewer = PullRequestReviewers(_usr, pull_request)
139 142 self.sa.add(reviewer)
140 143
141 144 for uid in to_remove:
142 145 reviewer = PullRequestReviewers.query()\
143 146 .filter(PullRequestReviewers.user_id==uid,
144 147 PullRequestReviewers.pull_request==pull_request)\
145 148 .scalar()
146 149 if reviewer:
147 150 self.sa.delete(reviewer)
148 151
149 152 def delete(self, pull_request):
150 153 pull_request = self.__get_pull_request(pull_request)
151 154 Session().delete(pull_request)
152 155
153 156 def close_pull_request(self, pull_request):
154 157 pull_request = self.__get_pull_request(pull_request)
155 158 pull_request.status = PullRequest.STATUS_CLOSED
156 159 pull_request.updated_on = datetime.datetime.now()
157 160 self.sa.add(pull_request)
158 161
159 162 def _get_changesets(self, alias, org_repo, org_ref, other_repo, other_ref):
160 163 """
161 164 Returns a list of changesets that are incoming from org_repo@org_ref
162 165 to other_repo@other_ref
163 166
164 167 :param org_repo:
165 168 :param org_ref:
166 169 :param other_repo:
167 170 :param other_ref:
168 171 :param tmp:
169 172 """
170 173
171 174 changesets = []
172 175 #case two independent repos
173 176 if org_repo != other_repo:
174 177 revs = [
175 178 org_repo._repo.lookup(org_ref[1]),
176 179 org_repo._repo.lookup(other_ref[1]),
177 180 ]
178 181
179 182 obj = findcommonoutgoing(org_repo._repo,
180 183 localrepo.locallegacypeer(other_repo._repo.local()),
181 184 revs,
182 185 force=True)
183 186 revs = obj.missing
184 187
185 188 for cs in map(binascii.hexlify, revs):
186 189 _cs = org_repo.get_changeset(cs)
187 190 changesets.append(_cs)
188 191 # in case we have revisions filter out the ones not in given range
189 192 if org_ref[0] == 'rev' and other_ref[0] == 'rev':
190 193 revs = [x.raw_id for x in changesets]
191 194 start = org_ref[1]
192 195 stop = other_ref[1]
193 196 changesets = changesets[revs.index(start):revs.index(stop) + 1]
194 197 else:
195 198 #no remote compare do it on the same repository
196 199 if alias == 'hg':
197 200 _revset_predicates = {
198 201 'branch': 'branch',
199 202 'book': 'bookmark',
200 203 'tag': 'tag',
201 204 'rev': 'id',
202 205 }
203 206
204 207 revs = [
205 208 "ancestors(%s('%s')) and not ancestors(%s('%s'))" % (
206 209 _revset_predicates[other_ref[0]], other_ref[1],
207 210 _revset_predicates[org_ref[0]], org_ref[1],
208 211 )
209 212 ]
210 213
211 214 out = scmutil.revrange(org_repo._repo, revs)
212 215 for cs in (out):
213 216 changesets.append(org_repo.get_changeset(cs))
214 217 elif alias == 'git':
215 218 so, se = org_repo.run_git_command(
216 219 'log --reverse --pretty="format: %%H" -s -p %s..%s' % (org_ref[1],
217 220 other_ref[1])
218 221 )
219 222 ids = re.findall(r'[0-9a-fA-F]{40}', so)
220 223 for cs in (ids):
221 224 changesets.append(org_repo.get_changeset(cs))
222 225
223 226 return changesets
224 227
225 228 def get_compare_data(self, org_repo, org_ref, other_repo, other_ref):
226 229 """
227 230 Returns incomming changesets for mercurial repositories
228 231
229 232 :param org_repo:
230 233 :type org_repo:
231 234 :param org_ref:
232 235 :type org_ref:
233 236 :param other_repo:
234 237 :type other_repo:
235 238 :param other_ref:
236 239 :type other_ref:
237 240 """
238 241
239 242 if len(org_ref) != 2 or not isinstance(org_ref, (list, tuple)):
240 243 raise Exception('org_ref must be a two element list/tuple')
241 244
242 245 if len(other_ref) != 2 or not isinstance(org_ref, (list, tuple)):
243 246 raise Exception('other_ref must be a two element list/tuple')
244 247
245 248 org_repo_scm = org_repo.scm_instance
246 249 other_repo_scm = other_repo.scm_instance
247 250
248 251 alias = org_repo.scm_instance.alias
249 252 cs_ranges = self._get_changesets(alias,
250 253 org_repo_scm, org_ref,
251 254 other_repo_scm, other_ref)
252 255 return cs_ranges
General Comments 0
You need to be logged in to leave comments. Login now