##// END OF EJS Templates
fix reset statistics call if there are no statistics yet
marcink -
r3314:059efaea beta
parent child Browse files
Show More
@@ -1,705 +1,705 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.repo
3 rhodecode.model.repo
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 Repository model for rhodecode
6 Repository model for rhodecode
7
7
8 :created_on: Jun 5, 2010
8 :created_on: Jun 5, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 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 from __future__ import with_statement
25 from __future__ import with_statement
26 import os
26 import os
27 import shutil
27 import shutil
28 import logging
28 import logging
29 import traceback
29 import traceback
30 from datetime import datetime
30 from datetime import datetime
31
31
32 from rhodecode.lib.vcs.backends import get_backend
32 from rhodecode.lib.vcs.backends import get_backend
33 from rhodecode.lib.compat import json
33 from rhodecode.lib.compat import json
34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\
34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\
35 remove_prefix
35 remove_prefix
36 from rhodecode.lib.caching_query import FromCache
36 from rhodecode.lib.caching_query import FromCache
37 from rhodecode.lib.hooks import log_create_repository, log_delete_repository
37 from rhodecode.lib.hooks import log_create_repository, log_delete_repository
38
38
39 from rhodecode.model import BaseModel
39 from rhodecode.model import BaseModel
40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
41 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
41 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
42 RhodeCodeSetting, RepositoryField
42 RhodeCodeSetting, RepositoryField
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.vcs.backends.base import EmptyChangeset
45 from rhodecode.lib.vcs.backends.base import EmptyChangeset
46
46
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50
50
51 class RepoModel(BaseModel):
51 class RepoModel(BaseModel):
52
52
53 cls = Repository
53 cls = Repository
54 URL_SEPARATOR = Repository.url_sep()
54 URL_SEPARATOR = Repository.url_sep()
55
55
56 def __get_users_group(self, users_group):
56 def __get_users_group(self, users_group):
57 return self._get_instance(UsersGroup, users_group,
57 return self._get_instance(UsersGroup, users_group,
58 callback=UsersGroup.get_by_group_name)
58 callback=UsersGroup.get_by_group_name)
59
59
60 def _get_repos_group(self, repos_group):
60 def _get_repos_group(self, repos_group):
61 return self._get_instance(RepoGroup, repos_group,
61 return self._get_instance(RepoGroup, repos_group,
62 callback=RepoGroup.get_by_group_name)
62 callback=RepoGroup.get_by_group_name)
63
63
64 @LazyProperty
64 @LazyProperty
65 def repos_path(self):
65 def repos_path(self):
66 """
66 """
67 Get's the repositories root path from database
67 Get's the repositories root path from database
68 """
68 """
69
69
70 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
70 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
71 return q.ui_value
71 return q.ui_value
72
72
73 def get(self, repo_id, cache=False):
73 def get(self, repo_id, cache=False):
74 repo = self.sa.query(Repository)\
74 repo = self.sa.query(Repository)\
75 .filter(Repository.repo_id == repo_id)
75 .filter(Repository.repo_id == repo_id)
76
76
77 if cache:
77 if cache:
78 repo = repo.options(FromCache("sql_cache_short",
78 repo = repo.options(FromCache("sql_cache_short",
79 "get_repo_%s" % repo_id))
79 "get_repo_%s" % repo_id))
80 return repo.scalar()
80 return repo.scalar()
81
81
82 def get_repo(self, repository):
82 def get_repo(self, repository):
83 return self._get_repo(repository)
83 return self._get_repo(repository)
84
84
85 def get_by_repo_name(self, repo_name, cache=False):
85 def get_by_repo_name(self, repo_name, cache=False):
86 repo = self.sa.query(Repository)\
86 repo = self.sa.query(Repository)\
87 .filter(Repository.repo_name == repo_name)
87 .filter(Repository.repo_name == repo_name)
88
88
89 if cache:
89 if cache:
90 repo = repo.options(FromCache("sql_cache_short",
90 repo = repo.options(FromCache("sql_cache_short",
91 "get_repo_%s" % repo_name))
91 "get_repo_%s" % repo_name))
92 return repo.scalar()
92 return repo.scalar()
93
93
94 def get_all_user_repos(self, user):
94 def get_all_user_repos(self, user):
95 """
95 """
96 Get's all repositories that user have at least read access
96 Get's all repositories that user have at least read access
97
97
98 :param user:
98 :param user:
99 :type user:
99 :type user:
100 """
100 """
101 from rhodecode.lib.auth import AuthUser
101 from rhodecode.lib.auth import AuthUser
102 user = self._get_user(user)
102 user = self._get_user(user)
103 repos = AuthUser(user_id=user.user_id).permissions['repositories']
103 repos = AuthUser(user_id=user.user_id).permissions['repositories']
104 access_check = lambda r: r[1] in ['repository.read',
104 access_check = lambda r: r[1] in ['repository.read',
105 'repository.write',
105 'repository.write',
106 'repository.admin']
106 'repository.admin']
107 repos = [x[0] for x in filter(access_check, repos.items())]
107 repos = [x[0] for x in filter(access_check, repos.items())]
108 return Repository.query().filter(Repository.repo_name.in_(repos))
108 return Repository.query().filter(Repository.repo_name.in_(repos))
109
109
110 def get_users_js(self):
110 def get_users_js(self):
111 users = self.sa.query(User).filter(User.active == True).all()
111 users = self.sa.query(User).filter(User.active == True).all()
112 return json.dumps([
112 return json.dumps([
113 {
113 {
114 'id': u.user_id,
114 'id': u.user_id,
115 'fname': u.name,
115 'fname': u.name,
116 'lname': u.lastname,
116 'lname': u.lastname,
117 'nname': u.username,
117 'nname': u.username,
118 'gravatar_lnk': h.gravatar_url(u.email, 14)
118 'gravatar_lnk': h.gravatar_url(u.email, 14)
119 } for u in users]
119 } for u in users]
120 )
120 )
121
121
122 def get_users_groups_js(self):
122 def get_users_groups_js(self):
123 users_groups = self.sa.query(UsersGroup)\
123 users_groups = self.sa.query(UsersGroup)\
124 .filter(UsersGroup.users_group_active == True).all()
124 .filter(UsersGroup.users_group_active == True).all()
125
125
126 return json.dumps([
126 return json.dumps([
127 {
127 {
128 'id': gr.users_group_id,
128 'id': gr.users_group_id,
129 'grname': gr.users_group_name,
129 'grname': gr.users_group_name,
130 'grmembers': len(gr.members),
130 'grmembers': len(gr.members),
131 } for gr in users_groups]
131 } for gr in users_groups]
132 )
132 )
133
133
134 @classmethod
134 @classmethod
135 def _render_datatable(cls, tmpl, *args, **kwargs):
135 def _render_datatable(cls, tmpl, *args, **kwargs):
136 import rhodecode
136 import rhodecode
137 from pylons import tmpl_context as c
137 from pylons import tmpl_context as c
138 from pylons.i18n.translation import _
138 from pylons.i18n.translation import _
139
139
140 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
140 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
141 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
141 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
142
142
143 tmpl = template.get_def(tmpl)
143 tmpl = template.get_def(tmpl)
144 kwargs.update(dict(_=_, h=h, c=c))
144 kwargs.update(dict(_=_, h=h, c=c))
145 return tmpl.render(*args, **kwargs)
145 return tmpl.render(*args, **kwargs)
146
146
147 @classmethod
147 @classmethod
148 def update_repoinfo(cls, repositories=None):
148 def update_repoinfo(cls, repositories=None):
149 if not repositories:
149 if not repositories:
150 repositories = Repository.getAll()
150 repositories = Repository.getAll()
151 for repo in repositories:
151 for repo in repositories:
152 scm_repo = repo.scm_instance_no_cache
152 scm_repo = repo.scm_instance_no_cache
153 last_cs = EmptyChangeset()
153 last_cs = EmptyChangeset()
154 if scm_repo:
154 if scm_repo:
155 last_cs = scm_repo.get_changeset()
155 last_cs = scm_repo.get_changeset()
156 repo.update_changeset_cache(last_cs)
156 repo.update_changeset_cache(last_cs)
157
157
158 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
158 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
159 super_user_actions=False):
159 super_user_actions=False):
160 _render = self._render_datatable
160 _render = self._render_datatable
161
161
162 def quick_menu(repo_name):
162 def quick_menu(repo_name):
163 return _render('quick_menu', repo_name)
163 return _render('quick_menu', repo_name)
164
164
165 def repo_lnk(name, rtype, private, fork_of):
165 def repo_lnk(name, rtype, private, fork_of):
166 return _render('repo_name', name, rtype, private, fork_of,
166 return _render('repo_name', name, rtype, private, fork_of,
167 short_name=not admin, admin=False)
167 short_name=not admin, admin=False)
168
168
169 def last_change(last_change):
169 def last_change(last_change):
170 return _render("last_change", last_change)
170 return _render("last_change", last_change)
171
171
172 def rss_lnk(repo_name):
172 def rss_lnk(repo_name):
173 return _render("rss", repo_name)
173 return _render("rss", repo_name)
174
174
175 def atom_lnk(repo_name):
175 def atom_lnk(repo_name):
176 return _render("atom", repo_name)
176 return _render("atom", repo_name)
177
177
178 def last_rev(repo_name, cs_cache):
178 def last_rev(repo_name, cs_cache):
179 return _render('revision', repo_name, cs_cache.get('revision'),
179 return _render('revision', repo_name, cs_cache.get('revision'),
180 cs_cache.get('raw_id'), cs_cache.get('author'),
180 cs_cache.get('raw_id'), cs_cache.get('author'),
181 cs_cache.get('message'))
181 cs_cache.get('message'))
182
182
183 def desc(desc):
183 def desc(desc):
184 from pylons import tmpl_context as c
184 from pylons import tmpl_context as c
185 if c.visual.stylify_metatags:
185 if c.visual.stylify_metatags:
186 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
186 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
187 else:
187 else:
188 return h.urlify_text(h.truncate(desc, 60))
188 return h.urlify_text(h.truncate(desc, 60))
189
189
190 def repo_actions(repo_name):
190 def repo_actions(repo_name):
191 return _render('repo_actions', repo_name, super_user_actions)
191 return _render('repo_actions', repo_name, super_user_actions)
192
192
193 def owner_actions(user_id, username):
193 def owner_actions(user_id, username):
194 return _render('user_name', user_id, username)
194 return _render('user_name', user_id, username)
195
195
196 repos_data = []
196 repos_data = []
197 for repo in repos_list:
197 for repo in repos_list:
198 if perm_check:
198 if perm_check:
199 # check permission at this level
199 # check permission at this level
200 if not HasRepoPermissionAny(
200 if not HasRepoPermissionAny(
201 'repository.read', 'repository.write', 'repository.admin'
201 'repository.read', 'repository.write', 'repository.admin'
202 )(repo.repo_name, 'get_repos_as_dict check'):
202 )(repo.repo_name, 'get_repos_as_dict check'):
203 continue
203 continue
204 cs_cache = repo.changeset_cache
204 cs_cache = repo.changeset_cache
205 row = {
205 row = {
206 "menu": quick_menu(repo.repo_name),
206 "menu": quick_menu(repo.repo_name),
207 "raw_name": repo.repo_name.lower(),
207 "raw_name": repo.repo_name.lower(),
208 "name": repo_lnk(repo.repo_name, repo.repo_type,
208 "name": repo_lnk(repo.repo_name, repo.repo_type,
209 repo.private, repo.fork),
209 repo.private, repo.fork),
210 "last_change": last_change(repo.last_db_change),
210 "last_change": last_change(repo.last_db_change),
211 "last_changeset": last_rev(repo.repo_name, cs_cache),
211 "last_changeset": last_rev(repo.repo_name, cs_cache),
212 "raw_tip": cs_cache.get('revision'),
212 "raw_tip": cs_cache.get('revision'),
213 "desc": desc(repo.description),
213 "desc": desc(repo.description),
214 "owner": h.person(repo.user.username),
214 "owner": h.person(repo.user.username),
215 "rss": rss_lnk(repo.repo_name),
215 "rss": rss_lnk(repo.repo_name),
216 "atom": atom_lnk(repo.repo_name),
216 "atom": atom_lnk(repo.repo_name),
217
217
218 }
218 }
219 if admin:
219 if admin:
220 row.update({
220 row.update({
221 "action": repo_actions(repo.repo_name),
221 "action": repo_actions(repo.repo_name),
222 "owner": owner_actions(repo.user.user_id,
222 "owner": owner_actions(repo.user.user_id,
223 h.person(repo.user.username))
223 h.person(repo.user.username))
224 })
224 })
225 repos_data.append(row)
225 repos_data.append(row)
226
226
227 return {
227 return {
228 "totalRecords": len(repos_list),
228 "totalRecords": len(repos_list),
229 "startIndex": 0,
229 "startIndex": 0,
230 "sort": "name",
230 "sort": "name",
231 "dir": "asc",
231 "dir": "asc",
232 "records": repos_data
232 "records": repos_data
233 }
233 }
234
234
235 def _get_defaults(self, repo_name):
235 def _get_defaults(self, repo_name):
236 """
236 """
237 Get's information about repository, and returns a dict for
237 Get's information about repository, and returns a dict for
238 usage in forms
238 usage in forms
239
239
240 :param repo_name:
240 :param repo_name:
241 """
241 """
242
242
243 repo_info = Repository.get_by_repo_name(repo_name)
243 repo_info = Repository.get_by_repo_name(repo_name)
244
244
245 if repo_info is None:
245 if repo_info is None:
246 return None
246 return None
247
247
248 defaults = repo_info.get_dict()
248 defaults = repo_info.get_dict()
249 group, repo_name = repo_info.groups_and_repo
249 group, repo_name = repo_info.groups_and_repo
250 defaults['repo_name'] = repo_name
250 defaults['repo_name'] = repo_name
251 defaults['repo_group'] = getattr(group[-1] if group else None,
251 defaults['repo_group'] = getattr(group[-1] if group else None,
252 'group_id', None)
252 'group_id', None)
253
253
254 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
254 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
255 (1, 'repo_description'), (1, 'repo_enable_locking'),
255 (1, 'repo_description'), (1, 'repo_enable_locking'),
256 (1, 'repo_landing_rev'), (0, 'clone_uri'),
256 (1, 'repo_landing_rev'), (0, 'clone_uri'),
257 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
257 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
258 attr = k
258 attr = k
259 if strip:
259 if strip:
260 attr = remove_prefix(k, 'repo_')
260 attr = remove_prefix(k, 'repo_')
261
261
262 defaults[k] = defaults[attr]
262 defaults[k] = defaults[attr]
263
263
264 # fill owner
264 # fill owner
265 if repo_info.user:
265 if repo_info.user:
266 defaults.update({'user': repo_info.user.username})
266 defaults.update({'user': repo_info.user.username})
267 else:
267 else:
268 replacement_user = User.query().filter(User.admin ==
268 replacement_user = User.query().filter(User.admin ==
269 True).first().username
269 True).first().username
270 defaults.update({'user': replacement_user})
270 defaults.update({'user': replacement_user})
271
271
272 # fill repository users
272 # fill repository users
273 for p in repo_info.repo_to_perm:
273 for p in repo_info.repo_to_perm:
274 defaults.update({'u_perm_%s' % p.user.username:
274 defaults.update({'u_perm_%s' % p.user.username:
275 p.permission.permission_name})
275 p.permission.permission_name})
276
276
277 # fill repository groups
277 # fill repository groups
278 for p in repo_info.users_group_to_perm:
278 for p in repo_info.users_group_to_perm:
279 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
279 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
280 p.permission.permission_name})
280 p.permission.permission_name})
281
281
282 return defaults
282 return defaults
283
283
284 def update(self, org_repo_name, **kwargs):
284 def update(self, org_repo_name, **kwargs):
285 try:
285 try:
286 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
286 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
287
287
288 # update permissions
288 # update permissions
289 for member, perm, member_type in kwargs['perms_updates']:
289 for member, perm, member_type in kwargs['perms_updates']:
290 if member_type == 'user':
290 if member_type == 'user':
291 # this updates existing one
291 # this updates existing one
292 RepoModel().grant_user_permission(
292 RepoModel().grant_user_permission(
293 repo=cur_repo, user=member, perm=perm
293 repo=cur_repo, user=member, perm=perm
294 )
294 )
295 else:
295 else:
296 RepoModel().grant_users_group_permission(
296 RepoModel().grant_users_group_permission(
297 repo=cur_repo, group_name=member, perm=perm
297 repo=cur_repo, group_name=member, perm=perm
298 )
298 )
299 # set new permissions
299 # set new permissions
300 for member, perm, member_type in kwargs['perms_new']:
300 for member, perm, member_type in kwargs['perms_new']:
301 if member_type == 'user':
301 if member_type == 'user':
302 RepoModel().grant_user_permission(
302 RepoModel().grant_user_permission(
303 repo=cur_repo, user=member, perm=perm
303 repo=cur_repo, user=member, perm=perm
304 )
304 )
305 else:
305 else:
306 RepoModel().grant_users_group_permission(
306 RepoModel().grant_users_group_permission(
307 repo=cur_repo, group_name=member, perm=perm
307 repo=cur_repo, group_name=member, perm=perm
308 )
308 )
309
309
310 if 'user' in kwargs:
310 if 'user' in kwargs:
311 cur_repo.user = User.get_by_username(kwargs['user'])
311 cur_repo.user = User.get_by_username(kwargs['user'])
312
312
313 if 'repo_group' in kwargs:
313 if 'repo_group' in kwargs:
314 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
314 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
315
315
316 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
316 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
317 (1, 'repo_description'), (1, 'repo_enable_locking'),
317 (1, 'repo_description'), (1, 'repo_enable_locking'),
318 (1, 'repo_landing_rev'), (0, 'clone_uri'),
318 (1, 'repo_landing_rev'), (0, 'clone_uri'),
319 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
319 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
320 if k in kwargs:
320 if k in kwargs:
321 val = kwargs[k]
321 val = kwargs[k]
322 if strip:
322 if strip:
323 k = remove_prefix(k, 'repo_')
323 k = remove_prefix(k, 'repo_')
324 setattr(cur_repo, k, val)
324 setattr(cur_repo, k, val)
325
325
326 new_name = cur_repo.get_new_name(kwargs['repo_name'])
326 new_name = cur_repo.get_new_name(kwargs['repo_name'])
327 cur_repo.repo_name = new_name
327 cur_repo.repo_name = new_name
328
328
329 #handle extra fields
329 #handle extra fields
330 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
330 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
331 k = RepositoryField.un_prefix_key(field)
331 k = RepositoryField.un_prefix_key(field)
332 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
332 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
333 if ex_field:
333 if ex_field:
334 ex_field.field_value = kwargs[field]
334 ex_field.field_value = kwargs[field]
335 self.sa.add(ex_field)
335 self.sa.add(ex_field)
336 self.sa.add(cur_repo)
336 self.sa.add(cur_repo)
337
337
338 if org_repo_name != new_name:
338 if org_repo_name != new_name:
339 # rename repository
339 # rename repository
340 self.__rename_repo(old=org_repo_name, new=new_name)
340 self.__rename_repo(old=org_repo_name, new=new_name)
341
341
342 return cur_repo
342 return cur_repo
343 except:
343 except:
344 log.error(traceback.format_exc())
344 log.error(traceback.format_exc())
345 raise
345 raise
346
346
347 def create_repo(self, repo_name, repo_type, description, owner,
347 def create_repo(self, repo_name, repo_type, description, owner,
348 private=False, clone_uri=None, repos_group=None,
348 private=False, clone_uri=None, repos_group=None,
349 landing_rev='tip', just_db=False, fork_of=None,
349 landing_rev='tip', just_db=False, fork_of=None,
350 copy_fork_permissions=False, enable_statistics=False,
350 copy_fork_permissions=False, enable_statistics=False,
351 enable_locking=False, enable_downloads=False):
351 enable_locking=False, enable_downloads=False):
352 """
352 """
353 Create repository
353 Create repository
354
354
355 """
355 """
356 from rhodecode.model.scm import ScmModel
356 from rhodecode.model.scm import ScmModel
357
357
358 owner = self._get_user(owner)
358 owner = self._get_user(owner)
359 fork_of = self._get_repo(fork_of)
359 fork_of = self._get_repo(fork_of)
360 repos_group = self._get_repos_group(repos_group)
360 repos_group = self._get_repos_group(repos_group)
361 try:
361 try:
362
362
363 # repo name is just a name of repository
363 # repo name is just a name of repository
364 # while repo_name_full is a full qualified name that is combined
364 # while repo_name_full is a full qualified name that is combined
365 # with name and path of group
365 # with name and path of group
366 repo_name_full = repo_name
366 repo_name_full = repo_name
367 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
367 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
368
368
369 new_repo = Repository()
369 new_repo = Repository()
370 new_repo.enable_statistics = False
370 new_repo.enable_statistics = False
371 new_repo.repo_name = repo_name_full
371 new_repo.repo_name = repo_name_full
372 new_repo.repo_type = repo_type
372 new_repo.repo_type = repo_type
373 new_repo.user = owner
373 new_repo.user = owner
374 new_repo.group = repos_group
374 new_repo.group = repos_group
375 new_repo.description = description or repo_name
375 new_repo.description = description or repo_name
376 new_repo.private = private
376 new_repo.private = private
377 new_repo.clone_uri = clone_uri
377 new_repo.clone_uri = clone_uri
378 new_repo.landing_rev = landing_rev
378 new_repo.landing_rev = landing_rev
379
379
380 new_repo.enable_statistics = enable_statistics
380 new_repo.enable_statistics = enable_statistics
381 new_repo.enable_locking = enable_locking
381 new_repo.enable_locking = enable_locking
382 new_repo.enable_downloads = enable_downloads
382 new_repo.enable_downloads = enable_downloads
383
383
384 if repos_group:
384 if repos_group:
385 new_repo.enable_locking = repos_group.enable_locking
385 new_repo.enable_locking = repos_group.enable_locking
386
386
387 if fork_of:
387 if fork_of:
388 parent_repo = fork_of
388 parent_repo = fork_of
389 new_repo.fork = parent_repo
389 new_repo.fork = parent_repo
390
390
391 self.sa.add(new_repo)
391 self.sa.add(new_repo)
392
392
393 def _create_default_perms():
393 def _create_default_perms():
394 # create default permission
394 # create default permission
395 repo_to_perm = UserRepoToPerm()
395 repo_to_perm = UserRepoToPerm()
396 default = 'repository.read'
396 default = 'repository.read'
397 for p in User.get_by_username('default').user_perms:
397 for p in User.get_by_username('default').user_perms:
398 if p.permission.permission_name.startswith('repository.'):
398 if p.permission.permission_name.startswith('repository.'):
399 default = p.permission.permission_name
399 default = p.permission.permission_name
400 break
400 break
401
401
402 default_perm = 'repository.none' if private else default
402 default_perm = 'repository.none' if private else default
403
403
404 repo_to_perm.permission_id = self.sa.query(Permission)\
404 repo_to_perm.permission_id = self.sa.query(Permission)\
405 .filter(Permission.permission_name == default_perm)\
405 .filter(Permission.permission_name == default_perm)\
406 .one().permission_id
406 .one().permission_id
407
407
408 repo_to_perm.repository = new_repo
408 repo_to_perm.repository = new_repo
409 repo_to_perm.user_id = User.get_by_username('default').user_id
409 repo_to_perm.user_id = User.get_by_username('default').user_id
410
410
411 self.sa.add(repo_to_perm)
411 self.sa.add(repo_to_perm)
412
412
413 if fork_of:
413 if fork_of:
414 if copy_fork_permissions:
414 if copy_fork_permissions:
415 repo = fork_of
415 repo = fork_of
416 user_perms = UserRepoToPerm.query()\
416 user_perms = UserRepoToPerm.query()\
417 .filter(UserRepoToPerm.repository == repo).all()
417 .filter(UserRepoToPerm.repository == repo).all()
418 group_perms = UsersGroupRepoToPerm.query()\
418 group_perms = UsersGroupRepoToPerm.query()\
419 .filter(UsersGroupRepoToPerm.repository == repo).all()
419 .filter(UsersGroupRepoToPerm.repository == repo).all()
420
420
421 for perm in user_perms:
421 for perm in user_perms:
422 UserRepoToPerm.create(perm.user, new_repo,
422 UserRepoToPerm.create(perm.user, new_repo,
423 perm.permission)
423 perm.permission)
424
424
425 for perm in group_perms:
425 for perm in group_perms:
426 UsersGroupRepoToPerm.create(perm.users_group, new_repo,
426 UsersGroupRepoToPerm.create(perm.users_group, new_repo,
427 perm.permission)
427 perm.permission)
428 else:
428 else:
429 _create_default_perms()
429 _create_default_perms()
430 else:
430 else:
431 _create_default_perms()
431 _create_default_perms()
432
432
433 if not just_db:
433 if not just_db:
434 self.__create_repo(repo_name, repo_type,
434 self.__create_repo(repo_name, repo_type,
435 repos_group,
435 repos_group,
436 clone_uri)
436 clone_uri)
437 log_create_repository(new_repo.get_dict(),
437 log_create_repository(new_repo.get_dict(),
438 created_by=owner.username)
438 created_by=owner.username)
439
439
440 # now automatically start following this repository as owner
440 # now automatically start following this repository as owner
441 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
441 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
442 owner.user_id)
442 owner.user_id)
443 return new_repo
443 return new_repo
444 except:
444 except:
445 log.error(traceback.format_exc())
445 log.error(traceback.format_exc())
446 raise
446 raise
447
447
448 def create(self, form_data, cur_user, just_db=False, fork=None):
448 def create(self, form_data, cur_user, just_db=False, fork=None):
449 """
449 """
450 Backward compatibility function, just a wrapper on top of create_repo
450 Backward compatibility function, just a wrapper on top of create_repo
451
451
452 :param form_data:
452 :param form_data:
453 :param cur_user:
453 :param cur_user:
454 :param just_db:
454 :param just_db:
455 :param fork:
455 :param fork:
456 """
456 """
457 owner = cur_user
457 owner = cur_user
458 repo_name = form_data['repo_name_full']
458 repo_name = form_data['repo_name_full']
459 repo_type = form_data['repo_type']
459 repo_type = form_data['repo_type']
460 description = form_data['repo_description']
460 description = form_data['repo_description']
461 private = form_data['repo_private']
461 private = form_data['repo_private']
462 clone_uri = form_data.get('clone_uri')
462 clone_uri = form_data.get('clone_uri')
463 repos_group = form_data['repo_group']
463 repos_group = form_data['repo_group']
464 landing_rev = form_data['repo_landing_rev']
464 landing_rev = form_data['repo_landing_rev']
465 copy_fork_permissions = form_data.get('copy_permissions')
465 copy_fork_permissions = form_data.get('copy_permissions')
466 fork_of = form_data.get('fork_parent_id')
466 fork_of = form_data.get('fork_parent_id')
467
467
468 ## repo creation defaults, private and repo_type are filled in form
468 ## repo creation defaults, private and repo_type are filled in form
469 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
469 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
470 enable_statistics = defs.get('repo_enable_statistics')
470 enable_statistics = defs.get('repo_enable_statistics')
471 enable_locking = defs.get('repo_enable_locking')
471 enable_locking = defs.get('repo_enable_locking')
472 enable_downloads = defs.get('repo_enable_downloads')
472 enable_downloads = defs.get('repo_enable_downloads')
473
473
474 return self.create_repo(
474 return self.create_repo(
475 repo_name, repo_type, description, owner, private, clone_uri,
475 repo_name, repo_type, description, owner, private, clone_uri,
476 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
476 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
477 enable_statistics, enable_locking, enable_downloads
477 enable_statistics, enable_locking, enable_downloads
478 )
478 )
479
479
480 def create_fork(self, form_data, cur_user):
480 def create_fork(self, form_data, cur_user):
481 """
481 """
482 Simple wrapper into executing celery task for fork creation
482 Simple wrapper into executing celery task for fork creation
483
483
484 :param form_data:
484 :param form_data:
485 :param cur_user:
485 :param cur_user:
486 """
486 """
487 from rhodecode.lib.celerylib import tasks, run_task
487 from rhodecode.lib.celerylib import tasks, run_task
488 run_task(tasks.create_repo_fork, form_data, cur_user)
488 run_task(tasks.create_repo_fork, form_data, cur_user)
489
489
490 def delete(self, repo):
490 def delete(self, repo):
491 repo = self._get_repo(repo)
491 repo = self._get_repo(repo)
492 if repo:
492 if repo:
493 old_repo_dict = repo.get_dict()
493 old_repo_dict = repo.get_dict()
494 owner = repo.user
494 owner = repo.user
495 try:
495 try:
496 self.sa.delete(repo)
496 self.sa.delete(repo)
497 self.__delete_repo(repo)
497 self.__delete_repo(repo)
498 log_delete_repository(old_repo_dict,
498 log_delete_repository(old_repo_dict,
499 deleted_by=owner.username)
499 deleted_by=owner.username)
500 except:
500 except:
501 log.error(traceback.format_exc())
501 log.error(traceback.format_exc())
502 raise
502 raise
503
503
504 def grant_user_permission(self, repo, user, perm):
504 def grant_user_permission(self, repo, user, perm):
505 """
505 """
506 Grant permission for user on given repository, or update existing one
506 Grant permission for user on given repository, or update existing one
507 if found
507 if found
508
508
509 :param repo: Instance of Repository, repository_id, or repository name
509 :param repo: Instance of Repository, repository_id, or repository name
510 :param user: Instance of User, user_id or username
510 :param user: Instance of User, user_id or username
511 :param perm: Instance of Permission, or permission_name
511 :param perm: Instance of Permission, or permission_name
512 """
512 """
513 user = self._get_user(user)
513 user = self._get_user(user)
514 repo = self._get_repo(repo)
514 repo = self._get_repo(repo)
515 permission = self._get_perm(perm)
515 permission = self._get_perm(perm)
516
516
517 # check if we have that permission already
517 # check if we have that permission already
518 obj = self.sa.query(UserRepoToPerm)\
518 obj = self.sa.query(UserRepoToPerm)\
519 .filter(UserRepoToPerm.user == user)\
519 .filter(UserRepoToPerm.user == user)\
520 .filter(UserRepoToPerm.repository == repo)\
520 .filter(UserRepoToPerm.repository == repo)\
521 .scalar()
521 .scalar()
522 if obj is None:
522 if obj is None:
523 # create new !
523 # create new !
524 obj = UserRepoToPerm()
524 obj = UserRepoToPerm()
525 obj.repository = repo
525 obj.repository = repo
526 obj.user = user
526 obj.user = user
527 obj.permission = permission
527 obj.permission = permission
528 self.sa.add(obj)
528 self.sa.add(obj)
529 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
529 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
530
530
531 def revoke_user_permission(self, repo, user):
531 def revoke_user_permission(self, repo, user):
532 """
532 """
533 Revoke permission for user on given repository
533 Revoke permission for user on given repository
534
534
535 :param repo: Instance of Repository, repository_id, or repository name
535 :param repo: Instance of Repository, repository_id, or repository name
536 :param user: Instance of User, user_id or username
536 :param user: Instance of User, user_id or username
537 """
537 """
538
538
539 user = self._get_user(user)
539 user = self._get_user(user)
540 repo = self._get_repo(repo)
540 repo = self._get_repo(repo)
541
541
542 obj = self.sa.query(UserRepoToPerm)\
542 obj = self.sa.query(UserRepoToPerm)\
543 .filter(UserRepoToPerm.repository == repo)\
543 .filter(UserRepoToPerm.repository == repo)\
544 .filter(UserRepoToPerm.user == user)\
544 .filter(UserRepoToPerm.user == user)\
545 .scalar()
545 .scalar()
546 if obj:
546 if obj:
547 self.sa.delete(obj)
547 self.sa.delete(obj)
548 log.debug('Revoked perm on %s on %s' % (repo, user))
548 log.debug('Revoked perm on %s on %s' % (repo, user))
549
549
550 def grant_users_group_permission(self, repo, group_name, perm):
550 def grant_users_group_permission(self, repo, group_name, perm):
551 """
551 """
552 Grant permission for users group on given repository, or update
552 Grant permission for users group on given repository, or update
553 existing one if found
553 existing one if found
554
554
555 :param repo: Instance of Repository, repository_id, or repository name
555 :param repo: Instance of Repository, repository_id, or repository name
556 :param group_name: Instance of UserGroup, users_group_id,
556 :param group_name: Instance of UserGroup, users_group_id,
557 or users group name
557 or users group name
558 :param perm: Instance of Permission, or permission_name
558 :param perm: Instance of Permission, or permission_name
559 """
559 """
560 repo = self._get_repo(repo)
560 repo = self._get_repo(repo)
561 group_name = self.__get_users_group(group_name)
561 group_name = self.__get_users_group(group_name)
562 permission = self._get_perm(perm)
562 permission = self._get_perm(perm)
563
563
564 # check if we have that permission already
564 # check if we have that permission already
565 obj = self.sa.query(UsersGroupRepoToPerm)\
565 obj = self.sa.query(UsersGroupRepoToPerm)\
566 .filter(UsersGroupRepoToPerm.users_group == group_name)\
566 .filter(UsersGroupRepoToPerm.users_group == group_name)\
567 .filter(UsersGroupRepoToPerm.repository == repo)\
567 .filter(UsersGroupRepoToPerm.repository == repo)\
568 .scalar()
568 .scalar()
569
569
570 if obj is None:
570 if obj is None:
571 # create new
571 # create new
572 obj = UsersGroupRepoToPerm()
572 obj = UsersGroupRepoToPerm()
573
573
574 obj.repository = repo
574 obj.repository = repo
575 obj.users_group = group_name
575 obj.users_group = group_name
576 obj.permission = permission
576 obj.permission = permission
577 self.sa.add(obj)
577 self.sa.add(obj)
578 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
578 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
579
579
580 def revoke_users_group_permission(self, repo, group_name):
580 def revoke_users_group_permission(self, repo, group_name):
581 """
581 """
582 Revoke permission for users group on given repository
582 Revoke permission for users group on given repository
583
583
584 :param repo: Instance of Repository, repository_id, or repository name
584 :param repo: Instance of Repository, repository_id, or repository name
585 :param group_name: Instance of UserGroup, users_group_id,
585 :param group_name: Instance of UserGroup, users_group_id,
586 or users group name
586 or users group name
587 """
587 """
588 repo = self._get_repo(repo)
588 repo = self._get_repo(repo)
589 group_name = self.__get_users_group(group_name)
589 group_name = self.__get_users_group(group_name)
590
590
591 obj = self.sa.query(UsersGroupRepoToPerm)\
591 obj = self.sa.query(UsersGroupRepoToPerm)\
592 .filter(UsersGroupRepoToPerm.repository == repo)\
592 .filter(UsersGroupRepoToPerm.repository == repo)\
593 .filter(UsersGroupRepoToPerm.users_group == group_name)\
593 .filter(UsersGroupRepoToPerm.users_group == group_name)\
594 .scalar()
594 .scalar()
595 if obj:
595 if obj:
596 self.sa.delete(obj)
596 self.sa.delete(obj)
597 log.debug('Revoked perm to %s on %s' % (repo, group_name))
597 log.debug('Revoked perm to %s on %s' % (repo, group_name))
598
598
599 def delete_stats(self, repo_name):
599 def delete_stats(self, repo_name):
600 """
600 """
601 removes stats for given repo
601 removes stats for given repo
602
602
603 :param repo_name:
603 :param repo_name:
604 """
604 """
605 repo = self._get_repo(repo_name)
605 try:
606 try:
606 obj = self.sa.query(Statistics)\
607 obj = self.sa.query(Statistics)\
607 .filter(Statistics.repository ==
608 .filter(Statistics.repository == repo).scalar()
608 self.get_by_repo_name(repo_name))\
609 if obj:
609 .one()
610 self.sa.delete(obj)
610 self.sa.delete(obj)
611 except:
611 except:
612 log.error(traceback.format_exc())
612 log.error(traceback.format_exc())
613 raise
613 raise
614
614
615 def __create_repo(self, repo_name, alias, parent, clone_uri=False):
615 def __create_repo(self, repo_name, alias, parent, clone_uri=False):
616 """
616 """
617 makes repository on filesystem. It's group aware means it'll create
617 makes repository on filesystem. It's group aware means it'll create
618 a repository within a group, and alter the paths accordingly of
618 a repository within a group, and alter the paths accordingly of
619 group location
619 group location
620
620
621 :param repo_name:
621 :param repo_name:
622 :param alias:
622 :param alias:
623 :param parent_id:
623 :param parent_id:
624 :param clone_uri:
624 :param clone_uri:
625 """
625 """
626 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
626 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
627 from rhodecode.model.scm import ScmModel
627 from rhodecode.model.scm import ScmModel
628
628
629 if parent:
629 if parent:
630 new_parent_path = os.sep.join(parent.full_path_splitted)
630 new_parent_path = os.sep.join(parent.full_path_splitted)
631 else:
631 else:
632 new_parent_path = ''
632 new_parent_path = ''
633
633
634 # we need to make it str for mercurial
634 # we need to make it str for mercurial
635 repo_path = os.path.join(*map(lambda x: safe_str(x),
635 repo_path = os.path.join(*map(lambda x: safe_str(x),
636 [self.repos_path, new_parent_path, repo_name]))
636 [self.repos_path, new_parent_path, repo_name]))
637
637
638 # check if this path is not a repository
638 # check if this path is not a repository
639 if is_valid_repo(repo_path, self.repos_path):
639 if is_valid_repo(repo_path, self.repos_path):
640 raise Exception('This path %s is a valid repository' % repo_path)
640 raise Exception('This path %s is a valid repository' % repo_path)
641
641
642 # check if this path is a group
642 # check if this path is a group
643 if is_valid_repos_group(repo_path, self.repos_path):
643 if is_valid_repos_group(repo_path, self.repos_path):
644 raise Exception('This path %s is a valid group' % repo_path)
644 raise Exception('This path %s is a valid group' % repo_path)
645
645
646 log.info('creating repo %s in %s @ %s' % (
646 log.info('creating repo %s in %s @ %s' % (
647 repo_name, safe_unicode(repo_path), clone_uri
647 repo_name, safe_unicode(repo_path), clone_uri
648 )
648 )
649 )
649 )
650 backend = get_backend(alias)
650 backend = get_backend(alias)
651 if alias == 'hg':
651 if alias == 'hg':
652 backend(repo_path, create=True, src_url=clone_uri)
652 backend(repo_path, create=True, src_url=clone_uri)
653 elif alias == 'git':
653 elif alias == 'git':
654 r = backend(repo_path, create=True, src_url=clone_uri, bare=True)
654 r = backend(repo_path, create=True, src_url=clone_uri, bare=True)
655 # add rhodecode hook into this repo
655 # add rhodecode hook into this repo
656 ScmModel().install_git_hook(repo=r)
656 ScmModel().install_git_hook(repo=r)
657 else:
657 else:
658 raise Exception('Undefined alias %s' % alias)
658 raise Exception('Undefined alias %s' % alias)
659
659
660 def __rename_repo(self, old, new):
660 def __rename_repo(self, old, new):
661 """
661 """
662 renames repository on filesystem
662 renames repository on filesystem
663
663
664 :param old: old name
664 :param old: old name
665 :param new: new name
665 :param new: new name
666 """
666 """
667 log.info('renaming repo from %s to %s' % (old, new))
667 log.info('renaming repo from %s to %s' % (old, new))
668
668
669 old_path = os.path.join(self.repos_path, old)
669 old_path = os.path.join(self.repos_path, old)
670 new_path = os.path.join(self.repos_path, new)
670 new_path = os.path.join(self.repos_path, new)
671 if os.path.isdir(new_path):
671 if os.path.isdir(new_path):
672 raise Exception(
672 raise Exception(
673 'Was trying to rename to already existing dir %s' % new_path
673 'Was trying to rename to already existing dir %s' % new_path
674 )
674 )
675 shutil.move(old_path, new_path)
675 shutil.move(old_path, new_path)
676
676
677 def __delete_repo(self, repo):
677 def __delete_repo(self, repo):
678 """
678 """
679 removes repo from filesystem, the removal is acctually made by
679 removes repo from filesystem, the removal is acctually made by
680 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
680 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
681 repository is no longer valid for rhodecode, can be undeleted later on
681 repository is no longer valid for rhodecode, can be undeleted later on
682 by reverting the renames on this repository
682 by reverting the renames on this repository
683
683
684 :param repo: repo object
684 :param repo: repo object
685 """
685 """
686 rm_path = os.path.join(self.repos_path, repo.repo_name)
686 rm_path = os.path.join(self.repos_path, repo.repo_name)
687 log.info("Removing %s" % (rm_path))
687 log.info("Removing %s" % (rm_path))
688 # disable hg/git internal that it doesn't get detected as repo
688 # disable hg/git internal that it doesn't get detected as repo
689 alias = repo.repo_type
689 alias = repo.repo_type
690
690
691 bare = getattr(repo.scm_instance, 'bare', False)
691 bare = getattr(repo.scm_instance, 'bare', False)
692
692
693 if not bare:
693 if not bare:
694 # skip this for bare git repos
694 # skip this for bare git repos
695 shutil.move(os.path.join(rm_path, '.%s' % alias),
695 shutil.move(os.path.join(rm_path, '.%s' % alias),
696 os.path.join(rm_path, 'rm__.%s' % alias))
696 os.path.join(rm_path, 'rm__.%s' % alias))
697 # disable repo
697 # disable repo
698 _now = datetime.now()
698 _now = datetime.now()
699 _ms = str(_now.microsecond).rjust(6, '0')
699 _ms = str(_now.microsecond).rjust(6, '0')
700 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
700 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
701 repo.just_name)
701 repo.just_name)
702 if repo.group:
702 if repo.group:
703 args = repo.group.full_path_splitted + [_d]
703 args = repo.group.full_path_splitted + [_d]
704 _d = os.path.join(*args)
704 _d = os.path.join(*args)
705 shutil.move(rm_path, os.path.join(self.repos_path, _d))
705 shutil.move(rm_path, os.path.join(self.repos_path, _d))
General Comments 0
You need to be logged in to leave comments. Login now