Show More
@@ -0,0 +1,31 b'' | |||||
|
1 | <%inherit file="/base/base.html"/> | |||
|
2 | ||||
|
3 | <%def name="title()"> | |||
|
4 | ${c.repo_name} ${_('All pull requests')} | |||
|
5 | </%def> | |||
|
6 | ||||
|
7 | <%def name="breadcrumbs_links()"> | |||
|
8 | ${h.link_to(u'Home',h.url('/'))} | |||
|
9 | » | |||
|
10 | ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))} | |||
|
11 | » | |||
|
12 | ${_('All pull requests')} | |||
|
13 | </%def> | |||
|
14 | ||||
|
15 | <%def name="main()"> | |||
|
16 | ||||
|
17 | <div class="box"> | |||
|
18 | <!-- box / title --> | |||
|
19 | <div class="title"> | |||
|
20 | ${self.breadcrumbs()} | |||
|
21 | </div> | |||
|
22 | ||||
|
23 | %for pr in c.pull_requests: | |||
|
24 | <a href="${h.url('pullrequest_show',repo_name=c.repo_name,pull_request_id=pr.pull_request_id)}">#${pr.pull_request_id}</a> | |||
|
25 | %endfor | |||
|
26 | ||||
|
27 | </div> | |||
|
28 | ||||
|
29 | <script type="text/javascript"></script> | |||
|
30 | ||||
|
31 | </%def> |
@@ -451,6 +451,12 b' def make_map(config):' | |||||
451 | action='show', conditions=dict(function=check_repo, |
|
451 | action='show', conditions=dict(function=check_repo, | |
452 | method=["GET"])) |
|
452 | method=["GET"])) | |
453 |
|
453 | |||
|
454 | rmap.connect('pullrequest_show_all', | |||
|
455 | '/{repo_name:.*}/pull-request', | |||
|
456 | controller='pullrequests', | |||
|
457 | action='show_all', conditions=dict(function=check_repo, | |||
|
458 | method=["GET"])) | |||
|
459 | ||||
454 | rmap.connect('summary_home', '/{repo_name:.*}/summary', |
|
460 | rmap.connect('summary_home', '/{repo_name:.*}/summary', | |
455 | controller='summary', conditions=dict(function=check_repo)) |
|
461 | controller='summary', conditions=dict(function=check_repo)) | |
456 |
|
462 |
@@ -295,7 +295,7 b' class ChangesetController(BaseRepoContro' | |||||
295 | ) |
|
295 | ) | |
296 |
|
296 | |||
297 | # count inline comments |
|
297 | # count inline comments | |
298 | for _, lines in c.inline_comments: |
|
298 | for __, lines in c.inline_comments: | |
299 | for comments in lines.values(): |
|
299 | for comments in lines.values(): | |
300 | c.inline_cnt += len(comments) |
|
300 | c.inline_cnt += len(comments) | |
301 |
|
301 |
@@ -24,6 +24,9 b'' | |||||
24 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
24 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
25 | import logging |
|
25 | import logging | |
26 | import traceback |
|
26 | import traceback | |
|
27 | import binascii | |||
|
28 | ||||
|
29 | from webob.exc import HTTPNotFound | |||
27 |
|
30 | |||
28 | from pylons import request, response, session, tmpl_context as c, url |
|
31 | from pylons import request, response, session, tmpl_context as c, url | |
29 | from pylons.controllers.util import abort, redirect |
|
32 | from pylons.controllers.util import abort, redirect | |
@@ -32,9 +35,13 b' from pylons.i18n.translation import _' | |||||
32 | from rhodecode.lib.base import BaseRepoController, render |
|
35 | from rhodecode.lib.base import BaseRepoController, render | |
33 | from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator |
|
36 | from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator | |
34 | from rhodecode.lib import helpers as h |
|
37 | from rhodecode.lib import helpers as h | |
35 |
from rhodecode. |
|
38 | from rhodecode.lib import diffs | |
|
39 | from rhodecode.model.db import User, PullRequest, Repository, ChangesetStatus | |||
36 | from rhodecode.model.pull_request import PullRequestModel |
|
40 | from rhodecode.model.pull_request import PullRequestModel | |
37 | from rhodecode.model.meta import Session |
|
41 | from rhodecode.model.meta import Session | |
|
42 | from rhodecode.model.repo import RepoModel | |||
|
43 | from rhodecode.model.comment import ChangesetCommentsModel | |||
|
44 | from rhodecode.model.changeset_status import ChangesetStatusModel | |||
38 |
|
45 | |||
39 | log = logging.getLogger(__name__) |
|
46 | log = logging.getLogger(__name__) | |
40 |
|
47 | |||
@@ -50,12 +57,12 b' class PullrequestsController(BaseRepoCon' | |||||
50 | def _get_repo_refs(self, repo): |
|
57 | def _get_repo_refs(self, repo): | |
51 | hist_l = [] |
|
58 | hist_l = [] | |
52 |
|
59 | |||
53 |
branches_group = ([('branch:' |
|
60 | branches_group = ([('branch:%s:%s' % (k, v), k) for | |
54 | _("Branches")) |
|
61 | k, v in repo.branches.iteritems()], _("Branches")) | |
55 |
bookmarks_group = ([('book:' |
|
62 | bookmarks_group = ([('book:%s:%s' % (k, v), k) for | |
56 | _("Bookmarks")) |
|
63 | k, v in repo.bookmarks.iteritems()], _("Bookmarks")) | |
57 |
tags_group = ([('tag:' |
|
64 | tags_group = ([('tag:%s:%s' % (k, v), k) for | |
58 | _("Tags")) |
|
65 | k, v in repo.tags.iteritems()], _("Tags")) | |
59 |
|
66 | |||
60 | hist_l.append(bookmarks_group) |
|
67 | hist_l.append(bookmarks_group) | |
61 | hist_l.append(branches_group) |
|
68 | hist_l.append(branches_group) | |
@@ -63,6 +70,11 b' class PullrequestsController(BaseRepoCon' | |||||
63 |
|
70 | |||
64 | return hist_l |
|
71 | return hist_l | |
65 |
|
72 | |||
|
73 | def show_all(self, repo_name): | |||
|
74 | c.pull_requests = PullRequestModel().get_all(repo_name) | |||
|
75 | c.repo_name = repo_name | |||
|
76 | return render('/pullrequests/pullrequest_show_all.html') | |||
|
77 | ||||
66 | def index(self): |
|
78 | def index(self): | |
67 | org_repo = c.rhodecode_db_repo |
|
79 | org_repo = c.rhodecode_db_repo | |
68 | c.org_refs = self._get_repo_refs(c.rhodecode_repo) |
|
80 | c.org_refs = self._get_repo_refs(c.rhodecode_repo) | |
@@ -128,6 +140,118 b' class PullrequestsController(BaseRepoCon' | |||||
128 |
|
140 | |||
129 | return redirect(url('changelog_home', repo_name=repo_name)) |
|
141 | return redirect(url('changelog_home', repo_name=repo_name)) | |
130 |
|
142 | |||
|
143 | def _get_changesets(self, org_repo, org_ref, other_repo, other_ref, tmp): | |||
|
144 | changesets = [] | |||
|
145 | #case two independent repos | |||
|
146 | if org_repo != other_repo: | |||
|
147 | common, incoming, rheads = tmp | |||
|
148 | ||||
|
149 | if not incoming: | |||
|
150 | revs = [] | |||
|
151 | else: | |||
|
152 | revs = org_repo._repo.changelog.findmissing(common, rheads) | |||
|
153 | ||||
|
154 | for cs in reversed(map(binascii.hexlify, revs)): | |||
|
155 | changesets.append(org_repo.get_changeset(cs)) | |||
|
156 | else: | |||
|
157 | revs = ['ancestors(%s) and not ancestors(%s)' % (org_ref[1], | |||
|
158 | other_ref[1])] | |||
|
159 | from mercurial import scmutil | |||
|
160 | out = scmutil.revrange(org_repo._repo, revs) | |||
|
161 | for cs in reversed(out): | |||
|
162 | changesets.append(org_repo.get_changeset(cs)) | |||
|
163 | ||||
|
164 | return changesets | |||
|
165 | ||||
|
166 | def _get_discovery(self, org_repo, org_ref, other_repo, other_ref): | |||
|
167 | from mercurial import discovery | |||
|
168 | other = org_repo._repo | |||
|
169 | repo = other_repo._repo | |||
|
170 | tip = other[org_ref[1]] | |||
|
171 | log.debug('Doing discovery for %s@%s vs %s@%s' % ( | |||
|
172 | org_repo, org_ref, other_repo, other_ref) | |||
|
173 | ) | |||
|
174 | log.debug('Filter heads are %s[%s]' % (tip, org_ref[1])) | |||
|
175 | tmp = discovery.findcommonincoming( | |||
|
176 | repo=repo, # other_repo we check for incoming | |||
|
177 | remote=other, # org_repo source for incoming | |||
|
178 | heads=[tip.node()], | |||
|
179 | force=False | |||
|
180 | ) | |||
|
181 | return tmp | |||
|
182 | ||||
|
183 | def _compare(self, pull_request): | |||
|
184 | ||||
|
185 | org_repo = pull_request.org_repo | |||
|
186 | org_ref_type, org_ref_, org_ref = pull_request.org_ref.split(':') | |||
|
187 | other_repo = pull_request.other_repo | |||
|
188 | other_ref_type, other_ref, other_ref_ = pull_request.other_ref.split(':') | |||
|
189 | ||||
|
190 | org_ref = (org_ref_type, org_ref) | |||
|
191 | other_ref = (other_ref_type, other_ref) | |||
|
192 | ||||
|
193 | c.org_repo = org_repo | |||
|
194 | c.other_repo = other_repo | |||
|
195 | ||||
|
196 | discovery_data = self._get_discovery(org_repo.scm_instance, | |||
|
197 | org_ref, | |||
|
198 | other_repo.scm_instance, | |||
|
199 | other_ref) | |||
|
200 | c.cs_ranges = self._get_changesets(org_repo.scm_instance, | |||
|
201 | org_ref, | |||
|
202 | other_repo.scm_instance, | |||
|
203 | other_ref, | |||
|
204 | discovery_data) | |||
|
205 | ||||
|
206 | c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in | |||
|
207 | c.cs_ranges]) | |||
|
208 | # defines that we need hidden inputs with changesets | |||
|
209 | c.as_form = request.GET.get('as_form', False) | |||
|
210 | if request.environ.get('HTTP_X_PARTIAL_XHR'): | |||
|
211 | return render('compare/compare_cs.html') | |||
|
212 | ||||
|
213 | c.org_ref = org_ref[1] | |||
|
214 | c.other_ref = other_ref[1] | |||
|
215 | # diff needs to have swapped org with other to generate proper diff | |||
|
216 | _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref, | |||
|
217 | discovery_data) | |||
|
218 | diff_processor = diffs.DiffProcessor(_diff, format='gitdiff') | |||
|
219 | _parsed = diff_processor.prepare() | |||
|
220 | ||||
|
221 | c.files = [] | |||
|
222 | c.changes = {} | |||
|
223 | ||||
|
224 | for f in _parsed: | |||
|
225 | fid = h.FID('', f['filename']) | |||
|
226 | c.files.append([fid, f['operation'], f['filename'], f['stats']]) | |||
|
227 | diff = diff_processor.as_html(enable_comments=False, diff_lines=[f]) | |||
|
228 | c.changes[fid] = [f['operation'], f['filename'], diff] | |||
|
229 | ||||
131 | def show(self, repo_name, pull_request_id): |
|
230 | def show(self, repo_name, pull_request_id): | |
|
231 | repo_model = RepoModel() | |||
|
232 | c.users_array = repo_model.get_users_js() | |||
|
233 | c.users_groups_array = repo_model.get_users_groups_js() | |||
132 | c.pull_request = PullRequest.get(pull_request_id) |
|
234 | c.pull_request = PullRequest.get(pull_request_id) | |
|
235 | ##TODO: need more generic solution | |||
|
236 | self._compare(c.pull_request) | |||
|
237 | ||||
|
238 | # inline comments | |||
|
239 | c.inline_cnt = 0 | |||
|
240 | c.inline_comments = ChangesetCommentsModel()\ | |||
|
241 | .get_inline_comments(c.rhodecode_db_repo.repo_id, | |||
|
242 | pull_request=pull_request_id) | |||
|
243 | # count inline comments | |||
|
244 | for __, lines in c.inline_comments: | |||
|
245 | for comments in lines.values(): | |||
|
246 | c.inline_cnt += len(comments) | |||
|
247 | # comments | |||
|
248 | c.comments = ChangesetCommentsModel()\ | |||
|
249 | .get_comments(c.rhodecode_db_repo.repo_id, | |||
|
250 | pull_request=pull_request_id) | |||
|
251 | ||||
|
252 | # changeset(pull-request) statuse | |||
|
253 | c.current_changeset_status = ChangesetStatusModel()\ | |||
|
254 | .get_status(c.rhodecode_db_repo.repo_id, | |||
|
255 | pull_request=pull_request_id) | |||
|
256 | c.changeset_statuses = ChangesetStatus.STATUSES | |||
133 | return render('/pullrequests/pullrequest_show.html') |
|
257 | return render('/pullrequests/pullrequest_show.html') |
@@ -204,7 +204,7 b' class BaseRepoController(BaseController)' | |||||
204 | super(BaseRepoController, self).__before__() |
|
204 | super(BaseRepoController, self).__before__() | |
205 | if c.repo_name: |
|
205 | if c.repo_name: | |
206 |
|
206 | |||
207 | c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name) |
|
207 | dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name) | |
208 | c.rhodecode_repo = c.rhodecode_db_repo.scm_instance |
|
208 | c.rhodecode_repo = c.rhodecode_db_repo.scm_instance | |
209 |
|
209 | |||
210 | if c.rhodecode_repo is None: |
|
210 | if c.rhodecode_repo is None: | |
@@ -213,5 +213,7 b' class BaseRepoController(BaseController)' | |||||
213 |
|
213 | |||
214 | redirect(url('home')) |
|
214 | redirect(url('home')) | |
215 |
|
215 | |||
216 | c.repository_followers = self.scm_model.get_followers(c.repo_name) |
|
216 | # some globals counter for menu | |
217 |
c.repository_for |
|
217 | c.repository_followers = self.scm_model.get_followers(dbr) | |
|
218 | c.repository_forks = self.scm_model.get_forks(dbr) | |||
|
219 | c.repository_pull_requests = self.scm_model.get_pull_requests(dbr) No newline at end of file |
@@ -26,7 +26,7 b'' | |||||
26 | import logging |
|
26 | import logging | |
27 |
|
27 | |||
28 | from rhodecode.model import BaseModel |
|
28 | from rhodecode.model import BaseModel | |
29 | from rhodecode.model.db import ChangesetStatus |
|
29 | from rhodecode.model.db import ChangesetStatus, PullRequest | |
30 |
|
30 | |||
31 | log = logging.getLogger(__name__) |
|
31 | log = logging.getLogger(__name__) | |
32 |
|
32 | |||
@@ -36,23 +36,37 b' class ChangesetStatusModel(BaseModel):' | |||||
36 | def __get_changeset_status(self, changeset_status): |
|
36 | def __get_changeset_status(self, changeset_status): | |
37 | return self._get_instance(ChangesetStatus, changeset_status) |
|
37 | return self._get_instance(ChangesetStatus, changeset_status) | |
38 |
|
38 | |||
39 |
def |
|
39 | def __get_pull_request(self, pull_request): | |
|
40 | return self._get_instance(PullRequest, pull_request) | |||
|
41 | ||||
|
42 | def get_status(self, repo, revision=None, pull_request=None): | |||
40 | """ |
|
43 | """ | |
41 |
Returns status of changeset for given revision |
|
44 | Returns latest status of changeset for given revision or for given | |
42 | versioning makes a history of statuses, and version == 0 is always the |
|
45 | pull request. Statuses are versioned inside a table itself and | |
43 | current one |
|
46 | version == 0 is always the current one | |
44 |
|
47 | |||
45 | :param repo: |
|
48 | :param repo: | |
46 | :type repo: |
|
49 | :type repo: | |
47 | :param revision: 40char hash |
|
50 | :param revision: 40char hash or None | |
48 | :type revision: str |
|
51 | :type revision: str | |
|
52 | :param pull_request: pull_request reference | |||
|
53 | :type: | |||
49 | """ |
|
54 | """ | |
50 | repo = self._get_repo(repo) |
|
55 | repo = self._get_repo(repo) | |
51 |
|
56 | |||
52 |
|
|
57 | q = ChangesetStatus.query()\ | |
53 | .filter(ChangesetStatus.repo == repo)\ |
|
58 | .filter(ChangesetStatus.repo == repo)\ | |
54 |
.filter(ChangesetStatus.r |
|
59 | .filter(ChangesetStatus.version == 0) | |
55 | .filter(ChangesetStatus.version == 0).scalar() |
|
60 | ||
|
61 | if revision: | |||
|
62 | q = q.filter(ChangesetStatus.revision == revision) | |||
|
63 | elif pull_request: | |||
|
64 | pull_request = self.__get_pull_request(pull_request) | |||
|
65 | q = q.filter(ChangesetStatus.pull_request == pull_request) | |||
|
66 | else: | |||
|
67 | raise Exception('Please specify revision or pull_request') | |||
|
68 | ||||
|
69 | status = q.scalar() | |||
56 | status = status.status if status else status |
|
70 | status = status.status if status else status | |
57 | st = status or ChangesetStatus.DEFAULT |
|
71 | st = status or ChangesetStatus.DEFAULT | |
58 | return str(st) |
|
72 | return str(st) |
@@ -32,7 +32,8 b' from sqlalchemy.util.compat import defau' | |||||
32 | from rhodecode.lib.utils2 import extract_mentioned_users, safe_unicode |
|
32 | from rhodecode.lib.utils2 import extract_mentioned_users, safe_unicode | |
33 | from rhodecode.lib import helpers as h |
|
33 | from rhodecode.lib import helpers as h | |
34 | from rhodecode.model import BaseModel |
|
34 | from rhodecode.model import BaseModel | |
35 |
from rhodecode.model.db import ChangesetComment, User, Repository, |
|
35 | from rhodecode.model.db import ChangesetComment, User, Repository, \ | |
|
36 | Notification, PullRequest | |||
36 | from rhodecode.model.notification import NotificationModel |
|
37 | from rhodecode.model.notification import NotificationModel | |
37 |
|
38 | |||
38 | log = logging.getLogger(__name__) |
|
39 | log = logging.getLogger(__name__) | |
@@ -43,6 +44,9 b' class ChangesetCommentsModel(BaseModel):' | |||||
43 | def __get_changeset_comment(self, changeset_comment): |
|
44 | def __get_changeset_comment(self, changeset_comment): | |
44 | return self._get_instance(ChangesetComment, changeset_comment) |
|
45 | return self._get_instance(ChangesetComment, changeset_comment) | |
45 |
|
46 | |||
|
47 | def __get_pull_request(self, pull_request): | |||
|
48 | return self._get_instance(PullRequest, pull_request) | |||
|
49 | ||||
46 | def _extract_mentions(self, s): |
|
50 | def _extract_mentions(self, s): | |
47 | user_objects = [] |
|
51 | user_objects = [] | |
48 | for username in extract_mentioned_users(s): |
|
52 | for username in extract_mentioned_users(s): | |
@@ -135,7 +139,7 b' class ChangesetCommentsModel(BaseModel):' | |||||
135 |
|
139 | |||
136 | return comment |
|
140 | return comment | |
137 |
|
141 | |||
138 |
def get_comments(self, repo_id, revision=None, pull_request |
|
142 | def get_comments(self, repo_id, revision=None, pull_request=None): | |
139 | """ |
|
143 | """ | |
140 | Get's main comments based on revision or pull_request_id |
|
144 | Get's main comments based on revision or pull_request_id | |
141 |
|
145 | |||
@@ -143,22 +147,24 b' class ChangesetCommentsModel(BaseModel):' | |||||
143 | :type repo_id: |
|
147 | :type repo_id: | |
144 | :param revision: |
|
148 | :param revision: | |
145 | :type revision: |
|
149 | :type revision: | |
146 |
:param pull_request |
|
150 | :param pull_request: | |
147 |
:type pull_request |
|
151 | :type pull_request: | |
148 | """ |
|
152 | """ | |
|
153 | ||||
149 | q = ChangesetComment.query()\ |
|
154 | q = ChangesetComment.query()\ | |
150 | .filter(ChangesetComment.repo_id == repo_id)\ |
|
155 | .filter(ChangesetComment.repo_id == repo_id)\ | |
151 | .filter(ChangesetComment.line_no == None)\ |
|
156 | .filter(ChangesetComment.line_no == None)\ | |
152 | .filter(ChangesetComment.f_path == None) |
|
157 | .filter(ChangesetComment.f_path == None) | |
153 | if revision: |
|
158 | if revision: | |
154 | q = q.filter(ChangesetComment.revision == revision) |
|
159 | q = q.filter(ChangesetComment.revision == revision) | |
155 |
elif pull_request |
|
160 | elif pull_request: | |
156 | q = q.filter(ChangesetComment.pull_request_id == pull_request_id) |
|
161 | pull_request = self.__get_pull_request(pull_request) | |
|
162 | q = q.filter(ChangesetComment.pull_request == pull_request) | |||
157 | else: |
|
163 | else: | |
158 |
raise Exception('Please specify revision or pull_request |
|
164 | raise Exception('Please specify revision or pull_request') | |
159 | return q.all() |
|
165 | return q.all() | |
160 |
|
166 | |||
161 |
def get_inline_comments(self, repo_id, revision=None, pull_request |
|
167 | def get_inline_comments(self, repo_id, revision=None, pull_request=None): | |
162 | q = self.sa.query(ChangesetComment)\ |
|
168 | q = self.sa.query(ChangesetComment)\ | |
163 | .filter(ChangesetComment.repo_id == repo_id)\ |
|
169 | .filter(ChangesetComment.repo_id == repo_id)\ | |
164 | .filter(ChangesetComment.line_no != None)\ |
|
170 | .filter(ChangesetComment.line_no != None)\ | |
@@ -167,8 +173,9 b' class ChangesetCommentsModel(BaseModel):' | |||||
167 |
|
173 | |||
168 | if revision: |
|
174 | if revision: | |
169 | q = q.filter(ChangesetComment.revision == revision) |
|
175 | q = q.filter(ChangesetComment.revision == revision) | |
170 |
elif pull_request |
|
176 | elif pull_request: | |
171 | q = q.filter(ChangesetComment.pull_request_id == pull_request_id) |
|
177 | pull_request = self.__get_pull_request(pull_request) | |
|
178 | q = q.filter(ChangesetComment.pull_request == pull_request) | |||
172 | else: |
|
179 | else: | |
173 | raise Exception('Please specify revision or pull_request_id') |
|
180 | raise Exception('Please specify revision or pull_request_id') | |
174 |
|
181 |
@@ -1322,7 +1322,8 b' class ChangesetComment(Base, BaseModel):' | |||||
1322 | ) |
|
1322 | ) | |
1323 | comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) |
|
1323 | comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True) | |
1324 | repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) |
|
1324 | repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) | |
1325 |
revision = Column('revision', String(40), nullable= |
|
1325 | revision = Column('revision', String(40), nullable=True) | |
|
1326 | pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True) | |||
1326 | line_no = Column('line_no', Unicode(10), nullable=True) |
|
1327 | line_no = Column('line_no', Unicode(10), nullable=True) | |
1327 | f_path = Column('f_path', Unicode(1000), nullable=True) |
|
1328 | f_path = Column('f_path', Unicode(1000), nullable=True) | |
1328 | user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) |
|
1329 | user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False) | |
@@ -1332,6 +1333,7 b' class ChangesetComment(Base, BaseModel):' | |||||
1332 | author = relationship('User', lazy='joined') |
|
1333 | author = relationship('User', lazy='joined') | |
1333 | repo = relationship('Repository') |
|
1334 | repo = relationship('Repository') | |
1334 | status_change = relationship('ChangesetStatus', uselist=False) |
|
1335 | status_change = relationship('ChangesetStatus', uselist=False) | |
|
1336 | pull_request = relationship('PullRequest', lazy='joined') | |||
1335 |
|
1337 | |||
1336 | @classmethod |
|
1338 | @classmethod | |
1337 | def get_users(cls, revision): |
|
1339 | def get_users(cls, revision): | |
@@ -1397,6 +1399,8 b' class PullRequest(Base, BaseModel):' | |||||
1397 | pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) |
|
1399 | pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True) | |
1398 | title = Column('title', Unicode(256), nullable=True) |
|
1400 | title = Column('title', Unicode(256), nullable=True) | |
1399 | description = Column('description', Unicode(10240), nullable=True) |
|
1401 | description = Column('description', Unicode(10240), nullable=True) | |
|
1402 | created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now) | |||
|
1403 | user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None) | |||
1400 | _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max |
|
1404 | _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max | |
1401 | org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) |
|
1405 | org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False) | |
1402 | org_ref = Column('org_ref', Unicode(256), nullable=False) |
|
1406 | org_ref = Column('org_ref', Unicode(256), nullable=False) | |
@@ -1411,6 +1415,7 b' class PullRequest(Base, BaseModel):' | |||||
1411 | def revisions(self, val): |
|
1415 | def revisions(self, val): | |
1412 | self._revisions = ':'.join(val) |
|
1416 | self._revisions = ':'.join(val) | |
1413 |
|
1417 | |||
|
1418 | author = relationship('User', lazy='joined') | |||
1414 | reviewers = relationship('PullRequestReviewers') |
|
1419 | reviewers = relationship('PullRequestReviewers') | |
1415 | org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') |
|
1420 | org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id') | |
1416 | other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') |
|
1421 | other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id') |
@@ -37,8 +37,13 b' log = logging.getLogger(__name__)' | |||||
37 |
|
37 | |||
38 | class PullRequestModel(BaseModel): |
|
38 | class PullRequestModel(BaseModel): | |
39 |
|
39 | |||
|
40 | def get_all(self, repo): | |||
|
41 | repo = self._get_repo(repo) | |||
|
42 | return PullRequest.query().filter(PullRequest.other_repo == repo).all() | |||
|
43 | ||||
40 | def create(self, created_by, org_repo, org_ref, other_repo, |
|
44 | def create(self, created_by, org_repo, org_ref, other_repo, | |
41 | other_ref, revisions, reviewers, title, description=None): |
|
45 | other_ref, revisions, reviewers, title, description=None): | |
|
46 | created_by_user = self._get_user(created_by) | |||
42 |
|
47 | |||
43 | new = PullRequest() |
|
48 | new = PullRequest() | |
44 | new.org_repo = self._get_repo(org_repo) |
|
49 | new.org_repo = self._get_repo(org_repo) | |
@@ -48,7 +53,7 b' class PullRequestModel(BaseModel):' | |||||
48 | new.revisions = revisions |
|
53 | new.revisions = revisions | |
49 | new.title = title |
|
54 | new.title = title | |
50 | new.description = description |
|
55 | new.description = description | |
51 |
|
56 | new.author = created_by_user | ||
52 | self.sa.add(new) |
|
57 | self.sa.add(new) | |
53 |
|
58 | |||
54 | #members |
|
59 | #members | |
@@ -59,7 +64,7 b' class PullRequestModel(BaseModel):' | |||||
59 |
|
64 | |||
60 | #notification to reviewers |
|
65 | #notification to reviewers | |
61 | notif = NotificationModel() |
|
66 | notif = NotificationModel() | |
62 | created_by_user = self._get_user(created_by) |
|
67 | ||
63 | subject = safe_unicode( |
|
68 | subject = safe_unicode( | |
64 | h.link_to( |
|
69 | h.link_to( | |
65 | _('%(user)s wants you to review pull request #%(pr_id)s') % \ |
|
70 | _('%(user)s wants you to review pull request #%(pr_id)s') % \ |
@@ -43,7 +43,7 b' from rhodecode.lib.utils import get_repo' | |||||
43 | action_logger, EmptyChangeset, REMOVED_REPO_PAT |
|
43 | action_logger, EmptyChangeset, REMOVED_REPO_PAT | |
44 | from rhodecode.model import BaseModel |
|
44 | from rhodecode.model import BaseModel | |
45 | from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \ |
|
45 | from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \ | |
46 | UserFollowing, UserLog, User, RepoGroup |
|
46 | UserFollowing, UserLog, User, RepoGroup, PullRequest | |
47 |
|
47 | |||
48 | log = logging.getLogger(__name__) |
|
48 | log = logging.getLogger(__name__) | |
49 |
|
49 | |||
@@ -320,19 +320,21 b' class ScmModel(BaseModel):' | |||||
320 |
|
320 | |||
321 | return f is not None |
|
321 | return f is not None | |
322 |
|
322 | |||
323 |
def get_followers(self, repo |
|
323 | def get_followers(self, repo): | |
324 | if not isinstance(repo_id, int): |
|
324 | repo = self._get_repo(repo) | |
325 | repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id') |
|
|||
326 |
|
325 | |||
327 | return self.sa.query(UserFollowing)\ |
|
326 | return self.sa.query(UserFollowing)\ | |
328 |
.filter(UserFollowing.follows_repo |
|
327 | .filter(UserFollowing.follows_repository == repo).count() | |
329 |
|
328 | |||
330 |
def get_forks(self, repo |
|
329 | def get_forks(self, repo): | |
331 | if not isinstance(repo_id, int): |
|
330 | repo = self._get_repo(repo) | |
332 | repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id') |
|
331 | return self.sa.query(Repository)\ | |
|
332 | .filter(Repository.fork == repo).count() | |||
333 |
|
333 | |||
334 | return self.sa.query(Repository)\ |
|
334 | def get_pull_requests(self, repo): | |
335 | .filter(Repository.fork_id == repo_id).count() |
|
335 | repo = self._get_repo(repo) | |
|
336 | return self.sa.query(PullRequest)\ | |||
|
337 | .filter(PullRequest.other_repo == repo).count() | |||
336 |
|
338 | |||
337 | def mark_as_fork(self, repo, fork, user): |
|
339 | def mark_as_fork(self, repo, fork, user): | |
338 | repo = self.__get_repo(repo) |
|
340 | repo = self.__get_repo(repo) |
@@ -247,6 +247,14 b'' | |||||
247 | <span class="short">${c.repository_forks}</span> |
|
247 | <span class="short">${c.repository_forks}</span> | |
248 | </a> |
|
248 | </a> | |
249 | </li> |
|
249 | </li> | |
|
250 | <li> | |||
|
251 | <a class="menu_link" title="${_('Pull requests')}" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}"> | |||
|
252 | <span class="icon_short"> | |||
|
253 | <img src="${h.url('/images/icons/arrow_join.png')}" alt="${_('Pull requests')}" /> | |||
|
254 | </span> | |||
|
255 | <span class="short">${c.repository_pull_requests}</span> | |||
|
256 | </a> | |||
|
257 | </li> | |||
250 | ${usermenu()} |
|
258 | ${usermenu()} | |
251 | </ul> |
|
259 | </ul> | |
252 | <script type="text/javascript"> |
|
260 | <script type="text/javascript"> |
@@ -20,7 +20,58 b'' | |||||
20 | ${self.breadcrumbs()} |
|
20 | ${self.breadcrumbs()} | |
21 | </div> |
|
21 | </div> | |
22 |
|
22 | |||
23 | pull request ${c.pull_request} overview... |
|
23 | <h3>${_('Title')}: ${c.pull_request.title}</h3> | |
|
24 | <div class="changeset-status-container" style="float:left;padding:0px 20px 20px 20px"> | |||
|
25 | %if c.current_changeset_status: | |||
|
26 | <div title="${_('Changeset status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.current_changeset_status)}]</div> | |||
|
27 | <div class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.current_changeset_status)}" /></div> | |||
|
28 | %endif | |||
|
29 | </div> | |||
|
30 | <div style="padding:4px"> | |||
|
31 | <div>${h.fmt_date(c.pull_request.created_on)}</div> | |||
|
32 | </div> | |||
|
33 | ||||
|
34 | ##DIFF | |||
|
35 | ||||
|
36 | <div class="table"> | |||
|
37 | <div id="body" class="diffblock"> | |||
|
38 | <div style="white-space:pre-wrap;padding:5px">${h.literal(c.pull_request.description)}</div> | |||
|
39 | </div> | |||
|
40 | <div id="changeset_compare_view_content"> | |||
|
41 | ##CS | |||
|
42 | <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Incoming changesets')}</div> | |||
|
43 | <%include file="/compare/compare_cs.html" /> | |||
|
44 | ||||
|
45 | ## FILES | |||
|
46 | <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div> | |||
|
47 | <div class="cs_files"> | |||
|
48 | %for fid, change, f, stat in c.files: | |||
|
49 | <div class="cs_${change}"> | |||
|
50 | <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div> | |||
|
51 | <div class="changes">${h.fancy_file_stats(stat)}</div> | |||
|
52 | </div> | |||
|
53 | %endfor | |||
|
54 | </div> | |||
|
55 | </div> | |||
|
56 | </div> | |||
|
57 | <script> | |||
|
58 | var _USERS_AC_DATA = ${c.users_array|n}; | |||
|
59 | var _GROUPS_AC_DATA = ${c.users_groups_array|n}; | |||
|
60 | </script> | |||
|
61 | ||||
|
62 | ## diff block | |||
|
63 | <%namespace name="diff_block" file="/changeset/diff_block.html"/> | |||
|
64 | %for fid, change, f, stat in c.files: | |||
|
65 | ${diff_block.diff_block_simple([c.changes[fid]])} | |||
|
66 | %endfor | |||
|
67 | ||||
|
68 | ## template for inline comment form | |||
|
69 | <%namespace name="comment" file="/changeset/changeset_file_comment.html"/> | |||
|
70 | ##${comment.comment_inline_form(c.changeset)} | |||
|
71 | ||||
|
72 | ## render comments main comments form and it status | |||
|
73 | ##${comment.comments(h.url('pull_request_comment', repo_name=c.repo_name, pull_request_id=c.pull_request.pull_request_id), | |||
|
74 | ## c.current_changeset_status)} | |||
24 |
|
75 | |||
25 | </div> |
|
76 | </div> | |
26 |
|
77 |
General Comments 0
You need to be logged in to leave comments.
Login now