##// END OF EJS Templates
compare: move get_changesets to compare controller where it is used - 2nd half that was lost in 6c79bfcd3b54...
Mads Kiilerich -
r3754:8beaaea7 beta
parent child Browse files
Show More
@@ -1,256 +1,158 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 datetime
28 import re
29 28
30 29 from pylons.i18n.translation import _
31 30
32 31 from rhodecode.model.meta import Session
33 from rhodecode.lib import helpers as h, unionrepo
32 from rhodecode.lib import helpers as h
34 33 from rhodecode.model import BaseModel
35 34 from rhodecode.model.db import PullRequest, PullRequestReviewers, Notification,\
36 35 ChangesetStatus
37 36 from rhodecode.model.notification import NotificationModel
38 37 from rhodecode.lib.utils2 import safe_unicode
39 38
40 from rhodecode.lib.vcs.utils.hgcompat import scmutil
41 from rhodecode.lib.vcs.utils import safe_str
42 39
43 40 log = logging.getLogger(__name__)
44 41
45 42
46 43 class PullRequestModel(BaseModel):
47 44
48 45 cls = PullRequest
49 46
50 47 def __get_pull_request(self, pull_request):
51 48 return self._get_instance(PullRequest, pull_request)
52 49
53 50 def get_all(self, repo):
54 51 repo = self._get_repo(repo)
55 52 return PullRequest.query()\
56 53 .filter(PullRequest.other_repo == repo)\
57 54 .order_by(PullRequest.created_on.desc())\
58 55 .all()
59 56
60 57 def create(self, created_by, org_repo, org_ref, other_repo, other_ref,
61 58 revisions, reviewers, title, description=None):
62 59 from rhodecode.model.changeset_status import ChangesetStatusModel
63 60
64 61 created_by_user = self._get_user(created_by)
65 62 org_repo = self._get_repo(org_repo)
66 63 other_repo = self._get_repo(other_repo)
67 64
68 65 new = PullRequest()
69 66 new.org_repo = org_repo
70 67 new.org_ref = org_ref
71 68 new.other_repo = other_repo
72 69 new.other_ref = other_ref
73 70 new.revisions = revisions
74 71 new.title = title
75 72 new.description = description
76 73 new.author = created_by_user
77 74 Session().add(new)
78 75 Session().flush()
79 76 #members
80 77 for member in set(reviewers):
81 78 _usr = self._get_user(member)
82 79 reviewer = PullRequestReviewers(_usr, new)
83 80 Session().add(reviewer)
84 81
85 82 #reset state to under-review
86 83 ChangesetStatusModel().set_status(
87 84 repo=org_repo,
88 85 status=ChangesetStatus.STATUS_UNDER_REVIEW,
89 86 user=created_by_user,
90 87 pull_request=new
91 88 )
92 89 revision_data = [(x.raw_id, x.message)
93 90 for x in map(org_repo.get_changeset, revisions)]
94 91 #notification to reviewers
95 92 notif = NotificationModel()
96 93
97 94 pr_url = h.url('pullrequest_show', repo_name=other_repo.repo_name,
98 95 pull_request_id=new.pull_request_id,
99 96 qualified=True,
100 97 )
101 98 subject = safe_unicode(
102 99 h.link_to(
103 100 _('%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s') % \
104 101 {'user': created_by_user.username,
105 102 'pr_title': new.title,
106 103 'pr_id': new.pull_request_id},
107 104 pr_url
108 105 )
109 106 )
110 107 body = description
111 108 kwargs = {
112 109 'pr_title': title,
113 110 'pr_user_created': h.person(created_by_user.email),
114 111 'pr_repo_url': h.url('summary_home', repo_name=other_repo.repo_name,
115 112 qualified=True,),
116 113 'pr_url': pr_url,
117 114 'pr_revisions': revision_data
118 115 }
119 116
120 117 notif.create(created_by=created_by_user, subject=subject, body=body,
121 118 recipients=reviewers,
122 119 type_=Notification.TYPE_PULL_REQUEST, email_kwargs=kwargs)
123 120 return new
124 121
125 122 def update_reviewers(self, pull_request, reviewers_ids):
126 123 reviewers_ids = set(reviewers_ids)
127 124 pull_request = self.__get_pull_request(pull_request)
128 125 current_reviewers = PullRequestReviewers.query()\
129 126 .filter(PullRequestReviewers.pull_request==
130 127 pull_request)\
131 128 .all()
132 129 current_reviewers_ids = set([x.user.user_id for x in current_reviewers])
133 130
134 131 to_add = reviewers_ids.difference(current_reviewers_ids)
135 132 to_remove = current_reviewers_ids.difference(reviewers_ids)
136 133
137 134 log.debug("Adding %s reviewers" % to_add)
138 135 log.debug("Removing %s reviewers" % to_remove)
139 136
140 137 for uid in to_add:
141 138 _usr = self._get_user(uid)
142 139 reviewer = PullRequestReviewers(_usr, pull_request)
143 140 Session().add(reviewer)
144 141
145 142 for uid in to_remove:
146 143 reviewer = PullRequestReviewers.query()\
147 144 .filter(PullRequestReviewers.user_id==uid,
148 145 PullRequestReviewers.pull_request==pull_request)\
149 146 .scalar()
150 147 if reviewer:
151 148 Session().delete(reviewer)
152 149
153 150 def delete(self, pull_request):
154 151 pull_request = self.__get_pull_request(pull_request)
155 152 Session().delete(pull_request)
156 153
157 154 def close_pull_request(self, pull_request):
158 155 pull_request = self.__get_pull_request(pull_request)
159 156 pull_request.status = PullRequest.STATUS_CLOSED
160 157 pull_request.updated_on = datetime.datetime.now()
161 158 Session().add(pull_request)
162
163 def _get_changesets(self, alias, org_repo, org_ref, other_repo, other_ref, merge):
164 """
165 Returns a list of changesets that can be merged from org_repo@org_ref
166 to other_repo@other_ref ... and the ancestor that would be used for merge
167
168 :param org_repo:
169 :param org_ref:
170 :param other_repo:
171 :param other_ref:
172 :param tmp:
173 """
174
175 ancestor = None
176
177 if alias == 'hg':
178 # lookup up the exact node id
179 _revset_predicates = {
180 'branch': 'branch',
181 'book': 'bookmark',
182 'tag': 'tag',
183 'rev': 'id',
184 }
185
186 org_rev_spec = "max(%s('%s'))" % (_revset_predicates[org_ref[0]],
187 safe_str(org_ref[1]))
188 org_revs = scmutil.revrange(org_repo._repo, [org_rev_spec])
189 org_rev = org_repo._repo[org_revs[-1] if org_revs else -1].hex()
190
191 other_rev_spec = "max(%s('%s'))" % (_revset_predicates[other_ref[0]],
192 safe_str(other_ref[1]))
193 other_revs = scmutil.revrange(other_repo._repo, [other_rev_spec])
194 other_rev = other_repo._repo[other_revs[-1] if other_revs else -1].hex()
195
196 #case two independent repos
197 if org_repo != other_repo:
198 hgrepo = unionrepo.unionrepository(other_repo.baseui,
199 other_repo.path,
200 org_repo.path)
201 # all the changesets we are looking for will be in other_repo,
202 # so rev numbers from hgrepo can be used in other_repo
203
204 #no remote compare do it on the same repository
205 else:
206 hgrepo = other_repo._repo
207
208 if merge:
209 revs = ["ancestors(id('%s')) and not ancestors(id('%s')) and not id('%s')" %
210 (other_rev, org_rev, org_rev)]
211
212 ancestors = scmutil.revrange(hgrepo,
213 ["ancestor(id('%s'), id('%s'))" % (org_rev, other_rev)])
214 if ancestors:
215 # pick arbitrary ancestor - but there is usually only one
216 ancestor = hgrepo[ancestors[0]].hex()
217 else:
218 # TODO: have both + and - changesets
219 revs = ["id('%s') :: id('%s') - id('%s')" %
220 (org_rev, other_rev, org_rev)]
221
222 changesets = [other_repo.get_changeset(cs)
223 for cs in scmutil.revrange(hgrepo, revs)]
224
225 elif alias == 'git':
226 assert org_repo == other_repo, (org_repo, other_repo) # no git support for different repos
227 so, se = org_repo.run_git_command(
228 'log --reverse --pretty="format: %%H" -s -p %s..%s' % (org_ref[1],
229 other_ref[1])
230 )
231 changesets = [org_repo.get_changeset(cs)
232 for cs in re.findall(r'[0-9a-fA-F]{40}', so)]
233
234 return changesets, ancestor
235
236 def get_compare_data(self, org_repo, org_ref, other_repo, other_ref, merge):
237 """
238 Returns incoming changesets for mercurial repositories
239
240 :param org_repo:
241 :param org_ref:
242 :param other_repo:
243 :param other_ref:
244 """
245
246 if len(org_ref) != 2 or not isinstance(org_ref, (list, tuple)):
247 raise Exception('org_ref must be a two element list/tuple')
248
249 if len(other_ref) != 2 or not isinstance(org_ref, (list, tuple)):
250 raise Exception('other_ref must be a two element list/tuple')
251
252 cs_ranges, ancestor = self._get_changesets(org_repo.scm_instance.alias,
253 org_repo.scm_instance, org_ref,
254 other_repo.scm_instance, other_ref,
255 merge)
256 return cs_ranges, ancestor
General Comments 0
You need to be logged in to leave comments. Login now