##// END OF EJS Templates
Fixed problem with new repos, and visibility on the main list.
marcink -
r1380:39ae0f09 beta
parent child Browse files
Show More
@@ -1,416 +1,416 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 from vcs.nodes import FileNode
41 from vcs.nodes import FileNode
42
42
43 from rhodecode import BACKENDS
43 from rhodecode import BACKENDS
44 from rhodecode.lib import helpers as h
44 from rhodecode.lib import helpers as h
45 from rhodecode.lib.auth import HasRepoPermissionAny
45 from rhodecode.lib.auth import HasRepoPermissionAny
46 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
46 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
47 action_logger
47 action_logger
48 from rhodecode.model import BaseModel
48 from rhodecode.model import BaseModel
49 from rhodecode.model.user import UserModel
49 from rhodecode.model.user import UserModel
50 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.repo import RepoModel
51 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
51 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
52 UserFollowing, UserLog
52 UserFollowing, UserLog
53 from rhodecode.model.caching_query import FromCache
53 from rhodecode.model.caching_query import FromCache
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57
57
58 class UserTemp(object):
58 class UserTemp(object):
59 def __init__(self, user_id):
59 def __init__(self, user_id):
60 self.user_id = user_id
60 self.user_id = user_id
61
61
62 def __repr__(self):
62 def __repr__(self):
63 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
63 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
64
64
65
65
66 class RepoTemp(object):
66 class RepoTemp(object):
67 def __init__(self, repo_id):
67 def __init__(self, repo_id):
68 self.repo_id = repo_id
68 self.repo_id = repo_id
69
69
70 def __repr__(self):
70 def __repr__(self):
71 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
71 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
72
72
73 class CachedRepoList(object):
73 class CachedRepoList(object):
74
74
75 def __init__(self, db_repo_list, invalidation_list, repos_path,
75 def __init__(self, db_repo_list, invalidation_list, repos_path,
76 order_by=None):
76 order_by=None):
77 self.db_repo_list = db_repo_list
77 self.db_repo_list = db_repo_list
78 self.invalidation_list = invalidation_list
78 self.invalidation_list = invalidation_list
79 self.repos_path = repos_path
79 self.repos_path = repos_path
80 self.order_by = order_by
80 self.order_by = order_by
81 self.reversed = (order_by or '').startswith('-')
81 self.reversed = (order_by or '').startswith('-')
82
82
83 def __len__(self):
83 def __len__(self):
84 return len(self.db_repo_list)
84 return len(self.db_repo_list)
85
85
86 def __repr__(self):
86 def __repr__(self):
87 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
87 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
88
88
89 def __iter__(self):
89 def __iter__(self):
90 for db_repo in self.db_repo_list:
90 for db_repo in self.db_repo_list:
91 dbr = db_repo
91 dbr = db_repo
92
92
93 # invalidate the repo cache if needed before getting the
93 # invalidate the repo cache if needed before getting the
94 # scm instance
94 # scm instance
95
95
96 scm_invalidate = False
96 scm_invalidate = False
97 if self.invalidation_list is not None:
97 if self.invalidation_list is not None:
98 scm_invalidate = dbr.repo_name in self.invalidation_list
98 scm_invalidate = dbr.repo_name in self.invalidation_list
99
99
100 if scm_invalidate:
100 if scm_invalidate:
101 log.info('invalidating cache for repository %s',
101 log.info('invalidating cache for repository %s',
102 dbr.repo_name)
102 dbr.repo_name)
103 db_repo.set_invalidate
103 db_repo.set_invalidate
104
104
105 scmr = db_repo.scm_instance_cached
105 scmr = db_repo.scm_instance_cached
106
106
107 #check permission at this level
107 #check permission at this level
108 if not HasRepoPermissionAny('repository.read',
108 if not HasRepoPermissionAny('repository.read',
109 'repository.write',
109 'repository.write',
110 'repository.admin')(dbr.repo_name,
110 'repository.admin')(dbr.repo_name,
111 'get repo check'):
111 'get repo check'):
112 continue
112 continue
113
113
114
114
115 if not scmr:
115 if scmr is None:
116 log.error('%s this repository is present in database but it '
116 log.error('%s this repository is present in database but it '
117 'cannot be created as an scm instance',
117 'cannot be created as an scm instance',
118 dbr.repo_name)
118 dbr.repo_name)
119 continue
119 continue
120
120
121
121
122 last_change = scmr.last_change
122 last_change = scmr.last_change
123 tip = h.get_changeset_safe(scmr, 'tip')
123 tip = h.get_changeset_safe(scmr, 'tip')
124
124
125 tmp_d = {}
125 tmp_d = {}
126 tmp_d['name'] = dbr.repo_name
126 tmp_d['name'] = dbr.repo_name
127 tmp_d['name_sort'] = tmp_d['name'].lower()
127 tmp_d['name_sort'] = tmp_d['name'].lower()
128 tmp_d['description'] = dbr.description
128 tmp_d['description'] = dbr.description
129 tmp_d['description_sort'] = tmp_d['description']
129 tmp_d['description_sort'] = tmp_d['description']
130 tmp_d['last_change'] = last_change
130 tmp_d['last_change'] = last_change
131 tmp_d['last_change_sort'] = time.mktime(last_change \
131 tmp_d['last_change_sort'] = time.mktime(last_change \
132 .timetuple())
132 .timetuple())
133 tmp_d['tip'] = tip.raw_id
133 tmp_d['tip'] = tip.raw_id
134 tmp_d['tip_sort'] = tip.revision
134 tmp_d['tip_sort'] = tip.revision
135 tmp_d['rev'] = tip.revision
135 tmp_d['rev'] = tip.revision
136 tmp_d['contact'] = dbr.user.full_contact
136 tmp_d['contact'] = dbr.user.full_contact
137 tmp_d['contact_sort'] = tmp_d['contact']
137 tmp_d['contact_sort'] = tmp_d['contact']
138 tmp_d['owner_sort'] = tmp_d['contact']
138 tmp_d['owner_sort'] = tmp_d['contact']
139 tmp_d['repo_archives'] = list(scmr._get_archives())
139 tmp_d['repo_archives'] = list(scmr._get_archives())
140 tmp_d['last_msg'] = tip.message
140 tmp_d['last_msg'] = tip.message
141 tmp_d['repo'] = scmr
141 tmp_d['repo'] = scmr
142 tmp_d['dbrepo'] = dbr.get_dict()
142 tmp_d['dbrepo'] = dbr.get_dict()
143 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork \
143 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork \
144 else {}
144 else {}
145 yield tmp_d
145 yield tmp_d
146
146
147 class ScmModel(BaseModel):
147 class ScmModel(BaseModel):
148 """Generic Scm Model
148 """Generic Scm Model
149 """
149 """
150
150
151 @LazyProperty
151 @LazyProperty
152 def repos_path(self):
152 def repos_path(self):
153 """Get's the repositories root path from database
153 """Get's the repositories root path from database
154 """
154 """
155
155
156 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
156 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
157
157
158 return q.ui_value
158 return q.ui_value
159
159
160 def repo_scan(self, repos_path=None):
160 def repo_scan(self, repos_path=None):
161 """Listing of repositories in given path. This path should not be a
161 """Listing of repositories in given path. This path should not be a
162 repository itself. Return a dictionary of repository objects
162 repository itself. Return a dictionary of repository objects
163
163
164 :param repos_path: path to directory containing repositories
164 :param repos_path: path to directory containing repositories
165 """
165 """
166
166
167 log.info('scanning for repositories in %s', repos_path)
167 log.info('scanning for repositories in %s', repos_path)
168
168
169 if repos_path is None:
169 if repos_path is None:
170 repos_path = self.repos_path
170 repos_path = self.repos_path
171
171
172 baseui = make_ui('db')
172 baseui = make_ui('db')
173 repos_list = {}
173 repos_list = {}
174
174
175 for name, path in get_filesystem_repos(repos_path, recursive=True):
175 for name, path in get_filesystem_repos(repos_path, recursive=True):
176 try:
176 try:
177 if name in repos_list:
177 if name in repos_list:
178 raise RepositoryError('Duplicate repository name %s '
178 raise RepositoryError('Duplicate repository name %s '
179 'found in %s' % (name, path))
179 'found in %s' % (name, path))
180 else:
180 else:
181
181
182 klass = get_backend(path[0])
182 klass = get_backend(path[0])
183
183
184 if path[0] == 'hg' and path[0] in BACKENDS.keys():
184 if path[0] == 'hg' and path[0] in BACKENDS.keys():
185 repos_list[name] = klass(path[1], baseui=baseui)
185 repos_list[name] = klass(path[1], baseui=baseui)
186
186
187 if path[0] == 'git' and path[0] in BACKENDS.keys():
187 if path[0] == 'git' and path[0] in BACKENDS.keys():
188 repos_list[name] = klass(path[1])
188 repos_list[name] = klass(path[1])
189 except OSError:
189 except OSError:
190 continue
190 continue
191
191
192 return repos_list
192 return repos_list
193
193
194 def get_repos(self, all_repos=None, sort_key=None):
194 def get_repos(self, all_repos=None, sort_key=None):
195 """
195 """
196 Get all repos from db and for each repo create it's
196 Get all repos from db and for each repo create it's
197 backend instance and fill that backed with information from database
197 backend instance and fill that backed with information from database
198
198
199 :param all_repos: list of repository names as strings
199 :param all_repos: list of repository names as strings
200 give specific repositories list, good for filtering
200 give specific repositories list, good for filtering
201 """
201 """
202 if all_repos is None:
202 if all_repos is None:
203 all_repos = self.sa.query(Repository)\
203 all_repos = self.sa.query(Repository)\
204 .filter(Repository.group_id == None)\
204 .filter(Repository.group_id == None)\
205 .order_by(Repository.repo_name).all()
205 .order_by(Repository.repo_name).all()
206
206
207 #get the repositories that should be invalidated
207 #get the repositories that should be invalidated
208 invalidation_list = [str(x.cache_key) for x in \
208 invalidation_list = [str(x.cache_key) for x in \
209 self.sa.query(CacheInvalidation.cache_key)\
209 self.sa.query(CacheInvalidation.cache_key)\
210 .filter(CacheInvalidation.cache_active == False)\
210 .filter(CacheInvalidation.cache_active == False)\
211 .all()]
211 .all()]
212
212
213 repo_iter = CachedRepoList(all_repos, invalidation_list,
213 repo_iter = CachedRepoList(all_repos, invalidation_list,
214 repos_path=self.repos_path,
214 repos_path=self.repos_path,
215 order_by=sort_key)
215 order_by=sort_key)
216
216
217 return repo_iter
217 return repo_iter
218
218
219 def mark_for_invalidation(self, repo_name):
219 def mark_for_invalidation(self, repo_name):
220 """Puts cache invalidation task into db for
220 """Puts cache invalidation task into db for
221 further global cache invalidation
221 further global cache invalidation
222
222
223 :param repo_name: this repo that should invalidation take place
223 :param repo_name: this repo that should invalidation take place
224 """
224 """
225
225
226 log.debug('marking %s for invalidation', repo_name)
226 log.debug('marking %s for invalidation', repo_name)
227 cache = self.sa.query(CacheInvalidation)\
227 cache = self.sa.query(CacheInvalidation)\
228 .filter(CacheInvalidation.cache_key == repo_name).scalar()
228 .filter(CacheInvalidation.cache_key == repo_name).scalar()
229
229
230 if cache:
230 if cache:
231 #mark this cache as inactive
231 #mark this cache as inactive
232 cache.cache_active = False
232 cache.cache_active = False
233 else:
233 else:
234 log.debug('cache key not found in invalidation db -> creating one')
234 log.debug('cache key not found in invalidation db -> creating one')
235 cache = CacheInvalidation(repo_name)
235 cache = CacheInvalidation(repo_name)
236
236
237 try:
237 try:
238 self.sa.add(cache)
238 self.sa.add(cache)
239 self.sa.commit()
239 self.sa.commit()
240 except (DatabaseError,):
240 except (DatabaseError,):
241 log.error(traceback.format_exc())
241 log.error(traceback.format_exc())
242 self.sa.rollback()
242 self.sa.rollback()
243
243
244 def toggle_following_repo(self, follow_repo_id, user_id):
244 def toggle_following_repo(self, follow_repo_id, user_id):
245
245
246 f = self.sa.query(UserFollowing)\
246 f = self.sa.query(UserFollowing)\
247 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
247 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
248 .filter(UserFollowing.user_id == user_id).scalar()
248 .filter(UserFollowing.user_id == user_id).scalar()
249
249
250 if f is not None:
250 if f is not None:
251
251
252 try:
252 try:
253 self.sa.delete(f)
253 self.sa.delete(f)
254 self.sa.commit()
254 self.sa.commit()
255 action_logger(UserTemp(user_id),
255 action_logger(UserTemp(user_id),
256 'stopped_following_repo',
256 'stopped_following_repo',
257 RepoTemp(follow_repo_id))
257 RepoTemp(follow_repo_id))
258 return
258 return
259 except:
259 except:
260 log.error(traceback.format_exc())
260 log.error(traceback.format_exc())
261 self.sa.rollback()
261 self.sa.rollback()
262 raise
262 raise
263
263
264 try:
264 try:
265 f = UserFollowing()
265 f = UserFollowing()
266 f.user_id = user_id
266 f.user_id = user_id
267 f.follows_repo_id = follow_repo_id
267 f.follows_repo_id = follow_repo_id
268 self.sa.add(f)
268 self.sa.add(f)
269 self.sa.commit()
269 self.sa.commit()
270 action_logger(UserTemp(user_id),
270 action_logger(UserTemp(user_id),
271 'started_following_repo',
271 'started_following_repo',
272 RepoTemp(follow_repo_id))
272 RepoTemp(follow_repo_id))
273 except:
273 except:
274 log.error(traceback.format_exc())
274 log.error(traceback.format_exc())
275 self.sa.rollback()
275 self.sa.rollback()
276 raise
276 raise
277
277
278 def toggle_following_user(self, follow_user_id, user_id):
278 def toggle_following_user(self, follow_user_id, user_id):
279 f = self.sa.query(UserFollowing)\
279 f = self.sa.query(UserFollowing)\
280 .filter(UserFollowing.follows_user_id == follow_user_id)\
280 .filter(UserFollowing.follows_user_id == follow_user_id)\
281 .filter(UserFollowing.user_id == user_id).scalar()
281 .filter(UserFollowing.user_id == user_id).scalar()
282
282
283 if f is not None:
283 if f is not None:
284 try:
284 try:
285 self.sa.delete(f)
285 self.sa.delete(f)
286 self.sa.commit()
286 self.sa.commit()
287 return
287 return
288 except:
288 except:
289 log.error(traceback.format_exc())
289 log.error(traceback.format_exc())
290 self.sa.rollback()
290 self.sa.rollback()
291 raise
291 raise
292
292
293 try:
293 try:
294 f = UserFollowing()
294 f = UserFollowing()
295 f.user_id = user_id
295 f.user_id = user_id
296 f.follows_user_id = follow_user_id
296 f.follows_user_id = follow_user_id
297 self.sa.add(f)
297 self.sa.add(f)
298 self.sa.commit()
298 self.sa.commit()
299 except:
299 except:
300 log.error(traceback.format_exc())
300 log.error(traceback.format_exc())
301 self.sa.rollback()
301 self.sa.rollback()
302 raise
302 raise
303
303
304 def is_following_repo(self, repo_name, user_id, cache=False):
304 def is_following_repo(self, repo_name, user_id, cache=False):
305 r = self.sa.query(Repository)\
305 r = self.sa.query(Repository)\
306 .filter(Repository.repo_name == repo_name).scalar()
306 .filter(Repository.repo_name == repo_name).scalar()
307
307
308 f = self.sa.query(UserFollowing)\
308 f = self.sa.query(UserFollowing)\
309 .filter(UserFollowing.follows_repository == r)\
309 .filter(UserFollowing.follows_repository == r)\
310 .filter(UserFollowing.user_id == user_id).scalar()
310 .filter(UserFollowing.user_id == user_id).scalar()
311
311
312 return f is not None
312 return f is not None
313
313
314 def is_following_user(self, username, user_id, cache=False):
314 def is_following_user(self, username, user_id, cache=False):
315 u = UserModel(self.sa).get_by_username(username)
315 u = UserModel(self.sa).get_by_username(username)
316
316
317 f = self.sa.query(UserFollowing)\
317 f = self.sa.query(UserFollowing)\
318 .filter(UserFollowing.follows_user == u)\
318 .filter(UserFollowing.follows_user == u)\
319 .filter(UserFollowing.user_id == user_id).scalar()
319 .filter(UserFollowing.user_id == user_id).scalar()
320
320
321 return f is not None
321 return f is not None
322
322
323 def get_followers(self, repo_id):
323 def get_followers(self, repo_id):
324 if not isinstance(repo_id, int):
324 if not isinstance(repo_id, int):
325 repo_id = getattr(Repository.by_repo_name(repo_id), 'repo_id')
325 repo_id = getattr(Repository.by_repo_name(repo_id), 'repo_id')
326
326
327 return self.sa.query(UserFollowing)\
327 return self.sa.query(UserFollowing)\
328 .filter(UserFollowing.follows_repo_id == repo_id).count()
328 .filter(UserFollowing.follows_repo_id == repo_id).count()
329
329
330 def get_forks(self, repo_id):
330 def get_forks(self, repo_id):
331 if not isinstance(repo_id, int):
331 if not isinstance(repo_id, int):
332 repo_id = getattr(Repository.by_repo_name(repo_id), 'repo_id')
332 repo_id = getattr(Repository.by_repo_name(repo_id), 'repo_id')
333
333
334 return self.sa.query(Repository)\
334 return self.sa.query(Repository)\
335 .filter(Repository.fork_id == repo_id).count()
335 .filter(Repository.fork_id == repo_id).count()
336
336
337 def pull_changes(self, repo_name, username):
337 def pull_changes(self, repo_name, username):
338 dbrepo = Repository.by_repo_name(repo_name)
338 dbrepo = Repository.by_repo_name(repo_name)
339 repo = dbrepo.scm_instance
339 repo = dbrepo.scm_instance
340 try:
340 try:
341 extras = {'ip': '',
341 extras = {'ip': '',
342 'username': username,
342 'username': username,
343 'action': 'push_remote',
343 'action': 'push_remote',
344 'repository': repo_name}
344 'repository': repo_name}
345
345
346 #inject ui extra param to log this action via push logger
346 #inject ui extra param to log this action via push logger
347 for k, v in extras.items():
347 for k, v in extras.items():
348 repo._repo.ui.setconfig('rhodecode_extras', k, v)
348 repo._repo.ui.setconfig('rhodecode_extras', k, v)
349
349
350 repo.pull(dbrepo.clone_uri)
350 repo.pull(dbrepo.clone_uri)
351 self.mark_for_invalidation(repo_name)
351 self.mark_for_invalidation(repo_name)
352 except:
352 except:
353 log.error(traceback.format_exc())
353 log.error(traceback.format_exc())
354 raise
354 raise
355
355
356
356
357 def commit_change(self, repo, repo_name, cs, user, author, message, content,
357 def commit_change(self, repo, repo_name, cs, user, author, message, content,
358 f_path):
358 f_path):
359
359
360 if repo.alias == 'hg':
360 if repo.alias == 'hg':
361 from vcs.backends.hg import MercurialInMemoryChangeset as IMC
361 from vcs.backends.hg import MercurialInMemoryChangeset as IMC
362 elif repo.alias == 'git':
362 elif repo.alias == 'git':
363 from vcs.backends.git import GitInMemoryChangeset as IMC
363 from vcs.backends.git import GitInMemoryChangeset as IMC
364
364
365 # decoding here will force that we have proper encoded values
365 # decoding here will force that we have proper encoded values
366 # in any other case this will throw exceptions and deny commit
366 # in any other case this will throw exceptions and deny commit
367 content = content.encode('utf8')
367 content = content.encode('utf8')
368 message = message.encode('utf8')
368 message = message.encode('utf8')
369 path = f_path.encode('utf8')
369 path = f_path.encode('utf8')
370 author = author.encode('utf8')
370 author = author.encode('utf8')
371 m = IMC(repo)
371 m = IMC(repo)
372 m.change(FileNode(path, content))
372 m.change(FileNode(path, content))
373 tip = m.commit(message=message,
373 tip = m.commit(message=message,
374 author=author,
374 author=author,
375 parents=[cs], branch=cs.branch)
375 parents=[cs], branch=cs.branch)
376
376
377 new_cs = tip.short_id
377 new_cs = tip.short_id
378 action = 'push_local:%s' % new_cs
378 action = 'push_local:%s' % new_cs
379
379
380 action_logger(user, action, repo_name)
380 action_logger(user, action, repo_name)
381
381
382 self.mark_for_invalidation(repo_name)
382 self.mark_for_invalidation(repo_name)
383
383
384
384
385 def get_unread_journal(self):
385 def get_unread_journal(self):
386 return self.sa.query(UserLog).count()
386 return self.sa.query(UserLog).count()
387
387
388 def _should_invalidate(self, repo_name):
388 def _should_invalidate(self, repo_name):
389 """Looks up database for invalidation signals for this repo_name
389 """Looks up database for invalidation signals for this repo_name
390
390
391 :param repo_name:
391 :param repo_name:
392 """
392 """
393
393
394 ret = self.sa.query(CacheInvalidation)\
394 ret = self.sa.query(CacheInvalidation)\
395 .filter(CacheInvalidation.cache_key == repo_name)\
395 .filter(CacheInvalidation.cache_key == repo_name)\
396 .filter(CacheInvalidation.cache_active == False)\
396 .filter(CacheInvalidation.cache_active == False)\
397 .scalar()
397 .scalar()
398
398
399 return ret
399 return ret
400
400
401 def _mark_invalidated(self, cache_key):
401 def _mark_invalidated(self, cache_key):
402 """ Marks all occurrences of cache to invalidation as already
402 """ Marks all occurrences of cache to invalidation as already
403 invalidated
403 invalidated
404
404
405 :param cache_key:
405 :param cache_key:
406 """
406 """
407
407
408 if cache_key:
408 if cache_key:
409 log.debug('marking %s as already invalidated', cache_key)
409 log.debug('marking %s as already invalidated', cache_key)
410 try:
410 try:
411 cache_key.cache_active = True
411 cache_key.cache_active = True
412 self.sa.add(cache_key)
412 self.sa.add(cache_key)
413 self.sa.commit()
413 self.sa.commit()
414 except (DatabaseError,):
414 except (DatabaseError,):
415 log.error(traceback.format_exc())
415 log.error(traceback.format_exc())
416 self.sa.rollback()
416 self.sa.rollback()
General Comments 0
You need to be logged in to leave comments. Login now