Show More
@@ -158,7 +158,7 b' class RcConf(object):' | |||||
158 | """ |
|
158 | """ | |
159 | try: |
|
159 | try: | |
160 | with open(self._conf_name, 'rb') as conf: |
|
160 | with open(self._conf_name, 'rb') as conf: | |
161 |
return |
|
161 | return json.load(conf) | |
162 | except IOError as e: |
|
162 | except IOError as e: | |
163 | #sys.stderr.write(str(e) + '\n') |
|
163 | #sys.stderr.write(str(e) + '\n') | |
164 | pass |
|
164 | pass |
@@ -121,5 +121,6 b' def main(argv=None):' | |||||
121 | ) |
|
121 | ) | |
122 | return 0 |
|
122 | return 0 | |
123 |
|
123 | |||
|
124 | ||||
124 | if __name__ == '__main__': |
|
125 | if __name__ == '__main__': | |
125 | sys.exit(main(sys.argv)) |
|
126 | sys.exit(main(sys.argv)) |
@@ -92,6 +92,7 b' class BackupManager(object):' | |||||
92 | logging.info('Removing file %s', self.backup_file_name) |
|
92 | logging.info('Removing file %s', self.backup_file_name) | |
93 | os.remove(os.path.join(self.backup_file_path, self.backup_file_name)) |
|
93 | os.remove(os.path.join(self.backup_file_path, self.backup_file_name)) | |
94 |
|
94 | |||
|
95 | ||||
95 | if __name__ == "__main__": |
|
96 | if __name__ == "__main__": | |
96 |
|
97 | |||
97 | repo_location = '/home/repo_path' |
|
98 | repo_location = '/home/repo_path' |
@@ -95,6 +95,7 b' class KallitheaAppConfig(AppConfig):' | |||||
95 | # Disable transaction manager -- currently Kallithea takes care of transactions itself |
|
95 | # Disable transaction manager -- currently Kallithea takes care of transactions itself | |
96 | self['tm.enabled'] = False |
|
96 | self['tm.enabled'] = False | |
97 |
|
97 | |||
|
98 | ||||
98 | base_config = KallitheaAppConfig() |
|
99 | base_config = KallitheaAppConfig() | |
99 |
|
100 | |||
100 | # TODO still needed as long as we use pylonslib |
|
101 | # TODO still needed as long as we use pylonslib | |
@@ -174,6 +175,7 b' def setup_configuration(app):' | |||||
174 | repo2db_mapper(ScmModel().repo_scan(repos_path), |
|
175 | repo2db_mapper(ScmModel().repo_scan(repos_path), | |
175 | remove_obsolete=False, install_git_hooks=False) |
|
176 | remove_obsolete=False, install_git_hooks=False) | |
176 |
|
177 | |||
|
178 | ||||
177 | hooks.register('configure_new_app', setup_configuration) |
|
179 | hooks.register('configure_new_app', setup_configuration) | |
178 |
|
180 | |||
179 |
|
181 | |||
@@ -190,4 +192,5 b' def setup_application(app):' | |||||
190 | app = HttpsFixup(app, config) |
|
192 | app = HttpsFixup(app, config) | |
191 | return app |
|
193 | return app | |
192 |
|
194 | |||
|
195 | ||||
193 | hooks.register('before_config', setup_application) |
|
196 | hooks.register('before_config', setup_application) |
@@ -23,10 +23,12 b' from kallithea.config.environment import' | |||||
23 | # make_base_app will wrap the TurboGears2 app with all the middleware it needs. |
|
23 | # make_base_app will wrap the TurboGears2 app with all the middleware it needs. | |
24 | make_base_app = base_config.setup_tg_wsgi_app(load_environment) |
|
24 | make_base_app = base_config.setup_tg_wsgi_app(load_environment) | |
25 |
|
25 | |||
|
26 | ||||
26 | def make_app_without_logging(global_conf, full_stack=True, **app_conf): |
|
27 | def make_app_without_logging(global_conf, full_stack=True, **app_conf): | |
27 | """The core of make_app for use from gearbox commands (other than 'serve')""" |
|
28 | """The core of make_app for use from gearbox commands (other than 'serve')""" | |
28 | return make_base_app(global_conf, full_stack=full_stack, **app_conf) |
|
29 | return make_base_app(global_conf, full_stack=full_stack, **app_conf) | |
29 |
|
30 | |||
|
31 | ||||
30 | def make_app(global_conf, full_stack=True, **app_conf): |
|
32 | def make_app(global_conf, full_stack=True, **app_conf): | |
31 | """ |
|
33 | """ | |
32 | Set up Kallithea with the settings found in the PasteDeploy configuration |
|
34 | Set up Kallithea with the settings found in the PasteDeploy configuration |
@@ -25,5 +25,6 b' def main():' | |||||
25 | _handler(repo_path, push_data, os.environ) |
|
25 | _handler(repo_path, push_data, os.environ) | |
26 | sys.exit(0) |
|
26 | sys.exit(0) | |
27 |
|
27 | |||
|
28 | ||||
28 | if __name__ == '__main__': |
|
29 | if __name__ == '__main__': | |
29 | main() |
|
30 | main() |
@@ -25,5 +25,6 b' def main():' | |||||
25 | _handler(repo_path, push_data, os.environ) |
|
25 | _handler(repo_path, push_data, os.environ) | |
26 | sys.exit(0) |
|
26 | sys.exit(0) | |
27 |
|
27 | |||
|
28 | ||||
28 | if __name__ == '__main__': |
|
29 | if __name__ == '__main__': | |
29 | main() |
|
30 | main() |
@@ -49,6 +49,8 b' def _crrepohook(*args, **kwargs):' | |||||
49 | :param created_by: |
|
49 | :param created_by: | |
50 | """ |
|
50 | """ | |
51 | return 0 |
|
51 | return 0 | |
|
52 | ||||
|
53 | ||||
52 | CREATE_REPO_HOOK = _crrepohook |
|
54 | CREATE_REPO_HOOK = _crrepohook | |
53 |
|
55 | |||
54 |
|
56 | |||
@@ -73,6 +75,8 b' def _pre_cruserhook(*args, **kwargs):' | |||||
73 | """ |
|
75 | """ | |
74 | reason = 'allowed' |
|
76 | reason = 'allowed' | |
75 | return True, reason |
|
77 | return True, reason | |
|
78 | ||||
|
79 | ||||
76 | PRE_CREATE_USER_HOOK = _pre_cruserhook |
|
80 | PRE_CREATE_USER_HOOK = _pre_cruserhook | |
77 |
|
81 | |||
78 | #============================================================================== |
|
82 | #============================================================================== | |
@@ -105,6 +109,8 b' def _cruserhook(*args, **kwargs):' | |||||
105 | :param created_by: |
|
109 | :param created_by: | |
106 | """ |
|
110 | """ | |
107 | return 0 |
|
111 | return 0 | |
|
112 | ||||
|
113 | ||||
108 | CREATE_USER_HOOK = _cruserhook |
|
114 | CREATE_USER_HOOK = _cruserhook | |
109 |
|
115 | |||
110 |
|
116 | |||
@@ -132,6 +138,8 b' def _dlrepohook(*args, **kwargs):' | |||||
132 | :param deleted_on: |
|
138 | :param deleted_on: | |
133 | """ |
|
139 | """ | |
134 | return 0 |
|
140 | return 0 | |
|
141 | ||||
|
142 | ||||
135 | DELETE_REPO_HOOK = _dlrepohook |
|
143 | DELETE_REPO_HOOK = _dlrepohook | |
136 |
|
144 | |||
137 |
|
145 | |||
@@ -165,6 +173,8 b' def _dluserhook(*args, **kwargs):' | |||||
165 | :param deleted_by: |
|
173 | :param deleted_by: | |
166 | """ |
|
174 | """ | |
167 | return 0 |
|
175 | return 0 | |
|
176 | ||||
|
177 | ||||
168 | DELETE_USER_HOOK = _dluserhook |
|
178 | DELETE_USER_HOOK = _dluserhook | |
169 |
|
179 | |||
170 |
|
180 | |||
@@ -189,6 +199,8 b' def _pushhook(*args, **kwargs):' | |||||
189 | :param pushed_revs: list of pushed revisions |
|
199 | :param pushed_revs: list of pushed revisions | |
190 | """ |
|
200 | """ | |
191 | return 0 |
|
201 | return 0 | |
|
202 | ||||
|
203 | ||||
192 | PUSH_HOOK = _pushhook |
|
204 | PUSH_HOOK = _pushhook | |
193 |
|
205 | |||
194 |
|
206 | |||
@@ -212,4 +224,6 b' def _pullhook(*args, **kwargs):' | |||||
212 | :param repository: repository name |
|
224 | :param repository: repository name | |
213 | """ |
|
225 | """ | |
214 | return 0 |
|
226 | return 0 | |
|
227 | ||||
|
228 | ||||
215 | PULL_HOOK = _pullhook |
|
229 | PULL_HOOK = _pullhook |
@@ -94,7 +94,7 b' def make_map(config):' | |||||
94 | # CUSTOM ROUTES HERE |
|
94 | # CUSTOM ROUTES HERE | |
95 | #========================================================================== |
|
95 | #========================================================================== | |
96 |
|
96 | |||
97 | #MAIN PAGE |
|
97 | # MAIN PAGE | |
98 | rmap.connect('home', '/', controller='home', action='index') |
|
98 | rmap.connect('home', '/', controller='home', action='index') | |
99 | rmap.connect('about', '/about', controller='home', action='about') |
|
99 | rmap.connect('about', '/about', controller='home', action='about') | |
100 | rmap.connect('repo_switcher_data', '/_repos', controller='home', |
|
100 | rmap.connect('repo_switcher_data', '/_repos', controller='home', | |
@@ -106,7 +106,7 b' def make_map(config):' | |||||
106 | rmap.connect('kallithea_project_url', "https://kallithea-scm.org/", _static=True) |
|
106 | rmap.connect('kallithea_project_url', "https://kallithea-scm.org/", _static=True) | |
107 | rmap.connect('issues_url', 'https://bitbucket.org/conservancy/kallithea/issues', _static=True) |
|
107 | rmap.connect('issues_url', 'https://bitbucket.org/conservancy/kallithea/issues', _static=True) | |
108 |
|
108 | |||
109 | #ADMIN REPOSITORY ROUTES |
|
109 | # ADMIN REPOSITORY ROUTES | |
110 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
110 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
111 | controller='admin/repos') as m: |
|
111 | controller='admin/repos') as m: | |
112 | m.connect("repos", "/repos", |
|
112 | m.connect("repos", "/repos", | |
@@ -121,7 +121,7 b' def make_map(config):' | |||||
121 | m.connect("delete_repo", "/repos/{repo_name:.*?}/delete", |
|
121 | m.connect("delete_repo", "/repos/{repo_name:.*?}/delete", | |
122 | action="delete", conditions=dict(method=["POST"])) |
|
122 | action="delete", conditions=dict(method=["POST"])) | |
123 |
|
123 | |||
124 | #ADMIN REPOSITORY GROUPS ROUTES |
|
124 | # ADMIN REPOSITORY GROUPS ROUTES | |
125 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
125 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
126 | controller='admin/repo_groups') as m: |
|
126 | controller='admin/repo_groups') as m: | |
127 | m.connect("repos_groups", "/repo_groups", |
|
127 | m.connect("repos_groups", "/repo_groups", | |
@@ -138,7 +138,7 b' def make_map(config):' | |||||
138 | action="show", conditions=dict(method=["GET"], |
|
138 | action="show", conditions=dict(method=["GET"], | |
139 | function=check_group)) |
|
139 | function=check_group)) | |
140 |
|
140 | |||
141 | #EXTRAS REPO GROUP ROUTES |
|
141 | # EXTRAS REPO GROUP ROUTES | |
142 | m.connect("edit_repo_group", "/repo_groups/{group_name:.*?}/edit", |
|
142 | m.connect("edit_repo_group", "/repo_groups/{group_name:.*?}/edit", | |
143 | action="edit", |
|
143 | action="edit", | |
144 | conditions=dict(method=["GET"], function=check_group)) |
|
144 | conditions=dict(method=["GET"], function=check_group)) | |
@@ -161,8 +161,7 b' def make_map(config):' | |||||
161 | action="delete", conditions=dict(method=["POST"], |
|
161 | action="delete", conditions=dict(method=["POST"], | |
162 | function=check_group_skip_path)) |
|
162 | function=check_group_skip_path)) | |
163 |
|
163 | |||
164 |
|
164 | # ADMIN USER ROUTES | ||
165 | #ADMIN USER ROUTES |
|
|||
166 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
165 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
167 | controller='admin/users') as m: |
|
166 | controller='admin/users') as m: | |
168 | m.connect("new_user", "/users/new", |
|
167 | m.connect("new_user", "/users/new", | |
@@ -180,7 +179,7 b' def make_map(config):' | |||||
180 | m.connect("edit_user", "/users/{id}/edit", |
|
179 | m.connect("edit_user", "/users/{id}/edit", | |
181 | action="edit", conditions=dict(method=["GET"])) |
|
180 | action="edit", conditions=dict(method=["GET"])) | |
182 |
|
181 | |||
183 | #EXTRAS USER ROUTES |
|
182 | # EXTRAS USER ROUTES | |
184 | m.connect("edit_user_advanced", "/users/{id}/edit/advanced", |
|
183 | m.connect("edit_user_advanced", "/users/{id}/edit/advanced", | |
185 | action="edit_advanced", conditions=dict(method=["GET"])) |
|
184 | action="edit_advanced", conditions=dict(method=["GET"])) | |
186 |
|
185 | |||
@@ -210,7 +209,7 b' def make_map(config):' | |||||
210 | m.connect("edit_user_ips_delete", "/users/{id}/edit/ips/delete", |
|
209 | m.connect("edit_user_ips_delete", "/users/{id}/edit/ips/delete", | |
211 | action="delete_ip", conditions=dict(method=["POST"])) |
|
210 | action="delete_ip", conditions=dict(method=["POST"])) | |
212 |
|
211 | |||
213 | #ADMIN USER GROUPS REST ROUTES |
|
212 | # ADMIN USER GROUPS REST ROUTES | |
214 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
213 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
215 | controller='admin/user_groups') as m: |
|
214 | controller='admin/user_groups') as m: | |
216 | m.connect("users_groups", "/user_groups", |
|
215 | m.connect("users_groups", "/user_groups", | |
@@ -227,13 +226,12 b' def make_map(config):' | |||||
227 | action="edit", conditions=dict(method=["GET"]), |
|
226 | action="edit", conditions=dict(method=["GET"]), | |
228 | function=check_user_group) |
|
227 | function=check_user_group) | |
229 |
|
228 | |||
230 | #EXTRAS USER GROUP ROUTES |
|
229 | # EXTRAS USER GROUP ROUTES | |
231 | m.connect("edit_user_group_default_perms", "/user_groups/{id}/edit/default_perms", |
|
230 | m.connect("edit_user_group_default_perms", "/user_groups/{id}/edit/default_perms", | |
232 | action="edit_default_perms", conditions=dict(method=["GET"])) |
|
231 | action="edit_default_perms", conditions=dict(method=["GET"])) | |
233 | m.connect("edit_user_group_default_perms_update", "/user_groups/{id}/edit/default_perms", |
|
232 | m.connect("edit_user_group_default_perms_update", "/user_groups/{id}/edit/default_perms", | |
234 | action="update_default_perms", conditions=dict(method=["POST"])) |
|
233 | action="update_default_perms", conditions=dict(method=["POST"])) | |
235 |
|
234 | |||
236 |
|
||||
237 | m.connect("edit_user_group_perms", "/user_groups/{id}/edit/perms", |
|
235 | m.connect("edit_user_group_perms", "/user_groups/{id}/edit/perms", | |
238 | action="edit_perms", conditions=dict(method=["GET"])) |
|
236 | action="edit_perms", conditions=dict(method=["GET"])) | |
239 | m.connect("edit_user_group_perms_update", "/user_groups/{id}/edit/perms", |
|
237 | m.connect("edit_user_group_perms_update", "/user_groups/{id}/edit/perms", | |
@@ -247,9 +245,7 b' def make_map(config):' | |||||
247 | m.connect("edit_user_group_members", "/user_groups/{id}/edit/members", |
|
245 | m.connect("edit_user_group_members", "/user_groups/{id}/edit/members", | |
248 | action="edit_members", conditions=dict(method=["GET"])) |
|
246 | action="edit_members", conditions=dict(method=["GET"])) | |
249 |
|
247 | |||
250 |
|
248 | # ADMIN PERMISSIONS ROUTES | ||
251 |
|
||||
252 | #ADMIN PERMISSIONS ROUTES |
|
|||
253 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
249 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
254 | controller='admin/permissions') as m: |
|
250 | controller='admin/permissions') as m: | |
255 | m.connect("admin_permissions", "/permissions", |
|
251 | m.connect("admin_permissions", "/permissions", | |
@@ -263,8 +259,7 b' def make_map(config):' | |||||
263 | m.connect("admin_permissions_perms", "/permissions/perms", |
|
259 | m.connect("admin_permissions_perms", "/permissions/perms", | |
264 | action="permission_perms", conditions=dict(method=["GET"])) |
|
260 | action="permission_perms", conditions=dict(method=["GET"])) | |
265 |
|
261 | |||
266 |
|
262 | # ADMIN DEFAULTS ROUTES | ||
267 | #ADMIN DEFAULTS ROUTES |
|
|||
268 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
263 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
269 | controller='admin/defaults') as m: |
|
264 | controller='admin/defaults') as m: | |
270 | m.connect('defaults', 'defaults', |
|
265 | m.connect('defaults', 'defaults', | |
@@ -272,14 +267,14 b' def make_map(config):' | |||||
272 | m.connect('defaults_update', 'defaults/{id}/update', |
|
267 | m.connect('defaults_update', 'defaults/{id}/update', | |
273 | action="update", conditions=dict(method=["POST"])) |
|
268 | action="update", conditions=dict(method=["POST"])) | |
274 |
|
269 | |||
275 | #ADMIN AUTH SETTINGS |
|
270 | # ADMIN AUTH SETTINGS | |
276 | rmap.connect('auth_settings', '%s/auth' % ADMIN_PREFIX, |
|
271 | rmap.connect('auth_settings', '%s/auth' % ADMIN_PREFIX, | |
277 | controller='admin/auth_settings', action='auth_settings', |
|
272 | controller='admin/auth_settings', action='auth_settings', | |
278 | conditions=dict(method=["POST"])) |
|
273 | conditions=dict(method=["POST"])) | |
279 | rmap.connect('auth_home', '%s/auth' % ADMIN_PREFIX, |
|
274 | rmap.connect('auth_home', '%s/auth' % ADMIN_PREFIX, | |
280 | controller='admin/auth_settings') |
|
275 | controller='admin/auth_settings') | |
281 |
|
276 | |||
282 | #ADMIN SETTINGS ROUTES |
|
277 | # ADMIN SETTINGS ROUTES | |
283 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
278 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
284 | controller='admin/settings') as m: |
|
279 | controller='admin/settings') as m: | |
285 | m.connect("admin_settings", "/settings", |
|
280 | m.connect("admin_settings", "/settings", | |
@@ -326,7 +321,7 b' def make_map(config):' | |||||
326 | m.connect("admin_settings_system_update", "/settings/system/updates", |
|
321 | m.connect("admin_settings_system_update", "/settings/system/updates", | |
327 | action="settings_system_update", conditions=dict(method=["GET"])) |
|
322 | action="settings_system_update", conditions=dict(method=["GET"])) | |
328 |
|
323 | |||
329 | #ADMIN MY ACCOUNT |
|
324 | # ADMIN MY ACCOUNT | |
330 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
325 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
331 | controller='admin/my_account') as m: |
|
326 | controller='admin/my_account') as m: | |
332 |
|
327 | |||
@@ -363,7 +358,7 b' def make_map(config):' | |||||
363 | m.connect("my_account_api_keys_delete", "/my_account/api_keys/delete", |
|
358 | m.connect("my_account_api_keys_delete", "/my_account/api_keys/delete", | |
364 | action="my_account_api_keys_delete", conditions=dict(method=["POST"])) |
|
359 | action="my_account_api_keys_delete", conditions=dict(method=["POST"])) | |
365 |
|
360 | |||
366 | #NOTIFICATION REST ROUTES |
|
361 | # NOTIFICATION REST ROUTES | |
367 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
362 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
368 | controller='admin/notifications') as m: |
|
363 | controller='admin/notifications') as m: | |
369 | m.connect("notifications", "/notifications", |
|
364 | m.connect("notifications", "/notifications", | |
@@ -381,7 +376,7 b' def make_map(config):' | |||||
381 | m.connect("formatted_notification", "/notifications/{notification_id}.{format}", |
|
376 | m.connect("formatted_notification", "/notifications/{notification_id}.{format}", | |
382 | action="show", conditions=dict(method=["GET"])) |
|
377 | action="show", conditions=dict(method=["GET"])) | |
383 |
|
378 | |||
384 | #ADMIN GIST |
|
379 | # ADMIN GIST | |
385 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
380 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
386 | controller='admin/gists') as m: |
|
381 | controller='admin/gists') as m: | |
387 | m.connect("gists", "/gists", |
|
382 | m.connect("gists", "/gists", | |
@@ -391,7 +386,6 b' def make_map(config):' | |||||
391 | m.connect("new_gist", "/gists/new", |
|
386 | m.connect("new_gist", "/gists/new", | |
392 | action="new", conditions=dict(method=["GET"])) |
|
387 | action="new", conditions=dict(method=["GET"])) | |
393 |
|
388 | |||
394 |
|
||||
395 | m.connect("gist_delete", "/gists/{gist_id}/delete", |
|
389 | m.connect("gist_delete", "/gists/{gist_id}/delete", | |
396 | action="delete", conditions=dict(method=["POST"])) |
|
390 | action="delete", conditions=dict(method=["POST"])) | |
397 | m.connect("edit_gist", "/gists/{gist_id}/edit", |
|
391 | m.connect("edit_gist", "/gists/{gist_id}/edit", | |
@@ -399,7 +393,6 b' def make_map(config):' | |||||
399 | m.connect("edit_gist_check_revision", "/gists/{gist_id}/edit/check_revision", |
|
393 | m.connect("edit_gist_check_revision", "/gists/{gist_id}/edit/check_revision", | |
400 | action="check_revision", conditions=dict(method=["POST"])) |
|
394 | action="check_revision", conditions=dict(method=["POST"])) | |
401 |
|
395 | |||
402 |
|
||||
403 | m.connect("gist", "/gists/{gist_id}", |
|
396 | m.connect("gist", "/gists/{gist_id}", | |
404 | action="show", conditions=dict(method=["GET"])) |
|
397 | action="show", conditions=dict(method=["GET"])) | |
405 | m.connect("gist_rev", "/gists/{gist_id}/{revision}", |
|
398 | m.connect("gist_rev", "/gists/{gist_id}/{revision}", | |
@@ -412,7 +405,7 b' def make_map(config):' | |||||
412 | revision='tip', |
|
405 | revision='tip', | |
413 | action="show", conditions=dict(method=["GET"])) |
|
406 | action="show", conditions=dict(method=["GET"])) | |
414 |
|
407 | |||
415 | #ADMIN MAIN PAGES |
|
408 | # ADMIN MAIN PAGES | |
416 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
409 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
417 | controller='admin/admin') as m: |
|
410 | controller='admin/admin') as m: | |
418 | m.connect('admin_home', '', action='index') |
|
411 | m.connect('admin_home', '', action='index') | |
@@ -425,7 +418,7 b' def make_map(config):' | |||||
425 | action='_dispatch') as m: |
|
418 | action='_dispatch') as m: | |
426 | m.connect('api', '/api') |
|
419 | m.connect('api', '/api') | |
427 |
|
420 | |||
428 | #USER JOURNAL |
|
421 | # USER JOURNAL | |
429 | rmap.connect('journal', '%s/journal' % ADMIN_PREFIX, |
|
422 | rmap.connect('journal', '%s/journal' % ADMIN_PREFIX, | |
430 | controller='journal', action='index') |
|
423 | controller='journal', action='index') | |
431 | rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX, |
|
424 | rmap.connect('journal_rss', '%s/journal/rss' % ADMIN_PREFIX, | |
@@ -454,7 +447,7 b' def make_map(config):' | |||||
454 | controller='journal', action='toggle_following', |
|
447 | controller='journal', action='toggle_following', | |
455 | conditions=dict(method=["POST"])) |
|
448 | conditions=dict(method=["POST"])) | |
456 |
|
449 | |||
457 | #SEARCH |
|
450 | # SEARCH | |
458 | rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',) |
|
451 | rmap.connect('search', '%s/search' % ADMIN_PREFIX, controller='search',) | |
459 | rmap.connect('search_repo_admin', '%s/search/{repo_name:.*}' % ADMIN_PREFIX, |
|
452 | rmap.connect('search_repo_admin', '%s/search/{repo_name:.*}' % ADMIN_PREFIX, | |
460 | controller='search', |
|
453 | controller='search', | |
@@ -464,7 +457,7 b' def make_map(config):' | |||||
464 | conditions=dict(function=check_repo), |
|
457 | conditions=dict(function=check_repo), | |
465 | ) |
|
458 | ) | |
466 |
|
459 | |||
467 | #LOGIN/LOGOUT/REGISTER/SIGN IN |
|
460 | # LOGIN/LOGOUT/REGISTER/SIGN IN | |
468 | rmap.connect('authentication_token', '%s/authentication_token' % ADMIN_PREFIX, controller='login', action='authentication_token') |
|
461 | rmap.connect('authentication_token', '%s/authentication_token' % ADMIN_PREFIX, controller='login', action='authentication_token') | |
469 | rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login') |
|
462 | rmap.connect('login_home', '%s/login' % ADMIN_PREFIX, controller='login') | |
470 | rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login', |
|
463 | rmap.connect('logout_home', '%s/logout' % ADMIN_PREFIX, controller='login', | |
@@ -480,7 +473,7 b' def make_map(config):' | |||||
480 | '%s/password_reset_confirmation' % ADMIN_PREFIX, |
|
473 | '%s/password_reset_confirmation' % ADMIN_PREFIX, | |
481 | controller='login', action='password_reset_confirmation') |
|
474 | controller='login', action='password_reset_confirmation') | |
482 |
|
475 | |||
483 | #FEEDS |
|
476 | # FEEDS | |
484 | rmap.connect('rss_feed_home', '/{repo_name:.*?}/feed/rss', |
|
477 | rmap.connect('rss_feed_home', '/{repo_name:.*?}/feed/rss', | |
485 | controller='feed', action='rss', |
|
478 | controller='feed', action='rss', | |
486 | conditions=dict(function=check_repo)) |
|
479 | conditions=dict(function=check_repo)) | |
@@ -551,7 +544,6 b' def make_map(config):' | |||||
551 | controller='admin/repos', action="delete_repo_field", |
|
544 | controller='admin/repos', action="delete_repo_field", | |
552 | conditions=dict(method=["POST"], function=check_repo)) |
|
545 | conditions=dict(method=["POST"], function=check_repo)) | |
553 |
|
546 | |||
554 |
|
||||
555 | rmap.connect("edit_repo_advanced", "/{repo_name:.*?}/settings/advanced", |
|
547 | rmap.connect("edit_repo_advanced", "/{repo_name:.*?}/settings/advanced", | |
556 | controller='admin/repos', action="edit_advanced", |
|
548 | controller='admin/repos', action="edit_advanced", | |
557 | conditions=dict(method=["GET"], function=check_repo)) |
|
549 | conditions=dict(method=["GET"], function=check_repo)) | |
@@ -571,7 +563,6 b' def make_map(config):' | |||||
571 | controller='admin/repos', action="edit_advanced_fork", |
|
563 | controller='admin/repos', action="edit_advanced_fork", | |
572 | conditions=dict(method=["POST"], function=check_repo)) |
|
564 | conditions=dict(method=["POST"], function=check_repo)) | |
573 |
|
565 | |||
574 |
|
||||
575 | rmap.connect("edit_repo_caches", "/{repo_name:.*?}/settings/caches", |
|
566 | rmap.connect("edit_repo_caches", "/{repo_name:.*?}/settings/caches", | |
576 | controller='admin/repos', action="edit_caches", |
|
567 | controller='admin/repos', action="edit_caches", | |
577 | conditions=dict(method=["GET"], function=check_repo)) |
|
568 | conditions=dict(method=["GET"], function=check_repo)) | |
@@ -579,7 +570,6 b' def make_map(config):' | |||||
579 | controller='admin/repos', action="edit_caches", |
|
570 | controller='admin/repos', action="edit_caches", | |
580 | conditions=dict(method=["POST"], function=check_repo)) |
|
571 | conditions=dict(method=["POST"], function=check_repo)) | |
581 |
|
572 | |||
582 |
|
||||
583 | rmap.connect("edit_repo_remote", "/{repo_name:.*?}/settings/remote", |
|
573 | rmap.connect("edit_repo_remote", "/{repo_name:.*?}/settings/remote", | |
584 | controller='admin/repos', action="edit_remote", |
|
574 | controller='admin/repos', action="edit_remote", | |
585 | conditions=dict(method=["GET"], function=check_repo)) |
|
575 | conditions=dict(method=["GET"], function=check_repo)) | |
@@ -594,7 +584,7 b' def make_map(config):' | |||||
594 | controller='admin/repos', action="edit_statistics", |
|
584 | controller='admin/repos', action="edit_statistics", | |
595 | conditions=dict(method=["POST"], function=check_repo)) |
|
585 | conditions=dict(method=["POST"], function=check_repo)) | |
596 |
|
586 | |||
597 | #still working url for backward compat. |
|
587 | # still working url for backward compat. | |
598 | rmap.connect('raw_changeset_home_depraced', |
|
588 | rmap.connect('raw_changeset_home_depraced', | |
599 | '/{repo_name:.*?}/raw-changeset/{revision}', |
|
589 | '/{repo_name:.*?}/raw-changeset/{revision}', | |
600 | controller='changeset', action='changeset_raw', |
|
590 | controller='changeset', action='changeset_raw', | |
@@ -812,7 +802,9 b' class UrlGenerator(object):' | |||||
812 | """ |
|
802 | """ | |
813 | def __call__(self, *args, **kwargs): |
|
803 | def __call__(self, *args, **kwargs): | |
814 | return request.environ['routes.url'](*args, **kwargs) |
|
804 | return request.environ['routes.url'](*args, **kwargs) | |
|
805 | ||||
815 | def current(self, *args, **kwargs): |
|
806 | def current(self, *args, **kwargs): | |
816 | return request.environ['routes.url'].current(*args, **kwargs) |
|
807 | return request.environ['routes.url'].current(*args, **kwargs) | |
817 |
|
808 | |||
|
809 | ||||
818 | url = UrlGenerator() |
|
810 | url = UrlGenerator() |
@@ -65,11 +65,11 b' def _journal_filter(user_log, search_ter' | |||||
65 |
|
65 | |||
66 | def wildcard_handler(col, wc_term): |
|
66 | def wildcard_handler(col, wc_term): | |
67 | if wc_term.startswith('*') and not wc_term.endswith('*'): |
|
67 | if wc_term.startswith('*') and not wc_term.endswith('*'): | |
68 | #postfix == endswith |
|
68 | # postfix == endswith | |
69 | wc_term = remove_prefix(wc_term, prefix='*') |
|
69 | wc_term = remove_prefix(wc_term, prefix='*') | |
70 | return func.lower(col).endswith(func.lower(wc_term)) |
|
70 | return func.lower(col).endswith(func.lower(wc_term)) | |
71 | elif wc_term.startswith('*') and wc_term.endswith('*'): |
|
71 | elif wc_term.startswith('*') and wc_term.endswith('*'): | |
72 | #wildcard == ilike |
|
72 | # wildcard == ilike | |
73 | wc_term = remove_prefix(wc_term, prefix='*') |
|
73 | wc_term = remove_prefix(wc_term, prefix='*') | |
74 | wc_term = remove_suffix(wc_term, suffix='*') |
|
74 | wc_term = remove_suffix(wc_term, suffix='*') | |
75 | return func.lower(col).contains(func.lower(wc_term)) |
|
75 | return func.lower(col).contains(func.lower(wc_term)) | |
@@ -88,7 +88,7 b' def _journal_filter(user_log, search_ter' | |||||
88 | field = getattr(UserLog, field) |
|
88 | field = getattr(UserLog, field) | |
89 | log.debug('filter field: %s val=>%s', field, val) |
|
89 | log.debug('filter field: %s val=>%s', field, val) | |
90 |
|
90 | |||
91 | #sql filtering |
|
91 | # sql filtering | |
92 | if isinstance(term, query.Wildcard): |
|
92 | if isinstance(term, query.Wildcard): | |
93 | return wildcard_handler(field, val) |
|
93 | return wildcard_handler(field, val) | |
94 | elif isinstance(term, query.Prefix): |
|
94 | elif isinstance(term, query.Prefix): | |
@@ -130,7 +130,7 b' class AdminController(BaseController):' | |||||
130 | .options(joinedload(UserLog.user)) \ |
|
130 | .options(joinedload(UserLog.user)) \ | |
131 | .options(joinedload(UserLog.repository)) |
|
131 | .options(joinedload(UserLog.repository)) | |
132 |
|
132 | |||
133 | #FILTERING |
|
133 | # FILTERING | |
134 | c.search_term = request.GET.get('filter') |
|
134 | c.search_term = request.GET.get('filter') | |
135 | users_log = _journal_filter(users_log, c.search_term) |
|
135 | users_log = _journal_filter(users_log, c.search_term) | |
136 |
|
136 |
@@ -106,7 +106,7 b' class GistsController(BaseController):' | |||||
106 | gist_form = GistForm([x[0] for x in c.lifetime_values])() |
|
106 | gist_form = GistForm([x[0] for x in c.lifetime_values])() | |
107 | try: |
|
107 | try: | |
108 | form_result = gist_form.to_python(dict(request.POST)) |
|
108 | form_result = gist_form.to_python(dict(request.POST)) | |
109 | #TODO: multiple files support, from the form |
|
109 | # TODO: multiple files support, from the form | |
110 | filename = form_result['filename'] or Gist.DEFAULT_FILENAME |
|
110 | filename = form_result['filename'] or Gist.DEFAULT_FILENAME | |
111 | nodes = { |
|
111 | nodes = { | |
112 | filename: { |
|
112 | filename: { | |
@@ -250,7 +250,7 b' class GistsController(BaseController):' | |||||
250 | success = True |
|
250 | success = True | |
251 | revision = request.POST.get('revision') |
|
251 | revision = request.POST.get('revision') | |
252 |
|
252 | |||
253 |
# |
|
253 | # TODO: maybe move this to model ? | |
254 | if revision != last_rev.raw_id: |
|
254 | if revision != last_rev.raw_id: | |
255 | log.error('Last revision %s is different than submitted %s', |
|
255 | log.error('Last revision %s is different than submitted %s', | |
256 | revision, last_rev) |
|
256 | revision, last_rev) |
@@ -131,7 +131,7 b' class MyAccountController(BaseController' | |||||
131 | force_defaults=False) |
|
131 | force_defaults=False) | |
132 | except Exception: |
|
132 | except Exception: | |
133 | log.error(traceback.format_exc()) |
|
133 | log.error(traceback.format_exc()) | |
134 |
h.flash(_('Error occurred during update of user %s') |
|
134 | h.flash(_('Error occurred during update of user %s') | |
135 | % form_result.get('username'), category='error') |
|
135 | % form_result.get('username'), category='error') | |
136 | if update: |
|
136 | if update: | |
137 | raise HTTPFound(location='my_account') |
|
137 | raise HTTPFound(location='my_account') | |
@@ -173,7 +173,7 b' class MyAccountController(BaseController' | |||||
173 | c.active = 'repos' |
|
173 | c.active = 'repos' | |
174 | self.__load_data() |
|
174 | self.__load_data() | |
175 |
|
175 | |||
176 | #data used to render the grid |
|
176 | # data used to render the grid | |
177 | c.data = self._load_my_repos_data() |
|
177 | c.data = self._load_my_repos_data() | |
178 | return render('admin/my_account/my_account.html') |
|
178 | return render('admin/my_account/my_account.html') | |
179 |
|
179 | |||
@@ -181,7 +181,7 b' class MyAccountController(BaseController' | |||||
181 | c.active = 'watched' |
|
181 | c.active = 'watched' | |
182 | self.__load_data() |
|
182 | self.__load_data() | |
183 |
|
183 | |||
184 | #data used to render the grid |
|
184 | # data used to render the grid | |
185 | c.data = self._load_my_repos_data(watched=True) |
|
185 | c.data = self._load_my_repos_data(watched=True) | |
186 | return render('admin/my_account/my_account.html') |
|
186 | return render('admin/my_account/my_account.html') | |
187 |
|
187 |
@@ -166,7 +166,7 b' class RepoGroupsController(BaseControlle' | |||||
166 | copy_permissions=form_result['group_copy_permissions'] |
|
166 | copy_permissions=form_result['group_copy_permissions'] | |
167 | ) |
|
167 | ) | |
168 | Session().commit() |
|
168 | Session().commit() | |
169 | #TODO: in future action_logger(, '', '', '') |
|
169 | # TODO: in future action_logger(, '', '', '') | |
170 | except formencode.Invalid as errors: |
|
170 | except formencode.Invalid as errors: | |
171 | return htmlfill.render( |
|
171 | return htmlfill.render( | |
172 | render('admin/repo_groups/repo_group_add.html'), |
|
172 | render('admin/repo_groups/repo_group_add.html'), | |
@@ -177,10 +177,10 b' class RepoGroupsController(BaseControlle' | |||||
177 | force_defaults=False) |
|
177 | force_defaults=False) | |
178 | except Exception: |
|
178 | except Exception: | |
179 | log.error(traceback.format_exc()) |
|
179 | log.error(traceback.format_exc()) | |
180 |
h.flash(_('Error occurred during creation of repository group %s') |
|
180 | h.flash(_('Error occurred during creation of repository group %s') | |
181 | % request.POST.get('group_name'), category='error') |
|
181 | % request.POST.get('group_name'), category='error') | |
182 | parent_group_id = form_result['parent_group_id'] |
|
182 | parent_group_id = form_result['parent_group_id'] | |
183 | #TODO: maybe we should get back to the main view, not the admin one |
|
183 | # TODO: maybe we should get back to the main view, not the admin one | |
184 | raise HTTPFound(location=url('repos_groups', parent_group=parent_group_id)) |
|
184 | raise HTTPFound(location=url('repos_groups', parent_group=parent_group_id)) | |
185 | h.flash(_('Created repository group %s') % gr.group_name, |
|
185 | h.flash(_('Created repository group %s') % gr.group_name, | |
186 | category='success') |
|
186 | category='success') | |
@@ -188,7 +188,7 b' class RepoGroupsController(BaseControlle' | |||||
188 |
|
188 | |||
189 | def new(self): |
|
189 | def new(self): | |
190 | if HasPermissionAny('hg.admin')('group create'): |
|
190 | if HasPermissionAny('hg.admin')('group create'): | |
191 | #we're global admin, we're ok and we can create TOP level groups |
|
191 | # we're global admin, we're ok and we can create TOP level groups | |
192 | pass |
|
192 | pass | |
193 | else: |
|
193 | else: | |
194 | # we pass in parent group into creation form, thus we know |
|
194 | # we pass in parent group into creation form, thus we know | |
@@ -212,7 +212,7 b' class RepoGroupsController(BaseControlle' | |||||
212 |
|
212 | |||
213 | # TODO: kill allow_empty_group - it is only used for redundant form validation! |
|
213 | # TODO: kill allow_empty_group - it is only used for redundant form validation! | |
214 | if HasPermissionAny('hg.admin')('group edit'): |
|
214 | if HasPermissionAny('hg.admin')('group edit'): | |
215 | #we're global admin, we're ok and we can create TOP level groups |
|
215 | # we're global admin, we're ok and we can create TOP level groups | |
216 | allow_empty_group = True |
|
216 | allow_empty_group = True | |
217 | elif not c.repo_group.parent_group: |
|
217 | elif not c.repo_group.parent_group: | |
218 | allow_empty_group = True |
|
218 | allow_empty_group = True | |
@@ -229,11 +229,11 b' class RepoGroupsController(BaseControlle' | |||||
229 |
|
229 | |||
230 | new_gr = RepoGroupModel().update(group_name, form_result) |
|
230 | new_gr = RepoGroupModel().update(group_name, form_result) | |
231 | Session().commit() |
|
231 | Session().commit() | |
232 |
h.flash(_('Updated repository group %s') |
|
232 | h.flash(_('Updated repository group %s') | |
233 | % form_result['group_name'], category='success') |
|
233 | % form_result['group_name'], category='success') | |
234 | # we now have new name ! |
|
234 | # we now have new name ! | |
235 | group_name = new_gr.group_name |
|
235 | group_name = new_gr.group_name | |
236 | #TODO: in future action_logger(, '', '', '') |
|
236 | # TODO: in future action_logger(, '', '', '') | |
237 | except formencode.Invalid as errors: |
|
237 | except formencode.Invalid as errors: | |
238 | c.active = 'settings' |
|
238 | c.active = 'settings' | |
239 | return htmlfill.render( |
|
239 | return htmlfill.render( | |
@@ -245,7 +245,7 b' class RepoGroupsController(BaseControlle' | |||||
245 | force_defaults=False) |
|
245 | force_defaults=False) | |
246 | except Exception: |
|
246 | except Exception: | |
247 | log.error(traceback.format_exc()) |
|
247 | log.error(traceback.format_exc()) | |
248 |
h.flash(_('Error occurred during update of repository group %s') |
|
248 | h.flash(_('Error occurred during update of repository group %s') | |
249 | % request.POST.get('group_name'), category='error') |
|
249 | % request.POST.get('group_name'), category='error') | |
250 |
|
250 | |||
251 | raise HTTPFound(location=url('edit_repo_group', group_name=group_name)) |
|
251 | raise HTTPFound(location=url('edit_repo_group', group_name=group_name)) | |
@@ -270,7 +270,7 b' class RepoGroupsController(BaseControlle' | |||||
270 | Session().commit() |
|
270 | Session().commit() | |
271 | h.flash(_('Removed repository group %s') % group_name, |
|
271 | h.flash(_('Removed repository group %s') % group_name, | |
272 | category='success') |
|
272 | category='success') | |
273 | #TODO: in future action_logger(, '', '', '') |
|
273 | # TODO: in future action_logger(, '', '', '') | |
274 | except Exception: |
|
274 | except Exception: | |
275 | log.error(traceback.format_exc()) |
|
275 | log.error(traceback.format_exc()) | |
276 | h.flash(_('Error occurred during deletion of repository group %s') |
|
276 | h.flash(_('Error occurred during deletion of repository group %s') | |
@@ -369,7 +369,7 b' class RepoGroupsController(BaseControlle' | |||||
369 | form_result['perms_new'], |
|
369 | form_result['perms_new'], | |
370 | form_result['perms_updates'], |
|
370 | form_result['perms_updates'], | |
371 | recursive) |
|
371 | recursive) | |
372 | #TODO: implement this |
|
372 | # TODO: implement this | |
373 | #action_logger(request.authuser, 'admin_changed_repo_permissions', |
|
373 | #action_logger(request.authuser, 'admin_changed_repo_permissions', | |
374 | # repo_name, request.ip_addr) |
|
374 | # repo_name, request.ip_addr) | |
375 | Session().commit() |
|
375 | Session().commit() |
@@ -104,7 +104,7 b' class ReposController(BaseRepoController' | |||||
104 | repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, |
|
104 | repos_data = RepoModel().get_repos_as_dict(repos_list=c.repos_list, | |
105 | admin=True, |
|
105 | admin=True, | |
106 | super_user_actions=True) |
|
106 | super_user_actions=True) | |
107 | #data used to render the grid |
|
107 | # data used to render the grid | |
108 | c.data = repos_data |
|
108 | c.data = repos_data | |
109 |
|
109 | |||
110 | return render('admin/repos/repos.html') |
|
110 | return render('admin/repos/repos.html') | |
@@ -257,7 +257,7 b' class ReposController(BaseRepoController' | |||||
257 |
|
257 | |||
258 | except Exception: |
|
258 | except Exception: | |
259 | log.error(traceback.format_exc()) |
|
259 | log.error(traceback.format_exc()) | |
260 |
h.flash(_('Error occurred during update of repository %s') |
|
260 | h.flash(_('Error occurred during update of repository %s') | |
261 | % repo_name, category='error') |
|
261 | % repo_name, category='error') | |
262 | raise HTTPFound(location=url('edit_repo', repo_name=changed_name)) |
|
262 | raise HTTPFound(location=url('edit_repo', repo_name=changed_name)) | |
263 |
|
263 | |||
@@ -331,7 +331,7 b' class ReposController(BaseRepoController' | |||||
331 | form = RepoPermsForm()().to_python(request.POST) |
|
331 | form = RepoPermsForm()().to_python(request.POST) | |
332 | RepoModel()._update_permissions(repo_name, form['perms_new'], |
|
332 | RepoModel()._update_permissions(repo_name, form['perms_new'], | |
333 | form['perms_updates']) |
|
333 | form['perms_updates']) | |
334 | #TODO: implement this |
|
334 | # TODO: implement this | |
335 | #action_logger(request.authuser, 'admin_changed_repo_permissions', |
|
335 | #action_logger(request.authuser, 'admin_changed_repo_permissions', | |
336 | # repo_name, request.ip_addr) |
|
336 | # repo_name, request.ip_addr) | |
337 | Session().commit() |
|
337 | Session().commit() | |
@@ -353,7 +353,7 b' class ReposController(BaseRepoController' | |||||
353 | RepoModel().revoke_user_group_permission( |
|
353 | RepoModel().revoke_user_group_permission( | |
354 | repo=repo_name, group_name=obj_id |
|
354 | repo=repo_name, group_name=obj_id | |
355 | ) |
|
355 | ) | |
356 | #TODO: implement this |
|
356 | # TODO: implement this | |
357 | #action_logger(request.authuser, 'admin_revoked_repo_permissions', |
|
357 | #action_logger(request.authuser, 'admin_revoked_repo_permissions', | |
358 | # repo_name, request.ip_addr) |
|
358 | # repo_name, request.ip_addr) | |
359 | Session().commit() |
|
359 | Session().commit() | |
@@ -456,7 +456,6 b' class ReposController(BaseRepoController' | |||||
456 | category='error') |
|
456 | category='error') | |
457 | raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name)) |
|
457 | raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name)) | |
458 |
|
458 | |||
459 |
|
||||
460 | @HasRepoPermissionLevelDecorator('admin') |
|
459 | @HasRepoPermissionLevelDecorator('admin') | |
461 | def edit_advanced_fork(self, repo_name): |
|
460 | def edit_advanced_fork(self, repo_name): | |
462 | """ |
|
461 | """ |
@@ -102,7 +102,7 b' class SettingsController(BaseController)' | |||||
102 | sett = Ui.get_by_key('paths', '/') |
|
102 | sett = Ui.get_by_key('paths', '/') | |
103 | sett.ui_value = form_result['paths_root_path'] |
|
103 | sett.ui_value = form_result['paths_root_path'] | |
104 |
|
104 | |||
105 | #HOOKS |
|
105 | # HOOKS | |
106 | sett = Ui.get_by_key('hooks', Ui.HOOK_UPDATE) |
|
106 | sett = Ui.get_by_key('hooks', Ui.HOOK_UPDATE) | |
107 | sett.ui_active = form_result['hooks_changegroup_update'] |
|
107 | sett.ui_active = form_result['hooks_changegroup_update'] | |
108 |
|
108 | |||
@@ -160,7 +160,7 b' class SettingsController(BaseController)' | |||||
160 | if request.POST: |
|
160 | if request.POST: | |
161 | rm_obsolete = request.POST.get('destroy', False) |
|
161 | rm_obsolete = request.POST.get('destroy', False) | |
162 | install_git_hooks = request.POST.get('hooks', False) |
|
162 | install_git_hooks = request.POST.get('hooks', False) | |
163 |
overwrite_git_hooks = request.POST.get('hooks_overwrite', False) |
|
163 | overwrite_git_hooks = request.POST.get('hooks_overwrite', False) | |
164 | invalidate_cache = request.POST.get('invalidate', False) |
|
164 | invalidate_cache = request.POST.get('invalidate', False) | |
165 | log.debug('rescanning repo location with destroy obsolete=%s, ' |
|
165 | log.debug('rescanning repo location with destroy obsolete=%s, ' | |
166 | 'install git hooks=%s and ' |
|
166 | 'install git hooks=%s and ' |
@@ -155,7 +155,7 b' class UserGroupsController(BaseControlle' | |||||
155 | force_defaults=False) |
|
155 | force_defaults=False) | |
156 | except Exception: |
|
156 | except Exception: | |
157 | log.error(traceback.format_exc()) |
|
157 | log.error(traceback.format_exc()) | |
158 |
h.flash(_('Error occurred during creation of user group %s') |
|
158 | h.flash(_('Error occurred during creation of user group %s') | |
159 | % request.POST.get('users_group_name'), category='error') |
|
159 | % request.POST.get('users_group_name'), category='error') | |
160 |
|
160 | |||
161 | raise HTTPFound(location=url('users_groups')) |
|
161 | raise HTTPFound(location=url('users_groups')) | |
@@ -205,7 +205,7 b' class UserGroupsController(BaseControlle' | |||||
205 | force_defaults=False) |
|
205 | force_defaults=False) | |
206 | except Exception: |
|
206 | except Exception: | |
207 | log.error(traceback.format_exc()) |
|
207 | log.error(traceback.format_exc()) | |
208 |
h.flash(_('Error occurred during update of user group %s') |
|
208 | h.flash(_('Error occurred during update of user group %s') | |
209 | % request.POST.get('users_group_name'), category='error') |
|
209 | % request.POST.get('users_group_name'), category='error') | |
210 |
|
210 | |||
211 | raise HTTPFound(location=url('edit_users_group', id=id)) |
|
211 | raise HTTPFound(location=url('edit_users_group', id=id)) | |
@@ -283,7 +283,7 b' class UserGroupsController(BaseControlle' | |||||
283 | except RepoGroupAssignmentError: |
|
283 | except RepoGroupAssignmentError: | |
284 | h.flash(_('Target group cannot be the same'), category='error') |
|
284 | h.flash(_('Target group cannot be the same'), category='error') | |
285 | raise HTTPFound(location=url('edit_user_group_perms', id=id)) |
|
285 | raise HTTPFound(location=url('edit_user_group_perms', id=id)) | |
286 | #TODO: implement this |
|
286 | # TODO: implement this | |
287 | #action_logger(request.authuser, 'admin_changed_repo_permissions', |
|
287 | #action_logger(request.authuser, 'admin_changed_repo_permissions', | |
288 | # repo_name, request.ip_addr) |
|
288 | # repo_name, request.ip_addr) | |
289 | Session().commit() |
|
289 | Session().commit() | |
@@ -415,7 +415,6 b' class UserGroupsController(BaseControlle' | |||||
415 | key=lambda u: u.username.lower()) |
|
415 | key=lambda u: u.username.lower()) | |
416 | return render('admin/user_groups/user_group_edit.html') |
|
416 | return render('admin/user_groups/user_group_edit.html') | |
417 |
|
417 | |||
418 |
|
||||
419 | @HasUserGroupPermissionLevelDecorator('admin') |
|
418 | @HasUserGroupPermissionLevelDecorator('admin') | |
420 | def edit_members(self, id): |
|
419 | def edit_members(self, id): | |
421 | c.user_group = UserGroup.get_or_404(id) |
|
420 | c.user_group = UserGroup.get_or_404(id) |
@@ -137,7 +137,7 b' class UsersController(BaseController):' | |||||
137 | h.flash(e, 'error') |
|
137 | h.flash(e, 'error') | |
138 | except Exception: |
|
138 | except Exception: | |
139 | log.error(traceback.format_exc()) |
|
139 | log.error(traceback.format_exc()) | |
140 |
h.flash(_('Error occurred during creation of user %s') |
|
140 | h.flash(_('Error occurred during creation of user %s') | |
141 | % request.POST.get('username'), category='error') |
|
141 | % request.POST.get('username'), category='error') | |
142 | raise HTTPFound(location=url('edit_user', id=user.user_id)) |
|
142 | raise HTTPFound(location=url('edit_user', id=user.user_id)) | |
143 |
|
143 | |||
@@ -180,7 +180,7 b' class UsersController(BaseController):' | |||||
180 | force_defaults=False) |
|
180 | force_defaults=False) | |
181 | except Exception: |
|
181 | except Exception: | |
182 | log.error(traceback.format_exc()) |
|
182 | log.error(traceback.format_exc()) | |
183 |
h.flash(_('Error occurred during update of user %s') |
|
183 | h.flash(_('Error occurred during update of user %s') | |
184 | % form_result.get('username'), category='error') |
|
184 | % form_result.get('username'), category='error') | |
185 | raise HTTPFound(location=url('edit_user', id=id)) |
|
185 | raise HTTPFound(location=url('edit_user', id=id)) | |
186 |
|
186 |
@@ -114,7 +114,7 b' class ChangelogController(BaseRepoContro' | |||||
114 | try: |
|
114 | try: | |
115 | collection = tip_cs.get_file_history(f_path) |
|
115 | collection = tip_cs.get_file_history(f_path) | |
116 | except (NodeDoesNotExistError, ChangesetError): |
|
116 | except (NodeDoesNotExistError, ChangesetError): | |
117 | #this node is not present at tip ! |
|
117 | # this node is not present at tip ! | |
118 | try: |
|
118 | try: | |
119 | cs = self.__get_cs(revision, repo_name) |
|
119 | cs = self.__get_cs(revision, repo_name) | |
120 | collection = cs.get_file_history(f_path) |
|
120 | collection = cs.get_file_history(f_path) |
@@ -115,7 +115,7 b' def get_line_ctx(fid, GET):' | |||||
115 | ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid)) |
|
115 | ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid)) | |
116 | else: |
|
116 | else: | |
117 | _ln_ctx = filter(lambda k: k.startswith('C'), GET) |
|
117 | _ln_ctx = filter(lambda k: k.startswith('C'), GET) | |
118 |
ln_ctx = GET.get(_ln_ctx[0]) if _ln_ctx |
|
118 | ln_ctx = GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global | |
119 | if ln_ctx: |
|
119 | if ln_ctx: | |
120 | ln_ctx = [ln_ctx] |
|
120 | ln_ctx = [ln_ctx] | |
121 |
|
121 | |||
@@ -207,7 +207,7 b' class ChangesetController(BaseRepoContro' | |||||
207 | c.ignorews_url = _ignorews_url |
|
207 | c.ignorews_url = _ignorews_url | |
208 | c.context_url = _context_url |
|
208 | c.context_url = _context_url | |
209 | c.fulldiff = fulldiff = request.GET.get('fulldiff') |
|
209 | c.fulldiff = fulldiff = request.GET.get('fulldiff') | |
210 | #get ranges of revisions if preset |
|
210 | # get ranges of revisions if preset | |
211 | rev_range = revision.split('...')[:2] |
|
211 | rev_range = revision.split('...')[:2] | |
212 | enable_comments = True |
|
212 | enable_comments = True | |
213 | c.cs_repo = c.db_repo |
|
213 | c.cs_repo = c.db_repo | |
@@ -300,7 +300,7 b' class ChangesetController(BaseRepoContro' | |||||
300 | file_diff_data.append(('', None, None, None, diff, None)) |
|
300 | file_diff_data.append(('', None, None, None, diff, None)) | |
301 | c.changes[changeset.raw_id] = (cs1, cs2, file_diff_data) |
|
301 | c.changes[changeset.raw_id] = (cs1, cs2, file_diff_data) | |
302 |
|
302 | |||
303 | #sort comments in creation order |
|
303 | # sort comments in creation order | |
304 | c.comments = [com for com_id, com in sorted(comments.items())] |
|
304 | c.comments = [com for com_id, com in sorted(comments.items())] | |
305 |
|
305 | |||
306 | # count inline comments |
|
306 | # count inline comments |
@@ -94,7 +94,7 b' class CompareController(BaseRepoControll' | |||||
94 | other_changesets = [] |
|
94 | other_changesets = [] | |
95 |
|
95 | |||
96 | elif alias == 'hg': |
|
96 | elif alias == 'hg': | |
97 | #case two independent repos |
|
97 | # case two independent repos | |
98 | if org_repo != other_repo: |
|
98 | if org_repo != other_repo: | |
99 | hgrepo = unionrepo.unionrepository(other_repo.baseui, |
|
99 | hgrepo = unionrepo.unionrepository(other_repo.baseui, | |
100 | other_repo.path, |
|
100 | other_repo.path, | |
@@ -102,7 +102,7 b' class CompareController(BaseRepoControll' | |||||
102 | # all ancestors of other_rev will be in other_repo and |
|
102 | # all ancestors of other_rev will be in other_repo and | |
103 | # rev numbers from hgrepo can be used in other_repo - org_rev ancestors cannot |
|
103 | # rev numbers from hgrepo can be used in other_repo - org_rev ancestors cannot | |
104 |
|
104 | |||
105 | #no remote compare do it on the same repository |
|
105 | # no remote compare do it on the same repository | |
106 | else: |
|
106 | else: | |
107 | hgrepo = other_repo._repo |
|
107 | hgrepo = other_repo._repo | |
108 |
|
108 |
@@ -83,7 +83,7 b' class FeedController(BaseRepoController)' | |||||
83 | def __get_desc(self, cs): |
|
83 | def __get_desc(self, cs): | |
84 | desc_msg = [(_('%s committed on %s') |
|
84 | desc_msg = [(_('%s committed on %s') | |
85 | % (h.person(cs.author), h.fmt_date(cs.date))) + '<br/>'] |
|
85 | % (h.person(cs.author), h.fmt_date(cs.date))) + '<br/>'] | |
86 | #branches, tags, bookmarks |
|
86 | # branches, tags, bookmarks | |
87 | if cs.branch: |
|
87 | if cs.branch: | |
88 | desc_msg.append('branch: %s<br/>' % cs.branch) |
|
88 | desc_msg.append('branch: %s<br/>' % cs.branch) | |
89 | for book in cs.bookmarks: |
|
89 | for book in cs.bookmarks: |
@@ -166,7 +166,7 b' class FilesController(BaseRepoController' | |||||
166 |
|
166 | |||
167 | if c.file.is_file(): |
|
167 | if c.file.is_file(): | |
168 | c.load_full_history = False |
|
168 | c.load_full_history = False | |
169 | #determine if we're on branch head |
|
169 | # determine if we're on branch head | |
170 | _branches = c.db_repo_scm_instance.branches |
|
170 | _branches = c.db_repo_scm_instance.branches | |
171 | c.on_branch_head = revision in _branches.keys() + _branches.values() |
|
171 | c.on_branch_head = revision in _branches.keys() + _branches.values() | |
172 | _hist = [] |
|
172 | _hist = [] | |
@@ -460,7 +460,7 b' class FilesController(BaseRepoController' | |||||
460 | h.flash(_('No filename'), category='warning') |
|
460 | h.flash(_('No filename'), category='warning') | |
461 | raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name, |
|
461 | raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name, | |
462 | revision='tip')) |
|
462 | revision='tip')) | |
463 | #strip all crap out of file, just leave the basename |
|
463 | # strip all crap out of file, just leave the basename | |
464 | filename = os.path.basename(filename) |
|
464 | filename = os.path.basename(filename) | |
465 | node_path = posixpath.join(location, filename) |
|
465 | node_path = posixpath.join(location, filename) | |
466 | author = request.authuser.full_contact |
|
466 | author = request.authuser.full_contact | |
@@ -599,8 +599,8 b' class FilesController(BaseRepoController' | |||||
599 | c.changes = OrderedDict() |
|
599 | c.changes = OrderedDict() | |
600 | c.changes[diff2] = [] |
|
600 | c.changes[diff2] = [] | |
601 |
|
601 | |||
602 | #special case if we want a show rev only, it's impl here |
|
602 | # special case if we want a show rev only, it's impl here | |
603 | #to reduce JS and callbacks |
|
603 | # to reduce JS and callbacks | |
604 |
|
604 | |||
605 | if request.GET.get('show_rev'): |
|
605 | if request.GET.get('show_rev'): | |
606 | if str2bool(request.GET.get('annotate', 'False')): |
|
606 | if str2bool(request.GET.get('annotate', 'False')): | |
@@ -748,7 +748,7 b' class FilesController(BaseRepoController' | |||||
748 | try: |
|
748 | try: | |
749 | changesets = tip_cs.get_file_history(f_path) |
|
749 | changesets = tip_cs.get_file_history(f_path) | |
750 | except (NodeDoesNotExistError, ChangesetError): |
|
750 | except (NodeDoesNotExistError, ChangesetError): | |
751 | #this node is not present at tip ! |
|
751 | # this node is not present at tip ! | |
752 | changesets = cs.get_file_history(f_path) |
|
752 | changesets = cs.get_file_history(f_path) | |
753 | hist_l = [] |
|
753 | hist_l = [] | |
754 |
|
754 |
@@ -57,7 +57,7 b' class HomeController(BaseController):' | |||||
57 |
|
57 | |||
58 | repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, |
|
58 | repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, | |
59 | admin=False, short_name=True) |
|
59 | admin=False, short_name=True) | |
60 | #data used to render the grid |
|
60 | # data used to render the grid | |
61 | c.data = repos_data |
|
61 | c.data = repos_data | |
62 |
|
62 | |||
63 | return render('/index.html') |
|
63 | return render('/index.html') | |
@@ -65,7 +65,7 b' class HomeController(BaseController):' | |||||
65 | @LoginRequired() |
|
65 | @LoginRequired() | |
66 | @jsonify |
|
66 | @jsonify | |
67 | def repo_switcher_data(self): |
|
67 | def repo_switcher_data(self): | |
68 | #wrapper for conditional cache |
|
68 | # wrapper for conditional cache | |
69 | def _c(): |
|
69 | def _c(): | |
70 | log.debug('generating switcher repo/groups list') |
|
70 | log.debug('generating switcher repo/groups list') | |
71 | all_repos = Repository.query(sorted=True).all() |
|
71 | all_repos = Repository.query(sorted=True).all() |
@@ -69,7 +69,7 b' class JournalController(BaseController):' | |||||
69 | groups = [] |
|
69 | groups = [] | |
70 | for k, g in groupby(journal, lambda x: x.action_as_day): |
|
70 | for k, g in groupby(journal, lambda x: x.action_as_day): | |
71 | user_group = [] |
|
71 | user_group = [] | |
72 | #groupby username if it's a present value, else fallback to journal username |
|
72 | # groupby username if it's a present value, else fallback to journal username | |
73 | for _unused, g2 in groupby(list(g), lambda x: x.user.username if x.user else x.username): |
|
73 | for _unused, g2 in groupby(list(g), lambda x: x.user.username if x.user else x.username): | |
74 | l = list(g2) |
|
74 | l = list(g2) | |
75 | user_group.append((l[0].user, l)) |
|
75 | user_group.append((l[0].user, l)) | |
@@ -97,7 +97,7 b' class JournalController(BaseController):' | |||||
97 | journal = UserLog.query() \ |
|
97 | journal = UserLog.query() \ | |
98 | .options(joinedload(UserLog.user)) \ |
|
98 | .options(joinedload(UserLog.user)) \ | |
99 | .options(joinedload(UserLog.repository)) |
|
99 | .options(joinedload(UserLog.repository)) | |
100 | #filter |
|
100 | # filter | |
101 | journal = _journal_filter(journal, c.search_term) |
|
101 | journal = _journal_filter(journal, c.search_term) | |
102 | journal = journal.filter(filtering_criterion) \ |
|
102 | journal = journal.filter(filtering_criterion) \ | |
103 | .order_by(UserLog.action_date.desc()) |
|
103 | .order_by(UserLog.action_date.desc()) | |
@@ -125,7 +125,7 b' class JournalController(BaseController):' | |||||
125 | for entry in journal[:feed_nr]: |
|
125 | for entry in journal[:feed_nr]: | |
126 | user = entry.user |
|
126 | user = entry.user | |
127 | if user is None: |
|
127 | if user is None: | |
128 | #fix deleted users |
|
128 | # fix deleted users | |
129 | user = AttributeDict({'short_contact': entry.username, |
|
129 | user = AttributeDict({'short_contact': entry.username, | |
130 | 'email': '', |
|
130 | 'email': '', | |
131 | 'full_contact': ''}) |
|
131 | 'full_contact': ''}) | |
@@ -167,7 +167,7 b' class JournalController(BaseController):' | |||||
167 | for entry in journal[:feed_nr]: |
|
167 | for entry in journal[:feed_nr]: | |
168 | user = entry.user |
|
168 | user = entry.user | |
169 | if user is None: |
|
169 | if user is None: | |
170 | #fix deleted users |
|
170 | # fix deleted users | |
171 | user = AttributeDict({'short_contact': entry.username, |
|
171 | user = AttributeDict({'short_contact': entry.username, | |
172 | 'email': '', |
|
172 | 'email': '', | |
173 | 'full_contact': ''}) |
|
173 | 'full_contact': ''}) | |
@@ -217,7 +217,7 b' class JournalController(BaseController):' | |||||
217 |
|
217 | |||
218 | repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, |
|
218 | repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list, | |
219 | admin=True) |
|
219 | admin=True) | |
220 | #data used to render the grid |
|
220 | # data used to render the grid | |
221 | c.data = repos_data |
|
221 | c.data = repos_data | |
222 |
|
222 | |||
223 | return render('journal/journal.html') |
|
223 | return render('journal/journal.html') |
@@ -391,7 +391,7 b' class PullrequestsController(BaseRepoCon' | |||||
391 | if pull_request.is_closed(): |
|
391 | if pull_request.is_closed(): | |
392 | raise HTTPForbidden() |
|
392 | raise HTTPForbidden() | |
393 | assert pull_request.other_repo.repo_name == repo_name |
|
393 | assert pull_request.other_repo.repo_name == repo_name | |
394 | #only owner or admin can update it |
|
394 | # only owner or admin can update it | |
395 | owner = pull_request.owner_id == request.authuser.user_id |
|
395 | owner = pull_request.owner_id == request.authuser.user_id | |
396 | repo_admin = h.HasRepoPermissionLevel('admin')(c.repo_name) |
|
396 | repo_admin = h.HasRepoPermissionLevel('admin')(c.repo_name) | |
397 | if not (h.HasPermissionAny('hg.admin')() or repo_admin or owner): |
|
397 | if not (h.HasPermissionAny('hg.admin')() or repo_admin or owner): | |
@@ -446,7 +446,7 b' class PullrequestsController(BaseRepoCon' | |||||
446 | @jsonify |
|
446 | @jsonify | |
447 | def delete(self, repo_name, pull_request_id): |
|
447 | def delete(self, repo_name, pull_request_id): | |
448 | pull_request = PullRequest.get_or_404(pull_request_id) |
|
448 | pull_request = PullRequest.get_or_404(pull_request_id) | |
449 | #only owner can delete it ! |
|
449 | # only owner can delete it ! | |
450 | if pull_request.owner_id == request.authuser.user_id: |
|
450 | if pull_request.owner_id == request.authuser.user_id: | |
451 | PullRequestModel().delete(pull_request) |
|
451 | PullRequestModel().delete(pull_request) | |
452 | Session().commit() |
|
452 | Session().commit() | |
@@ -596,7 +596,7 b' class PullrequestsController(BaseRepoCon' | |||||
596 | ignore_whitespace=ignore_whitespace, |
|
596 | ignore_whitespace=ignore_whitespace, | |
597 | context=line_context) |
|
597 | context=line_context) | |
598 | except ChangesetDoesNotExistError: |
|
598 | except ChangesetDoesNotExistError: | |
599 |
txtdiff = |
|
599 | txtdiff = _("The diff can't be shown - the PR revisions could not be found.") | |
600 | diff_processor = diffs.DiffProcessor(txtdiff or '', format='gitdiff', |
|
600 | diff_processor = diffs.DiffProcessor(txtdiff or '', format='gitdiff', | |
601 | diff_limit=diff_limit) |
|
601 | diff_limit=diff_limit) | |
602 | _parsed = diff_processor.prepare() |
|
602 | _parsed = diff_processor.prepare() | |
@@ -734,7 +734,7 b' class PullrequestsController(BaseRepoCon' | |||||
734 | def delete_comment(self, repo_name, comment_id): |
|
734 | def delete_comment(self, repo_name, comment_id): | |
735 | co = ChangesetComment.get(comment_id) |
|
735 | co = ChangesetComment.get(comment_id) | |
736 | if co.pull_request.is_closed(): |
|
736 | if co.pull_request.is_closed(): | |
737 | #don't allow deleting comments on closed pull request |
|
737 | # don't allow deleting comments on closed pull request | |
738 | raise HTTPForbidden() |
|
738 | raise HTTPForbidden() | |
739 |
|
739 | |||
740 | owner = co.author_id == request.authuser.user_id |
|
740 | owner = co.author_id == request.authuser.user_id |
@@ -17,6 +17,7 b' from kallithea.lib.base import BaseContr' | |||||
17 | from kallithea.controllers.error import ErrorController |
|
17 | from kallithea.controllers.error import ErrorController | |
18 | from tg import config |
|
18 | from tg import config | |
19 |
|
19 | |||
|
20 | ||||
20 | # This is the main Kallithea entry point; TurboGears will forward all requests |
|
21 | # This is the main Kallithea entry point; TurboGears will forward all requests | |
21 | # to an instance of 'controller.root.RootController' in the configured |
|
22 | # to an instance of 'controller.root.RootController' in the configured | |
22 | # 'application' module (set by app_cfg.py). Requests are forwarded to |
|
23 | # 'application' module (set by app_cfg.py). Requests are forwarded to |
@@ -149,7 +149,7 b' class AnnotateHtmlFormatter(HtmlFormatte' | |||||
149 | for i in range(fl, fl + lncount): |
|
149 | for i in range(fl, fl + lncount): | |
150 | if i % st == 0: |
|
150 | if i % st == 0: | |
151 | if aln: |
|
151 | if aln: | |
152 |
lines.append('<a href="#%s-%d">%*d</a>' |
|
152 | lines.append('<a href="#%s-%d">%*d</a>' | |
153 | % (la, i, mw, i)) |
|
153 | % (la, i, mw, i)) | |
154 | else: |
|
154 | else: | |
155 | lines.append('%*d' % (mw, i)) |
|
155 | lines.append('%*d' % (mw, i)) | |
@@ -158,7 +158,7 b' class AnnotateHtmlFormatter(HtmlFormatte' | |||||
158 | ls = '\n'.join(lines) |
|
158 | ls = '\n'.join(lines) | |
159 |
|
159 | |||
160 | # annotate_changesets = [tup[1] for tup in self.filenode.annotate] |
|
160 | # annotate_changesets = [tup[1] for tup in self.filenode.annotate] | |
161 |
# |
|
161 | # # TODO: not sure what that fixes | |
162 | # # If pygments cropped last lines break we need do that too |
|
162 | # # If pygments cropped last lines break we need do that too | |
163 | # ln_cs = len(annotate_changesets) |
|
163 | # ln_cs = len(annotate_changesets) | |
164 | # ln_ = len(ls.splitlines()) |
|
164 | # ln_ = len(ls.splitlines()) |
@@ -104,7 +104,7 b' def get_crypt_password(password):' | |||||
104 | import bcrypt |
|
104 | import bcrypt | |
105 | return bcrypt.hashpw(safe_str(password), bcrypt.gensalt(10)) |
|
105 | return bcrypt.hashpw(safe_str(password), bcrypt.gensalt(10)) | |
106 | else: |
|
106 | else: | |
107 |
raise Exception('Unknown or unsupported platform %s' |
|
107 | raise Exception('Unknown or unsupported platform %s' | |
108 | % __platform__) |
|
108 | % __platform__) | |
109 |
|
109 | |||
110 |
|
110 | |||
@@ -121,7 +121,7 b' def check_password(password, hashed):' | |||||
121 | return hashlib.sha256(password).hexdigest() == hashed |
|
121 | return hashlib.sha256(password).hexdigest() == hashed | |
122 | elif is_unix: |
|
122 | elif is_unix: | |
123 | import bcrypt |
|
123 | import bcrypt | |
124 |
print |
|
124 | print(safe_str(password), safe_str(hashed)) | |
125 | try: |
|
125 | try: | |
126 | return bcrypt.checkpw(safe_str(password), safe_str(hashed)) |
|
126 | return bcrypt.checkpw(safe_str(password), safe_str(hashed)) | |
127 | except ValueError as e: |
|
127 | except ValueError as e: | |
@@ -129,7 +129,7 b' def check_password(password, hashed):' | |||||
129 | log.error('error from bcrypt checking password: %s', e) |
|
129 | log.error('error from bcrypt checking password: %s', e) | |
130 | return False |
|
130 | return False | |
131 | else: |
|
131 | else: | |
132 |
raise Exception('Unknown or unsupported platform %s' |
|
132 | raise Exception('Unknown or unsupported platform %s' | |
133 | % __platform__) |
|
133 | % __platform__) | |
134 |
|
134 | |||
135 |
|
135 | |||
@@ -261,7 +261,7 b' def _cached_perms_data(user_id, user_is_' | |||||
261 | for gr, perms in _grouped: |
|
261 | for gr, perms in _grouped: | |
262 | # since user can be in multiple groups iterate over them and |
|
262 | # since user can be in multiple groups iterate over them and | |
263 | # select the lowest permissions first (more explicit) |
|
263 | # select the lowest permissions first (more explicit) | |
264 |
# |
|
264 | # TODO: do this^^ | |
265 | if not gr.inherit_default_permissions: |
|
265 | if not gr.inherit_default_permissions: | |
266 | # NEED TO IGNORE all configurable permissions and |
|
266 | # NEED TO IGNORE all configurable permissions and | |
267 | # replace them with explicitly set |
|
267 | # replace them with explicitly set | |
@@ -409,7 +409,7 b' def _cached_perms_data(user_id, user_is_' | |||||
409 | p = _choose_perm(p, cur_perm) |
|
409 | p = _choose_perm(p, cur_perm) | |
410 | permissions[UK][g_k] = p |
|
410 | permissions[UK][g_k] = p | |
411 |
|
411 | |||
412 | #user explicit permission for user groups |
|
412 | # user explicit permission for user groups | |
413 | user_user_groups_perms = Permission.get_default_user_group_perms(user_id) |
|
413 | user_user_groups_perms = Permission.get_default_user_group_perms(user_id) | |
414 | for perm in user_user_groups_perms: |
|
414 | for perm in user_user_groups_perms: | |
415 | u_k = perm.UserUserGroupToPerm.user_group.users_group_name |
|
415 | u_k = perm.UserUserGroupToPerm.user_group.users_group_name | |
@@ -437,7 +437,7 b' def allowed_api_access(controller_name, ' | |||||
437 | else: |
|
437 | else: | |
438 | msg = 'controller: %s is *NOT* in API whitelist' % (controller_name) |
|
438 | msg = 'controller: %s is *NOT* in API whitelist' % (controller_name) | |
439 | if api_key: |
|
439 | if api_key: | |
440 | #if we use API key and don't have access it's a warning |
|
440 | # if we use API key and don't have access it's a warning | |
441 | log.warning(msg) |
|
441 | log.warning(msg) | |
442 | else: |
|
442 | else: | |
443 | log.debug(msg) |
|
443 | log.debug(msg) | |
@@ -510,7 +510,7 b' class AuthUser(object):' | |||||
510 |
|
510 | |||
511 | # If user cannot be found, try falling back to anonymous. |
|
511 | # If user cannot be found, try falling back to anonymous. | |
512 | if not is_user_loaded: |
|
512 | if not is_user_loaded: | |
513 |
is_user_loaded = |
|
513 | is_user_loaded = self._fill_data(self._default_user) | |
514 |
|
514 | |||
515 | self.is_default_user = (self.user_id == self._default_user.user_id) |
|
515 | self.is_default_user = (self.user_id == self._default_user.user_id) | |
516 | self.is_anonymous = not is_user_loaded or self.is_default_user |
|
516 | self.is_anonymous = not is_user_loaded or self.is_default_user |
@@ -40,7 +40,7 b' class LazyFormencode(object):' | |||||
40 | from inspect import isfunction |
|
40 | from inspect import isfunction | |
41 | formencode_obj = self.formencode_obj |
|
41 | formencode_obj = self.formencode_obj | |
42 | if isfunction(formencode_obj): |
|
42 | if isfunction(formencode_obj): | |
43 | #case we wrap validators into functions |
|
43 | # case we wrap validators into functions | |
44 | formencode_obj = self.formencode_obj(*args, **kwargs) |
|
44 | formencode_obj = self.formencode_obj(*args, **kwargs) | |
45 | return formencode_obj(*self.args, **self.kwargs) |
|
45 | return formencode_obj(*self.args, **self.kwargs) | |
46 |
|
46 | |||
@@ -76,7 +76,6 b' class KallitheaAuthPluginBase(object):' | |||||
76 | #log.debug('Initializing lazy formencode object: %s', obj) |
|
76 | #log.debug('Initializing lazy formencode object: %s', obj) | |
77 | return LazyFormencode(obj, *args, **kwargs) |
|
77 | return LazyFormencode(obj, *args, **kwargs) | |
78 |
|
78 | |||
79 |
|
||||
80 | class ProxyGet(object): |
|
79 | class ProxyGet(object): | |
81 | def __getattribute__(self, name): |
|
80 | def __getattribute__(self, name): | |
82 | return LazyCaller(name) |
|
81 | return LazyCaller(name) | |
@@ -420,6 +419,7 b' def authenticate(username, password, env' | |||||
420 | username, module) |
|
419 | username, module) | |
421 | return None |
|
420 | return None | |
422 |
|
421 | |||
|
422 | ||||
423 | def get_managed_fields(user): |
|
423 | def get_managed_fields(user): | |
424 | """return list of fields that are managed by the user's auth source, usually some of |
|
424 | """return list of fields that are managed by the user's auth source, usually some of | |
425 | 'username', 'firstname', 'lastname', 'email', 'active', 'password' |
|
425 | 'username', 'firstname', 'lastname', 'email', 'active', 'password' |
@@ -290,7 +290,7 b' class BaseVCSController(object):' | |||||
290 | log.error(traceback.format_exc()) |
|
290 | log.error(traceback.format_exc()) | |
291 | return None, webob.exc.HTTPInternalServerError() |
|
291 | return None, webob.exc.HTTPInternalServerError() | |
292 |
|
292 | |||
293 | #check permissions for this repository |
|
293 | # check permissions for this repository | |
294 | perm = self._check_permission(action, user, repo_name, ip_addr) |
|
294 | perm = self._check_permission(action, user, repo_name, ip_addr) | |
295 | if not perm: |
|
295 | if not perm: | |
296 | return None, webob.exc.HTTPForbidden() |
|
296 | return None, webob.exc.HTTPForbidden() | |
@@ -522,7 +522,7 b' class BaseController(TGController):' | |||||
522 |
|
522 | |||
523 | self._basic_security_checks() |
|
523 | self._basic_security_checks() | |
524 |
|
524 | |||
525 | #set globals for auth user |
|
525 | # set globals for auth user | |
526 |
|
526 | |||
527 | bearer_token = None |
|
527 | bearer_token = None | |
528 | try: |
|
528 | try: |
@@ -220,8 +220,8 b' def _params_from_query(query):' | |||||
220 |
|
220 | |||
221 | """ |
|
221 | """ | |
222 | v = [] |
|
222 | v = [] | |
|
223 | ||||
223 | def visit_bindparam(bind): |
|
224 | def visit_bindparam(bind): | |
224 |
|
||||
225 | if bind.key in query._params: |
|
225 | if bind.key in query._params: | |
226 | value = query._params[bind.key] |
|
226 | value = query._params[bind.key] | |
227 | elif bind.callable: |
|
227 | elif bind.callable: | |
@@ -234,7 +234,7 b' def _params_from_query(query):' | |||||
234 |
|
234 | |||
235 | v.append(value) |
|
235 | v.append(value) | |
236 | if query._criterion is not None: |
|
236 | if query._criterion is not None: | |
237 | visitors.traverse(query._criterion, {}, {'bindparam':visit_bindparam}) |
|
237 | visitors.traverse(query._criterion, {}, {'bindparam': visit_bindparam}) | |
238 | for f in query._from_obj: |
|
238 | for f in query._from_obj: | |
239 | visitors.traverse(f, {}, {'bindparam':visit_bindparam}) |
|
239 | visitors.traverse(f, {}, {'bindparam': visit_bindparam}) | |
240 | return v |
|
240 | return v |
@@ -74,6 +74,7 b' def task(f_org):' | |||||
74 | f_async.__name__ = f_org.__name__ |
|
74 | f_async.__name__ = f_org.__name__ | |
75 | from kallithea.lib import celerypylons |
|
75 | from kallithea.lib import celerypylons | |
76 | runner = celerypylons.task(ignore_result=True)(f_async) |
|
76 | runner = celerypylons.task(ignore_result=True)(f_async) | |
|
77 | ||||
77 | def f_wrapped(*args, **kwargs): |
|
78 | def f_wrapped(*args, **kwargs): | |
78 | t = runner.apply_async(args=args, kwargs=kwargs) |
|
79 | t = runner.apply_async(args=args, kwargs=kwargs) | |
79 | log.info('executing task %s in async mode - id %s', f_org, t.task_id) |
|
80 | log.info('executing task %s in async mode - id %s', f_org, t.task_id) |
@@ -180,7 +180,7 b' def get_commits_stats(repo_name, ts_min_' | |||||
180 | "schema": ["commits"], |
|
180 | "schema": ["commits"], | |
181 | } |
|
181 | } | |
182 |
|
182 | |||
183 | #gather all data by day |
|
183 | # gather all data by day | |
184 | if k in commits_by_day_aggregate: |
|
184 | if k in commits_by_day_aggregate: | |
185 | commits_by_day_aggregate[k] += 1 |
|
185 | commits_by_day_aggregate[k] += 1 | |
186 | else: |
|
186 | else: | |
@@ -321,6 +321,7 b' def send_email(recipients, subject, body' | |||||
321 | return False |
|
321 | return False | |
322 | return True |
|
322 | return True | |
323 |
|
323 | |||
|
324 | ||||
324 | @celerylib.task |
|
325 | @celerylib.task | |
325 | @celerylib.dbsession |
|
326 | @celerylib.dbsession | |
326 | def create_repo(form_data, cur_user): |
|
327 | def create_repo(form_data, cur_user): | |
@@ -471,7 +472,7 b' def create_repo_fork(form_data, cur_user' | |||||
471 | except Exception as e: |
|
472 | except Exception as e: | |
472 | log.warning('Exception %s occurred when forking repository, ' |
|
473 | log.warning('Exception %s occurred when forking repository, ' | |
473 | 'doing cleanup...' % e) |
|
474 | 'doing cleanup...' % e) | |
474 | #rollback things manually ! |
|
475 | # rollback things manually ! | |
475 | repo = Repository.get_by_repo_name(repo_name_full) |
|
476 | repo = Repository.get_by_repo_name(repo_name_full) | |
476 | if repo: |
|
477 | if repo: | |
477 | Repository.delete(repo.repo_id) |
|
478 | Repository.delete(repo.repo_id) |
@@ -27,7 +27,9 b' def celery_config(config):' | |||||
27 | # Verify .ini file configuration has been loaded |
|
27 | # Verify .ini file configuration has been loaded | |
28 | assert config['celery.imports'] == 'kallithea.lib.celerylib.tasks', 'Kallithea Celery configuration has not been loaded' |
|
28 | assert config['celery.imports'] == 'kallithea.lib.celerylib.tasks', 'Kallithea Celery configuration has not been loaded' | |
29 |
|
29 | |||
30 |
class CeleryConfig(object): |
|
30 | class CeleryConfig(object): | |
|
31 | pass | |||
|
32 | ||||
31 | celery_config = CeleryConfig() |
|
33 | celery_config = CeleryConfig() | |
32 |
|
34 | |||
33 | PREFIXES = """ADMINS BROKER CASSANDRA CELERYBEAT CELERYD CELERYMON CELERY EMAIL SERVER""".split() |
|
35 | PREFIXES = """ADMINS BROKER CASSANDRA CELERYBEAT CELERYD CELERYMON CELERY EMAIL SERVER""".split() |
@@ -55,6 +55,7 b' else:' | |||||
55 |
|
55 | |||
56 | # Python Software Foundation License |
|
56 | # Python Software Foundation License | |
57 |
|
57 | |||
|
58 | ||||
58 | # XXX: it feels like using the class with "is" and "is not" instead of "==" and |
|
59 | # XXX: it feels like using the class with "is" and "is not" instead of "==" and | |
59 | # "!=" should be faster. |
|
60 | # "!=" should be faster. | |
60 | class _Nil(object): |
|
61 | class _Nil(object): | |
@@ -74,6 +75,7 b' class _Nil(object):' | |||||
74 | else: |
|
75 | else: | |
75 | return NotImplemented |
|
76 | return NotImplemented | |
76 |
|
77 | |||
|
78 | ||||
77 | _nil = _Nil() |
|
79 | _nil = _Nil() | |
78 |
|
80 | |||
79 |
|
81 |
@@ -84,7 +84,7 b' class DbManage(object):' | |||||
84 | if SESSION: |
|
84 | if SESSION: | |
85 | self.sa = SESSION |
|
85 | self.sa = SESSION | |
86 | else: |
|
86 | else: | |
87 | #init new sessions |
|
87 | # init new sessions | |
88 | engine = create_engine(self.dburi) |
|
88 | engine = create_engine(self.dburi) | |
89 | init_model(engine) |
|
89 | init_model(engine) | |
90 | self.sa = Session() |
|
90 | self.sa = Session() | |
@@ -205,7 +205,7 b' class DbManage(object):' | |||||
205 | if password is None: |
|
205 | if password is None: | |
206 | password = get_password() |
|
206 | password = get_password() | |
207 | if not password: |
|
207 | if not password: | |
208 | #second try |
|
208 | # second try | |
209 | password = get_password() |
|
209 | password = get_password() | |
210 | if not password: |
|
210 | if not password: | |
211 | sys.exit() |
|
211 | sys.exit() | |
@@ -234,7 +234,7 b' class DbManage(object):' | |||||
234 | Creates ui settings, fills out hooks |
|
234 | Creates ui settings, fills out hooks | |
235 | """ |
|
235 | """ | |
236 |
|
236 | |||
237 | #HOOKS |
|
237 | # HOOKS | |
238 | hooks1_key = Ui.HOOK_UPDATE |
|
238 | hooks1_key = Ui.HOOK_UPDATE | |
239 | hooks1_ = Ui.query() \ |
|
239 | hooks1_ = Ui.query() \ | |
240 | .filter(Ui.ui_key == hooks1_key).scalar() |
|
240 | .filter(Ui.ui_key == hooks1_key).scalar() |
@@ -1,5 +1,6 b'' | |||||
1 | from gearbox.command import Command |
|
1 | from gearbox.command import Command | |
2 |
|
2 | |||
|
3 | ||||
3 | class UpgradeDb(Command): |
|
4 | class UpgradeDb(Command): | |
4 | '''(removed)''' |
|
5 | '''(removed)''' | |
5 |
|
6 |
@@ -130,6 +130,7 b' def get_gitdiff(filenode_old, filenode_n' | |||||
130 | ignore_whitespace, context) |
|
130 | ignore_whitespace, context) | |
131 | return vcs_gitdiff |
|
131 | return vcs_gitdiff | |
132 |
|
132 | |||
|
133 | ||||
133 | NEW_FILENODE = 1 |
|
134 | NEW_FILENODE = 1 | |
134 | DEL_FILENODE = 2 |
|
135 | DEL_FILENODE = 2 | |
135 | MOD_FILENODE = 3 |
|
136 | MOD_FILENODE = 3 | |
@@ -205,7 +206,6 b' class DiffProcessor(object):' | |||||
205 |
|
206 | |||
206 | _escape_re = re.compile(r'(&)|(<)|(>)|(\t)|(\r)|(?<=.)( \n| $)') |
|
207 | _escape_re = re.compile(r'(&)|(<)|(>)|(\t)|(\r)|(?<=.)( \n| $)') | |
207 |
|
208 | |||
208 |
|
||||
209 | def __init__(self, diff, vcs='hg', format='gitdiff', diff_limit=None): |
|
209 | def __init__(self, diff, vcs='hg', format='gitdiff', diff_limit=None): | |
210 | """ |
|
210 | """ | |
211 | :param diff: a text in diff format |
|
211 | :param diff: a text in diff format | |
@@ -375,7 +375,7 b' class DiffProcessor(object):' | |||||
375 |
|
375 | |||
376 | def _clean_line(self, line, command): |
|
376 | def _clean_line(self, line, command): | |
377 | if command in ['+', '-', ' ']: |
|
377 | if command in ['+', '-', ' ']: | |
378 | #only modify the line if it's actually a diff thing |
|
378 | # only modify the line if it's actually a diff thing | |
379 | line = line[1:] |
|
379 | line = line[1:] | |
380 | return line |
|
380 | return line | |
381 |
|
381 | |||
@@ -383,7 +383,7 b' class DiffProcessor(object):' | |||||
383 | _files = [] |
|
383 | _files = [] | |
384 | diff_container = lambda arg: arg |
|
384 | diff_container = lambda arg: arg | |
385 |
|
385 | |||
386 |
# |
|
386 | # split the diff in chunks of separate --git a/file b/file chunks | |
387 | for raw_diff in ('\n' + self._diff).split('\ndiff --git')[1:]: |
|
387 | for raw_diff in ('\n' + self._diff).split('\ndiff --git')[1:]: | |
388 | head, diff = self._get_header(raw_diff) |
|
388 | head, diff = self._get_header(raw_diff) | |
389 |
|
389 |
@@ -22,6 +22,7 b' def _is_tz_aware(value):' | |||||
22 | return (value.tzinfo is not None |
|
22 | return (value.tzinfo is not None | |
23 | and value.tzinfo.utcoffset(value) is not None) |
|
23 | and value.tzinfo.utcoffset(value) is not None) | |
24 |
|
24 | |||
|
25 | ||||
25 | def _obj_dump(obj): |
|
26 | def _obj_dump(obj): | |
26 | """ |
|
27 | """ | |
27 | Custom function for dumping objects to JSON, if obj has __json__ attribute |
|
28 | Custom function for dumping objects to JSON, if obj has __json__ attribute |
@@ -19,6 +19,7 b' It allows to have a shared codebase for ' | |||||
19 |
|
19 | |||
20 | nullrev = -1 |
|
20 | nullrev = -1 | |
21 |
|
21 | |||
|
22 | ||||
22 | def _first_known_ancestors(parentrev_func, minrev, knownrevs, head): |
|
23 | def _first_known_ancestors(parentrev_func, minrev, knownrevs, head): | |
23 | """ |
|
24 | """ | |
24 | Return the apparent parents of the head revision in a filtered DAG. |
|
25 | Return the apparent parents of the head revision in a filtered DAG. | |
@@ -45,6 +46,7 b' def _first_known_ancestors(parentrev_fun' | |||||
45 | seen.add(r) |
|
46 | seen.add(r) | |
46 | return ancestors |
|
47 | return ancestors | |
47 |
|
48 | |||
|
49 | ||||
48 | def graph_data(repo, revs): |
|
50 | def graph_data(repo, revs): | |
49 | """Return a DAG with colored edge information for revs |
|
51 | """Return a DAG with colored edge information for revs | |
50 |
|
52 | |||
@@ -61,6 +63,7 b' def graph_data(repo, revs):' | |||||
61 | dag = _dagwalker(repo, revs) |
|
63 | dag = _dagwalker(repo, revs) | |
62 | return list(_colored(repo, dag)) |
|
64 | return list(_colored(repo, dag)) | |
63 |
|
65 | |||
|
66 | ||||
64 | def _dagwalker(repo, revs): |
|
67 | def _dagwalker(repo, revs): | |
65 | """Iterate over revs, yielding revs (highest first) and parents to show in the graph.""" |
|
68 | """Iterate over revs, yielding revs (highest first) and parents to show in the graph.""" | |
66 | if not revs: |
|
69 | if not revs: | |
@@ -102,6 +105,7 b' def _colored(repo, dag):' | |||||
102 | parents. |
|
105 | parents. | |
103 | """ |
|
106 | """ | |
104 | branch_cache = {} |
|
107 | branch_cache = {} | |
|
108 | ||||
105 | def branch(rev): |
|
109 | def branch(rev): | |
106 | """Return branch for rev, using cache for efficiency. |
|
110 | """Return branch for rev, using cache for efficiency. | |
107 | For Mercurial, always return the named branch name (which may be 'default'). |
|
111 | For Mercurial, always return the named branch name (which may be 'default'). |
@@ -64,6 +64,7 b' def canonical_url(*args, **kargs):' | |||||
64 | kargs['qualified'] = True |
|
64 | kargs['qualified'] = True | |
65 | return url(*args, **kargs) |
|
65 | return url(*args, **kargs) | |
66 |
|
66 | |||
|
67 | ||||
67 | def canonical_hostname(): |
|
68 | def canonical_hostname(): | |
68 | '''Return canonical hostname of system''' |
|
69 | '''Return canonical hostname of system''' | |
69 | from kallithea import CONFIG |
|
70 | from kallithea import CONFIG | |
@@ -74,6 +75,7 b' def canonical_hostname():' | |||||
74 | parts = url('home', qualified=True).split('://', 1) |
|
75 | parts = url('home', qualified=True).split('://', 1) | |
75 | return parts[1].split('/', 1)[0] |
|
76 | return parts[1].split('/', 1)[0] | |
76 |
|
77 | |||
|
78 | ||||
77 | def html_escape(s): |
|
79 | def html_escape(s): | |
78 | """Return string with all html escaped. |
|
80 | """Return string with all html escaped. | |
79 | This is also safe for javascript in html but not necessarily correct. |
|
81 | This is also safe for javascript in html but not necessarily correct. | |
@@ -116,6 +118,7 b' def js(value):' | |||||
116 | .replace('>', r'\x3e') |
|
118 | .replace('>', r'\x3e') | |
117 | ) |
|
119 | ) | |
118 |
|
120 | |||
|
121 | ||||
119 | def jshtml(val): |
|
122 | def jshtml(val): | |
120 | """HTML escapes a string value, then converts the resulting string |
|
123 | """HTML escapes a string value, then converts the resulting string | |
121 | to its corresponding JavaScript representation (see `js`). |
|
124 | to its corresponding JavaScript representation (see `js`). | |
@@ -150,6 +153,7 b' def _reset(name, value=None, id=NotGiven' | |||||
150 | convert_boolean_attrs(attrs, ["disabled"]) |
|
153 | convert_boolean_attrs(attrs, ["disabled"]) | |
151 | return HTML.input(**attrs) |
|
154 | return HTML.input(**attrs) | |
152 |
|
155 | |||
|
156 | ||||
153 | reset = _reset |
|
157 | reset = _reset | |
154 | safeid = _make_safe_id_component |
|
158 | safeid = _make_safe_id_component | |
155 |
|
159 | |||
@@ -190,6 +194,7 b' class _FilesBreadCrumbs(object):' | |||||
190 |
|
194 | |||
191 | return literal('/'.join(url_l)) |
|
195 | return literal('/'.join(url_l)) | |
192 |
|
196 | |||
|
197 | ||||
193 | files_breadcrumbs = _FilesBreadCrumbs() |
|
198 | files_breadcrumbs = _FilesBreadCrumbs() | |
194 |
|
199 | |||
195 |
|
200 | |||
@@ -272,6 +277,7 b' class CodeHtmlFormatter(HtmlFormatter):' | |||||
272 |
|
277 | |||
273 | _whitespace_re = re.compile(r'(\t)|( )(?=\n|</div>)') |
|
278 | _whitespace_re = re.compile(r'(\t)|( )(?=\n|</div>)') | |
274 |
|
279 | |||
|
280 | ||||
275 | def _markup_whitespace(m): |
|
281 | def _markup_whitespace(m): | |
276 | groups = m.groups() |
|
282 | groups = m.groups() | |
277 | if groups[0]: |
|
283 | if groups[0]: | |
@@ -279,9 +285,11 b' def _markup_whitespace(m):' | |||||
279 | if groups[1]: |
|
285 | if groups[1]: | |
280 | return ' <i></i>' |
|
286 | return ' <i></i>' | |
281 |
|
287 | |||
|
288 | ||||
282 | def markup_whitespace(s): |
|
289 | def markup_whitespace(s): | |
283 | return _whitespace_re.sub(_markup_whitespace, s) |
|
290 | return _whitespace_re.sub(_markup_whitespace, s) | |
284 |
|
291 | |||
|
292 | ||||
285 | def pygmentize(filenode, **kwargs): |
|
293 | def pygmentize(filenode, **kwargs): | |
286 | """ |
|
294 | """ | |
287 | pygmentize function using pygments |
|
295 | pygmentize function using pygments | |
@@ -399,6 +407,7 b' class _Message(object):' | |||||
399 | def __html__(self): |
|
407 | def __html__(self): | |
400 | return escape(safe_unicode(self.message)) |
|
408 | return escape(safe_unicode(self.message)) | |
401 |
|
409 | |||
|
410 | ||||
402 | class Flash(_Flash): |
|
411 | class Flash(_Flash): | |
403 |
|
412 | |||
404 | def __call__(self, message, category=None, ignore_duplicate=False, logf=None): |
|
413 | def __call__(self, message, category=None, ignore_duplicate=False, logf=None): | |
@@ -430,6 +439,7 b' class Flash(_Flash):' | |||||
430 | session.save() |
|
439 | session.save() | |
431 | return [_Message(*m) for m in messages] |
|
440 | return [_Message(*m) for m in messages] | |
432 |
|
441 | |||
|
442 | ||||
433 | flash = Flash() |
|
443 | flash = Flash() | |
434 |
|
444 | |||
435 | #============================================================================== |
|
445 | #============================================================================== | |
@@ -438,7 +448,7 b' flash = Flash()' | |||||
438 | from kallithea.lib.vcs.utils import author_name, author_email |
|
448 | from kallithea.lib.vcs.utils import author_name, author_email | |
439 | from kallithea.lib.utils2 import credentials_filter, age as _age |
|
449 | from kallithea.lib.utils2 import credentials_filter, age as _age | |
440 |
|
450 | |||
441 |
age = lambda |
|
451 | age = lambda x, y=False: _age(x, y) | |
442 | capitalize = lambda x: x.capitalize() |
|
452 | capitalize = lambda x: x.capitalize() | |
443 | email = author_email |
|
453 | email = author_email | |
444 | short_id = lambda x: x[:12] |
|
454 | short_id = lambda x: x[:12] | |
@@ -499,6 +509,7 b' def user_or_none(author):' | |||||
499 | return User.get_by_email(email, cache=True) # cache will only use sql_cache_short |
|
509 | return User.get_by_email(email, cache=True) # cache will only use sql_cache_short | |
500 | return None |
|
510 | return None | |
501 |
|
511 | |||
|
512 | ||||
502 | def email_or_none(author): |
|
513 | def email_or_none(author): | |
503 | """Try to match email part of VCS committer string with a local user. |
|
514 | """Try to match email part of VCS committer string with a local user. | |
504 | Return primary email of user, email part of the specified author name, or None.""" |
|
515 | Return primary email of user, email part of the specified author name, or None.""" | |
@@ -516,6 +527,7 b' def email_or_none(author):' | |||||
516 | # No valid email, not a valid user in the system, none! |
|
527 | # No valid email, not a valid user in the system, none! | |
517 | return None |
|
528 | return None | |
518 |
|
529 | |||
|
530 | ||||
519 | def person(author, show_attr="username"): |
|
531 | def person(author, show_attr="username"): | |
520 | """Find the user identified by 'author', return one of the users attributes, |
|
532 | """Find the user identified by 'author', return one of the users attributes, | |
521 | default to the username attribute, None if there is no user""" |
|
533 | default to the username attribute, None if there is no user""" | |
@@ -540,7 +552,7 b' def person_by_id(id_, show_attr="usernam' | |||||
540 | # attr to return from fetched user |
|
552 | # attr to return from fetched user | |
541 | person_getter = lambda usr: getattr(usr, show_attr) |
|
553 | person_getter = lambda usr: getattr(usr, show_attr) | |
542 |
|
554 | |||
543 | #maybe it's an ID ? |
|
555 | # maybe it's an ID ? | |
544 | if str(id_).isdigit() or isinstance(id_, int): |
|
556 | if str(id_).isdigit() or isinstance(id_, int): | |
545 | id_ = int(id_) |
|
557 | id_ = int(id_) | |
546 | user = User.get(id_) |
|
558 | user = User.get(id_) | |
@@ -614,7 +626,7 b' def action_parser(user_log, feed=False, ' | |||||
614 | if parse_cs: |
|
626 | if parse_cs: | |
615 | return link_to(lbl, url_, title=title_, **{'data-toggle': 'tooltip'}) |
|
627 | return link_to(lbl, url_, title=title_, **{'data-toggle': 'tooltip'}) | |
616 | return link_to(lbl, url_, class_='lazy-cs' if lazy_cs else '', |
|
628 | return link_to(lbl, url_, class_='lazy-cs' if lazy_cs else '', | |
617 | **{'data-raw_id':rev.raw_id, 'data-repo_name':repo_name}) |
|
629 | **{'data-raw_id': rev.raw_id, 'data-repo_name': repo_name}) | |
618 |
|
630 | |||
619 | def _get_op(rev_txt): |
|
631 | def _get_op(rev_txt): | |
620 | _op = None |
|
632 | _op = None | |
@@ -848,6 +860,7 b" def gravatar_div(email_address, cls='', " | |||||
848 | (''.join(attributes), |
|
860 | (''.join(attributes), | |
849 | gravatar(email_address, cls=cls, size=size))) |
|
861 | gravatar(email_address, cls=cls, size=size))) | |
850 |
|
862 | |||
|
863 | ||||
851 | def gravatar(email_address, cls='', size=30): |
|
864 | def gravatar(email_address, cls='', size=30): | |
852 | """return html element of the gravatar |
|
865 | """return html element of the gravatar | |
853 |
|
866 | |||
@@ -875,6 +888,7 b" def gravatar(email_address, cls='', size" | |||||
875 |
|
888 | |||
876 | return literal(html) |
|
889 | return literal(html) | |
877 |
|
890 | |||
|
891 | ||||
878 | def gravatar_url(email_address, size=30, default=''): |
|
892 | def gravatar_url(email_address, size=30, default=''): | |
879 | # doh, we need to re-import those to mock it later |
|
893 | # doh, we need to re-import those to mock it later | |
880 | from kallithea.config.routing import url |
|
894 | from kallithea.config.routing import url | |
@@ -931,7 +945,7 b' def fancy_file_stats(stats):' | |||||
931 | width = 100 |
|
945 | width = 100 | |
932 |
|
946 | |||
933 | if stats['binary']: |
|
947 | if stats['binary']: | |
934 | #binary mode |
|
948 | # binary mode | |
935 | lbl = '' |
|
949 | lbl = '' | |
936 | bin_op = 1 |
|
950 | bin_op = 1 | |
937 |
|
951 | |||
@@ -951,7 +965,7 b' def fancy_file_stats(stats):' | |||||
951 | lbl += _('rename') |
|
965 | lbl += _('rename') | |
952 | bin_op = RENAMED_FILENODE |
|
966 | bin_op = RENAMED_FILENODE | |
953 |
|
967 | |||
954 | #chmod can go with other operations |
|
968 | # chmod can go with other operations | |
955 | if CHMOD_FILENODE in stats['ops']: |
|
969 | if CHMOD_FILENODE in stats['ops']: | |
956 | _org_lbl = _('chmod') |
|
970 | _org_lbl = _('chmod') | |
957 | lbl += _org_lbl if lbl.endswith('+') else '+%s' % _org_lbl |
|
971 | lbl += _org_lbl if lbl.endswith('+') else '+%s' % _org_lbl | |
@@ -970,7 +984,7 b' def fancy_file_stats(stats):' | |||||
970 | p_sum = a_p + d_p |
|
984 | p_sum = a_p + d_p | |
971 |
|
985 | |||
972 | if p_sum > width: |
|
986 | if p_sum > width: | |
973 | #adjust the percentage to be == 100% since we adjusted to 9 |
|
987 | # adjust the percentage to be == 100% since we adjusted to 9 | |
974 | if a_p > d_p: |
|
988 | if a_p > d_p: | |
975 | a_p = a_p - (p_sum - width) |
|
989 | a_p = a_p - (p_sum - width) | |
976 | else: |
|
990 | else: | |
@@ -1013,7 +1027,6 b' def fancy_file_stats(stats):' | |||||
1013 | re.VERBOSE | re.MULTILINE | re.IGNORECASE) |
|
1027 | re.VERBOSE | re.MULTILINE | re.IGNORECASE) | |
1014 |
|
1028 | |||
1015 |
|
1029 | |||
1016 |
|
||||
1017 | def urlify_text(s, repo_name=None, link_=None, truncate=None, stylize=False, truncatef=truncate): |
|
1030 | def urlify_text(s, repo_name=None, link_=None, truncate=None, stylize=False, truncatef=truncate): | |
1018 | """ |
|
1031 | """ | |
1019 | Parses given text message and make literal html with markup. |
|
1032 | Parses given text message and make literal html with markup. | |
@@ -1131,6 +1144,7 b' def urlify_issues(newtext, repo_name):' | |||||
1131 |
|
1144 | |||
1132 | # Wrap tmp_urlify_issues_f with substitution of this pattern, while making sure all loop variables (and compiled regexpes) are bound |
|
1145 | # Wrap tmp_urlify_issues_f with substitution of this pattern, while making sure all loop variables (and compiled regexpes) are bound | |
1133 | issue_re = re.compile(issue_pat) |
|
1146 | issue_re = re.compile(issue_pat) | |
|
1147 | ||||
1134 | def issues_replace(match_obj, |
|
1148 | def issues_replace(match_obj, | |
1135 | issue_server_link=issue_server_link, issue_prefix=issue_prefix): |
|
1149 | issue_server_link=issue_server_link, issue_prefix=issue_prefix): | |
1136 | leadingspace = ' ' if match_obj.group().startswith(' ') else '' |
|
1150 | leadingspace = ' ' if match_obj.group().startswith(' ') else '' | |
@@ -1174,6 +1188,7 b' def short_ref(ref_type, ref_name):' | |||||
1174 | return short_id(ref_name) |
|
1188 | return short_id(ref_name) | |
1175 | return ref_name |
|
1189 | return ref_name | |
1176 |
|
1190 | |||
|
1191 | ||||
1177 | def link_to_ref(repo_name, ref_type, ref_name, rev=None): |
|
1192 | def link_to_ref(repo_name, ref_type, ref_name, rev=None): | |
1178 | """ |
|
1193 | """ | |
1179 | Return full markup for a href to changeset_home for a changeset. |
|
1194 | Return full markup for a href to changeset_home for a changeset. | |
@@ -1191,6 +1206,7 b' def link_to_ref(repo_name, ref_type, ref' | |||||
1191 | l = literal('%s (%s)' % (l, link_to(short_id(rev), url('changeset_home', repo_name=repo_name, revision=rev)))) |
|
1206 | l = literal('%s (%s)' % (l, link_to(short_id(rev), url('changeset_home', repo_name=repo_name, revision=rev)))) | |
1192 | return l |
|
1207 | return l | |
1193 |
|
1208 | |||
|
1209 | ||||
1194 | def changeset_status(repo, revision): |
|
1210 | def changeset_status(repo, revision): | |
1195 | from kallithea.model.changeset_status import ChangesetStatusModel |
|
1211 | from kallithea.model.changeset_status import ChangesetStatusModel | |
1196 | return ChangesetStatusModel().get_status(repo, revision) |
|
1212 | return ChangesetStatusModel().get_status(repo, revision) |
@@ -98,7 +98,7 b' def pre_push(ui, repo, **kwargs):' | |||||
98 | # on that proper return code is server to client |
|
98 | # on that proper return code is server to client | |
99 | _http_ret = HTTPLockedRC(ex.repository, locked_by) |
|
99 | _http_ret = HTTPLockedRC(ex.repository, locked_by) | |
100 | if str(_http_ret.code).startswith('2'): |
|
100 | if str(_http_ret.code).startswith('2'): | |
101 | #2xx Codes don't raise exceptions |
|
101 | # 2xx Codes don't raise exceptions | |
102 | ui.status(safe_str(_http_ret.title)) |
|
102 | ui.status(safe_str(_http_ret.title)) | |
103 | else: |
|
103 | else: | |
104 | raise _http_ret |
|
104 | raise _http_ret | |
@@ -113,7 +113,7 b' def pre_pull(ui, repo, **kwargs):' | |||||
113 | # on that proper return code is server to client |
|
113 | # on that proper return code is server to client | |
114 | _http_ret = HTTPLockedRC(ex.repository, locked_by) |
|
114 | _http_ret = HTTPLockedRC(ex.repository, locked_by) | |
115 | if str(_http_ret.code).startswith('2'): |
|
115 | if str(_http_ret.code).startswith('2'): | |
116 | #2xx Codes don't raise exceptions |
|
116 | # 2xx Codes don't raise exceptions | |
117 | ui.status(safe_str(_http_ret.title)) |
|
117 | ui.status(safe_str(_http_ret.title)) | |
118 | else: |
|
118 | else: | |
119 | raise _http_ret |
|
119 | raise _http_ret | |
@@ -148,7 +148,7 b' def log_pull_action(ui, repo, **kwargs):' | |||||
148 | locked_by = User.get(ex.locked_by[0]).username |
|
148 | locked_by = User.get(ex.locked_by[0]).username | |
149 | _http_ret = HTTPLockedRC(ex.repository, locked_by) |
|
149 | _http_ret = HTTPLockedRC(ex.repository, locked_by) | |
150 | if str(_http_ret.code).startswith('2'): |
|
150 | if str(_http_ret.code).startswith('2'): | |
151 | #2xx Codes don't raise exceptions |
|
151 | # 2xx Codes don't raise exceptions | |
152 | ui.status(safe_str(_http_ret.title)) |
|
152 | ui.status(safe_str(_http_ret.title)) | |
153 | return 0 |
|
153 | return 0 | |
154 |
|
154 | |||
@@ -203,7 +203,7 b' def log_push_action(ui, repo, **kwargs):' | |||||
203 | locked_by = User.get(ex.locked_by[0]).username |
|
203 | locked_by = User.get(ex.locked_by[0]).username | |
204 | _http_ret = HTTPLockedRC(ex.repository, locked_by) |
|
204 | _http_ret = HTTPLockedRC(ex.repository, locked_by) | |
205 | if str(_http_ret.code).startswith('2'): |
|
205 | if str(_http_ret.code).startswith('2'): | |
206 | #2xx Codes don't raise exceptions |
|
206 | # 2xx Codes don't raise exceptions | |
207 | ui.status(safe_str(_http_ret.title)) |
|
207 | ui.status(safe_str(_http_ret.title)) | |
208 |
|
208 | |||
209 | return 0 |
|
209 | return 0 | |
@@ -446,7 +446,7 b' def handle_git_receive(repo_path, revs, ' | |||||
446 | repo._repo.refs.set_symbolic_ref('HEAD', |
|
446 | repo._repo.refs.set_symbolic_ref('HEAD', | |
447 | 'refs/heads/%s' % push_ref['name']) |
|
447 | 'refs/heads/%s' % push_ref['name']) | |
448 |
|
448 | |||
449 | cmd = ['for-each-ref', '--format=%(refname)','refs/heads/*'] |
|
449 | cmd = ['for-each-ref', '--format=%(refname)', 'refs/heads/*'] | |
450 | heads = repo.run_git_command(cmd)[0] |
|
450 | heads = repo.run_git_command(cmd)[0] | |
451 | cmd = ['log', push_ref['new_rev'], |
|
451 | cmd = ['log', push_ref['new_rev'], | |
452 | '--reverse', '--pretty=format:%H', '--not'] |
|
452 | '--reverse', '--pretty=format:%H', '--not'] | |
@@ -456,7 +456,7 b' def handle_git_receive(repo_path, revs, ' | |||||
456 | git_revs += repo.run_git_command(cmd)[0].splitlines() |
|
456 | git_revs += repo.run_git_command(cmd)[0].splitlines() | |
457 |
|
457 | |||
458 | elif push_ref['new_rev'] == EmptyChangeset().raw_id: |
|
458 | elif push_ref['new_rev'] == EmptyChangeset().raw_id: | |
459 | #delete branch case |
|
459 | # delete branch case | |
460 | git_revs += ['delete_branch=>%s' % push_ref['name']] |
|
460 | git_revs += ['delete_branch=>%s' % push_ref['name']] | |
461 | else: |
|
461 | else: | |
462 | cmd = ['log', '%(old_rev)s..%(new_rev)s' % push_ref, |
|
462 | cmd = ['log', '%(old_rev)s..%(new_rev)s' % push_ref, |
@@ -50,7 +50,7 b' ANALYZER = RegexTokenizer(expression=r"\\' | |||||
50 | # - avoid removing "stop words" from text |
|
50 | # - avoid removing "stop words" from text | |
51 | # - search case-insensitively |
|
51 | # - search case-insensitively | |
52 | # |
|
52 | # | |
53 |
EMAILADDRANALYZER = |
|
53 | EMAILADDRANALYZER = RegexTokenizer() | LowercaseFilter() | |
54 |
|
54 | |||
55 | # CUSTOM ANALYZER raw-string + lowercase filter |
|
55 | # CUSTOM ANALYZER raw-string + lowercase filter | |
56 | # |
|
56 | # | |
@@ -77,7 +77,7 b' IDANALYZER = IDTokenizer()' | |||||
77 | # |
|
77 | # | |
78 | PATHANALYZER = RegexTokenizer() | LowercaseFilter() |
|
78 | PATHANALYZER = RegexTokenizer() | LowercaseFilter() | |
79 |
|
79 | |||
80 | #INDEX SCHEMA DEFINITION |
|
80 | # INDEX SCHEMA DEFINITION | |
81 | SCHEMA = Schema( |
|
81 | SCHEMA = Schema( | |
82 | fileid=ID(unique=True), |
|
82 | fileid=ID(unique=True), | |
83 | owner=TEXT(analyzer=EMAILADDRANALYZER), |
|
83 | owner=TEXT(analyzer=EMAILADDRANALYZER), |
@@ -77,9 +77,9 b' class WhooshIndexingDaemon(object):' | |||||
77 |
|
77 | |||
78 | self.repo_paths = ScmModel().repo_scan(self.repo_location) |
|
78 | self.repo_paths = ScmModel().repo_scan(self.repo_location) | |
79 |
|
79 | |||
80 | #filter repo list |
|
80 | # filter repo list | |
81 | if repo_list: |
|
81 | if repo_list: | |
82 | #Fix non-ascii repo names to unicode |
|
82 | # Fix non-ascii repo names to unicode | |
83 | repo_list = map(safe_unicode, repo_list) |
|
83 | repo_list = map(safe_unicode, repo_list) | |
84 | self.filtered_repo_paths = {} |
|
84 | self.filtered_repo_paths = {} | |
85 | for repo_name, repo in self.repo_paths.items(): |
|
85 | for repo_name, repo in self.repo_paths.items(): | |
@@ -88,7 +88,7 b' class WhooshIndexingDaemon(object):' | |||||
88 |
|
88 | |||
89 | self.repo_paths = self.filtered_repo_paths |
|
89 | self.repo_paths = self.filtered_repo_paths | |
90 |
|
90 | |||
91 | #filter update repo list |
|
91 | # filter update repo list | |
92 | self.filtered_repo_update_paths = {} |
|
92 | self.filtered_repo_update_paths = {} | |
93 | if repo_update_list: |
|
93 | if repo_update_list: | |
94 | self.filtered_repo_update_paths = {} |
|
94 | self.filtered_repo_update_paths = {} |
@@ -367,9 +367,11 b' def collapse_address_list(addresses):' | |||||
367 | return _collapse_address_list_recursive(sorted( |
|
367 | return _collapse_address_list_recursive(sorted( | |
368 | addrs + nets, key=_BaseNet._get_networks_key)) |
|
368 | addrs + nets, key=_BaseNet._get_networks_key)) | |
369 |
|
369 | |||
|
370 | ||||
370 | # backwards compatibility |
|
371 | # backwards compatibility | |
371 | CollapseAddrList = collapse_address_list |
|
372 | CollapseAddrList = collapse_address_list | |
372 |
|
373 | |||
|
374 | ||||
373 | # We need to distinguish between the string and packed-bytes representations |
|
375 | # We need to distinguish between the string and packed-bytes representations | |
374 | # of an IP address. For example, b'0::1' is the IPv4 address 48.58.58.49, |
|
376 | # of an IP address. For example, b'0::1' is the IPv4 address 48.58.58.49, | |
375 | # while '0::1' is an IPv6 address. |
|
377 | # while '0::1' is an IPv6 address. |
@@ -79,6 +79,7 b' class MarkupRenderer(object):' | |||||
79 |
|
79 | |||
80 | # Extract pre blocks. |
|
80 | # Extract pre blocks. | |
81 | extractions = {} |
|
81 | extractions = {} | |
|
82 | ||||
82 | def pre_extraction_callback(matchobj): |
|
83 | def pre_extraction_callback(matchobj): | |
83 | digest = md5(matchobj.group(0)).hexdigest() |
|
84 | digest = md5(matchobj.group(0)).hexdigest() | |
84 | extractions[digest] = matchobj.group(0) |
|
85 | extractions[digest] = matchobj.group(0) |
@@ -72,7 +72,7 b' class GitRepository(object):' | |||||
72 |
|
72 | |||
73 | def __init__(self, repo_name, content_path, extras): |
|
73 | def __init__(self, repo_name, content_path, extras): | |
74 | files = set([f.lower() for f in os.listdir(content_path)]) |
|
74 | files = set([f.lower() for f in os.listdir(content_path)]) | |
75 |
if |
|
75 | if not (self.git_folder_signature.intersection(files) | |
76 | == self.git_folder_signature): |
|
76 | == self.git_folder_signature): | |
77 | raise OSError('%s missing git signature' % content_path) |
|
77 | raise OSError('%s missing git signature' % content_path) | |
78 | self.content_path = content_path |
|
78 | self.content_path = content_path |
@@ -26,6 +26,7 b' Original Beaker SessionMiddleware class ' | |||||
26 | from beaker.session import SessionObject |
|
26 | from beaker.session import SessionObject | |
27 | from beaker.middleware import SessionMiddleware |
|
27 | from beaker.middleware import SessionMiddleware | |
28 |
|
28 | |||
|
29 | ||||
29 | class SecureSessionMiddleware(SessionMiddleware): |
|
30 | class SecureSessionMiddleware(SessionMiddleware): | |
30 | def __call__(self, environ, start_response): |
|
31 | def __call__(self, environ, start_response): | |
31 | """ |
|
32 | """ |
@@ -62,6 +62,7 b' def is_mercurial(environ):' | |||||
62 | ) |
|
62 | ) | |
63 | return ishg_path |
|
63 | return ishg_path | |
64 |
|
64 | |||
|
65 | ||||
65 | class SimpleHg(BaseVCSController): |
|
66 | class SimpleHg(BaseVCSController): | |
66 |
|
67 | |||
67 | def _handle_request(self, environ, start_response): |
|
68 | def _handle_request(self, environ, start_response): | |
@@ -229,7 +230,7 b' class SimpleHg(BaseVCSController):' | |||||
229 | repoui = make_ui('file', hgrc) |
|
230 | repoui = make_ui('file', hgrc) | |
230 |
|
231 | |||
231 | if repoui: |
|
232 | if repoui: | |
232 | #overwrite our ui instance with the section from hgrc file |
|
233 | # overwrite our ui instance with the section from hgrc file | |
233 | for section in ui_sections: |
|
234 | for section in ui_sections: | |
234 | for k, v in repoui.configitems(section): |
|
235 | for k, v in repoui.configitems(section): | |
235 | baseui.setconfig(section, k, v) |
|
236 | baseui.setconfig(section, k, v) |
@@ -21,6 +21,7 b' from kallithea.config.routing import url' | |||||
21 | from webhelpers.html import literal, HTML |
|
21 | from webhelpers.html import literal, HTML | |
22 | from webhelpers.paginate import Page as _Page |
|
22 | from webhelpers.paginate import Page as _Page | |
23 |
|
23 | |||
|
24 | ||||
24 | class Page(_Page): |
|
25 | class Page(_Page): | |
25 | """ |
|
26 | """ | |
26 | Custom pager to match rendering style with YUI paginator emitting Bootstrap paginators |
|
27 | Custom pager to match rendering style with YUI paginator emitting Bootstrap paginators |
@@ -84,7 +84,7 b' class Command(BasePasterCommand):' | |||||
84 | if dirs: |
|
84 | if dirs: | |
85 | print 'Scanning: %s' % dn_ |
|
85 | print 'Scanning: %s' % dn_ | |
86 |
|
86 | |||
87 | #filter older than (if present)! |
|
87 | # filter older than (if present)! | |
88 | now = datetime.datetime.now() |
|
88 | now = datetime.datetime.now() | |
89 | older_than = args.older_than |
|
89 | older_than = args.older_than | |
90 | if older_than: |
|
90 | if older_than: |
@@ -61,6 +61,7 b" if __name__=='__main__':" | |||||
61 | HandleCommandLine(params) |
|
61 | HandleCommandLine(params) | |
62 | ''' |
|
62 | ''' | |
63 |
|
63 | |||
|
64 | ||||
64 | class Command(BasePasterCommand): |
|
65 | class Command(BasePasterCommand): | |
65 | '''Kallithea: Install into IIS using isapi-wsgi''' |
|
66 | '''Kallithea: Install into IIS using isapi-wsgi''' | |
66 |
|
67 |
@@ -118,7 +118,7 b' def _run(args):' | |||||
118 | tmpl_stored_args.update(kwargs) |
|
118 | tmpl_stored_args.update(kwargs) | |
119 |
|
119 | |||
120 | if args.show_defaults: |
|
120 | if args.show_defaults: | |
121 | for k,v in tmpl_stored_args.iteritems(): |
|
121 | for k, v in tmpl_stored_args.iteritems(): | |
122 | print '%s=%s' % (k, v) |
|
122 | print '%s=%s' % (k, v) | |
123 | sys.exit(0) |
|
123 | sys.exit(0) | |
124 |
|
124 |
@@ -42,7 +42,7 b' class DaemonLock(object):' | |||||
42 | self.desc = desc |
|
42 | self.desc = desc | |
43 | self.debug = debug |
|
43 | self.debug = debug | |
44 | self.held = False |
|
44 | self.held = False | |
45 |
#run the lock automatically |
|
45 | # run the lock automatically! | |
46 | self.lock() |
|
46 | self.lock() | |
47 | self._finalize = Finalize(self, DaemonLock._on_finalize, |
|
47 | self._finalize = Finalize(self, DaemonLock._on_finalize, | |
48 | args=(self, debug), exitpriority=10) |
|
48 | args=(self, debug), exitpriority=10) |
@@ -196,7 +196,7 b' class MailResponse(object):' | |||||
196 | self.attachments.append({'filename': filename, |
|
196 | self.attachments.append({'filename': filename, | |
197 | 'content_type': content_type, |
|
197 | 'content_type': content_type, | |
198 | 'data': data, |
|
198 | 'data': data, | |
199 |
'disposition': disposition |
|
199 | 'disposition': disposition}) | |
200 |
|
200 | |||
201 | def attach_part(self, part): |
|
201 | def attach_part(self, part): | |
202 | """ |
|
202 | """ |
@@ -16,4 +16,5 b' class CachedDnsName(object):' | |||||
16 | self._fqdn = socket.getfqdn() |
|
16 | self._fqdn = socket.getfqdn() | |
17 | return self._fqdn |
|
17 | return self._fqdn | |
18 |
|
18 | |||
|
19 | ||||
19 | DNS_NAME = CachedDnsName() |
|
20 | DNS_NAME = CachedDnsName() |
@@ -214,7 +214,7 b' def get_filesystem_repos(path):' | |||||
214 | if REMOVED_REPO_PAT.match(subdir): |
|
214 | if REMOVED_REPO_PAT.match(subdir): | |
215 | continue |
|
215 | continue | |
216 |
|
216 | |||
217 | #skip .<something> dirs TODO: rly? then we should prevent creating them ... |
|
217 | # skip .<something> dirs TODO: rly? then we should prevent creating them ... | |
218 | if subdir.startswith('.'): |
|
218 | if subdir.startswith('.'): | |
219 | continue |
|
219 | continue | |
220 |
|
220 | |||
@@ -303,7 +303,7 b' def is_valid_repo_group(repo_group_name,' | |||||
303 | return False |
|
303 | return False | |
304 |
|
304 | |||
305 |
|
305 | |||
306 | #propagated from mercurial documentation |
|
306 | # propagated from mercurial documentation | |
307 | ui_sections = ['alias', 'auth', |
|
307 | ui_sections = ['alias', 'auth', | |
308 | 'decode/encode', 'defaults', |
|
308 | 'decode/encode', 'defaults', | |
309 | 'diff', 'email', |
|
309 | 'diff', 'email', | |
@@ -479,7 +479,7 b' def repo2db_mapper(initial_repo_list, re' | |||||
479 | user = User.get_first_admin() |
|
479 | user = User.get_first_admin() | |
480 | added = [] |
|
480 | added = [] | |
481 |
|
481 | |||
482 |
# |
|
482 | # creation defaults | |
483 | defs = Setting.get_default_repo_settings(strip_prefix=True) |
|
483 | defs = Setting.get_default_repo_settings(strip_prefix=True) | |
484 | enable_statistics = defs.get('repo_enable_statistics') |
|
484 | enable_statistics = defs.get('repo_enable_statistics') | |
485 | enable_locking = defs.get('repo_enable_locking') |
|
485 | enable_locking = defs.get('repo_enable_locking') | |
@@ -556,13 +556,13 b' def load_rcextensions(root_path):' | |||||
556 | # Additional mappings that are not present in the pygments lexers |
|
556 | # Additional mappings that are not present in the pygments lexers | |
557 | conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {})) |
|
557 | conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {})) | |
558 |
|
558 | |||
559 | #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present) |
|
559 | # OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present) | |
560 |
|
560 | |||
561 | if getattr(EXT, 'INDEX_EXTENSIONS', []): |
|
561 | if getattr(EXT, 'INDEX_EXTENSIONS', []): | |
562 | log.debug('settings custom INDEX_EXTENSIONS') |
|
562 | log.debug('settings custom INDEX_EXTENSIONS') | |
563 | conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', []) |
|
563 | conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', []) | |
564 |
|
564 | |||
565 | #ADDITIONAL MAPPINGS |
|
565 | # ADDITIONAL MAPPINGS | |
566 | log.debug('adding extra into INDEX_EXTENSIONS') |
|
566 | log.debug('adding extra into INDEX_EXTENSIONS') | |
567 | conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', [])) |
|
567 | conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', [])) | |
568 |
|
568 |
@@ -297,7 +297,7 b' def engine_from_config(configuration, pr' | |||||
297 | return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal]) |
|
297 | return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal]) | |
298 |
|
298 | |||
299 | if configuration['debug']: |
|
299 | if configuration['debug']: | |
300 | #attach events only for debug configuration |
|
300 | # attach events only for debug configuration | |
301 |
|
301 | |||
302 | def before_cursor_execute(conn, cursor, statement, |
|
302 | def before_cursor_execute(conn, cursor, statement, | |
303 | parameters, context, executemany): |
|
303 | parameters, context, executemany): | |
@@ -458,7 +458,7 b' def credentials_filter(uri):' | |||||
458 | """ |
|
458 | """ | |
459 |
|
459 | |||
460 | uri = uri_filter(uri) |
|
460 | uri = uri_filter(uri) | |
461 | #check if we have port |
|
461 | # check if we have port | |
462 | if len(uri) > 2 and uri[2]: |
|
462 | if len(uri) > 2 and uri[2]: | |
463 | uri[2] = ':' + uri[2] |
|
463 | uri[2] = ':' + uri[2] | |
464 |
|
464 | |||
@@ -531,6 +531,7 b' def time_to_datetime(tm):' | |||||
531 | # Matching is greedy so we don't have to look beyond the end. |
|
531 | # Matching is greedy so we don't have to look beyond the end. | |
532 | MENTIONS_REGEX = re.compile(r'(?:^|(?<=[^a-zA-Z0-9]))@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])') |
|
532 | MENTIONS_REGEX = re.compile(r'(?:^|(?<=[^a-zA-Z0-9]))@([a-zA-Z0-9][-_.a-zA-Z0-9]*[a-zA-Z0-9])') | |
533 |
|
533 | |||
|
534 | ||||
534 | def extract_mentioned_usernames(text): |
|
535 | def extract_mentioned_usernames(text): | |
535 | r""" |
|
536 | r""" | |
536 | Returns list of (possible) usernames @mentioned in given text. |
|
537 | Returns list of (possible) usernames @mentioned in given text. | |
@@ -540,6 +541,7 b' def extract_mentioned_usernames(text):' | |||||
540 | """ |
|
541 | """ | |
541 | return MENTIONS_REGEX.findall(text) |
|
542 | return MENTIONS_REGEX.findall(text) | |
542 |
|
543 | |||
|
544 | ||||
543 | def extract_mentioned_users(text): |
|
545 | def extract_mentioned_users(text): | |
544 | """ Returns set of actual database Users @mentioned in given text. """ |
|
546 | """ Returns set of actual database Users @mentioned in given text. """ | |
545 | from kallithea.model.db import User |
|
547 | from kallithea.model.db import User | |
@@ -649,7 +651,8 b' class OptionalAttr(object):' | |||||
649 | def __call__(self): |
|
651 | def __call__(self): | |
650 | return self |
|
652 | return self | |
651 |
|
653 | |||
652 | #alias |
|
654 | ||
|
655 | # alias | |||
653 | OAttr = OptionalAttr |
|
656 | OAttr = OptionalAttr | |
654 |
|
657 | |||
655 |
|
658 | |||
@@ -697,5 +700,6 b' class Optional(object):' | |||||
697 | return val.getval() |
|
700 | return val.getval() | |
698 | return val |
|
701 | return val | |
699 |
|
702 | |||
|
703 | ||||
700 | def urlreadable(s, _cleanstringsub=re.compile('[^-a-zA-Z0-9./]+').sub): |
|
704 | def urlreadable(s, _cleanstringsub=re.compile('[^-a-zA-Z0-9./]+').sub): | |
701 | return _cleanstringsub('_', safe_str(s)).rstrip('_') |
|
705 | return _cleanstringsub('_', safe_str(s)).rstrip('_') |
@@ -700,6 +700,7 b' class BaseChangeset(object):' | |||||
700 | def phase(self): |
|
700 | def phase(self): | |
701 | return '' |
|
701 | return '' | |
702 |
|
702 | |||
|
703 | ||||
703 | class BaseWorkdir(object): |
|
704 | class BaseWorkdir(object): | |
704 | """ |
|
705 | """ | |
705 | Working directory representation of single repository. |
|
706 | Working directory representation of single repository. |
@@ -118,7 +118,7 b' class GitRepository(BaseRepository):' | |||||
118 | _copts = ['-c', 'core.quotepath=false', ] |
|
118 | _copts = ['-c', 'core.quotepath=false', ] | |
119 | safe_call = False |
|
119 | safe_call = False | |
120 | if '_safe' in opts: |
|
120 | if '_safe' in opts: | |
121 | #no exc on failure |
|
121 | # no exc on failure | |
122 | del opts['_safe'] |
|
122 | del opts['_safe'] | |
123 | safe_call = True |
|
123 | safe_call = True | |
124 |
|
124 | |||
@@ -189,7 +189,7 b' class GitRepository(BaseRepository):' | |||||
189 | test_uri = test_uri.rstrip('/') + '/info/refs' |
|
189 | test_uri = test_uri.rstrip('/') + '/info/refs' | |
190 |
|
190 | |||
191 | if authinfo: |
|
191 | if authinfo: | |
192 | #create a password manager |
|
192 | # create a password manager | |
193 | passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() |
|
193 | passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() | |
194 | passmgr.add_password(*authinfo) |
|
194 | passmgr.add_password(*authinfo) | |
195 |
|
195 | |||
@@ -262,7 +262,7 b' class GitRepository(BaseRepository):' | |||||
262 | return so.splitlines() |
|
262 | return so.splitlines() | |
263 |
|
263 | |||
264 | def _get_all_revisions2(self): |
|
264 | def _get_all_revisions2(self): | |
265 | #alternate implementation using dulwich |
|
265 | # alternate implementation using dulwich | |
266 | includes = [x[1][0] for x in self._parsed_refs.iteritems() |
|
266 | includes = [x[1][0] for x in self._parsed_refs.iteritems() | |
267 | if x[1][1] != 'T'] |
|
267 | if x[1][1] != 'T'] | |
268 | return [c.commit.id for c in self._repo.get_walker(include=includes)] |
|
268 | return [c.commit.id for c in self._repo.get_walker(include=includes)] | |
@@ -527,7 +527,7 b' class GitRepository(BaseRepository):' | |||||
527 |
|
527 | |||
528 | """ |
|
528 | """ | |
529 | if branch_name and branch_name not in self.branches: |
|
529 | if branch_name and branch_name not in self.branches: | |
530 |
raise BranchDoesNotExistError("Branch '%s' not found" |
|
530 | raise BranchDoesNotExistError("Branch '%s' not found" | |
531 | % branch_name) |
|
531 | % branch_name) | |
532 | # actually we should check now if it's not an empty repo to not spaw |
|
532 | # actually we should check now if it's not an empty repo to not spaw | |
533 | # subprocess commands |
|
533 | # subprocess commands |
@@ -18,6 +18,7 b' from kallithea.lib.vcs.utils.hgcompat im' | |||||
18 |
|
18 | |||
19 | from mercurial import obsolete |
|
19 | from mercurial import obsolete | |
20 |
|
20 | |||
|
21 | ||||
21 | class MercurialChangeset(BaseChangeset): |
|
22 | class MercurialChangeset(BaseChangeset): | |
22 | """ |
|
23 | """ | |
23 | Represents state of the repository at the single revision. |
|
24 | Represents state of the repository at the single revision. | |
@@ -37,7 +38,7 b' class MercurialChangeset(BaseChangeset):' | |||||
37 |
|
38 | |||
38 | @LazyProperty |
|
39 | @LazyProperty | |
39 | def branch(self): |
|
40 | def branch(self): | |
40 |
return |
|
41 | return safe_unicode(self._ctx.branch()) | |
41 |
|
42 | |||
42 | @LazyProperty |
|
43 | @LazyProperty | |
43 | def closesbranch(self): |
|
44 | def closesbranch(self): | |
@@ -411,7 +412,7 b' class MercurialChangeset(BaseChangeset):' | |||||
411 | """ |
|
412 | """ | |
412 | Returns list of modified ``FileNode`` objects. |
|
413 | Returns list of modified ``FileNode`` objects. | |
413 | """ |
|
414 | """ | |
414 |
return ChangedFileNodesGenerator([n for n in |
|
415 | return ChangedFileNodesGenerator([n for n in self.status[0]], self) | |
415 |
|
416 | |||
416 | @property |
|
417 | @property | |
417 | def removed(self): |
|
418 | def removed(self): |
@@ -300,7 +300,7 b' class MercurialRepository(BaseRepository' | |||||
300 | cleaned_uri = str(url_obj) |
|
300 | cleaned_uri = str(url_obj) | |
301 |
|
301 | |||
302 | if authinfo: |
|
302 | if authinfo: | |
303 | #create a password manager |
|
303 | # create a password manager | |
304 | passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() |
|
304 | passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() | |
305 | passmgr.add_password(*authinfo) |
|
305 | passmgr.add_password(*authinfo) | |
306 |
|
306 | |||
@@ -395,7 +395,7 b' class MercurialRepository(BaseRepository' | |||||
395 | try: |
|
395 | try: | |
396 | return time.mktime(self.get_changeset().date.timetuple()) |
|
396 | return time.mktime(self.get_changeset().date.timetuple()) | |
397 | except RepositoryError: |
|
397 | except RepositoryError: | |
398 | #fallback to filesystem |
|
398 | # fallback to filesystem | |
399 | cl_path = os.path.join(self.path, '.hg', "00changelog.i") |
|
399 | cl_path = os.path.join(self.path, '.hg', "00changelog.i") | |
400 | st_path = os.path.join(self.path, '.hg', "store") |
|
400 | st_path = os.path.join(self.path, '.hg', "store") | |
401 | if os.path.exists(cl_path): |
|
401 | if os.path.exists(cl_path): | |
@@ -529,7 +529,7 b' class MercurialRepository(BaseRepository' | |||||
529 | raise BranchDoesNotExistError(msg) |
|
529 | raise BranchDoesNotExistError(msg) | |
530 | if end_pos is not None: |
|
530 | if end_pos is not None: | |
531 | end_pos += 1 |
|
531 | end_pos += 1 | |
532 | #filter branches |
|
532 | # filter branches | |
533 | filter_ = [] |
|
533 | filter_ = [] | |
534 | if branch_name: |
|
534 | if branch_name: | |
535 | filter_.append('branch("%s")' % (branch_name)) |
|
535 | filter_.append('branch("%s")' % (branch_name)) |
@@ -328,7 +328,7 b' class FileNode(Node):' | |||||
328 | mtype = 'text/plain' |
|
328 | mtype = 'text/plain' | |
329 | encoding = None |
|
329 | encoding = None | |
330 |
|
330 | |||
331 | #try with pygments |
|
331 | # try with pygments | |
332 | try: |
|
332 | try: | |
333 | from pygments import lexers |
|
333 | from pygments import lexers | |
334 | mt = lexers.get_lexer_for_filename(self.name).mimetypes |
|
334 | mt = lexers.get_lexer_for_filename(self.name).mimetypes | |
@@ -609,7 +609,7 b' class SubModuleNode(Node):' | |||||
609 |
|
609 | |||
610 | def _extract_submodule_url(self): |
|
610 | def _extract_submodule_url(self): | |
611 | if self.alias == 'git': |
|
611 | if self.alias == 'git': | |
612 | #TODO: find a way to parse gits submodule file and extract the |
|
612 | # TODO: find a way to parse gits submodule file and extract the | |
613 | # linking URL |
|
613 | # linking URL | |
614 | return self.path |
|
614 | return self.path | |
615 | if self.alias == 'hg': |
|
615 | if self.alias == 'hg': |
@@ -45,7 +45,7 b' class StreamFeeder(threading.Thread):' | |||||
45 | self.bytes = bytes(source) |
|
45 | self.bytes = bytes(source) | |
46 | else: # can be either file pointer or file-like |
|
46 | else: # can be either file pointer or file-like | |
47 | if type(source) in (int, long): # file pointer it is |
|
47 | if type(source) in (int, long): # file pointer it is | |
48 |
|
|
48 | # converting file descriptor (int) stdin into file-like | |
49 | source = os.fdopen(source, 'rb', 16384) |
|
49 | source = os.fdopen(source, 'rb', 16384) | |
50 | # let's see if source is file-like by now |
|
50 | # let's see if source is file-like by now | |
51 | filelike = hasattr(source, 'read') |
|
51 | filelike = hasattr(source, 'read') |
@@ -157,6 +157,7 b' email_re = re.compile(' | |||||
157 | r"""(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?""", |
|
157 | r"""(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?""", | |
158 | re.IGNORECASE) |
|
158 | re.IGNORECASE) | |
159 |
|
159 | |||
|
160 | ||||
160 | def author_email(author): |
|
161 | def author_email(author): | |
161 | """ |
|
162 | """ | |
162 | Returns email address of given author string. |
|
163 | Returns email address of given author string. |
@@ -122,7 +122,7 b' class AnnotateHtmlFormatter(HtmlFormatte' | |||||
122 | for i in range(fl, fl + lncount): |
|
122 | for i in range(fl, fl + lncount): | |
123 | if i % st == 0: |
|
123 | if i % st == 0: | |
124 | if aln: |
|
124 | if aln: | |
125 |
lines.append('<a href="#%s-%d">%*d</a>' |
|
125 | lines.append('<a href="#%s-%d">%*d</a>' | |
126 | % (la, i, mw, i)) |
|
126 | % (la, i, mw, i)) | |
127 | else: |
|
127 | else: | |
128 | lines.append('%*d' % (mw, i)) |
|
128 | lines.append('%*d' % (mw, i)) | |
@@ -134,7 +134,7 b' class AnnotateHtmlFormatter(HtmlFormatte' | |||||
134 | # If pygments cropped last lines break we need do that too |
|
134 | # If pygments cropped last lines break we need do that too | |
135 | ln_cs = len(annotate_changesets) |
|
135 | ln_cs = len(annotate_changesets) | |
136 | ln_ = len(ls.splitlines()) |
|
136 | ln_ = len(ls.splitlines()) | |
137 |
if |
|
137 | if ln_cs > ln_: | |
138 | annotate_changesets = annotate_changesets[:ln_ - ln_cs] |
|
138 | annotate_changesets = annotate_changesets[:ln_ - ln_cs] | |
139 | annotate = ''.join((self.annotate_from_changeset(changeset) |
|
139 | annotate = ''.join((self.annotate_from_changeset(changeset) | |
140 | for changeset in annotate_changesets)) |
|
140 | for changeset in annotate_changesets)) |
@@ -160,7 +160,7 b' class DiffProcessor(object):' | |||||
160 | l.extend(output[1].splitlines(1)) |
|
160 | l.extend(output[1].splitlines(1)) | |
161 | return map(line_decoder, l) |
|
161 | return map(line_decoder, l) | |
162 | elif size == 1: |
|
162 | elif size == 1: | |
163 |
return |
|
163 | return map(line_decoder, output[0].splitlines(1)) | |
164 | elif size == 0: |
|
164 | elif size == 0: | |
165 | return [] |
|
165 | return [] | |
166 |
|
166 |
@@ -4,7 +4,7 b' Mercurial libs compatibility' | |||||
4 |
|
4 | |||
5 | import mercurial |
|
5 | import mercurial | |
6 | import mercurial.demandimport |
|
6 | import mercurial.demandimport | |
7 |
|
|
7 | # patch demandimport, due to bug in mercurial when it always triggers demandimport.enable() | |
8 | mercurial.demandimport.enable = lambda *args, **kwargs: 1 |
|
8 | mercurial.demandimport.enable = lambda *args, **kwargs: 1 | |
9 | from mercurial import archival, merge as hg_merge, patch, ui |
|
9 | from mercurial import archival, merge as hg_merge, patch, ui | |
10 | from mercurial import discovery |
|
10 | from mercurial import discovery | |
@@ -37,7 +37,8 b' from mercurial.url import httpbasicauthh' | |||||
37 | import inspect |
|
37 | import inspect | |
38 | # Mercurial 3.1 503bb3af70fe |
|
38 | # Mercurial 3.1 503bb3af70fe | |
39 | if inspect.getargspec(memfilectx.__init__).args[1] != 'repo': |
|
39 | if inspect.getargspec(memfilectx.__init__).args[1] != 'repo': | |
40 | _org__init__=memfilectx.__init__ |
|
40 | _org__init__ = memfilectx.__init__ | |
|
41 | ||||
41 | def _memfilectx__init__(self, repo, *a, **b): |
|
42 | def _memfilectx__init__(self, repo, *a, **b): | |
42 | return _org__init__(self, *a, **b) |
|
43 | return _org__init__(self, *a, **b) | |
43 | memfilectx.__init__ = _memfilectx__init__ |
|
44 | memfilectx.__init__ = _memfilectx__init__ |
@@ -9,6 +9,7 b' class _Missing(object):' | |||||
9 | def __reduce__(self): |
|
9 | def __reduce__(self): | |
10 | return '_missing' |
|
10 | return '_missing' | |
11 |
|
11 | |||
|
12 | ||||
12 | _missing = _Missing() |
|
13 | _missing = _Missing() | |
13 |
|
14 | |||
14 |
|
15 |
@@ -10,6 +10,7 b' from kallithea.lib.vcs.utils.helpers imp' | |||||
10 | class ProgressBarError(Exception): |
|
10 | class ProgressBarError(Exception): | |
11 | pass |
|
11 | pass | |
12 |
|
12 | |||
|
13 | ||||
13 | class AlreadyFinishedError(ProgressBarError): |
|
14 | class AlreadyFinishedError(ProgressBarError): | |
14 | pass |
|
15 | pass | |
15 |
|
16 | |||
@@ -179,6 +180,7 b" background = dict([(color_names[x], '4%s" | |||||
179 | RESET = '0' |
|
180 | RESET = '0' | |
180 | opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} |
|
181 | opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} | |
181 |
|
182 | |||
|
183 | ||||
182 | def colorize(text='', opts=(), **kwargs): |
|
184 | def colorize(text='', opts=(), **kwargs): | |
183 | """ |
|
185 | """ | |
184 | Returns your text, enclosed in ANSI graphics codes. |
|
186 | Returns your text, enclosed in ANSI graphics codes. | |
@@ -223,6 +225,7 b" def colorize(text='', opts=(), **kwargs)" | |||||
223 | text = text + '\x1b[%sm' % RESET |
|
225 | text = text + '\x1b[%sm' % RESET | |
224 | return ('\x1b[%sm' % ';'.join(code_list)) + text |
|
226 | return ('\x1b[%sm' % ';'.join(code_list)) + text | |
225 |
|
227 | |||
|
228 | ||||
226 | def make_style(opts=(), **kwargs): |
|
229 | def make_style(opts=(), **kwargs): | |
227 | """ |
|
230 | """ | |
228 | Returns a function with default parameters for colorize() |
|
231 | Returns a function with default parameters for colorize() | |
@@ -235,6 +238,7 b' def make_style(opts=(), **kwargs):' | |||||
235 | """ |
|
238 | """ | |
236 | return lambda text: colorize(text, opts, **kwargs) |
|
239 | return lambda text: colorize(text, opts, **kwargs) | |
237 |
|
240 | |||
|
241 | ||||
238 | NOCOLOR_PALETTE = 'nocolor' |
|
242 | NOCOLOR_PALETTE = 'nocolor' | |
239 | DARK_PALETTE = 'dark' |
|
243 | DARK_PALETTE = 'dark' | |
240 | LIGHT_PALETTE = 'light' |
|
244 | LIGHT_PALETTE = 'light' | |
@@ -348,7 +352,6 b' class BarOnlyColoredProgressBar(ColoredP' | |||||
348 | pass |
|
352 | pass | |
349 |
|
353 | |||
350 |
|
354 | |||
351 |
|
||||
352 | def main(): |
|
355 | def main(): | |
353 | import time |
|
356 | import time | |
354 |
|
357 |
@@ -11,6 +11,7 b" background = dict([(color_names[x], '4%s" | |||||
11 | RESET = '0' |
|
11 | RESET = '0' | |
12 | opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} |
|
12 | opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} | |
13 |
|
13 | |||
|
14 | ||||
14 | def colorize(text='', opts=(), **kwargs): |
|
15 | def colorize(text='', opts=(), **kwargs): | |
15 | """ |
|
16 | """ | |
16 | Returns your text, enclosed in ANSI graphics codes. |
|
17 | Returns your text, enclosed in ANSI graphics codes. | |
@@ -55,6 +56,7 b" def colorize(text='', opts=(), **kwargs)" | |||||
55 | text = text + '\x1b[%sm' % RESET |
|
56 | text = text + '\x1b[%sm' % RESET | |
56 | return ('\x1b[%sm' % ';'.join(code_list)) + text |
|
57 | return ('\x1b[%sm' % ';'.join(code_list)) + text | |
57 |
|
58 | |||
|
59 | ||||
58 | def make_style(opts=(), **kwargs): |
|
60 | def make_style(opts=(), **kwargs): | |
59 | """ |
|
61 | """ | |
60 | Returns a function with default parameters for colorize() |
|
62 | Returns a function with default parameters for colorize() | |
@@ -67,6 +69,7 b' def make_style(opts=(), **kwargs):' | |||||
67 | """ |
|
69 | """ | |
68 | return lambda text: colorize(text, opts, **kwargs) |
|
70 | return lambda text: colorize(text, opts, **kwargs) | |
69 |
|
71 | |||
|
72 | ||||
70 | NOCOLOR_PALETTE = 'nocolor' |
|
73 | NOCOLOR_PALETTE = 'nocolor' | |
71 | DARK_PALETTE = 'dark' |
|
74 | DARK_PALETTE = 'dark' | |
72 | LIGHT_PALETTE = 'light' |
|
75 | LIGHT_PALETTE = 'light' | |
@@ -120,6 +123,7 b' PALETTES = {' | |||||
120 | } |
|
123 | } | |
121 | DEFAULT_PALETTE = DARK_PALETTE |
|
124 | DEFAULT_PALETTE = DARK_PALETTE | |
122 |
|
125 | |||
|
126 | ||||
123 | def parse_color_setting(config_string): |
|
127 | def parse_color_setting(config_string): | |
124 | """Parse a DJANGO_COLORS environment variable to produce the system palette |
|
128 | """Parse a DJANGO_COLORS environment variable to produce the system palette | |
125 |
|
129 |
@@ -5,10 +5,12 b' discussion at PyCon 2009.' | |||||
5 |
|
5 | |||
6 | import re |
|
6 | import re | |
7 |
|
7 | |||
|
8 | ||||
8 | class IrrationalVersionError(Exception): |
|
9 | class IrrationalVersionError(Exception): | |
9 | """This is an irrational version.""" |
|
10 | """This is an irrational version.""" | |
10 | pass |
|
11 | pass | |
11 |
|
12 | |||
|
13 | ||||
12 | class HugeMajorVersionNumError(IrrationalVersionError): |
|
14 | class HugeMajorVersionNumError(IrrationalVersionError): | |
13 | """An irrational version because the major version number is huge |
|
15 | """An irrational version because the major version number is huge | |
14 | (often because a year or date was used). |
|
16 | (often because a year or date was used). | |
@@ -18,6 +20,7 b' class HugeMajorVersionNumError(Irrationa' | |||||
18 | """ |
|
20 | """ | |
19 | pass |
|
21 | pass | |
20 |
|
22 | |||
|
23 | ||||
21 | # A marker used in the second and third parts of the `parts` tuple, for |
|
24 | # A marker used in the second and third parts of the `parts` tuple, for | |
22 | # versions that don't have those segments, to sort properly. An example |
|
25 | # versions that don't have those segments, to sort properly. An example | |
23 | # of versions in sort order ('highest' last): |
|
26 | # of versions in sort order ('highest' last): | |
@@ -47,6 +50,7 b" VERSION_RE = re.compile(r'''" | |||||
47 | (?P<postdev>(\.post(?P<post>\d+))?(\.dev(?P<dev>\d+))?)? |
|
50 | (?P<postdev>(\.post(?P<post>\d+))?(\.dev(?P<dev>\d+))?)? | |
48 | $''', re.VERBOSE) |
|
51 | $''', re.VERBOSE) | |
49 |
|
52 | |||
|
53 | ||||
50 | class NormalizedVersion(object): |
|
54 | class NormalizedVersion(object): | |
51 | """A rational version. |
|
55 | """A rational version. | |
52 |
|
56 | |||
@@ -212,6 +216,7 b' class NormalizedVersion(object):' | |||||
212 | def __ge__(self, other): |
|
216 | def __ge__(self, other): | |
213 | return self.__eq__(other) or self.__gt__(other) |
|
217 | return self.__eq__(other) or self.__gt__(other) | |
214 |
|
218 | |||
|
219 | ||||
215 | def suggest_normalized_version(s): |
|
220 | def suggest_normalized_version(s): | |
216 | """Suggest a normalized version close to the given version string. |
|
221 | """Suggest a normalized version close to the given version string. | |
217 |
|
222 | |||
@@ -267,7 +272,7 b' def suggest_normalized_version(s):' | |||||
267 | rs = rs[1:] |
|
272 | rs = rs[1:] | |
268 |
|
273 | |||
269 | # Clean leading '0's on numbers. |
|
274 | # Clean leading '0's on numbers. | |
270 | #TODO: unintended side-effect on, e.g., "2003.05.09" |
|
275 | # TODO: unintended side-effect on, e.g., "2003.05.09" | |
271 | # PyPI stats: 77 (~2%) better |
|
276 | # PyPI stats: 77 (~2%) better | |
272 | rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) |
|
277 | rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) | |
273 |
|
278 | |||
@@ -313,7 +318,6 b' def suggest_normalized_version(s):' | |||||
313 | # PyPI stats: ~21 (0.62%) better |
|
318 | # PyPI stats: ~21 (0.62%) better | |
314 | rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) |
|
319 | rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) | |
315 |
|
320 | |||
316 |
|
||||
317 | # Tcl/Tk uses "px" for their post release markers |
|
321 | # Tcl/Tk uses "px" for their post release markers | |
318 | rs = re.sub(r"p(\d+)$", r".post\1", rs) |
|
322 | rs = re.sub(r"p(\d+)$", r".post\1", rs) | |
319 |
|
323 |
@@ -165,7 +165,7 b' class ChangesetStatusModel(object):' | |||||
165 | revisions = pull_request.revisions |
|
165 | revisions = pull_request.revisions | |
166 | cur_statuses = q.all() |
|
166 | cur_statuses = q.all() | |
167 |
|
167 | |||
168 | #if statuses exists and last is associated with a closed pull request |
|
168 | # if statuses exists and last is associated with a closed pull request | |
169 | # we need to check if we can allow this status change |
|
169 | # we need to check if we can allow this status change | |
170 | if (dont_allow_on_closed_pull_request and cur_statuses |
|
170 | if (dont_allow_on_closed_pull_request and cur_statuses | |
171 | and getattr(cur_statuses[0].pull_request, 'status', '') |
|
171 | and getattr(cur_statuses[0].pull_request, 'status', '') | |
@@ -174,7 +174,7 b' class ChangesetStatusModel(object):' | |||||
174 | 'Changing status on closed pull request is not allowed' |
|
174 | 'Changing status on closed pull request is not allowed' | |
175 | ) |
|
175 | ) | |
176 |
|
176 | |||
177 | #update all current statuses with older version |
|
177 | # update all current statuses with older version | |
178 | for st in cur_statuses: |
|
178 | for st in cur_statuses: | |
179 | st.version += 1 |
|
179 | st.version += 1 | |
180 |
|
180 |
@@ -67,7 +67,7 b' class ChangesetCommentsModel(object):' | |||||
67 | if line_no: |
|
67 | if line_no: | |
68 | line = _('on line %s') % line_no |
|
68 | line = _('on line %s') % line_no | |
69 |
|
69 | |||
70 | #changeset |
|
70 | # changeset | |
71 | if revision: |
|
71 | if revision: | |
72 | notification_type = Notification.TYPE_CHANGESET_COMMENT |
|
72 | notification_type = Notification.TYPE_CHANGESET_COMMENT | |
73 | cs = repo.scm_instance.get_changeset(revision) |
|
73 | cs = repo.scm_instance.get_changeset(revision) | |
@@ -91,7 +91,7 b' class ChangesetCommentsModel(object):' | |||||
91 | # add changeset author if it's known locally |
|
91 | # add changeset author if it's known locally | |
92 | cs_author = User.get_from_cs_author(cs.author) |
|
92 | cs_author = User.get_from_cs_author(cs.author) | |
93 | if not cs_author: |
|
93 | if not cs_author: | |
94 | #use repo owner if we cannot extract the author correctly |
|
94 | # use repo owner if we cannot extract the author correctly | |
95 | # FIXME: just use committer name even if not a user |
|
95 | # FIXME: just use committer name even if not a user | |
96 | cs_author = repo.owner |
|
96 | cs_author = repo.owner | |
97 | recipients.append(cs_author) |
|
97 | recipients.append(cs_author) | |
@@ -112,7 +112,7 b' class ChangesetCommentsModel(object):' | |||||
112 | 'comment_username': author.username, |
|
112 | 'comment_username': author.username, | |
113 | 'threading': threading, |
|
113 | 'threading': threading, | |
114 | } |
|
114 | } | |
115 | #pull request |
|
115 | # pull request | |
116 | elif pull_request: |
|
116 | elif pull_request: | |
117 | notification_type = Notification.TYPE_PULL_REQUEST_COMMENT |
|
117 | notification_type = Notification.TYPE_PULL_REQUEST_COMMENT | |
118 | desc = comment.pull_request.title |
|
118 | desc = comment.pull_request.title | |
@@ -128,7 +128,7 b' class ChangesetCommentsModel(object):' | |||||
128 | comment_url = pull_request.url(canonical=True, |
|
128 | comment_url = pull_request.url(canonical=True, | |
129 | anchor='comment-%s' % comment.comment_id) |
|
129 | anchor='comment-%s' % comment.comment_id) | |
130 | subj = safe_unicode( |
|
130 | subj = safe_unicode( | |
131 |
h.link_to('Re pull request %(pr_nice_id)s: %(desc)s %(line)s' % |
|
131 | h.link_to('Re pull request %(pr_nice_id)s: %(desc)s %(line)s' % | |
132 | {'desc': desc, |
|
132 | {'desc': desc, | |
133 | 'pr_nice_id': comment.pull_request.nice_id(), |
|
133 | 'pr_nice_id': comment.pull_request.nice_id(), | |
134 | 'line': line}, |
|
134 | 'line': line}, | |
@@ -139,7 +139,7 b' class ChangesetCommentsModel(object):' | |||||
139 | recipients.append(pull_request.owner) |
|
139 | recipients.append(pull_request.owner) | |
140 | recipients += pull_request.get_reviewer_users() |
|
140 | recipients += pull_request.get_reviewer_users() | |
141 |
|
141 | |||
142 | #set some variables for email notification |
|
142 | # set some variables for email notification | |
143 | email_kwargs = { |
|
143 | email_kwargs = { | |
144 | 'pr_title': pull_request.title, |
|
144 | 'pr_title': pull_request.title, | |
145 | 'pr_title_short': h.shorter(pull_request.title, 50), |
|
145 | 'pr_title_short': h.shorter(pull_request.title, 50), |
@@ -457,12 +457,11 b' class User(Base, BaseDbModel):' | |||||
457 | user_created_notifications = relationship('Notification', cascade='all') |
|
457 | user_created_notifications = relationship('Notification', cascade='all') | |
458 | # comments created by this user |
|
458 | # comments created by this user | |
459 | user_comments = relationship('ChangesetComment', cascade='all') |
|
459 | user_comments = relationship('ChangesetComment', cascade='all') | |
460 | #extra emails for this user |
|
460 | # extra emails for this user | |
461 | user_emails = relationship('UserEmailMap', cascade='all') |
|
461 | user_emails = relationship('UserEmailMap', cascade='all') | |
462 | #extra API keys |
|
462 | # extra API keys | |
463 | user_api_keys = relationship('UserApiKeys', cascade='all') |
|
463 | user_api_keys = relationship('UserApiKeys', cascade='all') | |
464 |
|
464 | |||
465 |
|
||||
466 | @hybrid_property |
|
465 | @hybrid_property | |
467 | def email(self): |
|
466 | def email(self): | |
468 | return self._email |
|
467 | return self._email | |
@@ -478,12 +477,12 b' class User(Base, BaseDbModel):' | |||||
478 |
|
477 | |||
479 | @property |
|
478 | @property | |
480 | def emails(self): |
|
479 | def emails(self): | |
481 | other = UserEmailMap.query().filter(UserEmailMap.user==self).all() |
|
480 | other = UserEmailMap.query().filter(UserEmailMap.user == self).all() | |
482 | return [self.email] + [x.email for x in other] |
|
481 | return [self.email] + [x.email for x in other] | |
483 |
|
482 | |||
484 | @property |
|
483 | @property | |
485 | def api_keys(self): |
|
484 | def api_keys(self): | |
486 | other = UserApiKeys.query().filter(UserApiKeys.user==self).all() |
|
485 | other = UserApiKeys.query().filter(UserApiKeys.user == self).all() | |
487 | return [self.api_key] + [x.api_key for x in other] |
|
486 | return [self.api_key] + [x.api_key for x in other] | |
488 |
|
487 | |||
489 | @property |
|
488 | @property | |
@@ -615,7 +614,7 b' class User(Base, BaseDbModel):' | |||||
615 | res = q.scalar() |
|
614 | res = q.scalar() | |
616 |
|
615 | |||
617 | if fallback and not res: |
|
616 | if fallback and not res: | |
618 | #fallback to additional keys |
|
617 | # fallback to additional keys | |
619 | _res = UserApiKeys.query().filter_by(api_key=api_key, is_expired=False).first() |
|
618 | _res = UserApiKeys.query().filter_by(api_key=api_key, is_expired=False).first() | |
620 | if _res: |
|
619 | if _res: | |
621 | res = _res.user |
|
620 | res = _res.user | |
@@ -801,6 +800,7 b' class UserIpMap(Base, BaseDbModel):' | |||||
801 | return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__, |
|
800 | return u"<%s('user_id:%s=>%s')>" % (self.__class__.__name__, | |
802 | self.user_id, self.ip_addr) |
|
801 | self.user_id, self.ip_addr) | |
803 |
|
802 | |||
|
803 | ||||
804 | class UserLog(Base, BaseDbModel): |
|
804 | class UserLog(Base, BaseDbModel): | |
805 | __tablename__ = 'user_logs' |
|
805 | __tablename__ = 'user_logs' | |
806 | __table_args__ = ( |
|
806 | __table_args__ = ( | |
@@ -1752,7 +1752,7 b' class Permission(Base, BaseDbModel):' | |||||
1752 | ('hg.extern_activate.auto', _('Automatic activation of external account')), |
|
1752 | ('hg.extern_activate.auto', _('Automatic activation of external account')), | |
1753 | ] |
|
1753 | ] | |
1754 |
|
1754 | |||
1755 | #definition of system default permissions for DEFAULT user |
|
1755 | # definition of system default permissions for DEFAULT user | |
1756 | DEFAULT_USER_PERMISSIONS = [ |
|
1756 | DEFAULT_USER_PERMISSIONS = [ | |
1757 | 'repository.read', |
|
1757 | 'repository.read', | |
1758 | 'group.read', |
|
1758 | 'group.read', | |
@@ -2051,9 +2051,9 b' class Statistics(Base, BaseDbModel):' | |||||
2051 | stat_id = Column(Integer(), primary_key=True) |
|
2051 | stat_id = Column(Integer(), primary_key=True) | |
2052 | repository_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True) |
|
2052 | repository_id = Column(Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True) | |
2053 | stat_on_revision = Column(Integer(), nullable=False) |
|
2053 | stat_on_revision = Column(Integer(), nullable=False) | |
2054 | commit_activity = Column(LargeBinary(1000000), nullable=False)#JSON data |
|
2054 | commit_activity = Column(LargeBinary(1000000), nullable=False) # JSON data | |
2055 | commit_activity_combined = Column(LargeBinary(), nullable=False)#JSON data |
|
2055 | commit_activity_combined = Column(LargeBinary(), nullable=False) # JSON data | |
2056 | languages = Column(LargeBinary(1000000), nullable=False)#JSON data |
|
2056 | languages = Column(LargeBinary(1000000), nullable=False) # JSON data | |
2057 |
|
2057 | |||
2058 | repository = relationship('Repository', single_parent=True) |
|
2058 | repository = relationship('Repository', single_parent=True) | |
2059 |
|
2059 | |||
@@ -2455,6 +2455,7 b' class PullRequest(Base, BaseDbModel):' | |||||
2455 | return h.url('pullrequest_show', repo_name=self.other_repo.repo_name, |
|
2455 | return h.url('pullrequest_show', repo_name=self.other_repo.repo_name, | |
2456 | pull_request_id=self.pull_request_id, **kwargs) |
|
2456 | pull_request_id=self.pull_request_id, **kwargs) | |
2457 |
|
2457 | |||
|
2458 | ||||
2458 | class PullRequestReviewer(Base, BaseDbModel): |
|
2459 | class PullRequestReviewer(Base, BaseDbModel): | |
2459 | __tablename__ = 'pull_request_reviewers' |
|
2460 | __tablename__ = 'pull_request_reviewers' | |
2460 | __table_args__ = ( |
|
2461 | __table_args__ = ( |
@@ -90,6 +90,7 b' def PasswordChangeForm(username):' | |||||
90 |
|
90 | |||
91 | def UserForm(edit=False, old_data=None): |
|
91 | def UserForm(edit=False, old_data=None): | |
92 | old_data = old_data or {} |
|
92 | old_data = old_data or {} | |
|
93 | ||||
93 | class _UserForm(formencode.Schema): |
|
94 | class _UserForm(formencode.Schema): | |
94 | allow_extra_fields = True |
|
95 | allow_extra_fields = True | |
95 | filter_extra_fields = True |
|
96 | filter_extra_fields = True | |
@@ -131,6 +132,7 b' def UserForm(edit=False, old_data=None):' | |||||
131 | def UserGroupForm(edit=False, old_data=None, available_members=None): |
|
132 | def UserGroupForm(edit=False, old_data=None, available_members=None): | |
132 | old_data = old_data or {} |
|
133 | old_data = old_data or {} | |
133 | available_members = available_members or [] |
|
134 | available_members = available_members or [] | |
|
135 | ||||
134 | class _UserGroupForm(formencode.Schema): |
|
136 | class _UserGroupForm(formencode.Schema): | |
135 | allow_extra_fields = True |
|
137 | allow_extra_fields = True | |
136 | filter_extra_fields = True |
|
138 | filter_extra_fields = True | |
@@ -158,6 +160,7 b' def RepoGroupForm(edit=False, old_data=N' | |||||
158 | old_data = old_data or {} |
|
160 | old_data = old_data or {} | |
159 | repo_groups = repo_groups or [] |
|
161 | repo_groups = repo_groups or [] | |
160 | repo_group_ids = [rg[0] for rg in repo_groups] |
|
162 | repo_group_ids = [rg[0] for rg in repo_groups] | |
|
163 | ||||
161 | class _RepoGroupForm(formencode.Schema): |
|
164 | class _RepoGroupForm(formencode.Schema): | |
162 | allow_extra_fields = True |
|
165 | allow_extra_fields = True | |
163 | filter_extra_fields = False |
|
166 | filter_extra_fields = False | |
@@ -170,8 +173,8 b' def RepoGroupForm(edit=False, old_data=N' | |||||
170 | group_copy_permissions = v.StringBoolean(if_missing=False) |
|
173 | group_copy_permissions = v.StringBoolean(if_missing=False) | |
171 |
|
174 | |||
172 | if edit: |
|
175 | if edit: | |
173 | #FIXME: do a special check that we cannot move a group to one of |
|
176 | # FIXME: do a special check that we cannot move a group to one of | |
174 | #its children |
|
177 | # its children | |
175 | pass |
|
178 | pass | |
176 |
|
179 | |||
177 | parent_group_id = All(v.CanCreateGroup(can_create_in_root), |
|
180 | parent_group_id = All(v.CanCreateGroup(can_create_in_root), | |
@@ -219,6 +222,7 b' def PasswordResetRequestForm():' | |||||
219 | email = v.Email(not_empty=True) |
|
222 | email = v.Email(not_empty=True) | |
220 | return _PasswordResetRequestForm |
|
223 | return _PasswordResetRequestForm | |
221 |
|
224 | |||
|
225 | ||||
222 | def PasswordResetConfirmationForm(): |
|
226 | def PasswordResetConfirmationForm(): | |
223 | class _PasswordResetConfirmationForm(formencode.Schema): |
|
227 | class _PasswordResetConfirmationForm(formencode.Schema): | |
224 | allow_extra_fields = True |
|
228 | allow_extra_fields = True | |
@@ -234,12 +238,14 b' def PasswordResetConfirmationForm():' | |||||
234 | 'password_confirm')] |
|
238 | 'password_confirm')] | |
235 | return _PasswordResetConfirmationForm |
|
239 | return _PasswordResetConfirmationForm | |
236 |
|
240 | |||
|
241 | ||||
237 | def RepoForm(edit=False, old_data=None, supported_backends=BACKENDS.keys(), |
|
242 | def RepoForm(edit=False, old_data=None, supported_backends=BACKENDS.keys(), | |
238 | repo_groups=None, landing_revs=None): |
|
243 | repo_groups=None, landing_revs=None): | |
239 | old_data = old_data or {} |
|
244 | old_data = old_data or {} | |
240 | repo_groups = repo_groups or [] |
|
245 | repo_groups = repo_groups or [] | |
241 | landing_revs = landing_revs or [] |
|
246 | landing_revs = landing_revs or [] | |
242 | repo_group_ids = [rg[0] for rg in repo_groups] |
|
247 | repo_group_ids = [rg[0] for rg in repo_groups] | |
|
248 | ||||
243 | class _RepoForm(formencode.Schema): |
|
249 | class _RepoForm(formencode.Schema): | |
244 | allow_extra_fields = True |
|
250 | allow_extra_fields = True | |
245 | filter_extra_fields = False |
|
251 | filter_extra_fields = False | |
@@ -317,6 +323,7 b' def RepoForkForm(edit=False, old_data=No' | |||||
317 | repo_groups = repo_groups or [] |
|
323 | repo_groups = repo_groups or [] | |
318 | landing_revs = landing_revs or [] |
|
324 | landing_revs = landing_revs or [] | |
319 | repo_group_ids = [rg[0] for rg in repo_groups] |
|
325 | repo_group_ids = [rg[0] for rg in repo_groups] | |
|
326 | ||||
320 | class _RepoForkForm(formencode.Schema): |
|
327 | class _RepoForkForm(formencode.Schema): | |
321 | allow_extra_fields = True |
|
328 | allow_extra_fields = True | |
322 | filter_extra_fields = False |
|
329 | filter_extra_fields = False | |
@@ -466,7 +473,7 b' def AuthSettingsForm(current_active_modu' | |||||
466 | validator = sv["validator"] |
|
473 | validator = sv["validator"] | |
467 | if isinstance(validator, LazyFormencode): |
|
474 | if isinstance(validator, LazyFormencode): | |
468 | validator = validator() |
|
475 | validator = validator() | |
469 | #init all lazy validators from formencode.All |
|
476 | # init all lazy validators from formencode.All | |
470 | if isinstance(validator, All): |
|
477 | if isinstance(validator, All): | |
471 | init_validators = [] |
|
478 | init_validators = [] | |
472 | for validator in validator.validators: |
|
479 | for validator in validator.validators: |
@@ -114,7 +114,7 b' class GistModel(object):' | |||||
114 | log.debug('set GIST expiration date to: %s', |
|
114 | log.debug('set GIST expiration date to: %s', | |
115 | time_to_datetime(gist_expires) |
|
115 | time_to_datetime(gist_expires) | |
116 | if gist_expires != -1 else 'forever') |
|
116 | if gist_expires != -1 else 'forever') | |
117 | #create the Database version |
|
117 | # create the Database version | |
118 | gist = Gist() |
|
118 | gist = Gist() | |
119 | gist.gist_description = description |
|
119 | gist.gist_description = description | |
120 | gist.gist_access_id = gist_id |
|
120 | gist.gist_access_id = gist_id | |
@@ -139,7 +139,7 b' class GistModel(object):' | |||||
139 | raise Exception('Filename cannot be inside a directory') |
|
139 | raise Exception('Filename cannot be inside a directory') | |
140 |
|
140 | |||
141 | content = gist_mapping[filename]['content'] |
|
141 | content = gist_mapping[filename]['content'] | |
142 | #TODO: expand support for setting explicit lexers |
|
142 | # TODO: expand support for setting explicit lexers | |
143 | # if lexer is None: |
|
143 | # if lexer is None: | |
144 | # try: |
|
144 | # try: | |
145 | # guess_lexer = pygments.lexers.guess_lexer_for_filename |
|
145 | # guess_lexer = pygments.lexers.guess_lexer_for_filename | |
@@ -153,7 +153,7 b' class GistModel(object):' | |||||
153 | message += 's: ' if len(processed_mapping) > 1 else ': ' |
|
153 | message += 's: ' if len(processed_mapping) > 1 else ': ' | |
154 | message += ', '.join([x for x in processed_mapping]) |
|
154 | message += ', '.join([x for x in processed_mapping]) | |
155 |
|
155 | |||
156 | #fake Kallithea Repository object |
|
156 | # fake Kallithea Repository object | |
157 | fake_repo = AttributeDict(dict( |
|
157 | fake_repo = AttributeDict(dict( | |
158 | repo_name=gist_repo_path, |
|
158 | repo_name=gist_repo_path, | |
159 | scm_instance_no_cache=lambda: repo, |
|
159 | scm_instance_no_cache=lambda: repo, | |
@@ -192,7 +192,7 b' class GistModel(object):' | |||||
192 | else: |
|
192 | else: | |
193 | gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1 |
|
193 | gist_expires = time.time() + (lifetime * 60) if lifetime != -1 else -1 | |
194 |
|
194 | |||
195 | #calculate operation type based on given data |
|
195 | # calculate operation type based on given data | |
196 | gist_mapping_op = {} |
|
196 | gist_mapping_op = {} | |
197 | for k, v in gist_mapping.items(): |
|
197 | for k, v in gist_mapping.items(): | |
198 | # add, mod, del |
|
198 | # add, mod, del | |
@@ -215,7 +215,7 b' class GistModel(object):' | |||||
215 | message += 's: ' if len(gist_mapping) > 1 else ': ' |
|
215 | message += 's: ' if len(gist_mapping) > 1 else ': ' | |
216 | message += ', '.join([x for x in gist_mapping]) |
|
216 | message += ', '.join([x for x in gist_mapping]) | |
217 |
|
217 | |||
218 | #fake Kallithea Repository object |
|
218 | # fake Kallithea Repository object | |
219 | fake_repo = AttributeDict(dict( |
|
219 | fake_repo = AttributeDict(dict( | |
220 | repo_name=gist_repo.path, |
|
220 | repo_name=gist_repo.path, | |
221 | scm_instance_no_cache=lambda: gist_repo, |
|
221 | scm_instance_no_cache=lambda: gist_repo, |
@@ -38,8 +38,8 b' Session = scoped_session(session_factory' | |||||
38 | # Engine is injected when model.__init__.init_model() sets meta.Base.metadata.bind |
|
38 | # Engine is injected when model.__init__.init_model() sets meta.Base.metadata.bind | |
39 | Base = declarative_base() |
|
39 | Base = declarative_base() | |
40 |
|
40 | |||
41 | #to use cache use this in query |
|
41 | # to use cache use this in query: | |
42 | #.options(FromCache("sqlalchemy_cache_type", "cachekey")) |
|
42 | # .options(FromCache("sqlalchemy_cache_type", "cachekey")) | |
43 |
|
43 | |||
44 |
|
44 | |||
45 | # Define naming conventions for foreign keys, primary keys, indexes, |
|
45 | # Define naming conventions for foreign keys, primary keys, indexes, |
@@ -98,7 +98,7 b' class NotificationModel(object):' | |||||
98 | if not with_email: |
|
98 | if not with_email: | |
99 | return notif |
|
99 | return notif | |
100 |
|
100 | |||
101 | #don't send email to person who created this comment |
|
101 | # don't send email to person who created this comment | |
102 | rec_objs = set(recipients_objs).difference(set([created_by_obj])) |
|
102 | rec_objs = set(recipients_objs).difference(set([created_by_obj])) | |
103 |
|
103 | |||
104 | headers = {} |
|
104 | headers = {} | |
@@ -108,7 +108,7 b' class NotificationModel(object):' | |||||
108 |
|
108 | |||
109 | # send email with notification to all other participants |
|
109 | # send email with notification to all other participants | |
110 | for rec in rec_objs: |
|
110 | for rec in rec_objs: | |
111 |
|
|
111 | # this is passed into template | |
112 | html_kwargs = { |
|
112 | html_kwargs = { | |
113 | 'subject': subject, |
|
113 | 'subject': subject, | |
114 | 'body': h.render_w_mentions(body, repo_name), |
|
114 | 'body': h.render_w_mentions(body, repo_name), | |
@@ -232,7 +232,7 b' class NotificationModel(object):' | |||||
232 | Creates a human readable description based on properties |
|
232 | Creates a human readable description based on properties | |
233 | of notification object |
|
233 | of notification object | |
234 | """ |
|
234 | """ | |
235 | #alias |
|
235 | # alias | |
236 | _n = notification |
|
236 | _n = notification | |
237 |
|
237 | |||
238 | if show_age: |
|
238 | if show_age: |
@@ -116,13 +116,13 b' class PermissionModel(object):' | |||||
116 | .all() |
|
116 | .all() | |
117 | for p in u2p: |
|
117 | for p in u2p: | |
118 | Session().delete(p) |
|
118 | Session().delete(p) | |
119 | #create fresh set of permissions |
|
119 | # create fresh set of permissions | |
120 | for def_perm_key in ['default_repo_perm', |
|
120 | for def_perm_key in ['default_repo_perm', | |
121 | 'default_group_perm', |
|
121 | 'default_group_perm', | |
122 | 'default_user_group_perm', |
|
122 | 'default_user_group_perm', | |
123 | 'default_repo_create', |
|
123 | 'default_repo_create', | |
124 | 'create_on_write', # special case for create repos on write access to group |
|
124 | 'create_on_write', # special case for create repos on write access to group | |
125 | #'default_repo_group_create', #not implemented yet |
|
125 | #'default_repo_group_create', # not implemented yet | |
126 | 'default_user_group_create', |
|
126 | 'default_user_group_create', | |
127 | 'default_fork', |
|
127 | 'default_fork', | |
128 | 'default_register', |
|
128 | 'default_register', | |
@@ -130,7 +130,7 b' class PermissionModel(object):' | |||||
130 | p = _make_new(perm_user, form_result[def_perm_key]) |
|
130 | p = _make_new(perm_user, form_result[def_perm_key]) | |
131 | Session().add(p) |
|
131 | Session().add(p) | |
132 |
|
132 | |||
133 | #stage 3 update all default permissions for repos if checked |
|
133 | # stage 3 update all default permissions for repos if checked | |
134 | if form_result['overwrite_default_repo']: |
|
134 | if form_result['overwrite_default_repo']: | |
135 | _def_name = form_result['default_repo_perm'].split('repository.')[-1] |
|
135 | _def_name = form_result['default_repo_perm'].split('repository.')[-1] | |
136 | _def = Permission.get_by_key('repository.' + _def_name) |
|
136 | _def = Permission.get_by_key('repository.' + _def_name) | |
@@ -139,7 +139,7 b' class PermissionModel(object):' | |||||
139 | .filter(UserRepoToPerm.user == perm_user) \ |
|
139 | .filter(UserRepoToPerm.user == perm_user) \ | |
140 | .all(): |
|
140 | .all(): | |
141 |
|
141 | |||
142 | #don't reset PRIVATE repositories |
|
142 | # don't reset PRIVATE repositories | |
143 | if not r2p.repository.private: |
|
143 | if not r2p.repository.private: | |
144 | r2p.permission = _def |
|
144 | r2p.permission = _def | |
145 |
|
145 |
@@ -61,12 +61,12 b' class PullRequestModel(object):' | |||||
61 | mention_recipients = set(mention_recipients) - reviewers |
|
61 | mention_recipients = set(mention_recipients) - reviewers | |
62 | _assert_valid_reviewers(mention_recipients) |
|
62 | _assert_valid_reviewers(mention_recipients) | |
63 |
|
63 | |||
64 | #members |
|
64 | # members | |
65 | for reviewer in reviewers: |
|
65 | for reviewer in reviewers: | |
66 | prr = PullRequestReviewer(reviewer, pr) |
|
66 | prr = PullRequestReviewer(reviewer, pr) | |
67 | Session().add(prr) |
|
67 | Session().add(prr) | |
68 |
|
68 | |||
69 | #notification to reviewers |
|
69 | # notification to reviewers | |
70 | pr_url = pr.url(canonical=True) |
|
70 | pr_url = pr.url(canonical=True) | |
71 | threading = ['%s-pr-%s@%s' % (pr.other_repo.repo_name, |
|
71 | threading = ['%s-pr-%s@%s' % (pr.other_repo.repo_name, | |
72 | pr.pull_request_id, |
|
72 | pr.pull_request_id, | |
@@ -265,7 +265,7 b' class CreatePullRequestAction(object):' | |||||
265 | # create a ref under refs/pull/ so that commits don't get garbage-collected |
|
265 | # create a ref under refs/pull/ so that commits don't get garbage-collected | |
266 | self.org_repo.scm_instance._repo["refs/pull/%d/head" % pr.pull_request_id] = safe_str(self.org_rev) |
|
266 | self.org_repo.scm_instance._repo["refs/pull/%d/head" % pr.pull_request_id] = safe_str(self.org_rev) | |
267 |
|
267 | |||
268 | #reset state to under-review |
|
268 | # reset state to under-review | |
269 | from kallithea.model.changeset_status import ChangesetStatusModel |
|
269 | from kallithea.model.changeset_status import ChangesetStatusModel | |
270 | from kallithea.model.comment import ChangesetCommentsModel |
|
270 | from kallithea.model.comment import ChangesetCommentsModel | |
271 | comment = ChangesetCommentsModel().create( |
|
271 | comment = ChangesetCommentsModel().create( |
@@ -317,13 +317,13 b' class RepoModel(object):' | |||||
317 | if 'repo_name' in kwargs: |
|
317 | if 'repo_name' in kwargs: | |
318 | cur_repo.repo_name = cur_repo.get_new_name(kwargs['repo_name']) |
|
318 | cur_repo.repo_name = cur_repo.get_new_name(kwargs['repo_name']) | |
319 |
|
319 | |||
320 | #if private flag is set, reset default permission to NONE |
|
320 | # if private flag is set, reset default permission to NONE | |
321 | if kwargs.get('repo_private'): |
|
321 | if kwargs.get('repo_private'): | |
322 | EMPTY_PERM = 'repository.none' |
|
322 | EMPTY_PERM = 'repository.none' | |
323 | RepoModel().grant_user_permission( |
|
323 | RepoModel().grant_user_permission( | |
324 | repo=cur_repo, user='default', perm=EMPTY_PERM |
|
324 | repo=cur_repo, user='default', perm=EMPTY_PERM | |
325 | ) |
|
325 | ) | |
326 | #handle extra fields |
|
326 | # handle extra fields | |
327 | for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), |
|
327 | for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), | |
328 | kwargs): |
|
328 | kwargs): | |
329 | k = RepositoryField.un_prefix_key(field) |
|
329 | k = RepositoryField.un_prefix_key(field) | |
@@ -460,7 +460,7 b' class RepoModel(object):' | |||||
460 | repo=repo, user=member, perm=perm |
|
460 | repo=repo, user=member, perm=perm | |
461 | ) |
|
461 | ) | |
462 | else: |
|
462 | else: | |
463 | #check if we have permissions to alter this usergroup's access |
|
463 | # check if we have permissions to alter this usergroup's access | |
464 | if not check_perms or HasUserGroupPermissionLevel('read')(member): |
|
464 | if not check_perms or HasUserGroupPermissionLevel('read')(member): | |
465 | self.grant_user_group_permission( |
|
465 | self.grant_user_group_permission( | |
466 | repo=repo, group_name=member, perm=perm |
|
466 | repo=repo, group_name=member, perm=perm | |
@@ -472,7 +472,7 b' class RepoModel(object):' | |||||
472 | repo=repo, user=member, perm=perm |
|
472 | repo=repo, user=member, perm=perm | |
473 | ) |
|
473 | ) | |
474 | else: |
|
474 | else: | |
475 | #check if we have permissions to alter this usergroup's access |
|
475 | # check if we have permissions to alter this usergroup's access | |
476 | if not check_perms or HasUserGroupPermissionLevel('read')(member): |
|
476 | if not check_perms or HasUserGroupPermissionLevel('read')(member): | |
477 | self.grant_user_group_permission( |
|
477 | self.grant_user_group_permission( | |
478 | repo=repo, group_name=member, perm=perm |
|
478 | repo=repo, group_name=member, perm=perm |
@@ -125,7 +125,7 b' class RepoGroupModel(object):' | |||||
125 | if force_delete: |
|
125 | if force_delete: | |
126 | shutil.rmtree(rm_path) |
|
126 | shutil.rmtree(rm_path) | |
127 | else: |
|
127 | else: | |
128 |
#archive that group |
|
128 | # archive that group | |
129 | _now = datetime.datetime.now() |
|
129 | _now = datetime.datetime.now() | |
130 | _ms = str(_now.microsecond).rjust(6, '0') |
|
130 | _ms = str(_now.microsecond).rjust(6, '0') | |
131 | _d = 'rm__%s_GROUP_%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms), |
|
131 | _d = 'rm__%s_GROUP_%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms), | |
@@ -254,7 +254,7 b' class RepoGroupModel(object):' | |||||
254 | _set_perm_user(obj, user=member, perm=perm) |
|
254 | _set_perm_user(obj, user=member, perm=perm) | |
255 | ## set for user group |
|
255 | ## set for user group | |
256 | else: |
|
256 | else: | |
257 | #check if we have permissions to alter this usergroup's access |
|
257 | # check if we have permissions to alter this usergroup's access | |
258 | if not check_perms or HasUserGroupPermissionLevel('read')(member): |
|
258 | if not check_perms or HasUserGroupPermissionLevel('read')(member): | |
259 | _set_perm_group(obj, users_group=member, perm=perm) |
|
259 | _set_perm_group(obj, users_group=member, perm=perm) | |
260 | # set new permissions |
|
260 | # set new permissions | |
@@ -262,7 +262,7 b' class RepoGroupModel(object):' | |||||
262 | if member_type == 'user': |
|
262 | if member_type == 'user': | |
263 | _set_perm_user(obj, user=member, perm=perm) |
|
263 | _set_perm_user(obj, user=member, perm=perm) | |
264 | else: |
|
264 | else: | |
265 | #check if we have permissions to alter this usergroup's access |
|
265 | # check if we have permissions to alter this usergroup's access | |
266 | if not check_perms or HasUserGroupPermissionLevel('read')(member): |
|
266 | if not check_perms or HasUserGroupPermissionLevel('read')(member): | |
267 | _set_perm_group(obj, users_group=member, perm=perm) |
|
267 | _set_perm_group(obj, users_group=member, perm=perm) | |
268 | updates.append(obj) |
|
268 | updates.append(obj) | |
@@ -301,7 +301,7 b' class RepoGroupModel(object):' | |||||
301 | # if obj is a Repo fix it's name |
|
301 | # if obj is a Repo fix it's name | |
302 | # this can be potentially heavy operation |
|
302 | # this can be potentially heavy operation | |
303 | for obj in repo_group.recursive_groups_and_repos(): |
|
303 | for obj in repo_group.recursive_groups_and_repos(): | |
304 | #set the value from it's parent |
|
304 | # set the value from it's parent | |
305 | obj.enable_locking = repo_group.enable_locking |
|
305 | obj.enable_locking = repo_group.enable_locking | |
306 | if isinstance(obj, RepoGroup): |
|
306 | if isinstance(obj, RepoGroup): | |
307 | new_name = obj.get_new_name(obj.name) |
|
307 | new_name = obj.get_new_name(obj.name) |
@@ -600,7 +600,7 b' class ScmModel(object):' | |||||
600 | imc.remove(filenode) |
|
600 | imc.remove(filenode) | |
601 | elif op == 'mod': |
|
601 | elif op == 'mod': | |
602 | if filename != old_filename: |
|
602 | if filename != old_filename: | |
603 | #TODO: handle renames, needs vcs lib changes |
|
603 | # TODO: handle renames, needs vcs lib changes | |
604 | imc.remove(filenode) |
|
604 | imc.remove(filenode) | |
605 | imc.add(FileNode(filename, content=content)) |
|
605 | imc.add(FileNode(filename, content=content)) | |
606 | else: |
|
606 | else: | |
@@ -776,6 +776,7 b' class ScmModel(object):' | |||||
776 | else: |
|
776 | else: | |
777 | log.debug('skipping writing hook file') |
|
777 | log.debug('skipping writing hook file') | |
778 |
|
778 | |||
|
779 | ||||
779 | def AvailableRepoGroupChoices(top_perms, repo_group_perm_level, extras=()): |
|
780 | def AvailableRepoGroupChoices(top_perms, repo_group_perm_level, extras=()): | |
780 | """Return group_id,string tuples with choices for all the repo groups where |
|
781 | """Return group_id,string tuples with choices for all the repo groups where | |
781 | the user has the necessary permissions. |
|
782 | the user has the necessary permissions. |
@@ -71,7 +71,7 b' class UserGroupModel(object):' | |||||
71 | user_group=user_group, user=member, perm=perm |
|
71 | user_group=user_group, user=member, perm=perm | |
72 | ) |
|
72 | ) | |
73 | else: |
|
73 | else: | |
74 | #check if we have permissions to alter this usergroup's access |
|
74 | # check if we have permissions to alter this usergroup's access | |
75 | if HasUserGroupPermissionLevel('read')(member): |
|
75 | if HasUserGroupPermissionLevel('read')(member): | |
76 | self.grant_user_group_permission( |
|
76 | self.grant_user_group_permission( | |
77 | target_user_group=user_group, user_group=member, perm=perm |
|
77 | target_user_group=user_group, user_group=member, perm=perm | |
@@ -83,7 +83,7 b' class UserGroupModel(object):' | |||||
83 | user_group=user_group, user=member, perm=perm |
|
83 | user_group=user_group, user=member, perm=perm | |
84 | ) |
|
84 | ) | |
85 | else: |
|
85 | else: | |
86 | #check if we have permissions to alter this usergroup's access |
|
86 | # check if we have permissions to alter this usergroup's access | |
87 | if HasUserGroupPermissionLevel('read')(member): |
|
87 | if HasUserGroupPermissionLevel('read')(member): | |
88 | self.grant_user_group_permission( |
|
88 | self.grant_user_group_permission( | |
89 | target_user_group=user_group, user_group=member, perm=perm |
|
89 | target_user_group=user_group, user_group=member, perm=perm |
@@ -68,6 +68,7 b' def UniqueListFromString():' | |||||
68 |
|
68 | |||
69 | def ValidUsername(edit=False, old_data=None): |
|
69 | def ValidUsername(edit=False, old_data=None): | |
70 | old_data = old_data or {} |
|
70 | old_data = old_data or {} | |
|
71 | ||||
71 | class _validator(formencode.validators.FancyValidator): |
|
72 | class _validator(formencode.validators.FancyValidator): | |
72 | messages = { |
|
73 | messages = { | |
73 | 'username_exists': _('Username "%(username)s" already exists'), |
|
74 | 'username_exists': _('Username "%(username)s" already exists'), | |
@@ -83,7 +84,7 b' def ValidUsername(edit=False, old_data=N' | |||||
83 | if value in ['default', 'new_user']: |
|
84 | if value in ['default', 'new_user']: | |
84 | msg = self.message('system_invalid_username', state, username=value) |
|
85 | msg = self.message('system_invalid_username', state, username=value) | |
85 | raise formencode.Invalid(msg, value, state) |
|
86 | raise formencode.Invalid(msg, value, state) | |
86 | #check if user is unique |
|
87 | # check if user is unique | |
87 | old_un = None |
|
88 | old_un = None | |
88 | if edit: |
|
89 | if edit: | |
89 | old_un = User.get(old_data.get('user_id')).username |
|
90 | old_un = User.get(old_data.get('user_id')).username | |
@@ -126,6 +127,7 b' def ValidRepoUser():' | |||||
126 |
|
127 | |||
127 | def ValidUserGroup(edit=False, old_data=None): |
|
128 | def ValidUserGroup(edit=False, old_data=None): | |
128 | old_data = old_data or {} |
|
129 | old_data = old_data or {} | |
|
130 | ||||
129 | class _validator(formencode.validators.FancyValidator): |
|
131 | class _validator(formencode.validators.FancyValidator): | |
130 | messages = { |
|
132 | messages = { | |
131 | 'invalid_group': _('Invalid user group name'), |
|
133 | 'invalid_group': _('Invalid user group name'), | |
@@ -142,7 +144,7 b' def ValidUserGroup(edit=False, old_data=' | |||||
142 | raise formencode.Invalid(msg, value, state, |
|
144 | raise formencode.Invalid(msg, value, state, | |
143 | error_dict=dict(users_group_name=msg) |
|
145 | error_dict=dict(users_group_name=msg) | |
144 | ) |
|
146 | ) | |
145 | #check if group is unique |
|
147 | # check if group is unique | |
146 | old_ugname = None |
|
148 | old_ugname = None | |
147 | if edit: |
|
149 | if edit: | |
148 | old_id = old_data.get('users_group_id') |
|
150 | old_id = old_data.get('users_group_id') | |
@@ -494,7 +496,7 b' def CanWriteGroup(old_data=None):' | |||||
494 | } |
|
496 | } | |
495 |
|
497 | |||
496 | def _to_python(self, value, state): |
|
498 | def _to_python(self, value, state): | |
497 | #root location |
|
499 | # root location | |
498 | if value == -1: |
|
500 | if value == -1: | |
499 | return None |
|
501 | return None | |
500 | return value |
|
502 | return value | |
@@ -520,7 +522,7 b' def CanWriteGroup(old_data=None):' | |||||
520 | # don't need to check permission if he didn't change the value of |
|
522 | # don't need to check permission if he didn't change the value of | |
521 | # groups in form box |
|
523 | # groups in form box | |
522 | if value_changed or new: |
|
524 | if value_changed or new: | |
523 | #parent group need to be existing |
|
525 | # parent group need to be existing | |
524 | if gr and forbidden: |
|
526 | if gr and forbidden: | |
525 | msg = self.message('permission_denied', state) |
|
527 | msg = self.message('permission_denied', state) | |
526 | raise formencode.Invalid(msg, value, state, |
|
528 | raise formencode.Invalid(msg, value, state, | |
@@ -544,7 +546,7 b' def CanCreateGroup(can_create_in_root=Fa' | |||||
544 | } |
|
546 | } | |
545 |
|
547 | |||
546 | def to_python(self, value, state): |
|
548 | def to_python(self, value, state): | |
547 | #root location |
|
549 | # root location | |
548 | if value == -1: |
|
550 | if value == -1: | |
549 | return None |
|
551 | return None | |
550 | return value |
|
552 | return value | |
@@ -554,7 +556,7 b' def CanCreateGroup(can_create_in_root=Fa' | |||||
554 | gr_name = gr.group_name if gr is not None else None # None means ROOT location |
|
556 | gr_name = gr.group_name if gr is not None else None # None means ROOT location | |
555 |
|
557 | |||
556 | if can_create_in_root and gr is None: |
|
558 | if can_create_in_root and gr is None: | |
557 | #we can create in root, we're fine no validations required |
|
559 | # we can create in root, we're fine no validations required | |
558 | return |
|
560 | return | |
559 |
|
561 | |||
560 | forbidden_in_root = gr is None and not can_create_in_root |
|
562 | forbidden_in_root = gr is None and not can_create_in_root | |
@@ -587,7 +589,7 b" def ValidPerms(type_='repo'):" | |||||
587 | perms_new = OrderedSet() |
|
589 | perms_new = OrderedSet() | |
588 | # build a list of permission to update and new permission to create |
|
590 | # build a list of permission to update and new permission to create | |
589 |
|
591 | |||
590 | #CLEAN OUT ORG VALUE FROM NEW MEMBERS, and group them using |
|
592 | # CLEAN OUT ORG VALUE FROM NEW MEMBERS, and group them using | |
591 | new_perms_group = defaultdict(dict) |
|
593 | new_perms_group = defaultdict(dict) | |
592 | for k, v in value.copy().iteritems(): |
|
594 | for k, v in value.copy().iteritems(): | |
593 | if k.startswith('perm_new_member'): |
|
595 | if k.startswith('perm_new_member'): | |
@@ -768,11 +770,11 b' def ValidIp():' | |||||
768 | v = v.strip() |
|
770 | v = v.strip() | |
769 | net = ipaddr.IPNetwork(address=v) |
|
771 | net = ipaddr.IPNetwork(address=v) | |
770 | if isinstance(net, ipaddr.IPv4Network): |
|
772 | if isinstance(net, ipaddr.IPv4Network): | |
771 | #if IPv4 doesn't end with a mask, add /32 |
|
773 | # if IPv4 doesn't end with a mask, add /32 | |
772 | if '/' not in value: |
|
774 | if '/' not in value: | |
773 | v += '/32' |
|
775 | v += '/32' | |
774 | if isinstance(net, ipaddr.IPv6Network): |
|
776 | if isinstance(net, ipaddr.IPv6Network): | |
775 | #if IPv6 doesn't end with a mask, add /128 |
|
777 | # if IPv6 doesn't end with a mask, add /128 | |
776 | if '/' not in value: |
|
778 | if '/' not in value: | |
777 | v += '/128' |
|
779 | v += '/128' | |
778 | return v |
|
780 | return v | |
@@ -780,7 +782,7 b' def ValidIp():' | |||||
780 | def validate_python(self, value, state): |
|
782 | def validate_python(self, value, state): | |
781 | try: |
|
783 | try: | |
782 | addr = value.strip() |
|
784 | addr = value.strip() | |
783 | #this raises an ValueError if address is not IPv4 or IPv6 |
|
785 | # this raises an ValueError if address is not IPv4 or IPv6 | |
784 | ipaddr.IPNetwork(address=addr) |
|
786 | ipaddr.IPNetwork(address=addr) | |
785 | except ValueError: |
|
787 | except ValueError: | |
786 | raise formencode.Invalid(self.message('badFormat', state), |
|
788 | raise formencode.Invalid(self.message('badFormat', state), |
@@ -2482,7 +2482,7 b' class _BaseTestApi(object):' | |||||
2482 | def test_api_get_changeset(self): |
|
2482 | def test_api_get_changeset(self): | |
2483 | review = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") |
|
2483 | review = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") | |
2484 | id_, params = _build_data(self.apikey, 'get_changeset', |
|
2484 | id_, params = _build_data(self.apikey, 'get_changeset', | |
2485 |
repoid=self.REPO, raw_id |
|
2485 | repoid=self.REPO, raw_id=self.TEST_REVISION) | |
2486 | response = api_call(self, params) |
|
2486 | response = api_call(self, params) | |
2487 | result = json.loads(response.body)["result"] |
|
2487 | result = json.loads(response.body)["result"] | |
2488 | assert result["raw_id"] == self.TEST_REVISION |
|
2488 | assert result["raw_id"] == self.TEST_REVISION | |
@@ -2491,8 +2491,8 b' class _BaseTestApi(object):' | |||||
2491 | def test_api_get_changeset_with_reviews(self): |
|
2491 | def test_api_get_changeset_with_reviews(self): | |
2492 | reviewobjs = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") |
|
2492 | reviewobjs = fixture.review_changeset(self.REPO, self.TEST_REVISION, "approved") | |
2493 | id_, params = _build_data(self.apikey, 'get_changeset', |
|
2493 | id_, params = _build_data(self.apikey, 'get_changeset', | |
2494 |
repoid=self.REPO, raw_id |
|
2494 | repoid=self.REPO, raw_id=self.TEST_REVISION, | |
2495 |
with_reviews |
|
2495 | with_reviews=True) | |
2496 | response = api_call(self, params) |
|
2496 | response = api_call(self, params) | |
2497 | result = json.loads(response.body)["result"] |
|
2497 | result = json.loads(response.body)["result"] | |
2498 | assert result["raw_id"] == self.TEST_REVISION |
|
2498 | assert result["raw_id"] == self.TEST_REVISION | |
@@ -2522,7 +2522,7 b' class _BaseTestApi(object):' | |||||
2522 | RepoModel().revoke_user_permission(repo=self.REPO, user=self.TEST_USER_LOGIN) |
|
2522 | RepoModel().revoke_user_permission(repo=self.REPO, user=self.TEST_USER_LOGIN) | |
2523 | RepoModel().revoke_user_permission(repo=self.REPO, user="default") |
|
2523 | RepoModel().revoke_user_permission(repo=self.REPO, user="default") | |
2524 | id_, params = _build_data(self.apikey_regular, 'get_changeset', |
|
2524 | id_, params = _build_data(self.apikey_regular, 'get_changeset', | |
2525 |
repoid=self.REPO, raw_id |
|
2525 | repoid=self.REPO, raw_id=self.TEST_REVISION) | |
2526 | response = api_call(self, params) |
|
2526 | response = api_call(self, params) | |
2527 | expected = u'Access denied to repo %s' % self.REPO |
|
2527 | expected = u'Access denied to repo %s' % self.REPO | |
2528 | self._compare_error(id_, expected, given=response.body) |
|
2528 | self._compare_error(id_, expected, given=response.body) |
@@ -54,7 +54,7 b' testapp = None' | |||||
54 | # Invoke websetup with the current config file |
|
54 | # Invoke websetup with the current config file | |
55 | # SetupCommand('setup-app').run([config_file]) |
|
55 | # SetupCommand('setup-app').run([config_file]) | |
56 |
|
56 | |||
57 | #SOME GLOBALS FOR TESTS |
|
57 | ## SOME GLOBALS FOR TESTS | |
58 |
|
58 | |||
59 | TESTS_TMP_PATH = os.environ.get('KALLITHEA_TESTS_TMP_PATH', tempfile.mkdtemp(prefix='kallithea-test-')) |
|
59 | TESTS_TMP_PATH = os.environ.get('KALLITHEA_TESTS_TMP_PATH', tempfile.mkdtemp(prefix='kallithea-test-')) | |
60 | os.environ['VCS_TEST_ROOT'] = TESTS_TMP_PATH |
|
60 | os.environ['VCS_TEST_ROOT'] = TESTS_TMP_PATH | |
@@ -106,7 +106,7 b' TEST_HG_REPO_PULL = os.path.join(TESTS_T' | |||||
106 | GIT_REMOTE_REPO = os.path.join(TESTS_TMP_PATH, GIT_REPO) |
|
106 | GIT_REMOTE_REPO = os.path.join(TESTS_TMP_PATH, GIT_REPO) | |
107 | HG_REMOTE_REPO = os.path.join(TESTS_TMP_PATH, HG_REPO) |
|
107 | HG_REMOTE_REPO = os.path.join(TESTS_TMP_PATH, HG_REPO) | |
108 |
|
108 | |||
109 | #skip ldap tests if LDAP lib is not installed |
|
109 | # skip ldap tests if LDAP lib is not installed | |
110 | ldap_lib_installed = False |
|
110 | ldap_lib_installed = False | |
111 | try: |
|
111 | try: | |
112 | import ldap |
|
112 | import ldap | |
@@ -123,6 +123,7 b' try:' | |||||
123 | except ImportError: |
|
123 | except ImportError: | |
124 | pam_lib_installed = False |
|
124 | pam_lib_installed = False | |
125 |
|
125 | |||
|
126 | ||||
126 | def invalidate_all_caches(): |
|
127 | def invalidate_all_caches(): | |
127 | """Invalidate all beaker caches currently configured. |
|
128 | """Invalidate all beaker caches currently configured. | |
128 | Useful when manipulating IP permissions in a test and changes need to take |
|
129 | Useful when manipulating IP permissions in a test and changes need to take | |
@@ -133,10 +134,12 b' def invalidate_all_caches():' | |||||
133 | for cache in cache_managers.values(): |
|
134 | for cache in cache_managers.values(): | |
134 | cache.clear() |
|
135 | cache.clear() | |
135 |
|
136 | |||
|
137 | ||||
136 | class NullHandler(logging.Handler): |
|
138 | class NullHandler(logging.Handler): | |
137 | def emit(self, record): |
|
139 | def emit(self, record): | |
138 | pass |
|
140 | pass | |
139 |
|
141 | |||
|
142 | ||||
140 | class TestController(object): |
|
143 | class TestController(object): | |
141 | """Pytest-style test controller""" |
|
144 | """Pytest-style test controller""" | |
142 |
|
145 |
@@ -23,6 +23,7 b' import kallithea.tests.base # FIXME: nee' | |||||
23 |
|
23 | |||
24 | from tg.util.webtest import test_context |
|
24 | from tg.util.webtest import test_context | |
25 |
|
25 | |||
|
26 | ||||
26 | def pytest_configure(): |
|
27 | def pytest_configure(): | |
27 | os.environ['TZ'] = 'UTC' |
|
28 | os.environ['TZ'] = 'UTC' | |
28 | if not kallithea.is_windows: |
|
29 | if not kallithea.is_windows: | |
@@ -70,10 +71,12 b' def pytest_configure():' | |||||
70 | # set fixed language for form messages, regardless of environment settings |
|
71 | # set fixed language for form messages, regardless of environment settings | |
71 | formencode.api.set_stdtranslation(languages=[]) |
|
72 | formencode.api.set_stdtranslation(languages=[]) | |
72 |
|
73 | |||
|
74 | ||||
73 | @pytest.fixture |
|
75 | @pytest.fixture | |
74 | def create_test_user(): |
|
76 | def create_test_user(): | |
75 | """Provide users that automatically disappear after test is over.""" |
|
77 | """Provide users that automatically disappear after test is over.""" | |
76 | test_user_ids = [] |
|
78 | test_user_ids = [] | |
|
79 | ||||
77 | def _create_test_user(user_form): |
|
80 | def _create_test_user(user_form): | |
78 | user = UserModel().create(user_form) |
|
81 | user = UserModel().create(user_form) | |
79 | test_user_ids.append(user.user_id) |
|
82 | test_user_ids.append(user.user_id) | |
@@ -115,6 +118,7 b' def set_test_settings():' | |||||
115 | Setting.create_or_update(k, v, t) |
|
118 | Setting.create_or_update(k, v, t) | |
116 | session.commit() |
|
119 | session.commit() | |
117 |
|
120 | |||
|
121 | ||||
118 | @pytest.fixture |
|
122 | @pytest.fixture | |
119 | def auto_clear_ip_permissions(): |
|
123 | def auto_clear_ip_permissions(): | |
120 | """Fixture that provides nothing but clearing IP permissions upon test |
|
124 | """Fixture that provides nothing but clearing IP permissions upon test | |
@@ -135,6 +139,7 b' def auto_clear_ip_permissions():' | |||||
135 | # IP permissions are cached, need to invalidate this cache explicitly |
|
139 | # IP permissions are cached, need to invalidate this cache explicitly | |
136 | invalidate_all_caches() |
|
140 | invalidate_all_caches() | |
137 |
|
141 | |||
|
142 | ||||
138 | @pytest.fixture |
|
143 | @pytest.fixture | |
139 | def test_context_fixture(app_fixture): |
|
144 | def test_context_fixture(app_fixture): | |
140 | """ |
|
145 | """ | |
@@ -177,6 +182,7 b' class MyWSGIServer(WSGIServer):' | |||||
177 | auth += '@' |
|
182 | auth += '@' | |
178 | return '%s://%s%s:%s/%s' % (proto, auth, host, port, repo_name) |
|
183 | return '%s://%s%s:%s/%s' % (proto, auth, host, port, repo_name) | |
179 |
|
184 | |||
|
185 | ||||
180 | @pytest.yield_fixture(scope="session") |
|
186 | @pytest.yield_fixture(scope="session") | |
181 | def webserver(): |
|
187 | def webserver(): | |
182 | """Start web server while tests are running. |
|
188 | """Start web server while tests are running. |
@@ -257,11 +257,11 b' class Fixture(object):' | |||||
257 | 'owner': TEST_USER_ADMIN_LOGIN, |
|
257 | 'owner': TEST_USER_ADMIN_LOGIN, | |
258 | 'gist_type': Gist.GIST_PUBLIC, |
|
258 | 'gist_type': Gist.GIST_PUBLIC, | |
259 | 'lifetime': -1, |
|
259 | 'lifetime': -1, | |
260 |
'gist_mapping': {'filename1.txt':{'content':'hello world'} |
|
260 | 'gist_mapping': {'filename1.txt': {'content': 'hello world'}} | |
261 | } |
|
261 | } | |
262 | form_data.update(kwargs) |
|
262 | form_data.update(kwargs) | |
263 | gist = GistModel().create( |
|
263 | gist = GistModel().create( | |
264 | description=form_data['description'],owner=form_data['owner'], |
|
264 | description=form_data['description'], owner=form_data['owner'], | |
265 | gist_mapping=form_data['gist_mapping'], gist_type=form_data['gist_type'], |
|
265 | gist_mapping=form_data['gist_mapping'], gist_type=form_data['gist_type'], | |
266 | lifetime=form_data['lifetime'] |
|
266 | lifetime=form_data['lifetime'] | |
267 | ) |
|
267 | ) | |
@@ -376,7 +376,7 b' def create_test_env(repos_test_path, con' | |||||
376 | idx_path = config['index_dir'] |
|
376 | idx_path = config['index_dir'] | |
377 | data_path = config['cache_dir'] |
|
377 | data_path = config['cache_dir'] | |
378 |
|
378 | |||
379 | #clean index and data |
|
379 | # clean index and data | |
380 | if idx_path and os.path.exists(idx_path): |
|
380 | if idx_path and os.path.exists(idx_path): | |
381 | log.debug('remove %s', idx_path) |
|
381 | log.debug('remove %s', idx_path) | |
382 | shutil.rmtree(idx_path) |
|
382 | shutil.rmtree(idx_path) | |
@@ -385,7 +385,7 b' def create_test_env(repos_test_path, con' | |||||
385 | log.debug('remove %s', data_path) |
|
385 | log.debug('remove %s', data_path) | |
386 | shutil.rmtree(data_path) |
|
386 | shutil.rmtree(data_path) | |
387 |
|
387 | |||
388 | #CREATE DEFAULT TEST REPOS |
|
388 | # CREATE DEFAULT TEST REPOS | |
389 | tar = tarfile.open(os.path.join(FIXTURES, 'vcs_test_hg.tar.gz')) |
|
389 | tar = tarfile.open(os.path.join(FIXTURES, 'vcs_test_hg.tar.gz')) | |
390 | tar.extractall(os.path.join(TESTS_TMP_PATH, HG_REPO)) |
|
390 | tar.extractall(os.path.join(TESTS_TMP_PATH, HG_REPO)) | |
391 | tar.close() |
|
391 | tar.close() | |
@@ -394,7 +394,7 b' def create_test_env(repos_test_path, con' | |||||
394 | tar.extractall(os.path.join(TESTS_TMP_PATH, GIT_REPO)) |
|
394 | tar.extractall(os.path.join(TESTS_TMP_PATH, GIT_REPO)) | |
395 | tar.close() |
|
395 | tar.close() | |
396 |
|
396 | |||
397 | #LOAD VCS test stuff |
|
397 | # LOAD VCS test stuff | |
398 | from kallithea.tests.vcs import setup_package |
|
398 | from kallithea.tests.vcs import setup_package | |
399 | setup_package() |
|
399 | setup_package() | |
400 |
|
400 |
@@ -164,7 +164,6 b' class TestAuthSettingsController(TestCon' | |||||
164 | assert response.form['firstname'].value == 'John' |
|
164 | assert response.form['firstname'].value == 'John' | |
165 | assert response.form['lastname'].value == 'Doe' |
|
165 | assert response.form['lastname'].value == 'Doe' | |
166 |
|
166 | |||
167 |
|
||||
168 | def test_container_auth_login_fallback_header(self): |
|
167 | def test_container_auth_login_fallback_header(self): | |
169 | self._container_auth_setup( |
|
168 | self._container_auth_setup( | |
170 | auth_container_header='THE_USER_NAME', |
|
169 | auth_container_header='THE_USER_NAME', |
@@ -50,7 +50,7 b' class TestGistsController(TestController' | |||||
50 | response = self.app.get(url('gists', private=1)) |
|
50 | response = self.app.get(url('gists', private=1)) | |
51 | # Test response... |
|
51 | # Test response... | |
52 |
|
52 | |||
53 | #and privates |
|
53 | # and privates | |
54 | response.mustcontain('gist: %s' % gist.gist_access_id) |
|
54 | response.mustcontain('gist: %s' % gist.gist_access_id) | |
55 |
|
55 | |||
56 | def test_create_missing_description(self): |
|
56 | def test_create_missing_description(self): |
@@ -8,6 +8,7 b' from kallithea.lib import helpers as h' | |||||
8 |
|
8 | |||
9 | from tg.util.webtest import test_context |
|
9 | from tg.util.webtest import test_context | |
10 |
|
10 | |||
|
11 | ||||
11 | class TestNotificationsController(TestController): |
|
12 | class TestNotificationsController(TestController): | |
12 | def setup_method(self, method): |
|
13 | def setup_method(self, method): | |
13 | self.remove_all_notifications() |
|
14 | self.remove_all_notifications() |
@@ -74,7 +74,6 b' class TestAdminPermissionsController(Tes' | |||||
74 | response.mustcontain(no=['127.0.0.0/24']) |
|
74 | response.mustcontain(no=['127.0.0.0/24']) | |
75 | response.mustcontain(no=['127.0.0.0 - 127.0.0.255']) |
|
75 | response.mustcontain(no=['127.0.0.0 - 127.0.0.255']) | |
76 |
|
76 | |||
77 |
|
||||
78 | def test_index_overview(self): |
|
77 | def test_index_overview(self): | |
79 | self.log_user() |
|
78 | self.log_user() | |
80 | response = self.app.get(url('admin_permissions_perms')) |
|
79 | response = self.app.get(url('admin_permissions_perms')) |
@@ -7,6 +7,7 b' from kallithea.tests.fixture import Fixt' | |||||
7 |
|
7 | |||
8 | fixture = Fixture() |
|
8 | fixture = Fixture() | |
9 |
|
9 | |||
|
10 | ||||
10 | class TestRepoGroupsController(TestController): |
|
11 | class TestRepoGroupsController(TestController): | |
11 |
|
12 | |||
12 | def test_case_insensitivity(self): |
|
13 | def test_case_insensitivity(self): |
@@ -305,7 +305,7 b' class _BaseTestCase(TestController):' | |||||
305 | Session().commit() |
|
305 | Session().commit() | |
306 | pytest.fail('no repo %s in filesystem' % repo_name) |
|
306 | pytest.fail('no repo %s in filesystem' % repo_name) | |
307 |
|
307 | |||
308 | #check if inherited permissiona are applied |
|
308 | # check if inherited permissiona are applied | |
309 | inherited_perms = UserRepoToPerm.query() \ |
|
309 | inherited_perms = UserRepoToPerm.query() \ | |
310 | .filter(UserRepoToPerm.repository_id == new_repo_id).all() |
|
310 | .filter(UserRepoToPerm.repository_id == new_repo_id).all() | |
311 | assert len(inherited_perms) == 2 |
|
311 | assert len(inherited_perms) == 2 | |
@@ -332,7 +332,6 b' class _BaseTestCase(TestController):' | |||||
332 | _authentication_token=self.authentication_token())) |
|
332 | _authentication_token=self.authentication_token())) | |
333 | response.mustcontain('Invalid repository URL') |
|
333 | response.mustcontain('Invalid repository URL') | |
334 |
|
334 | |||
335 |
|
||||
336 | def test_create_remote_repo_wrong_clone_uri_hg_svn(self): |
|
335 | def test_create_remote_repo_wrong_clone_uri_hg_svn(self): | |
337 | self.log_user() |
|
336 | self.log_user() | |
338 | repo_name = self.NEW_REPO |
|
337 | repo_name = self.NEW_REPO | |
@@ -346,7 +345,6 b' class _BaseTestCase(TestController):' | |||||
346 | _authentication_token=self.authentication_token())) |
|
345 | _authentication_token=self.authentication_token())) | |
347 | response.mustcontain('Invalid repository URL') |
|
346 | response.mustcontain('Invalid repository URL') | |
348 |
|
347 | |||
349 |
|
||||
350 | def test_delete(self): |
|
348 | def test_delete(self): | |
351 | self.log_user() |
|
349 | self.log_user() | |
352 | repo_name = u'vcs_test_new_to_delete_%s' % self.REPO_TYPE |
|
350 | repo_name = u'vcs_test_new_to_delete_%s' % self.REPO_TYPE | |
@@ -387,7 +385,7 b' class _BaseTestCase(TestController):' | |||||
387 |
|
385 | |||
388 | response.follow() |
|
386 | response.follow() | |
389 |
|
387 | |||
390 | #check if repo was deleted from db |
|
388 | # check if repo was deleted from db | |
391 | deleted_repo = Session().query(Repository) \ |
|
389 | deleted_repo = Session().query(Repository) \ | |
392 | .filter(Repository.repo_name == repo_name).scalar() |
|
390 | .filter(Repository.repo_name == repo_name).scalar() | |
393 |
|
391 | |||
@@ -437,7 +435,7 b' class _BaseTestCase(TestController):' | |||||
437 | self.checkSessionFlash(response, 'Deleted repository %s' % (repo_name_unicode)) |
|
435 | self.checkSessionFlash(response, 'Deleted repository %s' % (repo_name_unicode)) | |
438 | response.follow() |
|
436 | response.follow() | |
439 |
|
437 | |||
440 | #check if repo was deleted from db |
|
438 | # check if repo was deleted from db | |
441 | deleted_repo = Session().query(Repository) \ |
|
439 | deleted_repo = Session().query(Repository) \ | |
442 | .filter(Repository.repo_name == repo_name_unicode).scalar() |
|
440 | .filter(Repository.repo_name == repo_name_unicode).scalar() | |
443 |
|
441 | |||
@@ -446,7 +444,7 b' class _BaseTestCase(TestController):' | |||||
446 | assert os.path.isdir(os.path.join(Ui.get_by_key('paths', '/').ui_value, repo_name_unicode)) == False |
|
444 | assert os.path.isdir(os.path.join(Ui.get_by_key('paths', '/').ui_value, repo_name_unicode)) == False | |
447 |
|
445 | |||
448 | def test_delete_repo_with_group(self): |
|
446 | def test_delete_repo_with_group(self): | |
449 | #TODO: |
|
447 | # TODO: | |
450 | pass |
|
448 | pass | |
451 |
|
449 | |||
452 | def test_delete_browser_fakeout(self): |
|
450 | def test_delete_browser_fakeout(self): | |
@@ -462,7 +460,7 b' class _BaseTestCase(TestController):' | |||||
462 |
|
460 | |||
463 | def test_set_private_flag_sets_default_to_none(self): |
|
461 | def test_set_private_flag_sets_default_to_none(self): | |
464 | self.log_user() |
|
462 | self.log_user() | |
465 | #initially repository perm should be read |
|
463 | # initially repository perm should be read | |
466 | perm = _get_permission_for_user(user='default', repo=self.REPO) |
|
464 | perm = _get_permission_for_user(user='default', repo=self.REPO) | |
467 | assert len(perm), 1 |
|
465 | assert len(perm), 1 | |
468 | assert perm[0].permission.permission_name == 'repository.read' |
|
466 | assert perm[0].permission.permission_name == 'repository.read' | |
@@ -478,7 +476,7 b' class _BaseTestCase(TestController):' | |||||
478 | msg='Repository %s updated successfully' % (self.REPO)) |
|
476 | msg='Repository %s updated successfully' % (self.REPO)) | |
479 | assert Repository.get_by_repo_name(self.REPO).private == True |
|
477 | assert Repository.get_by_repo_name(self.REPO).private == True | |
480 |
|
478 | |||
481 | #now the repo default permission should be None |
|
479 | # now the repo default permission should be None | |
482 | perm = _get_permission_for_user(user='default', repo=self.REPO) |
|
480 | perm = _get_permission_for_user(user='default', repo=self.REPO) | |
483 | assert len(perm), 1 |
|
481 | assert len(perm), 1 | |
484 | assert perm[0].permission.permission_name == 'repository.none' |
|
482 | assert perm[0].permission.permission_name == 'repository.none' | |
@@ -493,12 +491,12 b' class _BaseTestCase(TestController):' | |||||
493 | msg='Repository %s updated successfully' % (self.REPO)) |
|
491 | msg='Repository %s updated successfully' % (self.REPO)) | |
494 | assert Repository.get_by_repo_name(self.REPO).private == False |
|
492 | assert Repository.get_by_repo_name(self.REPO).private == False | |
495 |
|
493 | |||
496 | #we turn off private now the repo default permission should stay None |
|
494 | # we turn off private now the repo default permission should stay None | |
497 | perm = _get_permission_for_user(user='default', repo=self.REPO) |
|
495 | perm = _get_permission_for_user(user='default', repo=self.REPO) | |
498 | assert len(perm), 1 |
|
496 | assert len(perm), 1 | |
499 | assert perm[0].permission.permission_name == 'repository.none' |
|
497 | assert perm[0].permission.permission_name == 'repository.none' | |
500 |
|
498 | |||
501 | #update this permission back |
|
499 | # update this permission back | |
502 | perm[0].permission = Permission.get_by_key('repository.read') |
|
500 | perm[0].permission = Permission.get_by_key('repository.read') | |
503 | Session().commit() |
|
501 | Session().commit() | |
504 |
|
502 |
@@ -42,7 +42,7 b' class TestAdminUsersGroupsController(Tes' | |||||
42 | self.log_user() |
|
42 | self.log_user() | |
43 | users_group_name = TEST_USER_GROUP + 'another' |
|
43 | users_group_name = TEST_USER_GROUP + 'another' | |
44 | response = self.app.post(url('users_groups'), |
|
44 | response = self.app.post(url('users_groups'), | |
45 | {'users_group_name':users_group_name, |
|
45 | {'users_group_name': users_group_name, | |
46 | 'user_group_description': u'DESC', |
|
46 | 'user_group_description': u'DESC', | |
47 | 'active': True, |
|
47 | 'active': True, | |
48 | '_authentication_token': self.authentication_token()}) |
|
48 | '_authentication_token': self.authentication_token()}) |
@@ -30,6 +30,7 b' from tg.util.webtest import test_context' | |||||
30 |
|
30 | |||
31 | fixture = Fixture() |
|
31 | fixture = Fixture() | |
32 |
|
32 | |||
|
33 | ||||
33 | @pytest.fixture |
|
34 | @pytest.fixture | |
34 | def user_and_repo_group_fail(): |
|
35 | def user_and_repo_group_fail(): | |
35 | username = 'repogrouperr' |
|
36 | username = 'repogrouperr' | |
@@ -44,6 +45,7 b' def user_and_repo_group_fail():' | |||||
44 | # delete already succeeded in test body |
|
45 | # delete already succeeded in test body | |
45 | pass |
|
46 | pass | |
46 |
|
47 | |||
|
48 | ||||
47 | class TestAdminUsersController(TestController): |
|
49 | class TestAdminUsersController(TestController): | |
48 | test_user_1 = 'testme' |
|
50 | test_user_1 = 'testme' | |
49 |
|
51 | |||
@@ -159,14 +161,13 b' class TestAdminUsersController(TestContr' | |||||
159 | if name == 'email': |
|
161 | if name == 'email': | |
160 | params['emails'] = [attrs['email']] |
|
162 | params['emails'] = [attrs['email']] | |
161 | if name == 'extern_type': |
|
163 | if name == 'extern_type': | |
162 | #cannot update this via form, expected value is original one |
|
164 | # cannot update this via form, expected value is original one | |
163 | params['extern_type'] = "internal" |
|
165 | params['extern_type'] = "internal" | |
164 | if name == 'extern_name': |
|
166 | if name == 'extern_name': | |
165 | #cannot update this via form, expected value is original one |
|
167 | # cannot update this via form, expected value is original one | |
166 | params['extern_name'] = self.test_user_1 |
|
168 | params['extern_name'] = self.test_user_1 | |
167 | # special case since this user is not |
|
169 | # special case since this user is not logged in yet his data is | |
168 | # logged in yet his data is not filled |
|
170 | # not filled so we use creation data | |
169 | # so we use creation data |
|
|||
170 |
|
171 | |||
171 | params.update({'_authentication_token': self.authentication_token()}) |
|
172 | params.update({'_authentication_token': self.authentication_token()}) | |
172 | response = self.app.post(url('update_user', id=usr.user_id), params) |
|
173 | response = self.app.post(url('update_user', id=usr.user_id), params) | |
@@ -288,7 +289,7 b' class TestAdminUsersController(TestContr' | |||||
288 | uid = user.user_id |
|
289 | uid = user.user_id | |
289 |
|
290 | |||
290 | try: |
|
291 | try: | |
291 | #User should have None permission on creation repository |
|
292 | # User should have None permission on creation repository | |
292 | assert UserModel().has_perm(user, perm_none) == False |
|
293 | assert UserModel().has_perm(user, perm_none) == False | |
293 | assert UserModel().has_perm(user, perm_create) == False |
|
294 | assert UserModel().has_perm(user, perm_create) == False | |
294 |
|
295 | |||
@@ -299,7 +300,7 b' class TestAdminUsersController(TestContr' | |||||
299 | perm_none = Permission.get_by_key('hg.create.none') |
|
300 | perm_none = Permission.get_by_key('hg.create.none') | |
300 | perm_create = Permission.get_by_key('hg.create.repository') |
|
301 | perm_create = Permission.get_by_key('hg.create.repository') | |
301 |
|
302 | |||
302 | #User should have None permission on creation repository |
|
303 | # User should have None permission on creation repository | |
303 | assert UserModel().has_perm(uid, perm_none) == False |
|
304 | assert UserModel().has_perm(uid, perm_none) == False | |
304 | assert UserModel().has_perm(uid, perm_create) == True |
|
305 | assert UserModel().has_perm(uid, perm_create) == True | |
305 | finally: |
|
306 | finally: | |
@@ -318,7 +319,7 b' class TestAdminUsersController(TestContr' | |||||
318 | uid = user.user_id |
|
319 | uid = user.user_id | |
319 |
|
320 | |||
320 | try: |
|
321 | try: | |
321 | #User should have None permission on creation repository |
|
322 | # User should have None permission on creation repository | |
322 | assert UserModel().has_perm(user, perm_none) == False |
|
323 | assert UserModel().has_perm(user, perm_none) == False | |
323 | assert UserModel().has_perm(user, perm_create) == False |
|
324 | assert UserModel().has_perm(user, perm_create) == False | |
324 |
|
325 | |||
@@ -328,7 +329,7 b' class TestAdminUsersController(TestContr' | |||||
328 | perm_none = Permission.get_by_key('hg.create.none') |
|
329 | perm_none = Permission.get_by_key('hg.create.none') | |
329 | perm_create = Permission.get_by_key('hg.create.repository') |
|
330 | perm_create = Permission.get_by_key('hg.create.repository') | |
330 |
|
331 | |||
331 | #User should have None permission on creation repository |
|
332 | # User should have None permission on creation repository | |
332 | assert UserModel().has_perm(uid, perm_none) == True |
|
333 | assert UserModel().has_perm(uid, perm_none) == True | |
333 | assert UserModel().has_perm(uid, perm_create) == False |
|
334 | assert UserModel().has_perm(uid, perm_create) == False | |
334 | finally: |
|
335 | finally: | |
@@ -347,7 +348,7 b' class TestAdminUsersController(TestContr' | |||||
347 | uid = user.user_id |
|
348 | uid = user.user_id | |
348 |
|
349 | |||
349 | try: |
|
350 | try: | |
350 | #User should have None permission on creation repository |
|
351 | # User should have None permission on creation repository | |
351 | assert UserModel().has_perm(user, perm_none) == False |
|
352 | assert UserModel().has_perm(user, perm_none) == False | |
352 | assert UserModel().has_perm(user, perm_fork) == False |
|
353 | assert UserModel().has_perm(user, perm_fork) == False | |
353 |
|
354 | |||
@@ -358,7 +359,7 b' class TestAdminUsersController(TestContr' | |||||
358 | perm_none = Permission.get_by_key('hg.create.none') |
|
359 | perm_none = Permission.get_by_key('hg.create.none') | |
359 | perm_create = Permission.get_by_key('hg.create.repository') |
|
360 | perm_create = Permission.get_by_key('hg.create.repository') | |
360 |
|
361 | |||
361 | #User should have None permission on creation repository |
|
362 | # User should have None permission on creation repository | |
362 | assert UserModel().has_perm(uid, perm_none) == False |
|
363 | assert UserModel().has_perm(uid, perm_none) == False | |
363 | assert UserModel().has_perm(uid, perm_create) == True |
|
364 | assert UserModel().has_perm(uid, perm_create) == True | |
364 | finally: |
|
365 | finally: | |
@@ -377,7 +378,7 b' class TestAdminUsersController(TestContr' | |||||
377 | uid = user.user_id |
|
378 | uid = user.user_id | |
378 |
|
379 | |||
379 | try: |
|
380 | try: | |
380 | #User should have None permission on creation repository |
|
381 | # User should have None permission on creation repository | |
381 | assert UserModel().has_perm(user, perm_none) == False |
|
382 | assert UserModel().has_perm(user, perm_none) == False | |
382 | assert UserModel().has_perm(user, perm_fork) == False |
|
383 | assert UserModel().has_perm(user, perm_fork) == False | |
383 |
|
384 | |||
@@ -387,7 +388,7 b' class TestAdminUsersController(TestContr' | |||||
387 | perm_none = Permission.get_by_key('hg.create.none') |
|
388 | perm_none = Permission.get_by_key('hg.create.none') | |
388 | perm_create = Permission.get_by_key('hg.create.repository') |
|
389 | perm_create = Permission.get_by_key('hg.create.repository') | |
389 |
|
390 | |||
390 | #User should have None permission on creation repository |
|
391 | # User should have None permission on creation repository | |
391 | assert UserModel().has_perm(uid, perm_none) == True |
|
392 | assert UserModel().has_perm(uid, perm_none) == True | |
392 | assert UserModel().has_perm(uid, perm_create) == False |
|
393 | assert UserModel().has_perm(uid, perm_create) == False | |
393 | finally: |
|
394 | finally: | |
@@ -491,7 +492,7 b' class TestAdminUsersController(TestContr' | |||||
491 | self.checkSessionFlash(response, 'API key successfully created') |
|
492 | self.checkSessionFlash(response, 'API key successfully created') | |
492 | response = response.follow() |
|
493 | response = response.follow() | |
493 |
|
494 | |||
494 | #now delete our key |
|
495 | # now delete our key | |
495 | keys = UserApiKeys.query().filter(UserApiKeys.user_id == user_id).all() |
|
496 | keys = UserApiKeys.query().filter(UserApiKeys.user_id == user_id).all() | |
496 | assert 1 == len(keys) |
|
497 | assert 1 == len(keys) | |
497 |
|
498 |
@@ -15,7 +15,7 b' class TestChangelogController(TestContro' | |||||
15 | """name="7b22a518347bb9bc19679f6af07cd0a61bfe16e7" """ |
|
15 | """name="7b22a518347bb9bc19679f6af07cd0a61bfe16e7" """ | |
16 | """type="checkbox" value="1" />""" |
|
16 | """type="checkbox" value="1" />""" | |
17 | ) |
|
17 | ) | |
18 | #rev 640: code garden |
|
18 | # rev 640: code garden | |
19 | response.mustcontain( |
|
19 | response.mustcontain( | |
20 | """<a class="changeset_hash" href="/%s/changeset/0a4e54a4460401d6dbbd6a3604b17cd2b3606b82">r640:0a4e54a44604</a>""" % HG_REPO |
|
20 | """<a class="changeset_hash" href="/%s/changeset/0a4e54a4460401d6dbbd6a3604b17cd2b3606b82">r640:0a4e54a44604</a>""" % HG_REPO | |
21 | ) |
|
21 | ) | |
@@ -25,7 +25,7 b' class TestChangelogController(TestContro' | |||||
25 |
|
25 | |||
26 | def test_index_pagination_hg(self): |
|
26 | def test_index_pagination_hg(self): | |
27 | self.log_user() |
|
27 | self.log_user() | |
28 | #pagination |
|
28 | # pagination | |
29 | self.app.get(url(controller='changelog', action='index', |
|
29 | self.app.get(url(controller='changelog', action='index', | |
30 | repo_name=HG_REPO), {'page': 1}) |
|
30 | repo_name=HG_REPO), {'page': 1}) | |
31 | self.app.get(url(controller='changelog', action='index', |
|
31 | self.app.get(url(controller='changelog', action='index', | |
@@ -81,7 +81,7 b' class TestChangelogController(TestContro' | |||||
81 |
|
81 | |||
82 | def test_index_pagination_git(self): |
|
82 | def test_index_pagination_git(self): | |
83 | self.log_user() |
|
83 | self.log_user() | |
84 | #pagination |
|
84 | # pagination | |
85 | self.app.get(url(controller='changelog', action='index', |
|
85 | self.app.get(url(controller='changelog', action='index', | |
86 | repo_name=GIT_REPO), {'page': 1}) |
|
86 | repo_name=GIT_REPO), {'page': 1}) | |
87 | self.app.get(url(controller='changelog', action='index', |
|
87 | self.app.get(url(controller='changelog', action='index', | |
@@ -112,7 +112,7 b' class TestChangelogController(TestContro' | |||||
112 | response = self.app.get(url(controller='changelog', action='index', |
|
112 | response = self.app.get(url(controller='changelog', action='index', | |
113 | revision='tip', f_path='/vcs/exceptions.py', |
|
113 | revision='tip', f_path='/vcs/exceptions.py', | |
114 | repo_name=HG_REPO)) |
|
114 | repo_name=HG_REPO)) | |
115 | #history commits messages |
|
115 | # history commits messages | |
116 | response.mustcontain('Added exceptions module, this time for real') |
|
116 | response.mustcontain('Added exceptions module, this time for real') | |
117 | response.mustcontain('Added not implemented hg backend test case') |
|
117 | response.mustcontain('Added not implemented hg backend test case') | |
118 | response.mustcontain('Added BaseChangeset class') |
|
118 | response.mustcontain('Added BaseChangeset class') | |
@@ -123,7 +123,7 b' class TestChangelogController(TestContro' | |||||
123 | response = self.app.get(url(controller='changelog', action='index', |
|
123 | response = self.app.get(url(controller='changelog', action='index', | |
124 | revision='tip', f_path='/vcs/exceptions.py', |
|
124 | revision='tip', f_path='/vcs/exceptions.py', | |
125 | repo_name=GIT_REPO)) |
|
125 | repo_name=GIT_REPO)) | |
126 | #history commits messages |
|
126 | # history commits messages | |
127 | response.mustcontain('Added exceptions module, this time for real') |
|
127 | response.mustcontain('Added exceptions module, this time for real') | |
128 | response.mustcontain('Added not implemented hg backend test case') |
|
128 | response.mustcontain('Added not implemented hg backend test case') | |
129 | response.mustcontain('Added BaseChangeset class') |
|
129 | response.mustcontain('Added BaseChangeset class') |
@@ -62,7 +62,7 b' class TestChangeSetCommentsController(Te' | |||||
62 |
|
62 | |||
63 | response = self.app.get(url(controller='changeset', action='index', |
|
63 | response = self.app.get(url(controller='changeset', action='index', | |
64 | repo_name=HG_REPO, revision=rev)) |
|
64 | repo_name=HG_REPO, revision=rev)) | |
65 | #test DB |
|
65 | # test DB | |
66 | assert ChangesetComment.query().count() == 1 |
|
66 | assert ChangesetComment.query().count() == 1 | |
67 | response.mustcontain( |
|
67 | response.mustcontain( | |
68 | '''<div class="comments-number">''' |
|
68 | '''<div class="comments-number">''' |
@@ -6,6 +6,7 b' from kallithea.tests.fixture import Fixt' | |||||
6 |
|
6 | |||
7 | fixture = Fixture() |
|
7 | fixture = Fixture() | |
8 |
|
8 | |||
|
9 | ||||
9 | def _commit_ref(repo_name, sha, msg): |
|
10 | def _commit_ref(repo_name, sha, msg): | |
10 | return '''<div class="message-firstline"><a class="message-link" href="/%s/changeset/%s">%s</a></div>''' % (repo_name, sha, msg) |
|
11 | return '''<div class="message-firstline"><a class="message-link" href="/%s/changeset/%s">%s</a></div>''' % (repo_name, sha, msg) | |
11 |
|
12 | |||
@@ -30,16 +31,16 b' class TestCompareController(TestControll' | |||||
30 | repo_description='diff-test', |
|
31 | repo_description='diff-test', | |
31 | cur_user=TEST_USER_ADMIN_LOGIN) |
|
32 | cur_user=TEST_USER_ADMIN_LOGIN) | |
32 | self.r1_id = repo1.repo_id |
|
33 | self.r1_id = repo1.repo_id | |
33 | #commit something ! |
|
34 | # commit something ! | |
34 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
35 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', | |
35 | content='line1\n', message='commit1', vcs_type='hg', |
|
36 | content='line1\n', message='commit1', vcs_type='hg', | |
36 | parent=None, newfile=True) |
|
37 | parent=None, newfile=True) | |
37 |
|
38 | |||
38 | #fork this repo |
|
39 | # fork this repo | |
39 | repo2 = fixture.create_fork(u'one', u'one-fork') |
|
40 | repo2 = fixture.create_fork(u'one', u'one-fork') | |
40 | self.r2_id = repo2.repo_id |
|
41 | self.r2_id = repo2.repo_id | |
41 |
|
42 | |||
42 | #add two extra commit into fork |
|
43 | # add two extra commit into fork | |
43 | cs1 = fixture.commit_change(repo2.repo_name, filename='file1', |
|
44 | cs1 = fixture.commit_change(repo2.repo_name, filename='file1', | |
44 | content='line1\nline2\n', message='commit2', vcs_type='hg', |
|
45 | content='line1\nline2\n', message='commit2', vcs_type='hg', | |
45 | parent=cs0) |
|
46 | parent=cs0) | |
@@ -72,7 +73,7 b' class TestCompareController(TestControll' | |||||
72 | response.mustcontain("""<a class="changeset_hash" href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id)) |
|
73 | response.mustcontain("""<a class="changeset_hash" href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id)) | |
73 | ## files |
|
74 | ## files | |
74 | response.mustcontain("""<a href="#C--826e8142e6ba">file1</a>""") |
|
75 | response.mustcontain("""<a href="#C--826e8142e6ba">file1</a>""") | |
75 | #swap |
|
76 | # swap | |
76 | response.mustcontain("""<a class="btn btn-default btn-sm" href="/%s/compare/branch@%s...branch@%s?other_repo=%s&merge=True"><i class="icon-arrows-cw"></i> Swap</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name)) |
|
77 | response.mustcontain("""<a class="btn btn-default btn-sm" href="/%s/compare/branch@%s...branch@%s?other_repo=%s&merge=True"><i class="icon-arrows-cw"></i> Swap</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name)) | |
77 |
|
78 | |||
78 | def test_compare_forks_on_branch_extra_commits_git(self): |
|
79 | def test_compare_forks_on_branch_extra_commits_git(self): | |
@@ -81,16 +82,16 b' class TestCompareController(TestControll' | |||||
81 | repo_description='diff-test', |
|
82 | repo_description='diff-test', | |
82 | cur_user=TEST_USER_ADMIN_LOGIN) |
|
83 | cur_user=TEST_USER_ADMIN_LOGIN) | |
83 | self.r1_id = repo1.repo_id |
|
84 | self.r1_id = repo1.repo_id | |
84 | #commit something ! |
|
85 | # commit something ! | |
85 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
86 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', | |
86 | content='line1\n', message='commit1', vcs_type='git', |
|
87 | content='line1\n', message='commit1', vcs_type='git', | |
87 | parent=None, newfile=True) |
|
88 | parent=None, newfile=True) | |
88 |
|
89 | |||
89 | #fork this repo |
|
90 | # fork this repo | |
90 | repo2 = fixture.create_fork(u'one-git', u'one-git-fork') |
|
91 | repo2 = fixture.create_fork(u'one-git', u'one-git-fork') | |
91 | self.r2_id = repo2.repo_id |
|
92 | self.r2_id = repo2.repo_id | |
92 |
|
93 | |||
93 | #add two extra commit into fork |
|
94 | # add two extra commit into fork | |
94 | cs1 = fixture.commit_change(repo2.repo_name, filename='file1', |
|
95 | cs1 = fixture.commit_change(repo2.repo_name, filename='file1', | |
95 | content='line1\nline2\n', message='commit2', vcs_type='git', |
|
96 | content='line1\nline2\n', message='commit2', vcs_type='git', | |
96 | parent=cs0) |
|
97 | parent=cs0) | |
@@ -123,7 +124,7 b' class TestCompareController(TestControll' | |||||
123 | response.mustcontain("""<a class="changeset_hash" href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id)) |
|
124 | response.mustcontain("""<a class="changeset_hash" href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id)) | |
124 | ## files |
|
125 | ## files | |
125 | response.mustcontain("""<a href="#C--826e8142e6ba">file1</a>""") |
|
126 | response.mustcontain("""<a href="#C--826e8142e6ba">file1</a>""") | |
126 | #swap |
|
127 | # swap | |
127 | response.mustcontain("""<a class="btn btn-default btn-sm" href="/%s/compare/branch@%s...branch@%s?other_repo=%s&merge=True"><i class="icon-arrows-cw"></i> Swap</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name)) |
|
128 | response.mustcontain("""<a class="btn btn-default btn-sm" href="/%s/compare/branch@%s...branch@%s?other_repo=%s&merge=True"><i class="icon-arrows-cw"></i> Swap</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name)) | |
128 |
|
129 | |||
129 | def test_compare_forks_on_branch_extra_commits_origin_has_incoming_hg(self): |
|
130 | def test_compare_forks_on_branch_extra_commits_origin_has_incoming_hg(self): | |
@@ -135,21 +136,21 b' class TestCompareController(TestControll' | |||||
135 |
|
136 | |||
136 | self.r1_id = repo1.repo_id |
|
137 | self.r1_id = repo1.repo_id | |
137 |
|
138 | |||
138 | #commit something ! |
|
139 | # commit something ! | |
139 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
140 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', | |
140 | content='line1\n', message='commit1', vcs_type='hg', |
|
141 | content='line1\n', message='commit1', vcs_type='hg', | |
141 | parent=None, newfile=True) |
|
142 | parent=None, newfile=True) | |
142 |
|
143 | |||
143 | #fork this repo |
|
144 | # fork this repo | |
144 | repo2 = fixture.create_fork(u'one', u'one-fork') |
|
145 | repo2 = fixture.create_fork(u'one', u'one-fork') | |
145 | self.r2_id = repo2.repo_id |
|
146 | self.r2_id = repo2.repo_id | |
146 |
|
147 | |||
147 | #now commit something to origin repo |
|
148 | # now commit something to origin repo | |
148 | cs1_prim = fixture.commit_change(repo1.repo_name, filename='file2', |
|
149 | cs1_prim = fixture.commit_change(repo1.repo_name, filename='file2', | |
149 | content='line1file2\n', message='commit2', vcs_type='hg', |
|
150 | content='line1file2\n', message='commit2', vcs_type='hg', | |
150 | parent=cs0, newfile=True) |
|
151 | parent=cs0, newfile=True) | |
151 |
|
152 | |||
152 | #add two extra commit into fork |
|
153 | # add two extra commit into fork | |
153 | cs1 = fixture.commit_change(repo2.repo_name, filename='file1', |
|
154 | cs1 = fixture.commit_change(repo2.repo_name, filename='file1', | |
154 | content='line1\nline2\n', message='commit2', vcs_type='hg', |
|
155 | content='line1\nline2\n', message='commit2', vcs_type='hg', | |
155 | parent=cs0) |
|
156 | parent=cs0) | |
@@ -182,7 +183,7 b' class TestCompareController(TestControll' | |||||
182 | response.mustcontain("""<a class="changeset_hash" href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id)) |
|
183 | response.mustcontain("""<a class="changeset_hash" href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id)) | |
183 | ## files |
|
184 | ## files | |
184 | response.mustcontain("""<a href="#C--826e8142e6ba">file1</a>""") |
|
185 | response.mustcontain("""<a href="#C--826e8142e6ba">file1</a>""") | |
185 | #swap |
|
186 | # swap | |
186 | response.mustcontain("""<a class="btn btn-default btn-sm" href="/%s/compare/branch@%s...branch@%s?other_repo=%s&merge=True"><i class="icon-arrows-cw"></i> Swap</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name)) |
|
187 | response.mustcontain("""<a class="btn btn-default btn-sm" href="/%s/compare/branch@%s...branch@%s?other_repo=%s&merge=True"><i class="icon-arrows-cw"></i> Swap</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name)) | |
187 |
|
188 | |||
188 | def test_compare_forks_on_branch_extra_commits_origin_has_incoming_git(self): |
|
189 | def test_compare_forks_on_branch_extra_commits_origin_has_incoming_git(self): | |
@@ -194,21 +195,21 b' class TestCompareController(TestControll' | |||||
194 |
|
195 | |||
195 | self.r1_id = repo1.repo_id |
|
196 | self.r1_id = repo1.repo_id | |
196 |
|
197 | |||
197 | #commit something ! |
|
198 | # commit something ! | |
198 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
199 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', | |
199 | content='line1\n', message='commit1', vcs_type='git', |
|
200 | content='line1\n', message='commit1', vcs_type='git', | |
200 | parent=None, newfile=True) |
|
201 | parent=None, newfile=True) | |
201 |
|
202 | |||
202 | #fork this repo |
|
203 | # fork this repo | |
203 | repo2 = fixture.create_fork(u'one-git', u'one-git-fork') |
|
204 | repo2 = fixture.create_fork(u'one-git', u'one-git-fork') | |
204 | self.r2_id = repo2.repo_id |
|
205 | self.r2_id = repo2.repo_id | |
205 |
|
206 | |||
206 | #now commit something to origin repo |
|
207 | # now commit something to origin repo | |
207 | cs1_prim = fixture.commit_change(repo1.repo_name, filename='file2', |
|
208 | cs1_prim = fixture.commit_change(repo1.repo_name, filename='file2', | |
208 | content='line1file2\n', message='commit2', vcs_type='git', |
|
209 | content='line1file2\n', message='commit2', vcs_type='git', | |
209 | parent=cs0, newfile=True) |
|
210 | parent=cs0, newfile=True) | |
210 |
|
211 | |||
211 | #add two extra commit into fork |
|
212 | # add two extra commit into fork | |
212 | cs1 = fixture.commit_change(repo2.repo_name, filename='file1', |
|
213 | cs1 = fixture.commit_change(repo2.repo_name, filename='file1', | |
213 | content='line1\nline2\n', message='commit2', vcs_type='git', |
|
214 | content='line1\nline2\n', message='commit2', vcs_type='git', | |
214 | parent=cs0) |
|
215 | parent=cs0) | |
@@ -241,11 +242,11 b' class TestCompareController(TestControll' | |||||
241 | response.mustcontain("""<a class="changeset_hash" href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id)) |
|
242 | response.mustcontain("""<a class="changeset_hash" href="/%s/changeset/%s">r2:%s</a>""" % (repo2.repo_name, cs2.raw_id, cs2.short_id)) | |
242 | ## files |
|
243 | ## files | |
243 | response.mustcontain("""<a href="#C--826e8142e6ba">file1</a>""") |
|
244 | response.mustcontain("""<a href="#C--826e8142e6ba">file1</a>""") | |
244 | #swap |
|
245 | # swap | |
245 | response.mustcontain("""<a class="btn btn-default btn-sm" href="/%s/compare/branch@%s...branch@%s?other_repo=%s&merge=True"><i class="icon-arrows-cw"></i> Swap</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name)) |
|
246 | response.mustcontain("""<a class="btn btn-default btn-sm" href="/%s/compare/branch@%s...branch@%s?other_repo=%s&merge=True"><i class="icon-arrows-cw"></i> Swap</a>""" % (repo2.repo_name, rev1, rev2, repo1.repo_name)) | |
246 |
|
247 | |||
247 | def test_compare_cherry_pick_changesets_from_bottom(self): |
|
248 | def test_compare_cherry_pick_changesets_from_bottom(self): | |
248 |
|
249 | pass | ||
249 | # repo1: |
|
250 | # repo1: | |
250 | # cs0: |
|
251 | # cs0: | |
251 | # cs1: |
|
252 | # cs1: | |
@@ -256,7 +257,7 b' class TestCompareController(TestControll' | |||||
256 | # cs3: x |
|
257 | # cs3: x | |
257 | # cs4: x |
|
258 | # cs4: x | |
258 | # cs5: |
|
259 | # cs5: | |
259 | #make repo1, and cs1+cs2 |
|
260 | # make repo1, and cs1+cs2 | |
260 | self.log_user() |
|
261 | self.log_user() | |
261 |
|
262 | |||
262 | repo1 = fixture.create_repo(u'repo1', repo_type='hg', |
|
263 | repo1 = fixture.create_repo(u'repo1', repo_type='hg', | |
@@ -264,17 +265,17 b' class TestCompareController(TestControll' | |||||
264 | cur_user=TEST_USER_ADMIN_LOGIN) |
|
265 | cur_user=TEST_USER_ADMIN_LOGIN) | |
265 | self.r1_id = repo1.repo_id |
|
266 | self.r1_id = repo1.repo_id | |
266 |
|
267 | |||
267 | #commit something ! |
|
268 | # commit something ! | |
268 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
269 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', | |
269 | content='line1\n', message='commit1', vcs_type='hg', |
|
270 | content='line1\n', message='commit1', vcs_type='hg', | |
270 | parent=None, newfile=True) |
|
271 | parent=None, newfile=True) | |
271 | cs1 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
272 | cs1 = fixture.commit_change(repo1.repo_name, filename='file1', | |
272 | content='line1\nline2\n', message='commit2', vcs_type='hg', |
|
273 | content='line1\nline2\n', message='commit2', vcs_type='hg', | |
273 | parent=cs0) |
|
274 | parent=cs0) | |
274 | #fork this repo |
|
275 | # fork this repo | |
275 | repo2 = fixture.create_fork(u'repo1', u'repo1-fork') |
|
276 | repo2 = fixture.create_fork(u'repo1', u'repo1-fork') | |
276 | self.r2_id = repo2.repo_id |
|
277 | self.r2_id = repo2.repo_id | |
277 | #now make cs3-6 |
|
278 | # now make cs3-6 | |
278 | cs2 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
279 | cs2 = fixture.commit_change(repo1.repo_name, filename='file1', | |
279 | content='line1\nline2\nline3\n', message='commit3', |
|
280 | content='line1\nline2\nline3\n', message='commit3', | |
280 | vcs_type='hg', parent=cs1) |
|
281 | vcs_type='hg', parent=cs1) | |
@@ -313,6 +314,7 b' class TestCompareController(TestControll' | |||||
313 | response.mustcontain("""#C--826e8142e6ba">file1</a>""") |
|
314 | response.mustcontain("""#C--826e8142e6ba">file1</a>""") | |
314 |
|
315 | |||
315 | def test_compare_cherry_pick_changesets_from_top(self): |
|
316 | def test_compare_cherry_pick_changesets_from_top(self): | |
|
317 | pass | |||
316 | # repo1: |
|
318 | # repo1: | |
317 | # cs0: |
|
319 | # cs0: | |
318 | # cs1: |
|
320 | # cs1: | |
@@ -324,24 +326,24 b' class TestCompareController(TestControll' | |||||
324 | # cs4: x |
|
326 | # cs4: x | |
325 | # cs5: x |
|
327 | # cs5: x | |
326 | # |
|
328 | # | |
327 | #make repo1, and cs1+cs2 |
|
329 | # make repo1, and cs1+cs2 | |
328 | self.log_user() |
|
330 | self.log_user() | |
329 | repo1 = fixture.create_repo(u'repo1', repo_type='hg', |
|
331 | repo1 = fixture.create_repo(u'repo1', repo_type='hg', | |
330 | repo_description='diff-test', |
|
332 | repo_description='diff-test', | |
331 | cur_user=TEST_USER_ADMIN_LOGIN) |
|
333 | cur_user=TEST_USER_ADMIN_LOGIN) | |
332 | self.r1_id = repo1.repo_id |
|
334 | self.r1_id = repo1.repo_id | |
333 |
|
335 | |||
334 | #commit something ! |
|
336 | # commit something ! | |
335 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
337 | cs0 = fixture.commit_change(repo1.repo_name, filename='file1', | |
336 | content='line1\n', message='commit1', vcs_type='hg', |
|
338 | content='line1\n', message='commit1', vcs_type='hg', | |
337 | parent=None, newfile=True) |
|
339 | parent=None, newfile=True) | |
338 | cs1 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
340 | cs1 = fixture.commit_change(repo1.repo_name, filename='file1', | |
339 | content='line1\nline2\n', message='commit2', vcs_type='hg', |
|
341 | content='line1\nline2\n', message='commit2', vcs_type='hg', | |
340 | parent=cs0) |
|
342 | parent=cs0) | |
341 | #fork this repo |
|
343 | # fork this repo | |
342 | repo2 = fixture.create_fork(u'repo1', u'repo1-fork') |
|
344 | repo2 = fixture.create_fork(u'repo1', u'repo1-fork') | |
343 | self.r2_id = repo2.repo_id |
|
345 | self.r2_id = repo2.repo_id | |
344 | #now make cs3-6 |
|
346 | # now make cs3-6 | |
345 | cs2 = fixture.commit_change(repo1.repo_name, filename='file1', |
|
347 | cs2 = fixture.commit_change(repo1.repo_name, filename='file1', | |
346 | content='line1\nline2\nline3\n', message='commit3', |
|
348 | content='line1\nline2\nline3\n', message='commit3', | |
347 | vcs_type='hg', parent=cs1) |
|
349 | vcs_type='hg', parent=cs1) | |
@@ -379,7 +381,7 b' class TestCompareController(TestControll' | |||||
379 | response.mustcontain("""#C--826e8142e6ba">file1</a>""") |
|
381 | response.mustcontain("""#C--826e8142e6ba">file1</a>""") | |
380 |
|
382 | |||
381 | def test_compare_cherry_pick_changeset_mixed_branches(self): |
|
383 | def test_compare_cherry_pick_changeset_mixed_branches(self): | |
382 | #TODO: write this |
|
384 | # TODO: write this | |
383 | assert 1 |
|
385 | assert 1 | |
384 |
|
386 | |||
385 | def test_compare_remote_branches_hg(self): |
|
387 | def test_compare_remote_branches_hg(self): | |
@@ -456,7 +458,7 b' class TestCompareController(TestControll' | |||||
456 | content='line1', message='commit1', vcs_type='hg', newfile=True) |
|
458 | content='line1', message='commit1', vcs_type='hg', newfile=True) | |
457 | Session().commit() |
|
459 | Session().commit() | |
458 | assert repo1.scm_instance.revisions == [cs0.raw_id] |
|
460 | assert repo1.scm_instance.revisions == [cs0.raw_id] | |
459 | #fork the repo1 |
|
461 | # fork the repo1 | |
460 | repo2 = fixture.create_repo(u'one-fork', repo_type='hg', |
|
462 | repo2 = fixture.create_repo(u'one-fork', repo_type='hg', | |
461 | repo_description='diff-test', |
|
463 | repo_description='diff-test', | |
462 | cur_user=TEST_USER_ADMIN_LOGIN, |
|
464 | cur_user=TEST_USER_ADMIN_LOGIN, | |
@@ -478,7 +480,7 b' class TestCompareController(TestControll' | |||||
478 | cs3 = fixture.commit_change(repo=r2_name, filename='file3-fork', |
|
480 | cs3 = fixture.commit_change(repo=r2_name, filename='file3-fork', | |
479 | content='file3-line1-from-fork', message='commit3-fork', |
|
481 | content='file3-line1-from-fork', message='commit3-fork', | |
480 | vcs_type='hg', parent=cs2, newfile=True) |
|
482 | vcs_type='hg', parent=cs2, newfile=True) | |
481 | #compare ! |
|
483 | # compare ! | |
482 | rev1 = 'default' |
|
484 | rev1 = 'default' | |
483 | rev2 = 'default' |
|
485 | rev2 = 'default' | |
484 |
|
486 | |||
@@ -497,7 +499,7 b' class TestCompareController(TestControll' | |||||
497 | content='line1-added-after-fork', message='commit2-parent', |
|
499 | content='line1-added-after-fork', message='commit2-parent', | |
498 | vcs_type='hg', parent=None, newfile=True) |
|
500 | vcs_type='hg', parent=None, newfile=True) | |
499 |
|
501 | |||
500 | #compare ! |
|
502 | # compare ! | |
501 | rev1 = 'default' |
|
503 | rev1 = 'default' | |
502 | rev2 = 'default' |
|
504 | rev2 = 'default' | |
503 | response = self.app.get(url('compare_url', |
|
505 | response = self.app.get(url('compare_url', | |
@@ -532,7 +534,7 b' class TestCompareController(TestControll' | |||||
532 | newfile=True) |
|
534 | newfile=True) | |
533 | Session().commit() |
|
535 | Session().commit() | |
534 | assert repo1.scm_instance.revisions == [cs0.raw_id] |
|
536 | assert repo1.scm_instance.revisions == [cs0.raw_id] | |
535 | #fork the repo1 |
|
537 | # fork the repo1 | |
536 | repo2 = fixture.create_repo(u'one-git-fork', repo_type='git', |
|
538 | repo2 = fixture.create_repo(u'one-git-fork', repo_type='git', | |
537 | repo_description='diff-test', |
|
539 | repo_description='diff-test', | |
538 | cur_user=TEST_USER_ADMIN_LOGIN, |
|
540 | cur_user=TEST_USER_ADMIN_LOGIN, | |
@@ -555,7 +557,7 b' class TestCompareController(TestControll' | |||||
555 | cs3 = fixture.commit_change(repo=r2_name, filename='file3-fork', |
|
557 | cs3 = fixture.commit_change(repo=r2_name, filename='file3-fork', | |
556 | content='file3-line1-from-fork', message='commit3-fork', |
|
558 | content='file3-line1-from-fork', message='commit3-fork', | |
557 | vcs_type='git', parent=cs2, newfile=True) |
|
559 | vcs_type='git', parent=cs2, newfile=True) | |
558 | #compare ! |
|
560 | # compare ! | |
559 | rev1 = 'master' |
|
561 | rev1 = 'master' | |
560 | rev2 = 'master' |
|
562 | rev2 = 'master' | |
561 |
|
563 | |||
@@ -574,7 +576,7 b' class TestCompareController(TestControll' | |||||
574 | content='line1-added-after-fork', message='commit2-parent', |
|
576 | content='line1-added-after-fork', message='commit2-parent', | |
575 | vcs_type='git', parent=None, newfile=True) |
|
577 | vcs_type='git', parent=None, newfile=True) | |
576 |
|
578 | |||
577 | #compare ! |
|
579 | # compare ! | |
578 | rev1 = 'master' |
|
580 | rev1 = 'master' | |
579 | rev2 = 'master' |
|
581 | rev2 = 'master' | |
580 | response = self.app.get(url('compare_url', |
|
582 | response = self.app.get(url('compare_url', |
@@ -100,7 +100,7 b' class TestCompareController(TestControll' | |||||
100 |
|
100 | |||
101 | response.mustcontain('11 files changed with 94 insertions and 64 deletions') |
|
101 | response.mustcontain('11 files changed with 94 insertions and 64 deletions') | |
102 |
|
102 | |||
103 | #files |
|
103 | # files | |
104 | response.mustcontain('''<a href="#C--1c5cf9e91c12">docs/api/utils/index.rst</a>''') |
|
104 | response.mustcontain('''<a href="#C--1c5cf9e91c12">docs/api/utils/index.rst</a>''') | |
105 | response.mustcontain('''<a href="#C--e3305437df55">test_and_report.sh</a>''') |
|
105 | response.mustcontain('''<a href="#C--e3305437df55">test_and_report.sh</a>''') | |
106 | response.mustcontain('''<a href="#C--c8e92ef85cd1">.hgignore</a>''') |
|
106 | response.mustcontain('''<a href="#C--c8e92ef85cd1">.hgignore</a>''') |
@@ -7,8 +7,6 b' class TestFeedController(TestController)' | |||||
7 | response = self.app.get(url(controller='feed', action='rss', |
|
7 | response = self.app.get(url(controller='feed', action='rss', | |
8 | repo_name=HG_REPO)) |
|
8 | repo_name=HG_REPO)) | |
9 |
|
9 | |||
10 |
|
||||
11 |
|
||||
12 | assert response.content_type == "application/rss+xml" |
|
10 | assert response.content_type == "application/rss+xml" | |
13 | assert """<rss version="2.0">""" in response |
|
11 | assert """<rss version="2.0">""" in response | |
14 |
|
12 |
@@ -58,7 +58,7 b' class TestFilesController(TestController' | |||||
58 | f_path='/') |
|
58 | f_path='/') | |
59 | ) |
|
59 | ) | |
60 |
|
60 | |||
61 | #Test response... |
|
61 | # Test response... | |
62 |
|
62 | |||
63 | response.mustcontain('<a class="browser-dir ypjax-link" href="/%s/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/docs"><i class="icon-folder-open"></i><span>docs</span></a>' % HG_REPO) |
|
63 | response.mustcontain('<a class="browser-dir ypjax-link" href="/%s/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/docs"><i class="icon-folder-open"></i><span>docs</span></a>' % HG_REPO) | |
64 | response.mustcontain('<a class="browser-dir ypjax-link" href="/%s/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/tests"><i class="icon-folder-open"></i><span>tests</span></a>' % HG_REPO) |
|
64 | response.mustcontain('<a class="browser-dir ypjax-link" href="/%s/files/7ba66bec8d6dbba14a2155be32408c435c5f4492/tests"><i class="icon-folder-open"></i><span>tests</span></a>' % HG_REPO) |
@@ -14,6 +14,7 b' from kallithea.model.meta import Session' | |||||
14 |
|
14 | |||
15 | fixture = Fixture() |
|
15 | fixture = Fixture() | |
16 |
|
16 | |||
|
17 | ||||
17 | class _BaseTestCase(TestController): |
|
18 | class _BaseTestCase(TestController): | |
18 | """ |
|
19 | """ | |
19 | Write all tests here |
|
20 | Write all tests here | |
@@ -34,7 +35,6 b' class _BaseTestCase(TestController):' | |||||
34 | Session().delete(self.u1) |
|
35 | Session().delete(self.u1) | |
35 | Session().commit() |
|
36 | Session().commit() | |
36 |
|
37 | |||
37 |
|
||||
38 | def test_index(self): |
|
38 | def test_index(self): | |
39 | self.log_user() |
|
39 | self.log_user() | |
40 | repo_name = self.REPO |
|
40 | repo_name = self.REPO | |
@@ -114,12 +114,12 b' class _BaseTestCase(TestController):' | |||||
114 |
|
114 | |||
115 | ## run the check page that triggers the flash message |
|
115 | ## run the check page that triggers the flash message | |
116 | response = self.app.get(url('repo_check_home', repo_name=fork_name_full)) |
|
116 | response = self.app.get(url('repo_check_home', repo_name=fork_name_full)) | |
117 | #test if we have a message that fork is ok |
|
117 | # test if we have a message that fork is ok | |
118 | self.checkSessionFlash(response, |
|
118 | self.checkSessionFlash(response, | |
119 | 'Forked repository %s as <a href="/%s">%s</a>' |
|
119 | 'Forked repository %s as <a href="/%s">%s</a>' | |
120 | % (repo_name, fork_name_full, fork_name_full)) |
|
120 | % (repo_name, fork_name_full, fork_name_full)) | |
121 |
|
121 | |||
122 | #test if the fork was created in the database |
|
122 | # test if the fork was created in the database | |
123 | fork_repo = Session().query(Repository) \ |
|
123 | fork_repo = Session().query(Repository) \ | |
124 | .filter(Repository.repo_name == fork_name_full).one() |
|
124 | .filter(Repository.repo_name == fork_name_full).one() | |
125 |
|
125 | |||
@@ -208,12 +208,12 b' class _BaseTestCase(TestController):' | |||||
208 |
|
208 | |||
209 | ## run the check page that triggers the flash message |
|
209 | ## run the check page that triggers the flash message | |
210 | response = self.app.get(url('repo_check_home', repo_name=fork_name)) |
|
210 | response = self.app.get(url('repo_check_home', repo_name=fork_name)) | |
211 | #test if we have a message that fork is ok |
|
211 | # test if we have a message that fork is ok | |
212 | self.checkSessionFlash(response, |
|
212 | self.checkSessionFlash(response, | |
213 | 'Forked repository %s as <a href="/%s">%s</a>' |
|
213 | 'Forked repository %s as <a href="/%s">%s</a>' | |
214 | % (repo_name, fork_name, fork_name)) |
|
214 | % (repo_name, fork_name, fork_name)) | |
215 |
|
215 | |||
216 | #test if the fork was created in the database |
|
216 | # test if the fork was created in the database | |
217 | fork_repo = Session().query(Repository) \ |
|
217 | fork_repo = Session().query(Repository) \ | |
218 | .filter(Repository.repo_name == fork_name).one() |
|
218 | .filter(Repository.repo_name == fork_name).one() | |
219 |
|
219 |
@@ -14,7 +14,7 b' class TestHomeController(TestController)' | |||||
14 | def test_index(self): |
|
14 | def test_index(self): | |
15 | self.log_user() |
|
15 | self.log_user() | |
16 | response = self.app.get(url(controller='home', action='index')) |
|
16 | response = self.app.get(url(controller='home', action='index')) | |
17 | #if global permission is set |
|
17 | # if global permission is set | |
18 | response.mustcontain('Add Repository') |
|
18 | response.mustcontain('Add Repository') | |
19 |
|
19 | |||
20 | response.mustcontain('<span class="repotag">git') |
|
20 | response.mustcontain('<span class="repotag">git') |
@@ -181,7 +181,7 b' class TestLoginController(TestController' | |||||
181 | ]) |
|
181 | ]) | |
182 | def test_redirection_after_successful_login_preserves_get_args(self, args, args_encoded): |
|
182 | def test_redirection_after_successful_login_preserves_get_args(self, args, args_encoded): | |
183 | response = self.app.post(url(controller='login', action='index', |
|
183 | response = self.app.post(url(controller='login', action='index', | |
184 |
came_from |
|
184 | came_from=url('/_admin/users', **args)), | |
185 | {'username': TEST_USER_ADMIN_LOGIN, |
|
185 | {'username': TEST_USER_ADMIN_LOGIN, | |
186 | 'password': TEST_USER_ADMIN_PASS}) |
|
186 | 'password': TEST_USER_ADMIN_PASS}) | |
187 | assert response.status == '302 Found' |
|
187 | assert response.status == '302 Found' | |
@@ -510,7 +510,7 b' class TestLoginController(TestController' | |||||
510 |
|
510 | |||
511 | new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, u'test') |
|
511 | new_api_key = ApiKeyModel().create(TEST_USER_ADMIN_LOGIN, u'test') | |
512 | Session().commit() |
|
512 | Session().commit() | |
513 | #patch the API key and make it expired |
|
513 | # patch the API key and make it expired | |
514 | new_api_key.expires = 0 |
|
514 | new_api_key.expires = 0 | |
515 | Session().commit() |
|
515 | Session().commit() | |
516 | self._api_key_test(new_api_key.api_key, status=403) |
|
516 | self._api_key_test(new_api_key.api_key, status=403) |
@@ -134,16 +134,16 b' class TestMyAccountController(TestContro' | |||||
134 | if name == 'email': |
|
134 | if name == 'email': | |
135 | params['emails'] = [attrs['email']] |
|
135 | params['emails'] = [attrs['email']] | |
136 | if name == 'extern_type': |
|
136 | if name == 'extern_type': | |
137 | #cannot update this via form, expected value is original one |
|
137 | # cannot update this via form, expected value is original one | |
138 | params['extern_type'] = "internal" |
|
138 | params['extern_type'] = "internal" | |
139 | if name == 'extern_name': |
|
139 | if name == 'extern_name': | |
140 | #cannot update this via form, expected value is original one |
|
140 | # cannot update this via form, expected value is original one | |
141 | params['extern_name'] = str(user_id) |
|
141 | params['extern_name'] = str(user_id) | |
142 | if name == 'active': |
|
142 | if name == 'active': | |
143 | #my account cannot deactivate account |
|
143 | # my account cannot deactivate account | |
144 | params['active'] = True |
|
144 | params['active'] = True | |
145 | if name == 'admin': |
|
145 | if name == 'admin': | |
146 | #my account cannot make you an admin ! |
|
146 | # my account cannot make you an admin ! | |
147 | params['admin'] = False |
|
147 | params['admin'] = False | |
148 |
|
148 | |||
149 | params.pop('_authentication_token') |
|
149 | params.pop('_authentication_token') | |
@@ -224,7 +224,7 b' class TestMyAccountController(TestContro' | |||||
224 | self.checkSessionFlash(response, 'API key successfully created') |
|
224 | self.checkSessionFlash(response, 'API key successfully created') | |
225 | response = response.follow() |
|
225 | response = response.follow() | |
226 |
|
226 | |||
227 | #now delete our key |
|
227 | # now delete our key | |
228 | keys = UserApiKeys.query().all() |
|
228 | keys = UserApiKeys.query().all() | |
229 | assert 1 == len(keys) |
|
229 | assert 1 == len(keys) | |
230 |
|
230 | |||
@@ -234,7 +234,6 b' class TestMyAccountController(TestContro' | |||||
234 | keys = UserApiKeys.query().all() |
|
234 | keys = UserApiKeys.query().all() | |
235 | assert 0 == len(keys) |
|
235 | assert 0 == len(keys) | |
236 |
|
236 | |||
237 |
|
||||
238 | def test_my_account_reset_main_api_key(self): |
|
237 | def test_my_account_reset_main_api_key(self): | |
239 | usr = self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) |
|
238 | usr = self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS) | |
240 | user = User.get(usr['user_id']) |
|
239 | user = User.get(usr['user_id']) |
@@ -12,6 +12,7 b' from kallithea.controllers.pullrequests ' | |||||
12 |
|
12 | |||
13 | fixture = Fixture() |
|
13 | fixture = Fixture() | |
14 |
|
14 | |||
|
15 | ||||
15 | class TestPullrequestsController(TestController): |
|
16 | class TestPullrequestsController(TestController): | |
16 |
|
17 | |||
17 | def test_index(self): |
|
18 | def test_index(self): | |
@@ -208,7 +209,6 b' class TestPullrequestsController(TestCon' | |||||
208 | status=400) |
|
209 | status=400) | |
209 | response.mustcontain('Invalid reviewer "%s" specified' % invalid_user_id) |
|
210 | response.mustcontain('Invalid reviewer "%s" specified' % invalid_user_id) | |
210 |
|
211 | |||
211 |
|
||||
212 | def test_iteration_refs(self): |
|
212 | def test_iteration_refs(self): | |
213 | # Repo graph excerpt: |
|
213 | # Repo graph excerpt: | |
214 | # o fb95b340e0d0 webvcs |
|
214 | # o fb95b340e0d0 webvcs |
@@ -10,6 +10,7 b' from kallithea.tests.fixture import crea' | |||||
10 |
|
10 | |||
11 | fixture = Fixture() |
|
11 | fixture = Fixture() | |
12 |
|
12 | |||
|
13 | ||||
13 | def init_indexing_test(repo): |
|
14 | def init_indexing_test(repo): | |
14 | prev = fixture.commit_change(repo.repo_name, |
|
15 | prev = fixture.commit_change(repo.repo_name, | |
15 | filename='this_should_be_unique_filename.txt', |
|
16 | filename='this_should_be_unique_filename.txt', | |
@@ -34,6 +35,7 b' def init_stopword_test(repo):' | |||||
34 | parent=prev, |
|
35 | parent=prev, | |
35 | newfile=True) |
|
36 | newfile=True) | |
36 |
|
37 | |||
|
38 | ||||
37 | repos = [ |
|
39 | repos = [ | |
38 | # reponame, init func or fork base, groupname |
|
40 | # reponame, init func or fork base, groupname | |
39 | (u'indexing_test', init_indexing_test, None), |
|
41 | (u'indexing_test', init_indexing_test, None), | |
@@ -44,10 +46,12 b' repos = [' | |||||
44 | (u'stopword_test', init_stopword_test, None), |
|
46 | (u'stopword_test', init_stopword_test, None), | |
45 | ] |
|
47 | ] | |
46 |
|
48 | |||
|
49 | ||||
47 | # map: name => id |
|
50 | # map: name => id | |
48 | repoids = {} |
|
51 | repoids = {} | |
49 | groupids = {} |
|
52 | groupids = {} | |
50 |
|
53 | |||
|
54 | ||||
51 | def rebuild_index(full_index): |
|
55 | def rebuild_index(full_index): | |
52 | with mock.patch('kallithea.lib.indexers.daemon.log.debug', |
|
56 | with mock.patch('kallithea.lib.indexers.daemon.log.debug', | |
53 | lambda *args, **kwargs: None): |
|
57 | lambda *args, **kwargs: None): |
@@ -31,11 +31,11 b' class TestSummaryController(TestControll' | |||||
31 | action='index', |
|
31 | action='index', | |
32 | repo_name=HG_REPO)) |
|
32 | repo_name=HG_REPO)) | |
33 |
|
33 | |||
34 | #repo type |
|
34 | # repo type | |
35 | response.mustcontain( |
|
35 | response.mustcontain( | |
36 | """<span class="repotag">hg""" |
|
36 | """<span class="repotag">hg""" | |
37 | ) |
|
37 | ) | |
38 | #public/private |
|
38 | # public/private | |
39 | response.mustcontain( |
|
39 | response.mustcontain( | |
40 | """<i class="icon-globe">""" |
|
40 | """<i class="icon-globe">""" | |
41 | ) |
|
41 | ) | |
@@ -57,11 +57,11 b' class TestSummaryController(TestControll' | |||||
57 | action='index', |
|
57 | action='index', | |
58 | repo_name=GIT_REPO)) |
|
58 | repo_name=GIT_REPO)) | |
59 |
|
59 | |||
60 | #repo type |
|
60 | # repo type | |
61 | response.mustcontain( |
|
61 | response.mustcontain( | |
62 | """<span class="repotag">git""" |
|
62 | """<span class="repotag">git""" | |
63 | ) |
|
63 | ) | |
64 | #public/private |
|
64 | # public/private | |
65 | response.mustcontain( |
|
65 | response.mustcontain( | |
66 | """<i class="icon-globe">""" |
|
66 | """<i class="icon-globe">""" | |
67 | ) |
|
67 | ) | |
@@ -82,11 +82,11 b' class TestSummaryController(TestControll' | |||||
82 | action='index', |
|
82 | action='index', | |
83 | repo_name='_%s' % ID)) |
|
83 | repo_name='_%s' % ID)) | |
84 |
|
84 | |||
85 | #repo type |
|
85 | # repo type | |
86 | response.mustcontain( |
|
86 | response.mustcontain( | |
87 | """<span class="repotag">hg""" |
|
87 | """<span class="repotag">hg""" | |
88 | ) |
|
88 | ) | |
89 | #public/private |
|
89 | # public/private | |
90 | response.mustcontain( |
|
90 | response.mustcontain( | |
91 | """<i class="icon-globe">""" |
|
91 | """<i class="icon-globe">""" | |
92 | ) |
|
92 | ) | |
@@ -111,11 +111,11 b' class TestSummaryController(TestControll' | |||||
111 | action='index', |
|
111 | action='index', | |
112 | repo_name='_%s' % ID)) |
|
112 | repo_name='_%s' % ID)) | |
113 |
|
113 | |||
114 | #repo type |
|
114 | # repo type | |
115 | response.mustcontain( |
|
115 | response.mustcontain( | |
116 | """<span class="repotag">git""" |
|
116 | """<span class="repotag">git""" | |
117 | ) |
|
117 | ) | |
118 | #public/private |
|
118 | # public/private | |
119 | response.mustcontain( |
|
119 | response.mustcontain( | |
120 | """<i class="icon-globe">""" |
|
120 | """<i class="icon-globe">""" | |
121 | ) |
|
121 | ) | |
@@ -127,7 +127,7 b' class TestSummaryController(TestControll' | |||||
127 |
|
127 | |||
128 | def test_index_trending(self): |
|
128 | def test_index_trending(self): | |
129 | self.log_user() |
|
129 | self.log_user() | |
130 | #codes stats |
|
130 | # codes stats | |
131 | self._enable_stats(HG_REPO) |
|
131 | self._enable_stats(HG_REPO) | |
132 |
|
132 | |||
133 | ScmModel().mark_for_invalidation(HG_REPO) |
|
133 | ScmModel().mark_for_invalidation(HG_REPO) | |
@@ -151,7 +151,7 b' class TestSummaryController(TestControll' | |||||
151 |
|
151 | |||
152 | def test_index_statistics(self): |
|
152 | def test_index_statistics(self): | |
153 | self.log_user() |
|
153 | self.log_user() | |
154 | #codes stats |
|
154 | # codes stats | |
155 | self._enable_stats(HG_REPO) |
|
155 | self._enable_stats(HG_REPO) | |
156 |
|
156 | |||
157 | ScmModel().mark_for_invalidation(HG_REPO) |
|
157 | ScmModel().mark_for_invalidation(HG_REPO) | |
@@ -160,7 +160,7 b' class TestSummaryController(TestControll' | |||||
160 |
|
160 | |||
161 | def test_index_trending_git(self): |
|
161 | def test_index_trending_git(self): | |
162 | self.log_user() |
|
162 | self.log_user() | |
163 | #codes stats |
|
163 | # codes stats | |
164 | self._enable_stats(GIT_REPO) |
|
164 | self._enable_stats(GIT_REPO) | |
165 |
|
165 | |||
166 | ScmModel().mark_for_invalidation(GIT_REPO) |
|
166 | ScmModel().mark_for_invalidation(GIT_REPO) | |
@@ -184,7 +184,7 b' class TestSummaryController(TestControll' | |||||
184 |
|
184 | |||
185 | def test_index_statistics_git(self): |
|
185 | def test_index_statistics_git(self): | |
186 | self.log_user() |
|
186 | self.log_user() | |
187 | #codes stats |
|
187 | # codes stats | |
188 | self._enable_stats(GIT_REPO) |
|
188 | self._enable_stats(GIT_REPO) | |
189 |
|
189 | |||
190 | ScmModel().mark_for_invalidation(GIT_REPO) |
|
190 | ScmModel().mark_for_invalidation(GIT_REPO) |
@@ -2,11 +2,13 b' from kallithea.tests.base import *' | |||||
2 | from kallithea.model.changeset_status import ChangesetStatusModel |
|
2 | from kallithea.model.changeset_status import ChangesetStatusModel | |
3 | from kallithea.model.db import ChangesetStatus as CS |
|
3 | from kallithea.model.db import ChangesetStatus as CS | |
4 |
|
4 | |||
|
5 | ||||
5 | class CSM(object): # ChangesetStatusMock |
|
6 | class CSM(object): # ChangesetStatusMock | |
6 |
|
7 | |||
7 | def __init__(self, status): |
|
8 | def __init__(self, status): | |
8 | self.status = status |
|
9 | self.status = status | |
9 |
|
10 | |||
|
11 | ||||
10 | class TestChangesetStatusCalculation(TestController): |
|
12 | class TestChangesetStatusCalculation(TestController): | |
11 |
|
13 | |||
12 | def setup_method(self, method): |
|
14 | def setup_method(self, method): |
@@ -16,6 +16,7 b' import kallithea.lib.celerylib.tasks' | |||||
16 |
|
16 | |||
17 | from tg.util.webtest import test_context |
|
17 | from tg.util.webtest import test_context | |
18 |
|
18 | |||
|
19 | ||||
19 | class TestNotifications(TestController): |
|
20 | class TestNotifications(TestController): | |
20 |
|
21 | |||
21 | def setup_method(self, method): |
|
22 | def setup_method(self, method): | |
@@ -48,6 +49,7 b' class TestNotifications(TestController):' | |||||
48 | def test_create_notification(self): |
|
49 | def test_create_notification(self): | |
49 | with test_context(self.app): |
|
50 | with test_context(self.app): | |
50 | usrs = [self.u1, self.u2] |
|
51 | usrs = [self.u1, self.u2] | |
|
52 | ||||
51 | def send_email(recipients, subject, body='', html_body='', headers=None, author=None): |
|
53 | def send_email(recipients, subject, body='', html_body='', headers=None, author=None): | |
52 | assert recipients == ['u2@example.com'] |
|
54 | assert recipients == ['u2@example.com'] | |
53 | assert subject == 'Test Message' |
|
55 | assert subject == 'Test Message' | |
@@ -137,7 +139,7 b' class TestNotifications(TestController):' | |||||
137 | # notification object is still there |
|
139 | # notification object is still there | |
138 | assert Notification.query().all() == [notification] |
|
140 | assert Notification.query().all() == [notification] | |
139 |
|
141 | |||
140 | #u1 and u2 still have assignments |
|
142 | # u1 and u2 still have assignments | |
141 | u1notification = UserNotification.query() \ |
|
143 | u1notification = UserNotification.query() \ | |
142 | .filter(UserNotification.notification == |
|
144 | .filter(UserNotification.notification == | |
143 | notification) \ |
|
145 | notification) \ |
@@ -19,7 +19,7 b' class TestPermissions(TestController):' | |||||
19 |
|
19 | |||
20 | @classmethod |
|
20 | @classmethod | |
21 | def setup_class(cls): |
|
21 | def setup_class(cls): | |
22 | #recreate default user to get a clean start |
|
22 | # recreate default user to get a clean start | |
23 | PermissionModel().create_default_permissions(user=User.DEFAULT_USER, |
|
23 | PermissionModel().create_default_permissions(user=User.DEFAULT_USER, | |
24 | force=True) |
|
24 | force=True) | |
25 | Session().commit() |
|
25 | Session().commit() | |
@@ -218,7 +218,7 b' class TestPermissions(TestController):' | |||||
218 | a1_auth = AuthUser(user_id=self.anon.user_id) |
|
218 | a1_auth = AuthUser(user_id=self.anon.user_id) | |
219 | assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.read', u'group2': u'group.read'} |
|
219 | assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.read', u'group2': u'group.read'} | |
220 |
|
220 | |||
221 | #Change perms to none for both groups |
|
221 | # Change perms to none for both groups | |
222 | RepoGroupModel().grant_user_permission(repo_group=self.g1, |
|
222 | RepoGroupModel().grant_user_permission(repo_group=self.g1, | |
223 | user=self.anon, |
|
223 | user=self.anon, | |
224 | perm='group.none') |
|
224 | perm='group.none') | |
@@ -245,14 +245,14 b' class TestPermissions(TestController):' | |||||
245 | a1_auth = AuthUser(user_id=self.anon.user_id) |
|
245 | a1_auth = AuthUser(user_id=self.anon.user_id) | |
246 | assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'} |
|
246 | assert a1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'} | |
247 |
|
247 | |||
248 | #grant permission for u2 ! |
|
248 | # grant permission for u2 ! | |
249 | RepoGroupModel().grant_user_permission(repo_group=self.g1, user=self.u2, |
|
249 | RepoGroupModel().grant_user_permission(repo_group=self.g1, user=self.u2, | |
250 | perm='group.read') |
|
250 | perm='group.read') | |
251 | RepoGroupModel().grant_user_permission(repo_group=self.g2, user=self.u2, |
|
251 | RepoGroupModel().grant_user_permission(repo_group=self.g2, user=self.u2, | |
252 | perm='group.read') |
|
252 | perm='group.read') | |
253 | Session().commit() |
|
253 | Session().commit() | |
254 | assert self.u1 != self.u2 |
|
254 | assert self.u1 != self.u2 | |
255 | #u1 and anon should have not change perms while u2 should ! |
|
255 | # u1 and anon should have not change perms while u2 should ! | |
256 | u1_auth = AuthUser(user_id=self.u1.user_id) |
|
256 | u1_auth = AuthUser(user_id=self.u1.user_id) | |
257 | assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'} |
|
257 | assert u1_auth.permissions['repositories_groups'] == {u'group1': u'group.none', u'group2': u'group.none'} | |
258 |
|
258 | |||
@@ -357,7 +357,7 b' class TestPermissions(TestController):' | |||||
357 | user_model.revoke_perm(usr, 'hg.fork.none') |
|
357 | user_model.revoke_perm(usr, 'hg.fork.none') | |
358 | user_model.grant_perm(usr, 'hg.fork.repository') |
|
358 | user_model.grant_perm(usr, 'hg.fork.repository') | |
359 |
|
359 | |||
360 | #disable global perms on specific user |
|
360 | # disable global perms on specific user | |
361 | user_model.revoke_perm(self.u1, 'hg.create.repository') |
|
361 | user_model.revoke_perm(self.u1, 'hg.create.repository') | |
362 | user_model.grant_perm(self.u1, 'hg.create.none') |
|
362 | user_model.grant_perm(self.u1, 'hg.create.none') | |
363 | user_model.revoke_perm(self.u1, 'hg.fork.repository') |
|
363 | user_model.revoke_perm(self.u1, 'hg.fork.repository') | |
@@ -384,7 +384,7 b' class TestPermissions(TestController):' | |||||
384 | user_model.revoke_perm(usr, 'hg.fork.repository') |
|
384 | user_model.revoke_perm(usr, 'hg.fork.repository') | |
385 | user_model.grant_perm(usr, 'hg.fork.none') |
|
385 | user_model.grant_perm(usr, 'hg.fork.none') | |
386 |
|
386 | |||
387 | #enable global perms on specific user |
|
387 | # enable global perms on specific user | |
388 | user_model.revoke_perm(self.u1, 'hg.create.none') |
|
388 | user_model.revoke_perm(self.u1, 'hg.create.none') | |
389 | user_model.grant_perm(self.u1, 'hg.create.repository') |
|
389 | user_model.grant_perm(self.u1, 'hg.create.repository') | |
390 | user_model.revoke_perm(self.u1, 'hg.fork.none') |
|
390 | user_model.revoke_perm(self.u1, 'hg.fork.none') | |
@@ -609,15 +609,15 b' class TestPermissions(TestController):' | |||||
609 | assert u1_auth.permissions['user_groups'][u'G2'] == u'usergroup.admin' |
|
609 | assert u1_auth.permissions['user_groups'][u'G2'] == u'usergroup.admin' | |
610 |
|
610 | |||
611 | def test_owner_permissions_doesnot_get_overwritten_by_group(self): |
|
611 | def test_owner_permissions_doesnot_get_overwritten_by_group(self): | |
612 | #create repo as USER, |
|
612 | # create repo as USER, | |
613 | self.test_repo = fixture.create_repo(name=u'myownrepo', |
|
613 | self.test_repo = fixture.create_repo(name=u'myownrepo', | |
614 | repo_type='hg', |
|
614 | repo_type='hg', | |
615 | cur_user=self.u1) |
|
615 | cur_user=self.u1) | |
616 |
|
616 | |||
617 | #he has permissions of admin as owner |
|
617 | # he has permissions of admin as owner | |
618 | u1_auth = AuthUser(user_id=self.u1.user_id) |
|
618 | u1_auth = AuthUser(user_id=self.u1.user_id) | |
619 | assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.admin' |
|
619 | assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.admin' | |
620 | #set his permission as user group, he should still be admin |
|
620 | # set his permission as user group, he should still be admin | |
621 | self.ug1 = fixture.create_user_group(u'G1') |
|
621 | self.ug1 = fixture.create_user_group(u'G1') | |
622 | UserGroupModel().add_user_to_group(self.ug1, self.u1) |
|
622 | UserGroupModel().add_user_to_group(self.ug1, self.u1) | |
623 | RepoModel().grant_user_group_permission(self.test_repo, |
|
623 | RepoModel().grant_user_group_permission(self.test_repo, | |
@@ -629,15 +629,15 b' class TestPermissions(TestController):' | |||||
629 | assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.admin' |
|
629 | assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.admin' | |
630 |
|
630 | |||
631 | def test_owner_permissions_doesnot_get_overwritten_by_others(self): |
|
631 | def test_owner_permissions_doesnot_get_overwritten_by_others(self): | |
632 | #create repo as USER, |
|
632 | # create repo as USER, | |
633 | self.test_repo = fixture.create_repo(name=u'myownrepo', |
|
633 | self.test_repo = fixture.create_repo(name=u'myownrepo', | |
634 | repo_type='hg', |
|
634 | repo_type='hg', | |
635 | cur_user=self.u1) |
|
635 | cur_user=self.u1) | |
636 |
|
636 | |||
637 | #he has permissions of admin as owner |
|
637 | # he has permissions of admin as owner | |
638 | u1_auth = AuthUser(user_id=self.u1.user_id) |
|
638 | u1_auth = AuthUser(user_id=self.u1.user_id) | |
639 | assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.admin' |
|
639 | assert u1_auth.permissions['repositories']['myownrepo'] == 'repository.admin' | |
640 | #set his permission as user, he should still be admin |
|
640 | # set his permission as user, he should still be admin | |
641 | RepoModel().grant_user_permission(self.test_repo, user=self.u1, |
|
641 | RepoModel().grant_user_permission(self.test_repo, user=self.u1, | |
642 | perm='repository.none') |
|
642 | perm='repository.none') | |
643 | Session().commit() |
|
643 | Session().commit() | |
@@ -657,7 +657,7 b' class TestPermissions(TestController):' | |||||
657 | def test_set_default_permissions_after_one_is_missing(self): |
|
657 | def test_set_default_permissions_after_one_is_missing(self): | |
658 | PermissionModel().create_default_permissions(user=self.u1) |
|
658 | PermissionModel().create_default_permissions(user=self.u1) | |
659 | self._test_def_perm_equal(user=self.u1) |
|
659 | self._test_def_perm_equal(user=self.u1) | |
660 | #now we delete one, it should be re-created after another call |
|
660 | # now we delete one, it should be re-created after another call | |
661 | perms = UserToPerm.query() \ |
|
661 | perms = UserToPerm.query() \ | |
662 | .filter(UserToPerm.user == self.u1) \ |
|
662 | .filter(UserToPerm.user == self.u1) \ | |
663 | .all() |
|
663 | .all() | |
@@ -666,7 +666,7 b' class TestPermissions(TestController):' | |||||
666 |
|
666 | |||
667 | self._test_def_perm_equal(user=self.u1, change_factor=-1) |
|
667 | self._test_def_perm_equal(user=self.u1, change_factor=-1) | |
668 |
|
668 | |||
669 | #create missing one ! |
|
669 | # create missing one ! | |
670 | PermissionModel().create_default_permissions(user=self.u1) |
|
670 | PermissionModel().create_default_permissions(user=self.u1) | |
671 | self._test_def_perm_equal(user=self.u1) |
|
671 | self._test_def_perm_equal(user=self.u1) | |
672 |
|
672 | |||
@@ -687,7 +687,7 b' class TestPermissions(TestController):' | |||||
687 | assert old != None |
|
687 | assert old != None | |
688 | assert new != None |
|
688 | assert new != None | |
689 |
|
689 | |||
690 | #now modify permissions |
|
690 | # now modify permissions | |
691 | p = UserToPerm.query() \ |
|
691 | p = UserToPerm.query() \ | |
692 | .filter(UserToPerm.user == self.u1) \ |
|
692 | .filter(UserToPerm.user == self.u1) \ | |
693 | .filter(UserToPerm.permission == old) \ |
|
693 | .filter(UserToPerm.permission == old) \ |
@@ -161,7 +161,7 b' class TestRepoGroups(TestController):' | |||||
161 |
|
161 | |||
162 | r = fixture.create_repo(u'L1/L2/L3/L3_REPO', repo_group=g3.group_id) |
|
162 | r = fixture.create_repo(u'L1/L2/L3/L3_REPO', repo_group=g3.group_id) | |
163 |
|
163 | |||
164 | ##rename L1 all groups should be now changed |
|
164 | ## rename L1 all groups should be now changed | |
165 | _update_repo_group(g1.group_id, u'L1_NEW') |
|
165 | _update_repo_group(g1.group_id, u'L1_NEW') | |
166 | Session().commit() |
|
166 | Session().commit() | |
167 | assert g1.full_path == 'L1_NEW' |
|
167 | assert g1.full_path == 'L1_NEW' | |
@@ -176,7 +176,7 b' class TestRepoGroups(TestController):' | |||||
176 | g4 = fixture.create_repo_group(u'R1_NEW') |
|
176 | g4 = fixture.create_repo_group(u'R1_NEW') | |
177 |
|
177 | |||
178 | r = fixture.create_repo(u'R1/R2/R3/R3_REPO', repo_group=g3.group_id) |
|
178 | r = fixture.create_repo(u'R1/R2/R3/R3_REPO', repo_group=g3.group_id) | |
179 | ##rename L1 all groups should be now changed |
|
179 | ## rename L1 all groups should be now changed | |
180 | _update_repo_group(g1.group_id, u'R1', parent_id=g4.group_id) |
|
180 | _update_repo_group(g1.group_id, u'R1', parent_id=g4.group_id) | |
181 | Session().commit() |
|
181 | Session().commit() | |
182 | assert g1.full_path == 'R1_NEW/R1' |
|
182 | assert g1.full_path == 'R1_NEW/R1' | |
@@ -192,7 +192,7 b' class TestRepoGroups(TestController):' | |||||
192 |
|
192 | |||
193 | r = fixture.create_repo(u'X1/X2/X3/X3_REPO', repo_group=g3.group_id) |
|
193 | r = fixture.create_repo(u'X1/X2/X3/X3_REPO', repo_group=g3.group_id) | |
194 |
|
194 | |||
195 | ##rename L1 all groups should be now changed |
|
195 | ## rename L1 all groups should be now changed | |
196 | _update_repo_group(g1.group_id, u'X1_PRIM', parent_id=g4.group_id) |
|
196 | _update_repo_group(g1.group_id, u'X1_PRIM', parent_id=g4.group_id) | |
197 | Session().commit() |
|
197 | Session().commit() | |
198 | assert g1.full_path == 'X1_NEW/X1_PRIM' |
|
198 | assert g1.full_path == 'X1_NEW/X1_PRIM' |
@@ -45,7 +45,7 b' class TestRepos(TestController):' | |||||
45 | fork = fixture.create_fork(repo.repo_name, u'test-repo-fork-1') |
|
45 | fork = fixture.create_fork(repo.repo_name, u'test-repo-fork-1') | |
46 | Session().commit() |
|
46 | Session().commit() | |
47 |
|
47 | |||
48 | #fork of fork |
|
48 | # fork of fork | |
49 | fixture.create_fork(fork.repo_name, u'test-repo-fork-fork-1') |
|
49 | fixture.create_fork(fork.repo_name, u'test-repo-fork-fork-1') | |
50 | Session().commit() |
|
50 | Session().commit() | |
51 |
|
51 | |||
@@ -63,7 +63,7 b' class TestRepos(TestController):' | |||||
63 | fork = fixture.create_fork(repo.repo_name, u'test-repo-fork-1') |
|
63 | fork = fixture.create_fork(repo.repo_name, u'test-repo-fork-1') | |
64 | Session().commit() |
|
64 | Session().commit() | |
65 |
|
65 | |||
66 | #fork of fork |
|
66 | # fork of fork | |
67 | fixture.create_fork(fork.repo_name, u'test-repo-fork-fork-1') |
|
67 | fixture.create_fork(fork.repo_name, u'test-repo-fork-fork-1') | |
68 | Session().commit() |
|
68 | Session().commit() | |
69 |
|
69 |
@@ -4,6 +4,7 b' from kallithea.model.db import Setting' | |||||
4 |
|
4 | |||
5 | name = 'spam-setting-name' |
|
5 | name = 'spam-setting-name' | |
6 |
|
6 | |||
|
7 | ||||
7 | def test_passing_list_setting_value_results_in_string_valued_setting(): |
|
8 | def test_passing_list_setting_value_results_in_string_valued_setting(): | |
8 | assert Setting.get_by_name(name) is None |
|
9 | assert Setting.get_by_name(name) is None | |
9 | setting = Setting.create_or_update(name, ['spam', 'eggs']) |
|
10 | setting = Setting.create_or_update(name, ['spam', 'eggs']) | |
@@ -17,6 +18,7 b' def test_passing_list_setting_value_resu' | |||||
17 | finally: |
|
18 | finally: | |
18 | Session().delete(setting) |
|
19 | Session().delete(setting) | |
19 |
|
20 | |||
|
21 | ||||
20 | def test_list_valued_setting_creation_requires_manual_value_formatting(): |
|
22 | def test_list_valued_setting_creation_requires_manual_value_formatting(): | |
21 | assert Setting.get_by_name(name) is None |
|
23 | assert Setting.get_by_name(name) is None | |
22 | # Quirk: need manual formatting of list setting value. |
|
24 | # Quirk: need manual formatting of list setting value. | |
@@ -27,6 +29,7 b' def test_list_valued_setting_creation_re' | |||||
27 | finally: |
|
29 | finally: | |
28 | Session().delete(setting) |
|
30 | Session().delete(setting) | |
29 |
|
31 | |||
|
32 | ||||
30 | def test_list_valued_setting_update(): |
|
33 | def test_list_valued_setting_update(): | |
31 | assert Setting.get_by_name(name) is None |
|
34 | assert Setting.get_by_name(name) is None | |
32 | setting = Setting.create_or_update(name, 'spam', type='list') |
|
35 | setting = Setting.create_or_update(name, 'spam', type='list') |
@@ -1,1 +1,1 b'' | |||||
1 | #TODO; write tests when we activate algo for permissions. |
|
1 | # TODO; write tests when we activate algo for permissions. |
@@ -4,7 +4,6 b' from kallithea.tests.base import *' | |||||
4 | from kallithea.model.db import User, UserGroup, UserGroupMember, UserEmailMap, \ |
|
4 | from kallithea.model.db import User, UserGroup, UserGroupMember, UserEmailMap, \ | |
5 | Permission |
|
5 | Permission | |
6 | from kallithea.model.user import UserModel |
|
6 | from kallithea.model.user import UserModel | |
7 |
|
||||
8 | from kallithea.model.meta import Session |
|
7 | from kallithea.model.meta import Session | |
9 | from kallithea.model.user_group import UserGroupModel |
|
8 | from kallithea.model.user_group import UserGroupModel | |
10 | from kallithea.tests.fixture import Fixture |
|
9 | from kallithea.tests.fixture import Fixture | |
@@ -138,7 +137,7 b' class TestUsers(TestController):' | |||||
138 | Session().commit() |
|
137 | Session().commit() | |
139 | assert UserModel().has_perm(self.u1, perm) == True |
|
138 | assert UserModel().has_perm(self.u1, perm) == True | |
140 |
|
139 | |||
141 | #revoke |
|
140 | # revoke | |
142 | UserModel().revoke_perm(self.u1, perm) |
|
141 | UserModel().revoke_perm(self.u1, perm) | |
143 | Session().commit() |
|
142 | Session().commit() | |
144 | assert UserModel().has_perm(self.u1, perm) == False |
|
143 | assert UserModel().has_perm(self.u1, perm) == False |
@@ -67,6 +67,7 b' TEST_URLS += [' | |||||
67 | '%s://example.com:8080' % proto), |
|
67 | '%s://example.com:8080' % proto), | |
68 | ] |
|
68 | ] | |
69 |
|
69 | |||
|
70 | ||||
70 | class FakeUrlGenerator(object): |
|
71 | class FakeUrlGenerator(object): | |
71 |
|
72 | |||
72 | def __init__(self, current_url=None, default_route=None, **routes): |
|
73 | def __init__(self, current_url=None, default_route=None, **routes): | |
@@ -86,6 +87,7 b' class FakeUrlGenerator(object):' | |||||
86 | def current(self, *args, **kwargs): |
|
87 | def current(self, *args, **kwargs): | |
87 | return self.current_url % kwargs |
|
88 | return self.current_url % kwargs | |
88 |
|
89 | |||
|
90 | ||||
89 | class TestLibs(TestController): |
|
91 | class TestLibs(TestController): | |
90 |
|
92 | |||
91 | @parametrize('test_url,expected,expected_creds', TEST_URLS) |
|
93 | @parametrize('test_url,expected,expected_creds', TEST_URLS) |
@@ -4,6 +4,7 b' import kallithea' | |||||
4 | from kallithea.tests.base import * |
|
4 | from kallithea.tests.base import * | |
5 | from kallithea.model.db import User |
|
5 | from kallithea.model.db import User | |
6 |
|
6 | |||
|
7 | ||||
7 | class smtplib_mock(object): |
|
8 | class smtplib_mock(object): | |
8 |
|
9 | |||
9 | @classmethod |
|
10 | @classmethod | |
@@ -12,14 +13,17 b' class smtplib_mock(object):' | |||||
12 |
|
13 | |||
13 | def ehlo(self): |
|
14 | def ehlo(self): | |
14 | pass |
|
15 | pass | |
|
16 | ||||
15 | def quit(self): |
|
17 | def quit(self): | |
16 | pass |
|
18 | pass | |
|
19 | ||||
17 | def sendmail(self, sender, dest, msg): |
|
20 | def sendmail(self, sender, dest, msg): | |
18 | smtplib_mock.lastsender = sender |
|
21 | smtplib_mock.lastsender = sender | |
19 | smtplib_mock.lastdest = dest |
|
22 | smtplib_mock.lastdest = dest | |
20 | smtplib_mock.lastmsg = msg |
|
23 | smtplib_mock.lastmsg = msg | |
21 | pass |
|
24 | pass | |
22 |
|
25 | |||
|
26 | ||||
23 | @mock.patch('kallithea.lib.rcmail.smtp_mailer.smtplib', smtplib_mock) |
|
27 | @mock.patch('kallithea.lib.rcmail.smtp_mailer.smtplib', smtplib_mock) | |
24 | class TestMail(TestController): |
|
28 | class TestMail(TestController): | |
25 |
|
29 |
@@ -162,7 +162,7 b' class TestRepoGroups(TestController):' | |||||
162 | with pytest.raises(formencode.Invalid): |
|
162 | with pytest.raises(formencode.Invalid): | |
163 | validator.to_python({'repo_name': gr.group_name}) |
|
163 | validator.to_python({'repo_name': gr.group_name}) | |
164 |
|
164 | |||
165 | #TODO: write an error case for that ie. create a repo withinh a group |
|
165 | # TODO: write an error case for that ie. create a repo withinh a group | |
166 | # self.assertRaises(formencode.Invalid, |
|
166 | # self.assertRaises(formencode.Invalid, | |
167 | # validator.to_python, {'repo_name': 'some', |
|
167 | # validator.to_python, {'repo_name': 'some', | |
168 | # 'repo_group': gr.group_id}) |
|
168 | # 'repo_group': gr.group_id}) | |
@@ -181,7 +181,7 b' class TestRepoGroups(TestController):' | |||||
181 | assert expected == validator.to_python(name) |
|
181 | assert expected == validator.to_python(name) | |
182 |
|
182 | |||
183 | def test_ValidCloneUri(self): |
|
183 | def test_ValidCloneUri(self): | |
184 | #TODO: write this one |
|
184 | # TODO: write this one | |
185 | pass |
|
185 | pass | |
186 |
|
186 | |||
187 | def test_ValidForkType(self): |
|
187 | def test_ValidForkType(self): | |
@@ -191,7 +191,7 b' class TestRepoGroups(TestController):' | |||||
191 | validator.to_python('git') |
|
191 | validator.to_python('git') | |
192 |
|
192 | |||
193 | def test_ValidPerms(self): |
|
193 | def test_ValidPerms(self): | |
194 | #TODO: write this one |
|
194 | # TODO: write this one | |
195 | pass |
|
195 | pass | |
196 |
|
196 | |||
197 | def test_ValidSettings(self): |
|
197 | def test_ValidSettings(self): |
@@ -152,7 +152,7 b' def set_anonymous_access(enable=True):' | |||||
152 |
|
152 | |||
153 |
|
153 | |||
154 | def _check_proper_git_push(stdout, stderr): |
|
154 | def _check_proper_git_push(stdout, stderr): | |
155 | #WTF Git stderr is output ?! |
|
155 | # WTF Git stderr is output ?! | |
156 | assert 'fatal' not in stderr |
|
156 | assert 'fatal' not in stderr | |
157 | assert 'rejected' not in stderr |
|
157 | assert 'rejected' not in stderr | |
158 | assert 'Pushing to' in stderr |
|
158 | assert 'Pushing to' in stderr | |
@@ -164,7 +164,7 b' class TestVCSOperations(TestController):' | |||||
164 |
|
164 | |||
165 | @classmethod |
|
165 | @classmethod | |
166 | def setup_class(cls): |
|
166 | def setup_class(cls): | |
167 | #DISABLE ANONYMOUS ACCESS |
|
167 | # DISABLE ANONYMOUS ACCESS | |
168 | set_anonymous_access(False) |
|
168 | set_anonymous_access(False) | |
169 |
|
169 | |||
170 | def setup_method(self, method): |
|
170 | def setup_method(self, method): | |
@@ -255,7 +255,7 b' class TestVCSOperations(TestController):' | |||||
255 |
|
255 | |||
256 | def test_push_invalidates_cache_hg(self, webserver): |
|
256 | def test_push_invalidates_cache_hg(self, webserver): | |
257 | key = CacheInvalidation.query().filter(CacheInvalidation.cache_key |
|
257 | key = CacheInvalidation.query().filter(CacheInvalidation.cache_key | |
258 | ==HG_REPO).scalar() |
|
258 | == HG_REPO).scalar() | |
259 | if not key: |
|
259 | if not key: | |
260 | key = CacheInvalidation(HG_REPO, HG_REPO) |
|
260 | key = CacheInvalidation(HG_REPO, HG_REPO) | |
261 | Session().add(key) |
|
261 | Session().add(key) | |
@@ -273,12 +273,12 b' class TestVCSOperations(TestController):' | |||||
273 | stdout, stderr = _add_files_and_push(webserver, 'hg', DEST, files_no=1, clone_url=clone_url) |
|
273 | stdout, stderr = _add_files_and_push(webserver, 'hg', DEST, files_no=1, clone_url=clone_url) | |
274 |
|
274 | |||
275 | key = CacheInvalidation.query().filter(CacheInvalidation.cache_key |
|
275 | key = CacheInvalidation.query().filter(CacheInvalidation.cache_key | |
276 | ==fork_name).all() |
|
276 | == fork_name).all() | |
277 | assert key == [] |
|
277 | assert key == [] | |
278 |
|
278 | |||
279 | def test_push_invalidates_cache_git(self, webserver): |
|
279 | def test_push_invalidates_cache_git(self, webserver): | |
280 | key = CacheInvalidation.query().filter(CacheInvalidation.cache_key |
|
280 | key = CacheInvalidation.query().filter(CacheInvalidation.cache_key | |
281 | ==GIT_REPO).scalar() |
|
281 | == GIT_REPO).scalar() | |
282 | if not key: |
|
282 | if not key: | |
283 | key = CacheInvalidation(GIT_REPO, GIT_REPO) |
|
283 | key = CacheInvalidation(GIT_REPO, GIT_REPO) | |
284 | Session().add(key) |
|
284 | Session().add(key) | |
@@ -298,7 +298,7 b' class TestVCSOperations(TestController):' | |||||
298 | _check_proper_git_push(stdout, stderr) |
|
298 | _check_proper_git_push(stdout, stderr) | |
299 |
|
299 | |||
300 | key = CacheInvalidation.query().filter(CacheInvalidation.cache_key |
|
300 | key = CacheInvalidation.query().filter(CacheInvalidation.cache_key | |
301 | ==fork_name).all() |
|
301 | == fork_name).all() | |
302 | assert key == [] |
|
302 | assert key == [] | |
303 |
|
303 | |||
304 | def test_push_wrong_credentials_hg(self, webserver): |
|
304 | def test_push_wrong_credentials_hg(self, webserver): | |
@@ -352,7 +352,7 b' class TestVCSOperations(TestController):' | |||||
352 | clone_url = webserver.repo_url(HG_REPO) |
|
352 | clone_url = webserver.repo_url(HG_REPO) | |
353 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir()) |
|
353 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir()) | |
354 |
|
354 | |||
355 | #check if lock was made |
|
355 | # check if lock was made | |
356 | r = Repository.get_by_repo_name(HG_REPO) |
|
356 | r = Repository.get_by_repo_name(HG_REPO) | |
357 | assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id |
|
357 | assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id | |
358 |
|
358 | |||
@@ -365,15 +365,15 b' class TestVCSOperations(TestController):' | |||||
365 | clone_url = webserver.repo_url(GIT_REPO) |
|
365 | clone_url = webserver.repo_url(GIT_REPO) | |
366 | stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir()) |
|
366 | stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir()) | |
367 |
|
367 | |||
368 | #check if lock was made |
|
368 | # check if lock was made | |
369 | r = Repository.get_by_repo_name(GIT_REPO) |
|
369 | r = Repository.get_by_repo_name(GIT_REPO) | |
370 | assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id |
|
370 | assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id | |
371 |
|
371 | |||
372 | def test_clone_after_repo_was_locked_hg(self, webserver): |
|
372 | def test_clone_after_repo_was_locked_hg(self, webserver): | |
373 | #lock repo |
|
373 | # lock repo | |
374 | r = Repository.get_by_repo_name(HG_REPO) |
|
374 | r = Repository.get_by_repo_name(HG_REPO) | |
375 | Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) |
|
375 | Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) | |
376 | #pull fails since repo is locked |
|
376 | # pull fails since repo is locked | |
377 | clone_url = webserver.repo_url(HG_REPO) |
|
377 | clone_url = webserver.repo_url(HG_REPO) | |
378 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) |
|
378 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) | |
379 | msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" |
|
379 | msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" | |
@@ -381,22 +381,22 b' class TestVCSOperations(TestController):' | |||||
381 | assert msg in stderr |
|
381 | assert msg in stderr | |
382 |
|
382 | |||
383 | def test_clone_after_repo_was_locked_git(self, webserver): |
|
383 | def test_clone_after_repo_was_locked_git(self, webserver): | |
384 | #lock repo |
|
384 | # lock repo | |
385 | r = Repository.get_by_repo_name(GIT_REPO) |
|
385 | r = Repository.get_by_repo_name(GIT_REPO) | |
386 | Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) |
|
386 | Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) | |
387 | #pull fails since repo is locked |
|
387 | # pull fails since repo is locked | |
388 | clone_url = webserver.repo_url(GIT_REPO) |
|
388 | clone_url = webserver.repo_url(GIT_REPO) | |
389 | stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) |
|
389 | stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) | |
390 | msg = ("""The requested URL returned error: 423""") |
|
390 | msg = ("""The requested URL returned error: 423""") | |
391 | assert msg in stderr |
|
391 | assert msg in stderr | |
392 |
|
392 | |||
393 | def test_push_on_locked_repo_by_other_user_hg(self, webserver): |
|
393 | def test_push_on_locked_repo_by_other_user_hg(self, webserver): | |
394 | #clone some temp |
|
394 | # clone some temp | |
395 | DEST = _get_tmp_dir() |
|
395 | DEST = _get_tmp_dir() | |
396 | clone_url = webserver.repo_url(HG_REPO) |
|
396 | clone_url = webserver.repo_url(HG_REPO) | |
397 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, DEST) |
|
397 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, DEST) | |
398 |
|
398 | |||
399 | #lock repo |
|
399 | # lock repo | |
400 | r = Repository.get_by_repo_name(HG_REPO) |
|
400 | r = Repository.get_by_repo_name(HG_REPO) | |
401 | # let this user actually push ! |
|
401 | # let this user actually push ! | |
402 | RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, |
|
402 | RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, | |
@@ -404,7 +404,7 b' class TestVCSOperations(TestController):' | |||||
404 | Session().commit() |
|
404 | Session().commit() | |
405 | Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) |
|
405 | Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) | |
406 |
|
406 | |||
407 | #push fails repo is locked by other user ! |
|
407 | # push fails repo is locked by other user ! | |
408 | stdout, stderr = _add_files_and_push(webserver, 'hg', DEST, |
|
408 | stdout, stderr = _add_files_and_push(webserver, 'hg', DEST, | |
409 | username=TEST_USER_REGULAR_LOGIN, |
|
409 | username=TEST_USER_REGULAR_LOGIN, | |
410 | password=TEST_USER_REGULAR_PASS, |
|
410 | password=TEST_USER_REGULAR_PASS, | |
@@ -417,12 +417,12 b' class TestVCSOperations(TestController):' | |||||
417 | # Note: Git hooks must be executable on unix. This test will thus fail |
|
417 | # Note: Git hooks must be executable on unix. This test will thus fail | |
418 | # for example on Linux if /tmp is mounted noexec. |
|
418 | # for example on Linux if /tmp is mounted noexec. | |
419 |
|
419 | |||
420 | #clone some temp |
|
420 | # clone some temp | |
421 | DEST = _get_tmp_dir() |
|
421 | DEST = _get_tmp_dir() | |
422 | clone_url = webserver.repo_url(GIT_REPO) |
|
422 | clone_url = webserver.repo_url(GIT_REPO) | |
423 | stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, DEST) |
|
423 | stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, DEST) | |
424 |
|
424 | |||
425 | #lock repo |
|
425 | # lock repo | |
426 | r = Repository.get_by_repo_name(GIT_REPO) |
|
426 | r = Repository.get_by_repo_name(GIT_REPO) | |
427 | # let this user actually push ! |
|
427 | # let this user actually push ! | |
428 | RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, |
|
428 | RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, | |
@@ -430,7 +430,7 b' class TestVCSOperations(TestController):' | |||||
430 | Session().commit() |
|
430 | Session().commit() | |
431 | Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) |
|
431 | Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) | |
432 |
|
432 | |||
433 | #push fails repo is locked by other user ! |
|
433 | # push fails repo is locked by other user ! | |
434 | stdout, stderr = _add_files_and_push(webserver, 'git', DEST, |
|
434 | stdout, stderr = _add_files_and_push(webserver, 'git', DEST, | |
435 | username=TEST_USER_REGULAR_LOGIN, |
|
435 | username=TEST_USER_REGULAR_LOGIN, | |
436 | password=TEST_USER_REGULAR_PASS, |
|
436 | password=TEST_USER_REGULAR_PASS, | |
@@ -438,8 +438,8 b' class TestVCSOperations(TestController):' | |||||
438 | err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN) |
|
438 | err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN) | |
439 | assert err in stderr |
|
439 | assert err in stderr | |
440 |
|
440 | |||
441 | #TODO: fix this somehow later on Git, Git is stupid and even if we throw |
|
441 | # TODO: fix this somehow later on Git, Git is stupid and even if we throw | |
442 | #back 423 to it, it makes ANOTHER request and we fail there with 405 :/ |
|
442 | # back 423 to it, it makes ANOTHER request and we fail there with 405 :/ | |
443 |
|
443 | |||
444 | msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" |
|
444 | msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" | |
445 | % (GIT_REPO, TEST_USER_ADMIN_LOGIN)) |
|
445 | % (GIT_REPO, TEST_USER_ADMIN_LOGIN)) | |
@@ -453,25 +453,25 b' class TestVCSOperations(TestController):' | |||||
453 | r = Repository.get_by_repo_name(fork_name) |
|
453 | r = Repository.get_by_repo_name(fork_name) | |
454 | r.enable_locking = True |
|
454 | r.enable_locking = True | |
455 | Session().commit() |
|
455 | Session().commit() | |
456 | #clone some temp |
|
456 | # clone some temp | |
457 | DEST = _get_tmp_dir() |
|
457 | DEST = _get_tmp_dir() | |
458 | clone_url = webserver.repo_url(fork_name) |
|
458 | clone_url = webserver.repo_url(fork_name) | |
459 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, DEST) |
|
459 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, DEST) | |
460 |
|
460 | |||
461 | #check for lock repo after clone |
|
461 | # check for lock repo after clone | |
462 | r = Repository.get_by_repo_name(fork_name) |
|
462 | r = Repository.get_by_repo_name(fork_name) | |
463 | uid = User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id |
|
463 | uid = User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id | |
464 | assert r.locked[0] == uid |
|
464 | assert r.locked[0] == uid | |
465 |
|
465 | |||
466 | #push is ok and repo is now unlocked |
|
466 | # push is ok and repo is now unlocked | |
467 | stdout, stderr = _add_files_and_push(webserver, 'hg', DEST, clone_url=clone_url) |
|
467 | stdout, stderr = _add_files_and_push(webserver, 'hg', DEST, clone_url=clone_url) | |
468 | assert str('remote: Released lock on repo `%s`' % fork_name) in stdout |
|
468 | assert str('remote: Released lock on repo `%s`' % fork_name) in stdout | |
469 | #we need to cleanup the Session Here ! |
|
469 | # we need to cleanup the Session Here ! | |
470 | Session.remove() |
|
470 | Session.remove() | |
471 | r = Repository.get_by_repo_name(fork_name) |
|
471 | r = Repository.get_by_repo_name(fork_name) | |
472 | assert r.locked == [None, None] |
|
472 | assert r.locked == [None, None] | |
473 |
|
473 | |||
474 | #TODO: fix me ! somehow during tests hooks don't get called on Git |
|
474 | # TODO: fix me ! somehow during tests hooks don't get called on Git | |
475 | def test_push_unlocks_repository_git(self, webserver): |
|
475 | def test_push_unlocks_repository_git(self, webserver): | |
476 | # enable locking |
|
476 | # enable locking | |
477 | fork_name = '%s_fork%s' % (GIT_REPO, _RandomNameSequence().next()) |
|
477 | fork_name = '%s_fork%s' % (GIT_REPO, _RandomNameSequence().next()) | |
@@ -479,21 +479,21 b' class TestVCSOperations(TestController):' | |||||
479 | r = Repository.get_by_repo_name(fork_name) |
|
479 | r = Repository.get_by_repo_name(fork_name) | |
480 | r.enable_locking = True |
|
480 | r.enable_locking = True | |
481 | Session().commit() |
|
481 | Session().commit() | |
482 | #clone some temp |
|
482 | # clone some temp | |
483 | DEST = _get_tmp_dir() |
|
483 | DEST = _get_tmp_dir() | |
484 | clone_url = webserver.repo_url(fork_name) |
|
484 | clone_url = webserver.repo_url(fork_name) | |
485 | stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, DEST) |
|
485 | stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, DEST) | |
486 |
|
486 | |||
487 | #check for lock repo after clone |
|
487 | # check for lock repo after clone | |
488 | r = Repository.get_by_repo_name(fork_name) |
|
488 | r = Repository.get_by_repo_name(fork_name) | |
489 | assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id |
|
489 | assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id | |
490 |
|
490 | |||
491 | #push is ok and repo is now unlocked |
|
491 | # push is ok and repo is now unlocked | |
492 | stdout, stderr = _add_files_and_push(webserver, 'git', DEST, clone_url=clone_url) |
|
492 | stdout, stderr = _add_files_and_push(webserver, 'git', DEST, clone_url=clone_url) | |
493 | _check_proper_git_push(stdout, stderr) |
|
493 | _check_proper_git_push(stdout, stderr) | |
494 |
|
494 | |||
495 | assert ('remote: Released lock on repo `%s`' % fork_name) in stderr |
|
495 | assert ('remote: Released lock on repo `%s`' % fork_name) in stderr | |
496 | #we need to cleanup the Session Here ! |
|
496 | # we need to cleanup the Session Here ! | |
497 | Session.remove() |
|
497 | Session.remove() | |
498 | r = Repository.get_by_repo_name(fork_name) |
|
498 | r = Repository.get_by_repo_name(fork_name) | |
499 | assert r.locked == [None, None] |
|
499 | assert r.locked == [None, None] | |
@@ -507,7 +507,7 b' class TestVCSOperations(TestController):' | |||||
507 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) |
|
507 | stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) | |
508 | assert 'abort: HTTP Error 403: Forbidden' in stderr |
|
508 | assert 'abort: HTTP Error 403: Forbidden' in stderr | |
509 | finally: |
|
509 | finally: | |
510 | #release IP restrictions |
|
510 | # release IP restrictions | |
511 | for ip in UserIpMap.query(): |
|
511 | for ip in UserIpMap.query(): | |
512 | UserIpMap.delete(ip.ip_id) |
|
512 | UserIpMap.delete(ip.ip_id) | |
513 | Session().commit() |
|
513 | Session().commit() | |
@@ -535,7 +535,7 b' class TestVCSOperations(TestController):' | |||||
535 | # The message apparently changed in Git 1.8.3, so match it loosely. |
|
535 | # The message apparently changed in Git 1.8.3, so match it loosely. | |
536 | assert re.search(r'\b403\b', stderr) |
|
536 | assert re.search(r'\b403\b', stderr) | |
537 | finally: |
|
537 | finally: | |
538 | #release IP restrictions |
|
538 | # release IP restrictions | |
539 | for ip in UserIpMap.query(): |
|
539 | for ip in UserIpMap.query(): | |
540 | UserIpMap.delete(ip.ip_id) |
|
540 | UserIpMap.delete(ip.ip_id) | |
541 | Session().commit() |
|
541 | Session().commit() |
@@ -13,6 +13,7 b'' | |||||
13 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
13 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
14 |
|
14 | |||
15 | import pytest |
|
15 | import pytest | |
|
16 | ||||
16 | from kallithea.model.db import Repository |
|
17 | from kallithea.model.db import Repository | |
17 | from kallithea.tests.base import * |
|
18 | from kallithea.tests.base import * | |
18 |
|
19 |
@@ -132,8 +132,8 b' def create_test_repo(force=True):' | |||||
132 |
|
132 | |||
133 | form_data = {'repo_name': HG_REPO, |
|
133 | form_data = {'repo_name': HG_REPO, | |
134 | 'repo_type': 'hg', |
|
134 | 'repo_type': 'hg', | |
135 | 'private':False, |
|
135 | 'private': False, | |
136 |
'clone_uri': '' |
|
136 | 'clone_uri': ''} | |
137 | rm = RepoModel() |
|
137 | rm = RepoModel() | |
138 | rm.base_path = '/home/hg' |
|
138 | rm.base_path = '/home/hg' | |
139 | rm.create(form_data, user) |
|
139 | rm.create(form_data, user) | |
@@ -182,10 +182,11 b' def test_clone_with_credentials(no_error' | |||||
182 | if not no_errors: |
|
182 | if not no_errors: | |
183 | if backend == 'hg': |
|
183 | if backend == 'hg': | |
184 | assert """adding file changes""" in stdout, 'no messages about cloning' |
|
184 | assert """adding file changes""" in stdout, 'no messages about cloning' | |
185 |
assert """abort""" not in stderr |
|
185 | assert """abort""" not in stderr, 'got error from clone' | |
186 | elif backend == 'git': |
|
186 | elif backend == 'git': | |
187 | assert """Cloning into""" in stdout, 'no messages about cloning' |
|
187 | assert """Cloning into""" in stdout, 'no messages about cloning' | |
188 |
|
188 | |||
|
189 | ||||
189 | if __name__ == '__main__': |
|
190 | if __name__ == '__main__': | |
190 | try: |
|
191 | try: | |
191 | create_test_user(force=False) |
|
192 | create_test_user(force=False) |
@@ -63,7 +63,7 b" print 'Crawling @ %s' % BASE_URI" | |||||
63 | BASE_URI += '%s' |
|
63 | BASE_URI += '%s' | |
64 | PROJECT_PATH = os.path.join('/', 'home', 'username', 'repos') |
|
64 | PROJECT_PATH = os.path.join('/', 'home', 'username', 'repos') | |
65 | PROJECTS = [ |
|
65 | PROJECTS = [ | |
66 | #'linux-magx-pbranch', |
|
66 | # 'linux-magx-pbranch', | |
67 | 'CPython', |
|
67 | 'CPython', | |
68 | 'kallithea', |
|
68 | 'kallithea', | |
69 | ] |
|
69 | ] |
@@ -61,5 +61,6 b' def main():' | |||||
61 | collector() |
|
61 | collector() | |
62 | unittest.main() |
|
62 | unittest.main() | |
63 |
|
63 | |||
|
64 | ||||
64 | #if __name__ == '__main__': |
|
65 | #if __name__ == '__main__': | |
65 | # main() |
|
66 | # main() |
@@ -83,5 +83,5 b' PACKAGE_DIR = os.path.abspath(os.path.jo' | |||||
83 | shutil.copy(os.path.join(THIS, 'aconfig'), _dest) |
|
83 | shutil.copy(os.path.join(THIS, 'aconfig'), _dest) | |
84 | TEST_USER_CONFIG_FILE = _dest |
|
84 | TEST_USER_CONFIG_FILE = _dest | |
85 |
|
85 | |||
86 | #overide default configurations with kallithea ones |
|
86 | # overide default configurations with kallithea ones | |
87 | from kallithea.tests.base import * |
|
87 | from kallithea.tests.base import * |
@@ -100,6 +100,7 b' class ArchivesTestCaseMixin(_BackendTest' | |||||
100 | with self.assertRaises(VCSError): |
|
100 | with self.assertRaises(VCSError): | |
101 | self.tip.fill_archive(prefix='/any') |
|
101 | self.tip.fill_archive(prefix='/any') | |
102 |
|
102 | |||
|
103 | ||||
103 | # For each backend create test case class |
|
104 | # For each backend create test case class | |
104 | for alias in SCM_TESTS: |
|
105 | for alias in SCM_TESTS: | |
105 | attrs = { |
|
106 | attrs = { |
@@ -49,6 +49,7 b' class TestBaseChangeset(unittest.TestCas' | |||||
49 | 'removed': [], |
|
49 | 'removed': [], | |
50 | }) |
|
50 | }) | |
51 |
|
51 | |||
|
52 | ||||
52 | class _ChangesetsWithCommitsTestCaseixin(_BackendTestMixin): |
|
53 | class _ChangesetsWithCommitsTestCaseixin(_BackendTestMixin): | |
53 | recreate_repo_per_test = True |
|
54 | recreate_repo_per_test = True | |
54 |
|
55 | |||
@@ -365,6 +366,7 b' class _ChangesetsChangesTestCaseMixin(_B' | |||||
365 | self.assertEqual(33188, changeset.get_file_mode('foo/bał')) |
|
366 | self.assertEqual(33188, changeset.get_file_mode('foo/bał')) | |
366 | self.assertEqual(33188, changeset.get_file_mode(u'foo/bał')) |
|
367 | self.assertEqual(33188, changeset.get_file_mode(u'foo/bał')) | |
367 |
|
368 | |||
|
369 | ||||
368 | # For each backend create test case class |
|
370 | # For each backend create test case class | |
369 | for alias in SCM_TESTS: |
|
371 | for alias in SCM_TESTS: | |
370 | attrs = { |
|
372 | attrs = { |
@@ -104,7 +104,7 b' class GitRepositoryTest(unittest.TestCas' | |||||
104 | create=True, src_url=TEST_GIT_REPO, update_after_clone=True) |
|
104 | create=True, src_url=TEST_GIT_REPO, update_after_clone=True) | |
105 | self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) |
|
105 | self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) | |
106 |
|
106 | |||
107 | #check if current workdir was updated |
|
107 | # check if current workdir was updated | |
108 | fpath = os.path.join(clone_path, 'MANIFEST.in') |
|
108 | fpath = os.path.join(clone_path, 'MANIFEST.in') | |
109 | self.assertEqual(True, os.path.isfile(fpath), |
|
109 | self.assertEqual(True, os.path.isfile(fpath), | |
110 | 'Repo was cloned and updated but file %s could not be found' |
|
110 | 'Repo was cloned and updated but file %s could not be found' | |
@@ -116,7 +116,7 b' class GitRepositoryTest(unittest.TestCas' | |||||
116 | repo_clone = GitRepository(clone_path, |
|
116 | repo_clone = GitRepository(clone_path, | |
117 | create=True, src_url=TEST_GIT_REPO, update_after_clone=False) |
|
117 | create=True, src_url=TEST_GIT_REPO, update_after_clone=False) | |
118 | self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) |
|
118 | self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) | |
119 | #check if current workdir was *NOT* updated |
|
119 | # check if current workdir was *NOT* updated | |
120 | fpath = os.path.join(clone_path, 'MANIFEST.in') |
|
120 | fpath = os.path.join(clone_path, 'MANIFEST.in') | |
121 | # Make sure it's not bare repo |
|
121 | # Make sure it's not bare repo | |
122 | self.assertFalse(repo_clone._repo.bare) |
|
122 | self.assertFalse(repo_clone._repo.bare) | |
@@ -170,10 +170,8 b' class GitRepositoryTest(unittest.TestCas' | |||||
170 | 'e686b958768ee96af8029fe19c6050b1a8dd3b2b']) |
|
170 | 'e686b958768ee96af8029fe19c6050b1a8dd3b2b']) | |
171 | self.assertTrue(subset.issubset(set(self.repo.revisions))) |
|
171 | self.assertTrue(subset.issubset(set(self.repo.revisions))) | |
172 |
|
172 | |||
173 |
|
||||
174 |
|
||||
175 | def test_slicing(self): |
|
173 | def test_slicing(self): | |
176 | #4 1 5 10 95 |
|
174 | # 4 1 5 10 95 | |
177 | for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5), |
|
175 | for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5), | |
178 | (10, 20, 10), (5, 100, 95)]: |
|
176 | (10, 20, 10), (5, 100, 95)]: | |
179 | revs = list(self.repo[sfrom:sto]) |
|
177 | revs = list(self.repo[sfrom:sto]) | |
@@ -181,7 +179,6 b' class GitRepositoryTest(unittest.TestCas' | |||||
181 | self.assertEqual(revs[0], self.repo.get_changeset(sfrom)) |
|
179 | self.assertEqual(revs[0], self.repo.get_changeset(sfrom)) | |
182 | self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1)) |
|
180 | self.assertEqual(revs[-1], self.repo.get_changeset(sto - 1)) | |
183 |
|
181 | |||
184 |
|
||||
185 | def test_branches(self): |
|
182 | def test_branches(self): | |
186 | # TODO: Need more tests here |
|
183 | # TODO: Need more tests here | |
187 | # Removed (those are 'remotes' branches for cloned repo) |
|
184 | # Removed (those are 'remotes' branches for cloned repo) | |
@@ -370,7 +367,6 b' class GitChangesetTest(unittest.TestCase' | |||||
370 | 'vcs/backends/hg.py', 854), |
|
367 | 'vcs/backends/hg.py', 854), | |
371 | ('6e125e7c890379446e98980d8ed60fba87d0f6d1', |
|
368 | ('6e125e7c890379446e98980d8ed60fba87d0f6d1', | |
372 | 'setup.py', 1068), |
|
369 | 'setup.py', 1068), | |
373 |
|
||||
374 | ('d955cd312c17b02143c04fa1099a352b04368118', |
|
370 | ('d955cd312c17b02143c04fa1099a352b04368118', | |
375 | 'vcs/backends/base.py', 2921), |
|
371 | 'vcs/backends/base.py', 2921), | |
376 | ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e', |
|
372 | ('ca1eb7957a54bce53b12d1a51b13452f95bc7c7e', | |
@@ -548,7 +544,7 b' class GitChangesetTest(unittest.TestCase' | |||||
548 | self.assertEqual(l1_1, l1_2) |
|
544 | self.assertEqual(l1_1, l1_2) | |
549 | l1 = l1_1 |
|
545 | l1 = l1_1 | |
550 | l2 = files[fname][rev]['changesets'] |
|
546 | l2 = files[fname][rev]['changesets'] | |
551 |
self.assertTrue(l1 == l2 |
|
547 | self.assertTrue(l1 == l2, "The lists of revision for %s@rev %s" | |
552 | "from annotation list should match each other, " |
|
548 | "from annotation list should match each other, " | |
553 | "got \n%s \nvs \n%s " % (fname, rev, l1, l2)) |
|
549 | "got \n%s \nvs \n%s " % (fname, rev, l1, l2)) | |
554 |
|
550 | |||
@@ -766,7 +762,7 b' class GitRegressionTest(_BackendTestMixi' | |||||
766 |
|
762 | |||
767 | def test_similar_paths(self): |
|
763 | def test_similar_paths(self): | |
768 | cs = self.repo.get_changeset() |
|
764 | cs = self.repo.get_changeset() | |
769 | paths = lambda *n:[x.path for x in n] |
|
765 | paths = lambda *n: [x.path for x in n] | |
770 | self.assertEqual(paths(*cs.get_nodes('bot')), ['bot/build', 'bot/templates', 'bot/__init__.py']) |
|
766 | self.assertEqual(paths(*cs.get_nodes('bot')), ['bot/build', 'bot/templates', 'bot/__init__.py']) | |
771 | self.assertEqual(paths(*cs.get_nodes('bot/build')), ['bot/build/migrations', 'bot/build/static', 'bot/build/templates']) |
|
767 | self.assertEqual(paths(*cs.get_nodes('bot/build')), ['bot/build/migrations', 'bot/build/static', 'bot/build/templates']) | |
772 | self.assertEqual(paths(*cs.get_nodes('bot/build/static')), ['bot/build/static/templates']) |
|
768 | self.assertEqual(paths(*cs.get_nodes('bot/build/static')), ['bot/build/static/templates']) |
@@ -28,7 +28,7 b' class MercurialRepositoryTest(unittest.T' | |||||
28 | self.assertRaises(RepositoryError, MercurialRepository, wrong_repo_path) |
|
28 | self.assertRaises(RepositoryError, MercurialRepository, wrong_repo_path) | |
29 |
|
29 | |||
30 | def test_unicode_path_repo(self): |
|
30 | def test_unicode_path_repo(self): | |
31 | self.assertRaises(VCSError,lambda:MercurialRepository(u'iShouldFail')) |
|
31 | self.assertRaises(VCSError, lambda: MercurialRepository(u'iShouldFail')) | |
32 |
|
32 | |||
33 | def test_repo_clone(self): |
|
33 | def test_repo_clone(self): | |
34 | self.__check_for_existing_repo() |
|
34 | self.__check_for_existing_repo() | |
@@ -47,7 +47,7 b' class MercurialRepositoryTest(unittest.T' | |||||
47 | src_url=TEST_HG_REPO, update_after_clone=True) |
|
47 | src_url=TEST_HG_REPO, update_after_clone=True) | |
48 | self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) |
|
48 | self.assertEqual(len(repo.revisions), len(repo_clone.revisions)) | |
49 |
|
49 | |||
50 | #check if current workdir was updated |
|
50 | # check if current workdir was updated | |
51 | self.assertEqual(os.path.isfile(os.path.join(TEST_HG_REPO_CLONE \ |
|
51 | self.assertEqual(os.path.isfile(os.path.join(TEST_HG_REPO_CLONE \ | |
52 | + '_w_update', |
|
52 | + '_w_update', | |
53 | 'MANIFEST.in')), True,) |
|
53 | 'MANIFEST.in')), True,) | |
@@ -98,7 +98,6 b' class MercurialRepositoryTest(unittest.T' | |||||
98 | ]) |
|
98 | ]) | |
99 | self.assertTrue(subset.issubset(set(self.repo.revisions))) |
|
99 | self.assertTrue(subset.issubset(set(self.repo.revisions))) | |
100 |
|
100 | |||
101 |
|
||||
102 | # check if we have the proper order of revisions |
|
101 | # check if we have the proper order of revisions | |
103 | org = ['b986218ba1c9b0d6a259fac9b050b1724ed8e545', |
|
102 | org = ['b986218ba1c9b0d6a259fac9b050b1724ed8e545', | |
104 | '3d8f361e72ab303da48d799ff1ac40d5ac37c67e', |
|
103 | '3d8f361e72ab303da48d799ff1ac40d5ac37c67e', | |
@@ -139,7 +138,7 b' class MercurialRepositoryTest(unittest.T' | |||||
139 | self.assertEqual(sliced, itered) |
|
138 | self.assertEqual(sliced, itered) | |
140 |
|
139 | |||
141 | def test_slicing(self): |
|
140 | def test_slicing(self): | |
142 | #4 1 5 10 95 |
|
141 | # 4 1 5 10 95 | |
143 | for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5), |
|
142 | for sfrom, sto, size in [(0, 4, 4), (1, 2, 1), (10, 15, 5), | |
144 | (10, 20, 10), (5, 100, 95)]: |
|
143 | (10, 20, 10), (5, 100, 95)]: | |
145 | revs = list(self.repo[sfrom:sto]) |
|
144 | revs = list(self.repo[sfrom:sto]) | |
@@ -150,7 +149,7 b' class MercurialRepositoryTest(unittest.T' | |||||
150 | def test_branches(self): |
|
149 | def test_branches(self): | |
151 | # TODO: Need more tests here |
|
150 | # TODO: Need more tests here | |
152 |
|
151 | |||
153 | #active branches |
|
152 | # active branches | |
154 | self.assertTrue('default' in self.repo.branches) |
|
153 | self.assertTrue('default' in self.repo.branches) | |
155 | self.assertTrue('stable' in self.repo.branches) |
|
154 | self.assertTrue('stable' in self.repo.branches) | |
156 |
|
155 | |||
@@ -201,13 +200,13 b' class MercurialRepositoryTest(unittest.T' | |||||
201 | self.assertEqual(node.kind, NodeKind.FILE) |
|
200 | self.assertEqual(node.kind, NodeKind.FILE) | |
202 |
|
201 | |||
203 | def test_not_existing_changeset(self): |
|
202 | def test_not_existing_changeset(self): | |
204 | #rawid |
|
203 | # rawid | |
205 | self.assertRaises(RepositoryError, self.repo.get_changeset, |
|
204 | self.assertRaises(RepositoryError, self.repo.get_changeset, | |
206 | 'abcd' * 10) |
|
205 | 'abcd' * 10) | |
207 | #shortid |
|
206 | # shortid | |
208 | self.assertRaises(RepositoryError, self.repo.get_changeset, |
|
207 | self.assertRaises(RepositoryError, self.repo.get_changeset, | |
209 | 'erro' * 4) |
|
208 | 'erro' * 4) | |
210 | #numeric |
|
209 | # numeric | |
211 | self.assertRaises(RepositoryError, self.repo.get_changeset, |
|
210 | self.assertRaises(RepositoryError, self.repo.get_changeset, | |
212 | self.repo.count() + 1) |
|
211 | self.repo.count() + 1) | |
213 |
|
212 | |||
@@ -414,7 +413,7 b' class MercurialChangesetTest(unittest.Te' | |||||
414 | self.assertEqual(l1_1, l1_2) |
|
413 | self.assertEqual(l1_1, l1_2) | |
415 | l1 = l1_2 = [x[2]().revision for x in cs.get_file_annotate(fname)] |
|
414 | l1 = l1_2 = [x[2]().revision for x in cs.get_file_annotate(fname)] | |
416 | l2 = files[fname][rev]['changesets'] |
|
415 | l2 = files[fname][rev]['changesets'] | |
417 |
self.assertTrue(l1 == l2 |
|
416 | self.assertTrue(l1 == l2, "The lists of revision for %s@rev%s" | |
418 | "from annotation list should match each other," |
|
417 | "from annotation list should match each other," | |
419 | "got \n%s \nvs \n%s " % (fname, rev, l1, l2)) |
|
418 | "got \n%s \nvs \n%s " % (fname, rev, l1, l2)) | |
420 |
|
419 | |||
@@ -462,7 +461,7 b' class MercurialChangesetTest(unittest.Te' | |||||
462 | self.assertEqual(set((node.path for node in chset88.changed)), |
|
461 | self.assertEqual(set((node.path for node in chset88.changed)), | |
463 | set(['.hgignore'])) |
|
462 | set(['.hgignore'])) | |
464 | self.assertEqual(set((node.path for node in chset88.removed)), set()) |
|
463 | self.assertEqual(set((node.path for node in chset88.removed)), set()) | |
465 | # |
|
464 | ||
466 | # 85: |
|
465 | # 85: | |
467 | # added: 2 ['vcs/utils/diffs.py', 'vcs/web/simplevcs/views/diffs.py'] |
|
466 | # added: 2 ['vcs/utils/diffs.py', 'vcs/web/simplevcs/views/diffs.py'] | |
468 | # changed: 4 ['vcs/web/simplevcs/models.py', ...] |
|
467 | # changed: 4 ['vcs/web/simplevcs/models.py', ...] | |
@@ -536,13 +535,12 b' class MercurialChangesetTest(unittest.Te' | |||||
536 | path = 'foo/bar/setup.py' |
|
535 | path = 'foo/bar/setup.py' | |
537 | self.assertRaises(VCSError, self.repo.get_changeset().get_node, path) |
|
536 | self.assertRaises(VCSError, self.repo.get_changeset().get_node, path) | |
538 |
|
537 | |||
539 |
|
||||
540 | def test_archival_file(self): |
|
538 | def test_archival_file(self): | |
541 | #TODO: |
|
539 | # TODO: | |
542 | pass |
|
540 | pass | |
543 |
|
541 | |||
544 | def test_archival_as_generator(self): |
|
542 | def test_archival_as_generator(self): | |
545 | #TODO: |
|
543 | # TODO: | |
546 | pass |
|
544 | pass | |
547 |
|
545 | |||
548 | def test_archival_wrong_kind(self): |
|
546 | def test_archival_wrong_kind(self): | |
@@ -550,10 +548,9 b' class MercurialChangesetTest(unittest.Te' | |||||
550 | self.assertRaises(VCSError, tip.fill_archive, kind='error') |
|
548 | self.assertRaises(VCSError, tip.fill_archive, kind='error') | |
551 |
|
549 | |||
552 | def test_archival_empty_prefix(self): |
|
550 | def test_archival_empty_prefix(self): | |
553 | #TODO: |
|
551 | # TODO: | |
554 | pass |
|
552 | pass | |
555 |
|
553 | |||
556 |
|
||||
557 | def test_author_email(self): |
|
554 | def test_author_email(self): | |
558 | self.assertEqual('marcin@python-blog.com', |
|
555 | self.assertEqual('marcin@python-blog.com', | |
559 | self.repo.get_changeset('b986218ba1c9').author_email) |
|
556 | self.repo.get_changeset('b986218ba1c9').author_email) |
@@ -170,6 +170,7 b' class NodeBasicTest(unittest.TestCase):' | |||||
170 | self.assertEqual(my_node3.mimetype, 'application/octet-stream') |
|
170 | self.assertEqual(my_node3.mimetype, 'application/octet-stream') | |
171 | self.assertEqual(my_node3.get_mimetype(), ('application/octet-stream', None)) |
|
171 | self.assertEqual(my_node3.get_mimetype(), ('application/octet-stream', None)) | |
172 |
|
172 | |||
|
173 | ||||
173 | class NodeContentTest(unittest.TestCase): |
|
174 | class NodeContentTest(unittest.TestCase): | |
174 |
|
175 | |||
175 | def test_if_binary(self): |
|
176 | def test_if_binary(self): |
@@ -46,6 +46,7 b' class TagsTestCaseMixin(_BackendTestMixi' | |||||
46 | self.repo.tag('11', 'joe') |
|
46 | self.repo.tag('11', 'joe') | |
47 | self.assertTrue('11' in self.repo.tags) |
|
47 | self.assertTrue('11' in self.repo.tags) | |
48 |
|
48 | |||
|
49 | ||||
49 | # For each backend create test case class |
|
50 | # For each backend create test case class | |
50 | for alias in SCM_TESTS: |
|
51 | for alias in SCM_TESTS: | |
51 | attrs = { |
|
52 | attrs = { |
@@ -43,7 +43,6 b' class PathsTest(unittest.TestCase):' | |||||
43 | for path, expected in paths_and_results: |
|
43 | for path, expected in paths_and_results: | |
44 | self._test_get_dirs_for_path(path, expected) |
|
44 | self._test_get_dirs_for_path(path, expected) | |
45 |
|
45 | |||
46 |
|
||||
47 | def test_get_scm(self): |
|
46 | def test_get_scm(self): | |
48 | self.assertEqual(('hg', TEST_HG_REPO), get_scm(TEST_HG_REPO)) |
|
47 | self.assertEqual(('hg', TEST_HG_REPO), get_scm(TEST_HG_REPO)) | |
49 | self.assertEqual(('git', TEST_GIT_REPO), get_scm(TEST_GIT_REPO)) |
|
48 | self.assertEqual(('git', TEST_GIT_REPO), get_scm(TEST_GIT_REPO)) | |
@@ -209,13 +208,10 b' class TestAuthorExtractors(unittest.Test' | |||||
209 | ] |
|
208 | ] | |
210 |
|
209 | |||
211 | def test_author_email(self): |
|
210 | def test_author_email(self): | |
212 |
|
||||
213 | for test_str, result in self.TEST_AUTHORS: |
|
211 | for test_str, result in self.TEST_AUTHORS: | |
214 | self.assertEqual(result[1], author_email(test_str)) |
|
212 | self.assertEqual(result[1], author_email(test_str)) | |
215 |
|
213 | |||
216 |
|
||||
217 | def test_author_name(self): |
|
214 | def test_author_name(self): | |
218 |
|
||||
219 | for test_str, result in self.TEST_AUTHORS: |
|
215 | for test_str, result in self.TEST_AUTHORS: | |
220 | self.assertEqual(result[0], author_name(test_str)) |
|
216 | self.assertEqual(result[0], author_name(test_str)) | |
221 |
|
217 |
@@ -1,4 +1,3 b'' | |||||
1 |
|
||||
2 |
|
|
1 | import os | |
3 | import shutil |
|
2 | import shutil | |
4 |
|
3 | |||
@@ -9,7 +8,6 b' from kallithea.lib.vcs.utils.compat impo' | |||||
9 | from kallithea.tests.vcs.conf import TEST_HG_REPO, TEST_GIT_REPO, TEST_TMP_PATH |
|
8 | from kallithea.tests.vcs.conf import TEST_HG_REPO, TEST_GIT_REPO, TEST_TMP_PATH | |
10 |
|
9 | |||
11 |
|
10 | |||
12 |
|
||||
13 | class VCSTest(unittest.TestCase): |
|
11 | class VCSTest(unittest.TestCase): | |
14 | """ |
|
12 | """ | |
15 | Tests for main module's methods. |
|
13 | Tests for main module's methods. | |
@@ -24,14 +22,14 b' class VCSTest(unittest.TestCase):' | |||||
24 | path = TEST_HG_REPO |
|
22 | path = TEST_HG_REPO | |
25 | backend = get_backend(alias) |
|
23 | backend = get_backend(alias) | |
26 | repo = backend(safe_str(path)) |
|
24 | repo = backend(safe_str(path)) | |
27 | self.assertEqual('hg',repo.alias) |
|
25 | self.assertEqual('hg', repo.alias) | |
28 |
|
26 | |||
29 | def test_alias_detect_git(self): |
|
27 | def test_alias_detect_git(self): | |
30 | alias = 'git' |
|
28 | alias = 'git' | |
31 | path = TEST_GIT_REPO |
|
29 | path = TEST_GIT_REPO | |
32 | backend = get_backend(alias) |
|
30 | backend = get_backend(alias) | |
33 | repo = backend(safe_str(path)) |
|
31 | repo = backend(safe_str(path)) | |
34 | self.assertEqual('git',repo.alias) |
|
32 | self.assertEqual('git', repo.alias) | |
35 |
|
33 | |||
36 | def test_wrong_alias(self): |
|
34 | def test_wrong_alias(self): | |
37 | alias = 'wrong_alias' |
|
35 | alias = 'wrong_alias' | |
@@ -64,7 +62,6 b' class VCSTest(unittest.TestCase):' | |||||
64 | self.assertEqual(repo.__class__, get_repo(safe_str(path)).__class__) |
|
62 | self.assertEqual(repo.__class__, get_repo(safe_str(path)).__class__) | |
65 | self.assertEqual(repo.path, get_repo(safe_str(path)).path) |
|
63 | self.assertEqual(repo.path, get_repo(safe_str(path)).path) | |
66 |
|
64 | |||
67 |
|
||||
68 | def test_get_repo_err(self): |
|
65 | def test_get_repo_err(self): | |
69 | blank_repo_path = os.path.join(TEST_TMP_PATH, 'blank-error-repo') |
|
66 | blank_repo_path = os.path.join(TEST_TMP_PATH, 'blank-error-repo') | |
70 | if os.path.isdir(blank_repo_path): |
|
67 | if os.path.isdir(blank_repo_path): |
General Comments 0
You need to be logged in to leave comments.
Login now