##// END OF EJS Templates
compare: swap org and other when they refer to different repos, ie are pull request style...
Mads Kiilerich -
r3322:c9b0f1d3 beta
parent child Browse files
Show More
@@ -1,648 +1,648 b''
1 """
1 """
2 Routes configuration
2 Routes configuration
3
3
4 The more specific and detailed routes should be defined first so they
4 The more specific and detailed routes should be defined first so they
5 may take precedent over the more generic routes. For more information
5 may take precedent over the more generic routes. For more information
6 refer to the routes manual at http://routes.groovie.org/docs/
6 refer to the routes manual at http://routes.groovie.org/docs/
7 """
7 """
8 from __future__ import with_statement
8 from __future__ import with_statement
9 from routes import Mapper
9 from routes import Mapper
10
10
11 # prefix for non repository related links needs to be prefixed with `/`
11 # prefix for non repository related links needs to be prefixed with `/`
12 ADMIN_PREFIX = '/_admin'
12 ADMIN_PREFIX = '/_admin'
13
13
14
14
15 def make_map(config):
15 def make_map(config):
16 """Create, configure and return the routes Mapper"""
16 """Create, configure and return the routes Mapper"""
17 rmap = Mapper(directory=config['pylons.paths']['controllers'],
17 rmap = Mapper(directory=config['pylons.paths']['controllers'],
18 always_scan=config['debug'])
18 always_scan=config['debug'])
19 rmap.minimization = False
19 rmap.minimization = False
20 rmap.explicit = False
20 rmap.explicit = False
21
21
22 from rhodecode.lib.utils import is_valid_repo
22 from rhodecode.lib.utils import is_valid_repo
23 from rhodecode.lib.utils import is_valid_repos_group
23 from rhodecode.lib.utils import is_valid_repos_group
24
24
25 def check_repo(environ, match_dict):
25 def check_repo(environ, match_dict):
26 """
26 """
27 check for valid repository for proper 404 handling
27 check for valid repository for proper 404 handling
28
28
29 :param environ:
29 :param environ:
30 :param match_dict:
30 :param match_dict:
31 """
31 """
32 from rhodecode.model.db import Repository
32 from rhodecode.model.db import Repository
33 repo_name = match_dict.get('repo_name')
33 repo_name = match_dict.get('repo_name')
34
34
35 if match_dict.get('f_path'):
35 if match_dict.get('f_path'):
36 #fix for multiple initial slashes that causes errors
36 #fix for multiple initial slashes that causes errors
37 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
37 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
38
38
39 try:
39 try:
40 by_id = repo_name.split('_')
40 by_id = repo_name.split('_')
41 if len(by_id) == 2 and by_id[1].isdigit() and by_id[0] == '':
41 if len(by_id) == 2 and by_id[1].isdigit() and by_id[0] == '':
42 repo_name = Repository.get(by_id[1]).repo_name
42 repo_name = Repository.get(by_id[1]).repo_name
43 match_dict['repo_name'] = repo_name
43 match_dict['repo_name'] = repo_name
44 except:
44 except:
45 pass
45 pass
46
46
47 return is_valid_repo(repo_name, config['base_path'])
47 return is_valid_repo(repo_name, config['base_path'])
48
48
49 def check_group(environ, match_dict):
49 def check_group(environ, match_dict):
50 """
50 """
51 check for valid repositories group for proper 404 handling
51 check for valid repositories group for proper 404 handling
52
52
53 :param environ:
53 :param environ:
54 :param match_dict:
54 :param match_dict:
55 """
55 """
56 repos_group_name = match_dict.get('group_name')
56 repos_group_name = match_dict.get('group_name')
57 return is_valid_repos_group(repos_group_name, config['base_path'])
57 return is_valid_repos_group(repos_group_name, config['base_path'])
58
58
59 def check_int(environ, match_dict):
59 def check_int(environ, match_dict):
60 return match_dict.get('id').isdigit()
60 return match_dict.get('id').isdigit()
61
61
62 # The ErrorController route (handles 404/500 error pages); it should
62 # The ErrorController route (handles 404/500 error pages); it should
63 # likely stay at the top, ensuring it can always be resolved
63 # likely stay at the top, ensuring it can always be resolved
64 rmap.connect('/error/{action}', controller='error')
64 rmap.connect('/error/{action}', controller='error')
65 rmap.connect('/error/{action}/{id}', controller='error')
65 rmap.connect('/error/{action}/{id}', controller='error')
66
66
67 #==========================================================================
67 #==========================================================================
68 # CUSTOM ROUTES HERE
68 # CUSTOM ROUTES HERE
69 #==========================================================================
69 #==========================================================================
70
70
71 #MAIN PAGE
71 #MAIN PAGE
72 rmap.connect('home', '/', controller='home', action='index')
72 rmap.connect('home', '/', controller='home', action='index')
73 rmap.connect('repo_switcher', '/repos', controller='home',
73 rmap.connect('repo_switcher', '/repos', controller='home',
74 action='repo_switcher')
74 action='repo_switcher')
75 rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*?}',
75 rmap.connect('branch_tag_switcher', '/branches-tags/{repo_name:.*?}',
76 controller='home', action='branch_tag_switcher')
76 controller='home', action='branch_tag_switcher')
77 rmap.connect('bugtracker',
77 rmap.connect('bugtracker',
78 "http://bitbucket.org/marcinkuzminski/rhodecode/issues",
78 "http://bitbucket.org/marcinkuzminski/rhodecode/issues",
79 _static=True)
79 _static=True)
80 rmap.connect('rst_help',
80 rmap.connect('rst_help',
81 "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
81 "http://docutils.sourceforge.net/docs/user/rst/quickref.html",
82 _static=True)
82 _static=True)
83 rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True)
83 rmap.connect('rhodecode_official', "http://rhodecode.org", _static=True)
84
84
85 #ADMIN REPOSITORY REST ROUTES
85 #ADMIN REPOSITORY REST ROUTES
86 with rmap.submapper(path_prefix=ADMIN_PREFIX,
86 with rmap.submapper(path_prefix=ADMIN_PREFIX,
87 controller='admin/repos') as m:
87 controller='admin/repos') as m:
88 m.connect("repos", "/repos",
88 m.connect("repos", "/repos",
89 action="create", conditions=dict(method=["POST"]))
89 action="create", conditions=dict(method=["POST"]))
90 m.connect("repos", "/repos",
90 m.connect("repos", "/repos",
91 action="index", conditions=dict(method=["GET"]))
91 action="index", conditions=dict(method=["GET"]))
92 m.connect("formatted_repos", "/repos.{format}",
92 m.connect("formatted_repos", "/repos.{format}",
93 action="index",
93 action="index",
94 conditions=dict(method=["GET"]))
94 conditions=dict(method=["GET"]))
95 m.connect("new_repo", "/repos/new",
95 m.connect("new_repo", "/repos/new",
96 action="new", conditions=dict(method=["GET"]))
96 action="new", conditions=dict(method=["GET"]))
97 m.connect("formatted_new_repo", "/repos/new.{format}",
97 m.connect("formatted_new_repo", "/repos/new.{format}",
98 action="new", conditions=dict(method=["GET"]))
98 action="new", conditions=dict(method=["GET"]))
99 m.connect("/repos/{repo_name:.*?}",
99 m.connect("/repos/{repo_name:.*?}",
100 action="update", conditions=dict(method=["PUT"],
100 action="update", conditions=dict(method=["PUT"],
101 function=check_repo))
101 function=check_repo))
102 m.connect("/repos/{repo_name:.*?}",
102 m.connect("/repos/{repo_name:.*?}",
103 action="delete", conditions=dict(method=["DELETE"],
103 action="delete", conditions=dict(method=["DELETE"],
104 function=check_repo))
104 function=check_repo))
105 # no longer used:
105 # no longer used:
106 m.connect("edit_repo_admin", "/repos/{repo_name:.*?}/edit",
106 m.connect("edit_repo_admin", "/repos/{repo_name:.*?}/edit",
107 action="edit", conditions=dict(method=["GET"],
107 action="edit", conditions=dict(method=["GET"],
108 function=check_repo))
108 function=check_repo))
109 m.connect("formatted_edit_repo", "/repos/{repo_name:.*?}.{format}/edit",
109 m.connect("formatted_edit_repo", "/repos/{repo_name:.*?}.{format}/edit",
110 action="edit", conditions=dict(method=["GET"],
110 action="edit", conditions=dict(method=["GET"],
111 function=check_repo))
111 function=check_repo))
112 m.connect("repo", "/repos/{repo_name:.*?}",
112 m.connect("repo", "/repos/{repo_name:.*?}",
113 action="show", conditions=dict(method=["GET"],
113 action="show", conditions=dict(method=["GET"],
114 function=check_repo))
114 function=check_repo))
115 m.connect("formatted_repo", "/repos/{repo_name:.*?}.{format}",
115 m.connect("formatted_repo", "/repos/{repo_name:.*?}.{format}",
116 action="show", conditions=dict(method=["GET"],
116 action="show", conditions=dict(method=["GET"],
117 function=check_repo))
117 function=check_repo))
118 #ajax delete repo perm user
118 #ajax delete repo perm user
119 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*?}",
119 m.connect('delete_repo_user', "/repos_delete_user/{repo_name:.*?}",
120 action="delete_perm_user",
120 action="delete_perm_user",
121 conditions=dict(method=["DELETE"], function=check_repo))
121 conditions=dict(method=["DELETE"], function=check_repo))
122
122
123 #ajax delete repo perm users_group
123 #ajax delete repo perm users_group
124 m.connect('delete_repo_users_group',
124 m.connect('delete_repo_users_group',
125 "/repos_delete_users_group/{repo_name:.*?}",
125 "/repos_delete_users_group/{repo_name:.*?}",
126 action="delete_perm_users_group",
126 action="delete_perm_users_group",
127 conditions=dict(method=["DELETE"], function=check_repo))
127 conditions=dict(method=["DELETE"], function=check_repo))
128
128
129 #settings actions
129 #settings actions
130 m.connect('repo_stats', "/repos_stats/{repo_name:.*?}",
130 m.connect('repo_stats', "/repos_stats/{repo_name:.*?}",
131 action="repo_stats", conditions=dict(method=["DELETE"],
131 action="repo_stats", conditions=dict(method=["DELETE"],
132 function=check_repo))
132 function=check_repo))
133 m.connect('repo_cache', "/repos_cache/{repo_name:.*?}",
133 m.connect('repo_cache', "/repos_cache/{repo_name:.*?}",
134 action="repo_cache", conditions=dict(method=["DELETE"],
134 action="repo_cache", conditions=dict(method=["DELETE"],
135 function=check_repo))
135 function=check_repo))
136 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*?}",
136 m.connect('repo_public_journal', "/repos_public_journal/{repo_name:.*?}",
137 action="repo_public_journal", conditions=dict(method=["PUT"],
137 action="repo_public_journal", conditions=dict(method=["PUT"],
138 function=check_repo))
138 function=check_repo))
139 m.connect('repo_pull', "/repo_pull/{repo_name:.*?}",
139 m.connect('repo_pull', "/repo_pull/{repo_name:.*?}",
140 action="repo_pull", conditions=dict(method=["PUT"],
140 action="repo_pull", conditions=dict(method=["PUT"],
141 function=check_repo))
141 function=check_repo))
142 m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*?}",
142 m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*?}",
143 action="repo_as_fork", conditions=dict(method=["PUT"],
143 action="repo_as_fork", conditions=dict(method=["PUT"],
144 function=check_repo))
144 function=check_repo))
145 m.connect('repo_locking', "/repo_locking/{repo_name:.*?}",
145 m.connect('repo_locking', "/repo_locking/{repo_name:.*?}",
146 action="repo_locking", conditions=dict(method=["PUT"],
146 action="repo_locking", conditions=dict(method=["PUT"],
147 function=check_repo))
147 function=check_repo))
148 #repo fields
148 #repo fields
149 m.connect('create_repo_fields', "/repo_fields/{repo_name:.*?}/new",
149 m.connect('create_repo_fields', "/repo_fields/{repo_name:.*?}/new",
150 action="create_repo_field", conditions=dict(method=["PUT"],
150 action="create_repo_field", conditions=dict(method=["PUT"],
151 function=check_repo))
151 function=check_repo))
152
152
153 m.connect('delete_repo_fields', "/repo_fields/{repo_name:.*?}/{field_id}",
153 m.connect('delete_repo_fields', "/repo_fields/{repo_name:.*?}/{field_id}",
154 action="delete_repo_field", conditions=dict(method=["DELETE"],
154 action="delete_repo_field", conditions=dict(method=["DELETE"],
155 function=check_repo))
155 function=check_repo))
156
156
157 with rmap.submapper(path_prefix=ADMIN_PREFIX,
157 with rmap.submapper(path_prefix=ADMIN_PREFIX,
158 controller='admin/repos_groups') as m:
158 controller='admin/repos_groups') as m:
159 m.connect("repos_groups", "/repos_groups",
159 m.connect("repos_groups", "/repos_groups",
160 action="create", conditions=dict(method=["POST"]))
160 action="create", conditions=dict(method=["POST"]))
161 m.connect("repos_groups", "/repos_groups",
161 m.connect("repos_groups", "/repos_groups",
162 action="index", conditions=dict(method=["GET"]))
162 action="index", conditions=dict(method=["GET"]))
163 m.connect("formatted_repos_groups", "/repos_groups.{format}",
163 m.connect("formatted_repos_groups", "/repos_groups.{format}",
164 action="index", conditions=dict(method=["GET"]))
164 action="index", conditions=dict(method=["GET"]))
165 m.connect("new_repos_group", "/repos_groups/new",
165 m.connect("new_repos_group", "/repos_groups/new",
166 action="new", conditions=dict(method=["GET"]))
166 action="new", conditions=dict(method=["GET"]))
167 m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
167 m.connect("formatted_new_repos_group", "/repos_groups/new.{format}",
168 action="new", conditions=dict(method=["GET"]))
168 action="new", conditions=dict(method=["GET"]))
169 m.connect("update_repos_group", "/repos_groups/{group_name:.*?}",
169 m.connect("update_repos_group", "/repos_groups/{group_name:.*?}",
170 action="update", conditions=dict(method=["PUT"],
170 action="update", conditions=dict(method=["PUT"],
171 function=check_group))
171 function=check_group))
172 m.connect("delete_repos_group", "/repos_groups/{group_name:.*?}",
172 m.connect("delete_repos_group", "/repos_groups/{group_name:.*?}",
173 action="delete", conditions=dict(method=["DELETE"],
173 action="delete", conditions=dict(method=["DELETE"],
174 function=check_group))
174 function=check_group))
175 m.connect("edit_repos_group", "/repos_groups/{group_name:.*?}/edit",
175 m.connect("edit_repos_group", "/repos_groups/{group_name:.*?}/edit",
176 action="edit", conditions=dict(method=["GET"],))
176 action="edit", conditions=dict(method=["GET"],))
177 m.connect("formatted_edit_repos_group",
177 m.connect("formatted_edit_repos_group",
178 "/repos_groups/{group_name:.*?}.{format}/edit",
178 "/repos_groups/{group_name:.*?}.{format}/edit",
179 action="edit", conditions=dict(method=["GET"],
179 action="edit", conditions=dict(method=["GET"],
180 function=check_group))
180 function=check_group))
181 m.connect("repos_group", "/repos_groups/{group_name:.*?}",
181 m.connect("repos_group", "/repos_groups/{group_name:.*?}",
182 action="show", conditions=dict(method=["GET"],
182 action="show", conditions=dict(method=["GET"],
183 function=check_group))
183 function=check_group))
184 m.connect("formatted_repos_group", "/repos_groups/{group_name:.*?}.{format}",
184 m.connect("formatted_repos_group", "/repos_groups/{group_name:.*?}.{format}",
185 action="show", conditions=dict(method=["GET"],
185 action="show", conditions=dict(method=["GET"],
186 function=check_group))
186 function=check_group))
187 # ajax delete repos group perm user
187 # ajax delete repos group perm user
188 m.connect('delete_repos_group_user_perm',
188 m.connect('delete_repos_group_user_perm',
189 "/delete_repos_group_user_perm/{group_name:.*?}",
189 "/delete_repos_group_user_perm/{group_name:.*?}",
190 action="delete_repos_group_user_perm",
190 action="delete_repos_group_user_perm",
191 conditions=dict(method=["DELETE"], function=check_group))
191 conditions=dict(method=["DELETE"], function=check_group))
192
192
193 # ajax delete repos group perm users_group
193 # ajax delete repos group perm users_group
194 m.connect('delete_repos_group_users_group_perm',
194 m.connect('delete_repos_group_users_group_perm',
195 "/delete_repos_group_users_group_perm/{group_name:.*?}",
195 "/delete_repos_group_users_group_perm/{group_name:.*?}",
196 action="delete_repos_group_users_group_perm",
196 action="delete_repos_group_users_group_perm",
197 conditions=dict(method=["DELETE"], function=check_group))
197 conditions=dict(method=["DELETE"], function=check_group))
198
198
199 #ADMIN USER REST ROUTES
199 #ADMIN USER REST ROUTES
200 with rmap.submapper(path_prefix=ADMIN_PREFIX,
200 with rmap.submapper(path_prefix=ADMIN_PREFIX,
201 controller='admin/users') as m:
201 controller='admin/users') as m:
202 m.connect("users", "/users",
202 m.connect("users", "/users",
203 action="create", conditions=dict(method=["POST"]))
203 action="create", conditions=dict(method=["POST"]))
204 m.connect("users", "/users",
204 m.connect("users", "/users",
205 action="index", conditions=dict(method=["GET"]))
205 action="index", conditions=dict(method=["GET"]))
206 m.connect("formatted_users", "/users.{format}",
206 m.connect("formatted_users", "/users.{format}",
207 action="index", conditions=dict(method=["GET"]))
207 action="index", conditions=dict(method=["GET"]))
208 m.connect("new_user", "/users/new",
208 m.connect("new_user", "/users/new",
209 action="new", conditions=dict(method=["GET"]))
209 action="new", conditions=dict(method=["GET"]))
210 m.connect("formatted_new_user", "/users/new.{format}",
210 m.connect("formatted_new_user", "/users/new.{format}",
211 action="new", conditions=dict(method=["GET"]))
211 action="new", conditions=dict(method=["GET"]))
212 m.connect("update_user", "/users/{id}",
212 m.connect("update_user", "/users/{id}",
213 action="update", conditions=dict(method=["PUT"]))
213 action="update", conditions=dict(method=["PUT"]))
214 m.connect("delete_user", "/users/{id}",
214 m.connect("delete_user", "/users/{id}",
215 action="delete", conditions=dict(method=["DELETE"]))
215 action="delete", conditions=dict(method=["DELETE"]))
216 m.connect("edit_user", "/users/{id}/edit",
216 m.connect("edit_user", "/users/{id}/edit",
217 action="edit", conditions=dict(method=["GET"]))
217 action="edit", conditions=dict(method=["GET"]))
218 m.connect("formatted_edit_user",
218 m.connect("formatted_edit_user",
219 "/users/{id}.{format}/edit",
219 "/users/{id}.{format}/edit",
220 action="edit", conditions=dict(method=["GET"]))
220 action="edit", conditions=dict(method=["GET"]))
221 m.connect("user", "/users/{id}",
221 m.connect("user", "/users/{id}",
222 action="show", conditions=dict(method=["GET"]))
222 action="show", conditions=dict(method=["GET"]))
223 m.connect("formatted_user", "/users/{id}.{format}",
223 m.connect("formatted_user", "/users/{id}.{format}",
224 action="show", conditions=dict(method=["GET"]))
224 action="show", conditions=dict(method=["GET"]))
225
225
226 #EXTRAS USER ROUTES
226 #EXTRAS USER ROUTES
227 m.connect("user_perm", "/users_perm/{id}",
227 m.connect("user_perm", "/users_perm/{id}",
228 action="update_perm", conditions=dict(method=["PUT"]))
228 action="update_perm", conditions=dict(method=["PUT"]))
229 m.connect("user_emails", "/users_emails/{id}",
229 m.connect("user_emails", "/users_emails/{id}",
230 action="add_email", conditions=dict(method=["PUT"]))
230 action="add_email", conditions=dict(method=["PUT"]))
231 m.connect("user_emails_delete", "/users_emails/{id}",
231 m.connect("user_emails_delete", "/users_emails/{id}",
232 action="delete_email", conditions=dict(method=["DELETE"]))
232 action="delete_email", conditions=dict(method=["DELETE"]))
233 m.connect("user_ips", "/users_ips/{id}",
233 m.connect("user_ips", "/users_ips/{id}",
234 action="add_ip", conditions=dict(method=["PUT"]))
234 action="add_ip", conditions=dict(method=["PUT"]))
235 m.connect("user_ips_delete", "/users_ips/{id}",
235 m.connect("user_ips_delete", "/users_ips/{id}",
236 action="delete_ip", conditions=dict(method=["DELETE"]))
236 action="delete_ip", conditions=dict(method=["DELETE"]))
237
237
238 #ADMIN USERS GROUPS REST ROUTES
238 #ADMIN USERS GROUPS REST ROUTES
239 with rmap.submapper(path_prefix=ADMIN_PREFIX,
239 with rmap.submapper(path_prefix=ADMIN_PREFIX,
240 controller='admin/users_groups') as m:
240 controller='admin/users_groups') as m:
241 m.connect("users_groups", "/users_groups",
241 m.connect("users_groups", "/users_groups",
242 action="create", conditions=dict(method=["POST"]))
242 action="create", conditions=dict(method=["POST"]))
243 m.connect("users_groups", "/users_groups",
243 m.connect("users_groups", "/users_groups",
244 action="index", conditions=dict(method=["GET"]))
244 action="index", conditions=dict(method=["GET"]))
245 m.connect("formatted_users_groups", "/users_groups.{format}",
245 m.connect("formatted_users_groups", "/users_groups.{format}",
246 action="index", conditions=dict(method=["GET"]))
246 action="index", conditions=dict(method=["GET"]))
247 m.connect("new_users_group", "/users_groups/new",
247 m.connect("new_users_group", "/users_groups/new",
248 action="new", conditions=dict(method=["GET"]))
248 action="new", conditions=dict(method=["GET"]))
249 m.connect("formatted_new_users_group", "/users_groups/new.{format}",
249 m.connect("formatted_new_users_group", "/users_groups/new.{format}",
250 action="new", conditions=dict(method=["GET"]))
250 action="new", conditions=dict(method=["GET"]))
251 m.connect("update_users_group", "/users_groups/{id}",
251 m.connect("update_users_group", "/users_groups/{id}",
252 action="update", conditions=dict(method=["PUT"]))
252 action="update", conditions=dict(method=["PUT"]))
253 m.connect("delete_users_group", "/users_groups/{id}",
253 m.connect("delete_users_group", "/users_groups/{id}",
254 action="delete", conditions=dict(method=["DELETE"]))
254 action="delete", conditions=dict(method=["DELETE"]))
255 m.connect("edit_users_group", "/users_groups/{id}/edit",
255 m.connect("edit_users_group", "/users_groups/{id}/edit",
256 action="edit", conditions=dict(method=["GET"]))
256 action="edit", conditions=dict(method=["GET"]))
257 m.connect("formatted_edit_users_group",
257 m.connect("formatted_edit_users_group",
258 "/users_groups/{id}.{format}/edit",
258 "/users_groups/{id}.{format}/edit",
259 action="edit", conditions=dict(method=["GET"]))
259 action="edit", conditions=dict(method=["GET"]))
260 m.connect("users_group", "/users_groups/{id}",
260 m.connect("users_group", "/users_groups/{id}",
261 action="show", conditions=dict(method=["GET"]))
261 action="show", conditions=dict(method=["GET"]))
262 m.connect("formatted_users_group", "/users_groups/{id}.{format}",
262 m.connect("formatted_users_group", "/users_groups/{id}.{format}",
263 action="show", conditions=dict(method=["GET"]))
263 action="show", conditions=dict(method=["GET"]))
264
264
265 #EXTRAS USER ROUTES
265 #EXTRAS USER ROUTES
266 m.connect("users_group_perm", "/users_groups_perm/{id}",
266 m.connect("users_group_perm", "/users_groups_perm/{id}",
267 action="update_perm", conditions=dict(method=["PUT"]))
267 action="update_perm", conditions=dict(method=["PUT"]))
268
268
269 #ADMIN GROUP REST ROUTES
269 #ADMIN GROUP REST ROUTES
270 rmap.resource('group', 'groups',
270 rmap.resource('group', 'groups',
271 controller='admin/groups', path_prefix=ADMIN_PREFIX)
271 controller='admin/groups', path_prefix=ADMIN_PREFIX)
272
272
273 #ADMIN PERMISSIONS REST ROUTES
273 #ADMIN PERMISSIONS REST ROUTES
274 rmap.resource('permission', 'permissions',
274 rmap.resource('permission', 'permissions',
275 controller='admin/permissions', path_prefix=ADMIN_PREFIX)
275 controller='admin/permissions', path_prefix=ADMIN_PREFIX)
276
276
277 #ADMIN DEFAULTS REST ROUTES
277 #ADMIN DEFAULTS REST ROUTES
278 rmap.resource('default', 'defaults',
278 rmap.resource('default', 'defaults',
279 controller='admin/defaults', path_prefix=ADMIN_PREFIX)
279 controller='admin/defaults', path_prefix=ADMIN_PREFIX)
280
280
281 ##ADMIN LDAP SETTINGS
281 ##ADMIN LDAP SETTINGS
282 rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX,
282 rmap.connect('ldap_settings', '%s/ldap' % ADMIN_PREFIX,
283 controller='admin/ldap_settings', action='ldap_settings',
283 controller='admin/ldap_settings', action='ldap_settings',
284 conditions=dict(method=["POST"]))
284 conditions=dict(method=["POST"]))
285
285
286 rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX,
286 rmap.connect('ldap_home', '%s/ldap' % ADMIN_PREFIX,
287 controller='admin/ldap_settings')
287 controller='admin/ldap_settings')
288
288
289 #ADMIN SETTINGS REST ROUTES
289 #ADMIN SETTINGS REST ROUTES
290 with rmap.submapper(path_prefix=ADMIN_PREFIX,
290 with rmap.submapper(path_prefix=ADMIN_PREFIX,
291 controller='admin/settings') as m:
291 controller='admin/settings') as m:
292 m.connect("admin_settings", "/settings",
292 m.connect("admin_settings", "/settings",
293 action="create", conditions=dict(method=["POST"]))
293 action="create", conditions=dict(method=["POST"]))
294 m.connect("admin_settings", "/settings",
294 m.connect("admin_settings", "/settings",
295 action="index", conditions=dict(method=["GET"]))
295 action="index", conditions=dict(method=["GET"]))
296 m.connect("formatted_admin_settings", "/settings.{format}",
296 m.connect("formatted_admin_settings", "/settings.{format}",
297 action="index", conditions=dict(method=["GET"]))
297 action="index", conditions=dict(method=["GET"]))
298 m.connect("admin_new_setting", "/settings/new",
298 m.connect("admin_new_setting", "/settings/new",
299 action="new", conditions=dict(method=["GET"]))
299 action="new", conditions=dict(method=["GET"]))
300 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
300 m.connect("formatted_admin_new_setting", "/settings/new.{format}",
301 action="new", conditions=dict(method=["GET"]))
301 action="new", conditions=dict(method=["GET"]))
302 m.connect("/settings/{setting_id}",
302 m.connect("/settings/{setting_id}",
303 action="update", conditions=dict(method=["PUT"]))
303 action="update", conditions=dict(method=["PUT"]))
304 m.connect("/settings/{setting_id}",
304 m.connect("/settings/{setting_id}",
305 action="delete", conditions=dict(method=["DELETE"]))
305 action="delete", conditions=dict(method=["DELETE"]))
306 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
306 m.connect("admin_edit_setting", "/settings/{setting_id}/edit",
307 action="edit", conditions=dict(method=["GET"]))
307 action="edit", conditions=dict(method=["GET"]))
308 m.connect("formatted_admin_edit_setting",
308 m.connect("formatted_admin_edit_setting",
309 "/settings/{setting_id}.{format}/edit",
309 "/settings/{setting_id}.{format}/edit",
310 action="edit", conditions=dict(method=["GET"]))
310 action="edit", conditions=dict(method=["GET"]))
311 m.connect("admin_setting", "/settings/{setting_id}",
311 m.connect("admin_setting", "/settings/{setting_id}",
312 action="show", conditions=dict(method=["GET"]))
312 action="show", conditions=dict(method=["GET"]))
313 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
313 m.connect("formatted_admin_setting", "/settings/{setting_id}.{format}",
314 action="show", conditions=dict(method=["GET"]))
314 action="show", conditions=dict(method=["GET"]))
315 m.connect("admin_settings_my_account", "/my_account",
315 m.connect("admin_settings_my_account", "/my_account",
316 action="my_account", conditions=dict(method=["GET"]))
316 action="my_account", conditions=dict(method=["GET"]))
317 m.connect("admin_settings_my_account_update", "/my_account_update",
317 m.connect("admin_settings_my_account_update", "/my_account_update",
318 action="my_account_update", conditions=dict(method=["PUT"]))
318 action="my_account_update", conditions=dict(method=["PUT"]))
319 m.connect("admin_settings_create_repository", "/create_repository",
319 m.connect("admin_settings_create_repository", "/create_repository",
320 action="create_repository", conditions=dict(method=["GET"]))
320 action="create_repository", conditions=dict(method=["GET"]))
321 m.connect("admin_settings_my_repos", "/my_account/repos",
321 m.connect("admin_settings_my_repos", "/my_account/repos",
322 action="my_account_my_repos", conditions=dict(method=["GET"]))
322 action="my_account_my_repos", conditions=dict(method=["GET"]))
323 m.connect("admin_settings_my_pullrequests", "/my_account/pull_requests",
323 m.connect("admin_settings_my_pullrequests", "/my_account/pull_requests",
324 action="my_account_my_pullrequests", conditions=dict(method=["GET"]))
324 action="my_account_my_pullrequests", conditions=dict(method=["GET"]))
325
325
326 #NOTIFICATION REST ROUTES
326 #NOTIFICATION REST ROUTES
327 with rmap.submapper(path_prefix=ADMIN_PREFIX,
327 with rmap.submapper(path_prefix=ADMIN_PREFIX,
328 controller='admin/notifications') as m:
328 controller='admin/notifications') as m:
329 m.connect("notifications", "/notifications",
329 m.connect("notifications", "/notifications",
330 action="create", conditions=dict(method=["POST"]))
330 action="create", conditions=dict(method=["POST"]))
331 m.connect("notifications", "/notifications",
331 m.connect("notifications", "/notifications",
332 action="index", conditions=dict(method=["GET"]))
332 action="index", conditions=dict(method=["GET"]))
333 m.connect("notifications_mark_all_read", "/notifications/mark_all_read",
333 m.connect("notifications_mark_all_read", "/notifications/mark_all_read",
334 action="mark_all_read", conditions=dict(method=["GET"]))
334 action="mark_all_read", conditions=dict(method=["GET"]))
335 m.connect("formatted_notifications", "/notifications.{format}",
335 m.connect("formatted_notifications", "/notifications.{format}",
336 action="index", conditions=dict(method=["GET"]))
336 action="index", conditions=dict(method=["GET"]))
337 m.connect("new_notification", "/notifications/new",
337 m.connect("new_notification", "/notifications/new",
338 action="new", conditions=dict(method=["GET"]))
338 action="new", conditions=dict(method=["GET"]))
339 m.connect("formatted_new_notification", "/notifications/new.{format}",
339 m.connect("formatted_new_notification", "/notifications/new.{format}",
340 action="new", conditions=dict(method=["GET"]))
340 action="new", conditions=dict(method=["GET"]))
341 m.connect("/notification/{notification_id}",
341 m.connect("/notification/{notification_id}",
342 action="update", conditions=dict(method=["PUT"]))
342 action="update", conditions=dict(method=["PUT"]))
343 m.connect("/notification/{notification_id}",
343 m.connect("/notification/{notification_id}",
344 action="delete", conditions=dict(method=["DELETE"]))
344 action="delete", conditions=dict(method=["DELETE"]))
345 m.connect("edit_notification", "/notification/{notification_id}/edit",
345 m.connect("edit_notification", "/notification/{notification_id}/edit",
346 action="edit", conditions=dict(method=["GET"]))
346 action="edit", conditions=dict(method=["GET"]))
347 m.connect("formatted_edit_notification",
347 m.connect("formatted_edit_notification",
348 "/notification/{notification_id}.{format}/edit",
348 "/notification/{notification_id}.{format}/edit",
349 action="edit", conditions=dict(method=["GET"]))
349 action="edit", conditions=dict(method=["GET"]))
350 m.connect("notification", "/notification/{notification_id}",
350 m.connect("notification", "/notification/{notification_id}",
351 action="show", conditions=dict(method=["GET"]))
351 action="show", conditions=dict(method=["GET"]))
352 m.connect("formatted_notification", "/notifications/{notification_id}.{format}",
352 m.connect("formatted_notification", "/notifications/{notification_id}.{format}",
353 action="show", conditions=dict(method=["GET"]))
353 action="show", conditions=dict(method=["GET"]))
354
354
355 #ADMIN MAIN PAGES
355 #ADMIN MAIN PAGES
356 with rmap.submapper(path_prefix=ADMIN_PREFIX,
356 with rmap.submapper(path_prefix=ADMIN_PREFIX,
357 controller='admin/admin') as m:
357 controller='admin/admin') as m:
358 m.connect('admin_home', '', action='index')
358 m.connect('admin_home', '', action='index')
359 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
359 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
360 action='add_repo')
360 action='add_repo')
361
361
362 #==========================================================================
362 #==========================================================================
363 # API V2
363 # API V2
364 #==========================================================================
364 #==========================================================================
365 with rmap.submapper(path_prefix=ADMIN_PREFIX,
365 with rmap.submapper(path_prefix=ADMIN_PREFIX,
366 controller='api/api') as m:
366 controller='api/api') as m:
367 m.connect('api', '/api')
367 m.connect('api', '/api')
368
368
369 #USER JOURNAL
369 #USER JOURNAL
370 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX,
370 rmap.connect('journal', '%s/journal' % ADMIN_PREFIX,
371 controller='journal', action='index')
371 controller='journal', action='index')
372 rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX,
372 rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX,
373 controller='journal', action='journal_rss')
373 controller='journal', action='journal_rss')
374 rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX,
374 rmap.connect('journal_atom', '%s/journal/atom' % ADMIN_PREFIX,
375 controller='journal', action='journal_atom')
375 controller='journal', action='journal_atom')
376
376
377 rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
377 rmap.connect('public_journal', '%s/public_journal' % ADMIN_PREFIX,
378 controller='journal', action="public_journal")
378 controller='journal', action="public_journal")
379
379
380 rmap.connect('public_journal_rss', '%s/public_journal/rss' % ADMIN_PREFIX,
380 rmap.connect('public_journal_rss', '%s/public_journal/rss' % ADMIN_PREFIX,
381 controller='journal', action="public_journal_rss")
381 controller='journal', action="public_journal_rss")
382
382
383 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % ADMIN_PREFIX,
383 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % ADMIN_PREFIX,
384 controller='journal', action="public_journal_rss")
384 controller='journal', action="public_journal_rss")
385
385
386 rmap.connect('public_journal_atom',
386 rmap.connect('public_journal_atom',
387 '%s/public_journal/atom' % ADMIN_PREFIX, controller='journal',
387 '%s/public_journal/atom' % ADMIN_PREFIX, controller='journal',
388 action="public_journal_atom")
388 action="public_journal_atom")
389
389
390 rmap.connect('public_journal_atom_old',
390 rmap.connect('public_journal_atom_old',
391 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
391 '%s/public_journal_atom' % ADMIN_PREFIX, controller='journal',
392 action="public_journal_atom")
392 action="public_journal_atom")
393
393
394 rmap.connect('toggle_following', '%s/toggle_following' % ADMIN_PREFIX,
394 rmap.connect('toggle_following', '%s/toggle_following' % ADMIN_PREFIX,
395 controller='journal', action='toggle_following',
395 controller='journal', action='toggle_following',
396 conditions=dict(method=["POST"]))
396 conditions=dict(method=["POST"]))
397
397
398 #SEARCH
398 #SEARCH
399 rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',)
399 rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',)
400 rmap.connect('search_repo_admin', '%s/search/{repo_name:.*}' % ADMIN_PREFIX,
400 rmap.connect('search_repo_admin', '%s/search/{repo_name:.*}' % ADMIN_PREFIX,
401 controller='search',
401 controller='search',
402 conditions=dict(function=check_repo))
402 conditions=dict(function=check_repo))
403 rmap.connect('search_repo', '/{repo_name:.*?}/search',
403 rmap.connect('search_repo', '/{repo_name:.*?}/search',
404 controller='search',
404 controller='search',
405 conditions=dict(function=check_repo),
405 conditions=dict(function=check_repo),
406 )
406 )
407
407
408 #LOGIN/LOGOUT/REGISTER/SIGN IN
408 #LOGIN/LOGOUT/REGISTER/SIGN IN
409 rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
409 rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login')
410 rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
410 rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login',
411 action='logout')
411 action='logout')
412
412
413 rmap.connect('register', '%s/register' % ADMIN_PREFIX, controller='login',
413 rmap.connect('register', '%s/register' % ADMIN_PREFIX, controller='login',
414 action='register')
414 action='register')
415
415
416 rmap.connect('reset_password', '%s/password_reset' % ADMIN_PREFIX,
416 rmap.connect('reset_password', '%s/password_reset' % ADMIN_PREFIX,
417 controller='login', action='password_reset')
417 controller='login', action='password_reset')
418
418
419 rmap.connect('reset_password_confirmation',
419 rmap.connect('reset_password_confirmation',
420 '%s/password_reset_confirmation' % ADMIN_PREFIX,
420 '%s/password_reset_confirmation' % ADMIN_PREFIX,
421 controller='login', action='password_reset_confirmation')
421 controller='login', action='password_reset_confirmation')
422
422
423 #FEEDS
423 #FEEDS
424 rmap.connect('rss_feed_home', '/{repo_name:.*?}/feed/rss',
424 rmap.connect('rss_feed_home', '/{repo_name:.*?}/feed/rss',
425 controller='feed', action='rss',
425 controller='feed', action='rss',
426 conditions=dict(function=check_repo))
426 conditions=dict(function=check_repo))
427
427
428 rmap.connect('atom_feed_home', '/{repo_name:.*?}/feed/atom',
428 rmap.connect('atom_feed_home', '/{repo_name:.*?}/feed/atom',
429 controller='feed', action='atom',
429 controller='feed', action='atom',
430 conditions=dict(function=check_repo))
430 conditions=dict(function=check_repo))
431
431
432 #==========================================================================
432 #==========================================================================
433 # REPOSITORY ROUTES
433 # REPOSITORY ROUTES
434 #==========================================================================
434 #==========================================================================
435 rmap.connect('summary_home', '/{repo_name:.*?}',
435 rmap.connect('summary_home', '/{repo_name:.*?}',
436 controller='summary',
436 controller='summary',
437 conditions=dict(function=check_repo))
437 conditions=dict(function=check_repo))
438
438
439 rmap.connect('repo_size', '/{repo_name:.*?}/repo_size',
439 rmap.connect('repo_size', '/{repo_name:.*?}/repo_size',
440 controller='summary', action='repo_size',
440 controller='summary', action='repo_size',
441 conditions=dict(function=check_repo))
441 conditions=dict(function=check_repo))
442
442
443 rmap.connect('repos_group_home', '/{group_name:.*}',
443 rmap.connect('repos_group_home', '/{group_name:.*}',
444 controller='admin/repos_groups', action="show_by_name",
444 controller='admin/repos_groups', action="show_by_name",
445 conditions=dict(function=check_group))
445 conditions=dict(function=check_group))
446
446
447 rmap.connect('changeset_home', '/{repo_name:.*?}/changeset/{revision}',
447 rmap.connect('changeset_home', '/{repo_name:.*?}/changeset/{revision}',
448 controller='changeset', revision='tip',
448 controller='changeset', revision='tip',
449 conditions=dict(function=check_repo))
449 conditions=dict(function=check_repo))
450
450
451 rmap.connect("edit_repo", "/{repo_name:.*?}/edit",
451 rmap.connect("edit_repo", "/{repo_name:.*?}/edit",
452 controller='admin/repos', action="edit",
452 controller='admin/repos', action="edit",
453 conditions=dict(method=["GET"], function=check_repo)
453 conditions=dict(method=["GET"], function=check_repo)
454 )
454 )
455
455
456 #still working url for backward compat.
456 #still working url for backward compat.
457 rmap.connect('raw_changeset_home_depraced',
457 rmap.connect('raw_changeset_home_depraced',
458 '/{repo_name:.*?}/raw-changeset/{revision}',
458 '/{repo_name:.*?}/raw-changeset/{revision}',
459 controller='changeset', action='changeset_raw',
459 controller='changeset', action='changeset_raw',
460 revision='tip', conditions=dict(function=check_repo))
460 revision='tip', conditions=dict(function=check_repo))
461
461
462 ## new URLs
462 ## new URLs
463 rmap.connect('changeset_raw_home',
463 rmap.connect('changeset_raw_home',
464 '/{repo_name:.*?}/changeset-diff/{revision}',
464 '/{repo_name:.*?}/changeset-diff/{revision}',
465 controller='changeset', action='changeset_raw',
465 controller='changeset', action='changeset_raw',
466 revision='tip', conditions=dict(function=check_repo))
466 revision='tip', conditions=dict(function=check_repo))
467
467
468 rmap.connect('changeset_patch_home',
468 rmap.connect('changeset_patch_home',
469 '/{repo_name:.*?}/changeset-patch/{revision}',
469 '/{repo_name:.*?}/changeset-patch/{revision}',
470 controller='changeset', action='changeset_patch',
470 controller='changeset', action='changeset_patch',
471 revision='tip', conditions=dict(function=check_repo))
471 revision='tip', conditions=dict(function=check_repo))
472
472
473 rmap.connect('changeset_download_home',
473 rmap.connect('changeset_download_home',
474 '/{repo_name:.*?}/changeset-download/{revision}',
474 '/{repo_name:.*?}/changeset-download/{revision}',
475 controller='changeset', action='changeset_download',
475 controller='changeset', action='changeset_download',
476 revision='tip', conditions=dict(function=check_repo))
476 revision='tip', conditions=dict(function=check_repo))
477
477
478 rmap.connect('changeset_comment',
478 rmap.connect('changeset_comment',
479 '/{repo_name:.*?}/changeset/{revision}/comment',
479 '/{repo_name:.*?}/changeset/{revision}/comment',
480 controller='changeset', revision='tip', action='comment',
480 controller='changeset', revision='tip', action='comment',
481 conditions=dict(function=check_repo))
481 conditions=dict(function=check_repo))
482
482
483 rmap.connect('changeset_comment_delete',
483 rmap.connect('changeset_comment_delete',
484 '/{repo_name:.*?}/changeset/comment/{comment_id}/delete',
484 '/{repo_name:.*?}/changeset/comment/{comment_id}/delete',
485 controller='changeset', action='delete_comment',
485 controller='changeset', action='delete_comment',
486 conditions=dict(function=check_repo, method=["DELETE"]))
486 conditions=dict(function=check_repo, method=["DELETE"]))
487
487
488 rmap.connect('changeset_info', '/changeset_info/{repo_name:.*?}/{revision}',
488 rmap.connect('changeset_info', '/changeset_info/{repo_name:.*?}/{revision}',
489 controller='changeset', action='changeset_info')
489 controller='changeset', action='changeset_info')
490
490
491 rmap.connect('compare_url',
491 rmap.connect('compare_url',
492 '/{repo_name:.*?}/compare/{org_ref_type}@{org_ref:.*?}...{other_ref_type}@{other_ref:.*?}',
492 '/{repo_name:.*?}/compare/{org_ref_type}@{org_ref:.*?}...{other_ref_type}@{other_ref:.*?}',
493 controller='compare', action='index',
493 controller='compare', action='index',
494 conditions=dict(function=check_repo),
494 conditions=dict(function=check_repo),
495 requirements=dict(
495 requirements=dict(
496 org_ref_type='(branch|book|tag|rev|__org_ref_type__)',
496 org_ref_type='(branch|book|tag|rev|__other_ref_type__)',
497 other_ref_type='(branch|book|tag|rev|__other_ref_type__)')
497 other_ref_type='(branch|book|tag|rev|__org_ref_type__)')
498 )
498 )
499
499
500 rmap.connect('pullrequest_home',
500 rmap.connect('pullrequest_home',
501 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
501 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
502 action='index', conditions=dict(function=check_repo,
502 action='index', conditions=dict(function=check_repo,
503 method=["GET"]))
503 method=["GET"]))
504
504
505 rmap.connect('pullrequest',
505 rmap.connect('pullrequest',
506 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
506 '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
507 action='create', conditions=dict(function=check_repo,
507 action='create', conditions=dict(function=check_repo,
508 method=["POST"]))
508 method=["POST"]))
509
509
510 rmap.connect('pullrequest_show',
510 rmap.connect('pullrequest_show',
511 '/{repo_name:.*?}/pull-request/{pull_request_id}',
511 '/{repo_name:.*?}/pull-request/{pull_request_id}',
512 controller='pullrequests',
512 controller='pullrequests',
513 action='show', conditions=dict(function=check_repo,
513 action='show', conditions=dict(function=check_repo,
514 method=["GET"]))
514 method=["GET"]))
515 rmap.connect('pullrequest_update',
515 rmap.connect('pullrequest_update',
516 '/{repo_name:.*?}/pull-request/{pull_request_id}',
516 '/{repo_name:.*?}/pull-request/{pull_request_id}',
517 controller='pullrequests',
517 controller='pullrequests',
518 action='update', conditions=dict(function=check_repo,
518 action='update', conditions=dict(function=check_repo,
519 method=["PUT"]))
519 method=["PUT"]))
520 rmap.connect('pullrequest_delete',
520 rmap.connect('pullrequest_delete',
521 '/{repo_name:.*?}/pull-request/{pull_request_id}',
521 '/{repo_name:.*?}/pull-request/{pull_request_id}',
522 controller='pullrequests',
522 controller='pullrequests',
523 action='delete', conditions=dict(function=check_repo,
523 action='delete', conditions=dict(function=check_repo,
524 method=["DELETE"]))
524 method=["DELETE"]))
525
525
526 rmap.connect('pullrequest_show_all',
526 rmap.connect('pullrequest_show_all',
527 '/{repo_name:.*?}/pull-request',
527 '/{repo_name:.*?}/pull-request',
528 controller='pullrequests',
528 controller='pullrequests',
529 action='show_all', conditions=dict(function=check_repo,
529 action='show_all', conditions=dict(function=check_repo,
530 method=["GET"]))
530 method=["GET"]))
531
531
532 rmap.connect('pullrequest_comment',
532 rmap.connect('pullrequest_comment',
533 '/{repo_name:.*?}/pull-request-comment/{pull_request_id}',
533 '/{repo_name:.*?}/pull-request-comment/{pull_request_id}',
534 controller='pullrequests',
534 controller='pullrequests',
535 action='comment', conditions=dict(function=check_repo,
535 action='comment', conditions=dict(function=check_repo,
536 method=["POST"]))
536 method=["POST"]))
537
537
538 rmap.connect('pullrequest_comment_delete',
538 rmap.connect('pullrequest_comment_delete',
539 '/{repo_name:.*?}/pull-request-comment/{comment_id}/delete',
539 '/{repo_name:.*?}/pull-request-comment/{comment_id}/delete',
540 controller='pullrequests', action='delete_comment',
540 controller='pullrequests', action='delete_comment',
541 conditions=dict(function=check_repo, method=["DELETE"]))
541 conditions=dict(function=check_repo, method=["DELETE"]))
542
542
543 rmap.connect('summary_home_summary', '/{repo_name:.*?}/summary',
543 rmap.connect('summary_home_summary', '/{repo_name:.*?}/summary',
544 controller='summary', conditions=dict(function=check_repo))
544 controller='summary', conditions=dict(function=check_repo))
545
545
546 rmap.connect('shortlog_home', '/{repo_name:.*?}/shortlog',
546 rmap.connect('shortlog_home', '/{repo_name:.*?}/shortlog',
547 controller='shortlog', conditions=dict(function=check_repo))
547 controller='shortlog', conditions=dict(function=check_repo))
548
548
549 rmap.connect('shortlog_file_home', '/{repo_name:.*?}/shortlog/{revision}/{f_path:.*}',
549 rmap.connect('shortlog_file_home', '/{repo_name:.*?}/shortlog/{revision}/{f_path:.*}',
550 controller='shortlog', f_path=None,
550 controller='shortlog', f_path=None,
551 conditions=dict(function=check_repo))
551 conditions=dict(function=check_repo))
552
552
553 rmap.connect('branches_home', '/{repo_name:.*?}/branches',
553 rmap.connect('branches_home', '/{repo_name:.*?}/branches',
554 controller='branches', conditions=dict(function=check_repo))
554 controller='branches', conditions=dict(function=check_repo))
555
555
556 rmap.connect('tags_home', '/{repo_name:.*?}/tags',
556 rmap.connect('tags_home', '/{repo_name:.*?}/tags',
557 controller='tags', conditions=dict(function=check_repo))
557 controller='tags', conditions=dict(function=check_repo))
558
558
559 rmap.connect('bookmarks_home', '/{repo_name:.*?}/bookmarks',
559 rmap.connect('bookmarks_home', '/{repo_name:.*?}/bookmarks',
560 controller='bookmarks', conditions=dict(function=check_repo))
560 controller='bookmarks', conditions=dict(function=check_repo))
561
561
562 rmap.connect('changelog_home', '/{repo_name:.*?}/changelog',
562 rmap.connect('changelog_home', '/{repo_name:.*?}/changelog',
563 controller='changelog', conditions=dict(function=check_repo))
563 controller='changelog', conditions=dict(function=check_repo))
564
564
565 rmap.connect('changelog_details', '/{repo_name:.*?}/changelog_details/{cs}',
565 rmap.connect('changelog_details', '/{repo_name:.*?}/changelog_details/{cs}',
566 controller='changelog', action='changelog_details',
566 controller='changelog', action='changelog_details',
567 conditions=dict(function=check_repo))
567 conditions=dict(function=check_repo))
568
568
569 rmap.connect('files_home', '/{repo_name:.*?}/files/{revision}/{f_path:.*}',
569 rmap.connect('files_home', '/{repo_name:.*?}/files/{revision}/{f_path:.*}',
570 controller='files', revision='tip', f_path='',
570 controller='files', revision='tip', f_path='',
571 conditions=dict(function=check_repo))
571 conditions=dict(function=check_repo))
572
572
573 rmap.connect('files_history_home',
573 rmap.connect('files_history_home',
574 '/{repo_name:.*?}/history/{revision}/{f_path:.*}',
574 '/{repo_name:.*?}/history/{revision}/{f_path:.*}',
575 controller='files', action='history', revision='tip', f_path='',
575 controller='files', action='history', revision='tip', f_path='',
576 conditions=dict(function=check_repo))
576 conditions=dict(function=check_repo))
577
577
578 rmap.connect('files_diff_home', '/{repo_name:.*?}/diff/{f_path:.*}',
578 rmap.connect('files_diff_home', '/{repo_name:.*?}/diff/{f_path:.*}',
579 controller='files', action='diff', revision='tip', f_path='',
579 controller='files', action='diff', revision='tip', f_path='',
580 conditions=dict(function=check_repo))
580 conditions=dict(function=check_repo))
581
581
582 rmap.connect('files_rawfile_home',
582 rmap.connect('files_rawfile_home',
583 '/{repo_name:.*?}/rawfile/{revision}/{f_path:.*}',
583 '/{repo_name:.*?}/rawfile/{revision}/{f_path:.*}',
584 controller='files', action='rawfile', revision='tip',
584 controller='files', action='rawfile', revision='tip',
585 f_path='', conditions=dict(function=check_repo))
585 f_path='', conditions=dict(function=check_repo))
586
586
587 rmap.connect('files_raw_home',
587 rmap.connect('files_raw_home',
588 '/{repo_name:.*?}/raw/{revision}/{f_path:.*}',
588 '/{repo_name:.*?}/raw/{revision}/{f_path:.*}',
589 controller='files', action='raw', revision='tip', f_path='',
589 controller='files', action='raw', revision='tip', f_path='',
590 conditions=dict(function=check_repo))
590 conditions=dict(function=check_repo))
591
591
592 rmap.connect('files_annotate_home',
592 rmap.connect('files_annotate_home',
593 '/{repo_name:.*?}/annotate/{revision}/{f_path:.*}',
593 '/{repo_name:.*?}/annotate/{revision}/{f_path:.*}',
594 controller='files', action='index', revision='tip',
594 controller='files', action='index', revision='tip',
595 f_path='', annotate=True, conditions=dict(function=check_repo))
595 f_path='', annotate=True, conditions=dict(function=check_repo))
596
596
597 rmap.connect('files_edit_home',
597 rmap.connect('files_edit_home',
598 '/{repo_name:.*?}/edit/{revision}/{f_path:.*}',
598 '/{repo_name:.*?}/edit/{revision}/{f_path:.*}',
599 controller='files', action='edit', revision='tip',
599 controller='files', action='edit', revision='tip',
600 f_path='', conditions=dict(function=check_repo))
600 f_path='', conditions=dict(function=check_repo))
601
601
602 rmap.connect('files_add_home',
602 rmap.connect('files_add_home',
603 '/{repo_name:.*?}/add/{revision}/{f_path:.*}',
603 '/{repo_name:.*?}/add/{revision}/{f_path:.*}',
604 controller='files', action='add', revision='tip',
604 controller='files', action='add', revision='tip',
605 f_path='', conditions=dict(function=check_repo))
605 f_path='', conditions=dict(function=check_repo))
606
606
607 rmap.connect('files_archive_home', '/{repo_name:.*?}/archive/{fname}',
607 rmap.connect('files_archive_home', '/{repo_name:.*?}/archive/{fname}',
608 controller='files', action='archivefile',
608 controller='files', action='archivefile',
609 conditions=dict(function=check_repo))
609 conditions=dict(function=check_repo))
610
610
611 rmap.connect('files_nodelist_home',
611 rmap.connect('files_nodelist_home',
612 '/{repo_name:.*?}/nodelist/{revision}/{f_path:.*}',
612 '/{repo_name:.*?}/nodelist/{revision}/{f_path:.*}',
613 controller='files', action='nodelist',
613 controller='files', action='nodelist',
614 conditions=dict(function=check_repo))
614 conditions=dict(function=check_repo))
615
615
616 rmap.connect('repo_settings_delete', '/{repo_name:.*?}/settings',
616 rmap.connect('repo_settings_delete', '/{repo_name:.*?}/settings',
617 controller='settings', action="delete",
617 controller='settings', action="delete",
618 conditions=dict(method=["DELETE"], function=check_repo))
618 conditions=dict(method=["DELETE"], function=check_repo))
619
619
620 rmap.connect('repo_settings_update', '/{repo_name:.*?}/settings',
620 rmap.connect('repo_settings_update', '/{repo_name:.*?}/settings',
621 controller='settings', action="update",
621 controller='settings', action="update",
622 conditions=dict(method=["PUT"], function=check_repo))
622 conditions=dict(method=["PUT"], function=check_repo))
623
623
624 rmap.connect('repo_settings_home', '/{repo_name:.*?}/settings',
624 rmap.connect('repo_settings_home', '/{repo_name:.*?}/settings',
625 controller='settings', action='index',
625 controller='settings', action='index',
626 conditions=dict(function=check_repo))
626 conditions=dict(function=check_repo))
627
627
628 rmap.connect('toggle_locking', "/{repo_name:.*?}/locking_toggle",
628 rmap.connect('toggle_locking', "/{repo_name:.*?}/locking_toggle",
629 controller='settings', action="toggle_locking",
629 controller='settings', action="toggle_locking",
630 conditions=dict(method=["GET"], function=check_repo))
630 conditions=dict(method=["GET"], function=check_repo))
631
631
632 rmap.connect('repo_fork_create_home', '/{repo_name:.*?}/fork',
632 rmap.connect('repo_fork_create_home', '/{repo_name:.*?}/fork',
633 controller='forks', action='fork_create',
633 controller='forks', action='fork_create',
634 conditions=dict(function=check_repo, method=["POST"]))
634 conditions=dict(function=check_repo, method=["POST"]))
635
635
636 rmap.connect('repo_fork_home', '/{repo_name:.*?}/fork',
636 rmap.connect('repo_fork_home', '/{repo_name:.*?}/fork',
637 controller='forks', action='fork',
637 controller='forks', action='fork',
638 conditions=dict(function=check_repo))
638 conditions=dict(function=check_repo))
639
639
640 rmap.connect('repo_forks_home', '/{repo_name:.*?}/forks',
640 rmap.connect('repo_forks_home', '/{repo_name:.*?}/forks',
641 controller='forks', action='forks',
641 controller='forks', action='forks',
642 conditions=dict(function=check_repo))
642 conditions=dict(function=check_repo))
643
643
644 rmap.connect('repo_followers_home', '/{repo_name:.*?}/followers',
644 rmap.connect('repo_followers_home', '/{repo_name:.*?}/followers',
645 controller='followers', action='followers',
645 controller='followers', action='followers',
646 conditions=dict(function=check_repo))
646 conditions=dict(function=check_repo))
647
647
648 return rmap
648 return rmap
@@ -1,181 +1,181 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.controllers.compare
3 rhodecode.controllers.compare
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 compare controller for pylons showing differences between two
6 compare controller for pylons showing differences between two
7 repos, branches, bookmarks or tips
7 repos, branches, bookmarks or tips
8
8
9 :created_on: May 6, 2012
9 :created_on: May 6, 2012
10 :author: marcink
10 :author: marcink
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software: you can redistribute it and/or modify
14 # This program is free software: you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation, either version 3 of the License, or
16 # the Free Software Foundation, either version 3 of the License, or
17 # (at your option) any later version.
17 # (at your option) any later version.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 import logging
26 import logging
27 import traceback
27 import traceback
28
28
29 from webob.exc import HTTPNotFound
29 from webob.exc import HTTPNotFound
30 from pylons import request, response, session, tmpl_context as c, url
30 from pylons import request, response, session, tmpl_context as c, url
31 from pylons.controllers.util import abort, redirect
31 from pylons.controllers.util import abort, redirect
32 from pylons.i18n.translation import _
32 from pylons.i18n.translation import _
33
33
34 from rhodecode.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError
34 from rhodecode.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError
35 from rhodecode.lib import helpers as h
35 from rhodecode.lib import helpers as h
36 from rhodecode.lib.base import BaseRepoController, render
36 from rhodecode.lib.base import BaseRepoController, render
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
38 from rhodecode.lib import diffs
38 from rhodecode.lib import diffs
39
39
40 from rhodecode.model.db import Repository
40 from rhodecode.model.db import Repository
41 from rhodecode.model.pull_request import PullRequestModel
41 from rhodecode.model.pull_request import PullRequestModel
42 from webob.exc import HTTPBadRequest
42 from webob.exc import HTTPBadRequest
43 from rhodecode.lib.utils2 import str2bool
43 from rhodecode.lib.utils2 import str2bool
44 from rhodecode.lib.diffs import LimitedDiffContainer
44 from rhodecode.lib.diffs import LimitedDiffContainer
45 from rhodecode.lib.vcs.backends.base import EmptyChangeset
45 from rhodecode.lib.vcs.backends.base import EmptyChangeset
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 class CompareController(BaseRepoController):
50 class CompareController(BaseRepoController):
51
51
52 @LoginRequired()
52 @LoginRequired()
53 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
53 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
54 'repository.admin')
54 'repository.admin')
55 def __before__(self):
55 def __before__(self):
56 super(CompareController, self).__before__()
56 super(CompareController, self).__before__()
57
57
58 def __get_cs_or_redirect(self, rev, repo, redirect_after=True,
58 def __get_cs_or_redirect(self, rev, repo, redirect_after=True,
59 partial=False):
59 partial=False):
60 """
60 """
61 Safe way to get changeset if error occur it redirects to changeset with
61 Safe way to get changeset if error occur it redirects to changeset with
62 proper message. If partial is set then don't do redirect raise Exception
62 proper message. If partial is set then don't do redirect raise Exception
63 instead
63 instead
64
64
65 :param rev: revision to fetch
65 :param rev: revision to fetch
66 :param repo: repo instance
66 :param repo: repo instance
67 """
67 """
68
68
69 try:
69 try:
70 type_, rev = rev
70 type_, rev = rev
71 return repo.scm_instance.get_changeset(rev)
71 return repo.scm_instance.get_changeset(rev)
72 except EmptyRepositoryError, e:
72 except EmptyRepositoryError, e:
73 if not redirect_after:
73 if not redirect_after:
74 return None
74 return None
75 h.flash(h.literal(_('There are no changesets yet')),
75 h.flash(h.literal(_('There are no changesets yet')),
76 category='warning')
76 category='warning')
77 redirect(url('summary_home', repo_name=repo.repo_name))
77 redirect(url('summary_home', repo_name=repo.repo_name))
78
78
79 except RepositoryError, e:
79 except RepositoryError, e:
80 log.error(traceback.format_exc())
80 log.error(traceback.format_exc())
81 h.flash(str(e), category='warning')
81 h.flash(str(e), category='warning')
82 if not partial:
82 if not partial:
83 redirect(h.url('summary_home', repo_name=repo.repo_name))
83 redirect(h.url('summary_home', repo_name=repo.repo_name))
84 raise HTTPBadRequest()
84 raise HTTPBadRequest()
85
85
86 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
86 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
87
87
88 org_repo = c.rhodecode_db_repo.repo_name
88 org_repo = c.rhodecode_db_repo.repo_name
89 org_ref = (org_ref_type, org_ref)
89 org_ref = (org_ref_type, org_ref)
90 other_ref = (other_ref_type, other_ref)
90 other_ref = (other_ref_type, other_ref)
91 other_repo = request.GET.get('other_repo', org_repo)
91 other_repo = request.GET.get('other_repo', org_repo)
92 c.fulldiff = fulldiff = request.GET.get('fulldiff')
92 c.fulldiff = fulldiff = request.GET.get('fulldiff')
93 rev_start = request.GET.get('rev_start')
93 rev_start = request.GET.get('rev_start')
94 rev_end = request.GET.get('rev_end')
94 rev_end = request.GET.get('rev_end')
95
95
96 c.swap_url = h.url('compare_url', as_form=request.GET.get('as_form'),
96 c.swap_url = h.url('compare_url', as_form=request.GET.get('as_form'),
97 repo_name=other_repo,
97 repo_name=other_repo,
98 org_ref_type=other_ref[0], org_ref=other_ref[1],
98 org_ref_type=other_ref[0], org_ref=other_ref[1],
99 other_repo=org_repo,
99 other_repo=org_repo,
100 other_ref_type=org_ref[0], other_ref=org_ref[1])
100 other_ref_type=org_ref[0], other_ref=org_ref[1])
101
101
102 c.org_repo = org_repo = Repository.get_by_repo_name(org_repo)
102 c.org_repo = org_repo = Repository.get_by_repo_name(org_repo)
103 c.other_repo = other_repo = Repository.get_by_repo_name(other_repo)
103 c.other_repo = other_repo = Repository.get_by_repo_name(other_repo)
104
104
105 if c.org_repo is None:
105 if c.org_repo is None:
106 log.error('Could not find org repo %s' % org_repo)
106 log.error('Could not find org repo %s' % org_repo)
107 raise HTTPNotFound
107 raise HTTPNotFound
108 if c.other_repo is None:
108 if c.other_repo is None:
109 log.error('Could not find other repo %s' % other_repo)
109 log.error('Could not find other repo %s' % other_repo)
110 raise HTTPNotFound
110 raise HTTPNotFound
111
111
112 if c.org_repo != c.other_repo and h.is_git(c.rhodecode_repo):
112 if c.org_repo != c.other_repo and h.is_git(c.rhodecode_repo):
113 log.error('compare of two remote repos not available for GIT REPOS')
113 log.error('compare of two remote repos not available for GIT REPOS')
114 raise HTTPNotFound
114 raise HTTPNotFound
115
115
116 if c.org_repo.scm_instance.alias != c.other_repo.scm_instance.alias:
116 if c.org_repo.scm_instance.alias != c.other_repo.scm_instance.alias:
117 log.error('compare of two different kind of remote repos not available')
117 log.error('compare of two different kind of remote repos not available')
118 raise HTTPNotFound
118 raise HTTPNotFound
119
119
120 partial = request.environ.get('HTTP_X_PARTIAL_XHR')
120 partial = request.environ.get('HTTP_X_PARTIAL_XHR')
121 self.__get_cs_or_redirect(rev=org_ref, repo=org_repo, partial=partial)
121 self.__get_cs_or_redirect(rev=org_ref, repo=org_repo, partial=partial)
122 self.__get_cs_or_redirect(rev=other_ref, repo=other_repo, partial=partial)
122 self.__get_cs_or_redirect(rev=other_ref, repo=other_repo, partial=partial)
123
123
124 if rev_start and rev_end:
124 if rev_start and rev_end:
125 #replace our org_ref with given CS
125 #replace our org_ref with given CS
126 org_ref = ('rev', rev_start)
126 org_ref = ('rev', rev_start)
127 other_ref = ('rev', rev_end)
127 other_ref = ('rev', rev_end)
128
128
129 c.cs_ranges = PullRequestModel().get_compare_data(
129 c.cs_ranges = PullRequestModel().get_compare_data(
130 org_repo, org_ref, other_repo, other_ref,
130 org_repo, org_ref, other_repo, other_ref,
131 )
131 )
132
132
133 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
133 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
134 c.cs_ranges])
134 c.cs_ranges])
135 c.target_repo = c.repo_name
135 c.target_repo = c.other_repo.repo_name
136 # defines that we need hidden inputs with changesets
136 # defines that we need hidden inputs with changesets
137 c.as_form = request.GET.get('as_form', False)
137 c.as_form = request.GET.get('as_form', False)
138 if partial:
138 if partial:
139 return render('compare/compare_cs.html')
139 return render('compare/compare_cs.html')
140
140
141 c.org_ref = org_ref[1]
141 c.org_ref = org_ref[1]
142 c.other_ref = other_ref[1]
142 c.other_ref = other_ref[1]
143
143
144 if c.cs_ranges and c.org_repo != c.other_repo:
144 if c.cs_ranges and c.org_repo != c.other_repo:
145 # case we want a simple diff without incoming changesets, just
145 # case we want a simple diff without incoming changesets, just
146 # for review purposes. Make the diff on the forked repo, with
146 # for review purposes. Make the diff on the forked repo, with
147 # revision that is common ancestor
147 # revision that is common ancestor
148 _org_ref = org_ref
148 _org_ref = org_ref
149 org_ref = ('rev', getattr(c.cs_ranges[0].parents[0]
149 org_ref = ('rev', getattr(c.cs_ranges[0].parents[0]
150 if c.cs_ranges[0].parents
150 if c.cs_ranges[0].parents
151 else EmptyChangeset(), 'raw_id'))
151 else EmptyChangeset(), 'raw_id'))
152 log.debug('Changed org_ref from %s to %s' % (_org_ref, org_ref))
152 log.debug('Changed org_ref from %s to %s' % (_org_ref, org_ref))
153 other_repo = org_repo
153 org_repo = other_repo
154
154
155 diff_limit = self.cut_off_limit if not fulldiff else None
155 diff_limit = self.cut_off_limit if not fulldiff else None
156
156
157 _diff = diffs.differ(org_repo, org_ref, other_repo, other_ref)
157 _diff = diffs.differ(org_repo, org_ref, other_repo, other_ref)
158
158
159 diff_processor = diffs.DiffProcessor(_diff or '', format='gitdiff',
159 diff_processor = diffs.DiffProcessor(_diff or '', format='gitdiff',
160 diff_limit=diff_limit)
160 diff_limit=diff_limit)
161 _parsed = diff_processor.prepare()
161 _parsed = diff_processor.prepare()
162
162
163 c.limited_diff = False
163 c.limited_diff = False
164 if isinstance(_parsed, LimitedDiffContainer):
164 if isinstance(_parsed, LimitedDiffContainer):
165 c.limited_diff = True
165 c.limited_diff = True
166
166
167 c.files = []
167 c.files = []
168 c.changes = {}
168 c.changes = {}
169 c.lines_added = 0
169 c.lines_added = 0
170 c.lines_deleted = 0
170 c.lines_deleted = 0
171 for f in _parsed:
171 for f in _parsed:
172 st = f['stats']
172 st = f['stats']
173 if st[0] != 'b':
173 if st[0] != 'b':
174 c.lines_added += st[0]
174 c.lines_added += st[0]
175 c.lines_deleted += st[1]
175 c.lines_deleted += st[1]
176 fid = h.FID('', f['filename'])
176 fid = h.FID('', f['filename'])
177 c.files.append([fid, f['operation'], f['filename'], f['stats']])
177 c.files.append([fid, f['operation'], f['filename'], f['stats']])
178 diff = diff_processor.as_html(enable_comments=False, parsed_lines=[f])
178 diff = diff_processor.as_html(enable_comments=False, parsed_lines=[f])
179 c.changes[fid] = [f['operation'], f['filename'], diff]
179 c.changes[fid] = [f['operation'], f['filename'], diff]
180
180
181 return render('compare/compare_diff.html')
181 return render('compare/compare_diff.html')
@@ -1,248 +1,248 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.pull_request
3 rhodecode.model.pull_request
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 pull request model for RhodeCode
6 pull request model for RhodeCode
7
7
8 :created_on: Jun 6, 2012
8 :created_on: Jun 6, 2012
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2012-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2012-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
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
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
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
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/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import datetime
27 import datetime
28 import re
28 import re
29
29
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31
31
32 from rhodecode.model.meta import Session
32 from rhodecode.model.meta import Session
33 from rhodecode.lib import helpers as h, unionrepo
33 from rhodecode.lib import helpers as h, unionrepo
34 from rhodecode.model import BaseModel
34 from rhodecode.model import BaseModel
35 from rhodecode.model.db import PullRequest, PullRequestReviewers, Notification,\
35 from rhodecode.model.db import PullRequest, PullRequestReviewers, Notification,\
36 ChangesetStatus
36 ChangesetStatus
37 from rhodecode.model.notification import NotificationModel
37 from rhodecode.model.notification import NotificationModel
38 from rhodecode.lib.utils2 import safe_unicode
38 from rhodecode.lib.utils2 import safe_unicode
39
39
40 from rhodecode.lib.vcs.utils.hgcompat import scmutil
40 from rhodecode.lib.vcs.utils.hgcompat import scmutil
41 from rhodecode.lib.vcs.utils import safe_str
41 from rhodecode.lib.vcs.utils import safe_str
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45
45
46 class PullRequestModel(BaseModel):
46 class PullRequestModel(BaseModel):
47
47
48 cls = PullRequest
48 cls = PullRequest
49
49
50 def __get_pull_request(self, pull_request):
50 def __get_pull_request(self, pull_request):
51 return self._get_instance(PullRequest, pull_request)
51 return self._get_instance(PullRequest, pull_request)
52
52
53 def get_all(self, repo):
53 def get_all(self, repo):
54 repo = self._get_repo(repo)
54 repo = self._get_repo(repo)
55 return PullRequest.query()\
55 return PullRequest.query()\
56 .filter(PullRequest.other_repo == repo)\
56 .filter(PullRequest.other_repo == repo)\
57 .order_by(PullRequest.created_on)\
57 .order_by(PullRequest.created_on)\
58 .all()
58 .all()
59
59
60 def create(self, created_by, org_repo, org_ref, other_repo, other_ref,
60 def create(self, created_by, org_repo, org_ref, other_repo, other_ref,
61 revisions, reviewers, title, description=None):
61 revisions, reviewers, title, description=None):
62 from rhodecode.model.changeset_status import ChangesetStatusModel
62 from rhodecode.model.changeset_status import ChangesetStatusModel
63
63
64 created_by_user = self._get_user(created_by)
64 created_by_user = self._get_user(created_by)
65 org_repo = self._get_repo(org_repo)
65 org_repo = self._get_repo(org_repo)
66 other_repo = self._get_repo(other_repo)
66 other_repo = self._get_repo(other_repo)
67
67
68 new = PullRequest()
68 new = PullRequest()
69 new.org_repo = org_repo
69 new.org_repo = org_repo
70 new.org_ref = org_ref
70 new.org_ref = org_ref
71 new.other_repo = other_repo
71 new.other_repo = other_repo
72 new.other_ref = other_ref
72 new.other_ref = other_ref
73 new.revisions = revisions
73 new.revisions = revisions
74 new.title = title
74 new.title = title
75 new.description = description
75 new.description = description
76 new.author = created_by_user
76 new.author = created_by_user
77 self.sa.add(new)
77 self.sa.add(new)
78 Session().flush()
78 Session().flush()
79 #members
79 #members
80 for member in reviewers:
80 for member in reviewers:
81 _usr = self._get_user(member)
81 _usr = self._get_user(member)
82 reviewer = PullRequestReviewers(_usr, new)
82 reviewer = PullRequestReviewers(_usr, new)
83 self.sa.add(reviewer)
83 self.sa.add(reviewer)
84
84
85 #reset state to under-review
85 #reset state to under-review
86 ChangesetStatusModel().set_status(
86 ChangesetStatusModel().set_status(
87 repo=org_repo,
87 repo=org_repo,
88 status=ChangesetStatus.STATUS_UNDER_REVIEW,
88 status=ChangesetStatus.STATUS_UNDER_REVIEW,
89 user=created_by_user,
89 user=created_by_user,
90 pull_request=new
90 pull_request=new
91 )
91 )
92
92
93 #notification to reviewers
93 #notification to reviewers
94 notif = NotificationModel()
94 notif = NotificationModel()
95
95
96 pr_url = h.url('pullrequest_show', repo_name=other_repo.repo_name,
96 pr_url = h.url('pullrequest_show', repo_name=other_repo.repo_name,
97 pull_request_id=new.pull_request_id,
97 pull_request_id=new.pull_request_id,
98 qualified=True,
98 qualified=True,
99 )
99 )
100 subject = safe_unicode(
100 subject = safe_unicode(
101 h.link_to(
101 h.link_to(
102 _('%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s') % \
102 _('%(user)s wants you to review pull request #%(pr_id)s: %(pr_title)s') % \
103 {'user': created_by_user.username,
103 {'user': created_by_user.username,
104 'pr_title': new.title,
104 'pr_title': new.title,
105 'pr_id': new.pull_request_id},
105 'pr_id': new.pull_request_id},
106 pr_url
106 pr_url
107 )
107 )
108 )
108 )
109 body = description
109 body = description
110 kwargs = {
110 kwargs = {
111 'pr_title': title,
111 'pr_title': title,
112 'pr_user_created': h.person(created_by_user.email),
112 'pr_user_created': h.person(created_by_user.email),
113 'pr_repo_url': h.url('summary_home', repo_name=other_repo.repo_name,
113 'pr_repo_url': h.url('summary_home', repo_name=other_repo.repo_name,
114 qualified=True,),
114 qualified=True,),
115 'pr_url': pr_url,
115 'pr_url': pr_url,
116 'pr_revisions': revisions
116 'pr_revisions': revisions
117 }
117 }
118 notif.create(created_by=created_by_user, subject=subject, body=body,
118 notif.create(created_by=created_by_user, subject=subject, body=body,
119 recipients=reviewers,
119 recipients=reviewers,
120 type_=Notification.TYPE_PULL_REQUEST, email_kwargs=kwargs)
120 type_=Notification.TYPE_PULL_REQUEST, email_kwargs=kwargs)
121 return new
121 return new
122
122
123 def update_reviewers(self, pull_request, reviewers_ids):
123 def update_reviewers(self, pull_request, reviewers_ids):
124 reviewers_ids = set(reviewers_ids)
124 reviewers_ids = set(reviewers_ids)
125 pull_request = self.__get_pull_request(pull_request)
125 pull_request = self.__get_pull_request(pull_request)
126 current_reviewers = PullRequestReviewers.query()\
126 current_reviewers = PullRequestReviewers.query()\
127 .filter(PullRequestReviewers.pull_request==
127 .filter(PullRequestReviewers.pull_request==
128 pull_request)\
128 pull_request)\
129 .all()
129 .all()
130 current_reviewers_ids = set([x.user.user_id for x in current_reviewers])
130 current_reviewers_ids = set([x.user.user_id for x in current_reviewers])
131
131
132 to_add = reviewers_ids.difference(current_reviewers_ids)
132 to_add = reviewers_ids.difference(current_reviewers_ids)
133 to_remove = current_reviewers_ids.difference(reviewers_ids)
133 to_remove = current_reviewers_ids.difference(reviewers_ids)
134
134
135 log.debug("Adding %s reviewers" % to_add)
135 log.debug("Adding %s reviewers" % to_add)
136 log.debug("Removing %s reviewers" % to_remove)
136 log.debug("Removing %s reviewers" % to_remove)
137
137
138 for uid in to_add:
138 for uid in to_add:
139 _usr = self._get_user(uid)
139 _usr = self._get_user(uid)
140 reviewer = PullRequestReviewers(_usr, pull_request)
140 reviewer = PullRequestReviewers(_usr, pull_request)
141 self.sa.add(reviewer)
141 self.sa.add(reviewer)
142
142
143 for uid in to_remove:
143 for uid in to_remove:
144 reviewer = PullRequestReviewers.query()\
144 reviewer = PullRequestReviewers.query()\
145 .filter(PullRequestReviewers.user_id==uid,
145 .filter(PullRequestReviewers.user_id==uid,
146 PullRequestReviewers.pull_request==pull_request)\
146 PullRequestReviewers.pull_request==pull_request)\
147 .scalar()
147 .scalar()
148 if reviewer:
148 if reviewer:
149 self.sa.delete(reviewer)
149 self.sa.delete(reviewer)
150
150
151 def delete(self, pull_request):
151 def delete(self, pull_request):
152 pull_request = self.__get_pull_request(pull_request)
152 pull_request = self.__get_pull_request(pull_request)
153 Session().delete(pull_request)
153 Session().delete(pull_request)
154
154
155 def close_pull_request(self, pull_request):
155 def close_pull_request(self, pull_request):
156 pull_request = self.__get_pull_request(pull_request)
156 pull_request = self.__get_pull_request(pull_request)
157 pull_request.status = PullRequest.STATUS_CLOSED
157 pull_request.status = PullRequest.STATUS_CLOSED
158 pull_request.updated_on = datetime.datetime.now()
158 pull_request.updated_on = datetime.datetime.now()
159 self.sa.add(pull_request)
159 self.sa.add(pull_request)
160
160
161 def _get_changesets(self, alias, org_repo, org_ref, other_repo, other_ref):
161 def _get_changesets(self, alias, org_repo, org_ref, other_repo, other_ref):
162 """
162 """
163 Returns a list of changesets that are incoming from org_repo@org_ref
163 Returns a list of changesets that are incoming from org_repo@org_ref
164 to other_repo@other_ref
164 to other_repo@other_ref
165
165
166 :param org_repo:
166 :param org_repo:
167 :param org_ref:
167 :param org_ref:
168 :param other_repo:
168 :param other_repo:
169 :param other_ref:
169 :param other_ref:
170 :param tmp:
170 :param tmp:
171 """
171 """
172
172
173 changesets = []
173 changesets = []
174
174
175 if alias == 'hg':
175 if alias == 'hg':
176 # lookup up the exact node id
176 # lookup up the exact node id
177 _revset_predicates = {
177 _revset_predicates = {
178 'branch': 'branch',
178 'branch': 'branch',
179 'book': 'bookmark',
179 'book': 'bookmark',
180 'tag': 'tag',
180 'tag': 'tag',
181 'rev': 'id',
181 'rev': 'id',
182 }
182 }
183 org_rev_spec = "%s('%s')" % (_revset_predicates[org_ref[0]],
183 org_rev_spec = "%s('%s')" % (_revset_predicates[org_ref[0]],
184 safe_str(org_ref[1]))
184 safe_str(org_ref[1]))
185 org_rev = scmutil.revsingle(org_repo._repo,
185 org_rev = scmutil.revsingle(org_repo._repo,
186 org_rev_spec)
186 org_rev_spec)
187 other_rev_spec = "%s('%s')" % (_revset_predicates[other_ref[0]],
187 other_rev_spec = "%s('%s')" % (_revset_predicates[other_ref[0]],
188 safe_str(other_ref[1]))
188 safe_str(other_ref[1]))
189 other_rev = scmutil.revsingle(other_repo._repo, other_rev_spec)
189 other_rev = scmutil.revsingle(other_repo._repo, other_rev_spec)
190
190
191 #case two independent repos
191 #case two independent repos
192 if org_repo != other_repo:
192 if org_repo != other_repo:
193 hgrepo = unionrepo.unionrepository(org_repo.baseui,
193 hgrepo = unionrepo.unionrepository(other_repo.baseui,
194 org_repo.path,
194 other_repo.path,
195 other_repo.path)
195 org_repo.path)
196 revs = ["ancestors(id('%s')) and not ancestors(id('%s'))" %
196 # all the changesets we are looking for will be in other_repo,
197 (org_rev, other_rev)]
197 # so rev numbers from hgrepo can be used in other_repo
198
198
199 #no remote compare do it on the same repository
199 #no remote compare do it on the same repository
200 else:
200 else:
201 hgrepo = org_repo._repo
201 hgrepo = other_repo._repo
202 revs = ["ancestors(id('%s')) and not ancestors(id('%s'))" %
203 (other_rev, org_rev)]
204
202
203 revs = ["ancestors(id('%s')) and not ancestors(id('%s'))" %
204 (other_rev, org_rev)]
205 out = scmutil.revrange(hgrepo, revs)
205 out = scmutil.revrange(hgrepo, revs)
206 for cs in (out):
206 for cs in (out):
207 changesets.append(org_repo.get_changeset(cs))
207 changesets.append(other_repo.get_changeset(cs))
208
208
209 elif alias == 'git':
209 elif alias == 'git':
210 assert org_repo == other_repo, (org_repo, other_repo) # no git support for different repos
210 assert org_repo == other_repo, (org_repo, other_repo) # no git support for different repos
211 so, se = org_repo.run_git_command(
211 so, se = org_repo.run_git_command(
212 'log --reverse --pretty="format: %%H" -s -p %s..%s' % (org_ref[1],
212 'log --reverse --pretty="format: %%H" -s -p %s..%s' % (org_ref[1],
213 other_ref[1])
213 other_ref[1])
214 )
214 )
215 ids = re.findall(r'[0-9a-fA-F]{40}', so)
215 ids = re.findall(r'[0-9a-fA-F]{40}', so)
216 for cs in (ids):
216 for cs in (ids):
217 changesets.append(org_repo.get_changeset(cs))
217 changesets.append(org_repo.get_changeset(cs))
218
218
219 return changesets
219 return changesets
220
220
221 def get_compare_data(self, org_repo, org_ref, other_repo, other_ref):
221 def get_compare_data(self, org_repo, org_ref, other_repo, other_ref):
222 """
222 """
223 Returns incoming changesets for mercurial repositories
223 Returns incoming changesets for mercurial repositories
224
224
225 :param org_repo:
225 :param org_repo:
226 :type org_repo:
226 :type org_repo:
227 :param org_ref:
227 :param org_ref:
228 :type org_ref:
228 :type org_ref:
229 :param other_repo:
229 :param other_repo:
230 :type other_repo:
230 :type other_repo:
231 :param other_ref:
231 :param other_ref:
232 :type other_ref:
232 :type other_ref:
233 """
233 """
234
234
235 if len(org_ref) != 2 or not isinstance(org_ref, (list, tuple)):
235 if len(org_ref) != 2 or not isinstance(org_ref, (list, tuple)):
236 raise Exception('org_ref must be a two element list/tuple')
236 raise Exception('org_ref must be a two element list/tuple')
237
237
238 if len(other_ref) != 2 or not isinstance(org_ref, (list, tuple)):
238 if len(other_ref) != 2 or not isinstance(org_ref, (list, tuple)):
239 raise Exception('other_ref must be a two element list/tuple')
239 raise Exception('other_ref must be a two element list/tuple')
240
240
241 org_repo_scm = org_repo.scm_instance
241 org_repo_scm = org_repo.scm_instance
242 other_repo_scm = other_repo.scm_instance
242 other_repo_scm = other_repo.scm_instance
243
243
244 alias = org_repo.scm_instance.alias
244 alias = org_repo.scm_instance.alias
245 cs_ranges = self._get_changesets(alias,
245 cs_ranges = self._get_changesets(alias,
246 org_repo_scm, org_ref,
246 org_repo_scm, org_ref,
247 other_repo_scm, other_ref)
247 other_repo_scm, other_ref)
248 return cs_ranges
248 return cs_ranges
@@ -1,367 +1,367 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="root.html"/>
2 <%inherit file="root.html"/>
3
3
4 <!-- HEADER -->
4 <!-- HEADER -->
5 <div id="header-dd"></div>
5 <div id="header-dd"></div>
6 <div id="header">
6 <div id="header">
7 <div id="header-inner" class="title">
7 <div id="header-inner" class="title">
8 <div id="logo">
8 <div id="logo">
9 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
9 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
10 </div>
10 </div>
11 <!-- MENU -->
11 <!-- MENU -->
12 ${self.page_nav()}
12 ${self.page_nav()}
13 <!-- END MENU -->
13 <!-- END MENU -->
14 ${self.body()}
14 ${self.body()}
15 </div>
15 </div>
16 </div>
16 </div>
17 <!-- END HEADER -->
17 <!-- END HEADER -->
18
18
19 <!-- CONTENT -->
19 <!-- CONTENT -->
20 <div id="content">
20 <div id="content">
21 <div class="flash_msg">
21 <div class="flash_msg">
22 <% messages = h.flash.pop_messages() %>
22 <% messages = h.flash.pop_messages() %>
23 % if messages:
23 % if messages:
24 <ul id="flash-messages">
24 <ul id="flash-messages">
25 % for message in messages:
25 % for message in messages:
26 <li class="${message.category}_msg">${message}</li>
26 <li class="${message.category}_msg">${message}</li>
27 % endfor
27 % endfor
28 </ul>
28 </ul>
29 % endif
29 % endif
30 </div>
30 </div>
31 <div id="main">
31 <div id="main">
32 ${next.main()}
32 ${next.main()}
33 </div>
33 </div>
34 </div>
34 </div>
35 <!-- END CONTENT -->
35 <!-- END CONTENT -->
36
36
37 <!-- FOOTER -->
37 <!-- FOOTER -->
38 <div id="footer">
38 <div id="footer">
39 <div id="footer-inner" class="title">
39 <div id="footer-inner" class="title">
40 <div>
40 <div>
41 <p class="footer-link">
41 <p class="footer-link">
42 <a href="${h.url('bugtracker')}">${_('Submit a bug')}</a>
42 <a href="${h.url('bugtracker')}">${_('Submit a bug')}</a>
43 </p>
43 </p>
44 <p class="footer-link-right">
44 <p class="footer-link-right">
45 <a href="${h.url('rhodecode_official')}">RhodeCode${'-%s' % c.rhodecode_instanceid if c.rhodecode_instanceid else ''}</a>
45 <a href="${h.url('rhodecode_official')}">RhodeCode${'-%s' % c.rhodecode_instanceid if c.rhodecode_instanceid else ''}</a>
46 ${c.rhodecode_version} &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski
46 ${c.rhodecode_version} &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski
47 </p>
47 </p>
48 </div>
48 </div>
49 </div>
49 </div>
50 </div>
50 </div>
51 <!-- END FOOTER -->
51 <!-- END FOOTER -->
52
52
53 ### MAKO DEFS ###
53 ### MAKO DEFS ###
54 <%def name="page_nav()">
54 <%def name="page_nav()">
55 ${self.menu()}
55 ${self.menu()}
56 </%def>
56 </%def>
57
57
58 <%def name="breadcrumbs()">
58 <%def name="breadcrumbs()">
59 <div class="breadcrumbs">
59 <div class="breadcrumbs">
60 ${self.breadcrumbs_links()}
60 ${self.breadcrumbs_links()}
61 </div>
61 </div>
62 </%def>
62 </%def>
63
63
64 <%def name="usermenu()">
64 <%def name="usermenu()">
65 ## USER MENU
65 ## USER MENU
66 <li>
66 <li>
67 <a class="menu_link" id="quick_login_link">
67 <a class="menu_link" id="quick_login_link">
68 <span class="icon" style="padding:5px 5px 0px 5px">
68 <span class="icon" style="padding:5px 5px 0px 5px">
69 <img src="${h.gravatar_url(c.rhodecode_user.email,20)}" alt="avatar">
69 <img src="${h.gravatar_url(c.rhodecode_user.email,20)}" alt="avatar">
70 </span>
70 </span>
71 %if c.rhodecode_user.username != 'default':
71 %if c.rhodecode_user.username != 'default':
72 <span class="menu_link_user">${c.rhodecode_user.username}</span>
72 <span class="menu_link_user">${c.rhodecode_user.username}</span>
73 %if c.unread_notifications != 0:
73 %if c.unread_notifications != 0:
74 <span class="menu_link_notifications">${c.unread_notifications}</span>
74 <span class="menu_link_notifications">${c.unread_notifications}</span>
75 %endif
75 %endif
76 %else:
76 %else:
77 <span>${_('Not logged in')}</span>
77 <span>${_('Not logged in')}</span>
78 %endif
78 %endif
79 </a>
79 </a>
80
80
81 <div class="user-menu">
81 <div class="user-menu">
82 <div id="quick_login">
82 <div id="quick_login">
83 %if c.rhodecode_user.username == 'default':
83 %if c.rhodecode_user.username == 'default':
84 <h4>${_('Login to your account')}</h4>
84 <h4>${_('Login to your account')}</h4>
85 ${h.form(h.url('login_home',came_from=h.url.current()))}
85 ${h.form(h.url('login_home',came_from=h.url.current()))}
86 <div class="form">
86 <div class="form">
87 <div class="fields">
87 <div class="fields">
88 <div class="field">
88 <div class="field">
89 <div class="label">
89 <div class="label">
90 <label for="username">${_('Username')}:</label>
90 <label for="username">${_('Username')}:</label>
91 </div>
91 </div>
92 <div class="input">
92 <div class="input">
93 ${h.text('username',class_='focus',size=40)}
93 ${h.text('username',class_='focus',size=40)}
94 </div>
94 </div>
95
95
96 </div>
96 </div>
97 <div class="field">
97 <div class="field">
98 <div class="label">
98 <div class="label">
99 <label for="password">${_('Password')}:</label>
99 <label for="password">${_('Password')}:</label>
100 </div>
100 </div>
101 <div class="input">
101 <div class="input">
102 ${h.password('password',class_='focus',size=40)}
102 ${h.password('password',class_='focus',size=40)}
103 </div>
103 </div>
104
104
105 </div>
105 </div>
106 <div class="buttons">
106 <div class="buttons">
107 <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
107 <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
108 <div class="register">
108 <div class="register">
109 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
109 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
110 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
110 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
111 %endif
111 %endif
112 </div>
112 </div>
113 <div class="submit">
113 <div class="submit">
114 ${h.submit('sign_in',_('Log In'),class_="ui-btn xsmall")}
114 ${h.submit('sign_in',_('Log In'),class_="ui-btn xsmall")}
115 </div>
115 </div>
116 </div>
116 </div>
117 </div>
117 </div>
118 </div>
118 </div>
119 ${h.end_form()}
119 ${h.end_form()}
120 %else:
120 %else:
121 <div class="links_left">
121 <div class="links_left">
122 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
122 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
123 <div class="email">${c.rhodecode_user.email}</div>
123 <div class="email">${c.rhodecode_user.email}</div>
124 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
124 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
125 <div class="notifications"><a href="${h.url('notifications')}">${_('Notifications')}</a></div>
125 <div class="notifications"><a href="${h.url('notifications')}">${_('Notifications')}</a></div>
126 <div class="unread"><a href="${h.url('notifications')}">${_('Unread')}: ${c.unread_notifications}</a></div>
126 <div class="unread"><a href="${h.url('notifications')}">${_('Unread')}: ${c.unread_notifications}</a></div>
127 </div>
127 </div>
128 <div class="links_right">
128 <div class="links_right">
129 <ol class="links">
129 <ol class="links">
130 <li>${h.link_to(_(u'Home'),h.url('home'))}</li>
130 <li>${h.link_to(_(u'Home'),h.url('home'))}</li>
131 <li>${h.link_to(_(u'Journal'),h.url('journal'))}</li>
131 <li>${h.link_to(_(u'Journal'),h.url('journal'))}</li>
132 <li>${h.link_to(_(u'My account'),h.url('admin_settings_my_account'))}</li>
132 <li>${h.link_to(_(u'My account'),h.url('admin_settings_my_account'))}</li>
133 <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
133 <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
134 </ol>
134 </ol>
135 </div>
135 </div>
136 %endif
136 %endif
137 </div>
137 </div>
138 </div>
138 </div>
139
139
140 </li>
140 </li>
141 </%def>
141 </%def>
142
142
143 <%def name="menu(current=None)">
143 <%def name="menu(current=None)">
144 <%
144 <%
145 def is_current(selected):
145 def is_current(selected):
146 if selected == current:
146 if selected == current:
147 return h.literal('class="current"')
147 return h.literal('class="current"')
148 %>
148 %>
149 <ul id="quick">
149 <ul id="quick">
150 <!-- repo switcher -->
150 <!-- repo switcher -->
151 <li ${is_current('home')}>
151 <li ${is_current('home')}>
152 <a class="menu_link" id="repo_switcher" title="${_('Switch repository')}" href="${h.url('home')}">
152 <a class="menu_link" id="repo_switcher" title="${_('Switch repository')}" href="${h.url('home')}">
153 <span class="icon">
153 <span class="icon">
154 <img src="${h.url('/images/icons/database.png')}" alt="${_('Products')}" />
154 <img src="${h.url('/images/icons/database.png')}" alt="${_('Products')}" />
155 </span>
155 </span>
156 <span>${_('Repositories')}</span>
156 <span>${_('Repositories')}</span>
157 </a>
157 </a>
158 <ul id="repo_switcher_list" class="repo_switcher">
158 <ul id="repo_switcher_list" class="repo_switcher">
159 <li>
159 <li>
160 <a href="#">${_('loading...')}</a>
160 <a href="#">${_('loading...')}</a>
161 </li>
161 </li>
162 </ul>
162 </ul>
163 </li>
163 </li>
164 ## we render this menu only not for those pages
164 ## we render this menu only not for those pages
165 %if current not in ['home','admin', 'search', 'journal']:
165 %if current not in ['home','admin', 'search', 'journal']:
166 ##REGULAR MENU
166 ##REGULAR MENU
167 <li ${is_current('summary')}>
167 <li ${is_current('summary')}>
168 <a class="menu_link" title="${_('Summary page')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
168 <a class="menu_link" title="${_('Summary page')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
169 <span class="icon">
169 <span class="icon">
170 <img src="${h.url('/images/icons/clipboard_16.png')}" alt="${_('Summary')}" />
170 <img src="${h.url('/images/icons/clipboard_16.png')}" alt="${_('Summary')}" />
171 </span>
171 </span>
172 <span>${_('Summary')}</span>
172 <span>${_('Summary')}</span>
173 </a>
173 </a>
174 </li>
174 </li>
175 <li ${is_current('changelog')}>
175 <li ${is_current('changelog')}>
176 <a class="menu_link" title="${_('Changeset list')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
176 <a class="menu_link" title="${_('Changeset list')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
177 <span class="icon">
177 <span class="icon">
178 <img src="${h.url('/images/icons/time.png')}" alt="${_('Changelog')}" />
178 <img src="${h.url('/images/icons/time.png')}" alt="${_('Changelog')}" />
179 </span>
179 </span>
180 <span>${_('Changelog')}</span>
180 <span>${_('Changelog')}</span>
181 </a>
181 </a>
182 </li>
182 </li>
183 <li ${is_current('switch_to')}>
183 <li ${is_current('switch_to')}>
184 <a class="menu_link" id="branch_tag_switcher" title="${_('Switch to')}" href="#">
184 <a class="menu_link" id="branch_tag_switcher" title="${_('Switch to')}" href="#">
185 <span class="icon">
185 <span class="icon">
186 <img src="${h.url('/images/icons/arrow_switch.png')}" alt="${_('Switch to')}" />
186 <img src="${h.url('/images/icons/arrow_switch.png')}" alt="${_('Switch to')}" />
187 </span>
187 </span>
188 <span>${_('Switch to')}</span>
188 <span>${_('Switch to')}</span>
189 </a>
189 </a>
190 <ul id="switch_to_list" class="switch_to">
190 <ul id="switch_to_list" class="switch_to">
191 <li><a href="#">${_('loading...')}</a></li>
191 <li><a href="#">${_('loading...')}</a></li>
192 </ul>
192 </ul>
193 </li>
193 </li>
194 <li ${is_current('files')}>
194 <li ${is_current('files')}>
195 <a class="menu_link" title="${_('Show repository content')}" href="${h.url('files_home',repo_name=c.repo_name)}">
195 <a class="menu_link" title="${_('Show repository content')}" href="${h.url('files_home',repo_name=c.repo_name)}">
196 <span class="icon">
196 <span class="icon">
197 <img src="${h.url('/images/icons/file.png')}" alt="${_('Files')}" />
197 <img src="${h.url('/images/icons/file.png')}" alt="${_('Files')}" />
198 </span>
198 </span>
199 <span>${_('Files')}</span>
199 <span>${_('Files')}</span>
200 </a>
200 </a>
201 </li>
201 </li>
202 <li ${is_current('options')}>
202 <li ${is_current('options')}>
203 <a class="menu_link" title="${_('Options')}" href="#">
203 <a class="menu_link" title="${_('Options')}" href="#">
204 <span class="icon">
204 <span class="icon">
205 <img src="${h.url('/images/icons/table_gear.png')}" alt="${_('Admin')}" />
205 <img src="${h.url('/images/icons/table_gear.png')}" alt="${_('Admin')}" />
206 </span>
206 </span>
207 <span>${_('Options')}</span>
207 <span>${_('Options')}</span>
208 </a>
208 </a>
209 <ul>
209 <ul>
210 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
210 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
211 %if h.HasPermissionAll('hg.admin')('access settings on repository'):
211 %if h.HasPermissionAll('hg.admin')('access settings on repository'):
212 <li>${h.link_to(_('repository settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
212 <li>${h.link_to(_('repository settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
213 %else:
213 %else:
214 <li>${h.link_to(_('repository settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
214 <li>${h.link_to(_('repository settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
215 %endif
215 %endif
216 %endif
216 %endif
217
217
218 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
218 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
219 %if h.is_hg(c.rhodecode_repo):
219 %if h.is_hg(c.rhodecode_repo):
220 <li>${h.link_to(_('open new pull request'),h.url('pullrequest_home',repo_name=c.repo_name),class_='pull_request')}</li>
220 <li>${h.link_to(_('open new pull request'),h.url('pullrequest_home',repo_name=c.repo_name),class_='pull_request')}</li>
221 %endif
221 %endif
222 %if c.rhodecode_db_repo.fork:
222 %if c.rhodecode_db_repo.fork:
223 <li>${h.link_to(_('compare fork'),h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref=request.GET.get('branch') or 'default',other_repo=c.rhodecode_db_repo.fork.repo_name,other_ref_type='branch',other_ref='default'),class_='compare_request')}</li>
223 <li>${h.link_to(_('compare fork'),h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,org_ref_type='branch',org_ref='default',other_repo=c.repo_name,other_ref_type='branch',other_ref=request.GET.get('branch') or 'default'),class_='compare_request')}</li>
224 %endif
224 %endif
225 <li>${h.link_to(_('lightweight changelog'),h.url('shortlog_home',repo_name=c.repo_name),class_='shortlog')}</li>
225 <li>${h.link_to(_('lightweight changelog'),h.url('shortlog_home',repo_name=c.repo_name),class_='shortlog')}</li>
226 <li>${h.link_to(_('search'),h.url('search_repo',repo_name=c.repo_name),class_='search')}</li>
226 <li>${h.link_to(_('search'),h.url('search_repo',repo_name=c.repo_name),class_='search')}</li>
227
227
228 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
228 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
229 %if c.rhodecode_db_repo.locked[0]:
229 %if c.rhodecode_db_repo.locked[0]:
230 <li>${h.link_to(_('unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
230 <li>${h.link_to(_('unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
231 %else:
231 %else:
232 <li>${h.link_to(_('lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
232 <li>${h.link_to(_('lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
233 %endif
233 %endif
234 %endif
234 %endif
235
235
236 % if h.HasPermissionAll('hg.admin')('access admin main page'):
236 % if h.HasPermissionAll('hg.admin')('access admin main page'):
237 <li>
237 <li>
238 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
238 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
239 <%def name="admin_menu()">
239 <%def name="admin_menu()">
240 <ul>
240 <ul>
241 <li>${h.link_to(_('admin journal'),h.url('admin_home'),class_='journal')}</li>
241 <li>${h.link_to(_('admin journal'),h.url('admin_home'),class_='journal')}</li>
242 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
242 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
243 <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li>
243 <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li>
244 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
244 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
245 <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
245 <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
246 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
246 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
247 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
247 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
248 <li>${h.link_to(_('defaults'),h.url('defaults'),class_='defaults')}</li>
248 <li>${h.link_to(_('defaults'),h.url('defaults'),class_='defaults')}</li>
249 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
249 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
250 </ul>
250 </ul>
251 </%def>
251 </%def>
252 ## ADMIN MENU
252 ## ADMIN MENU
253 ${admin_menu()}
253 ${admin_menu()}
254 </li>
254 </li>
255 % endif
255 % endif
256 </ul>
256 </ul>
257 </li>
257 </li>
258 <li>
258 <li>
259 <a class="menu_link" title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
259 <a class="menu_link" title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
260 <span class="icon_short">
260 <span class="icon_short">
261 <img src="${h.url('/images/icons/heart.png')}" alt="${_('Followers')}" />
261 <img src="${h.url('/images/icons/heart.png')}" alt="${_('Followers')}" />
262 </span>
262 </span>
263 <span id="current_followers_count" class="short">${c.repository_followers}</span>
263 <span id="current_followers_count" class="short">${c.repository_followers}</span>
264 </a>
264 </a>
265 </li>
265 </li>
266 <li>
266 <li>
267 <a class="menu_link" title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
267 <a class="menu_link" title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
268 <span class="icon_short">
268 <span class="icon_short">
269 <img src="${h.url('/images/icons/arrow_divide.png')}" alt="${_('Forks')}" />
269 <img src="${h.url('/images/icons/arrow_divide.png')}" alt="${_('Forks')}" />
270 </span>
270 </span>
271 <span class="short">${c.repository_forks}</span>
271 <span class="short">${c.repository_forks}</span>
272 </a>
272 </a>
273 </li>
273 </li>
274 <li>
274 <li>
275 <a class="menu_link" title="${_('Pull requests')}" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}">
275 <a class="menu_link" title="${_('Pull requests')}" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}">
276 <span class="icon_short">
276 <span class="icon_short">
277 <img src="${h.url('/images/icons/arrow_join.png')}" alt="${_('Pull requests')}" />
277 <img src="${h.url('/images/icons/arrow_join.png')}" alt="${_('Pull requests')}" />
278 </span>
278 </span>
279 <span class="short">${c.repository_pull_requests}</span>
279 <span class="short">${c.repository_pull_requests}</span>
280 </a>
280 </a>
281 </li>
281 </li>
282 ${usermenu()}
282 ${usermenu()}
283 <script type="text/javascript">
283 <script type="text/javascript">
284 YUE.on('branch_tag_switcher','mouseover',function(){
284 YUE.on('branch_tag_switcher','mouseover',function(){
285 var loaded = YUD.hasClass('branch_tag_switcher','loaded');
285 var loaded = YUD.hasClass('branch_tag_switcher','loaded');
286 if(!loaded){
286 if(!loaded){
287 YUD.addClass('branch_tag_switcher','loaded');
287 YUD.addClass('branch_tag_switcher','loaded');
288 ypjax("${h.url('branch_tag_switcher',repo_name=c.repo_name)}",'switch_to_list',
288 ypjax("${h.url('branch_tag_switcher',repo_name=c.repo_name)}",'switch_to_list',
289 function(o){},
289 function(o){},
290 function(o){YUD.removeClass('branch_tag_switcher','loaded');}
290 function(o){YUD.removeClass('branch_tag_switcher','loaded');}
291 ,null);
291 ,null);
292 }
292 }
293 return false;
293 return false;
294 });
294 });
295 </script>
295 </script>
296 %else:
296 %else:
297 ##ROOT MENU
297 ##ROOT MENU
298 %if c.rhodecode_user.username != 'default':
298 %if c.rhodecode_user.username != 'default':
299 <li ${is_current('journal')}>
299 <li ${is_current('journal')}>
300 <a class="menu_link" title="${_('Show recent activity')}" href="${h.url('journal')}">
300 <a class="menu_link" title="${_('Show recent activity')}" href="${h.url('journal')}">
301 <span class="icon">
301 <span class="icon">
302 <img src="${h.url('/images/icons/book.png')}" alt="${_('Journal')}" />
302 <img src="${h.url('/images/icons/book.png')}" alt="${_('Journal')}" />
303 </span>
303 </span>
304 <span>${_('Journal')}</span>
304 <span>${_('Journal')}</span>
305 </a>
305 </a>
306 </li>
306 </li>
307 %else:
307 %else:
308 <li ${is_current('journal')}>
308 <li ${is_current('journal')}>
309 <a class="menu_link" title="${_('Public journal')}" href="${h.url('public_journal')}">
309 <a class="menu_link" title="${_('Public journal')}" href="${h.url('public_journal')}">
310 <span class="icon">
310 <span class="icon">
311 <img src="${h.url('/images/icons/book.png')}" alt="${_('Public journal')}" />
311 <img src="${h.url('/images/icons/book.png')}" alt="${_('Public journal')}" />
312 </span>
312 </span>
313 <span>${_('Public journal')}</span>
313 <span>${_('Public journal')}</span>
314 </a>
314 </a>
315 </li>
315 </li>
316 %endif
316 %endif
317 <li ${is_current('search')}>
317 <li ${is_current('search')}>
318 <a class="menu_link" title="${_('Search in repositories')}" href="${h.url('search')}">
318 <a class="menu_link" title="${_('Search in repositories')}" href="${h.url('search')}">
319 <span class="icon">
319 <span class="icon">
320 <img src="${h.url('/images/icons/search_16.png')}" alt="${_('Search')}" />
320 <img src="${h.url('/images/icons/search_16.png')}" alt="${_('Search')}" />
321 </span>
321 </span>
322 <span>${_('Search')}</span>
322 <span>${_('Search')}</span>
323 </a>
323 </a>
324 </li>
324 </li>
325 %if h.HasPermissionAll('hg.admin')('access admin main page'):
325 %if h.HasPermissionAll('hg.admin')('access admin main page'):
326 <li ${is_current('admin')}>
326 <li ${is_current('admin')}>
327 <a class="menu_link" title="${_('Admin')}" href="${h.url('admin_home')}">
327 <a class="menu_link" title="${_('Admin')}" href="${h.url('admin_home')}">
328 <span class="icon">
328 <span class="icon">
329 <img src="${h.url('/images/icons/cog_edit.png')}" alt="${_('Admin')}" />
329 <img src="${h.url('/images/icons/cog_edit.png')}" alt="${_('Admin')}" />
330 </span>
330 </span>
331 <span>${_('Admin')}</span>
331 <span>${_('Admin')}</span>
332 </a>
332 </a>
333 ${admin_menu()}
333 ${admin_menu()}
334 </li>
334 </li>
335 %endif
335 %endif
336 ${usermenu()}
336 ${usermenu()}
337 %endif
337 %endif
338 <script type="text/javascript">
338 <script type="text/javascript">
339 YUE.on('repo_switcher','mouseover',function(){
339 YUE.on('repo_switcher','mouseover',function(){
340 var target = 'q_filter_rs';
340 var target = 'q_filter_rs';
341 var qfilter_activate = function(){
341 var qfilter_activate = function(){
342 var nodes = YUQ('ul#repo_switcher_list li a.repo_name');
342 var nodes = YUQ('ul#repo_switcher_list li a.repo_name');
343 var func = function(node){
343 var func = function(node){
344 return node.parentNode;
344 return node.parentNode;
345 }
345 }
346 q_filter(target,nodes,func);
346 q_filter(target,nodes,func);
347 }
347 }
348
348
349 var loaded = YUD.hasClass('repo_switcher','loaded');
349 var loaded = YUD.hasClass('repo_switcher','loaded');
350 if(!loaded){
350 if(!loaded){
351 YUD.addClass('repo_switcher','loaded');
351 YUD.addClass('repo_switcher','loaded');
352 ypjax("${h.url('repo_switcher')}",'repo_switcher_list',
352 ypjax("${h.url('repo_switcher')}",'repo_switcher_list',
353 function(o){qfilter_activate();YUD.get(target).focus()},
353 function(o){qfilter_activate();YUD.get(target).focus()},
354 function(o){YUD.removeClass('repo_switcher','loaded');}
354 function(o){YUD.removeClass('repo_switcher','loaded');}
355 ,null);
355 ,null);
356 }else{
356 }else{
357 YUD.get(target).focus();
357 YUD.get(target).focus();
358 }
358 }
359 return false;
359 return false;
360 });
360 });
361
361
362 YUE.on('header-dd', 'click',function(e){
362 YUE.on('header-dd', 'click',function(e){
363 YUD.addClass('header-inner', 'hover');
363 YUD.addClass('header-inner', 'hover');
364 });
364 });
365
365
366 </script>
366 </script>
367 </%def>
367 </%def>
@@ -1,306 +1,306 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 <%inherit file="/base/base.html"/>
3 <%inherit file="/base/base.html"/>
4
4
5 <%def name="title()">
5 <%def name="title()">
6 ${_('%s Changelog') % c.repo_name} - ${c.rhodecode_name}
6 ${_('%s Changelog') % c.repo_name} - ${c.rhodecode_name}
7 </%def>
7 </%def>
8
8
9 <%def name="breadcrumbs_links()">
9 <%def name="breadcrumbs_links()">
10 ${h.link_to(_(u'Home'),h.url('/'))}
10 ${h.link_to(_(u'Home'),h.url('/'))}
11 &raquo;
11 &raquo;
12 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
12 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
13 &raquo;
13 &raquo;
14 <% size = c.size if c.size <= c.total_cs else c.total_cs %>
14 <% size = c.size if c.size <= c.total_cs else c.total_cs %>
15 ${_('Changelog')} - ${ungettext('showing %d out of %d revision', 'showing %d out of %d revisions', size) % (size, c.total_cs)}
15 ${_('Changelog')} - ${ungettext('showing %d out of %d revision', 'showing %d out of %d revisions', size) % (size, c.total_cs)}
16 </%def>
16 </%def>
17
17
18 <%def name="page_nav()">
18 <%def name="page_nav()">
19 ${self.menu('changelog')}
19 ${self.menu('changelog')}
20 </%def>
20 </%def>
21
21
22 <%def name="main()">
22 <%def name="main()">
23 <div class="box">
23 <div class="box">
24 <!-- box / title -->
24 <!-- box / title -->
25 <div class="title">
25 <div class="title">
26 ${self.breadcrumbs()}
26 ${self.breadcrumbs()}
27 </div>
27 </div>
28 <div class="table">
28 <div class="table">
29 % if c.pagination:
29 % if c.pagination:
30 <div id="graph">
30 <div id="graph">
31 <div id="graph_nodes">
31 <div id="graph_nodes">
32 <canvas id="graph_canvas"></canvas>
32 <canvas id="graph_canvas"></canvas>
33 </div>
33 </div>
34 <div id="graph_content">
34 <div id="graph_content">
35 <div class="info_box" style="clear: both;padding: 10px 6px;vertical-align: right;text-align: right;">
35 <div class="info_box" style="clear: both;padding: 10px 6px;vertical-align: right;text-align: right;">
36 <a href="#" class="ui-btn small" id="rev_range_container" style="display:none"></a>
36 <a href="#" class="ui-btn small" id="rev_range_container" style="display:none"></a>
37 <a href="#" class="ui-btn small" id="rev_range_clear" style="display:none">${_('Clear selection')}</a>
37 <a href="#" class="ui-btn small" id="rev_range_clear" style="display:none">${_('Clear selection')}</a>
38
38
39 %if c.rhodecode_db_repo.fork:
39 %if c.rhodecode_db_repo.fork:
40 <a title="${_('compare fork with %s' % c.rhodecode_db_repo.fork.repo_name)}" href="${h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref=request.GET.get('branch') or 'default',other_repo=c.rhodecode_db_repo.fork.repo_name,other_ref_type='branch',other_ref='default')}" class="ui-btn small">${_('Compare fork with parent')}</a>
40 <a title="${_('compare fork with %s' % c.rhodecode_db_repo.fork.repo_name)}" href="${h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,org_ref_type='branch',org_ref='default',other_repo=c.repo_name,other_ref_type='branch',other_ref=request.GET.get('branch') or 'default')}" class="ui-btn small">${_('Compare fork with parent')}</a>
41 %endif
41 %endif
42 %if h.is_hg(c.rhodecode_repo):
42 %if h.is_hg(c.rhodecode_repo):
43 <a id="open_new_pr" href="${h.url('pullrequest_home',repo_name=c.repo_name)}" class="ui-btn small">${_('open new pull request')}</a>
43 <a id="open_new_pr" href="${h.url('pullrequest_home',repo_name=c.repo_name)}" class="ui-btn small">${_('open new pull request')}</a>
44 %endif
44 %endif
45 </div>
45 </div>
46 <div class="container_header">
46 <div class="container_header">
47 ${h.form(h.url.current(),method='get')}
47 ${h.form(h.url.current(),method='get')}
48 <div class="info_box" style="float:left">
48 <div class="info_box" style="float:left">
49 ${h.submit('set',_('Show'),class_="ui-btn")}
49 ${h.submit('set',_('Show'),class_="ui-btn")}
50 ${h.text('size',size=1,value=c.size)}
50 ${h.text('size',size=1,value=c.size)}
51 ${_('revisions')}
51 ${_('revisions')}
52 </div>
52 </div>
53 ${h.end_form()}
53 ${h.end_form()}
54 <div style="float:right">${h.select('branch_filter',c.branch_name,c.branch_filters)}</div>
54 <div style="float:right">${h.select('branch_filter',c.branch_name,c.branch_filters)}</div>
55 </div>
55 </div>
56
56
57 %for cnt,cs in enumerate(c.pagination):
57 %for cnt,cs in enumerate(c.pagination):
58 <div id="chg_${cnt+1}" class="container ${'tablerow%s' % (cnt%2)}">
58 <div id="chg_${cnt+1}" class="container ${'tablerow%s' % (cnt%2)}">
59 <div class="left">
59 <div class="left">
60 <div>
60 <div>
61 ${h.checkbox(cs.raw_id,class_="changeset_range")}
61 ${h.checkbox(cs.raw_id,class_="changeset_range")}
62 <span class="tooltip" title="${h.tooltip(h.age(cs.date))}"><a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}"><span class="changeset_id">${cs.revision}:<span class="changeset_hash">${h.short_id(cs.raw_id)}</span></span></a></span>
62 <span class="tooltip" title="${h.tooltip(h.age(cs.date))}"><a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}"><span class="changeset_id">${cs.revision}:<span class="changeset_hash">${h.short_id(cs.raw_id)}</span></span></a></span>
63 </div>
63 </div>
64 <div class="author">
64 <div class="author">
65 <div class="gravatar">
65 <div class="gravatar">
66 <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),16)}"/>
66 <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),16)}"/>
67 </div>
67 </div>
68 <div title="${cs.author}" class="user">${h.shorter(h.person(cs.author),22)}</div>
68 <div title="${cs.author}" class="user">${h.shorter(h.person(cs.author),22)}</div>
69 </div>
69 </div>
70 <div class="date">${h.fmt_date(cs.date)}</div>
70 <div class="date">${h.fmt_date(cs.date)}</div>
71 </div>
71 </div>
72 <div class="mid">
72 <div class="mid">
73 <div class="message">${h.urlify_commit(cs.message, c.repo_name,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
73 <div class="message">${h.urlify_commit(cs.message, c.repo_name,h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div>
74 <div class="expand"><span class="expandtext">&darr; ${_('show more')} &darr;</span></div>
74 <div class="expand"><span class="expandtext">&darr; ${_('show more')} &darr;</span></div>
75 </div>
75 </div>
76 <div class="right">
76 <div class="right">
77 <div class="changes">
77 <div class="changes">
78 <div id="changed_total_${cs.raw_id}" style="float:right;" class="changed_total tooltip" title="${h.tooltip(_('Affected number of files, click to show more details'))}">${len(cs.affected_files)}</div>
78 <div id="changed_total_${cs.raw_id}" style="float:right;" class="changed_total tooltip" title="${h.tooltip(_('Affected number of files, click to show more details'))}">${len(cs.affected_files)}</div>
79 <div class="comments-container">
79 <div class="comments-container">
80 %if len(c.comments.get(cs.raw_id,[])) > 0:
80 %if len(c.comments.get(cs.raw_id,[])) > 0:
81 <div class="comments-cnt" title="${('comments')}">
81 <div class="comments-cnt" title="${('comments')}">
82 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
82 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
83 <div class="comments-cnt">${len(c.comments[cs.raw_id])}</div>
83 <div class="comments-cnt">${len(c.comments[cs.raw_id])}</div>
84 <img src="${h.url('/images/icons/comments.png')}">
84 <img src="${h.url('/images/icons/comments.png')}">
85 </a>
85 </a>
86 </div>
86 </div>
87 %endif
87 %endif
88 </div>
88 </div>
89 <div class="changeset-status-container">
89 <div class="changeset-status-container">
90 %if c.statuses.get(cs.raw_id):
90 %if c.statuses.get(cs.raw_id):
91 <div title="${_('Changeset status')}" class="changeset-status-lbl">${c.statuses.get(cs.raw_id)[1]}</div>
91 <div title="${_('Changeset status')}" class="changeset-status-lbl">${c.statuses.get(cs.raw_id)[1]}</div>
92 <div class="changeset-status-ico">
92 <div class="changeset-status-ico">
93 %if c.statuses.get(cs.raw_id)[2]:
93 %if c.statuses.get(cs.raw_id)[2]:
94 <a class="tooltip" title="${_('Click to open associated pull request #%s' % c.statuses.get(cs.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" /></a>
94 <a class="tooltip" title="${_('Click to open associated pull request #%s' % c.statuses.get(cs.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" /></a>
95 %else:
95 %else:
96 <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
96 <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
97 %endif
97 %endif
98 </div>
98 </div>
99 %endif
99 %endif
100 </div>
100 </div>
101 </div>
101 </div>
102 %if cs.parents:
102 %if cs.parents:
103 %for p_cs in reversed(cs.parents):
103 %for p_cs in reversed(cs.parents):
104 <div class="parent">${_('Parent')}
104 <div class="parent">${_('Parent')}
105 <span class="changeset_id">${p_cs.revision}:<span class="changeset_hash">${h.link_to(h.short_id(p_cs.raw_id),
105 <span class="changeset_id">${p_cs.revision}:<span class="changeset_hash">${h.link_to(h.short_id(p_cs.raw_id),
106 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}</span></span>
106 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}</span></span>
107 </div>
107 </div>
108 %endfor
108 %endfor
109 %else:
109 %else:
110 <div class="parent">${_('No parents')}</div>
110 <div class="parent">${_('No parents')}</div>
111 %endif
111 %endif
112
112
113 <span class="logtags">
113 <span class="logtags">
114 %if len(cs.parents)>1:
114 %if len(cs.parents)>1:
115 <span class="merge">${_('merge')}</span>
115 <span class="merge">${_('merge')}</span>
116 %endif
116 %endif
117 %if cs.branch:
117 %if cs.branch:
118 <span class="branchtag" title="${'%s %s' % (_('branch'),cs.branch)}">
118 <span class="branchtag" title="${'%s %s' % (_('branch'),cs.branch)}">
119 ${h.link_to(h.shorter(cs.branch),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}
119 ${h.link_to(h.shorter(cs.branch),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}
120 </span>
120 </span>
121 %endif
121 %endif
122 %if h.is_hg(c.rhodecode_repo):
122 %if h.is_hg(c.rhodecode_repo):
123 %for book in cs.bookmarks:
123 %for book in cs.bookmarks:
124 <span class="bookbook" title="${'%s %s' % (_('bookmark'),book)}">
124 <span class="bookbook" title="${'%s %s' % (_('bookmark'),book)}">
125 ${h.link_to(h.shorter(book),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}
125 ${h.link_to(h.shorter(book),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}
126 </span>
126 </span>
127 %endfor
127 %endfor
128 %endif
128 %endif
129 %for tag in cs.tags:
129 %for tag in cs.tags:
130 <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}">
130 <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}">
131 ${h.link_to(h.shorter(tag),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}</span>
131 ${h.link_to(h.shorter(tag),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}</span>
132 %endfor
132 %endfor
133 </span>
133 </span>
134 </div>
134 </div>
135 </div>
135 </div>
136
136
137 %endfor
137 %endfor
138 <div class="pagination-wh pagination-left">
138 <div class="pagination-wh pagination-left">
139 ${c.pagination.pager('$link_previous ~2~ $link_next')}
139 ${c.pagination.pager('$link_previous ~2~ $link_next')}
140 </div>
140 </div>
141 </div>
141 </div>
142 </div>
142 </div>
143
143
144 <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
144 <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
145 <script type="text/javascript">
145 <script type="text/javascript">
146 YAHOO.util.Event.onDOMReady(function(){
146 YAHOO.util.Event.onDOMReady(function(){
147
147
148 //Monitor range checkboxes and build a link to changesets
148 //Monitor range checkboxes and build a link to changesets
149 //ranges
149 //ranges
150 var checkboxes = YUD.getElementsByClassName('changeset_range');
150 var checkboxes = YUD.getElementsByClassName('changeset_range');
151 var url_tmpl = "${h.url('changeset_home',repo_name=c.repo_name,revision='__REVRANGE__')}";
151 var url_tmpl = "${h.url('changeset_home',repo_name=c.repo_name,revision='__REVRANGE__')}";
152 var pr_tmpl = "${h.url('pullrequest_home',repo_name=c.repo_name)}";
152 var pr_tmpl = "${h.url('pullrequest_home',repo_name=c.repo_name)}";
153 YUE.on(checkboxes,'click',function(e){
153 YUE.on(checkboxes,'click',function(e){
154 var clicked_cb = e.currentTarget;
154 var clicked_cb = e.currentTarget;
155 var checked_checkboxes = [];
155 var checked_checkboxes = [];
156 for (pos in checkboxes){
156 for (pos in checkboxes){
157 if(checkboxes[pos].checked){
157 if(checkboxes[pos].checked){
158 checked_checkboxes.push(checkboxes[pos]);
158 checked_checkboxes.push(checkboxes[pos]);
159 }
159 }
160 }
160 }
161 if(YUD.get('open_new_pr')){
161 if(YUD.get('open_new_pr')){
162 if(checked_checkboxes.length>0){
162 if(checked_checkboxes.length>0){
163 // modify open pull request to show we have selected cs
163 // modify open pull request to show we have selected cs
164 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request for selected changesets'];
164 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request for selected changesets'];
165
165
166 }else{
166 }else{
167 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request'];
167 YUD.get('open_new_pr').innerHTML = _TM['Open new pull request'];
168 }
168 }
169 }
169 }
170
170
171 if(checked_checkboxes.length>0){
171 if(checked_checkboxes.length>0){
172 var rev_end = checked_checkboxes[0].name;
172 var rev_end = checked_checkboxes[0].name;
173 var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
173 var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
174
174
175 // now select all checkboxes in the middle.
175 // now select all checkboxes in the middle.
176 var checked = false;
176 var checked = false;
177 for (var i=0; i<checkboxes.length; i++){
177 for (var i=0; i<checkboxes.length; i++){
178 var cb = checkboxes[i];
178 var cb = checkboxes[i];
179 var rev = cb.name;
179 var rev = cb.name;
180
180
181 if (rev == rev_end){
181 if (rev == rev_end){
182 checked = true;
182 checked = true;
183 }
183 }
184 if (checked){
184 if (checked){
185 cb.checked = true;
185 cb.checked = true;
186 }
186 }
187 else{
187 else{
188 cb.checked = false;
188 cb.checked = false;
189 }
189 }
190 if (rev == rev_start){
190 if (rev == rev_start){
191 checked = false;
191 checked = false;
192 }
192 }
193
193
194 }
194 }
195
195
196 var url = url_tmpl.replace('__REVRANGE__',
196 var url = url_tmpl.replace('__REVRANGE__',
197 rev_start+'...'+rev_end);
197 rev_start+'...'+rev_end);
198
198
199 var link = _TM['Show selected changes __S -> __E'];
199 var link = _TM['Show selected changes __S -> __E'];
200 link = link.replace('__S',rev_start.substr(0,6));
200 link = link.replace('__S',rev_start.substr(0,6));
201 link = link.replace('__E',rev_end.substr(0,6));
201 link = link.replace('__E',rev_end.substr(0,6));
202 YUD.get('rev_range_container').href = url;
202 YUD.get('rev_range_container').href = url;
203 YUD.get('rev_range_container').innerHTML = link;
203 YUD.get('rev_range_container').innerHTML = link;
204 YUD.setStyle('rev_range_container','display','');
204 YUD.setStyle('rev_range_container','display','');
205 YUD.setStyle('rev_range_clear','display','');
205 YUD.setStyle('rev_range_clear','display','');
206
206
207 YUD.get('open_new_pr').href = pr_tmpl + '?rev_start={0}&rev_end={1}'.format(rev_start,rev_end);
207 YUD.get('open_new_pr').href = pr_tmpl + '?rev_start={0}&rev_end={1}'.format(rev_start,rev_end);
208
208
209 }
209 }
210 else{
210 else{
211 YUD.setStyle('rev_range_container','display','none');
211 YUD.setStyle('rev_range_container','display','none');
212 YUD.setStyle('rev_range_clear','display','none');
212 YUD.setStyle('rev_range_clear','display','none');
213 }
213 }
214 });
214 });
215 YUE.on('rev_range_clear','click',function(e){
215 YUE.on('rev_range_clear','click',function(e){
216 for (var i=0; i<checkboxes.length; i++){
216 for (var i=0; i<checkboxes.length; i++){
217 var cb = checkboxes[i];
217 var cb = checkboxes[i];
218 cb.checked = false;
218 cb.checked = false;
219 }
219 }
220 YUE.preventDefault(e);
220 YUE.preventDefault(e);
221 })
221 })
222 var msgs = YUQ('.message');
222 var msgs = YUQ('.message');
223 // get first element height
223 // get first element height
224 var el = YUQ('#graph_content .container')[0];
224 var el = YUQ('#graph_content .container')[0];
225 var row_h = el.clientHeight;
225 var row_h = el.clientHeight;
226 for(var i=0;i<msgs.length;i++){
226 for(var i=0;i<msgs.length;i++){
227 var m = msgs[i];
227 var m = msgs[i];
228
228
229 var h = m.clientHeight;
229 var h = m.clientHeight;
230 var pad = YUD.getStyle(m,'padding');
230 var pad = YUD.getStyle(m,'padding');
231 if(h > row_h){
231 if(h > row_h){
232 var offset = row_h - (h+12);
232 var offset = row_h - (h+12);
233 YUD.setStyle(m.nextElementSibling,'display','block');
233 YUD.setStyle(m.nextElementSibling,'display','block');
234 YUD.setStyle(m.nextElementSibling,'margin-top',offset+'px');
234 YUD.setStyle(m.nextElementSibling,'margin-top',offset+'px');
235 };
235 };
236 }
236 }
237 YUE.on(YUQ('.expand'),'click',function(e){
237 YUE.on(YUQ('.expand'),'click',function(e){
238 var elem = e.currentTarget.parentNode.parentNode;
238 var elem = e.currentTarget.parentNode.parentNode;
239 YUD.setStyle(e.currentTarget,'display','none');
239 YUD.setStyle(e.currentTarget,'display','none');
240 YUD.setStyle(elem,'height','auto');
240 YUD.setStyle(elem,'height','auto');
241
241
242 //redraw the graph, line_count and jsdata are global vars
242 //redraw the graph, line_count and jsdata are global vars
243 set_canvas(100);
243 set_canvas(100);
244
244
245 var r = new BranchRenderer();
245 var r = new BranchRenderer();
246 r.render(jsdata,100,line_count);
246 r.render(jsdata,100,line_count);
247
247
248 })
248 })
249
249
250 // Fetch changeset details
250 // Fetch changeset details
251 YUE.on(YUD.getElementsByClassName('changed_total'),'click',function(e){
251 YUE.on(YUD.getElementsByClassName('changed_total'),'click',function(e){
252 var id = e.currentTarget.id;
252 var id = e.currentTarget.id;
253 var url = "${h.url('changelog_details',repo_name=c.repo_name,cs='__CS__')}";
253 var url = "${h.url('changelog_details',repo_name=c.repo_name,cs='__CS__')}";
254 var url = url.replace('__CS__',id.replace('changed_total_',''));
254 var url = url.replace('__CS__',id.replace('changed_total_',''));
255 ypjax(url,id,function(){tooltip_activate()});
255 ypjax(url,id,function(){tooltip_activate()});
256 });
256 });
257
257
258 // change branch filter
258 // change branch filter
259 YUE.on(YUD.get('branch_filter'),'change',function(e){
259 YUE.on(YUD.get('branch_filter'),'change',function(e){
260 var selected_branch = e.currentTarget.options[e.currentTarget.selectedIndex].value;
260 var selected_branch = e.currentTarget.options[e.currentTarget.selectedIndex].value;
261 var url_main = "${h.url('changelog_home',repo_name=c.repo_name)}";
261 var url_main = "${h.url('changelog_home',repo_name=c.repo_name)}";
262 var url = "${h.url('changelog_home',repo_name=c.repo_name,branch='__BRANCH__')}";
262 var url = "${h.url('changelog_home',repo_name=c.repo_name,branch='__BRANCH__')}";
263 var url = url.replace('__BRANCH__',selected_branch);
263 var url = url.replace('__BRANCH__',selected_branch);
264 if(selected_branch != ''){
264 if(selected_branch != ''){
265 window.location = url;
265 window.location = url;
266 }else{
266 }else{
267 window.location = url_main;
267 window.location = url_main;
268 }
268 }
269
269
270 });
270 });
271
271
272 function set_canvas(width) {
272 function set_canvas(width) {
273 var c = document.getElementById('graph_nodes');
273 var c = document.getElementById('graph_nodes');
274 var t = document.getElementById('graph_content');
274 var t = document.getElementById('graph_content');
275 canvas = document.getElementById('graph_canvas');
275 canvas = document.getElementById('graph_canvas');
276 var div_h = t.clientHeight;
276 var div_h = t.clientHeight;
277 c.style.height=div_h+'px';
277 c.style.height=div_h+'px';
278 canvas.setAttribute('height',div_h);
278 canvas.setAttribute('height',div_h);
279 c.style.height=width+'px';
279 c.style.height=width+'px';
280 canvas.setAttribute('width',width);
280 canvas.setAttribute('width',width);
281 };
281 };
282 var heads = 1;
282 var heads = 1;
283 var line_count = 0;
283 var line_count = 0;
284 var jsdata = ${c.jsdata|n};
284 var jsdata = ${c.jsdata|n};
285
285
286 for (var i=0;i<jsdata.length;i++) {
286 for (var i=0;i<jsdata.length;i++) {
287 var in_l = jsdata[i][2];
287 var in_l = jsdata[i][2];
288 for (var j in in_l) {
288 for (var j in in_l) {
289 var m = in_l[j][1];
289 var m = in_l[j][1];
290 if (m > line_count)
290 if (m > line_count)
291 line_count = m;
291 line_count = m;
292 }
292 }
293 }
293 }
294 set_canvas(100);
294 set_canvas(100);
295
295
296 var r = new BranchRenderer();
296 var r = new BranchRenderer();
297 r.render(jsdata,100,line_count);
297 r.render(jsdata,100,line_count);
298
298
299 });
299 });
300 </script>
300 </script>
301 %else:
301 %else:
302 ${_('There are no changes yet')}
302 ${_('There are no changes yet')}
303 %endif
303 %endif
304 </div>
304 </div>
305 </div>
305 </div>
306 </%def>
306 </%def>
@@ -1,43 +1,43 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2
2
3 % if c.forks_pager:
3 % if c.forks_pager:
4 % for f in c.forks_pager:
4 % for f in c.forks_pager:
5 <div>
5 <div>
6 <div class="fork_user">
6 <div class="fork_user">
7 <div class="gravatar">
7 <div class="gravatar">
8 <img alt="gravatar" src="${h.gravatar_url(f.user.email,24)}"/>
8 <img alt="gravatar" src="${h.gravatar_url(f.user.email,24)}"/>
9 </div>
9 </div>
10 <span style="font-size: 20px">
10 <span style="font-size: 20px">
11 <b>${f.user.username}</b> (${f.user.name} ${f.user.lastname}) /
11 <b>${f.user.username}</b> (${f.user.name} ${f.user.lastname}) /
12 ${h.link_to(f.repo_name,h.url('summary_home',repo_name=f.repo_name))}
12 ${h.link_to(f.repo_name,h.url('summary_home',repo_name=f.repo_name))}
13 </span>
13 </span>
14 <div style="padding:5px 3px 3px 42px;">${f.description}</div>
14 <div style="padding:5px 3px 3px 42px;">${f.description}</div>
15 </div>
15 </div>
16 <div style="clear:both;padding-top: 10px"></div>
16 <div style="clear:both;padding-top: 10px"></div>
17 <div class="follower_date">${_('forked')} -
17 <div class="follower_date">${_('forked')} -
18 <span class="tooltip" title="${h.tooltip(h.fmt_date(f.created_on))}"> ${h.age(f.created_on)}</span>
18 <span class="tooltip" title="${h.tooltip(h.fmt_date(f.created_on))}"> ${h.age(f.created_on)}</span>
19 <a title="${_('compare fork with %s' % c.repo_name)}"
19 <a title="${_('compare fork with %s' % c.repo_name)}"
20 href="${h.url('compare_url',repo_name=f.repo_name,org_ref_type='branch',org_ref='default',other_repo=c.repo_name,other_ref_type='branch',other_ref='default')}"
20 href="${h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref='default',other_repo=f.repo_name,other_ref_type='branch',other_ref='default')}"
21 class="ui-btn small">${_('Compare fork')}</a>
21 class="ui-btn small">${_('Compare fork')}</a>
22 </div>
22 </div>
23 <div style="border-bottom: 1px solid #DDD;margin:10px 0px 10px 0px"></div>
23 <div style="border-bottom: 1px solid #DDD;margin:10px 0px 10px 0px"></div>
24 </div>
24 </div>
25 % endfor
25 % endfor
26 <div class="pagination-wh pagination-left">
26 <div class="pagination-wh pagination-left">
27 <script type="text/javascript">
27 <script type="text/javascript">
28 YUE.onDOMReady(function(){
28 YUE.onDOMReady(function(){
29 YUE.delegate("forks","click",function(e, matchedEl, container){
29 YUE.delegate("forks","click",function(e, matchedEl, container){
30 ypjax(e.target.href,"forks",function(){
30 ypjax(e.target.href,"forks",function(){
31 show_more_event();
31 show_more_event();
32 tooltip_activate();
32 tooltip_activate();
33 show_changeset_tooltip();
33 show_changeset_tooltip();
34 });
34 });
35 YUE.preventDefault(e);
35 YUE.preventDefault(e);
36 },'.pager_link');
36 },'.pager_link');
37 });
37 });
38 </script>
38 </script>
39 ${c.forks_pager.pager('$link_previous ~2~ $link_next')}
39 ${c.forks_pager.pager('$link_previous ~2~ $link_next')}
40 </div>
40 </div>
41 % else:
41 % else:
42 ${_('There are no forks yet')}
42 ${_('There are no forks yet')}
43 % endif
43 % endif
@@ -1,199 +1,199 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} ${_('New 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()">
8 ${h.link_to(_(u'Home'),h.url('/'))}
8 ${h.link_to(_(u'Home'),h.url('/'))}
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 ${_('New pull request')}
12 ${_('New pull request')}
13 </%def>
13 </%def>
14
14
15 <%def name="main()">
15 <%def name="main()">
16
16
17 <div class="box">
17 <div class="box">
18 <!-- box / title -->
18 <!-- box / title -->
19 <div class="title">
19 <div class="title">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22 ${h.form(url('pullrequest', repo_name=c.repo_name), method='post', 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:0px 30px 30px 30px">
23 <div style="float:left;padding:0px 30px 30px 30px">
24 <input type="hidden" name="rev_start" value="${request.GET.get('rev_start')}" />
24 <input type="hidden" name="rev_start" value="${request.GET.get('rev_start')}" />
25 <input type="hidden" name="rev_end" value="${request.GET.get('rev_end')}" />
25 <input type="hidden" name="rev_end" value="${request.GET.get('rev_end')}" />
26
26
27 ##ORG
27 ##ORG
28 <div style="float:left">
28 <div style="float:left">
29 <div class="fork_user">
29 <div class="fork_user">
30 <div class="gravatar">
30 <div class="gravatar">
31 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_db_repo.user.email,24)}"/>
31 <img alt="gravatar" src="${h.gravatar_url(c.rhodecode_db_repo.user.email,24)}"/>
32 </div>
32 </div>
33 <span style="font-size: 20px">
33 <span style="font-size: 20px">
34 ${h.select('org_repo','',c.org_repos,class_='refs')}:${h.select('org_ref','',c.org_refs,class_='refs')}
34 ${h.select('org_repo','',c.org_repos,class_='refs')}:${h.select('org_ref','',c.org_refs,class_='refs')}
35 </span>
35 </span>
36 <div style="padding:5px 3px 3px 42px;">${c.rhodecode_db_repo.description}</div>
36 <div style="padding:5px 3px 3px 42px;">${c.rhodecode_db_repo.description}</div>
37 </div>
37 </div>
38 <div style="clear:both;padding-top: 10px"></div>
38 <div style="clear:both;padding-top: 10px"></div>
39 </div>
39 </div>
40 <div style="float:left;font-size:24px;padding:0px 20px">
40 <div style="float:left;font-size:24px;padding:0px 20px">
41 <img height=32 width=32 src="${h.url('/images/arrow_right_64.png')}"/>
41 <img height=32 width=32 src="${h.url('/images/arrow_right_64.png')}"/>
42 </div>
42 </div>
43
43
44 ##OTHER, most Probably the PARENT OF THIS FORK
44 ##OTHER, most Probably the PARENT OF THIS FORK
45 <div style="float:left">
45 <div style="float:left">
46 <div class="fork_user">
46 <div class="fork_user">
47 <div class="gravatar">
47 <div class="gravatar">
48 <img id="other_repo_gravatar" alt="gravatar" src=""/>
48 <img id="other_repo_gravatar" alt="gravatar" src=""/>
49 </div>
49 </div>
50 <span style="font-size: 20px">
50 <span style="font-size: 20px">
51 ${h.select('other_repo',c.default_pull_request ,c.other_repos,class_='refs')}:${h.select('other_ref',c.default_pull_request_rev,c.default_revs,class_='refs')}
51 ${h.select('other_repo',c.default_pull_request ,c.other_repos,class_='refs')}:${h.select('other_ref',c.default_pull_request_rev,c.default_revs,class_='refs')}
52 </span>
52 </span>
53 <span style="padding:3px">
53 <span style="padding:3px">
54 <a id="refresh" href="#" class="tooltip" title="${h.tooltip(_('refresh overview'))}">
54 <a id="refresh" href="#" class="tooltip" title="${h.tooltip(_('refresh overview'))}">
55 <img style="margin:3px" class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/>
55 <img style="margin:3px" class="icon" title="${_('Refresh')}" alt="${_('Refresh')}" src="${h.url('/images/icons/arrow_refresh.png')}"/>
56 </a>
56 </a>
57 </span>
57 </span>
58 <div id="other_repo_desc" style="padding:5px 3px 3px 42px;"></div>
58 <div id="other_repo_desc" style="padding:5px 3px 3px 42px;"></div>
59 </div>
59 </div>
60 <div style="clear:both;padding-top: 10px"></div>
60 <div style="clear:both;padding-top: 10px"></div>
61 </div>
61 </div>
62 <div style="clear:both;padding-top: 10px"></div>
62 <div style="clear:both;padding-top: 10px"></div>
63 ## overview pulled by ajax
63 ## overview pulled by ajax
64 <div style="float:left" id="pull_request_overview"></div>
64 <div style="float:left" id="pull_request_overview"></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>
71 <div id="reviewers" style="padding:0px 0px 0px 15px">
71 <div id="reviewers" style="padding:0px 0px 0px 15px">
72 ## members goes here !
72 ## members goes here !
73 <div class="group_members_wrap">
73 <div class="group_members_wrap">
74 <ul id="review_members" class="group_members">
74 <ul id="review_members" class="group_members">
75 %for member in c.review_members:
75 %for member in c.review_members:
76 <li id="reviewer_${member.user_id}">
76 <li id="reviewer_${member.user_id}">
77 <div class="reviewers_member">
77 <div class="reviewers_member">
78 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
78 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
79 <div style="float:left">${member.full_name} (${_('owner')})</div>
79 <div style="float:left">${member.full_name} (${_('owner')})</div>
80 <input type="hidden" value="${member.user_id}" name="review_members" />
80 <input type="hidden" value="${member.user_id}" name="review_members" />
81 <span class="delete_icon action_button" onclick="removeReviewer(${member.user_id})"></span>
81 <span class="delete_icon action_button" onclick="removeReviewer(${member.user_id})"></span>
82 </div>
82 </div>
83 </li>
83 </li>
84 %endfor
84 %endfor
85 </ul>
85 </ul>
86 </div>
86 </div>
87
87
88 <div class='ac'>
88 <div class='ac'>
89 <div class="reviewer_ac">
89 <div class="reviewer_ac">
90 ${h.text('user', class_='yui-ac-input')}
90 ${h.text('user', class_='yui-ac-input')}
91 <span class="help-block">${_('Add reviewer to this pull request.')}</span>
91 <span class="help-block">${_('Add reviewer to this pull request.')}</span>
92 <div id="reviewers_container"></div>
92 <div id="reviewers_container"></div>
93 </div>
93 </div>
94 </div>
94 </div>
95 </div>
95 </div>
96 </div>
96 </div>
97 <h3>${_('Create new pull request')}</h3>
97 <h3>${_('Create new pull request')}</h3>
98
98
99 <div class="form">
99 <div class="form">
100 <!-- fields -->
100 <!-- fields -->
101
101
102 <div class="fields">
102 <div class="fields">
103
103
104 <div class="field">
104 <div class="field">
105 <div class="label">
105 <div class="label">
106 <label for="pullrequest_title">${_('Title')}:</label>
106 <label for="pullrequest_title">${_('Title')}:</label>
107 </div>
107 </div>
108 <div class="input">
108 <div class="input">
109 ${h.text('pullrequest_title',size=30)}
109 ${h.text('pullrequest_title',size=30)}
110 </div>
110 </div>
111 </div>
111 </div>
112
112
113 <div class="field">
113 <div class="field">
114 <div class="label label-textarea">
114 <div class="label label-textarea">
115 <label for="pullrequest_desc">${_('description')}:</label>
115 <label for="pullrequest_desc">${_('description')}:</label>
116 </div>
116 </div>
117 <div class="textarea text-area editor">
117 <div class="textarea text-area editor">
118 ${h.textarea('pullrequest_desc',size=30)}
118 ${h.textarea('pullrequest_desc',size=30)}
119 </div>
119 </div>
120 </div>
120 </div>
121
121
122 <div class="buttons">
122 <div class="buttons">
123 ${h.submit('save',_('Send pull request'),class_="ui-btn large")}
123 ${h.submit('save',_('Send pull request'),class_="ui-btn large")}
124 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
124 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
125 </div>
125 </div>
126 </div>
126 </div>
127 </div>
127 </div>
128 ${h.end_form()}
128 ${h.end_form()}
129
129
130 </div>
130 </div>
131
131
132 <script type="text/javascript">
132 <script type="text/javascript">
133 var _USERS_AC_DATA = ${c.users_array|n};
133 var _USERS_AC_DATA = ${c.users_array|n};
134 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
134 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
135 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
135 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
136
136
137 var other_repos_info = ${c.other_repos_info|n};
137 var other_repos_info = ${c.other_repos_info|n};
138
138
139 var loadPreview = function(){
139 var loadPreview = function(){
140 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
140 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','none');
141 //url template
141 //url template
142 var url = "${h.url('compare_url',
142 var url = "${h.url('compare_url',
143 repo_name='__org_repo__',
143 repo_name='__other_repo__',
144 org_ref_type='__org_ref_type__',
144 org_ref_type='__other_ref_type__',
145 org_ref='__org_ref__',
145 org_ref='__other_ref__',
146 other_repo='__other_repo__',
146 other_repo='__org_repo__',
147 other_ref_type='__other_ref_type__',
147 other_ref_type='__org_ref_type__',
148 other_ref='__other_ref__',
148 other_ref='__org_ref__',
149 as_form=True,
149 as_form=True,
150 rev_start=request.GET.get('rev_start',''),
150 rev_start=request.GET.get('rev_start',''),
151 rev_end=request.GET.get('rev_end',''))}";
151 rev_end=request.GET.get('rev_end',''))}";
152 var org_repo = YUQ('#pull_request_form #org_repo')[0].value;
152 var org_repo = YUQ('#pull_request_form #org_repo')[0].value;
153 var org_ref = YUQ('#pull_request_form #org_ref')[0].value.split(':');
153 var org_ref = YUQ('#pull_request_form #org_ref')[0].value.split(':');
154
154
155 var other_repo = YUQ('#pull_request_form #other_repo')[0].value;
155 var other_repo = YUQ('#pull_request_form #other_repo')[0].value;
156 var other_ref = YUQ('#pull_request_form #other_ref')[0].value.split(':');
156 var other_ref = YUQ('#pull_request_form #other_ref')[0].value.split(':');
157
157
158 var select_refs = YUQ('#pull_request_form select.refs')
158 var select_refs = YUQ('#pull_request_form select.refs')
159 var rev_data = {
159 var rev_data = {
160 'org_repo': org_repo,
160 'org_repo': org_repo,
161 'org_ref': org_ref[1],
161 'org_ref': org_ref[1],
162 'org_ref_type': org_ref[0],
162 'org_ref_type': org_ref[0],
163 'other_repo': other_repo,
163 'other_repo': other_repo,
164 'other_ref': other_ref[1],
164 'other_ref': other_ref[1],
165 'other_ref_type': other_ref[0],
165 'other_ref_type': other_ref[0],
166 }; // gather the org/other ref and repo here
166 }; // gather the org/other ref and repo here
167
167
168 for (k in rev_data){
168 for (k in rev_data){
169 url = url.replace('__'+k+'__',rev_data[k]);
169 url = url.replace('__'+k+'__',rev_data[k]);
170 }
170 }
171
171
172 YUE.on('other_repo', 'change', function(e){
172 YUE.on('other_repo', 'change', function(e){
173 var repo_name = e.currentTarget.value;
173 var repo_name = e.currentTarget.value;
174 // replace the <select> of changed repo
174 // replace the <select> of changed repo
175 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
175 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
176 });
176 });
177
177
178 ypjax(url,'pull_request_overview', function(data){
178 ypjax(url,'pull_request_overview', function(data){
179 var sel_box = YUQ('#pull_request_form #other_repo')[0];
179 var sel_box = YUQ('#pull_request_form #other_repo')[0];
180 var repo_name = sel_box.options[sel_box.selectedIndex].value;
180 var repo_name = sel_box.options[sel_box.selectedIndex].value;
181 YUD.get('pull_request_overview_url').href = url;
181 YUD.get('pull_request_overview_url').href = url;
182 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
182 YUD.setStyle(YUD.get('pull_request_overview_url').parentElement,'display','');
183 YUD.get('other_repo_gravatar').src = other_repos_info[repo_name]['gravatar'];
183 YUD.get('other_repo_gravatar').src = other_repos_info[repo_name]['gravatar'];
184 YUD.get('other_repo_desc').innerHTML = other_repos_info[repo_name]['description'];
184 YUD.get('other_repo_desc').innerHTML = other_repos_info[repo_name]['description'];
185 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
185 YUD.get('other_ref').innerHTML = other_repos_info[repo_name]['revs'];
186 // select back the revision that was just compared
186 // select back the revision that was just compared
187 setSelectValue(YUD.get('other_ref'), rev_data['other_ref']);
187 setSelectValue(YUD.get('other_ref'), rev_data['other_ref']);
188 })
188 })
189 }
189 }
190 YUE.on('refresh','click',function(e){
190 YUE.on('refresh','click',function(e){
191 loadPreview()
191 loadPreview()
192 })
192 })
193
193
194 //lazy load overview after 0.5s
194 //lazy load overview after 0.5s
195 setTimeout(loadPreview, 500)
195 setTimeout(loadPreview, 500)
196
196
197 </script>
197 </script>
198
198
199 </%def>
199 </%def>
@@ -1,348 +1,348 b''
1 from rhodecode.tests import *
1 from rhodecode.tests import *
2 from rhodecode.model.repo import RepoModel
2 from rhodecode.model.repo import RepoModel
3 from rhodecode.model.meta import Session
3 from rhodecode.model.meta import Session
4 from rhodecode.model.db import Repository
4 from rhodecode.model.db import Repository
5 from rhodecode.model.scm import ScmModel
5 from rhodecode.model.scm import ScmModel
6 from rhodecode.lib.vcs.backends.base import EmptyChangeset
6 from rhodecode.lib.vcs.backends.base import EmptyChangeset
7
7
8
8
9 def _fork_repo(fork_name, vcs_type, parent=None):
9 def _fork_repo(fork_name, vcs_type, parent=None):
10 if vcs_type =='hg':
10 if vcs_type =='hg':
11 _REPO = HG_REPO
11 _REPO = HG_REPO
12 elif vcs_type == 'git':
12 elif vcs_type == 'git':
13 _REPO = GIT_REPO
13 _REPO = GIT_REPO
14
14
15 if parent:
15 if parent:
16 _REPO = parent
16 _REPO = parent
17
17
18 form_data = dict(
18 form_data = dict(
19 repo_name=fork_name,
19 repo_name=fork_name,
20 repo_name_full=fork_name,
20 repo_name_full=fork_name,
21 repo_group=None,
21 repo_group=None,
22 repo_type=vcs_type,
22 repo_type=vcs_type,
23 description='',
23 description='',
24 private=False,
24 private=False,
25 copy_permissions=False,
25 copy_permissions=False,
26 landing_rev='tip',
26 landing_rev='tip',
27 update_after_clone=False,
27 update_after_clone=False,
28 fork_parent_id=Repository.get_by_repo_name(_REPO),
28 fork_parent_id=Repository.get_by_repo_name(_REPO),
29 )
29 )
30 repo = RepoModel().create_fork(form_data, cur_user=TEST_USER_ADMIN_LOGIN)
30 repo = RepoModel().create_fork(form_data, cur_user=TEST_USER_ADMIN_LOGIN)
31
31
32 Session().commit()
32 Session().commit()
33 return Repository.get_by_repo_name(fork_name)
33 return Repository.get_by_repo_name(fork_name)
34
34
35
35
36 def _commit_change(repo, filename, content, message, vcs_type, parent=None, newfile=False):
36 def _commit_change(repo, filename, content, message, vcs_type, parent=None, newfile=False):
37 repo = Repository.get_by_repo_name(repo)
37 repo = Repository.get_by_repo_name(repo)
38 _cs = parent
38 _cs = parent
39 if not parent:
39 if not parent:
40 _cs = EmptyChangeset(alias=vcs_type)
40 _cs = EmptyChangeset(alias=vcs_type)
41
41
42 if newfile:
42 if newfile:
43 cs = ScmModel().create_node(
43 cs = ScmModel().create_node(
44 repo=repo.scm_instance, repo_name=repo.repo_name,
44 repo=repo.scm_instance, repo_name=repo.repo_name,
45 cs=_cs, user=TEST_USER_ADMIN_LOGIN,
45 cs=_cs, user=TEST_USER_ADMIN_LOGIN,
46 author=TEST_USER_ADMIN_LOGIN,
46 author=TEST_USER_ADMIN_LOGIN,
47 message=message,
47 message=message,
48 content=content,
48 content=content,
49 f_path=filename
49 f_path=filename
50 )
50 )
51 else:
51 else:
52 cs = ScmModel().commit_change(
52 cs = ScmModel().commit_change(
53 repo=repo.scm_instance, repo_name=repo.repo_name,
53 repo=repo.scm_instance, repo_name=repo.repo_name,
54 cs=parent, user=TEST_USER_ADMIN_LOGIN,
54 cs=parent, user=TEST_USER_ADMIN_LOGIN,
55 author=TEST_USER_ADMIN_LOGIN,
55 author=TEST_USER_ADMIN_LOGIN,
56 message=message,
56 message=message,
57 content=content,
57 content=content,
58 f_path=filename
58 f_path=filename
59 )
59 )
60 return cs
60 return cs
61
61
62
62
63 class TestCompareController(TestController):
63 class TestCompareController(TestController):
64
64
65 def test_compare_forks_on_branch_extra_commits_hg(self):
65 def test_compare_forks_on_branch_extra_commits_hg(self):
66 self.log_user()
66 self.log_user()
67
67
68 repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
68 repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
69 description='diff-test',
69 description='diff-test',
70 owner=TEST_USER_ADMIN_LOGIN)
70 owner=TEST_USER_ADMIN_LOGIN)
71 r1_id = repo1.repo_id
71 r1_id = repo1.repo_id
72 Session().commit()
72 Session().commit()
73 #commit something !
73 #commit something !
74 cs0 = _commit_change(repo1.repo_name, filename='file1', content='line1\n',
74 cs0 = _commit_change(repo1.repo_name, filename='file1', content='line1\n',
75 message='commit1', vcs_type='hg', parent=None, newfile=True)
75 message='commit1', vcs_type='hg', parent=None, newfile=True)
76
76
77 #fork this repo
77 #fork this repo
78 repo2 = _fork_repo('one-fork', 'hg', parent='one')
78 repo2 = _fork_repo('one-fork', 'hg', parent='one')
79 Session().commit()
79 Session().commit()
80 r2_id = repo2.repo_id
80 r2_id = repo2.repo_id
81
81
82 #add two extra commit into fork
82 #add two extra commit into fork
83 cs1 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\n',
83 cs1 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\n',
84 message='commit2', vcs_type='hg', parent=cs0)
84 message='commit2', vcs_type='hg', parent=cs0)
85
85
86 cs2 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\nline3\n',
86 cs2 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\nline3\n',
87 message='commit3', vcs_type='hg', parent=cs1)
87 message='commit3', vcs_type='hg', parent=cs1)
88
88
89 rev1 = 'default'
89 rev1 = 'default'
90 rev2 = 'default'
90 rev2 = 'default'
91 response = self.app.get(url(controller='compare', action='index',
91 response = self.app.get(url(controller='compare', action='index',
92 repo_name=repo2.repo_name,
92 repo_name=repo1.repo_name,
93 org_ref_type="branch",
93 org_ref_type="branch",
94 org_ref=rev1,
94 org_ref=rev2,
95 other_repo=repo1.repo_name,
95 other_repo=repo2.repo_name,
96 other_ref_type="branch",
96 other_ref_type="branch",
97 other_ref=rev2,
97 other_ref=rev1,
98 ))
98 ))
99
99
100 try:
100 try:
101 response.mustcontain('%s@%s -&gt; %s@%s' % (repo2.repo_name, rev1, repo1.repo_name, rev2))
101 response.mustcontain('%s@%s -&gt; %s@%s' % (repo1.repo_name, rev2, repo2.repo_name, rev1))
102 response.mustcontain("""Showing 2 commits""")
102 response.mustcontain("""Showing 2 commits""")
103 response.mustcontain("""1 file changed with 2 insertions and 0 deletions""")
103 response.mustcontain("""1 file changed with 2 insertions and 0 deletions""")
104
104
105 response.mustcontain("""<div class="message tooltip" title="commit2" style="white-space:normal">commit2</div>""")
105 response.mustcontain("""<div class="message tooltip" title="commit2" style="white-space:normal">commit2</div>""")
106 response.mustcontain("""<div class="message tooltip" title="commit3" style="white-space:normal">commit3</div>""")
106 response.mustcontain("""<div class="message tooltip" title="commit3" style="white-space:normal">commit3</div>""")
107
107
108 response.mustcontain("""<a href="/%s/changeset/%s">r1:%s</a>""" % (repo2.repo_name, cs1.raw_id, cs1.short_id))
108 response.mustcontain("""<a href="/%s/changeset/%s">r1:%s</a>""" % (repo2.repo_name, cs1.raw_id, cs1.short_id))
109 response.mustcontain("""<a href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id))
109 response.mustcontain("""<a href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id))
110 ## files
110 ## files
111 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
111 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo1.repo_name, rev2, rev1, repo2.repo_name))
112 #swap
112 #swap
113 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?as_form=None&amp;other_repo=%s">[swap]</a>""" % (repo1.repo_name, rev1, rev2, repo2.repo_name))
113 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?as_form=None&amp;other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
114 finally:
114 finally:
115 RepoModel().delete(r2_id)
115 RepoModel().delete(r2_id)
116 RepoModel().delete(r1_id)
116 RepoModel().delete(r1_id)
117
117
118 def test_compare_forks_on_branch_extra_commits_origin_has_incomming_hg(self):
118 def test_compare_forks_on_branch_extra_commits_origin_has_incomming_hg(self):
119 self.log_user()
119 self.log_user()
120
120
121 repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
121 repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
122 description='diff-test',
122 description='diff-test',
123 owner=TEST_USER_ADMIN_LOGIN)
123 owner=TEST_USER_ADMIN_LOGIN)
124 r1_id = repo1.repo_id
124 r1_id = repo1.repo_id
125 Session().commit()
125 Session().commit()
126 #commit something !
126 #commit something !
127 cs0 = _commit_change(repo1.repo_name, filename='file1', content='line1\n',
127 cs0 = _commit_change(repo1.repo_name, filename='file1', content='line1\n',
128 message='commit1', vcs_type='hg', parent=None, newfile=True)
128 message='commit1', vcs_type='hg', parent=None, newfile=True)
129
129
130 #fork this repo
130 #fork this repo
131 repo2 = _fork_repo('one-fork', 'hg', parent='one')
131 repo2 = _fork_repo('one-fork', 'hg', parent='one')
132 Session().commit()
132 Session().commit()
133
133
134 #now commit something to origin repo
134 #now commit something to origin repo
135 cs1_prim = _commit_change(repo1.repo_name, filename='file2', content='line1file2\n',
135 cs1_prim = _commit_change(repo1.repo_name, filename='file2', content='line1file2\n',
136 message='commit2', vcs_type='hg', parent=cs0, newfile=True)
136 message='commit2', vcs_type='hg', parent=cs0, newfile=True)
137
137
138 r2_id = repo2.repo_id
138 r2_id = repo2.repo_id
139
139
140 #add two extra commit into fork
140 #add two extra commit into fork
141 cs1 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\n',
141 cs1 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\n',
142 message='commit2', vcs_type='hg', parent=cs0)
142 message='commit2', vcs_type='hg', parent=cs0)
143
143
144 cs2 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\nline3\n',
144 cs2 = _commit_change(repo2.repo_name, filename='file1', content='line1\nline2\nline3\n',
145 message='commit3', vcs_type='hg', parent=cs1)
145 message='commit3', vcs_type='hg', parent=cs1)
146
146
147 rev1 = 'default'
147 rev1 = 'default'
148 rev2 = 'default'
148 rev2 = 'default'
149 response = self.app.get(url(controller='compare', action='index',
149 response = self.app.get(url(controller='compare', action='index',
150 repo_name=repo2.repo_name,
150 repo_name=repo1.repo_name,
151 org_ref_type="branch",
151 org_ref_type="branch",
152 org_ref=rev1,
152 org_ref=rev2,
153 other_repo=repo1.repo_name,
153 other_repo=repo2.repo_name,
154 other_ref_type="branch",
154 other_ref_type="branch",
155 other_ref=rev2,
155 other_ref=rev1,
156 ))
156 ))
157
157
158 try:
158 try:
159 response.mustcontain('%s@%s -&gt; %s@%s' % (repo2.repo_name, rev1, repo1.repo_name, rev2))
159 response.mustcontain('%s@%s -&gt; %s@%s' % (repo1.repo_name, rev2, repo2.repo_name, rev1))
160 response.mustcontain("""Showing 2 commits""")
160 response.mustcontain("""Showing 2 commits""")
161 response.mustcontain("""1 file changed with 2 insertions and 0 deletions""")
161 response.mustcontain("""1 file changed with 2 insertions and 0 deletions""")
162
162
163 response.mustcontain("""<div class="message tooltip" title="commit2" style="white-space:normal">commit2</div>""")
163 response.mustcontain("""<div class="message tooltip" title="commit2" style="white-space:normal">commit2</div>""")
164 response.mustcontain("""<div class="message tooltip" title="commit3" style="white-space:normal">commit3</div>""")
164 response.mustcontain("""<div class="message tooltip" title="commit3" style="white-space:normal">commit3</div>""")
165
165
166 response.mustcontain("""<a href="/%s/changeset/%s">r1:%s</a>""" % (repo2.repo_name, cs1.raw_id, cs1.short_id))
166 response.mustcontain("""<a href="/%s/changeset/%s">r1:%s</a>""" % (repo2.repo_name, cs1.raw_id, cs1.short_id))
167 response.mustcontain("""<a href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id))
167 response.mustcontain("""<a href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id))
168 ## files
168 ## files
169 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
169 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?other_repo=%s#C--826e8142e6ba">file1</a>""" % (repo1.repo_name, rev2, rev1, repo2.repo_name))
170 #swap
170 #swap
171 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?as_form=None&amp;other_repo=%s">[swap]</a>""" % (repo1.repo_name, rev1, rev2, repo2.repo_name))
171 response.mustcontain("""<a href="/%s/compare/branch@%s...branch@%s?as_form=None&amp;other_repo=%s">[swap]</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name))
172 finally:
172 finally:
173 RepoModel().delete(r2_id)
173 RepoModel().delete(r2_id)
174 RepoModel().delete(r1_id)
174 RepoModel().delete(r1_id)
175
175
176
176
177 # def test_compare_remote_repos_remote_flag_off(self):
177 # def test_compare_remote_repos_remote_flag_off(self):
178 # self.log_user()
178 # self.log_user()
179 # _fork_repo(HG_FORK, 'hg')
179 # _fork_repo(HG_FORK, 'hg')
180 #
180 #
181 # rev1 = '56349e29c2af'
181 # rev1 = '56349e29c2af'
182 # rev2 = '7d4bc8ec6be5'
182 # rev2 = '7d4bc8ec6be5'
183 #
183 #
184 # response = self.app.get(url(controller='compare', action='index',
184 # response = self.app.get(url(controller='compare', action='index',
185 # repo_name=HG_REPO,
185 # repo_name=HG_REPO,
186 # org_ref_type="rev",
186 # org_ref_type="rev",
187 # org_ref=rev1,
187 # org_ref=rev1,
188 # other_ref_type="rev",
188 # other_ref_type="rev",
189 # other_ref=rev2,
189 # other_ref=rev2,
190 # repo=HG_FORK,
190 # repo=HG_FORK,
191 # bundle=False,
191 # bundle=False,
192 # ))
192 # ))
193 #
193 #
194 # try:
194 # try:
195 # response.mustcontain('%s@%s -&gt; %s@%s' % (HG_REPO, rev1, HG_FORK, rev2))
195 # response.mustcontain('%s@%s -&gt; %s@%s' % (HG_REPO, rev1, HG_FORK, rev2))
196 # ## outgoing changesets between those revisions
196 # ## outgoing changesets between those revisions
197 #
197 #
198 # response.mustcontain("""<a href="/%s/changeset/2dda4e345facb0ccff1a191052dd1606dba6781d">r4:2dda4e345fac</a>""" % (HG_REPO))
198 # response.mustcontain("""<a href="/%s/changeset/2dda4e345facb0ccff1a191052dd1606dba6781d">r4:2dda4e345fac</a>""" % (HG_REPO))
199 # response.mustcontain("""<a href="/%s/changeset/6fff84722075f1607a30f436523403845f84cd9e">r5:6fff84722075</a>""" % (HG_REPO))
199 # response.mustcontain("""<a href="/%s/changeset/6fff84722075f1607a30f436523403845f84cd9e">r5:6fff84722075</a>""" % (HG_REPO))
200 # response.mustcontain("""<a href="/%s/changeset/7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7">r6:%s</a>""" % (HG_REPO, rev2))
200 # response.mustcontain("""<a href="/%s/changeset/7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7">r6:%s</a>""" % (HG_REPO, rev2))
201 #
201 #
202 # ## files
202 # ## files
203 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--9c390eb52cd6">vcs/backends/hg.py</a>""" % (HG_REPO, rev1, rev2))
203 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--9c390eb52cd6">vcs/backends/hg.py</a>""" % (HG_REPO, rev1, rev2))
204 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--41b41c1f2796">vcs/backends/__init__.py</a>""" % (HG_REPO, rev1, rev2))
204 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--41b41c1f2796">vcs/backends/__init__.py</a>""" % (HG_REPO, rev1, rev2))
205 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--2f574d260608">vcs/backends/base.py</a>""" % (HG_REPO, rev1, rev2))
205 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--2f574d260608">vcs/backends/base.py</a>""" % (HG_REPO, rev1, rev2))
206 # finally:
206 # finally:
207 # RepoModel().delete(HG_FORK)
207 # RepoModel().delete(HG_FORK)
208
208
209
209
210
210
211 #
211 #
212 # def test_compare_remote_branches_hg(self):
212 # def test_compare_remote_branches_hg(self):
213 # self.log_user()
213 # self.log_user()
214 #
214 #
215 # _fork_repo(HG_FORK, 'hg')
215 # _fork_repo(HG_FORK, 'hg')
216 #
216 #
217 # rev1 = '56349e29c2af'
217 # rev1 = '56349e29c2af'
218 # rev2 = '7d4bc8ec6be5'
218 # rev2 = '7d4bc8ec6be5'
219 #
219 #
220 # response = self.app.get(url(controller='compare', action='index',
220 # response = self.app.get(url(controller='compare', action='index',
221 # repo_name=HG_REPO,
221 # repo_name=HG_REPO,
222 # org_ref_type="rev",
222 # org_ref_type="rev",
223 # org_ref=rev1,
223 # org_ref=rev1,
224 # other_ref_type="rev",
224 # other_ref_type="rev",
225 # other_ref=rev2,
225 # other_ref=rev2,
226 # repo=HG_FORK,
226 # repo=HG_FORK,
227 # ))
227 # ))
228 #
228 #
229 # try:
229 # try:
230 # response.mustcontain('%s@%s -&gt; %s@%s' % (HG_REPO, rev1, HG_FORK, rev2))
230 # response.mustcontain('%s@%s -&gt; %s@%s' % (HG_REPO, rev1, HG_FORK, rev2))
231 # ## outgoing changesets between those revisions
231 # ## outgoing changesets between those revisions
232 #
232 #
233 # response.mustcontain("""<a href="/%s/changeset/2dda4e345facb0ccff1a191052dd1606dba6781d">r4:2dda4e345fac</a>""" % (HG_REPO))
233 # response.mustcontain("""<a href="/%s/changeset/2dda4e345facb0ccff1a191052dd1606dba6781d">r4:2dda4e345fac</a>""" % (HG_REPO))
234 # response.mustcontain("""<a href="/%s/changeset/6fff84722075f1607a30f436523403845f84cd9e">r5:6fff84722075</a>""" % (HG_REPO))
234 # response.mustcontain("""<a href="/%s/changeset/6fff84722075f1607a30f436523403845f84cd9e">r5:6fff84722075</a>""" % (HG_REPO))
235 # response.mustcontain("""<a href="/%s/changeset/7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7">r6:%s</a>""" % (HG_REPO, rev2))
235 # response.mustcontain("""<a href="/%s/changeset/7d4bc8ec6be56c0f10425afb40b6fc315a4c25e7">r6:%s</a>""" % (HG_REPO, rev2))
236 #
236 #
237 # ## files
237 # ## files
238 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--9c390eb52cd6">vcs/backends/hg.py</a>""" % (HG_REPO, rev1, rev2))
238 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--9c390eb52cd6">vcs/backends/hg.py</a>""" % (HG_REPO, rev1, rev2))
239 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--41b41c1f2796">vcs/backends/__init__.py</a>""" % (HG_REPO, rev1, rev2))
239 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--41b41c1f2796">vcs/backends/__init__.py</a>""" % (HG_REPO, rev1, rev2))
240 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--2f574d260608">vcs/backends/base.py</a>""" % (HG_REPO, rev1, rev2))
240 # response.mustcontain("""<a href="/%s/compare/rev@%s...rev@%s#C--2f574d260608">vcs/backends/base.py</a>""" % (HG_REPO, rev1, rev2))
241 # finally:
241 # finally:
242 # RepoModel().delete(HG_FORK)
242 # RepoModel().delete(HG_FORK)
243 #
243 #
244 # def test_org_repo_new_commits_after_forking_simple_diff(self):
244 # def test_org_repo_new_commits_after_forking_simple_diff(self):
245 # self.log_user()
245 # self.log_user()
246 #
246 #
247 # repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
247 # repo1 = RepoModel().create_repo(repo_name='one', repo_type='hg',
248 # description='diff-test',
248 # description='diff-test',
249 # owner=TEST_USER_ADMIN_LOGIN)
249 # owner=TEST_USER_ADMIN_LOGIN)
250 #
250 #
251 # Session().commit()
251 # Session().commit()
252 # r1_id = repo1.repo_id
252 # r1_id = repo1.repo_id
253 # r1_name = repo1.repo_name
253 # r1_name = repo1.repo_name
254 #
254 #
255 # #commit something initially !
255 # #commit something initially !
256 # cs0 = ScmModel().create_node(
256 # cs0 = ScmModel().create_node(
257 # repo=repo1.scm_instance, repo_name=r1_name,
257 # repo=repo1.scm_instance, repo_name=r1_name,
258 # cs=EmptyChangeset(alias='hg'), user=TEST_USER_ADMIN_LOGIN,
258 # cs=EmptyChangeset(alias='hg'), user=TEST_USER_ADMIN_LOGIN,
259 # author=TEST_USER_ADMIN_LOGIN,
259 # author=TEST_USER_ADMIN_LOGIN,
260 # message='commit1',
260 # message='commit1',
261 # content='line1',
261 # content='line1',
262 # f_path='file1'
262 # f_path='file1'
263 # )
263 # )
264 # Session().commit()
264 # Session().commit()
265 # self.assertEqual(repo1.scm_instance.revisions, [cs0.raw_id])
265 # self.assertEqual(repo1.scm_instance.revisions, [cs0.raw_id])
266 # #fork the repo1
266 # #fork the repo1
267 # repo2 = RepoModel().create_repo(repo_name='one-fork', repo_type='hg',
267 # repo2 = RepoModel().create_repo(repo_name='one-fork', repo_type='hg',
268 # description='compare-test',
268 # description='compare-test',
269 # clone_uri=repo1.repo_full_path,
269 # clone_uri=repo1.repo_full_path,
270 # owner=TEST_USER_ADMIN_LOGIN, fork_of='one')
270 # owner=TEST_USER_ADMIN_LOGIN, fork_of='one')
271 # Session().commit()
271 # Session().commit()
272 # self.assertEqual(repo2.scm_instance.revisions, [cs0.raw_id])
272 # self.assertEqual(repo2.scm_instance.revisions, [cs0.raw_id])
273 # r2_id = repo2.repo_id
273 # r2_id = repo2.repo_id
274 # r2_name = repo2.repo_name
274 # r2_name = repo2.repo_name
275 #
275 #
276 # #make 3 new commits in fork
276 # #make 3 new commits in fork
277 # cs1 = ScmModel().create_node(
277 # cs1 = ScmModel().create_node(
278 # repo=repo2.scm_instance, repo_name=r2_name,
278 # repo=repo2.scm_instance, repo_name=r2_name,
279 # cs=repo2.scm_instance[-1], user=TEST_USER_ADMIN_LOGIN,
279 # cs=repo2.scm_instance[-1], user=TEST_USER_ADMIN_LOGIN,
280 # author=TEST_USER_ADMIN_LOGIN,
280 # author=TEST_USER_ADMIN_LOGIN,
281 # message='commit1-fork',
281 # message='commit1-fork',
282 # content='file1-line1-from-fork',
282 # content='file1-line1-from-fork',
283 # f_path='file1-fork'
283 # f_path='file1-fork'
284 # )
284 # )
285 # cs2 = ScmModel().create_node(
285 # cs2 = ScmModel().create_node(
286 # repo=repo2.scm_instance, repo_name=r2_name,
286 # repo=repo2.scm_instance, repo_name=r2_name,
287 # cs=cs1, user=TEST_USER_ADMIN_LOGIN,
287 # cs=cs1, user=TEST_USER_ADMIN_LOGIN,
288 # author=TEST_USER_ADMIN_LOGIN,
288 # author=TEST_USER_ADMIN_LOGIN,
289 # message='commit2-fork',
289 # message='commit2-fork',
290 # content='file2-line1-from-fork',
290 # content='file2-line1-from-fork',
291 # f_path='file2-fork'
291 # f_path='file2-fork'
292 # )
292 # )
293 # cs3 = ScmModel().create_node(
293 # cs3 = ScmModel().create_node(
294 # repo=repo2.scm_instance, repo_name=r2_name,
294 # repo=repo2.scm_instance, repo_name=r2_name,
295 # cs=cs2, user=TEST_USER_ADMIN_LOGIN,
295 # cs=cs2, user=TEST_USER_ADMIN_LOGIN,
296 # author=TEST_USER_ADMIN_LOGIN,
296 # author=TEST_USER_ADMIN_LOGIN,
297 # message='commit3-fork',
297 # message='commit3-fork',
298 # content='file3-line1-from-fork',
298 # content='file3-line1-from-fork',
299 # f_path='file3-fork'
299 # f_path='file3-fork'
300 # )
300 # )
301 #
301 #
302 # #compare !
302 # #compare !
303 # rev1 = 'default'
303 # rev1 = 'default'
304 # rev2 = 'default'
304 # rev2 = 'default'
305 # response = self.app.get(url(controller='compare', action='index',
305 # response = self.app.get(url(controller='compare', action='index',
306 # repo_name=r2_name,
306 # repo_name=r2_name,
307 # org_ref_type="branch",
307 # org_ref_type="branch",
308 # org_ref=rev1,
308 # org_ref=rev1,
309 # other_ref_type="branch",
309 # other_ref_type="branch",
310 # other_ref=rev2,
310 # other_ref=rev2,
311 # repo=r1_name,
311 # repo=r1_name,
312 # bundle=False,
312 # bundle=False,
313 # ))
313 # ))
314 #
314 #
315 # try:
315 # try:
316 # #response.mustcontain('%s@%s -&gt; %s@%s' % (r2_name, rev1, r1_name, rev2))
316 # #response.mustcontain('%s@%s -&gt; %s@%s' % (r2_name, rev1, r1_name, rev2))
317 #
317 #
318 # #add new commit into parent !
318 # #add new commit into parent !
319 # cs0 = ScmModel().create_node(
319 # cs0 = ScmModel().create_node(
320 # repo=repo1.scm_instance, repo_name=r1_name,
320 # repo=repo1.scm_instance, repo_name=r1_name,
321 # cs=EmptyChangeset(alias='hg'), user=TEST_USER_ADMIN_LOGIN,
321 # cs=EmptyChangeset(alias='hg'), user=TEST_USER_ADMIN_LOGIN,
322 # author=TEST_USER_ADMIN_LOGIN,
322 # author=TEST_USER_ADMIN_LOGIN,
323 # message='commit2',
323 # message='commit2',
324 # content='line1',
324 # content='line1',
325 # f_path='file2'
325 # f_path='file2'
326 # )
326 # )
327 # #compare !
327 # #compare !
328 # rev1 = 'default'
328 # rev1 = 'default'
329 # rev2 = 'default'
329 # rev2 = 'default'
330 # response = self.app.get(url(controller='compare', action='index',
330 # response = self.app.get(url(controller='compare', action='index',
331 # repo_name=r2_name,
331 # repo_name=r2_name,
332 # org_ref_type="branch",
332 # org_ref_type="branch",
333 # org_ref=rev1,
333 # org_ref=rev1,
334 # other_ref_type="branch",
334 # other_ref_type="branch",
335 # other_ref=rev2,
335 # other_ref=rev2,
336 # repo=r1_name,
336 # repo=r1_name,
337 # bundle=False
337 # bundle=False
338 # ))
338 # ))
339 #
339 #
340 # response.mustcontain('%s@%s -&gt; %s@%s' % (r2_name, rev1, r1_name, rev2))
340 # response.mustcontain('%s@%s -&gt; %s@%s' % (r2_name, rev1, r1_name, rev2))
341 # response.mustcontain("""file1-line1-from-fork""")
341 # response.mustcontain("""file1-line1-from-fork""")
342 # response.mustcontain("""file2-line1-from-fork""")
342 # response.mustcontain("""file2-line1-from-fork""")
343 # response.mustcontain("""file3-line1-from-fork""")
343 # response.mustcontain("""file3-line1-from-fork""")
344 # self.assertFalse("""<a href="#">file2</a>""" in response.body) # new commit from parent
344 # self.assertFalse("""<a href="#">file2</a>""" in response.body) # new commit from parent
345 # self.assertFalse("""line1-from-new-parent""" in response.body)
345 # self.assertFalse("""line1-from-new-parent""" in response.body)
346 # finally:
346 # finally:
347 # RepoModel().delete(r2_id)
347 # RepoModel().delete(r2_id)
348 # RepoModel().delete(r1_id)
348 # RepoModel().delete(r1_id)
General Comments 0
You need to be logged in to leave comments. Login now