##// END OF EJS Templates
added some info to corrupted repo message that helps diagnose the cause from log itself.
marcink -
r1265:08ac2c3a beta
parent child Browse files
Show More
@@ -1,412 +1,414 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.scm
3 rhodecode.model.scm
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Scm model for RhodeCode
6 Scm model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import os
25 import os
26 import time
26 import time
27 import traceback
27 import traceback
28 import logging
28 import logging
29
29
30 from mercurial import ui
30 from mercurial import ui
31
31
32 from sqlalchemy.exc import DatabaseError
32 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.orm import make_transient
33 from sqlalchemy.orm import make_transient
34
34
35 from beaker.cache import cache_region, region_invalidate
35 from beaker.cache import cache_region, region_invalidate
36
36
37 from vcs import get_backend
37 from vcs import get_backend
38 from vcs.utils.helpers import get_scm
38 from vcs.utils.helpers import get_scm
39 from vcs.exceptions import RepositoryError, VCSError
39 from vcs.exceptions import RepositoryError, VCSError
40 from vcs.utils.lazy import LazyProperty
40 from vcs.utils.lazy import LazyProperty
41
41
42 from rhodecode import BACKENDS
42 from rhodecode import BACKENDS
43 from rhodecode.lib import helpers as h
43 from rhodecode.lib import helpers as h
44 from rhodecode.lib.auth import HasRepoPermissionAny
44 from rhodecode.lib.auth import HasRepoPermissionAny
45 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
45 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
46 action_logger
46 action_logger
47 from rhodecode.model import BaseModel
47 from rhodecode.model import BaseModel
48 from rhodecode.model.user import UserModel
48 from rhodecode.model.user import UserModel
49 from rhodecode.model.repo import RepoModel
49 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
50 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
51 UserFollowing, UserLog
51 UserFollowing, UserLog
52 from rhodecode.model.caching_query import FromCache
52 from rhodecode.model.caching_query import FromCache
53
53
54 log = logging.getLogger(__name__)
54 log = logging.getLogger(__name__)
55
55
56
56
57 class UserTemp(object):
57 class UserTemp(object):
58 def __init__(self, user_id):
58 def __init__(self, user_id):
59 self.user_id = user_id
59 self.user_id = user_id
60
60
61 def __repr__(self):
61 def __repr__(self):
62 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
62 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
63
63
64
64
65 class RepoTemp(object):
65 class RepoTemp(object):
66 def __init__(self, repo_id):
66 def __init__(self, repo_id):
67 self.repo_id = repo_id
67 self.repo_id = repo_id
68
68
69 def __repr__(self):
69 def __repr__(self):
70 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
70 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
71
71
72
72
73 class ScmModel(BaseModel):
73 class ScmModel(BaseModel):
74 """Generic Scm Model
74 """Generic Scm Model
75 """
75 """
76
76
77 @LazyProperty
77 @LazyProperty
78 def repos_path(self):
78 def repos_path(self):
79 """Get's the repositories root path from database
79 """Get's the repositories root path from database
80 """
80 """
81
81
82 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
82 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
83
83
84 return q.ui_value
84 return q.ui_value
85
85
86 def repo_scan(self, repos_path=None):
86 def repo_scan(self, repos_path=None):
87 """Listing of repositories in given path. This path should not be a
87 """Listing of repositories in given path. This path should not be a
88 repository itself. Return a dictionary of repository objects
88 repository itself. Return a dictionary of repository objects
89
89
90 :param repos_path: path to directory containing repositories
90 :param repos_path: path to directory containing repositories
91 """
91 """
92
92
93 log.info('scanning for repositories in %s', repos_path)
93 log.info('scanning for repositories in %s', repos_path)
94
94
95 if repos_path is None:
95 if repos_path is None:
96 repos_path = self.repos_path
96 repos_path = self.repos_path
97
97
98 baseui = make_ui('db')
98 baseui = make_ui('db')
99 repos_list = {}
99 repos_list = {}
100
100
101 for name, path in get_filesystem_repos(repos_path, recursive=True):
101 for name, path in get_filesystem_repos(repos_path, recursive=True):
102 try:
102 try:
103 if name in repos_list:
103 if name in repos_list:
104 raise RepositoryError('Duplicate repository name %s '
104 raise RepositoryError('Duplicate repository name %s '
105 'found in %s' % (name, path))
105 'found in %s' % (name, path))
106 else:
106 else:
107
107
108 klass = get_backend(path[0])
108 klass = get_backend(path[0])
109
109
110 if path[0] == 'hg' and path[0] in BACKENDS.keys():
110 if path[0] == 'hg' and path[0] in BACKENDS.keys():
111 repos_list[name] = klass(path[1], baseui=baseui)
111 repos_list[name] = klass(path[1], baseui=baseui)
112
112
113 if path[0] == 'git' and path[0] in BACKENDS.keys():
113 if path[0] == 'git' and path[0] in BACKENDS.keys():
114 repos_list[name] = klass(path[1])
114 repos_list[name] = klass(path[1])
115 except OSError:
115 except OSError:
116 continue
116 continue
117
117
118 return repos_list
118 return repos_list
119
119
120 def get_repos(self, all_repos=None):
120 def get_repos(self, all_repos=None):
121 """Get all repos from db and for each repo create it's
121 """Get all repos from db and for each repo create it's
122 backend instance and fill that backed with information from database
122 backend instance and fill that backed with information from database
123
123
124 :param all_repos: give specific repositories list, good for filtering
124 :param all_repos: give specific repositories list, good for filtering
125 this have to be a list of just the repository names
125 this have to be a list of just the repository names
126 """
126 """
127 if all_repos is None:
127 if all_repos is None:
128 repos = self.sa.query(Repository)\
128 repos = self.sa.query(Repository)\
129 .order_by(Repository.repo_name).all()
129 .order_by(Repository.repo_name).all()
130 all_repos = [r.repo_name for r in repos]
130 all_repos = [r.repo_name for r in repos]
131
131
132 #get the repositories that should be invalidated
132 #get the repositories that should be invalidated
133 invalidation_list = [str(x.cache_key) for x in \
133 invalidation_list = [str(x.cache_key) for x in \
134 self.sa.query(CacheInvalidation.cache_key)\
134 self.sa.query(CacheInvalidation.cache_key)\
135 .filter(CacheInvalidation.cache_active == False)\
135 .filter(CacheInvalidation.cache_active == False)\
136 .all()]
136 .all()]
137 for r_name in all_repos:
137 for r_name in all_repos:
138 r_dbr = self.get(r_name, invalidation_list)
138 r_dbr = self.get(r_name, invalidation_list)
139 if r_dbr is not None:
139 if r_dbr is not None:
140 repo, dbrepo = r_dbr
140 repo, dbrepo = r_dbr
141
141
142 if repo is None or dbrepo is None:
142 if repo is None or dbrepo is None:
143 log.error('Repository %s looks somehow corrupted', r_name)
143 log.error('Repository "%s" looks somehow corrupted '
144 'fs-repo:%s,db-repo:%s both values should be '
145 'present', r_name, repo, dbrepo)
144 continue
146 continue
145 last_change = repo.last_change
147 last_change = repo.last_change
146 tip = h.get_changeset_safe(repo, 'tip')
148 tip = h.get_changeset_safe(repo, 'tip')
147
149
148 tmp_d = {}
150 tmp_d = {}
149 tmp_d['name'] = dbrepo.repo_name
151 tmp_d['name'] = dbrepo.repo_name
150 tmp_d['name_sort'] = tmp_d['name'].lower()
152 tmp_d['name_sort'] = tmp_d['name'].lower()
151 tmp_d['description'] = dbrepo.description
153 tmp_d['description'] = dbrepo.description
152 tmp_d['description_sort'] = tmp_d['description']
154 tmp_d['description_sort'] = tmp_d['description']
153 tmp_d['last_change'] = last_change
155 tmp_d['last_change'] = last_change
154 tmp_d['last_change_sort'] = time.mktime(last_change \
156 tmp_d['last_change_sort'] = time.mktime(last_change \
155 .timetuple())
157 .timetuple())
156 tmp_d['tip'] = tip.raw_id
158 tmp_d['tip'] = tip.raw_id
157 tmp_d['tip_sort'] = tip.revision
159 tmp_d['tip_sort'] = tip.revision
158 tmp_d['rev'] = tip.revision
160 tmp_d['rev'] = tip.revision
159 tmp_d['contact'] = dbrepo.user.full_contact
161 tmp_d['contact'] = dbrepo.user.full_contact
160 tmp_d['contact_sort'] = tmp_d['contact']
162 tmp_d['contact_sort'] = tmp_d['contact']
161 tmp_d['owner_sort'] = tmp_d['contact']
163 tmp_d['owner_sort'] = tmp_d['contact']
162 tmp_d['repo_archives'] = list(repo._get_archives())
164 tmp_d['repo_archives'] = list(repo._get_archives())
163 tmp_d['last_msg'] = tip.message
165 tmp_d['last_msg'] = tip.message
164 tmp_d['repo'] = repo
166 tmp_d['repo'] = repo
165 tmp_d['dbrepo'] = dbrepo.get_dict()
167 tmp_d['dbrepo'] = dbrepo.get_dict()
166 tmp_d['dbrepo_fork'] = dbrepo.fork.get_dict() if dbrepo.fork \
168 tmp_d['dbrepo_fork'] = dbrepo.fork.get_dict() if dbrepo.fork \
167 else {}
169 else {}
168 yield tmp_d
170 yield tmp_d
169
171
170 def get(self, repo_name, invalidation_list=None, retval='all'):
172 def get(self, repo_name, invalidation_list=None, retval='all'):
171 """Returns a tuple of Repository,DbRepository,
173 """Returns a tuple of Repository,DbRepository,
172 Get's repository from given name, creates BackendInstance and
174 Get's repository from given name, creates BackendInstance and
173 propagates it's data from database with all additional information
175 propagates it's data from database with all additional information
174
176
175 :param repo_name:
177 :param repo_name:
176 :param invalidation_list: if a invalidation list is given the get
178 :param invalidation_list: if a invalidation list is given the get
177 method should not manually check if this repository needs
179 method should not manually check if this repository needs
178 invalidation and just invalidate the repositories in list
180 invalidation and just invalidate the repositories in list
179 :param retval: string specifing what to return one of 'repo','dbrepo',
181 :param retval: string specifing what to return one of 'repo','dbrepo',
180 'all'if repo or dbrepo is given it'll just lazy load chosen type
182 'all'if repo or dbrepo is given it'll just lazy load chosen type
181 and return None as the second
183 and return None as the second
182 """
184 """
183 if not HasRepoPermissionAny('repository.read', 'repository.write',
185 if not HasRepoPermissionAny('repository.read', 'repository.write',
184 'repository.admin')(repo_name, 'get repo check'):
186 'repository.admin')(repo_name, 'get repo check'):
185 return
187 return
186
188
187 #======================================================================
189 #======================================================================
188 # CACHE FUNCTION
190 # CACHE FUNCTION
189 #======================================================================
191 #======================================================================
190 @cache_region('long_term')
192 @cache_region('long_term')
191 def _get_repo(repo_name):
193 def _get_repo(repo_name):
192
194
193 repo_path = os.path.join(self.repos_path, repo_name)
195 repo_path = os.path.join(self.repos_path, repo_name)
194
196
195 try:
197 try:
196 alias = get_scm(repo_path)[0]
198 alias = get_scm(repo_path)[0]
197 log.debug('Creating instance of %s repository', alias)
199 log.debug('Creating instance of %s repository', alias)
198 backend = get_backend(alias)
200 backend = get_backend(alias)
199 except VCSError:
201 except VCSError:
200 log.error(traceback.format_exc())
202 log.error(traceback.format_exc())
201 log.error('Perhaps this repository is in db and not in '
203 log.error('Perhaps this repository is in db and not in '
202 'filesystem run rescan repositories with '
204 'filesystem run rescan repositories with '
203 '"destroy old data " option from admin panel')
205 '"destroy old data " option from admin panel')
204 return
206 return
205
207
206 if alias == 'hg':
208 if alias == 'hg':
207 repo = backend(repo_path, create=False, baseui=make_ui('db'))
209 repo = backend(repo_path, create=False, baseui=make_ui('db'))
208 #skip hidden web repository
210 #skip hidden web repository
209 if repo._get_hidden():
211 if repo._get_hidden():
210 return
212 return
211 else:
213 else:
212 repo = backend(repo_path, create=False)
214 repo = backend(repo_path, create=False)
213
215
214 return repo
216 return repo
215
217
216 pre_invalidate = True
218 pre_invalidate = True
217 dbinvalidate = False
219 dbinvalidate = False
218
220
219 if invalidation_list is not None:
221 if invalidation_list is not None:
220 pre_invalidate = repo_name in invalidation_list
222 pre_invalidate = repo_name in invalidation_list
221
223
222 if pre_invalidate:
224 if pre_invalidate:
223 #this returns object to invalidate
225 #this returns object to invalidate
224 invalidate = self._should_invalidate(repo_name)
226 invalidate = self._should_invalidate(repo_name)
225 if invalidate:
227 if invalidate:
226 log.info('invalidating cache for repository %s', repo_name)
228 log.info('invalidating cache for repository %s', repo_name)
227 region_invalidate(_get_repo, None, repo_name)
229 region_invalidate(_get_repo, None, repo_name)
228 self._mark_invalidated(invalidate)
230 self._mark_invalidated(invalidate)
229 dbinvalidate = True
231 dbinvalidate = True
230
232
231 r, dbr = None, None
233 r, dbr = None, None
232 if retval == 'repo' or 'all':
234 if retval == 'repo' or 'all':
233 r = _get_repo(repo_name)
235 r = _get_repo(repo_name)
234 if retval == 'dbrepo' or 'all':
236 if retval == 'dbrepo' or 'all':
235 dbr = RepoModel().get_full(repo_name, cache=True,
237 dbr = RepoModel().get_full(repo_name, cache=True,
236 invalidate=dbinvalidate)
238 invalidate=dbinvalidate)
237
239
238 return r, dbr
240 return r, dbr
239
241
240 def mark_for_invalidation(self, repo_name):
242 def mark_for_invalidation(self, repo_name):
241 """Puts cache invalidation task into db for
243 """Puts cache invalidation task into db for
242 further global cache invalidation
244 further global cache invalidation
243
245
244 :param repo_name: this repo that should invalidation take place
246 :param repo_name: this repo that should invalidation take place
245 """
247 """
246
248
247 log.debug('marking %s for invalidation', repo_name)
249 log.debug('marking %s for invalidation', repo_name)
248 cache = self.sa.query(CacheInvalidation)\
250 cache = self.sa.query(CacheInvalidation)\
249 .filter(CacheInvalidation.cache_key == repo_name).scalar()
251 .filter(CacheInvalidation.cache_key == repo_name).scalar()
250
252
251 if cache:
253 if cache:
252 #mark this cache as inactive
254 #mark this cache as inactive
253 cache.cache_active = False
255 cache.cache_active = False
254 else:
256 else:
255 log.debug('cache key not found in invalidation db -> creating one')
257 log.debug('cache key not found in invalidation db -> creating one')
256 cache = CacheInvalidation(repo_name)
258 cache = CacheInvalidation(repo_name)
257
259
258 try:
260 try:
259 self.sa.add(cache)
261 self.sa.add(cache)
260 self.sa.commit()
262 self.sa.commit()
261 except (DatabaseError,):
263 except (DatabaseError,):
262 log.error(traceback.format_exc())
264 log.error(traceback.format_exc())
263 self.sa.rollback()
265 self.sa.rollback()
264
266
265 def toggle_following_repo(self, follow_repo_id, user_id):
267 def toggle_following_repo(self, follow_repo_id, user_id):
266
268
267 f = self.sa.query(UserFollowing)\
269 f = self.sa.query(UserFollowing)\
268 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
270 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
269 .filter(UserFollowing.user_id == user_id).scalar()
271 .filter(UserFollowing.user_id == user_id).scalar()
270
272
271 if f is not None:
273 if f is not None:
272
274
273 try:
275 try:
274 self.sa.delete(f)
276 self.sa.delete(f)
275 self.sa.commit()
277 self.sa.commit()
276 action_logger(UserTemp(user_id),
278 action_logger(UserTemp(user_id),
277 'stopped_following_repo',
279 'stopped_following_repo',
278 RepoTemp(follow_repo_id))
280 RepoTemp(follow_repo_id))
279 return
281 return
280 except:
282 except:
281 log.error(traceback.format_exc())
283 log.error(traceback.format_exc())
282 self.sa.rollback()
284 self.sa.rollback()
283 raise
285 raise
284
286
285 try:
287 try:
286 f = UserFollowing()
288 f = UserFollowing()
287 f.user_id = user_id
289 f.user_id = user_id
288 f.follows_repo_id = follow_repo_id
290 f.follows_repo_id = follow_repo_id
289 self.sa.add(f)
291 self.sa.add(f)
290 self.sa.commit()
292 self.sa.commit()
291 action_logger(UserTemp(user_id),
293 action_logger(UserTemp(user_id),
292 'started_following_repo',
294 'started_following_repo',
293 RepoTemp(follow_repo_id))
295 RepoTemp(follow_repo_id))
294 except:
296 except:
295 log.error(traceback.format_exc())
297 log.error(traceback.format_exc())
296 self.sa.rollback()
298 self.sa.rollback()
297 raise
299 raise
298
300
299 def toggle_following_user(self, follow_user_id, user_id):
301 def toggle_following_user(self, follow_user_id, user_id):
300 f = self.sa.query(UserFollowing)\
302 f = self.sa.query(UserFollowing)\
301 .filter(UserFollowing.follows_user_id == follow_user_id)\
303 .filter(UserFollowing.follows_user_id == follow_user_id)\
302 .filter(UserFollowing.user_id == user_id).scalar()
304 .filter(UserFollowing.user_id == user_id).scalar()
303
305
304 if f is not None:
306 if f is not None:
305 try:
307 try:
306 self.sa.delete(f)
308 self.sa.delete(f)
307 self.sa.commit()
309 self.sa.commit()
308 return
310 return
309 except:
311 except:
310 log.error(traceback.format_exc())
312 log.error(traceback.format_exc())
311 self.sa.rollback()
313 self.sa.rollback()
312 raise
314 raise
313
315
314 try:
316 try:
315 f = UserFollowing()
317 f = UserFollowing()
316 f.user_id = user_id
318 f.user_id = user_id
317 f.follows_user_id = follow_user_id
319 f.follows_user_id = follow_user_id
318 self.sa.add(f)
320 self.sa.add(f)
319 self.sa.commit()
321 self.sa.commit()
320 except:
322 except:
321 log.error(traceback.format_exc())
323 log.error(traceback.format_exc())
322 self.sa.rollback()
324 self.sa.rollback()
323 raise
325 raise
324
326
325 def is_following_repo(self, repo_name, user_id, cache=False):
327 def is_following_repo(self, repo_name, user_id, cache=False):
326 r = self.sa.query(Repository)\
328 r = self.sa.query(Repository)\
327 .filter(Repository.repo_name == repo_name).scalar()
329 .filter(Repository.repo_name == repo_name).scalar()
328
330
329 f = self.sa.query(UserFollowing)\
331 f = self.sa.query(UserFollowing)\
330 .filter(UserFollowing.follows_repository == r)\
332 .filter(UserFollowing.follows_repository == r)\
331 .filter(UserFollowing.user_id == user_id).scalar()
333 .filter(UserFollowing.user_id == user_id).scalar()
332
334
333 return f is not None
335 return f is not None
334
336
335 def is_following_user(self, username, user_id, cache=False):
337 def is_following_user(self, username, user_id, cache=False):
336 u = UserModel(self.sa).get_by_username(username)
338 u = UserModel(self.sa).get_by_username(username)
337
339
338 f = self.sa.query(UserFollowing)\
340 f = self.sa.query(UserFollowing)\
339 .filter(UserFollowing.follows_user == u)\
341 .filter(UserFollowing.follows_user == u)\
340 .filter(UserFollowing.user_id == user_id).scalar()
342 .filter(UserFollowing.user_id == user_id).scalar()
341
343
342 return f is not None
344 return f is not None
343
345
344 def get_followers(self, repo_id):
346 def get_followers(self, repo_id):
345 if isinstance(repo_id, int):
347 if isinstance(repo_id, int):
346 return self.sa.query(UserFollowing)\
348 return self.sa.query(UserFollowing)\
347 .filter(UserFollowing.follows_repo_id == repo_id).count()
349 .filter(UserFollowing.follows_repo_id == repo_id).count()
348 else:
350 else:
349 return self.sa.query(UserFollowing)\
351 return self.sa.query(UserFollowing)\
350 .filter(UserFollowing.follows_repository \
352 .filter(UserFollowing.follows_repository \
351 == RepoModel().get_by_repo_name(repo_id)).count()
353 == RepoModel().get_by_repo_name(repo_id)).count()
352
354
353 def get_forks(self, repo_id):
355 def get_forks(self, repo_id):
354 if isinstance(repo_id, int):
356 if isinstance(repo_id, int):
355 return self.sa.query(Repository)\
357 return self.sa.query(Repository)\
356 .filter(Repository.fork_id == repo_id).count()
358 .filter(Repository.fork_id == repo_id).count()
357 else:
359 else:
358 return self.sa.query(Repository)\
360 return self.sa.query(Repository)\
359 .filter(Repository.fork \
361 .filter(Repository.fork \
360 == RepoModel().get_by_repo_name(repo_id)).count()
362 == RepoModel().get_by_repo_name(repo_id)).count()
361
363
362 def pull_changes(self, repo_name, username):
364 def pull_changes(self, repo_name, username):
363 repo, dbrepo = self.get(repo_name, retval='all')
365 repo, dbrepo = self.get(repo_name, retval='all')
364
366
365 try:
367 try:
366 extras = {'ip': '',
368 extras = {'ip': '',
367 'username': username,
369 'username': username,
368 'action': 'push_remote',
370 'action': 'push_remote',
369 'repository': repo_name}
371 'repository': repo_name}
370
372
371 #inject ui extra param to log this action via push logger
373 #inject ui extra param to log this action via push logger
372 for k, v in extras.items():
374 for k, v in extras.items():
373 repo._repo.ui.setconfig('rhodecode_extras', k, v)
375 repo._repo.ui.setconfig('rhodecode_extras', k, v)
374
376
375 repo.pull(dbrepo.clone_uri)
377 repo.pull(dbrepo.clone_uri)
376 self.mark_for_invalidation(repo_name)
378 self.mark_for_invalidation(repo_name)
377 except:
379 except:
378 log.error(traceback.format_exc())
380 log.error(traceback.format_exc())
379 raise
381 raise
380
382
381 def get_unread_journal(self):
383 def get_unread_journal(self):
382 return self.sa.query(UserLog).count()
384 return self.sa.query(UserLog).count()
383
385
384 def _should_invalidate(self, repo_name):
386 def _should_invalidate(self, repo_name):
385 """Looks up database for invalidation signals for this repo_name
387 """Looks up database for invalidation signals for this repo_name
386
388
387 :param repo_name:
389 :param repo_name:
388 """
390 """
389
391
390 ret = self.sa.query(CacheInvalidation)\
392 ret = self.sa.query(CacheInvalidation)\
391 .filter(CacheInvalidation.cache_key == repo_name)\
393 .filter(CacheInvalidation.cache_key == repo_name)\
392 .filter(CacheInvalidation.cache_active == False)\
394 .filter(CacheInvalidation.cache_active == False)\
393 .scalar()
395 .scalar()
394
396
395 return ret
397 return ret
396
398
397 def _mark_invalidated(self, cache_key):
399 def _mark_invalidated(self, cache_key):
398 """ Marks all occurrences of cache to invalidation as already
400 """ Marks all occurrences of cache to invalidation as already
399 invalidated
401 invalidated
400
402
401 :param cache_key:
403 :param cache_key:
402 """
404 """
403
405
404 if cache_key:
406 if cache_key:
405 log.debug('marking %s as already invalidated', cache_key)
407 log.debug('marking %s as already invalidated', cache_key)
406 try:
408 try:
407 cache_key.cache_active = True
409 cache_key.cache_active = True
408 self.sa.add(cache_key)
410 self.sa.add(cache_key)
409 self.sa.commit()
411 self.sa.commit()
410 except (DatabaseError,):
412 except (DatabaseError,):
411 log.error(traceback.format_exc())
413 log.error(traceback.format_exc())
412 self.sa.rollback()
414 self.sa.rollback()
General Comments 0
You need to be logged in to leave comments. Login now