##// END OF EJS Templates
Added basic models for saving open pull requests...
marcink -
r2434:f2946967 codereview
parent child Browse files
Show More
@@ -0,0 +1,79 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.model.pull_reuquest
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 pull request model for RhodeCode
7
8 :created_on: Jun 6, 2012
9 :author: marcink
10 :copyright: (C) 2012-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
26 import logging
27 from pylons.i18n.translation import _
28
29 from rhodecode.lib import helpers as h
30 from rhodecode.model import BaseModel
31 from rhodecode.model.db import PullRequest, PullRequestReviewers, Notification
32 from rhodecode.model.notification import NotificationModel
33 from rhodecode.lib.utils2 import safe_unicode
34
35 log = logging.getLogger(__name__)
36
37
38 class PullRequestModel(BaseModel):
39
40 def create(self, created_by, org_repo, org_ref, other_repo,
41 other_ref, revisions, reviewers, title, description=None):
42
43 new = PullRequest()
44 new.org_repo = self._get_repo(org_repo)
45 new.org_ref = org_ref
46 new.other_repo = self._get_repo(other_repo)
47 new.other_ref = other_ref
48 new.revisions = revisions
49 new.title = title
50 new.description = description
51
52 self.sa.add(new)
53
54 #members
55 for member in reviewers:
56 _usr = self._get_user(member)
57 reviewer = PullRequestReviewers(_usr, new)
58 self.sa.add(reviewer)
59
60 #notification to reviewers
61 notif = NotificationModel()
62 created_by_user = self._get_user(created_by)
63 subject = safe_unicode(
64 h.link_to(
65 _('%(user)s wants you to review pull request #%(pr_id)s') % \
66 {'user': created_by_user.username,
67 'pr_id': new.pull_request_id},
68 h.url('pullrequest_show', repo_name=other_repo,
69 pull_request_id=new.pull_request_id,
70 qualified=True,
71 )
72 )
73 )
74 body = description
75 notif.create(created_by=created_by, subject=subject, body=body,
76 recipients=reviewers,
77 type_=Notification.TYPE_PULL_REQUEST,)
78
79 return new
@@ -0,0 +1,32 b''
1 <%inherit file="/base/base.html"/>
2
3 <%def name="title()">
4 ${c.repo_name} ${_('Pull request #%s') % c.pull_request.pull_request_id}
5 </%def>
6
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(u'Home',h.url('/'))}
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
11 &raquo;
12 ${_('Pull request #%s') % c.pull_request.pull_request_id}
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 pull request ${c.pull_request} overview...
24
25 </div>
26
27 <script type="text/javascript">
28
29
30 </script>
31
32 </%def>
@@ -436,9 +436,20 b' def make_map(config):'
436 other_ref_type='(branch|book|tag)'))
436 other_ref_type='(branch|book|tag)'))
437
437
438 rmap.connect('pullrequest_home',
438 rmap.connect('pullrequest_home',
439 '/{repo_name:.*}/pull-request/new',
439 '/{repo_name:.*}/pull-request/new', controller='pullrequests',
440 controller='pullrequests', action='index',
440 action='index', conditions=dict(function=check_repo,
441 conditions=dict(function=check_repo))
441 method=["GET"]))
442
443 rmap.connect('pullrequest',
444 '/{repo_name:.*}/pull-request/new', controller='pullrequests',
445 action='create', conditions=dict(function=check_repo,
446 method=["POST"]))
447
448 rmap.connect('pullrequest_show',
449 '/{repo_name:.*}/pull-request/{pull_request_id}',
450 controller='pullrequests',
451 action='show', conditions=dict(function=check_repo,
452 method=["GET"]))
442
453
443 rmap.connect('summary_home', '/{repo_name:.*}/summary',
454 rmap.connect('summary_home', '/{repo_name:.*}/summary',
444 controller='summary', conditions=dict(function=check_repo))
455 controller='summary', conditions=dict(function=check_repo))
@@ -120,6 +120,8 b' class CompareController(BaseRepoControll'
120
120
121 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
121 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
122 c.cs_ranges])
122 c.cs_ranges])
123 # defines that we need hidden inputs with changesets
124 c.as_form = request.GET.get('as_form', False)
123 if request.environ.get('HTTP_X_PARTIAL_XHR'):
125 if request.environ.get('HTTP_X_PARTIAL_XHR'):
124 return render('compare/compare_cs.html')
126 return render('compare/compare_cs.html')
125
127
@@ -31,7 +31,10 b' from pylons.i18n.translation import _'
31
31
32 from rhodecode.lib.base import BaseRepoController, render
32 from rhodecode.lib.base import BaseRepoController, render
33 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
33 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
34 from rhodecode.model.db import User
34 from rhodecode.lib import helpers as h
35 from rhodecode.model.db import User, PullRequest
36 from rhodecode.model.pull_request import PullRequestModel
37 from rhodecode.model.meta import Session
35
38
36 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
37
40
@@ -71,20 +74,60 b' class PullrequestsController(BaseRepoCon'
71
74
72 c.other_refs = c.org_refs
75 c.other_refs = c.org_refs
73 c.other_repos.extend(c.org_repos)
76 c.other_repos.extend(c.org_repos)
74
77 c.default_pull_request = org_repo.repo_name
75 #gather forks and add to this list
78 #gather forks and add to this list
76 for fork in org_repo.forks:
79 for fork in org_repo.forks:
77 c.other_repos.append((fork.repo_name, '%s/%s' % (
80 c.other_repos.append((fork.repo_name, '%s/%s' % (
78 fork.user.username, fork.repo_name))
81 fork.user.username, fork.repo_name))
79 )
82 )
80 #add parents of this fork also
83 #add parents of this fork also
81 c.other_repos.append((org_repo.parent.repo_name, '%s/%s' % (
84 if org_repo.parent:
82 org_repo.parent.user.username,
85 c.default_pull_request = org_repo.parent.repo_name
83 org_repo.parent.repo_name))
86 c.other_repos.append((org_repo.parent.repo_name, '%s/%s' % (
84 )
87 org_repo.parent.user.username,
88 org_repo.parent.repo_name))
89 )
85
90
86 #TODO: maybe the owner should be default ?
91 #TODO: maybe the owner should be default ?
87 c.review_members = []
92 c.review_members = []
88 c.available_members = [(x.user_id, x.username) for x in
93 c.available_members = []
89 User.query().filter(User.username != 'default').all()]
94 for u in User.query().filter(User.username != 'default').all():
95 uname = u.username
96 if org_repo.user == u:
97 uname = _('%s (owner)' % u.username)
98 # auto add owner to pull-request recipients
99 c.review_members.append([u.user_id, uname])
100 c.available_members.append([u.user_id, uname])
90 return render('/pullrequests/pullrequest.html')
101 return render('/pullrequests/pullrequest.html')
102
103 def create(self, repo_name):
104 req_p = request.POST
105 org_repo = req_p['org_repo']
106 org_ref = req_p['org_ref']
107 other_repo = req_p['other_repo']
108 other_ref = req_p['other_ref']
109 revisions = req_p.getall('revisions')
110 reviewers = req_p.getall('review_members')
111 #TODO: wrap this into a FORM !!!
112
113 title = req_p['pullrequest_title']
114 description = req_p['pullrequest_desc']
115
116 try:
117 model = PullRequestModel()
118 model.create(self.rhodecode_user.user_id, org_repo,
119 org_ref, other_repo, other_ref, revisions,
120 reviewers, title, description)
121 Session.commit()
122 h.flash(_('Pull request send'), category='success')
123 except Exception:
124 raise
125 h.flash(_('Error occured during sending pull request'),
126 category='error')
127 log.error(traceback.format_exc())
128
129 return redirect(url('changelog_home', repo_name=repo_name))
130
131 def show(self, repo_name, pull_request_id):
132 c.pull_request = PullRequest.get(pull_request_id)
133 return render('/pullrequests/pullrequest_show.html')
@@ -118,7 +118,8 b' class ChangesetCommentsModel(BaseModel):'
118 NotificationModel().create(
118 NotificationModel().create(
119 created_by=user_id, subject=subj, body=body,
119 created_by=user_id, subject=subj, body=body,
120 recipients=mention_recipients,
120 recipients=mention_recipients,
121 type_=Notification.TYPE_CHANGESET_COMMENT
121 type_=Notification.TYPE_CHANGESET_COMMENT,
122 email_kwargs={'status_change': status_change}
122 )
123 )
123
124
124 return comment
125 return comment
@@ -1371,9 +1371,12 b' class ChangesetStatus(Base, BaseModel):'
1371 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1371 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1372 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1372 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1373 version = Column('version', Integer(), nullable=False, default=0)
1373 version = Column('version', Integer(), nullable=False, default=0)
1374 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1375
1374 author = relationship('User', lazy='joined')
1376 author = relationship('User', lazy='joined')
1375 repo = relationship('Repository')
1377 repo = relationship('Repository')
1376 comment = relationship('ChangesetComment', lazy='joined')
1378 comment = relationship('ChangesetComment', lazy='joined')
1379 pull_request = relationship('PullRequest', lazy='joined')
1377
1380
1378 @classmethod
1381 @classmethod
1379 def get_status_lbl(cls, value):
1382 def get_status_lbl(cls, value):
@@ -1384,6 +1387,59 b' class ChangesetStatus(Base, BaseModel):'
1384 return ChangesetStatus.get_status_lbl(self.status)
1387 return ChangesetStatus.get_status_lbl(self.status)
1385
1388
1386
1389
1390 class PullRequest(Base, BaseModel):
1391 __tablename__ = 'pull_requests'
1392 __table_args__ = (
1393 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1394 'mysql_charset': 'utf8'},
1395 )
1396
1397 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1398 title = Column('title', Unicode(256), nullable=True)
1399 description = Column('description', Unicode(10240), nullable=True)
1400 _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max
1401 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1402 org_ref = Column('org_ref', Unicode(256), nullable=False)
1403 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1404 other_ref = Column('other_ref', Unicode(256), nullable=False)
1405
1406 @hybrid_property
1407 def revisions(self):
1408 return self._revisions.split(':')
1409
1410 @revisions.setter
1411 def revisions(self, val):
1412 self._revisions = ':'.join(val)
1413
1414 reviewers = relationship('PullRequestReviewers')
1415 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')
1417
1418 def __json__(self):
1419 return dict(
1420 revisions=self.revisions
1421 )
1422
1423
1424 class PullRequestReviewers(Base, BaseModel):
1425 __tablename__ = 'pull_request_reviewers'
1426 __table_args__ = (
1427 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1428 'mysql_charset': 'utf8'},
1429 )
1430
1431 def __init__(self, user=None, pull_request=None):
1432 self.user = user
1433 self.pull_request = pull_request
1434
1435 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1436 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1437 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1438
1439 user = relationship('User')
1440 pull_request = relationship('PullRequest')
1441
1442
1387 class Notification(Base, BaseModel):
1443 class Notification(Base, BaseModel):
1388 __tablename__ = 'notifications'
1444 __tablename__ = 'notifications'
1389 __table_args__ = (
1445 __table_args__ = (
@@ -226,6 +226,7 b' class EmailNotificationModel(BaseModel):'
226 TYPE_CHANGESET_COMMENT = Notification.TYPE_CHANGESET_COMMENT
226 TYPE_CHANGESET_COMMENT = Notification.TYPE_CHANGESET_COMMENT
227 TYPE_PASSWORD_RESET = 'passoword_link'
227 TYPE_PASSWORD_RESET = 'passoword_link'
228 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
228 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
229 TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
229 TYPE_DEFAULT = 'default'
230 TYPE_DEFAULT = 'default'
230
231
231 def __init__(self):
232 def __init__(self):
@@ -11,8 +11,12 b''
11 %if cs.raw_id in c.statuses:
11 %if cs.raw_id in c.statuses:
12 <div title="${c.statuses[cs.raw_id][1]}" class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[cs.raw_id][0])}" /></div>
12 <div title="${c.statuses[cs.raw_id][1]}" class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[cs.raw_id][0])}" /></div>
13 %endif
13 %endif
14 </td>
14 </td>
15 <td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</td>
15 <td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}
16 %if c.as_form:
17 ${h.hidden('revisions',cs.raw_id)}
18 %endif
19 </td>
16 <td><div class="author">${h.person(cs.author)}</div></td>
20 <td><div class="author">${h.person(cs.author)}</div></td>
17 <td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td>
21 <td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td>
18 <td><div class="message">${h.urlify_commit(h.wrap_paragraphs(cs.message),c.repo_name)}</div></td>
22 <td><div class="message">${h.urlify_commit(h.wrap_paragraphs(cs.message),c.repo_name)}</div></td>
@@ -20,4 +24,4 b''
20 %endfor
24 %endfor
21 %endif
25 %endif
22 </table>
26 </table>
23 </div> No newline at end of file
27 </div>
@@ -34,13 +34,13 b''
34 </div>
34 </div>
35 <div id="changeset_compare_view_content">
35 <div id="changeset_compare_view_content">
36 ##CS
36 ##CS
37 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Changesets')}</div>
37 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Outgoing changesets')}</div>
38 <%include file="compare_cs.html" />
38 <%include file="compare_cs.html" />
39
39
40 ## FILES
40 ## FILES
41 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div>
41 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div>
42 <div class="cs_files">
42 <div class="cs_files">
43 %for fid, change, f, stat in c.files:
43 %for fid, change, f, stat in c.files:
44 <div class="cs_${change}">
44 <div class="cs_${change}">
45 <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
45 <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
46 <div class="changes">${h.fancy_file_stats(stat)}</div>
46 <div class="changes">${h.fancy_file_stats(stat)}</div>
@@ -49,13 +49,13 b''
49 </div>
49 </div>
50 </div>
50 </div>
51 </div>
51 </div>
52
52
53 ## diff block
53 ## diff block
54 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
54 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
55 %for fid, change, f, stat in c.files:
55 %for fid, change, f, stat in c.files:
56 ${diff_block.diff_block_simple([c.changes[fid]])}
56 ${diff_block.diff_block_simple([c.changes[fid]])}
57 %endfor
57 %endfor
58
58
59 <script type="text/javascript">
59 <script type="text/javascript">
60
60
61 YUE.onDOMReady(function(){
61 YUE.onDOMReady(function(){
@@ -1,7 +1,7 b''
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repo_name} ${_('Pull request')}
4 ${c.repo_name} ${_('New pull request')}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
@@ -9,7 +9,7 b''
9 &raquo;
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
10 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
11 &raquo;
11 &raquo;
12 ${_('Pull request')}
12 ${_('New pull request')}
13 </%def>
13 </%def>
14
14
15 <%def name="main()">
15 <%def name="main()">
@@ -19,8 +19,16 b''
19 <div class="title">
19 <div class="title">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22 ${h.form(url('#'),method='put', id='pull_request_form')}
22 ${h.form(url('pullrequest', repo_name=c.repo_name), method='post', id='pull_request_form')}
23 <div style="float:left;padding:30px">
23 <div style="float:left;padding:0px 30px 30px 30px">
24 <div style="padding:0px 5px 5px 5px">
25 <span>
26 <a id="refresh" href="#">
27 <img class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/>
28 ${_('refresh overview')}
29 </a>
30 </span>
31 </div>
24 ##ORG
32 ##ORG
25 <div style="float:left">
33 <div style="float:left">
26 <div class="fork_user">
34 <div class="fork_user">
@@ -37,7 +45,7 b''
37 <div style="float:left;font-size:24px;padding:0px 20px">
45 <div style="float:left;font-size:24px;padding:0px 20px">
38 <img height=32 width=32 src="${h.url('/images/arrow_right_64.png')}"/>
46 <img height=32 width=32 src="${h.url('/images/arrow_right_64.png')}"/>
39 </div>
47 </div>
40
48
41 ##OTHER, most Probably the PARENT OF THIS FORK
49 ##OTHER, most Probably the PARENT OF THIS FORK
42 <div style="float:left">
50 <div style="float:left">
43 <div class="fork_user">
51 <div class="fork_user">
@@ -45,26 +53,18 b''
45 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_db_repo.user.email,24)}"/>
53 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_db_repo.user.email,24)}"/>
46 </div>
54 </div>
47 <span style="font-size: 20px">
55 <span style="font-size: 20px">
48 ${h.select('other_repo','',c.other_repos,class_='refs')}:${h.select('other_ref','',c.other_refs,class_='refs')}
56 ${h.select('other_repo',c.default_pull_request ,c.other_repos,class_='refs')}:${h.select('other_ref','',c.other_refs,class_='refs')}
49 </span>
57 </span>
50 <div style="padding:5px 3px 3px 42px;">${c.rhodecode_db_repo.description}</div>
58 <div style="padding:5px 3px 3px 42px;">${c.rhodecode_db_repo.description}</div>
51 </div>
59 </div>
52 <div style="clear:both;padding-top: 10px"></div>
60 <div style="clear:both;padding-top: 10px"></div>
53 </div>
61 </div>
54 <div style="float:left;padding:5px 5px 5px 15px">
62 <div style="clear:both;padding-top: 10px"></div>
55 <span>
63 ## overview pulled by ajax
56 <a id="refresh" href="#">
64 <div style="float:left" id="pull_request_overview"></div>
57 <img class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/>
58 ${_('refresh overview')}
59 </a>
60 </span>
61 </div>
62 <div style="clear:both;padding-top: 10px"></div>
63 <div style="float:left" id="pull_request_overview">
64 </div>
65 <div style="float:left;clear:both;padding:10px 10px 10px 0px;display:none">
65 <div style="float:left;clear:both;padding:10px 10px 10px 0px;display:none">
66 <a id="pull_request_overview_url" href="#">${_('Detailed compare view')}</a>
66 <a id="pull_request_overview_url" href="#">${_('Detailed compare view')}</a>
67 </div>
67 </div>
68 </div>
68 </div>
69 <div style="float:left; border-left:1px dashed #eee">
69 <div style="float:left; border-left:1px dashed #eee">
70 <h4>${_('Pull request reviewers')}</h4>
70 <h4>${_('Pull request reviewers')}</h4>
@@ -75,7 +75,7 b''
75 <td>
75 <td>
76 <div>
76 <div>
77 <div style="float:left">
77 <div style="float:left">
78 <div class="text" style="padding: 0px 0px 6px;">${_('Choosen reviewers')}</div>
78 <div class="text" style="padding: 0px 0px 6px;">${_('Chosen reviewers')}</div>
79 ${h.select('review_members',[x[0] for x in c.review_members],c.review_members,multiple=True,size=8,style="min-width:210px")}
79 ${h.select('review_members',[x[0] for x in c.review_members],c.review_members,multiple=True,size=8,style="min-width:210px")}
80 <div id="remove_all_elements" style="cursor:pointer;text-align:center">
80 <div id="remove_all_elements" style="cursor:pointer;text-align:center">
81 ${_('Remove all elements')}
81 ${_('Remove all elements')}
@@ -102,11 +102,11 b''
102 </div>
102 </div>
103 </td>
103 </td>
104 </tr>
104 </tr>
105 </table>
105 </table>
106 </div>
106 </div>
107 </div>
107 </div>
108 <h3>${_('Create new pull request')}</h3>
108 <h3>${_('Create new pull request')}</h3>
109
109
110 <div class="form">
110 <div class="form">
111 <!-- fields -->
111 <!-- fields -->
112
112
@@ -136,23 +136,24 b''
136 </div>
136 </div>
137 </div>
137 </div>
138 </div>
138 </div>
139 ${h.end_form()}
139 ${h.end_form()}
140
140
141 </div>
141 </div>
142
142
143 <script type="text/javascript">
143 <script type="text/javascript">
144 MultiSelectWidget('review_members','available_members','pull_request_form');
144 MultiSelectWidget('review_members','available_members','pull_request_form');
145
145
146 var loadPreview = function(){
146 var loadPreview = function(){
147 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
147 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
148 var url = "${h.url('compare_url',
148 var url = "${h.url('compare_url',
149 repo_name='org_repo',
149 repo_name='org_repo',
150 org_ref_type='branch', org_ref='org_ref',
150 org_ref_type='branch', org_ref='org_ref',
151 other_ref_type='branch', other_ref='other_ref',
151 other_ref_type='branch', other_ref='other_ref',
152 repo='other_repo')}";
152 repo='other_repo',
153
153 as_form=True)}";
154
154 var select_refs = YUQ('#pull_request_form select.refs')
155 var select_refs = YUQ('#pull_request_form select.refs')
155
156
156 for(var i=0;i<select_refs.length;i++){
157 for(var i=0;i<select_refs.length;i++){
157 var select_ref = select_refs[i];
158 var select_ref = select_refs[i];
158 var select_ref_data = select_ref.value.split(':');
159 var select_ref_data = select_ref.value.split(':');
@@ -162,31 +163,30 b''
162 key = select_ref.name+"_type";
163 key = select_ref.name+"_type";
163 val = select_ref_data[0];
164 val = select_ref_data[0];
164 url = url.replace(key,val);
165 url = url.replace(key,val);
165
166
166 key = select_ref.name;
167 key = select_ref.name;
167 val = select_ref_data[1];
168 val = select_ref_data[1];
168 url = url.replace(key,val);
169 url = url.replace(key,val);
169
170
170 }else{
171 }else{
171 key = select_ref.name;
172 key = select_ref.name;
172 val = select_ref.value;
173 val = select_ref.value;
173 url = url.replace(key,val);
174 url = url.replace(key,val);
174 }
175 }
175 }
176 }
176
177
177 ypjax(url,'pull_request_overview', function(data){
178 ypjax(url,'pull_request_overview', function(data){
178 YUD.get('pull_request_overview_url').href = url;
179 YUD.get('pull_request_overview_url').href = url;
179 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
180 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
180 })
181 })
181 }
182 }
182 YUE.on('refresh','click',function(e){
183 YUE.on('refresh','click',function(e){
183 loadPreview()
184 loadPreview()
184 })
185 })
185
186
186 //lazy load after 0.5
187 //lazy load overview after 0.5s
187
188 setTimeout(loadPreview, 500)
188 setTimeout(loadPreview,500)
189
189
190 </script>
190 </script>
191
191
192 </%def>
192 </%def>
@@ -1,7 +1,52 b''
1 from rhodecode.tests import *
1 from rhodecode.tests import *
2
2
3
3 class TestCompareController(TestController):
4 class TestCompareController(TestController):
4
5
5 def test_index(self):
6 def test_index_tag(self):
6 response = self.app.get(url(controller='compare', action='index'))
7 self.log_user()
7 # Test response...
8 tag1='0.1.3'
9 tag2='0.1.2'
10 response = self.app.get(url(controller='compare', action='index',
11 repo_name=HG_REPO,
12 org_ref_type="tag",
13 org_ref=tag1,
14 other_ref_type="tag",
15 other_ref=tag2,
16 ))
17 response.mustcontain('%s@%s -> %s@%s' % (HG_REPO, tag1, HG_REPO, tag2))
18 ## outgoing changesets between tags
19 response.mustcontain('''<a href="/%s/changeset/17544fbfcd33ffb439e2b728b5d526b1ef30bfcf">r120:17544fbfcd33</a>''' % HG_REPO)
20 response.mustcontain('''<a href="/%s/changeset/36e0fc9d2808c5022a24f49d6658330383ed8666">r119:36e0fc9d2808</a>''' % HG_REPO)
21 response.mustcontain('''<a href="/%s/changeset/bb1a3ab98cc45cb934a77dcabf87a5a598b59e97">r118:bb1a3ab98cc4</a>''' % HG_REPO)
22 response.mustcontain('''<a href="/%s/changeset/41fda979f02fda216374bf8edac4e83f69e7581c">r117:41fda979f02f</a>''' % HG_REPO)
23 response.mustcontain('''<a href="/%s/changeset/9749bfbfc0d2eba208d7947de266303b67c87cda">r116:9749bfbfc0d2</a>''' % HG_REPO)
24 response.mustcontain('''<a href="/%s/changeset/70d4cef8a37657ee4cf5aabb3bd9f68879769816">r115:70d4cef8a376</a>''' % HG_REPO)
25 response.mustcontain('''<a href="/%s/changeset/c5ddebc06eaaba3010c2d66ea6ec9d074eb0f678">r112:c5ddebc06eaa</a>''' % HG_REPO)
26
27 ## files diff
28 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--1c5cf9e91c12">docs/api/utils/index.rst</a></div>''' % (HG_REPO, tag1, tag2))
29 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--e3305437df55">test_and_report.sh</a></div>''' % (HG_REPO, tag1, tag2))
30 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--c8e92ef85cd1">.hgignore</a></div>''' % (HG_REPO, tag1, tag2))
31 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--6e08b694d687">.hgtags</a></div>''' % (HG_REPO, tag1, tag2))
32 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--2c14b00f3393">docs/api/index.rst</a></div>''' % (HG_REPO, tag1, tag2))
33 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--430ccbc82bdf">vcs/__init__.py</a></div>''' % (HG_REPO, tag1, tag2))
34 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--9c390eb52cd6">vcs/backends/hg.py</a></div>''' % (HG_REPO, tag1, tag2))
35 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--ebb592c595c0">vcs/utils/__init__.py</a></div>''' % (HG_REPO, tag1, tag2))
36 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--7abc741b5052">vcs/utils/annotate.py</a></div>''' % (HG_REPO, tag1, tag2))
37 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--2ef0ef106c56">vcs/utils/diffs.py</a></div>''' % (HG_REPO, tag1, tag2))
38 response.mustcontain('''<div class="node"><a href="/%s/compare/tag@%s...tag@%s#C--3150cb87d4b7">vcs/utils/lazy.py</a></div>''' % (HG_REPO, tag1, tag2))
39
40 def test_index_branch(self):
41 self.log_user()
42 response = self.app.get(url(controller='compare', action='index',
43 repo_name=HG_REPO,
44 org_ref_type="branch",
45 org_ref='default',
46 other_ref_type="branch",
47 other_ref='default',
48 ))
49
50 response.mustcontain('%s@default -> %s@default' % (HG_REPO, HG_REPO))
51 # branch are equal
52 response.mustcontain('<tr><td>No changesets</td></tr>')
@@ -1,7 +1,9 b''
1 from rhodecode.tests import *
1 from rhodecode.tests import *
2
2
3
3 class TestPullrequestsController(TestController):
4 class TestPullrequestsController(TestController):
4
5
5 def test_index(self):
6 def test_index(self):
6 response = self.app.get(url(controller='pullrequests', action='index'))
7 self.log_user()
7 # Test response...
8 response = self.app.get(url(controller='pullrequests', action='index',
9 repo_name=HG_REPO))
@@ -181,7 +181,7 b' class TestUser(unittest.TestCase):'
181 super(TestUser, self).__init__(methodName=methodName)
181 super(TestUser, self).__init__(methodName=methodName)
182
182
183 def test_create_and_remove(self):
183 def test_create_and_remove(self):
184 usr = UserModel().create_or_update(username=u'test_user',
184 usr = UserModel().create_or_update(username=u'test_user',
185 password=u'qweqwe',
185 password=u'qweqwe',
186 email=u'u232@rhodecode.org',
186 email=u'u232@rhodecode.org',
187 name=u'u1', lastname=u'u1')
187 name=u'u1', lastname=u'u1')
@@ -203,7 +203,7 b' class TestUser(unittest.TestCase):'
203 self.assertEqual(UsersGroupMember.query().all(), [])
203 self.assertEqual(UsersGroupMember.query().all(), [])
204
204
205 def test_additonal_email_as_main(self):
205 def test_additonal_email_as_main(self):
206 usr = UserModel().create_or_update(username=u'test_user',
206 usr = UserModel().create_or_update(username=u'test_user',
207 password=u'qweqwe',
207 password=u'qweqwe',
208 email=u'main_email@rhodecode.org',
208 email=u'main_email@rhodecode.org',
209 name=u'u1', lastname=u'u1')
209 name=u'u1', lastname=u'u1')
@@ -221,7 +221,7 b' class TestUser(unittest.TestCase):'
221 Session.commit()
221 Session.commit()
222
222
223 def test_extra_email_map(self):
223 def test_extra_email_map(self):
224 usr = UserModel().create_or_update(username=u'test_user',
224 usr = UserModel().create_or_update(username=u'test_user',
225 password=u'qweqwe',
225 password=u'qweqwe',
226 email=u'main_email@rhodecode.org',
226 email=u'main_email@rhodecode.org',
227 name=u'u1', lastname=u'u1')
227 name=u'u1', lastname=u'u1')
General Comments 0
You need to be logged in to leave comments. Login now