##// END OF EJS Templates
vcs-settings: when setting landing ref from UI switch default GIT branch too....
super-admin -
r4753:515e2e65 default
parent child
Show More
@@ -1,1185 +1,1194
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import os
21 import os
22 import re
22 import re
23 import shutil
23 import shutil
24 import time
24 import time
25 import logging
25 import logging
26 import traceback
26 import traceback
27 import datetime
27 import datetime
28
28
29 from pyramid.threadlocal import get_current_request
29 from pyramid.threadlocal import get_current_request
30 from zope.cachedescriptors.property import Lazy as LazyProperty
30 from zope.cachedescriptors.property import Lazy as LazyProperty
31
31
32 from rhodecode import events
32 from rhodecode import events
33 from rhodecode.lib.auth import HasUserGroupPermissionAny
33 from rhodecode.lib.auth import HasUserGroupPermissionAny
34 from rhodecode.lib.caching_query import FromCache
34 from rhodecode.lib.caching_query import FromCache
35 from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError
35 from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError
36 from rhodecode.lib import hooks_base
36 from rhodecode.lib import hooks_base
37 from rhodecode.lib.user_log_filter import user_log_filter
37 from rhodecode.lib.user_log_filter import user_log_filter
38 from rhodecode.lib.utils import make_db_config
38 from rhodecode.lib.utils import make_db_config
39 from rhodecode.lib.utils2 import (
39 from rhodecode.lib.utils2 import (
40 safe_str, safe_unicode, remove_prefix, obfuscate_url_pw,
40 safe_str, safe_unicode, remove_prefix, obfuscate_url_pw,
41 get_current_rhodecode_user, safe_int, action_logger_generic)
41 get_current_rhodecode_user, safe_int, action_logger_generic)
42 from rhodecode.lib.vcs.backends import get_backend
42 from rhodecode.lib.vcs.backends import get_backend
43 from rhodecode.model import BaseModel
43 from rhodecode.model import BaseModel
44 from rhodecode.model.db import (
44 from rhodecode.model.db import (
45 _hash_key, func, case, joinedload, or_, in_filter_generator,
45 _hash_key, func, case, joinedload, or_, in_filter_generator,
46 Session, Repository, UserRepoToPerm, UserGroupRepoToPerm,
46 Session, Repository, UserRepoToPerm, UserGroupRepoToPerm,
47 UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission,
47 UserRepoGroupToPerm, UserGroupRepoGroupToPerm, User, Permission,
48 Statistics, UserGroup, RepoGroup, RepositoryField, UserLog)
48 Statistics, UserGroup, RepoGroup, RepositoryField, UserLog)
49 from rhodecode.model.permission import PermissionModel
49 from rhodecode.model.permission import PermissionModel
50 from rhodecode.model.settings import VcsSettingsModel
50 from rhodecode.model.settings import VcsSettingsModel
51
51
52 log = logging.getLogger(__name__)
52 log = logging.getLogger(__name__)
53
53
54
54
55 class RepoModel(BaseModel):
55 class RepoModel(BaseModel):
56
56
57 cls = Repository
57 cls = Repository
58
58
59 def _get_user_group(self, users_group):
59 def _get_user_group(self, users_group):
60 return self._get_instance(UserGroup, users_group,
60 return self._get_instance(UserGroup, users_group,
61 callback=UserGroup.get_by_group_name)
61 callback=UserGroup.get_by_group_name)
62
62
63 def _get_repo_group(self, repo_group):
63 def _get_repo_group(self, repo_group):
64 return self._get_instance(RepoGroup, repo_group,
64 return self._get_instance(RepoGroup, repo_group,
65 callback=RepoGroup.get_by_group_name)
65 callback=RepoGroup.get_by_group_name)
66
66
67 def _create_default_perms(self, repository, private):
67 def _create_default_perms(self, repository, private):
68 # create default permission
68 # create default permission
69 default = 'repository.read'
69 default = 'repository.read'
70 def_user = User.get_default_user()
70 def_user = User.get_default_user()
71 for p in def_user.user_perms:
71 for p in def_user.user_perms:
72 if p.permission.permission_name.startswith('repository.'):
72 if p.permission.permission_name.startswith('repository.'):
73 default = p.permission.permission_name
73 default = p.permission.permission_name
74 break
74 break
75
75
76 default_perm = 'repository.none' if private else default
76 default_perm = 'repository.none' if private else default
77
77
78 repo_to_perm = UserRepoToPerm()
78 repo_to_perm = UserRepoToPerm()
79 repo_to_perm.permission = Permission.get_by_key(default_perm)
79 repo_to_perm.permission = Permission.get_by_key(default_perm)
80
80
81 repo_to_perm.repository = repository
81 repo_to_perm.repository = repository
82 repo_to_perm.user_id = def_user.user_id
82 repo_to_perm.user_id = def_user.user_id
83
83
84 return repo_to_perm
84 return repo_to_perm
85
85
86 @LazyProperty
86 @LazyProperty
87 def repos_path(self):
87 def repos_path(self):
88 """
88 """
89 Gets the repositories root path from database
89 Gets the repositories root path from database
90 """
90 """
91 settings_model = VcsSettingsModel(sa=self.sa)
91 settings_model = VcsSettingsModel(sa=self.sa)
92 return settings_model.get_repos_location()
92 return settings_model.get_repos_location()
93
93
94 def get(self, repo_id):
94 def get(self, repo_id):
95 repo = self.sa.query(Repository) \
95 repo = self.sa.query(Repository) \
96 .filter(Repository.repo_id == repo_id)
96 .filter(Repository.repo_id == repo_id)
97
97
98 return repo.scalar()
98 return repo.scalar()
99
99
100 def get_repo(self, repository):
100 def get_repo(self, repository):
101 return self._get_repo(repository)
101 return self._get_repo(repository)
102
102
103 def get_by_repo_name(self, repo_name, cache=False):
103 def get_by_repo_name(self, repo_name, cache=False):
104 repo = self.sa.query(Repository) \
104 repo = self.sa.query(Repository) \
105 .filter(Repository.repo_name == repo_name)
105 .filter(Repository.repo_name == repo_name)
106
106
107 if cache:
107 if cache:
108 name_key = _hash_key(repo_name)
108 name_key = _hash_key(repo_name)
109 repo = repo.options(
109 repo = repo.options(
110 FromCache("sql_cache_short", "get_repo_%s" % name_key))
110 FromCache("sql_cache_short", "get_repo_%s" % name_key))
111 return repo.scalar()
111 return repo.scalar()
112
112
113 def _extract_id_from_repo_name(self, repo_name):
113 def _extract_id_from_repo_name(self, repo_name):
114 if repo_name.startswith('/'):
114 if repo_name.startswith('/'):
115 repo_name = repo_name.lstrip('/')
115 repo_name = repo_name.lstrip('/')
116 by_id_match = re.match(r'^_(\d{1,})', repo_name)
116 by_id_match = re.match(r'^_(\d{1,})', repo_name)
117 if by_id_match:
117 if by_id_match:
118 return by_id_match.groups()[0]
118 return by_id_match.groups()[0]
119
119
120 def get_repo_by_id(self, repo_name):
120 def get_repo_by_id(self, repo_name):
121 """
121 """
122 Extracts repo_name by id from special urls.
122 Extracts repo_name by id from special urls.
123 Example url is _11/repo_name
123 Example url is _11/repo_name
124
124
125 :param repo_name:
125 :param repo_name:
126 :return: repo object if matched else None
126 :return: repo object if matched else None
127 """
127 """
128 _repo_id = None
128 _repo_id = None
129 try:
129 try:
130 _repo_id = self._extract_id_from_repo_name(repo_name)
130 _repo_id = self._extract_id_from_repo_name(repo_name)
131 if _repo_id:
131 if _repo_id:
132 return self.get(_repo_id)
132 return self.get(_repo_id)
133 except Exception:
133 except Exception:
134 log.exception('Failed to extract repo_name from URL')
134 log.exception('Failed to extract repo_name from URL')
135 if _repo_id:
135 if _repo_id:
136 Session().rollback()
136 Session().rollback()
137
137
138 return None
138 return None
139
139
140 def get_repos_for_root(self, root, traverse=False):
140 def get_repos_for_root(self, root, traverse=False):
141 if traverse:
141 if traverse:
142 like_expression = u'{}%'.format(safe_unicode(root))
142 like_expression = u'{}%'.format(safe_unicode(root))
143 repos = Repository.query().filter(
143 repos = Repository.query().filter(
144 Repository.repo_name.like(like_expression)).all()
144 Repository.repo_name.like(like_expression)).all()
145 else:
145 else:
146 if root and not isinstance(root, RepoGroup):
146 if root and not isinstance(root, RepoGroup):
147 raise ValueError(
147 raise ValueError(
148 'Root must be an instance '
148 'Root must be an instance '
149 'of RepoGroup, got:{} instead'.format(type(root)))
149 'of RepoGroup, got:{} instead'.format(type(root)))
150 repos = Repository.query().filter(Repository.group == root).all()
150 repos = Repository.query().filter(Repository.group == root).all()
151 return repos
151 return repos
152
152
153 def get_url(self, repo, request=None, permalink=False):
153 def get_url(self, repo, request=None, permalink=False):
154 if not request:
154 if not request:
155 request = get_current_request()
155 request = get_current_request()
156
156
157 if not request:
157 if not request:
158 return
158 return
159
159
160 if permalink:
160 if permalink:
161 return request.route_url(
161 return request.route_url(
162 'repo_summary', repo_name='_{}'.format(safe_str(repo.repo_id)))
162 'repo_summary', repo_name='_{}'.format(safe_str(repo.repo_id)))
163 else:
163 else:
164 return request.route_url(
164 return request.route_url(
165 'repo_summary', repo_name=safe_str(repo.repo_name))
165 'repo_summary', repo_name=safe_str(repo.repo_name))
166
166
167 def get_commit_url(self, repo, commit_id, request=None, permalink=False):
167 def get_commit_url(self, repo, commit_id, request=None, permalink=False):
168 if not request:
168 if not request:
169 request = get_current_request()
169 request = get_current_request()
170
170
171 if not request:
171 if not request:
172 return
172 return
173
173
174 if permalink:
174 if permalink:
175 return request.route_url(
175 return request.route_url(
176 'repo_commit', repo_name=safe_str(repo.repo_id),
176 'repo_commit', repo_name=safe_str(repo.repo_id),
177 commit_id=commit_id)
177 commit_id=commit_id)
178
178
179 else:
179 else:
180 return request.route_url(
180 return request.route_url(
181 'repo_commit', repo_name=safe_str(repo.repo_name),
181 'repo_commit', repo_name=safe_str(repo.repo_name),
182 commit_id=commit_id)
182 commit_id=commit_id)
183
183
184 def get_repo_log(self, repo, filter_term):
184 def get_repo_log(self, repo, filter_term):
185 repo_log = UserLog.query()\
185 repo_log = UserLog.query()\
186 .filter(or_(UserLog.repository_id == repo.repo_id,
186 .filter(or_(UserLog.repository_id == repo.repo_id,
187 UserLog.repository_name == repo.repo_name))\
187 UserLog.repository_name == repo.repo_name))\
188 .options(joinedload(UserLog.user))\
188 .options(joinedload(UserLog.user))\
189 .options(joinedload(UserLog.repository))\
189 .options(joinedload(UserLog.repository))\
190 .order_by(UserLog.action_date.desc())
190 .order_by(UserLog.action_date.desc())
191
191
192 repo_log = user_log_filter(repo_log, filter_term)
192 repo_log = user_log_filter(repo_log, filter_term)
193 return repo_log
193 return repo_log
194
194
195 @classmethod
195 @classmethod
196 def update_commit_cache(cls, repositories=None):
196 def update_commit_cache(cls, repositories=None):
197 if not repositories:
197 if not repositories:
198 repositories = Repository.getAll()
198 repositories = Repository.getAll()
199 for repo in repositories:
199 for repo in repositories:
200 repo.update_commit_cache()
200 repo.update_commit_cache()
201
201
202 def get_repos_as_dict(self, repo_list=None, admin=False,
202 def get_repos_as_dict(self, repo_list=None, admin=False,
203 super_user_actions=False, short_name=None):
203 super_user_actions=False, short_name=None):
204
204
205 _render = get_current_request().get_partial_renderer(
205 _render = get_current_request().get_partial_renderer(
206 'rhodecode:templates/data_table/_dt_elements.mako')
206 'rhodecode:templates/data_table/_dt_elements.mako')
207 c = _render.get_call_context()
207 c = _render.get_call_context()
208 h = _render.get_helpers()
208 h = _render.get_helpers()
209
209
210 def quick_menu(repo_name):
210 def quick_menu(repo_name):
211 return _render('quick_menu', repo_name)
211 return _render('quick_menu', repo_name)
212
212
213 def repo_lnk(name, rtype, rstate, private, archived, fork_of):
213 def repo_lnk(name, rtype, rstate, private, archived, fork_of):
214 if short_name is not None:
214 if short_name is not None:
215 short_name_var = short_name
215 short_name_var = short_name
216 else:
216 else:
217 short_name_var = not admin
217 short_name_var = not admin
218 return _render('repo_name', name, rtype, rstate, private, archived, fork_of,
218 return _render('repo_name', name, rtype, rstate, private, archived, fork_of,
219 short_name=short_name_var, admin=False)
219 short_name=short_name_var, admin=False)
220
220
221 def last_change(last_change):
221 def last_change(last_change):
222 if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
222 if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo:
223 ts = time.time()
223 ts = time.time()
224 utc_offset = (datetime.datetime.fromtimestamp(ts)
224 utc_offset = (datetime.datetime.fromtimestamp(ts)
225 - datetime.datetime.utcfromtimestamp(ts)).total_seconds()
225 - datetime.datetime.utcfromtimestamp(ts)).total_seconds()
226 last_change = last_change + datetime.timedelta(seconds=utc_offset)
226 last_change = last_change + datetime.timedelta(seconds=utc_offset)
227
227
228 return _render("last_change", last_change)
228 return _render("last_change", last_change)
229
229
230 def rss_lnk(repo_name):
230 def rss_lnk(repo_name):
231 return _render("rss", repo_name)
231 return _render("rss", repo_name)
232
232
233 def atom_lnk(repo_name):
233 def atom_lnk(repo_name):
234 return _render("atom", repo_name)
234 return _render("atom", repo_name)
235
235
236 def last_rev(repo_name, cs_cache):
236 def last_rev(repo_name, cs_cache):
237 return _render('revision', repo_name, cs_cache.get('revision'),
237 return _render('revision', repo_name, cs_cache.get('revision'),
238 cs_cache.get('raw_id'), cs_cache.get('author'),
238 cs_cache.get('raw_id'), cs_cache.get('author'),
239 cs_cache.get('message'), cs_cache.get('date'))
239 cs_cache.get('message'), cs_cache.get('date'))
240
240
241 def desc(desc):
241 def desc(desc):
242 return _render('repo_desc', desc, c.visual.stylify_metatags)
242 return _render('repo_desc', desc, c.visual.stylify_metatags)
243
243
244 def state(repo_state):
244 def state(repo_state):
245 return _render("repo_state", repo_state)
245 return _render("repo_state", repo_state)
246
246
247 def repo_actions(repo_name):
247 def repo_actions(repo_name):
248 return _render('repo_actions', repo_name, super_user_actions)
248 return _render('repo_actions', repo_name, super_user_actions)
249
249
250 def user_profile(username):
250 def user_profile(username):
251 return _render('user_profile', username)
251 return _render('user_profile', username)
252
252
253 repos_data = []
253 repos_data = []
254 for repo in repo_list:
254 for repo in repo_list:
255 # NOTE(marcink): because we use only raw column we need to load it like that
255 # NOTE(marcink): because we use only raw column we need to load it like that
256 changeset_cache = Repository._load_changeset_cache(
256 changeset_cache = Repository._load_changeset_cache(
257 repo.repo_id, repo._changeset_cache)
257 repo.repo_id, repo._changeset_cache)
258
258
259 row = {
259 row = {
260 "menu": quick_menu(repo.repo_name),
260 "menu": quick_menu(repo.repo_name),
261
261
262 "name": repo_lnk(repo.repo_name, repo.repo_type, repo.repo_state,
262 "name": repo_lnk(repo.repo_name, repo.repo_type, repo.repo_state,
263 repo.private, repo.archived, repo.fork),
263 repo.private, repo.archived, repo.fork),
264
264
265 "desc": desc(h.escape(repo.description)),
265 "desc": desc(h.escape(repo.description)),
266
266
267 "last_change": last_change(repo.updated_on),
267 "last_change": last_change(repo.updated_on),
268
268
269 "last_changeset": last_rev(repo.repo_name, changeset_cache),
269 "last_changeset": last_rev(repo.repo_name, changeset_cache),
270 "last_changeset_raw": changeset_cache.get('revision'),
270 "last_changeset_raw": changeset_cache.get('revision'),
271
271
272 "owner": user_profile(repo.User.username),
272 "owner": user_profile(repo.User.username),
273
273
274 "state": state(repo.repo_state),
274 "state": state(repo.repo_state),
275 "rss": rss_lnk(repo.repo_name),
275 "rss": rss_lnk(repo.repo_name),
276 "atom": atom_lnk(repo.repo_name),
276 "atom": atom_lnk(repo.repo_name),
277 }
277 }
278 if admin:
278 if admin:
279 row.update({
279 row.update({
280 "action": repo_actions(repo.repo_name),
280 "action": repo_actions(repo.repo_name),
281 })
281 })
282 repos_data.append(row)
282 repos_data.append(row)
283
283
284 return repos_data
284 return repos_data
285
285
286 def get_repos_data_table(
286 def get_repos_data_table(
287 self, draw, start, limit,
287 self, draw, start, limit,
288 search_q, order_by, order_dir,
288 search_q, order_by, order_dir,
289 auth_user, repo_group_id):
289 auth_user, repo_group_id):
290 from rhodecode.model.scm import RepoList
290 from rhodecode.model.scm import RepoList
291
291
292 _perms = ['repository.read', 'repository.write', 'repository.admin']
292 _perms = ['repository.read', 'repository.write', 'repository.admin']
293
293
294 repos = Repository.query() \
294 repos = Repository.query() \
295 .filter(Repository.group_id == repo_group_id) \
295 .filter(Repository.group_id == repo_group_id) \
296 .all()
296 .all()
297 auth_repo_list = RepoList(
297 auth_repo_list = RepoList(
298 repos, perm_set=_perms,
298 repos, perm_set=_perms,
299 extra_kwargs=dict(user=auth_user))
299 extra_kwargs=dict(user=auth_user))
300
300
301 allowed_ids = [-1]
301 allowed_ids = [-1]
302 for repo in auth_repo_list:
302 for repo in auth_repo_list:
303 allowed_ids.append(repo.repo_id)
303 allowed_ids.append(repo.repo_id)
304
304
305 repos_data_total_count = Repository.query() \
305 repos_data_total_count = Repository.query() \
306 .filter(Repository.group_id == repo_group_id) \
306 .filter(Repository.group_id == repo_group_id) \
307 .filter(or_(
307 .filter(or_(
308 # generate multiple IN to fix limitation problems
308 # generate multiple IN to fix limitation problems
309 *in_filter_generator(Repository.repo_id, allowed_ids))
309 *in_filter_generator(Repository.repo_id, allowed_ids))
310 ) \
310 ) \
311 .count()
311 .count()
312
312
313 base_q = Session.query(
313 base_q = Session.query(
314 Repository.repo_id,
314 Repository.repo_id,
315 Repository.repo_name,
315 Repository.repo_name,
316 Repository.description,
316 Repository.description,
317 Repository.repo_type,
317 Repository.repo_type,
318 Repository.repo_state,
318 Repository.repo_state,
319 Repository.private,
319 Repository.private,
320 Repository.archived,
320 Repository.archived,
321 Repository.fork,
321 Repository.fork,
322 Repository.updated_on,
322 Repository.updated_on,
323 Repository._changeset_cache,
323 Repository._changeset_cache,
324 User,
324 User,
325 ) \
325 ) \
326 .filter(Repository.group_id == repo_group_id) \
326 .filter(Repository.group_id == repo_group_id) \
327 .filter(or_(
327 .filter(or_(
328 # generate multiple IN to fix limitation problems
328 # generate multiple IN to fix limitation problems
329 *in_filter_generator(Repository.repo_id, allowed_ids))
329 *in_filter_generator(Repository.repo_id, allowed_ids))
330 ) \
330 ) \
331 .join(User, User.user_id == Repository.user_id) \
331 .join(User, User.user_id == Repository.user_id) \
332 .group_by(Repository, User)
332 .group_by(Repository, User)
333
333
334 repos_data_total_filtered_count = base_q.count()
334 repos_data_total_filtered_count = base_q.count()
335
335
336 sort_defined = False
336 sort_defined = False
337 if order_by == 'repo_name':
337 if order_by == 'repo_name':
338 sort_col = func.lower(Repository.repo_name)
338 sort_col = func.lower(Repository.repo_name)
339 sort_defined = True
339 sort_defined = True
340 elif order_by == 'user_username':
340 elif order_by == 'user_username':
341 sort_col = User.username
341 sort_col = User.username
342 else:
342 else:
343 sort_col = getattr(Repository, order_by, None)
343 sort_col = getattr(Repository, order_by, None)
344
344
345 if sort_defined or sort_col:
345 if sort_defined or sort_col:
346 if order_dir == 'asc':
346 if order_dir == 'asc':
347 sort_col = sort_col.asc()
347 sort_col = sort_col.asc()
348 else:
348 else:
349 sort_col = sort_col.desc()
349 sort_col = sort_col.desc()
350
350
351 base_q = base_q.order_by(sort_col)
351 base_q = base_q.order_by(sort_col)
352 base_q = base_q.offset(start).limit(limit)
352 base_q = base_q.offset(start).limit(limit)
353
353
354 repos_list = base_q.all()
354 repos_list = base_q.all()
355
355
356 repos_data = RepoModel().get_repos_as_dict(
356 repos_data = RepoModel().get_repos_as_dict(
357 repo_list=repos_list, admin=False)
357 repo_list=repos_list, admin=False)
358
358
359 data = ({
359 data = ({
360 'draw': draw,
360 'draw': draw,
361 'data': repos_data,
361 'data': repos_data,
362 'recordsTotal': repos_data_total_count,
362 'recordsTotal': repos_data_total_count,
363 'recordsFiltered': repos_data_total_filtered_count,
363 'recordsFiltered': repos_data_total_filtered_count,
364 })
364 })
365 return data
365 return data
366
366
367 def _get_defaults(self, repo_name):
367 def _get_defaults(self, repo_name):
368 """
368 """
369 Gets information about repository, and returns a dict for
369 Gets information about repository, and returns a dict for
370 usage in forms
370 usage in forms
371
371
372 :param repo_name:
372 :param repo_name:
373 """
373 """
374
374
375 repo_info = Repository.get_by_repo_name(repo_name)
375 repo_info = Repository.get_by_repo_name(repo_name)
376
376
377 if repo_info is None:
377 if repo_info is None:
378 return None
378 return None
379
379
380 defaults = repo_info.get_dict()
380 defaults = repo_info.get_dict()
381 defaults['repo_name'] = repo_info.just_name
381 defaults['repo_name'] = repo_info.just_name
382
382
383 groups = repo_info.groups_with_parents
383 groups = repo_info.groups_with_parents
384 parent_group = groups[-1] if groups else None
384 parent_group = groups[-1] if groups else None
385
385
386 # we use -1 as this is how in HTML, we mark an empty group
386 # we use -1 as this is how in HTML, we mark an empty group
387 defaults['repo_group'] = getattr(parent_group, 'group_id', -1)
387 defaults['repo_group'] = getattr(parent_group, 'group_id', -1)
388
388
389 keys_to_process = (
389 keys_to_process = (
390 {'k': 'repo_type', 'strip': False},
390 {'k': 'repo_type', 'strip': False},
391 {'k': 'repo_enable_downloads', 'strip': True},
391 {'k': 'repo_enable_downloads', 'strip': True},
392 {'k': 'repo_description', 'strip': True},
392 {'k': 'repo_description', 'strip': True},
393 {'k': 'repo_enable_locking', 'strip': True},
393 {'k': 'repo_enable_locking', 'strip': True},
394 {'k': 'repo_landing_rev', 'strip': True},
394 {'k': 'repo_landing_rev', 'strip': True},
395 {'k': 'clone_uri', 'strip': False},
395 {'k': 'clone_uri', 'strip': False},
396 {'k': 'push_uri', 'strip': False},
396 {'k': 'push_uri', 'strip': False},
397 {'k': 'repo_private', 'strip': True},
397 {'k': 'repo_private', 'strip': True},
398 {'k': 'repo_enable_statistics', 'strip': True}
398 {'k': 'repo_enable_statistics', 'strip': True}
399 )
399 )
400
400
401 for item in keys_to_process:
401 for item in keys_to_process:
402 attr = item['k']
402 attr = item['k']
403 if item['strip']:
403 if item['strip']:
404 attr = remove_prefix(item['k'], 'repo_')
404 attr = remove_prefix(item['k'], 'repo_')
405
405
406 val = defaults[attr]
406 val = defaults[attr]
407 if item['k'] == 'repo_landing_rev':
407 if item['k'] == 'repo_landing_rev':
408 val = ':'.join(defaults[attr])
408 val = ':'.join(defaults[attr])
409 defaults[item['k']] = val
409 defaults[item['k']] = val
410 if item['k'] == 'clone_uri':
410 if item['k'] == 'clone_uri':
411 defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
411 defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
412 if item['k'] == 'push_uri':
412 if item['k'] == 'push_uri':
413 defaults['push_uri_hidden'] = repo_info.push_uri_hidden
413 defaults['push_uri_hidden'] = repo_info.push_uri_hidden
414
414
415 # fill owner
415 # fill owner
416 if repo_info.user:
416 if repo_info.user:
417 defaults.update({'user': repo_info.user.username})
417 defaults.update({'user': repo_info.user.username})
418 else:
418 else:
419 replacement_user = User.get_first_super_admin().username
419 replacement_user = User.get_first_super_admin().username
420 defaults.update({'user': replacement_user})
420 defaults.update({'user': replacement_user})
421
421
422 return defaults
422 return defaults
423
423
424 def update(self, repo, **kwargs):
424 def update(self, repo, **kwargs):
425 try:
425 try:
426 cur_repo = self._get_repo(repo)
426 cur_repo = self._get_repo(repo)
427 source_repo_name = cur_repo.repo_name
427 source_repo_name = cur_repo.repo_name
428
428
429 affected_user_ids = []
429 affected_user_ids = []
430 if 'user' in kwargs:
430 if 'user' in kwargs:
431 old_owner_id = cur_repo.user.user_id
431 old_owner_id = cur_repo.user.user_id
432 new_owner = User.get_by_username(kwargs['user'])
432 new_owner = User.get_by_username(kwargs['user'])
433 cur_repo.user = new_owner
433 cur_repo.user = new_owner
434
434
435 if old_owner_id != new_owner.user_id:
435 if old_owner_id != new_owner.user_id:
436 affected_user_ids = [new_owner.user_id, old_owner_id]
436 affected_user_ids = [new_owner.user_id, old_owner_id]
437
437
438 if 'repo_group' in kwargs:
438 if 'repo_group' in kwargs:
439 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
439 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
440 log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
440 log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
441
441
442 update_keys = [
442 update_keys = [
443 (1, 'repo_description'),
443 (1, 'repo_description'),
444 (1, 'repo_landing_rev'),
444 (1, 'repo_landing_rev'),
445 (1, 'repo_private'),
445 (1, 'repo_private'),
446 (1, 'repo_enable_downloads'),
446 (1, 'repo_enable_downloads'),
447 (1, 'repo_enable_locking'),
447 (1, 'repo_enable_locking'),
448 (1, 'repo_enable_statistics'),
448 (1, 'repo_enable_statistics'),
449 (0, 'clone_uri'),
449 (0, 'clone_uri'),
450 (0, 'push_uri'),
450 (0, 'push_uri'),
451 (0, 'fork_id')
451 (0, 'fork_id')
452 ]
452 ]
453 for strip, k in update_keys:
453 for strip, k in update_keys:
454 if k in kwargs:
454 if k in kwargs:
455 val = kwargs[k]
455 val = kwargs[k]
456 if strip:
456 if strip:
457 k = remove_prefix(k, 'repo_')
457 k = remove_prefix(k, 'repo_')
458
458
459 setattr(cur_repo, k, val)
459 setattr(cur_repo, k, val)
460
460
461 new_name = cur_repo.get_new_name(kwargs['repo_name'])
461 new_name = cur_repo.get_new_name(kwargs['repo_name'])
462 cur_repo.repo_name = new_name
462 cur_repo.repo_name = new_name
463
463
464 # if private flag is set, reset default permission to NONE
464 # if private flag is set, reset default permission to NONE
465 if kwargs.get('repo_private'):
465 if kwargs.get('repo_private'):
466 EMPTY_PERM = 'repository.none'
466 EMPTY_PERM = 'repository.none'
467 RepoModel().grant_user_permission(
467 RepoModel().grant_user_permission(
468 repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM
468 repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM
469 )
469 )
470 if kwargs.get('repo_landing_rev'):
471 landing_rev_val = kwargs['repo_landing_rev']
472 RepoModel().set_landing_rev(cur_repo, landing_rev_val)
470
473
471 # handle extra fields
474 # handle extra fields
472 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
475 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
473 k = RepositoryField.un_prefix_key(field)
476 k = RepositoryField.un_prefix_key(field)
474 ex_field = RepositoryField.get_by_key_name(
477 ex_field = RepositoryField.get_by_key_name(
475 key=k, repo=cur_repo)
478 key=k, repo=cur_repo)
476 if ex_field:
479 if ex_field:
477 ex_field.field_value = kwargs[field]
480 ex_field.field_value = kwargs[field]
478 self.sa.add(ex_field)
481 self.sa.add(ex_field)
479
482
480 self.sa.add(cur_repo)
483 self.sa.add(cur_repo)
481
484
482 if source_repo_name != new_name:
485 if source_repo_name != new_name:
483 # rename repository
486 # rename repository
484 self._rename_filesystem_repo(
487 self._rename_filesystem_repo(
485 old=source_repo_name, new=new_name)
488 old=source_repo_name, new=new_name)
486
489
487 if affected_user_ids:
490 if affected_user_ids:
488 PermissionModel().trigger_permission_flush(affected_user_ids)
491 PermissionModel().trigger_permission_flush(affected_user_ids)
489
492
490 return cur_repo
493 return cur_repo
491 except Exception:
494 except Exception:
492 log.error(traceback.format_exc())
495 log.error(traceback.format_exc())
493 raise
496 raise
494
497
495 def _create_repo(self, repo_name, repo_type, description, owner,
498 def _create_repo(self, repo_name, repo_type, description, owner,
496 private=False, clone_uri=None, repo_group=None,
499 private=False, clone_uri=None, repo_group=None,
497 landing_rev='rev:tip', fork_of=None,
500 landing_rev='rev:tip', fork_of=None,
498 copy_fork_permissions=False, enable_statistics=False,
501 copy_fork_permissions=False, enable_statistics=False,
499 enable_locking=False, enable_downloads=False,
502 enable_locking=False, enable_downloads=False,
500 copy_group_permissions=False,
503 copy_group_permissions=False,
501 state=Repository.STATE_PENDING):
504 state=Repository.STATE_PENDING):
502 """
505 """
503 Create repository inside database with PENDING state, this should be
506 Create repository inside database with PENDING state, this should be
504 only executed by create() repo. With exception of importing existing
507 only executed by create() repo. With exception of importing existing
505 repos
508 repos
506 """
509 """
507 from rhodecode.model.scm import ScmModel
510 from rhodecode.model.scm import ScmModel
508
511
509 owner = self._get_user(owner)
512 owner = self._get_user(owner)
510 fork_of = self._get_repo(fork_of)
513 fork_of = self._get_repo(fork_of)
511 repo_group = self._get_repo_group(safe_int(repo_group))
514 repo_group = self._get_repo_group(safe_int(repo_group))
512
515
513 try:
516 try:
514 repo_name = safe_unicode(repo_name)
517 repo_name = safe_unicode(repo_name)
515 description = safe_unicode(description)
518 description = safe_unicode(description)
516 # repo name is just a name of repository
519 # repo name is just a name of repository
517 # while repo_name_full is a full qualified name that is combined
520 # while repo_name_full is a full qualified name that is combined
518 # with name and path of group
521 # with name and path of group
519 repo_name_full = repo_name
522 repo_name_full = repo_name
520 repo_name = repo_name.split(Repository.NAME_SEP)[-1]
523 repo_name = repo_name.split(Repository.NAME_SEP)[-1]
521
524
522 new_repo = Repository()
525 new_repo = Repository()
523 new_repo.repo_state = state
526 new_repo.repo_state = state
524 new_repo.enable_statistics = False
527 new_repo.enable_statistics = False
525 new_repo.repo_name = repo_name_full
528 new_repo.repo_name = repo_name_full
526 new_repo.repo_type = repo_type
529 new_repo.repo_type = repo_type
527 new_repo.user = owner
530 new_repo.user = owner
528 new_repo.group = repo_group
531 new_repo.group = repo_group
529 new_repo.description = description or repo_name
532 new_repo.description = description or repo_name
530 new_repo.private = private
533 new_repo.private = private
531 new_repo.archived = False
534 new_repo.archived = False
532 new_repo.clone_uri = clone_uri
535 new_repo.clone_uri = clone_uri
533 new_repo.landing_rev = landing_rev
536 new_repo.landing_rev = landing_rev
534
537
535 new_repo.enable_statistics = enable_statistics
538 new_repo.enable_statistics = enable_statistics
536 new_repo.enable_locking = enable_locking
539 new_repo.enable_locking = enable_locking
537 new_repo.enable_downloads = enable_downloads
540 new_repo.enable_downloads = enable_downloads
538
541
539 if repo_group:
542 if repo_group:
540 new_repo.enable_locking = repo_group.enable_locking
543 new_repo.enable_locking = repo_group.enable_locking
541
544
542 if fork_of:
545 if fork_of:
543 parent_repo = fork_of
546 parent_repo = fork_of
544 new_repo.fork = parent_repo
547 new_repo.fork = parent_repo
545
548
546 events.trigger(events.RepoPreCreateEvent(new_repo))
549 events.trigger(events.RepoPreCreateEvent(new_repo))
547
550
548 self.sa.add(new_repo)
551 self.sa.add(new_repo)
549
552
550 EMPTY_PERM = 'repository.none'
553 EMPTY_PERM = 'repository.none'
551 if fork_of and copy_fork_permissions:
554 if fork_of and copy_fork_permissions:
552 repo = fork_of
555 repo = fork_of
553 user_perms = UserRepoToPerm.query() \
556 user_perms = UserRepoToPerm.query() \
554 .filter(UserRepoToPerm.repository == repo).all()
557 .filter(UserRepoToPerm.repository == repo).all()
555 group_perms = UserGroupRepoToPerm.query() \
558 group_perms = UserGroupRepoToPerm.query() \
556 .filter(UserGroupRepoToPerm.repository == repo).all()
559 .filter(UserGroupRepoToPerm.repository == repo).all()
557
560
558 for perm in user_perms:
561 for perm in user_perms:
559 UserRepoToPerm.create(
562 UserRepoToPerm.create(
560 perm.user, new_repo, perm.permission)
563 perm.user, new_repo, perm.permission)
561
564
562 for perm in group_perms:
565 for perm in group_perms:
563 UserGroupRepoToPerm.create(
566 UserGroupRepoToPerm.create(
564 perm.users_group, new_repo, perm.permission)
567 perm.users_group, new_repo, perm.permission)
565 # in case we copy permissions and also set this repo to private
568 # in case we copy permissions and also set this repo to private
566 # override the default user permission to make it a private repo
569 # override the default user permission to make it a private repo
567 if private:
570 if private:
568 RepoModel(self.sa).grant_user_permission(
571 RepoModel(self.sa).grant_user_permission(
569 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
572 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
570
573
571 elif repo_group and copy_group_permissions:
574 elif repo_group and copy_group_permissions:
572 user_perms = UserRepoGroupToPerm.query() \
575 user_perms = UserRepoGroupToPerm.query() \
573 .filter(UserRepoGroupToPerm.group == repo_group).all()
576 .filter(UserRepoGroupToPerm.group == repo_group).all()
574
577
575 group_perms = UserGroupRepoGroupToPerm.query() \
578 group_perms = UserGroupRepoGroupToPerm.query() \
576 .filter(UserGroupRepoGroupToPerm.group == repo_group).all()
579 .filter(UserGroupRepoGroupToPerm.group == repo_group).all()
577
580
578 for perm in user_perms:
581 for perm in user_perms:
579 perm_name = perm.permission.permission_name.replace(
582 perm_name = perm.permission.permission_name.replace(
580 'group.', 'repository.')
583 'group.', 'repository.')
581 perm_obj = Permission.get_by_key(perm_name)
584 perm_obj = Permission.get_by_key(perm_name)
582 UserRepoToPerm.create(perm.user, new_repo, perm_obj)
585 UserRepoToPerm.create(perm.user, new_repo, perm_obj)
583
586
584 for perm in group_perms:
587 for perm in group_perms:
585 perm_name = perm.permission.permission_name.replace(
588 perm_name = perm.permission.permission_name.replace(
586 'group.', 'repository.')
589 'group.', 'repository.')
587 perm_obj = Permission.get_by_key(perm_name)