##// END OF EJS Templates
Disable git support due to large problems with dulwich....
marcink -
r710:e2f3c8e6 beta
parent child Browse files
Show More
@@ -1,35 +1,40 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # RhodeCode, a web based repository management based on pylons
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 9, 2010
22 22 RhodeCode, a web based repository management based on pylons
23 23 versioning implementation: http://semver.org/
24 24 @author: marcink
25 25 """
26 26
27 27 VERSION = (1, 1, 0, 'beta')
28 28
29 29 __version__ = '.'.join((str(each) for each in VERSION[:4]))
30 30
31 31 def get_version():
32 32 """
33 33 Returns shorter version (digit parts only) as string.
34 34 """
35 35 return '.'.join((str(each) for each in VERSION[:3]))
36
37 BACKENDS = {
38 'hg': 'Mercurial repository',
39 #'git': 'Git repository',
40 }
@@ -1,46 +1,46 b''
1 1 """The base Controller API
2 2
3 3 Provides the BaseController class for subclassing.
4 4 """
5 5 from pylons import config, tmpl_context as c, request, session
6 6 from pylons.controllers import WSGIController
7 7 from pylons.templating import render_mako as render
8 8 from rhodecode import __version__
9 9 from rhodecode.lib import auth
10 10 from rhodecode.lib.utils import get_repo_slug
11 11 from rhodecode.model import meta
12 12 from rhodecode.model.scm import ScmModel
13 from vcs import BACKENDS
13 from rhodecode import BACKENDS
14 14
15 15 class BaseController(WSGIController):
16 16
17 17 def __before__(self):
18 18 c.rhodecode_version = __version__
19 19 c.rhodecode_name = config['rhodecode_title']
20 20 c.repo_name = get_repo_slug(request)
21 21 c.cached_repo_list = ScmModel().get_repos()
22 22 c.backends = BACKENDS.keys()
23 23
24 24 if c.repo_name:
25 25 cached_repo = ScmModel().get(c.repo_name)
26 26
27 27 if cached_repo:
28 28 c.repository_tags = cached_repo.tags
29 29 c.repository_branches = cached_repo.branches
30 30 else:
31 31 c.repository_tags = {}
32 32 c.repository_branches = {}
33 33
34 34 self.sa = meta.Session()
35 35
36 36 def __call__(self, environ, start_response):
37 37 """Invoke the Controller"""
38 38 # WSGIController.__call__ dispatches to the Controller method
39 39 # the request is routed to. This routing information is
40 40 # available in environ['pylons.routes_dict']
41 41 try:
42 42 #putting this here makes sure that we update permissions every time
43 43 self.rhodecode_user = c.rhodecode_user = auth.get_user(session)
44 44 return WSGIController.__call__(self, environ, start_response)
45 45 finally:
46 46 meta.Session.remove()
@@ -1,388 +1,388 b''
1 1 """ this is forms validation classes
2 2 http://formencode.org/module-formencode.validators.html
3 3 for list off all availible validators
4 4
5 5 we can create our own validators
6 6
7 7 The table below outlines the options which can be used in a schema in addition to the validators themselves
8 8 pre_validators [] These validators will be applied before the schema
9 9 chained_validators [] These validators will be applied after the schema
10 10 allow_extra_fields False If True, then it is not an error when keys that aren't associated with a validator are present
11 11 filter_extra_fields False If True, then keys that aren't associated with a validator are removed
12 12 if_key_missing NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
13 13 ignore_key_missing False If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
14 14
15 15
16 16 <name> = formencode.validators.<name of validator>
17 17 <name> must equal form name
18 18 list=[1,2,3,4,5]
19 19 for SELECT use formencode.All(OneOf(list), Int())
20 20
21 21 """
22 22 from formencode import All
23 23 from formencode.validators import UnicodeString, OneOf, Int, Number, Regex, \
24 24 Email, Bool, StringBoolean
25 25 from pylons import session
26 26 from pylons.i18n.translation import _
27 27 from rhodecode.lib.auth import authfunc, get_crypt_password
28 28 from rhodecode.lib.exceptions import LdapImportError
29 29 from rhodecode.model import meta
30 30 from rhodecode.model.user import UserModel
31 31 from rhodecode.model.repo import RepoModel
32 32 from rhodecode.model.db import User
33 33 from webhelpers.pylonslib.secure_form import authentication_token
34 from vcs import BACKENDS
34 from rhodecode import BACKENDS
35 35 import formencode
36 36 import logging
37 37 import os
38 38 import rhodecode.lib.helpers as h
39 39
40 40 log = logging.getLogger(__name__)
41 41
42 42 #this is needed to translate the messages using _() in validators
43 43 class State_obj(object):
44 44 _ = staticmethod(_)
45 45
46 46 #===============================================================================
47 47 # VALIDATORS
48 48 #===============================================================================
49 49 class ValidAuthToken(formencode.validators.FancyValidator):
50 50 messages = {'invalid_token':_('Token mismatch')}
51 51
52 52 def validate_python(self, value, state):
53 53
54 54 if value != authentication_token():
55 55 raise formencode.Invalid(self.message('invalid_token', state,
56 56 search_number=value), value, state)
57 57
58 58 def ValidUsername(edit, old_data):
59 59 class _ValidUsername(formencode.validators.FancyValidator):
60 60
61 61 def validate_python(self, value, state):
62 62 if value in ['default', 'new_user']:
63 63 raise formencode.Invalid(_('Invalid username'), value, state)
64 64 #check if user is unique
65 65 old_un = None
66 66 if edit:
67 67 old_un = UserModel().get(old_data.get('user_id')).username
68 68
69 69 if old_un != value or not edit:
70 70 if UserModel().get_by_username(value, cache=False):
71 71 raise formencode.Invalid(_('This username already exists') ,
72 72 value, state)
73 73
74 74 return _ValidUsername
75 75
76 76 class ValidPassword(formencode.validators.FancyValidator):
77 77
78 78 def to_python(self, value, state):
79 79 if value:
80 80 return get_crypt_password(value)
81 81
82 82 class ValidAuth(formencode.validators.FancyValidator):
83 83 messages = {
84 84 'invalid_password':_('invalid password'),
85 85 'invalid_login':_('invalid user name'),
86 86 'disabled_account':_('Your account is disabled')
87 87
88 88 }
89 89 #error mapping
90 90 e_dict = {'username':messages['invalid_login'],
91 91 'password':messages['invalid_password']}
92 92 e_dict_disable = {'username':messages['disabled_account']}
93 93
94 94 def validate_python(self, value, state):
95 95 password = value['password']
96 96 username = value['username']
97 97 user = UserModel().get_by_username(username)
98 98
99 99 if authfunc(None, username, password):
100 100 return value
101 101 else:
102 102 if user and user.active is False:
103 103 log.warning('user %s is disabled', username)
104 104 raise formencode.Invalid(self.message('disabled_account',
105 105 state=State_obj),
106 106 value, state,
107 107 error_dict=self.e_dict_disable)
108 108 else:
109 109 log.warning('user %s not authenticated', username)
110 110 raise formencode.Invalid(self.message('invalid_password',
111 111 state=State_obj), value, state,
112 112 error_dict=self.e_dict)
113 113
114 114 class ValidRepoUser(formencode.validators.FancyValidator):
115 115
116 116 def to_python(self, value, state):
117 117 sa = meta.Session()
118 118 try:
119 119 self.user_db = sa.query(User)\
120 120 .filter(User.active == True)\
121 121 .filter(User.username == value).one()
122 122 except Exception:
123 123 raise formencode.Invalid(_('This username is not valid'),
124 124 value, state)
125 125 finally:
126 126 meta.Session.remove()
127 127
128 128 return self.user_db.user_id
129 129
130 130 def ValidRepoName(edit, old_data):
131 131 class _ValidRepoName(formencode.validators.FancyValidator):
132 132
133 133 def to_python(self, value, state):
134 134 slug = h.repo_name_slug(value)
135 135 if slug in ['_admin']:
136 136 raise formencode.Invalid(_('This repository name is disallowed'),
137 137 value, state)
138 138 if old_data.get('repo_name') != value or not edit:
139 139 if RepoModel().get(slug, cache=False):
140 140 raise formencode.Invalid(_('This repository already exists') ,
141 141 value, state)
142 142 return slug
143 143
144 144
145 145 return _ValidRepoName
146 146
147 147 def ValidForkType(old_data):
148 148 class _ValidForkType(formencode.validators.FancyValidator):
149 149
150 150 def to_python(self, value, state):
151 151 if old_data['repo_type'] != value:
152 152 raise formencode.Invalid(_('Fork have to be the same type as original'), value, state)
153 153 return value
154 154 return _ValidForkType
155 155
156 156 class ValidPerms(formencode.validators.FancyValidator):
157 157 messages = {'perm_new_user_name':_('This username is not valid')}
158 158
159 159 def to_python(self, value, state):
160 160 perms_update = []
161 161 perms_new = []
162 162 #build a list of permission to update and new permission to create
163 163 for k, v in value.items():
164 164 if k.startswith('perm_'):
165 165 if k.startswith('perm_new_user'):
166 166 new_perm = value.get('perm_new_user', False)
167 167 new_user = value.get('perm_new_user_name', False)
168 168 if new_user and new_perm:
169 169 if (new_user, new_perm) not in perms_new:
170 170 perms_new.append((new_user, new_perm))
171 171 else:
172 172 usr = k[5:]
173 173 if usr == 'default':
174 174 if value['private']:
175 175 #set none for default when updating to private repo
176 176 v = 'repository.none'
177 177 perms_update.append((usr, v))
178 178 value['perms_updates'] = perms_update
179 179 value['perms_new'] = perms_new
180 180 sa = meta.Session
181 181 for k, v in perms_new:
182 182 try:
183 183 self.user_db = sa.query(User)\
184 184 .filter(User.active == True)\
185 185 .filter(User.username == k).one()
186 186 except Exception:
187 187 msg = self.message('perm_new_user_name',
188 188 state=State_obj)
189 189 raise formencode.Invalid(msg, value, state, error_dict={'perm_new_user_name':msg})
190 190 return value
191 191
192 192 class ValidSettings(formencode.validators.FancyValidator):
193 193
194 194 def to_python(self, value, state):
195 195 #settings form can't edit user
196 196 if value.has_key('user'):
197 197 del['value']['user']
198 198
199 199 return value
200 200
201 201 class ValidPath(formencode.validators.FancyValidator):
202 202 def to_python(self, value, state):
203 203
204 204 if not os.path.isdir(value):
205 205 msg = _('This is not a valid path')
206 206 raise formencode.Invalid(msg, value, state,
207 207 error_dict={'paths_root_path':msg})
208 208 return value
209 209
210 210 def UniqSystemEmail(old_data):
211 211 class _UniqSystemEmail(formencode.validators.FancyValidator):
212 212 def to_python(self, value, state):
213 213 if old_data.get('email') != value:
214 214 sa = meta.Session()
215 215 try:
216 216 user = sa.query(User).filter(User.email == value).scalar()
217 217 if user:
218 218 raise formencode.Invalid(_("That e-mail address is already taken") ,
219 219 value, state)
220 220 finally:
221 221 meta.Session.remove()
222 222
223 223 return value
224 224
225 225 return _UniqSystemEmail
226 226
227 227 class ValidSystemEmail(formencode.validators.FancyValidator):
228 228 def to_python(self, value, state):
229 229 sa = meta.Session
230 230 try:
231 231 user = sa.query(User).filter(User.email == value).scalar()
232 232 if user is None:
233 233 raise formencode.Invalid(_("That e-mail address doesn't exist.") ,
234 234 value, state)
235 235 finally:
236 236 meta.Session.remove()
237 237
238 238 return value
239 239
240 240 class LdapLibValidator(formencode.validators.FancyValidator):
241 241
242 242 def to_python(self, value, state):
243 243
244 244 try:
245 245 import ldap
246 246 except ImportError:
247 247 raise LdapImportError
248 248 return value
249 249
250 250 #===============================================================================
251 251 # FORMS
252 252 #===============================================================================
253 253 class LoginForm(formencode.Schema):
254 254 allow_extra_fields = True
255 255 filter_extra_fields = True
256 256 username = UnicodeString(
257 257 strip=True,
258 258 min=1,
259 259 not_empty=True,
260 260 messages={
261 261 'empty':_('Please enter a login'),
262 262 'tooShort':_('Enter a value %(min)i characters long or more')}
263 263 )
264 264
265 265 password = UnicodeString(
266 266 strip=True,
267 267 min=6,
268 268 not_empty=True,
269 269 messages={
270 270 'empty':_('Please enter a password'),
271 271 'tooShort':_('Enter %(min)i characters or more')}
272 272 )
273 273
274 274
275 275 #chained validators have access to all data
276 276 chained_validators = [ValidAuth]
277 277
278 278 def UserForm(edit=False, old_data={}):
279 279 class _UserForm(formencode.Schema):
280 280 allow_extra_fields = True
281 281 filter_extra_fields = True
282 282 username = All(UnicodeString(strip=True, min=1, not_empty=True), ValidUsername(edit, old_data))
283 283 if edit:
284 284 new_password = All(UnicodeString(strip=True, min=6, not_empty=False), ValidPassword)
285 285 admin = StringBoolean(if_missing=False)
286 286 else:
287 287 password = All(UnicodeString(strip=True, min=6, not_empty=True), ValidPassword)
288 288 active = StringBoolean(if_missing=False)
289 289 name = UnicodeString(strip=True, min=1, not_empty=True)
290 290 lastname = UnicodeString(strip=True, min=1, not_empty=True)
291 291 email = All(Email(not_empty=True), UniqSystemEmail(old_data))
292 292
293 293 return _UserForm
294 294
295 295 RegisterForm = UserForm
296 296
297 297 def PasswordResetForm():
298 298 class _PasswordResetForm(formencode.Schema):
299 299 allow_extra_fields = True
300 300 filter_extra_fields = True
301 301 email = All(ValidSystemEmail(), Email(not_empty=True))
302 302 return _PasswordResetForm
303 303
304 def RepoForm(edit=False, old_data={}):
304 def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
305 305 class _RepoForm(formencode.Schema):
306 306 allow_extra_fields = True
307 307 filter_extra_fields = False
308 308 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
309 309 description = UnicodeString(strip=True, min=1, not_empty=True)
310 310 private = StringBoolean(if_missing=False)
311 repo_type = OneOf(BACKENDS.keys())
311 repo_type = OneOf(supported_backends)
312 312 if edit:
313 313 user = All(Int(not_empty=True), ValidRepoUser)
314 314
315 315 chained_validators = [ValidPerms]
316 316 return _RepoForm
317 317
318 def RepoForkForm(edit=False, old_data={}):
318 def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
319 319 class _RepoForkForm(formencode.Schema):
320 320 allow_extra_fields = True
321 321 filter_extra_fields = False
322 322 fork_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
323 323 description = UnicodeString(strip=True, min=1, not_empty=True)
324 324 private = StringBoolean(if_missing=False)
325 repo_type = All(ValidForkType(old_data), OneOf(BACKENDS.keys()))
325 repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
326 326 return _RepoForkForm
327 327
328 328 def RepoSettingsForm(edit=False, old_data={}):
329 329 class _RepoForm(formencode.Schema):
330 330 allow_extra_fields = True
331 331 filter_extra_fields = False
332 332 repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
333 333 description = UnicodeString(strip=True, min=1, not_empty=True)
334 334 private = StringBoolean(if_missing=False)
335 335
336 336 chained_validators = [ValidPerms, ValidSettings]
337 337 return _RepoForm
338 338
339 339
340 340 def ApplicationSettingsForm():
341 341 class _ApplicationSettingsForm(formencode.Schema):
342 342 allow_extra_fields = True
343 343 filter_extra_fields = False
344 344 rhodecode_title = UnicodeString(strip=True, min=1, not_empty=True)
345 345 rhodecode_realm = UnicodeString(strip=True, min=1, not_empty=True)
346 346
347 347 return _ApplicationSettingsForm
348 348
349 349 def ApplicationUiSettingsForm():
350 350 class _ApplicationUiSettingsForm(formencode.Schema):
351 351 allow_extra_fields = True
352 352 filter_extra_fields = False
353 353 web_push_ssl = OneOf(['true', 'false'], if_missing='false')
354 354 paths_root_path = All(ValidPath(), UnicodeString(strip=True, min=1, not_empty=True))
355 355 hooks_changegroup_update = OneOf(['True', 'False'], if_missing=False)
356 356 hooks_changegroup_repo_size = OneOf(['True', 'False'], if_missing=False)
357 357 hooks_pretxnchangegroup_push_logger = OneOf(['True', 'False'], if_missing=False)
358 358 hooks_preoutgoing_pull_logger = OneOf(['True', 'False'], if_missing=False)
359 359
360 360 return _ApplicationUiSettingsForm
361 361
362 362 def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
363 363 class _DefaultPermissionsForm(formencode.Schema):
364 364 allow_extra_fields = True
365 365 filter_extra_fields = True
366 366 overwrite_default = StringBoolean(if_missing=False)
367 367 anonymous = OneOf(['True', 'False'], if_missing=False)
368 368 default_perm = OneOf(perms_choices)
369 369 default_register = OneOf(register_choices)
370 370 default_create = OneOf(create_choices)
371 371
372 372 return _DefaultPermissionsForm
373 373
374 374
375 375 def LdapSettingsForm():
376 376 class _LdapSettingsForm(formencode.Schema):
377 377 allow_extra_fields = True
378 378 filter_extra_fields = True
379 379 pre_validators = [LdapLibValidator]
380 380 ldap_active = StringBoolean(if_missing=False)
381 381 ldap_host = UnicodeString(strip=True,)
382 382 ldap_port = Number(strip=True,)
383 383 ldap_ldaps = StringBoolean(if_missing=False)
384 384 ldap_dn_user = UnicodeString(strip=True,)
385 385 ldap_dn_pass = UnicodeString(strip=True,)
386 386 ldap_base_dn = UnicodeString(strip=True,)
387 387
388 388 return _LdapSettingsForm
@@ -1,240 +1,242 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # Model for RhodeCode
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; version 2
9 9 # of the License or (at your opinion) any later version of the license.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 19 # MA 02110-1301, USA.
20 20 """
21 21 Created on April 9, 2010
22 22 Model for RhodeCode
23 23 @author: marcink
24 24 """
25 25 from beaker.cache import cache_region, region_invalidate
26 26 from mercurial import ui
27 from rhodecode import BACKENDS
27 28 from rhodecode.lib import helpers as h
28 29 from rhodecode.lib.auth import HasRepoPermissionAny
29 30 from rhodecode.lib.utils import get_repos
30 31 from rhodecode.model import meta
31 32 from rhodecode.model.db import Repository, User, RhodeCodeUi, CacheInvalidation
32 33 from rhodecode.model.caching_query import FromCache
33 34 from sqlalchemy.orm import joinedload
34 35 from sqlalchemy.orm.session import make_transient
35 36 from vcs import get_backend
36 37 from vcs.utils.helpers import get_scm
37 38 from vcs.exceptions import RepositoryError, VCSError
38 39 from vcs.utils.lazy import LazyProperty
39 40 import traceback
40 41 import logging
41 42 import os
42 43 import time
43 44
44 45 log = logging.getLogger(__name__)
45 46
46 47 class ScmModel(object):
47 48 """
48 49 Mercurial Model
49 50 """
50 51
51 52 def __init__(self):
52 53 self.sa = meta.Session()
53 54
54 55 @LazyProperty
55 56 def repos_path(self):
56 57 """
57 58 Get's the repositories root path from database
58 59 """
59 60 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
60 61
61 62 return q.ui_value
62 63
63 64 def repo_scan(self, repos_path, baseui, initial=False):
64 65 """
65 66 Listing of repositories in given path. This path should not be a
66 67 repository itself. Return a dictionary of repository objects
67 68
68 69 :param repos_path: path to directory containing repositories
69 70 :param baseui
70 71 :param initial: initial scan
71 72 """
72 73 log.info('scanning for repositories in %s', repos_path)
73 74
74 75 if not isinstance(baseui, ui.ui):
75 76 baseui = ui.ui()
76 77 repos_list = {}
77 78
78 79 for name, path in get_repos(repos_path):
79 80 try:
80 81 if repos_list.has_key(name):
81 82 raise RepositoryError('Duplicate repository name %s '
82 83 'found in %s' % (name, path))
83 84 else:
84 85
85 86 klass = get_backend(path[0])
86 87
87 if path[0] == 'hg':
88 if path[0] == 'hg' and path[0] in BACKENDS.keys():
88 89 repos_list[name] = klass(path[1], baseui=baseui)
89 90
90 if path[0] == 'git':
91 if path[0] == 'git' and path[0] in BACKENDS.keys():
91 92 repos_list[name] = klass(path[1])
92 93 except OSError:
93 94 continue
94 95
95 96 return repos_list
96 97
97 98 def get_repos(self, all_repos=None):
98 99 """
99 100 Get all repos from db and for each repo create it's backend instance.
100 101 and fill that backed with information from database
101 102
102 103 :param all_repos: give specific repositories list, good for filtering
103 104 """
104 105 if not all_repos:
105 106 all_repos = self.sa.query(Repository)\
106 107 .order_by(Repository.repo_name).all()
107 108
108 109 for r in all_repos:
109 110
110 111 repo = self.get(r.repo_name)
111 112
112 113 if repo is not None:
113 114 last_change = repo.last_change
114 115 tip = h.get_changeset_safe(repo, 'tip')
115 116
116 117 tmp_d = {}
117 118 tmp_d['name'] = repo.name
118 119 tmp_d['name_sort'] = tmp_d['name'].lower()
119 120 tmp_d['description'] = repo.dbrepo.description
120 121 tmp_d['description_sort'] = tmp_d['description']
121 122 tmp_d['last_change'] = last_change
122 123 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
123 124 tmp_d['tip'] = tip.raw_id
124 125 tmp_d['tip_sort'] = tip.revision
125 126 tmp_d['rev'] = tip.revision
126 127 tmp_d['contact'] = repo.dbrepo.user.full_contact
127 128 tmp_d['contact_sort'] = tmp_d['contact']
128 129 tmp_d['repo_archives'] = list(repo._get_archives())
129 130 tmp_d['last_msg'] = tip.message
130 131 tmp_d['repo'] = repo
131 132 yield tmp_d
132 133
133 134 def get_repo(self, repo_name):
134 135 return self.get(repo_name)
135 136
136 137 def get(self, repo_name):
137 138 """
138 139 Get's repository from given name, creates BackendInstance and
139 140 propagates it's data from database with all additional information
140 141 :param repo_name:
141 142 """
142 143 if not HasRepoPermissionAny('repository.read', 'repository.write',
143 144 'repository.admin')(repo_name, 'get repo check'):
144 145 return
145 146
146 147 @cache_region('long_term')
147 148 def _get_repo(repo_name):
148 149
149 150 repo_path = os.path.join(self.repos_path, repo_name)
150 151 alias = get_scm(repo_path)[0]
151 152
152 153 log.debug('Creating instance of %s repository', alias)
153 154 backend = get_backend(alias)
154 155
156 #TODO: get the baseui from somewhere for this
155 157 if alias == 'hg':
156 158 repo = backend(repo_path, create=False, baseui=None)
157 159 #skip hidden web repository
158 160 if repo._get_hidden():
159 161 return
160 162 else:
161 163 repo = backend(repo_path, create=False)
162 164
163 165 dbrepo = self.sa.query(Repository)\
164 166 .options(joinedload(Repository.fork))\
165 167 .options(joinedload(Repository.user))\
166 168 .filter(Repository.repo_name == repo_name)\
167 169 .scalar()
168 170 make_transient(dbrepo)
169 171 repo.dbrepo = dbrepo
170 172 return repo
171 173
172 174 invalidate = self._should_invalidate(repo_name)
173 175 if invalidate:
174 176 log.info('invalidating cache for repository %s', repo_name)
175 177 region_invalidate(_get_repo, None, repo_name)
176 178 self._mark_invalidated(invalidate)
177 179
178 180 return _get_repo(repo_name)
179 181
180 182
181 183
182 184 def mark_for_invalidation(self, repo_name):
183 185 """
184 186 Puts cache invalidation task into db for
185 187 further global cache invalidation
186 188
187 189 :param repo_name: this repo that should invalidation take place
188 190 """
189 191 log.debug('marking %s for invalidation', repo_name)
190 192 cache = self.sa.query(CacheInvalidation)\
191 193 .filter(CacheInvalidation.cache_key == repo_name).scalar()
192 194
193 195 if cache:
194 196 #mark this cache as inactive
195 197 cache.cache_active = False
196 198 else:
197 199 log.debug('cache key not found in invalidation db -> creating one')
198 200 cache = CacheInvalidation(repo_name)
199 201
200 202 try:
201 203 self.sa.add(cache)
202 204 self.sa.commit()
203 205 except:
204 206 log.error(traceback.format_exc())
205 207 self.sa.rollback()
206 208
207 209
208 210
209 211
210 212
211 213 def _should_invalidate(self, repo_name):
212 214 """
213 215 Looks up database for invalidation signals for this repo_name
214 216 :param repo_name:
215 217 """
216 218
217 219 ret = self.sa.query(CacheInvalidation)\
218 220 .options(FromCache('sql_cache_short',
219 221 'get_invalidation_%s' % repo_name))\
220 222 .filter(CacheInvalidation.cache_key == repo_name)\
221 223 .filter(CacheInvalidation.cache_active == False)\
222 224 .scalar()
223 225
224 226 return ret
225 227
226 228 def _mark_invalidated(self, cache_key):
227 229 """
228 230 Marks all occurences of cache to invaldation as already invalidated
229 231 @param repo_name:
230 232 """
231 233 if cache_key:
232 234 log.debug('marking %s as already invalidated', cache_key)
233 235 try:
234 236 cache_key.cache_active = True
235 237 self.sa.add(cache_key)
236 238 self.sa.commit()
237 239 except:
238 240 log.error(traceback.format_exc())
239 241 self.sa.rollback()
240 242
General Comments 0
You need to be logged in to leave comments. Login now