##// END OF EJS Templates
change the way of detection of corrupted repos. sqlalchemy objects needs to be checkec `is None`.
marcink -
r1229:8748f797 beta
parent child Browse files
Show More
@@ -1,412 +1,412 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 not repo and dbrepo:
142 if repo is None and dbrepo is None:
143 log.error('Repository %s looks somehow corrupted', r_name)
143 log.error('Repository %s looks somehow corrupted', r_name)
144 continue
144 continue
145 last_change = repo.last_change
145 last_change = repo.last_change
146 tip = h.get_changeset_safe(repo, 'tip')
146 tip = h.get_changeset_safe(repo, 'tip')
147
147
148 tmp_d = {}
148 tmp_d = {}
149 tmp_d['name'] = dbrepo.repo_name
149 tmp_d['name'] = dbrepo.repo_name
150 tmp_d['name_sort'] = tmp_d['name'].lower()
150 tmp_d['name_sort'] = tmp_d['name'].lower()
151 tmp_d['description'] = dbrepo.description
151 tmp_d['description'] = dbrepo.description
152 tmp_d['description_sort'] = tmp_d['description']
152 tmp_d['description_sort'] = tmp_d['description']
153 tmp_d['last_change'] = last_change
153 tmp_d['last_change'] = last_change
154 tmp_d['last_change_sort'] = time.mktime(last_change \
154 tmp_d['last_change_sort'] = time.mktime(last_change \
155 .timetuple())
155 .timetuple())
156 tmp_d['tip'] = tip.raw_id
156 tmp_d['tip'] = tip.raw_id
157 tmp_d['tip_sort'] = tip.revision
157 tmp_d['tip_sort'] = tip.revision
158 tmp_d['rev'] = tip.revision
158 tmp_d['rev'] = tip.revision
159 tmp_d['contact'] = dbrepo.user.full_contact
159 tmp_d['contact'] = dbrepo.user.full_contact
160 tmp_d['contact_sort'] = tmp_d['contact']
160 tmp_d['contact_sort'] = tmp_d['contact']
161 tmp_d['owner_sort'] = tmp_d['contact']
161 tmp_d['owner_sort'] = tmp_d['contact']
162 tmp_d['repo_archives'] = list(repo._get_archives())
162 tmp_d['repo_archives'] = list(repo._get_archives())
163 tmp_d['last_msg'] = tip.message
163 tmp_d['last_msg'] = tip.message
164 tmp_d['repo'] = repo
164 tmp_d['repo'] = repo
165 tmp_d['dbrepo'] = dbrepo.get_dict()
165 tmp_d['dbrepo'] = dbrepo.get_dict()
166 tmp_d['dbrepo_fork'] = dbrepo.fork.get_dict() if dbrepo.fork \
166 tmp_d['dbrepo_fork'] = dbrepo.fork.get_dict() if dbrepo.fork \
167 else {}
167 else {}
168 yield tmp_d
168 yield tmp_d
169
169
170 def get(self, repo_name, invalidation_list=None, retval='all'):
170 def get(self, repo_name, invalidation_list=None, retval='all'):
171 """Returns a tuple of Repository,DbRepository,
171 """Returns a tuple of Repository,DbRepository,
172 Get's repository from given name, creates BackendInstance and
172 Get's repository from given name, creates BackendInstance and
173 propagates it's data from database with all additional information
173 propagates it's data from database with all additional information
174
174
175 :param repo_name:
175 :param repo_name:
176 :param invalidation_list: if a invalidation list is given the get
176 :param invalidation_list: if a invalidation list is given the get
177 method should not manually check if this repository needs
177 method should not manually check if this repository needs
178 invalidation and just invalidate the repositories in list
178 invalidation and just invalidate the repositories in list
179 :param retval: string specifing what to return one of 'repo','dbrepo',
179 :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
180 'all'if repo or dbrepo is given it'll just lazy load chosen type
181 and return None as the second
181 and return None as the second
182 """
182 """
183 if not HasRepoPermissionAny('repository.read', 'repository.write',
183 if not HasRepoPermissionAny('repository.read', 'repository.write',
184 'repository.admin')(repo_name, 'get repo check'):
184 'repository.admin')(repo_name, 'get repo check'):
185 return
185 return
186
186
187 #======================================================================
187 #======================================================================
188 # CACHE FUNCTION
188 # CACHE FUNCTION
189 #======================================================================
189 #======================================================================
190 @cache_region('long_term')
190 @cache_region('long_term')
191 def _get_repo(repo_name):
191 def _get_repo(repo_name):
192
192
193 repo_path = os.path.join(self.repos_path, repo_name)
193 repo_path = os.path.join(self.repos_path, repo_name)
194
194
195 try:
195 try:
196 alias = get_scm(repo_path)[0]
196 alias = get_scm(repo_path)[0]
197 log.debug('Creating instance of %s repository', alias)
197 log.debug('Creating instance of %s repository', alias)
198 backend = get_backend(alias)
198 backend = get_backend(alias)
199 except VCSError:
199 except VCSError:
200 log.error(traceback.format_exc())
200 log.error(traceback.format_exc())
201 log.error('Perhaps this repository is in db and not in '
201 log.error('Perhaps this repository is in db and not in '
202 'filesystem run rescan repositories with '
202 'filesystem run rescan repositories with '
203 '"destroy old data " option from admin panel')
203 '"destroy old data " option from admin panel')
204 return
204 return
205
205
206 if alias == 'hg':
206 if alias == 'hg':
207 repo = backend(repo_path, create=False, baseui=make_ui('db'))
207 repo = backend(repo_path, create=False, baseui=make_ui('db'))
208 #skip hidden web repository
208 #skip hidden web repository
209 if repo._get_hidden():
209 if repo._get_hidden():
210 return
210 return
211 else:
211 else:
212 repo = backend(repo_path, create=False)
212 repo = backend(repo_path, create=False)
213
213
214 return repo
214 return repo
215
215
216 pre_invalidate = True
216 pre_invalidate = True
217 dbinvalidate = False
217 dbinvalidate = False
218
218
219 if invalidation_list is not None:
219 if invalidation_list is not None:
220 pre_invalidate = repo_name in invalidation_list
220 pre_invalidate = repo_name in invalidation_list
221
221
222 if pre_invalidate:
222 if pre_invalidate:
223 #this returns object to invalidate
223 #this returns object to invalidate
224 invalidate = self._should_invalidate(repo_name)
224 invalidate = self._should_invalidate(repo_name)
225 if invalidate:
225 if invalidate:
226 log.info('invalidating cache for repository %s', repo_name)
226 log.info('invalidating cache for repository %s', repo_name)
227 region_invalidate(_get_repo, None, repo_name)
227 region_invalidate(_get_repo, None, repo_name)
228 self._mark_invalidated(invalidate)
228 self._mark_invalidated(invalidate)
229 dbinvalidate = True
229 dbinvalidate = True
230
230
231 r, dbr = None, None
231 r, dbr = None, None
232 if retval == 'repo' or 'all':
232 if retval == 'repo' or 'all':
233 r = _get_repo(repo_name)
233 r = _get_repo(repo_name)
234 if retval == 'dbrepo' or 'all':
234 if retval == 'dbrepo' or 'all':
235 dbr = RepoModel().get_full(repo_name, cache=True,
235 dbr = RepoModel().get_full(repo_name, cache=True,
236 invalidate=dbinvalidate)
236 invalidate=dbinvalidate)
237
237
238 return r, dbr
238 return r, dbr
239
239
240 def mark_for_invalidation(self, repo_name):
240 def mark_for_invalidation(self, repo_name):
241 """Puts cache invalidation task into db for
241 """Puts cache invalidation task into db for
242 further global cache invalidation
242 further global cache invalidation
243
243
244 :param repo_name: this repo that should invalidation take place
244 :param repo_name: this repo that should invalidation take place
245 """
245 """
246
246
247 log.debug('marking %s for invalidation', repo_name)
247 log.debug('marking %s for invalidation', repo_name)
248 cache = self.sa.query(CacheInvalidation)\
248 cache = self.sa.query(CacheInvalidation)\
249 .filter(CacheInvalidation.cache_key == repo_name).scalar()
249 .filter(CacheInvalidation.cache_key == repo_name).scalar()
250
250
251 if cache:
251 if cache:
252 #mark this cache as inactive
252 #mark this cache as inactive
253 cache.cache_active = False
253 cache.cache_active = False
254 else:
254 else:
255 log.debug('cache key not found in invalidation db -> creating one')
255 log.debug('cache key not found in invalidation db -> creating one')
256 cache = CacheInvalidation(repo_name)
256 cache = CacheInvalidation(repo_name)
257
257
258 try:
258 try:
259 self.sa.add(cache)
259 self.sa.add(cache)
260 self.sa.commit()
260 self.sa.commit()
261 except (DatabaseError,):
261 except (DatabaseError,):
262 log.error(traceback.format_exc())
262 log.error(traceback.format_exc())
263 self.sa.rollback()
263 self.sa.rollback()
264
264
265 def toggle_following_repo(self, follow_repo_id, user_id):
265 def toggle_following_repo(self, follow_repo_id, user_id):
266
266
267 f = self.sa.query(UserFollowing)\
267 f = self.sa.query(UserFollowing)\
268 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
268 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
269 .filter(UserFollowing.user_id == user_id).scalar()
269 .filter(UserFollowing.user_id == user_id).scalar()
270
270
271 if f is not None:
271 if f is not None:
272
272
273 try:
273 try:
274 self.sa.delete(f)
274 self.sa.delete(f)
275 self.sa.commit()
275 self.sa.commit()
276 action_logger(UserTemp(user_id),
276 action_logger(UserTemp(user_id),
277 'stopped_following_repo',
277 'stopped_following_repo',
278 RepoTemp(follow_repo_id))
278 RepoTemp(follow_repo_id))
279 return
279 return
280 except:
280 except:
281 log.error(traceback.format_exc())
281 log.error(traceback.format_exc())
282 self.sa.rollback()
282 self.sa.rollback()
283 raise
283 raise
284
284
285 try:
285 try:
286 f = UserFollowing()
286 f = UserFollowing()
287 f.user_id = user_id
287 f.user_id = user_id
288 f.follows_repo_id = follow_repo_id
288 f.follows_repo_id = follow_repo_id
289 self.sa.add(f)
289 self.sa.add(f)
290 self.sa.commit()
290 self.sa.commit()
291 action_logger(UserTemp(user_id),
291 action_logger(UserTemp(user_id),
292 'started_following_repo',
292 'started_following_repo',
293 RepoTemp(follow_repo_id))
293 RepoTemp(follow_repo_id))
294 except:
294 except:
295 log.error(traceback.format_exc())
295 log.error(traceback.format_exc())
296 self.sa.rollback()
296 self.sa.rollback()
297 raise
297 raise
298
298
299 def toggle_following_user(self, follow_user_id, user_id):
299 def toggle_following_user(self, follow_user_id, user_id):
300 f = self.sa.query(UserFollowing)\
300 f = self.sa.query(UserFollowing)\
301 .filter(UserFollowing.follows_user_id == follow_user_id)\
301 .filter(UserFollowing.follows_user_id == follow_user_id)\
302 .filter(UserFollowing.user_id == user_id).scalar()
302 .filter(UserFollowing.user_id == user_id).scalar()
303
303
304 if f is not None:
304 if f is not None:
305 try:
305 try:
306 self.sa.delete(f)
306 self.sa.delete(f)
307 self.sa.commit()
307 self.sa.commit()
308 return
308 return
309 except:
309 except:
310 log.error(traceback.format_exc())
310 log.error(traceback.format_exc())
311 self.sa.rollback()
311 self.sa.rollback()
312 raise
312 raise
313
313
314 try:
314 try:
315 f = UserFollowing()
315 f = UserFollowing()
316 f.user_id = user_id
316 f.user_id = user_id
317 f.follows_user_id = follow_user_id
317 f.follows_user_id = follow_user_id
318 self.sa.add(f)
318 self.sa.add(f)
319 self.sa.commit()
319 self.sa.commit()
320 except:
320 except:
321 log.error(traceback.format_exc())
321 log.error(traceback.format_exc())
322 self.sa.rollback()
322 self.sa.rollback()
323 raise
323 raise
324
324
325 def is_following_repo(self, repo_name, user_id, cache=False):
325 def is_following_repo(self, repo_name, user_id, cache=False):
326 r = self.sa.query(Repository)\
326 r = self.sa.query(Repository)\
327 .filter(Repository.repo_name == repo_name).scalar()
327 .filter(Repository.repo_name == repo_name).scalar()
328
328
329 f = self.sa.query(UserFollowing)\
329 f = self.sa.query(UserFollowing)\
330 .filter(UserFollowing.follows_repository == r)\
330 .filter(UserFollowing.follows_repository == r)\
331 .filter(UserFollowing.user_id == user_id).scalar()
331 .filter(UserFollowing.user_id == user_id).scalar()
332
332
333 return f is not None
333 return f is not None
334
334
335 def is_following_user(self, username, user_id, cache=False):
335 def is_following_user(self, username, user_id, cache=False):
336 u = UserModel(self.sa).get_by_username(username)
336 u = UserModel(self.sa).get_by_username(username)
337
337
338 f = self.sa.query(UserFollowing)\
338 f = self.sa.query(UserFollowing)\
339 .filter(UserFollowing.follows_user == u)\
339 .filter(UserFollowing.follows_user == u)\
340 .filter(UserFollowing.user_id == user_id).scalar()
340 .filter(UserFollowing.user_id == user_id).scalar()
341
341
342 return f is not None
342 return f is not None
343
343
344 def get_followers(self, repo_id):
344 def get_followers(self, repo_id):
345 if isinstance(repo_id, int):
345 if isinstance(repo_id, int):
346 return self.sa.query(UserFollowing)\
346 return self.sa.query(UserFollowing)\
347 .filter(UserFollowing.follows_repo_id == repo_id).count()
347 .filter(UserFollowing.follows_repo_id == repo_id).count()
348 else:
348 else:
349 return self.sa.query(UserFollowing)\
349 return self.sa.query(UserFollowing)\
350 .filter(UserFollowing.follows_repository \
350 .filter(UserFollowing.follows_repository \
351 == RepoModel().get_by_repo_name(repo_id)).count()
351 == RepoModel().get_by_repo_name(repo_id)).count()
352
352
353 def get_forks(self, repo_id):
353 def get_forks(self, repo_id):
354 if isinstance(repo_id, int):
354 if isinstance(repo_id, int):
355 return self.sa.query(Repository)\
355 return self.sa.query(Repository)\
356 .filter(Repository.fork_id == repo_id).count()
356 .filter(Repository.fork_id == repo_id).count()
357 else:
357 else:
358 return self.sa.query(Repository)\
358 return self.sa.query(Repository)\
359 .filter(Repository.fork \
359 .filter(Repository.fork \
360 == RepoModel().get_by_repo_name(repo_id)).count()
360 == RepoModel().get_by_repo_name(repo_id)).count()
361
361
362 def pull_changes(self, repo_name, username):
362 def pull_changes(self, repo_name, username):
363 repo, dbrepo = self.get(repo_name, retval='all')
363 repo, dbrepo = self.get(repo_name, retval='all')
364
364
365 try:
365 try:
366 extras = {'ip': '',
366 extras = {'ip': '',
367 'username': username,
367 'username': username,
368 'action': 'push_remote',
368 'action': 'push_remote',
369 'repository': repo_name}
369 'repository': repo_name}
370
370
371 #inject ui extra param to log this action via push logger
371 #inject ui extra param to log this action via push logger
372 for k, v in extras.items():
372 for k, v in extras.items():
373 repo._repo.ui.setconfig('rhodecode_extras', k, v)
373 repo._repo.ui.setconfig('rhodecode_extras', k, v)
374
374
375 repo.pull(dbrepo.clone_uri)
375 repo.pull(dbrepo.clone_uri)
376 self.mark_for_invalidation(repo_name)
376 self.mark_for_invalidation(repo_name)
377 except:
377 except:
378 log.error(traceback.format_exc())
378 log.error(traceback.format_exc())
379 raise
379 raise
380
380
381 def get_unread_journal(self):
381 def get_unread_journal(self):
382 return self.sa.query(UserLog).count()
382 return self.sa.query(UserLog).count()
383
383
384 def _should_invalidate(self, repo_name):
384 def _should_invalidate(self, repo_name):
385 """Looks up database for invalidation signals for this repo_name
385 """Looks up database for invalidation signals for this repo_name
386
386
387 :param repo_name:
387 :param repo_name:
388 """
388 """
389
389
390 ret = self.sa.query(CacheInvalidation)\
390 ret = self.sa.query(CacheInvalidation)\
391 .filter(CacheInvalidation.cache_key == repo_name)\
391 .filter(CacheInvalidation.cache_key == repo_name)\
392 .filter(CacheInvalidation.cache_active == False)\
392 .filter(CacheInvalidation.cache_active == False)\
393 .scalar()
393 .scalar()
394
394
395 return ret
395 return ret
396
396
397 def _mark_invalidated(self, cache_key):
397 def _mark_invalidated(self, cache_key):
398 """ Marks all occurrences of cache to invalidation as already
398 """ Marks all occurrences of cache to invalidation as already
399 invalidated
399 invalidated
400
400
401 :param cache_key:
401 :param cache_key:
402 """
402 """
403
403
404 if cache_key:
404 if cache_key:
405 log.debug('marking %s as already invalidated', cache_key)
405 log.debug('marking %s as already invalidated', cache_key)
406 try:
406 try:
407 cache_key.cache_active = True
407 cache_key.cache_active = True
408 self.sa.add(cache_key)
408 self.sa.add(cache_key)
409 self.sa.commit()
409 self.sa.commit()
410 except (DatabaseError,):
410 except (DatabaseError,):
411 log.error(traceback.format_exc())
411 log.error(traceback.format_exc())
412 self.sa.rollback()
412 self.sa.rollback()
General Comments 0
You need to be logged in to leave comments. Login now