##// END OF EJS Templates
fixed issue with db transaction when filesystem creation of repository failed...
marcink -
r1028:f42ee60e beta
parent child Browse files
Show More
@@ -1,330 +1,331 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.repo
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Repository model for rhodecode
7 7
8 8 :created_on: Jun 5, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27 import os
28 28 import shutil
29 29 import logging
30 30 import traceback
31 31 from datetime import datetime
32 32
33 33 from rhodecode.model import BaseModel
34 34 from rhodecode.model.caching_query import FromCache
35 35 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
36 36 Statistics, UsersGroup, UsersGroupToPerm
37 37 from rhodecode.model.user import UserModel
38 38 from rhodecode.model.users_group import UsersGroupMember, UsersGroupModel
39 39
40 40 from vcs.backends import get_backend
41 41
42 42 log = logging.getLogger(__name__)
43 43
44 44 class RepoModel(BaseModel):
45 45
46 46 def __init__(self, sa=None):
47 47 try:
48 48 from pylons import app_globals
49 49 self._base_path = app_globals.base_path
50 50 except:
51 51 self._base_path = None
52 52
53 53 super(RepoModel, self).__init__(sa)
54 54
55 55 @property
56 56 def base_path(self):
57 57 if self._base_path is None:
58 58 raise Exception('Base Path is empty, try set this after'
59 59 'class initialization when not having '
60 60 'app_globals available')
61 61 return self._base_path
62 62
63 63 super(RepoModel, self).__init__()
64 64
65 65
66 66 def get(self, repo_id, cache=False):
67 67 repo = self.sa.query(Repository)\
68 68 .filter(Repository.repo_id == repo_id)
69 69
70 70 if cache:
71 71 repo = repo.options(FromCache("sql_cache_short",
72 72 "get_repo_%s" % repo_id))
73 73 return repo.scalar()
74 74
75 75
76 76 def get_by_repo_name(self, repo_name, cache=False):
77 77 repo = self.sa.query(Repository)\
78 78 .filter(Repository.repo_name == repo_name)
79 79
80 80 if cache:
81 81 repo = repo.options(FromCache("sql_cache_short",
82 82 "get_repo_%s" % repo_name))
83 83 return repo.scalar()
84 84
85 85 def get_users_js(self):
86 86
87 87 users = self.sa.query(User).filter(User.active == True).all()
88 88 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
89 89 users_array = '[%s]' % '\n'.join([u_tmpl % (u.user_id, u.name,
90 90 u.lastname, u.username)
91 91 for u in users])
92 92 return users_array
93 93
94 94
95 95 def get_users_groups_js(self):
96 96 users_groups = self.sa.query(UsersGroup)\
97 97 .filter(UsersGroup.users_group_active == True).all()
98 98
99 99 g_tmpl = '''{id:%s, grname:"%s",grmembers:"%s"},'''
100 100
101 101 users_groups_array = '[%s]' % '\n'.join([g_tmpl % \
102 102 (gr.users_group_id, gr.users_group_name,
103 103 len(gr.members))
104 104 for gr in users_groups])
105 105 return users_groups_array
106 106
107 107 def update(self, repo_name, form_data):
108 108 try:
109 109 cur_repo = self.get_by_repo_name(repo_name, cache=False)
110 110 user_model = UserModel(self.sa)
111 111 users_group_model = UsersGroupModel(self.sa)
112 112
113 113 #update permissions
114 114 for member, perm, member_type in form_data['perms_updates']:
115 115 if member_type == 'user':
116 116 r2p = self.sa.query(RepoToPerm)\
117 117 .filter(RepoToPerm.user == user_model.get_by_username(member))\
118 118 .filter(RepoToPerm.repository == cur_repo)\
119 119 .one()
120 120
121 121 r2p.permission = self.sa.query(Permission)\
122 122 .filter(Permission.permission_name == perm)\
123 123 .scalar()
124 124 self.sa.add(r2p)
125 125 else:
126 126 g2p = self.sa.query(UsersGroupToPerm)\
127 127 .filter(UsersGroupToPerm.users_group == users_group_model.get_by_groupname(member))\
128 128 .filter(UsersGroupToPerm.repository == cur_repo)\
129 129 .one()
130 130
131 131 g2p.permission = self.sa.query(Permission)\
132 132 .filter(Permission.permission_name == perm)\
133 133 .scalar()
134 134 self.sa.add(g2p)
135 135
136 136 #set new permissions
137 137 for member, perm, member_type in form_data['perms_new']:
138 138 if member_type == 'user':
139 139 r2p = RepoToPerm()
140 140 r2p.repository = cur_repo
141 141 r2p.user = user_model.get_by_username(member)
142 142
143 143 r2p.permission = self.sa.query(Permission)\
144 144 .filter(Permission.permission_name == perm)\
145 145 .scalar()
146 146 self.sa.add(r2p)
147 147 else:
148 148 g2p = UsersGroupToPerm()
149 149 g2p.repository = cur_repo
150 150 g2p.users_group = users_group_model.get_by_groupname(member)
151 151
152 152 g2p.permission = self.sa.query(Permission)\
153 153 .filter(Permission.permission_name == perm)\
154 154 .scalar()
155 155 self.sa.add(g2p)
156 156
157 157 #update current repo
158 158 for k, v in form_data.items():
159 159 if k == 'user':
160 160 cur_repo.user = user_model.get(v)
161 161 else:
162 162 setattr(cur_repo, k, v)
163 163
164 164 self.sa.add(cur_repo)
165 165
166 166 if repo_name != form_data['repo_name']:
167 167 #rename our data
168 168 self.__rename_repo(repo_name, form_data['repo_name'])
169 169
170 170 self.sa.commit()
171 171 except:
172 172 log.error(traceback.format_exc())
173 173 self.sa.rollback()
174 174 raise
175 175
176 176 def create(self, form_data, cur_user, just_db=False, fork=False):
177 177 try:
178 178 if fork:
179 179 #force str since hg doesn't go with unicode
180 180 repo_name = str(form_data['fork_name'])
181 181 org_name = str(form_data['repo_name'])
182 182
183 183 else:
184 184 org_name = repo_name = str(form_data['repo_name'])
185 185 new_repo = Repository()
186 186 new_repo.enable_statistics = True
187 187 for k, v in form_data.items():
188 188 if k == 'repo_name':
189 189 v = repo_name
190 190 setattr(new_repo, k, v)
191 191
192 192 if fork:
193 193 parent_repo = self.sa.query(Repository)\
194 194 .filter(Repository.repo_name == org_name).scalar()
195 195 new_repo.fork = parent_repo
196 196
197 197 new_repo.user_id = cur_user.user_id
198 198 self.sa.add(new_repo)
199 199
200 200 #create default permission
201 201 repo_to_perm = RepoToPerm()
202 202 default = 'repository.read'
203 203 for p in UserModel(self.sa).get_by_username('default', cache=False).user_perms:
204 204 if p.permission.permission_name.startswith('repository.'):
205 205 default = p.permission.permission_name
206 206 break
207 207
208 208 default_perm = 'repository.none' if form_data['private'] else default
209 209
210 210 repo_to_perm.permission_id = self.sa.query(Permission)\
211 211 .filter(Permission.permission_name == default_perm)\
212 212 .one().permission_id
213 213
214 repo_to_perm.repository_id = new_repo.repo_id
214 repo_to_perm.repository = new_repo
215 215 repo_to_perm.user_id = UserModel(self.sa)\
216 216 .get_by_username('default', cache=False).user_id
217 217
218 218 self.sa.add(repo_to_perm)
219
220 if not just_db:
221 self.__create_repo(repo_name, form_data['repo_type'])
222
219 223 self.sa.commit()
220 224
221
222 225 #now automatically start following this repository as owner
223 226 from rhodecode.model.scm import ScmModel
224 227 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
225 228 cur_user.user_id)
226 229
227 if not just_db:
228 self.__create_repo(repo_name, form_data['repo_type'])
229 230 except:
230 231 log.error(traceback.format_exc())
231 232 self.sa.rollback()
232 233 raise
233 234
234 235 def create_fork(self, form_data, cur_user):
235 236 from rhodecode.lib.celerylib import tasks, run_task
236 237 run_task(tasks.create_repo_fork, form_data, cur_user)
237 238
238 239 def delete(self, repo):
239 240 try:
240 241 self.sa.delete(repo)
241 242 self.__delete_repo(repo)
242 243 self.sa.commit()
243 244 except:
244 245 log.error(traceback.format_exc())
245 246 self.sa.rollback()
246 247 raise
247 248
248 249 def delete_perm_user(self, form_data, repo_name):
249 250 try:
250 251 self.sa.query(RepoToPerm)\
251 252 .filter(RepoToPerm.repository \
252 253 == self.get_by_repo_name(repo_name))\
253 254 .filter(RepoToPerm.user_id == form_data['user_id']).delete()
254 255 self.sa.commit()
255 256 except:
256 257 log.error(traceback.format_exc())
257 258 self.sa.rollback()
258 259 raise
259 260
260 261 def delete_perm_users_group(self, form_data, repo_name):
261 262 try:
262 263 self.sa.query(UsersGroupToPerm)\
263 264 .filter(UsersGroupToPerm.repository \
264 265 == self.get_by_repo_name(repo_name))\
265 266 .filter(UsersGroupToPerm.users_group_id \
266 267 == form_data['users_group_id']).delete()
267 268 self.sa.commit()
268 269 except:
269 270 log.error(traceback.format_exc())
270 271 self.sa.rollback()
271 272 raise
272 273
273 274 def delete_stats(self, repo_name):
274 275 try:
275 276 self.sa.query(Statistics)\
276 277 .filter(Statistics.repository == \
277 278 self.get_by_repo_name(repo_name)).delete()
278 279 self.sa.commit()
279 280 except:
280 281 log.error(traceback.format_exc())
281 282 self.sa.rollback()
282 283 raise
283 284
284 285
285 286 def __create_repo(self, repo_name, alias):
286 287 """
287 288 makes repository on filesystem
288 289 :param repo_name:
289 290 :param alias:
290 291 """
291 292 from rhodecode.lib.utils import check_repo
292 293 repo_path = os.path.join(self.base_path, repo_name)
293 294 if check_repo(repo_name, self.base_path):
294 295 log.info('creating repo %s in %s', repo_name, repo_path)
295 296 backend = get_backend(alias)
296 297 backend(repo_path, create=True)
297 298
298 299 def __rename_repo(self, old, new):
299 300 """
300 301 renames repository on filesystem
301 302 :param old: old name
302 303 :param new: new name
303 304 """
304 305 log.info('renaming repo from %s to %s', old, new)
305 306
306 307 old_path = os.path.join(self.base_path, old)
307 308 new_path = os.path.join(self.base_path, new)
308 309 if os.path.isdir(new_path):
309 310 raise Exception('Was trying to rename to already existing dir %s',
310 311 new_path)
311 312 shutil.move(old_path, new_path)
312 313
313 314 def __delete_repo(self, repo):
314 315 """
315 316 removes repo from filesystem, the removal is acctually made by
316 317 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
317 318 repository is no longer valid for rhodecode, can be undeleted later on
318 319 by reverting the renames on this repository
319 320 :param repo: repo object
320 321 """
321 322 rm_path = os.path.join(self.base_path, repo.repo_name)
322 323 log.info("Removing %s", rm_path)
323 324 #disable hg/git
324 325 alias = repo.repo_type
325 326 shutil.move(os.path.join(rm_path, '.%s' % alias),
326 327 os.path.join(rm_path, 'rm__.%s' % alias))
327 328 #disable repo
328 329 shutil.move(rm_path, os.path.join(self.base_path, 'rm__%s__%s' \
329 330 % (datetime.today().isoformat(),
330 331 repo.repo_name)))
@@ -1,384 +1,386 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.scm
4 4 ~~~~~~~~~~~~~~~~~~~
5 5
6 6 Scm model for RhodeCode
7 7
8 8 :created_on: Apr 9, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27 import os
28 28 import time
29 29 import traceback
30 30 import logging
31 31
32 32 from mercurial import ui
33 33
34 34 from sqlalchemy.orm import joinedload
35 35 from sqlalchemy.orm.session import make_transient
36 36 from sqlalchemy.exc import DatabaseError
37 37
38 38 from beaker.cache import cache_region, region_invalidate
39 39
40 40 from vcs import get_backend
41 41 from vcs.utils.helpers import get_scm
42 42 from vcs.exceptions import RepositoryError, VCSError
43 43 from vcs.utils.lazy import LazyProperty
44 44
45 45 from rhodecode import BACKENDS
46 46 from rhodecode.lib import helpers as h
47 47 from rhodecode.lib.auth import HasRepoPermissionAny
48 48 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, action_logger
49 49 from rhodecode.model import BaseModel
50 50 from rhodecode.model.user import UserModel
51 51 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
52 52 UserFollowing, UserLog
53 53 from rhodecode.model.caching_query import FromCache
54 54
55 55 log = logging.getLogger(__name__)
56 56
57 57
58 58 class UserTemp(object):
59 59 def __init__(self, user_id):
60 60 self.user_id = user_id
61 61
62 62 def __repr__(self):
63 63 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
64 64
65 65 class RepoTemp(object):
66 66 def __init__(self, repo_id):
67 67 self.repo_id = repo_id
68 68
69 69 def __repr__(self):
70 70 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
71 71
72 72 class ScmModel(BaseModel):
73 73 """Generic Scm Model
74 74 """
75 75
76 76 @LazyProperty
77 77 def repos_path(self):
78 78 """Get's the repositories root path from database
79 79 """
80 80
81 81 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
82 82
83 83 return q.ui_value
84 84
85 85 def repo_scan(self, repos_path, baseui):
86 86 """Listing of repositories in given path. This path should not be a
87 87 repository itself. Return a dictionary of repository objects
88 88
89 89 :param repos_path: path to directory containing repositories
90 90 :param baseui: baseui instance to instantiate MercurialRepostitory with
91 91 """
92 92
93 93 log.info('scanning for repositories in %s', repos_path)
94 94
95 95 if not isinstance(baseui, ui.ui):
96 96 baseui = make_ui('db')
97 97 repos_list = {}
98 98
99 99 for name, path in get_filesystem_repos(repos_path, recursive=True):
100 100 try:
101 101 if repos_list.has_key(name):
102 102 raise RepositoryError('Duplicate repository name %s '
103 103 'found in %s' % (name, path))
104 104 else:
105 105
106 106 klass = get_backend(path[0])
107 107
108 108 if path[0] == 'hg' and path[0] in BACKENDS.keys():
109 109 repos_list[name] = klass(path[1], baseui=baseui)
110 110
111 111 if path[0] == 'git' and path[0] in BACKENDS.keys():
112 112 repos_list[name] = klass(path[1])
113 113 except OSError:
114 114 continue
115 115
116 116 return repos_list
117 117
118 118 def get_repos(self, all_repos=None):
119 119 """Get all repos from db and for each repo create it's backend instance.
120 120 and fill that backed with information from database
121 121
122 122 :param all_repos: give specific repositories list, good for filtering
123 123 """
124 124
125 125 if all_repos is None:
126 126 all_repos = self.sa.query(Repository)\
127 127 .order_by(Repository.repo_name).all()
128 128
129 129 #get the repositories that should be invalidated
130 130 invalidation_list = [str(x.cache_key) for x in \
131 131 self.sa.query(CacheInvalidation.cache_key)\
132 132 .filter(CacheInvalidation.cache_active == False)\
133 133 .all()]
134 134
135 135 for r in all_repos:
136 136
137 137 repo = self.get(r.repo_name, invalidation_list)
138 138
139 139 if repo is not None:
140 140 last_change = repo.last_change
141 141 tip = h.get_changeset_safe(repo, 'tip')
142 142
143 143 tmp_d = {}
144 144 tmp_d['name'] = r.repo_name
145 145 tmp_d['name_sort'] = tmp_d['name'].lower()
146 146 tmp_d['description'] = repo.dbrepo.description
147 147 tmp_d['description_sort'] = tmp_d['description']
148 148 tmp_d['last_change'] = last_change
149 149 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
150 150 tmp_d['tip'] = tip.raw_id
151 151 tmp_d['tip_sort'] = tip.revision
152 152 tmp_d['rev'] = tip.revision
153 153 tmp_d['contact'] = repo.dbrepo.user.full_contact
154 154 tmp_d['contact_sort'] = tmp_d['contact']
155 155 tmp_d['owner_sort'] = tmp_d['contact']
156 156 tmp_d['repo_archives'] = list(repo._get_archives())
157 157 tmp_d['last_msg'] = tip.message
158 158 tmp_d['repo'] = repo
159 159 yield tmp_d
160 160
161 161 def get_repo(self, repo_name):
162 162 return self.get(repo_name)
163 163
164 164 def get(self, repo_name, invalidation_list=None):
165 165 """Get's repository from given name, creates BackendInstance and
166 166 propagates it's data from database with all additional information
167 167
168 168 :param repo_name:
169 169 :param invalidation_list: if a invalidation list is given the get
170 170 method should not manually check if this repository needs
171 171 invalidation and just invalidate the repositories in list
172 172
173 173 """
174 174 if not HasRepoPermissionAny('repository.read', 'repository.write',
175 175 'repository.admin')(repo_name, 'get repo check'):
176 176 return
177 177
178 178 #======================================================================
179 179 # CACHE FUNCTION
180 180 #======================================================================
181 181 @cache_region('long_term')
182 182 def _get_repo(repo_name):
183 183
184 184 repo_path = os.path.join(self.repos_path, repo_name)
185 185
186 186 try:
187 187 alias = get_scm(repo_path)[0]
188
189 188 log.debug('Creating instance of %s repository', alias)
190 189 backend = get_backend(alias)
191 190 except VCSError:
192 191 log.error(traceback.format_exc())
192 log.error('Perhaps this repository is in db and not in filesystem'
193 'run rescan repositories with "destroy old data "'
194 'option from admin panel')
193 195 return
194 196
195 197 if alias == 'hg':
196 198 from pylons import app_globals as g
197 199 repo = backend(repo_path, create=False, baseui=g.baseui)
198 200 #skip hidden web repository
199 201 if repo._get_hidden():
200 202 return
201 203 else:
202 204 repo = backend(repo_path, create=False)
203 205
204 206 dbrepo = self.sa.query(Repository)\
205 207 .options(joinedload(Repository.fork))\
206 208 .options(joinedload(Repository.user))\
207 209 .filter(Repository.repo_name == repo_name)\
208 210 .scalar()
209 211
210 212 make_transient(dbrepo)
211 213 if dbrepo.user:
212 214 make_transient(dbrepo.user)
213 215 if dbrepo.fork:
214 216 make_transient(dbrepo.fork)
215 217
216 218 repo.dbrepo = dbrepo
217 219 return repo
218 220
219 221 pre_invalidate = True
220 222 if invalidation_list is not None:
221 223 pre_invalidate = repo_name in invalidation_list
222 224
223 225 if pre_invalidate:
224 226 invalidate = self._should_invalidate(repo_name)
225 227
226 228 if invalidate:
227 229 log.info('invalidating cache for repository %s', repo_name)
228 230 region_invalidate(_get_repo, None, repo_name)
229 231 self._mark_invalidated(invalidate)
230 232
231 233 return _get_repo(repo_name)
232 234
233 235
234 236
235 237 def mark_for_invalidation(self, repo_name):
236 238 """Puts cache invalidation task into db for
237 239 further global cache invalidation
238 240
239 241 :param repo_name: this repo that should invalidation take place
240 242 """
241 243
242 244 log.debug('marking %s for invalidation', repo_name)
243 245 cache = self.sa.query(CacheInvalidation)\
244 246 .filter(CacheInvalidation.cache_key == repo_name).scalar()
245 247
246 248 if cache:
247 249 #mark this cache as inactive
248 250 cache.cache_active = False
249 251 else:
250 252 log.debug('cache key not found in invalidation db -> creating one')
251 253 cache = CacheInvalidation(repo_name)
252 254
253 255 try:
254 256 self.sa.add(cache)
255 257 self.sa.commit()
256 258 except (DatabaseError,):
257 259 log.error(traceback.format_exc())
258 260 self.sa.rollback()
259 261
260 262
261 263 def toggle_following_repo(self, follow_repo_id, user_id):
262 264
263 265 f = self.sa.query(UserFollowing)\
264 266 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
265 267 .filter(UserFollowing.user_id == user_id).scalar()
266 268
267 269 if f is not None:
268 270
269 271 try:
270 272 self.sa.delete(f)
271 273 self.sa.commit()
272 274 action_logger(UserTemp(user_id),
273 275 'stopped_following_repo',
274 276 RepoTemp(follow_repo_id))
275 277 return
276 278 except:
277 279 log.error(traceback.format_exc())
278 280 self.sa.rollback()
279 281 raise
280 282
281 283
282 284 try:
283 285 f = UserFollowing()
284 286 f.user_id = user_id
285 287 f.follows_repo_id = follow_repo_id
286 288 self.sa.add(f)
287 289 self.sa.commit()
288 290 action_logger(UserTemp(user_id),
289 291 'started_following_repo',
290 292 RepoTemp(follow_repo_id))
291 293 except:
292 294 log.error(traceback.format_exc())
293 295 self.sa.rollback()
294 296 raise
295 297
296 298 def toggle_following_user(self, follow_user_id , user_id):
297 299 f = self.sa.query(UserFollowing)\
298 300 .filter(UserFollowing.follows_user_id == follow_user_id)\
299 301 .filter(UserFollowing.user_id == user_id).scalar()
300 302
301 303 if f is not None:
302 304 try:
303 305 self.sa.delete(f)
304 306 self.sa.commit()
305 307 return
306 308 except:
307 309 log.error(traceback.format_exc())
308 310 self.sa.rollback()
309 311 raise
310 312
311 313 try:
312 314 f = UserFollowing()
313 315 f.user_id = user_id
314 316 f.follows_user_id = follow_user_id
315 317 self.sa.add(f)
316 318 self.sa.commit()
317 319 except:
318 320 log.error(traceback.format_exc())
319 321 self.sa.rollback()
320 322 raise
321 323
322 324 def is_following_repo(self, repo_name, user_id, cache=False):
323 325 r = self.sa.query(Repository)\
324 326 .filter(Repository.repo_name == repo_name).scalar()
325 327
326 328 f = self.sa.query(UserFollowing)\
327 329 .filter(UserFollowing.follows_repository == r)\
328 330 .filter(UserFollowing.user_id == user_id).scalar()
329 331
330 332 return f is not None
331 333
332 334 def is_following_user(self, username, user_id, cache=False):
333 335 u = UserModel(self.sa).get_by_username(username)
334 336
335 337 f = self.sa.query(UserFollowing)\
336 338 .filter(UserFollowing.follows_user == u)\
337 339 .filter(UserFollowing.user_id == user_id).scalar()
338 340
339 341 return f is not None
340 342
341 343 def get_followers(self, repo_id):
342 344 return self.sa.query(UserFollowing)\
343 345 .filter(UserFollowing.follows_repo_id == repo_id).count()
344 346
345 347 def get_forks(self, repo_id):
346 348 return self.sa.query(Repository)\
347 349 .filter(Repository.fork_id == repo_id).count()
348 350
349 351
350 352 def get_unread_journal(self):
351 353 return self.sa.query(UserLog).count()
352 354
353 355
354 356 def _should_invalidate(self, repo_name):
355 357 """Looks up database for invalidation signals for this repo_name
356 358
357 359 :param repo_name:
358 360 """
359 361
360 362 ret = self.sa.query(CacheInvalidation)\
361 363 .options(FromCache('sql_cache_short',
362 364 'get_invalidation_%s' % repo_name))\
363 365 .filter(CacheInvalidation.cache_key == repo_name)\
364 366 .filter(CacheInvalidation.cache_active == False)\
365 367 .scalar()
366 368
367 369 return ret
368 370
369 371 def _mark_invalidated(self, cache_key):
370 372 """ Marks all occurences of cache to invaldation as already invalidated
371 373
372 374 :param cache_key:
373 375 """
374 376
375 377 if cache_key:
376 378 log.debug('marking %s as already invalidated', cache_key)
377 379 try:
378 380 cache_key.cache_active = True
379 381 self.sa.add(cache_key)
380 382 self.sa.commit()
381 383 except (DatabaseError,):
382 384 log.error(traceback.format_exc())
383 385 self.sa.rollback()
384 386
General Comments 0
You need to be logged in to leave comments. Login now