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