##// END OF EJS Templates
autocomplete: add flags to show/hide active users, and also display this information...
marcink -
r222:c6ddf19a default
parent child Browse files
Show More
@@ -1,277 +1,284 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 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 """
21 """
22 Home controller for RhodeCode Enterprise
22 Home controller for RhodeCode Enterprise
23 """
23 """
24
24
25 import logging
25 import logging
26 import time
26 import time
27 import re
27 import re
28
28
29 from pylons import tmpl_context as c, request, url, config
29 from pylons import tmpl_context as c, request, url, config
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31 from sqlalchemy.sql import func
31 from sqlalchemy.sql import func
32
32
33 from rhodecode.lib.auth import (
33 from rhodecode.lib.auth import (
34 LoginRequired, HasPermissionAllDecorator, AuthUser,
34 LoginRequired, HasPermissionAllDecorator, AuthUser,
35 HasRepoGroupPermissionAnyDecorator, XHRRequired)
35 HasRepoGroupPermissionAnyDecorator, XHRRequired)
36 from rhodecode.lib.base import BaseController, render
36 from rhodecode.lib.base import BaseController, render
37 from rhodecode.lib.index import searcher_from_config
37 from rhodecode.lib.index import searcher_from_config
38 from rhodecode.lib.ext_json import json
38 from rhodecode.lib.ext_json import json
39 from rhodecode.lib.utils import jsonify
39 from rhodecode.lib.utils import jsonify
40 from rhodecode.lib.utils2 import safe_unicode
40 from rhodecode.lib.utils2 import safe_unicode
41 from rhodecode.model.db import Repository, RepoGroup
41 from rhodecode.model.db import Repository, RepoGroup
42 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.repo import RepoModel
43 from rhodecode.model.repo_group import RepoGroupModel
43 from rhodecode.model.repo_group import RepoGroupModel
44 from rhodecode.model.scm import RepoList, RepoGroupList
44 from rhodecode.model.scm import RepoList, RepoGroupList
45
45
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 class HomeController(BaseController):
50 class HomeController(BaseController):
51 def __before__(self):
51 def __before__(self):
52 super(HomeController, self).__before__()
52 super(HomeController, self).__before__()
53
53
54 def ping(self):
54 def ping(self):
55 """
55 """
56 Ping, doesn't require login, good for checking out the platform
56 Ping, doesn't require login, good for checking out the platform
57 """
57 """
58 instance_id = getattr(c, 'rhodecode_instanceid', '')
58 instance_id = getattr(c, 'rhodecode_instanceid', '')
59 return 'pong[%s] => %s' % (instance_id, self.ip_addr,)
59 return 'pong[%s] => %s' % (instance_id, self.ip_addr,)
60
60
61 @LoginRequired()
61 @LoginRequired()
62 @HasPermissionAllDecorator('hg.admin')
62 @HasPermissionAllDecorator('hg.admin')
63 def error_test(self):
63 def error_test(self):
64 """
64 """
65 Test exception handling and emails on errors
65 Test exception handling and emails on errors
66 """
66 """
67 class TestException(Exception):
67 class TestException(Exception):
68 pass
68 pass
69
69
70 msg = ('RhodeCode Enterprise %s test exception. Generation time: %s'
70 msg = ('RhodeCode Enterprise %s test exception. Generation time: %s'
71 % (c.rhodecode_name, time.time()))
71 % (c.rhodecode_name, time.time()))
72 raise TestException(msg)
72 raise TestException(msg)
73
73
74 def _get_groups_and_repos(self, repo_group_id=None):
74 def _get_groups_and_repos(self, repo_group_id=None):
75 # repo groups groups
75 # repo groups groups
76 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
76 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
77 _perms = ['group.read', 'group.write', 'group.admin']
77 _perms = ['group.read', 'group.write', 'group.admin']
78 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
78 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
79 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
79 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
80 repo_group_list=repo_group_list_acl, admin=False)
80 repo_group_list=repo_group_list_acl, admin=False)
81
81
82 # repositories
82 # repositories
83 repo_list = Repository.get_all_repos(group_id=repo_group_id)
83 repo_list = Repository.get_all_repos(group_id=repo_group_id)
84 _perms = ['repository.read', 'repository.write', 'repository.admin']
84 _perms = ['repository.read', 'repository.write', 'repository.admin']
85 repo_list_acl = RepoList(repo_list, perm_set=_perms)
85 repo_list_acl = RepoList(repo_list, perm_set=_perms)
86 repo_data = RepoModel().get_repos_as_dict(
86 repo_data = RepoModel().get_repos_as_dict(
87 repo_list=repo_list_acl, admin=False)
87 repo_list=repo_list_acl, admin=False)
88
88
89 return repo_data, repo_group_data
89 return repo_data, repo_group_data
90
90
91 @LoginRequired()
91 @LoginRequired()
92 def index(self):
92 def index(self):
93 c.repo_group = None
93 c.repo_group = None
94
94
95 repo_data, repo_group_data = self._get_groups_and_repos()
95 repo_data, repo_group_data = self._get_groups_and_repos()
96 # json used to render the grids
96 # json used to render the grids
97 c.repos_data = json.dumps(repo_data)
97 c.repos_data = json.dumps(repo_data)
98 c.repo_groups_data = json.dumps(repo_group_data)
98 c.repo_groups_data = json.dumps(repo_group_data)
99
99
100 return render('/index.html')
100 return render('/index.html')
101
101
102 @LoginRequired()
102 @LoginRequired()
103 @HasRepoGroupPermissionAnyDecorator('group.read', 'group.write',
103 @HasRepoGroupPermissionAnyDecorator('group.read', 'group.write',
104 'group.admin')
104 'group.admin')
105 def index_repo_group(self, group_name):
105 def index_repo_group(self, group_name):
106 """GET /repo_group_name: Show a specific item"""
106 """GET /repo_group_name: Show a specific item"""
107 c.repo_group = RepoGroupModel()._get_repo_group(group_name)
107 c.repo_group = RepoGroupModel()._get_repo_group(group_name)
108 repo_data, repo_group_data = self._get_groups_and_repos(
108 repo_data, repo_group_data = self._get_groups_and_repos(
109 c.repo_group.group_id)
109 c.repo_group.group_id)
110
110
111 # json used to render the grids
111 # json used to render the grids
112 c.repos_data = json.dumps(repo_data)
112 c.repos_data = json.dumps(repo_data)
113 c.repo_groups_data = json.dumps(repo_group_data)
113 c.repo_groups_data = json.dumps(repo_group_data)
114
114
115 return render('index_repo_group.html')
115 return render('index_repo_group.html')
116
116
117 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
117 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
118 query = Repository.query()\
118 query = Repository.query()\
119 .order_by(func.length(Repository.repo_name))\
119 .order_by(func.length(Repository.repo_name))\
120 .order_by(Repository.repo_name)
120 .order_by(Repository.repo_name)
121
121
122 if repo_type:
122 if repo_type:
123 query = query.filter(Repository.repo_type == repo_type)
123 query = query.filter(Repository.repo_type == repo_type)
124
124
125 if name_contains:
125 if name_contains:
126 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
126 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
127 query = query.filter(
127 query = query.filter(
128 Repository.repo_name.ilike(ilike_expression))
128 Repository.repo_name.ilike(ilike_expression))
129 query = query.limit(limit)
129 query = query.limit(limit)
130
130
131 all_repos = query.all()
131 all_repos = query.all()
132 repo_iter = self.scm_model.get_repos(all_repos)
132 repo_iter = self.scm_model.get_repos(all_repos)
133 return [
133 return [
134 {
134 {
135 'id': obj['name'],
135 'id': obj['name'],
136 'text': obj['name'],
136 'text': obj['name'],
137 'type': 'repo',
137 'type': 'repo',
138 'obj': obj['dbrepo'],
138 'obj': obj['dbrepo'],
139 'url': url('summary_home', repo_name=obj['name'])
139 'url': url('summary_home', repo_name=obj['name'])
140 }
140 }
141 for obj in repo_iter]
141 for obj in repo_iter]
142
142
143 def _get_repo_group_list(self, name_contains=None, limit=20):
143 def _get_repo_group_list(self, name_contains=None, limit=20):
144 query = RepoGroup.query()\
144 query = RepoGroup.query()\
145 .order_by(func.length(RepoGroup.group_name))\
145 .order_by(func.length(RepoGroup.group_name))\
146 .order_by(RepoGroup.group_name)
146 .order_by(RepoGroup.group_name)
147
147
148 if name_contains:
148 if name_contains:
149 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
149 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
150 query = query.filter(
150 query = query.filter(
151 RepoGroup.group_name.ilike(ilike_expression))
151 RepoGroup.group_name.ilike(ilike_expression))
152 query = query.limit(limit)
152 query = query.limit(limit)
153
153
154 all_groups = query.all()
154 all_groups = query.all()
155 repo_groups_iter = self.scm_model.get_repo_groups(all_groups)
155 repo_groups_iter = self.scm_model.get_repo_groups(all_groups)
156 return [
156 return [
157 {
157 {
158 'id': obj.group_name,
158 'id': obj.group_name,
159 'text': obj.group_name,
159 'text': obj.group_name,
160 'type': 'group',
160 'type': 'group',
161 'obj': {},
161 'obj': {},
162 'url': url('repo_group_home', group_name=obj.group_name)
162 'url': url('repo_group_home', group_name=obj.group_name)
163 }
163 }
164 for obj in repo_groups_iter]
164 for obj in repo_groups_iter]
165
165
166 def _get_hash_commit_list(self, hash_starts_with=None, limit=20):
166 def _get_hash_commit_list(self, hash_starts_with=None, limit=20):
167 if not hash_starts_with or len(hash_starts_with) < 3:
167 if not hash_starts_with or len(hash_starts_with) < 3:
168 return []
168 return []
169
169
170 commit_hashes = re.compile('([0-9a-f]{2,40})').findall(hash_starts_with)
170 commit_hashes = re.compile('([0-9a-f]{2,40})').findall(hash_starts_with)
171
171
172 if len(commit_hashes) != 1:
172 if len(commit_hashes) != 1:
173 return []
173 return []
174
174
175 commit_hash_prefix = commit_hashes[0]
175 commit_hash_prefix = commit_hashes[0]
176
176
177 auth_user = AuthUser(
177 auth_user = AuthUser(
178 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
178 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
179 searcher = searcher_from_config(config)
179 searcher = searcher_from_config(config)
180 result = searcher.search(
180 result = searcher.search(
181 'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user)
181 'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user)
182
182
183 return [
183 return [
184 {
184 {
185 'id': entry['commit_id'],
185 'id': entry['commit_id'],
186 'text': entry['commit_id'],
186 'text': entry['commit_id'],
187 'type': 'commit',
187 'type': 'commit',
188 'obj': {'repo': entry['repository']},
188 'obj': {'repo': entry['repository']},
189 'url': url('changeset_home',
189 'url': url('changeset_home',
190 repo_name=entry['repository'], revision=entry['commit_id'])
190 repo_name=entry['repository'], revision=entry['commit_id'])
191 }
191 }
192 for entry in result['results']]
192 for entry in result['results']]
193
193
194 @LoginRequired()
194 @LoginRequired()
195 @XHRRequired()
195 @XHRRequired()
196 @jsonify
196 @jsonify
197 def goto_switcher_data(self):
197 def goto_switcher_data(self):
198 query = request.GET.get('query')
198 query = request.GET.get('query')
199 log.debug('generating goto switcher list, query %s', query)
199 log.debug('generating goto switcher list, query %s', query)
200
200
201 res = []
201 res = []
202 repo_groups = self._get_repo_group_list(query)
202 repo_groups = self._get_repo_group_list(query)
203 if repo_groups:
203 if repo_groups:
204 res.append({
204 res.append({
205 'text': _('Groups'),
205 'text': _('Groups'),
206 'children': repo_groups
206 'children': repo_groups
207 })
207 })
208
208
209 repos = self._get_repo_list(query)
209 repos = self._get_repo_list(query)
210 if repos:
210 if repos:
211 res.append({
211 res.append({
212 'text': _('Repositories'),
212 'text': _('Repositories'),
213 'children': repos
213 'children': repos
214 })
214 })
215
215
216 commits = self._get_hash_commit_list(query)
216 commits = self._get_hash_commit_list(query)
217 if commits:
217 if commits:
218 unique_repos = {}
218 unique_repos = {}
219 for commit in commits:
219 for commit in commits:
220 unique_repos.setdefault(commit['obj']['repo'], []
220 unique_repos.setdefault(commit['obj']['repo'], []
221 ).append(commit)
221 ).append(commit)
222
222
223 for repo in unique_repos:
223 for repo in unique_repos:
224 res.append({
224 res.append({
225 'text': _('Commits in %(repo)s') % {'repo': repo},
225 'text': _('Commits in %(repo)s') % {'repo': repo},
226 'children': unique_repos[repo]
226 'children': unique_repos[repo]
227 })
227 })
228
228
229 data = {
229 data = {
230 'more': False,
230 'more': False,
231 'results': res
231 'results': res
232 }
232 }
233 return data
233 return data
234
234
235 @LoginRequired()
235 @LoginRequired()
236 @XHRRequired()
236 @XHRRequired()
237 @jsonify
237 @jsonify
238 def repo_list_data(self):
238 def repo_list_data(self):
239 query = request.GET.get('query')
239 query = request.GET.get('query')
240 repo_type = request.GET.get('repo_type')
240 repo_type = request.GET.get('repo_type')
241 log.debug('generating repo list, query:%s', query)
241 log.debug('generating repo list, query:%s', query)
242
242
243 res = []
243 res = []
244 repos = self._get_repo_list(query, repo_type=repo_type)
244 repos = self._get_repo_list(query, repo_type=repo_type)
245 if repos:
245 if repos:
246 res.append({
246 res.append({
247 'text': _('Repositories'),
247 'text': _('Repositories'),
248 'children': repos
248 'children': repos
249 })
249 })
250
250
251 data = {
251 data = {
252 'more': False,
252 'more': False,
253 'results': res
253 'results': res
254 }
254 }
255 return data
255 return data
256
256
257 @LoginRequired()
257 @LoginRequired()
258 @XHRRequired()
258 @XHRRequired()
259 @jsonify
259 @jsonify
260 def user_autocomplete_data(self):
260 def user_autocomplete_data(self):
261 query = request.GET.get('query')
261 query = request.GET.get('query')
262
262
263 repo_model = RepoModel()
263 repo_model = RepoModel()
264 _users = repo_model.get_users(name_contains=query)
264 _users = repo_model.get_users(name_contains=query)
265
265
266 if request.GET.get('user_groups'):
266 if request.GET.get('user_groups'):
267 # extend with user groups
267 # extend with user groups
268 _user_groups = repo_model.get_user_groups(name_contains=query)
268 _user_groups = repo_model.get_user_groups(name_contains=query)
269 _users = _users + _user_groups
269 _users = _users + _user_groups
270
270
271 return {'suggestions': _users}
271 return {'suggestions': _users}
272
272
273 @LoginRequired()
273 @LoginRequired()
274 @XHRRequired()
274 @XHRRequired()
275 @jsonify
275 @jsonify
276 def user_group_autocomplete_data(self):
276 def user_group_autocomplete_data(self):
277 return {'suggestions': []}
277 query = request.GET.get('query')
278
279 repo_model = RepoModel()
280 _user_groups = repo_model.get_user_groups(name_contains=query)
281 _user_groups = _user_groups
282
283 return {'suggestions': _user_groups}
284
@@ -1,918 +1,924 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 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 """
21 """
22 Repository model for rhodecode
22 Repository model for rhodecode
23 """
23 """
24
24
25 import logging
25 import logging
26 import os
26 import os
27 import re
27 import re
28 import shutil
28 import shutil
29 import time
29 import time
30 import traceback
30 import traceback
31 from datetime import datetime
31 from datetime import datetime
32
32
33 from sqlalchemy.sql import func
33 from sqlalchemy.sql import func
34 from sqlalchemy.sql.expression import true, or_
34 from sqlalchemy.sql.expression import true, or_
35 from zope.cachedescriptors.property import Lazy as LazyProperty
35 from zope.cachedescriptors.property import Lazy as LazyProperty
36
36
37 from rhodecode.lib import helpers as h
37 from rhodecode.lib import helpers as h
38 from rhodecode.lib.auth import HasUserGroupPermissionAny
38 from rhodecode.lib.auth import HasUserGroupPermissionAny
39 from rhodecode.lib.caching_query import FromCache
39 from rhodecode.lib.caching_query import FromCache
40 from rhodecode.lib.exceptions import AttachedForksError
40 from rhodecode.lib.exceptions import AttachedForksError
41 from rhodecode.lib.hooks_base import log_delete_repository
41 from rhodecode.lib.hooks_base import log_delete_repository
42 from rhodecode.lib.utils import make_db_config
42 from rhodecode.lib.utils import make_db_config
43 from rhodecode.lib.utils2 import (
43 from rhodecode.lib.utils2 import (
44 safe_str, safe_unicode, remove_prefix, obfuscate_url_pw,
44 safe_str, safe_unicode, remove_prefix, obfuscate_url_pw,
45 get_current_rhodecode_user, safe_int, datetime_to_time, action_logger_generic)
45 get_current_rhodecode_user, safe_int, datetime_to_time, action_logger_generic)
46 from rhodecode.lib.vcs.backends import get_backend
46 from rhodecode.lib.vcs.backends import get_backend
47 from rhodecode.model import BaseModel
47 from rhodecode.model import BaseModel
48 from rhodecode.model.db import (
48 from rhodecode.model.db import (
49 Repository, UserRepoToPerm, UserGroupRepoToPerm, UserRepoGroupToPerm,
49 Repository, UserRepoToPerm, UserGroupRepoToPerm, UserRepoGroupToPerm,
50 UserGroupRepoGroupToPerm, User, Permission, Statistics, UserGroup,
50 UserGroupRepoGroupToPerm, User, Permission, Statistics, UserGroup,
51 RepoGroup, RepositoryField)
51 RepoGroup, RepositoryField)
52 from rhodecode.model.scm import UserGroupList
52 from rhodecode.model.scm import UserGroupList
53 from rhodecode.model.settings import VcsSettingsModel
53 from rhodecode.model.settings import VcsSettingsModel
54
54
55
55
56 log = logging.getLogger(__name__)
56 log = logging.getLogger(__name__)
57
57
58
58
59 class RepoModel(BaseModel):
59 class RepoModel(BaseModel):
60
60
61 cls = Repository
61 cls = Repository
62
62
63 def _get_user_group(self, users_group):
63 def _get_user_group(self, users_group):
64 return self._get_instance(UserGroup, users_group,
64 return self._get_instance(UserGroup, users_group,
65 callback=UserGroup.get_by_group_name)
65 callback=UserGroup.get_by_group_name)
66
66
67 def _get_repo_group(self, repo_group):
67 def _get_repo_group(self, repo_group):
68 return self._get_instance(RepoGroup, repo_group,
68 return self._get_instance(RepoGroup, repo_group,
69 callback=RepoGroup.get_by_group_name)
69 callback=RepoGroup.get_by_group_name)
70
70
71 def _create_default_perms(self, repository, private):
71 def _create_default_perms(self, repository, private):
72 # create default permission
72 # create default permission
73 default = 'repository.read'
73 default = 'repository.read'
74 def_user = User.get_default_user()
74 def_user = User.get_default_user()
75 for p in def_user.user_perms:
75 for p in def_user.user_perms:
76 if p.permission.permission_name.startswith('repository.'):
76 if p.permission.permission_name.startswith('repository.'):
77 default = p.permission.permission_name
77 default = p.permission.permission_name
78 break
78 break
79
79
80 default_perm = 'repository.none' if private else default
80 default_perm = 'repository.none' if private else default
81
81
82 repo_to_perm = UserRepoToPerm()
82 repo_to_perm = UserRepoToPerm()
83 repo_to_perm.permission = Permission.get_by_key(default_perm)
83 repo_to_perm.permission = Permission.get_by_key(default_perm)
84
84
85 repo_to_perm.repository = repository
85 repo_to_perm.repository = repository
86 repo_to_perm.user_id = def_user.user_id
86 repo_to_perm.user_id = def_user.user_id
87
87
88 return repo_to_perm
88 return repo_to_perm
89
89
90 @LazyProperty
90 @LazyProperty
91 def repos_path(self):
91 def repos_path(self):
92 """
92 """
93 Gets the repositories root path from database
93 Gets the repositories root path from database
94 """
94 """
95 settings_model = VcsSettingsModel(sa=self.sa)
95 settings_model = VcsSettingsModel(sa=self.sa)
96 return settings_model.get_repos_location()
96 return settings_model.get_repos_location()
97
97
98 def get(self, repo_id, cache=False):
98 def get(self, repo_id, cache=False):
99 repo = self.sa.query(Repository) \
99 repo = self.sa.query(Repository) \
100 .filter(Repository.repo_id == repo_id)
100 .filter(Repository.repo_id == repo_id)
101
101
102 if cache:
102 if cache:
103 repo = repo.options(FromCache("sql_cache_short",
103 repo = repo.options(FromCache("sql_cache_short",
104 "get_repo_%s" % repo_id))
104 "get_repo_%s" % repo_id))
105 return repo.scalar()
105 return repo.scalar()
106
106
107 def get_repo(self, repository):
107 def get_repo(self, repository):
108 return self._get_repo(repository)
108 return self._get_repo(repository)
109
109
110 def get_by_repo_name(self, repo_name, cache=False):
110 def get_by_repo_name(self, repo_name, cache=False):
111 repo = self.sa.query(Repository) \
111 repo = self.sa.query(Repository) \
112 .filter(Repository.repo_name == repo_name)
112 .filter(Repository.repo_name == repo_name)
113
113
114 if cache:
114 if cache:
115 repo = repo.options(FromCache("sql_cache_short",
115 repo = repo.options(FromCache("sql_cache_short",
116 "get_repo_%s" % repo_name))
116 "get_repo_%s" % repo_name))
117 return repo.scalar()
117 return repo.scalar()
118
118
119 def _extract_id_from_repo_name(self, repo_name):
119 def _extract_id_from_repo_name(self, repo_name):
120 if repo_name.startswith('/'):
120 if repo_name.startswith('/'):
121 repo_name = repo_name.lstrip('/')
121 repo_name = repo_name.lstrip('/')
122 by_id_match = re.match(r'^_(\d{1,})', repo_name)
122 by_id_match = re.match(r'^_(\d{1,})', repo_name)
123 if by_id_match:
123 if by_id_match:
124 return by_id_match.groups()[0]
124 return by_id_match.groups()[0]
125
125
126 def get_repo_by_id(self, repo_name):
126 def get_repo_by_id(self, repo_name):
127 """
127 """
128 Extracts repo_name by id from special urls.
128 Extracts repo_name by id from special urls.
129 Example url is _11/repo_name
129 Example url is _11/repo_name
130
130
131 :param repo_name:
131 :param repo_name:
132 :return: repo object if matched else None
132 :return: repo object if matched else None
133 """
133 """
134 try:
134 try:
135 _repo_id = self._extract_id_from_repo_name(repo_name)
135 _repo_id = self._extract_id_from_repo_name(repo_name)
136 if _repo_id:
136 if _repo_id:
137 return self.get(_repo_id)
137 return self.get(_repo_id)
138 except Exception:
138 except Exception:
139 log.exception('Failed to extract repo_name from URL')
139 log.exception('Failed to extract repo_name from URL')
140
140
141 return None
141 return None
142
142
143 def get_users(self, name_contains=None, limit=20):
143 def get_users(self, name_contains=None, limit=20, only_active=True):
144 # TODO: mikhail: move this method to the UserModel.
144 # TODO: mikhail: move this method to the UserModel.
145 query = self.sa.query(User)
145 query = self.sa.query(User)
146 if only_active:
146 query = query.filter(User.active == true())
147 query = query.filter(User.active == true())
148
147 if name_contains:
149 if name_contains:
148 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
150 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
149 query = query.filter(
151 query = query.filter(
150 or_(
152 or_(
151 User.name.ilike(ilike_expression),
153 User.name.ilike(ilike_expression),
152 User.lastname.ilike(ilike_expression),
154 User.lastname.ilike(ilike_expression),
153 User.username.ilike(ilike_expression)
155 User.username.ilike(ilike_expression)
154 )
156 )
155 )
157 )
156 query = query.limit(limit)
158 query = query.limit(limit)
157 users = query.all()
159 users = query.all()
158
160
159 _users = [
161 _users = [
160 {
162 {
161 'id': user.user_id,
163 'id': user.user_id,
162 'first_name': user.name,
164 'first_name': user.name,
163 'last_name': user.lastname,
165 'last_name': user.lastname,
164 'username': user.username,
166 'username': user.username,
165 'icon_link': h.gravatar_url(user.email, 14),
167 'icon_link': h.gravatar_url(user.email, 14),
166 'value_display': h.person(user.email),
168 'value_display': h.person(user.email),
167 'value': user.username,
169 'value': user.username,
168 'value_type': 'user'
170 'value_type': 'user',
171 'active': user.active,
169 }
172 }
170 for user in users
173 for user in users
171 ]
174 ]
172 return _users
175 return _users
173
176
174 def get_user_groups(self, name_contains=None, limit=20):
177 def get_user_groups(self, name_contains=None, limit=20, only_active=True):
175 # TODO: mikhail: move this method to the UserGroupModel.
178 # TODO: mikhail: move this method to the UserGroupModel.
176 query = self.sa.query(UserGroup)
179 query = self.sa.query(UserGroup)
180 if only_active:
177 query = query.filter(UserGroup.users_group_active == true())
181 query = query.filter(UserGroup.users_group_active == true())
182
178 if name_contains:
183 if name_contains:
179 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
184 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
180 query = query.filter(
185 query = query.filter(
181 UserGroup.users_group_name.ilike(ilike_expression))\
186 UserGroup.users_group_name.ilike(ilike_expression))\
182 .order_by(func.length(UserGroup.users_group_name))\
187 .order_by(func.length(UserGroup.users_group_name))\
183 .order_by(UserGroup.users_group_name)
188 .order_by(UserGroup.users_group_name)
184
189
185 query = query.limit(limit)
190 query = query.limit(limit)
186 user_groups = query.all()
191 user_groups = query.all()
187 perm_set = ['usergroup.read', 'usergroup.write', 'usergroup.admin']
192 perm_set = ['usergroup.read', 'usergroup.write', 'usergroup.admin']
188 user_groups = UserGroupList(user_groups, perm_set=perm_set)
193 user_groups = UserGroupList(user_groups, perm_set=perm_set)
189
194
190 _groups = [
195 _groups = [
191 {
196 {
192 'id': group.users_group_id,
197 'id': group.users_group_id,
193 # TODO: marcink figure out a way to generate the url for the
198 # TODO: marcink figure out a way to generate the url for the
194 # icon
199 # icon
195 'icon_link': '',
200 'icon_link': '',
196 'value_display': 'Group: %s (%d members)' % (
201 'value_display': 'Group: %s (%d members)' % (
197 group.users_group_name, len(group.members),),
202 group.users_group_name, len(group.members),),
198 'value': group.users_group_name,
203 'value': group.users_group_name,
199 'value_type': 'user_group'
204 'value_type': 'user_group',
205 'active': group.users_group_active,
200 }
206 }
201 for group in user_groups
207 for group in user_groups
202 ]
208 ]
203 return _groups
209 return _groups
204
210
205 @classmethod
211 @classmethod
206 def update_repoinfo(cls, repositories=None):
212 def update_repoinfo(cls, repositories=None):
207 if not repositories:
213 if not repositories:
208 repositories = Repository.getAll()
214 repositories = Repository.getAll()
209 for repo in repositories:
215 for repo in repositories:
210 repo.update_commit_cache()
216 repo.update_commit_cache()
211
217
212 def get_repos_as_dict(self, repo_list=None, admin=False,
218 def get_repos_as_dict(self, repo_list=None, admin=False,
213 super_user_actions=False):
219 super_user_actions=False):
214
220
215 from rhodecode.lib.utils import PartialRenderer
221 from rhodecode.lib.utils import PartialRenderer
216 _render = PartialRenderer('data_table/_dt_elements.html')
222 _render = PartialRenderer('data_table/_dt_elements.html')
217 c = _render.c
223 c = _render.c
218
224
219 def quick_menu(repo_name):
225 def quick_menu(repo_name):
220 return _render('quick_menu', repo_name)
226 return _render('quick_menu', repo_name)
221
227
222 def repo_lnk(name, rtype, rstate, private, fork_of):
228 def repo_lnk(name, rtype, rstate, private, fork_of):
223 return _render('repo_name', name, rtype, rstate, private, fork_of,
229 return _render('repo_name', name, rtype, rstate, private, fork_of,
224 short_name=not admin, admin=False)
230 short_name=not admin, admin=False)
225
231
226 def last_change(last_change):
232 def last_change(last_change):
227 return _render("last_change", last_change)
233 return _render("last_change", last_change)
228
234
229 def rss_lnk(repo_name):
235 def rss_lnk(repo_name):
230 return _render("rss", repo_name)
236 return _render("rss", repo_name)
231
237
232 def atom_lnk(repo_name):
238 def atom_lnk(repo_name):
233 return _render("atom", repo_name)
239 return _render("atom", repo_name)
234
240
235 def last_rev(repo_name, cs_cache):
241 def last_rev(repo_name, cs_cache):
236 return _render('revision', repo_name, cs_cache.get('revision'),
242 return _render('revision', repo_name, cs_cache.get('revision'),
237 cs_cache.get('raw_id'), cs_cache.get('author'),
243 cs_cache.get('raw_id'), cs_cache.get('author'),
238 cs_cache.get('message'))
244 cs_cache.get('message'))
239
245
240 def desc(desc):
246 def desc(desc):
241 if c.visual.stylify_metatags:
247 if c.visual.stylify_metatags:
242 return h.urlify_text(h.escaped_stylize(h.truncate(desc, 60)))
248 return h.urlify_text(h.escaped_stylize(h.truncate(desc, 60)))
243 else:
249 else:
244 return h.urlify_text(h.html_escape(h.truncate(desc, 60)))
250 return h.urlify_text(h.html_escape(h.truncate(desc, 60)))
245
251
246 def state(repo_state):
252 def state(repo_state):
247 return _render("repo_state", repo_state)
253 return _render("repo_state", repo_state)
248
254
249 def repo_actions(repo_name):
255 def repo_actions(repo_name):
250 return _render('repo_actions', repo_name, super_user_actions)
256 return _render('repo_actions', repo_name, super_user_actions)
251
257
252 def user_profile(username):
258 def user_profile(username):
253 return _render('user_profile', username)
259 return _render('user_profile', username)
254
260
255 repos_data = []
261 repos_data = []
256 for repo in repo_list:
262 for repo in repo_list:
257 cs_cache = repo.changeset_cache
263 cs_cache = repo.changeset_cache
258 row = {
264 row = {
259 "menu": quick_menu(repo.repo_name),
265 "menu": quick_menu(repo.repo_name),
260
266
261 "name": repo_lnk(repo.repo_name, repo.repo_type,
267 "name": repo_lnk(repo.repo_name, repo.repo_type,
262 repo.repo_state, repo.private, repo.fork),
268 repo.repo_state, repo.private, repo.fork),
263 "name_raw": repo.repo_name.lower(),
269 "name_raw": repo.repo_name.lower(),
264
270
265 "last_change": last_change(repo.last_db_change),
271 "last_change": last_change(repo.last_db_change),
266 "last_change_raw": datetime_to_time(repo.last_db_change),
272 "last_change_raw": datetime_to_time(repo.last_db_change),
267
273
268 "last_changeset": last_rev(repo.repo_name, cs_cache),
274 "last_changeset": last_rev(repo.repo_name, cs_cache),
269 "last_changeset_raw": cs_cache.get('revision'),
275 "last_changeset_raw": cs_cache.get('revision'),
270
276
271 "desc": desc(repo.description),
277 "desc": desc(repo.description),
272 "owner": user_profile(repo.user.username),
278 "owner": user_profile(repo.user.username),
273
279
274 "state": state(repo.repo_state),
280 "state": state(repo.repo_state),
275 "rss": rss_lnk(repo.repo_name),
281 "rss": rss_lnk(repo.repo_name),
276
282
277 "atom": atom_lnk(repo.repo_name),
283 "atom": atom_lnk(repo.repo_name),
278 }
284 }
279 if admin:
285 if admin:
280 row.update({
286 row.update({
281 "action": repo_actions(repo.repo_name),
287 "action": repo_actions(repo.repo_name),
282 })
288 })
283 repos_data.append(row)
289 repos_data.append(row)
284
290
285 return repos_data
291 return repos_data
286
292
287 def _get_defaults(self, repo_name):
293 def _get_defaults(self, repo_name):
288 """
294 """
289 Gets information about repository, and returns a dict for
295 Gets information about repository, and returns a dict for
290 usage in forms
296 usage in forms
291
297
292 :param repo_name:
298 :param repo_name:
293 """
299 """
294
300
295 repo_info = Repository.get_by_repo_name(repo_name)
301 repo_info = Repository.get_by_repo_name(repo_name)
296
302
297 if repo_info is None:
303 if repo_info is None:
298 return None
304 return None
299
305
300 defaults = repo_info.get_dict()
306 defaults = repo_info.get_dict()
301 defaults['repo_name'] = repo_info.just_name
307 defaults['repo_name'] = repo_info.just_name
302
308
303 groups = repo_info.groups_with_parents
309 groups = repo_info.groups_with_parents
304 parent_group = groups[-1] if groups else None
310 parent_group = groups[-1] if groups else None
305
311
306 # we use -1 as this is how in HTML, we mark an empty group
312 # we use -1 as this is how in HTML, we mark an empty group
307 defaults['repo_group'] = getattr(parent_group, 'group_id', -1)
313 defaults['repo_group'] = getattr(parent_group, 'group_id', -1)
308
314
309 keys_to_process = (
315 keys_to_process = (
310 {'k': 'repo_type', 'strip': False},
316 {'k': 'repo_type', 'strip': False},
311 {'k': 'repo_enable_downloads', 'strip': True},
317 {'k': 'repo_enable_downloads', 'strip': True},
312 {'k': 'repo_description', 'strip': True},
318 {'k': 'repo_description', 'strip': True},
313 {'k': 'repo_enable_locking', 'strip': True},
319 {'k': 'repo_enable_locking', 'strip': True},
314 {'k': 'repo_landing_rev', 'strip': True},
320 {'k': 'repo_landing_rev', 'strip': True},
315 {'k': 'clone_uri', 'strip': False},
321 {'k': 'clone_uri', 'strip': False},
316 {'k': 'repo_private', 'strip': True},
322 {'k': 'repo_private', 'strip': True},
317 {'k': 'repo_enable_statistics', 'strip': True}
323 {'k': 'repo_enable_statistics', 'strip': True}
318 )
324 )
319
325
320 for item in keys_to_process:
326 for item in keys_to_process:
321 attr = item['k']
327 attr = item['k']
322 if item['strip']:
328 if item['strip']:
323 attr = remove_prefix(item['k'], 'repo_')
329 attr = remove_prefix(item['k'], 'repo_')
324
330
325 val = defaults[attr]
331 val = defaults[attr]
326 if item['k'] == 'repo_landing_rev':
332 if item['k'] == 'repo_landing_rev':
327 val = ':'.join(defaults[attr])
333 val = ':'.join(defaults[attr])
328 defaults[item['k']] = val
334 defaults[item['k']] = val
329 if item['k'] == 'clone_uri':
335 if item['k'] == 'clone_uri':
330 defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
336 defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden
331
337
332 # fill owner
338 # fill owner
333 if repo_info.user:
339 if repo_info.user:
334 defaults.update({'user': repo_info.user.username})
340 defaults.update({'user': repo_info.user.username})
335 else:
341 else:
336 replacement_user = User.get_first_admin().username
342 replacement_user = User.get_first_admin().username
337 defaults.update({'user': replacement_user})
343 defaults.update({'user': replacement_user})
338
344
339 # fill repository users
345 # fill repository users
340 for p in repo_info.repo_to_perm:
346 for p in repo_info.repo_to_perm:
341 defaults.update({'u_perm_%s' % p.user.user_id:
347 defaults.update({'u_perm_%s' % p.user.user_id:
342 p.permission.permission_name})
348 p.permission.permission_name})
343
349
344 # fill repository groups
350 # fill repository groups
345 for p in repo_info.users_group_to_perm:
351 for p in repo_info.users_group_to_perm:
346 defaults.update({'g_perm_%s' % p.users_group.users_group_id:
352 defaults.update({'g_perm_%s' % p.users_group.users_group_id:
347 p.permission.permission_name})
353 p.permission.permission_name})
348
354
349 return defaults
355 return defaults
350
356
351 def update(self, repo, **kwargs):
357 def update(self, repo, **kwargs):
352 try:
358 try:
353 cur_repo = self._get_repo(repo)
359 cur_repo = self._get_repo(repo)
354 source_repo_name = cur_repo.repo_name
360 source_repo_name = cur_repo.repo_name
355 if 'user' in kwargs:
361 if 'user' in kwargs:
356 cur_repo.user = User.get_by_username(kwargs['user'])
362 cur_repo.user = User.get_by_username(kwargs['user'])
357
363
358 if 'repo_group' in kwargs:
364 if 'repo_group' in kwargs:
359 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
365 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
360 log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
366 log.debug('Updating repo %s with params:%s', cur_repo, kwargs)
361
367
362 update_keys = [
368 update_keys = [
363 (1, 'repo_enable_downloads'),
369 (1, 'repo_enable_downloads'),
364 (1, 'repo_description'),
370 (1, 'repo_description'),
365 (1, 'repo_enable_locking'),
371 (1, 'repo_enable_locking'),
366 (1, 'repo_landing_rev'),
372 (1, 'repo_landing_rev'),
367 (1, 'repo_private'),
373 (1, 'repo_private'),
368 (1, 'repo_enable_statistics'),
374 (1, 'repo_enable_statistics'),
369 (0, 'clone_uri'),
375 (0, 'clone_uri'),
370 (0, 'fork_id')
376 (0, 'fork_id')
371 ]
377 ]
372 for strip, k in update_keys:
378 for strip, k in update_keys:
373 if k in kwargs:
379 if k in kwargs:
374 val = kwargs[k]
380 val = kwargs[k]
375 if strip:
381 if strip:
376 k = remove_prefix(k, 'repo_')
382 k = remove_prefix(k, 'repo_')
377 if k == 'clone_uri':
383 if k == 'clone_uri':
378 from rhodecode.model.validators import Missing
384 from rhodecode.model.validators import Missing
379 _change = kwargs.get('clone_uri_change')
385 _change = kwargs.get('clone_uri_change')
380 if _change in [Missing, 'OLD']:
386 if _change in [Missing, 'OLD']:
381 # we don't change the value, so use original one
387 # we don't change the value, so use original one
382 val = cur_repo.clone_uri
388 val = cur_repo.clone_uri
383
389
384 setattr(cur_repo, k, val)
390 setattr(cur_repo, k, val)
385
391
386 new_name = cur_repo.get_new_name(kwargs['repo_name'])
392 new_name = cur_repo.get_new_name(kwargs['repo_name'])
387 cur_repo.repo_name = new_name
393 cur_repo.repo_name = new_name
388
394
389 # if private flag is set, reset default permission to NONE
395 # if private flag is set, reset default permission to NONE
390 if kwargs.get('repo_private'):
396 if kwargs.get('repo_private'):
391 EMPTY_PERM = 'repository.none'
397 EMPTY_PERM = 'repository.none'
392 RepoModel().grant_user_permission(
398 RepoModel().grant_user_permission(
393 repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM
399 repo=cur_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM
394 )
400 )
395
401
396 # handle extra fields
402 # handle extra fields
397 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX),
403 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX),
398 kwargs):
404 kwargs):
399 k = RepositoryField.un_prefix_key(field)
405 k = RepositoryField.un_prefix_key(field)
400 ex_field = RepositoryField.get_by_key_name(
406 ex_field = RepositoryField.get_by_key_name(
401 key=k, repo=cur_repo)
407 key=k, repo=cur_repo)
402 if ex_field:
408 if ex_field:
403 ex_field.field_value = kwargs[field]
409 ex_field.field_value = kwargs[field]
404 self.sa.add(ex_field)
410 self.sa.add(ex_field)
405 self.sa.add(cur_repo)
411 self.sa.add(cur_repo)
406
412
407 if source_repo_name != new_name:
413 if source_repo_name != new_name:
408 # rename repository
414 # rename repository
409 self._rename_filesystem_repo(
415 self._rename_filesystem_repo(
410 old=source_repo_name, new=new_name)
416 old=source_repo_name, new=new_name)
411
417
412 return cur_repo
418 return cur_repo
413 except Exception:
419 except Exception:
414 log.error(traceback.format_exc())
420 log.error(traceback.format_exc())
415 raise
421 raise
416
422
417 def _create_repo(self, repo_name, repo_type, description, owner,
423 def _create_repo(self, repo_name, repo_type, description, owner,
418 private=False, clone_uri=None, repo_group=None,
424 private=False, clone_uri=None, repo_group=None,
419 landing_rev='rev:tip', fork_of=None,
425 landing_rev='rev:tip', fork_of=None,
420 copy_fork_permissions=False, enable_statistics=False,
426 copy_fork_permissions=False, enable_statistics=False,
421 enable_locking=False, enable_downloads=False,
427 enable_locking=False, enable_downloads=False,
422 copy_group_permissions=False,
428 copy_group_permissions=False,
423 state=Repository.STATE_PENDING):
429 state=Repository.STATE_PENDING):
424 """
430 """
425 Create repository inside database with PENDING state, this should be
431 Create repository inside database with PENDING state, this should be
426 only executed by create() repo. With exception of importing existing
432 only executed by create() repo. With exception of importing existing
427 repos
433 repos
428 """
434 """
429 from rhodecode.model.scm import ScmModel
435 from rhodecode.model.scm import ScmModel
430
436
431 owner = self._get_user(owner)
437 owner = self._get_user(owner)
432 fork_of = self._get_repo(fork_of)
438 fork_of = self._get_repo(fork_of)
433 repo_group = self._get_repo_group(safe_int(repo_group))
439 repo_group = self._get_repo_group(safe_int(repo_group))
434
440
435 try:
441 try:
436 repo_name = safe_unicode(repo_name)
442 repo_name = safe_unicode(repo_name)
437 description = safe_unicode(description)
443 description = safe_unicode(description)
438 # repo name is just a name of repository
444 # repo name is just a name of repository
439 # while repo_name_full is a full qualified name that is combined
445 # while repo_name_full is a full qualified name that is combined
440 # with name and path of group
446 # with name and path of group
441 repo_name_full = repo_name
447 repo_name_full = repo_name
442 repo_name = repo_name.split(Repository.NAME_SEP)[-1]
448 repo_name = repo_name.split(Repository.NAME_SEP)[-1]
443
449
444 new_repo = Repository()
450 new_repo = Repository()
445 new_repo.repo_state = state
451 new_repo.repo_state = state
446 new_repo.enable_statistics = False
452 new_repo.enable_statistics = False
447 new_repo.repo_name = repo_name_full
453 new_repo.repo_name = repo_name_full
448 new_repo.repo_type = repo_type
454 new_repo.repo_type = repo_type
449 new_repo.user = owner
455 new_repo.user = owner
450 new_repo.group = repo_group
456 new_repo.group = repo_group
451 new_repo.description = description or repo_name
457 new_repo.description = description or repo_name
452 new_repo.private = private
458 new_repo.private = private
453 new_repo.clone_uri = clone_uri
459 new_repo.clone_uri = clone_uri
454 new_repo.landing_rev = landing_rev
460 new_repo.landing_rev = landing_rev
455
461
456 new_repo.enable_statistics = enable_statistics
462 new_repo.enable_statistics = enable_statistics
457 new_repo.enable_locking = enable_locking
463 new_repo.enable_locking = enable_locking
458 new_repo.enable_downloads = enable_downloads
464 new_repo.enable_downloads = enable_downloads
459
465
460 if repo_group:
466 if repo_group:
461 new_repo.enable_locking = repo_group.enable_locking
467 new_repo.enable_locking = repo_group.enable_locking
462
468
463 if fork_of:
469 if fork_of:
464 parent_repo = fork_of
470 parent_repo = fork_of
465 new_repo.fork = parent_repo
471 new_repo.fork = parent_repo
466
472
467 self.sa.add(new_repo)
473 self.sa.add(new_repo)
468
474
469 EMPTY_PERM = 'repository.none'
475 EMPTY_PERM = 'repository.none'
470 if fork_of and copy_fork_permissions:
476 if fork_of and copy_fork_permissions:
471 repo = fork_of
477 repo = fork_of
472 user_perms = UserRepoToPerm.query() \
478 user_perms = UserRepoToPerm.query() \
473 .filter(UserRepoToPerm.repository == repo).all()
479 .filter(UserRepoToPerm.repository == repo).all()
474 group_perms = UserGroupRepoToPerm.query() \
480 group_perms = UserGroupRepoToPerm.query() \
475 .filter(UserGroupRepoToPerm.repository == repo).all()
481 .filter(UserGroupRepoToPerm.repository == repo).all()
476
482
477 for perm in user_perms:
483 for perm in user_perms:
478 UserRepoToPerm.create(
484 UserRepoToPerm.create(
479 perm.user, new_repo, perm.permission)
485 perm.user, new_repo, perm.permission)
480
486
481 for perm in group_perms:
487 for perm in group_perms:
482 UserGroupRepoToPerm.create(
488 UserGroupRepoToPerm.create(
483 perm.users_group, new_repo, perm.permission)
489 perm.users_group, new_repo, perm.permission)
484 # in case we copy permissions and also set this repo to private
490 # in case we copy permissions and also set this repo to private
485 # override the default user permission to make it a private
491 # override the default user permission to make it a private
486 # repo
492 # repo
487 if private:
493 if private:
488 RepoModel(self.sa).grant_user_permission(
494 RepoModel(self.sa).grant_user_permission(
489 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
495 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
490
496
491 elif repo_group and copy_group_permissions:
497 elif repo_group and copy_group_permissions:
492 user_perms = UserRepoGroupToPerm.query() \
498 user_perms = UserRepoGroupToPerm.query() \
493 .filter(UserRepoGroupToPerm.group == repo_group).all()
499 .filter(UserRepoGroupToPerm.group == repo_group).all()
494
500
495 group_perms = UserGroupRepoGroupToPerm.query() \
501 group_perms = UserGroupRepoGroupToPerm.query() \
496 .filter(UserGroupRepoGroupToPerm.group == repo_group).all()
502 .filter(UserGroupRepoGroupToPerm.group == repo_group).all()
497
503
498 for perm in user_perms:
504 for perm in user_perms:
499 perm_name = perm.permission.permission_name.replace(
505 perm_name = perm.permission.permission_name.replace(
500 'group.', 'repository.')
506 'group.', 'repository.')
501 perm_obj = Permission.get_by_key(perm_name)
507 perm_obj = Permission.get_by_key(perm_name)
502 UserRepoToPerm.create(perm.user, new_repo, perm_obj)
508 UserRepoToPerm.create(perm.user, new_repo, perm_obj)
503
509
504 for perm in group_perms:
510 for perm in group_perms:
505 perm_name = perm.permission.permission_name.replace(
511 perm_name = perm.permission.permission_name.replace(
506 'group.', 'repository.')
512 'group.', 'repository.')
507 perm_obj = Permission.get_by_key(perm_name)
513 perm_obj = Permission.get_by_key(perm_name)
508 UserGroupRepoToPerm.create(
514 UserGroupRepoToPerm.create(
509 perm.users_group, new_repo, perm_obj)
515 perm.users_group, new_repo, perm_obj)
510
516
511 if private:
517 if private:
512 RepoModel(self.sa).grant_user_permission(
518 RepoModel(self.sa).grant_user_permission(
513 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
519 repo=new_repo, user=User.DEFAULT_USER, perm=EMPTY_PERM)
514
520
515 else:
521 else:
516 perm_obj = self._create_default_perms(new_repo, private)
522 perm_obj = self._create_default_perms(new_repo, private)
517 self.sa.add(perm_obj)
523 self.sa.add(perm_obj)
518
524
519 # now automatically start following this repository as owner
525 # now automatically start following this repository as owner
520 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
526 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
521 owner.user_id)
527 owner.user_id)
522 # we need to flush here, in order to check if database won't
528 # we need to flush here, in order to check if database won't
523 # throw any exceptions, create filesystem dirs at the very end
529 # throw any exceptions, create filesystem dirs at the very end
524 self.sa.flush()
530 self.sa.flush()
525
531
526 return new_repo
532 return new_repo
527 except Exception:
533 except Exception:
528 log.error(traceback.format_exc())
534 log.error(traceback.format_exc())
529 raise
535 raise
530
536
531 def create(self, form_data, cur_user):
537 def create(self, form_data, cur_user):
532 """
538 """
533 Create repository using celery tasks
539 Create repository using celery tasks
534
540
535 :param form_data:
541 :param form_data:
536 :param cur_user:
542 :param cur_user:
537 """
543 """
538 from rhodecode.lib.celerylib import tasks, run_task
544 from rhodecode.lib.celerylib import tasks, run_task
539 return run_task(tasks.create_repo, form_data, cur_user)
545 return run_task(tasks.create_repo, form_data, cur_user)
540
546
541 def update_permissions(self, repo, perm_additions=None, perm_updates=None,
547 def update_permissions(self, repo, perm_additions=None, perm_updates=None,
542 perm_deletions=None, check_perms=True,
548 perm_deletions=None, check_perms=True,
543 cur_user=None):
549 cur_user=None):
544 if not perm_additions:
550 if not perm_additions:
545 perm_additions = []
551 perm_additions = []
546 if not perm_updates:
552 if not perm_updates:
547 perm_updates = []
553 perm_updates = []
548 if not perm_deletions:
554 if not perm_deletions:
549 perm_deletions = []
555 perm_deletions = []
550
556
551 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
557 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
552
558
553 # update permissions
559 # update permissions
554 for member_id, perm, member_type in perm_updates:
560 for member_id, perm, member_type in perm_updates:
555 member_id = int(member_id)
561 member_id = int(member_id)
556 if member_type == 'user':
562 if member_type == 'user':
557 # this updates also current one if found
563 # this updates also current one if found
558 self.grant_user_permission(
564 self.grant_user_permission(
559 repo=repo, user=member_id, perm=perm)
565 repo=repo, user=member_id, perm=perm)
560 else: # set for user group
566 else: # set for user group
561 # check if we have permissions to alter this usergroup
567 # check if we have permissions to alter this usergroup
562 member_name = UserGroup.get(member_id).users_group_name
568 member_name = UserGroup.get(member_id).users_group_name
563 if not check_perms or HasUserGroupPermissionAny(
569 if not check_perms or HasUserGroupPermissionAny(
564 *req_perms)(member_name, user=cur_user):
570 *req_perms)(member_name, user=cur_user):
565 self.grant_user_group_permission(
571 self.grant_user_group_permission(
566 repo=repo, group_name=member_id, perm=perm)
572 repo=repo, group_name=member_id, perm=perm)
567
573
568 # set new permissions
574 # set new permissions
569 for member_id, perm, member_type in perm_additions:
575 for member_id, perm, member_type in perm_additions:
570 member_id = int(member_id)
576 member_id = int(member_id)
571 if member_type == 'user':
577 if member_type == 'user':
572 self.grant_user_permission(
578 self.grant_user_permission(
573 repo=repo, user=member_id, perm=perm)
579 repo=repo, user=member_id, perm=perm)
574 else: # set for user group
580 else: # set for user group
575 # check if we have permissions to alter this usergroup
581 # check if we have permissions to alter this usergroup
576 member_name = UserGroup.get(member_id).users_group_name
582 member_name = UserGroup.get(member_id).users_group_name
577 if not check_perms or HasUserGroupPermissionAny(
583 if not check_perms or HasUserGroupPermissionAny(
578 *req_perms)(member_name, user=cur_user):
584 *req_perms)(member_name, user=cur_user):
579 self.grant_user_group_permission(
585 self.grant_user_group_permission(
580 repo=repo, group_name=member_id, perm=perm)
586 repo=repo, group_name=member_id, perm=perm)
581
587
582 # delete permissions
588 # delete permissions
583 for member_id, perm, member_type in perm_deletions:
589 for member_id, perm, member_type in perm_deletions:
584 member_id = int(member_id)
590 member_id = int(member_id)
585 if member_type == 'user':
591 if member_type == 'user':
586 self.revoke_user_permission(repo=repo, user=member_id)
592 self.revoke_user_permission(repo=repo, user=member_id)
587 else: # set for user group
593 else: # set for user group
588 # check if we have permissions to alter this usergroup
594 # check if we have permissions to alter this usergroup
589 member_name = UserGroup.get(member_id).users_group_name
595 member_name = UserGroup.get(member_id).users_group_name
590 if not check_perms or HasUserGroupPermissionAny(
596 if not check_perms or HasUserGroupPermissionAny(
591 *req_perms)(member_name, user=cur_user):
597 *req_perms)(member_name, user=cur_user):
592 self.revoke_user_group_permission(
598 self.revoke_user_group_permission(
593 repo=repo, group_name=member_id)
599 repo=repo, group_name=member_id)
594
600
595 def create_fork(self, form_data, cur_user):
601 def create_fork(self, form_data, cur_user):
596 """
602 """
597 Simple wrapper into executing celery task for fork creation
603 Simple wrapper into executing celery task for fork creation
598
604
599 :param form_data:
605 :param form_data:
600 :param cur_user:
606 :param cur_user:
601 """
607 """
602 from rhodecode.lib.celerylib import tasks, run_task
608 from rhodecode.lib.celerylib import tasks, run_task
603 return run_task(tasks.create_repo_fork, form_data, cur_user)
609 return run_task(tasks.create_repo_fork, form_data, cur_user)
604
610
605 def delete(self, repo, forks=None, fs_remove=True, cur_user=None):
611 def delete(self, repo, forks=None, fs_remove=True, cur_user=None):
606 """
612 """
607 Delete given repository, forks parameter defines what do do with
613 Delete given repository, forks parameter defines what do do with
608 attached forks. Throws AttachedForksError if deleted repo has attached
614 attached forks. Throws AttachedForksError if deleted repo has attached
609 forks
615 forks
610
616
611 :param repo:
617 :param repo:
612 :param forks: str 'delete' or 'detach'
618 :param forks: str 'delete' or 'detach'
613 :param fs_remove: remove(archive) repo from filesystem
619 :param fs_remove: remove(archive) repo from filesystem
614 """
620 """
615 if not cur_user:
621 if not cur_user:
616 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
622 cur_user = getattr(get_current_rhodecode_user(), 'username', None)
617 repo = self._get_repo(repo)
623 repo = self._get_repo(repo)
618 if repo:
624 if repo:
619 if forks == 'detach':
625 if forks == 'detach':
620 for r in repo.forks:
626 for r in repo.forks:
621 r.fork = None
627 r.fork = None
622 self.sa.add(r)
628 self.sa.add(r)
623 elif forks == 'delete':
629 elif forks == 'delete':
624 for r in repo.forks:
630 for r in repo.forks:
625 self.delete(r, forks='delete')
631 self.delete(r, forks='delete')
626 elif [f for f in repo.forks]:
632 elif [f for f in repo.forks]:
627 raise AttachedForksError()
633 raise AttachedForksError()
628
634
629 old_repo_dict = repo.get_dict()
635 old_repo_dict = repo.get_dict()
630 try:
636 try:
631 self.sa.delete(repo)
637 self.sa.delete(repo)
632 if fs_remove:
638 if fs_remove:
633 self._delete_filesystem_repo(repo)
639 self._delete_filesystem_repo(repo)
634 else:
640 else:
635 log.debug('skipping removal from filesystem')
641 log.debug('skipping removal from filesystem')
636 old_repo_dict.update({
642 old_repo_dict.update({
637 'deleted_by': cur_user,
643 'deleted_by': cur_user,
638 'deleted_on': time.time(),
644 'deleted_on': time.time(),
639 })
645 })
640 log_delete_repository(**old_repo_dict)
646 log_delete_repository(**old_repo_dict)
641 except Exception:
647 except Exception:
642 log.error(traceback.format_exc())
648 log.error(traceback.format_exc())
643 raise
649 raise
644
650
645 def grant_user_permission(self, repo, user, perm):
651 def grant_user_permission(self, repo, user, perm):
646 """
652 """
647 Grant permission for user on given repository, or update existing one
653 Grant permission for user on given repository, or update existing one
648 if found
654 if found
649
655
650 :param repo: Instance of Repository, repository_id, or repository name
656 :param repo: Instance of Repository, repository_id, or repository name
651 :param user: Instance of User, user_id or username
657 :param user: Instance of User, user_id or username
652 :param perm: Instance of Permission, or permission_name
658 :param perm: Instance of Permission, or permission_name
653 """
659 """
654 user = self._get_user(user)
660 user = self._get_user(user)
655 repo = self._get_repo(repo)
661 repo = self._get_repo(repo)
656 permission = self._get_perm(perm)
662 permission = self._get_perm(perm)
657
663
658 # check if we have that permission already
664 # check if we have that permission already
659 obj = self.sa.query(UserRepoToPerm) \
665 obj = self.sa.query(UserRepoToPerm) \
660 .filter(UserRepoToPerm.user == user) \
666 .filter(UserRepoToPerm.user == user) \
661 .filter(UserRepoToPerm.repository == repo) \
667 .filter(UserRepoToPerm.repository == repo) \
662 .scalar()
668 .scalar()
663 if obj is None:
669 if obj is None:
664 # create new !
670 # create new !
665 obj = UserRepoToPerm()
671 obj = UserRepoToPerm()
666 obj.repository = repo
672 obj.repository = repo
667 obj.user = user
673 obj.user = user
668 obj.permission = permission
674 obj.permission = permission
669 self.sa.add(obj)
675 self.sa.add(obj)
670 log.debug('Granted perm %s to %s on %s', perm, user, repo)
676 log.debug('Granted perm %s to %s on %s', perm, user, repo)
671 action_logger_generic(
677 action_logger_generic(
672 'granted permission: {} to user: {} on repo: {}'.format(
678 'granted permission: {} to user: {} on repo: {}'.format(
673 perm, user, repo), namespace='security.repo')
679 perm, user, repo), namespace='security.repo')
674 return obj
680 return obj
675
681
676 def revoke_user_permission(self, repo, user):
682 def revoke_user_permission(self, repo, user):
677 """
683 """
678 Revoke permission for user on given repository
684 Revoke permission for user on given repository
679
685
680 :param repo: Instance of Repository, repository_id, or repository name
686 :param repo: Instance of Repository, repository_id, or repository name
681 :param user: Instance of User, user_id or username
687 :param user: Instance of User, user_id or username
682 """
688 """
683
689
684 user = self._get_user(user)
690 user = self._get_user(user)
685 repo = self._get_repo(repo)
691 repo = self._get_repo(repo)
686
692
687 obj = self.sa.query(UserRepoToPerm) \
693 obj = self.sa.query(UserRepoToPerm) \
688 .filter(UserRepoToPerm.repository == repo) \
694 .filter(UserRepoToPerm.repository == repo) \
689 .filter(UserRepoToPerm.user == user) \
695 .filter(UserRepoToPerm.user == user) \
690 .scalar()
696 .scalar()
691 if obj:
697 if obj:
692 self.sa.delete(obj)
698 self.sa.delete(obj)
693 log.debug('Revoked perm on %s on %s', repo, user)
699 log.debug('Revoked perm on %s on %s', repo, user)
694 action_logger_generic(
700 action_logger_generic(
695 'revoked permission from user: {} on repo: {}'.format(
701 'revoked permission from user: {} on repo: {}'.format(
696 user, repo), namespace='security.repo')
702 user, repo), namespace='security.repo')
697
703
698 def grant_user_group_permission(self, repo, group_name, perm):
704 def grant_user_group_permission(self, repo, group_name, perm):
699 """
705 """
700 Grant permission for user group on given repository, or update
706 Grant permission for user group on given repository, or update
701 existing one if found
707 existing one if found
702
708
703 :param repo: Instance of Repository, repository_id, or repository name
709 :param repo: Instance of Repository, repository_id, or repository name
704 :param group_name: Instance of UserGroup, users_group_id,
710 :param group_name: Instance of UserGroup, users_group_id,
705 or user group name
711 or user group name
706 :param perm: Instance of Permission, or permission_name
712 :param perm: Instance of Permission, or permission_name
707 """
713 """
708 repo = self._get_repo(repo)
714 repo = self._get_repo(repo)
709 group_name = self._get_user_group(group_name)
715 group_name = self._get_user_group(group_name)
710 permission = self._get_perm(perm)
716 permission = self._get_perm(perm)
711
717
712 # check if we have that permission already
718 # check if we have that permission already
713 obj = self.sa.query(UserGroupRepoToPerm) \
719 obj = self.sa.query(UserGroupRepoToPerm) \
714 .filter(UserGroupRepoToPerm.users_group == group_name) \
720 .filter(UserGroupRepoToPerm.users_group == group_name) \
715 .filter(UserGroupRepoToPerm.repository == repo) \
721 .filter(UserGroupRepoToPerm.repository == repo) \
716 .scalar()
722 .scalar()
717
723
718 if obj is None:
724 if obj is None:
719 # create new
725 # create new
720 obj = UserGroupRepoToPerm()
726 obj = UserGroupRepoToPerm()
721
727
722 obj.repository = repo
728 obj.repository = repo
723 obj.users_group = group_name
729 obj.users_group = group_name
724 obj.permission = permission
730 obj.permission = permission
725 self.sa.add(obj)
731 self.sa.add(obj)
726 log.debug('Granted perm %s to %s on %s', perm, group_name, repo)
732 log.debug('Granted perm %s to %s on %s', perm, group_name, repo)
727 action_logger_generic(
733 action_logger_generic(
728 'granted permission: {} to usergroup: {} on repo: {}'.format(
734 'granted permission: {} to usergroup: {} on repo: {}'.format(
729 perm, group_name, repo), namespace='security.repo')
735 perm, group_name, repo), namespace='security.repo')
730
736
731 return obj
737 return obj
732
738
733 def revoke_user_group_permission(self, repo, group_name):
739 def revoke_user_group_permission(self, repo, group_name):
734 """
740 """
735 Revoke permission for user group on given repository
741 Revoke permission for user group on given repository
736
742
737 :param repo: Instance of Repository, repository_id, or repository name
743 :param repo: Instance of Repository, repository_id, or repository name
738 :param group_name: Instance of UserGroup, users_group_id,
744 :param group_name: Instance of UserGroup, users_group_id,
739 or user group name
745 or user group name
740 """
746 """
741 repo = self._get_repo(repo)
747 repo = self._get_repo(repo)
742 group_name = self._get_user_group(group_name)
748 group_name = self._get_user_group(group_name)
743
749
744 obj = self.sa.query(UserGroupRepoToPerm) \
750 obj = self.sa.query(UserGroupRepoToPerm) \
745 .filter(UserGroupRepoToPerm.repository == repo) \
751 .filter(UserGroupRepoToPerm.repository == repo) \
746 .filter(UserGroupRepoToPerm.users_group == group_name) \
752 .filter(UserGroupRepoToPerm.users_group == group_name) \
747 .scalar()
753 .scalar()
748 if obj:
754 if obj:
749 self.sa.delete(obj)
755 self.sa.delete(obj)
750 log.debug('Revoked perm to %s on %s', repo, group_name)
756 log.debug('Revoked perm to %s on %s', repo, group_name)
751 action_logger_generic(
757 action_logger_generic(
752 'revoked permission from usergroup: {} on repo: {}'.format(
758 'revoked permission from usergroup: {} on repo: {}'.format(
753 group_name, repo), namespace='security.repo')
759 group_name, repo), namespace='security.repo')
754
760
755 def delete_stats(self, repo_name):
761 def delete_stats(self, repo_name):
756 """
762 """
757 removes stats for given repo
763 removes stats for given repo
758
764
759 :param repo_name:
765 :param repo_name:
760 """
766 """
761 repo = self._get_repo(repo_name)
767 repo = self._get_repo(repo_name)
762 try:
768 try:
763 obj = self.sa.query(Statistics) \
769 obj = self.sa.query(Statistics) \
764 .filter(Statistics.repository == repo).scalar()
770 .filter(Statistics.repository == repo).scalar()
765 if obj:
771 if obj:
766 self.sa.delete(obj)
772 self.sa.delete(obj)
767 except Exception:
773 except Exception:
768 log.error(traceback.format_exc())
774 log.error(traceback.format_exc())
769 raise
775 raise
770
776
771 def add_repo_field(self, repo_name, field_key, field_label, field_value='',
777 def add_repo_field(self, repo_name, field_key, field_label, field_value='',
772 field_type='str', field_desc=''):
778 field_type='str', field_desc=''):
773
779
774 repo = self._get_repo(repo_name)
780 repo = self._get_repo(repo_name)
775
781
776 new_field = RepositoryField()
782 new_field = RepositoryField()
777 new_field.repository = repo
783 new_field.repository = repo
778 new_field.field_key = field_key
784 new_field.field_key = field_key
779 new_field.field_type = field_type # python type
785 new_field.field_type = field_type # python type
780 new_field.field_value = field_value
786 new_field.field_value = field_value
781 new_field.field_desc = field_desc
787 new_field.field_desc = field_desc
782 new_field.field_label = field_label
788 new_field.field_label = field_label
783 self.sa.add(new_field)
789 self.sa.add(new_field)
784 return new_field
790 return new_field
785
791
786 def delete_repo_field(self, repo_name, field_key):
792 def delete_repo_field(self, repo_name, field_key):
787 repo = self._get_repo(repo_name)
793 repo = self._get_repo(repo_name)
788 field = RepositoryField.get_by_key_name(field_key, repo)
794 field = RepositoryField.get_by_key_name(field_key, repo)
789 if field:
795 if field:
790 self.sa.delete(field)
796 self.sa.delete(field)
791
797
792 def _create_filesystem_repo(self, repo_name, repo_type, repo_group,
798 def _create_filesystem_repo(self, repo_name, repo_type, repo_group,
793 clone_uri=None, repo_store_location=None,
799 clone_uri=None, repo_store_location=None,
794 use_global_config=False):
800 use_global_config=False):
795 """
801 """
796 makes repository on filesystem. It's group aware means it'll create
802 makes repository on filesystem. It's group aware means it'll create
797 a repository within a group, and alter the paths accordingly of
803 a repository within a group, and alter the paths accordingly of
798 group location
804 group location
799
805
800 :param repo_name:
806 :param repo_name:
801 :param alias:
807 :param alias:
802 :param parent:
808 :param parent:
803 :param clone_uri:
809 :param clone_uri:
804 :param repo_store_location:
810 :param repo_store_location:
805 """
811 """
806 from rhodecode.lib.utils import is_valid_repo, is_valid_repo_group
812 from rhodecode.lib.utils import is_valid_repo, is_valid_repo_group
807 from rhodecode.model.scm import ScmModel
813 from rhodecode.model.scm import ScmModel
808
814
809 if Repository.NAME_SEP in repo_name:
815 if Repository.NAME_SEP in repo_name:
810 raise ValueError(
816 raise ValueError(
811 'repo_name must not contain groups got `%s`' % repo_name)
817 'repo_name must not contain groups got `%s`' % repo_name)
812
818
813 if isinstance(repo_group, RepoGroup):
819 if isinstance(repo_group, RepoGroup):
814 new_parent_path = os.sep.join(repo_group.full_path_splitted)
820 new_parent_path = os.sep.join(repo_group.full_path_splitted)
815 else:
821 else:
816 new_parent_path = repo_group or ''
822 new_parent_path = repo_group or ''
817
823
818 if repo_store_location:
824 if repo_store_location:
819 _paths = [repo_store_location]
825 _paths = [repo_store_location]
820 else:
826 else:
821 _paths = [self.repos_path, new_parent_path, repo_name]
827 _paths = [self.repos_path, new_parent_path, repo_name]
822 # we need to make it str for mercurial
828 # we need to make it str for mercurial
823 repo_path = os.path.join(*map(lambda x: safe_str(x), _paths))
829 repo_path = os.path.join(*map(lambda x: safe_str(x), _paths))
824
830
825 # check if this path is not a repository
831 # check if this path is not a repository
826 if is_valid_repo(repo_path, self.repos_path):
832 if is_valid_repo(repo_path, self.repos_path):
827 raise Exception('This path %s is a valid repository' % repo_path)
833 raise Exception('This path %s is a valid repository' % repo_path)
828
834
829 # check if this path is a group
835 # check if this path is a group
830 if is_valid_repo_group(repo_path, self.repos_path):
836 if is_valid_repo_group(repo_path, self.repos_path):
831 raise Exception('This path %s is a valid group' % repo_path)
837 raise Exception('This path %s is a valid group' % repo_path)
832
838
833 log.info('creating repo %s in %s from url: `%s`',
839 log.info('creating repo %s in %s from url: `%s`',
834 repo_name, safe_unicode(repo_path),
840 repo_name, safe_unicode(repo_path),
835 obfuscate_url_pw(clone_uri))
841 obfuscate_url_pw(clone_uri))
836
842
837 backend = get_backend(repo_type)
843 backend = get_backend(repo_type)
838
844
839 config_repo = None if use_global_config else repo_name
845 config_repo = None if use_global_config else repo_name
840 if config_repo and new_parent_path:
846 if config_repo and new_parent_path:
841 config_repo = Repository.NAME_SEP.join(
847 config_repo = Repository.NAME_SEP.join(
842 (new_parent_path, config_repo))
848 (new_parent_path, config_repo))
843 config = make_db_config(clear_session=False, repo=config_repo)
849 config = make_db_config(clear_session=False, repo=config_repo)
844 config.set('extensions', 'largefiles', '')
850 config.set('extensions', 'largefiles', '')
845
851
846 # patch and reset hooks section of UI config to not run any
852 # patch and reset hooks section of UI config to not run any
847 # hooks on creating remote repo
853 # hooks on creating remote repo
848 config.clear_section('hooks')
854 config.clear_section('hooks')
849
855
850 # TODO: johbo: Unify this, hardcoded "bare=True" does not look nice
856 # TODO: johbo: Unify this, hardcoded "bare=True" does not look nice
851 if repo_type == 'git':
857 if repo_type == 'git':
852 repo = backend(
858 repo = backend(
853 repo_path, config=config, create=True, src_url=clone_uri,
859 repo_path, config=config, create=True, src_url=clone_uri,
854 bare=True)
860 bare=True)
855 else:
861 else:
856 repo = backend(
862 repo = backend(
857 repo_path, config=config, create=True, src_url=clone_uri)
863 repo_path, config=config, create=True, src_url=clone_uri)
858
864
859 ScmModel().install_hooks(repo, repo_type=repo_type)
865 ScmModel().install_hooks(repo, repo_type=repo_type)
860
866
861 log.debug('Created repo %s with %s backend',
867 log.debug('Created repo %s with %s backend',
862 safe_unicode(repo_name), safe_unicode(repo_type))
868 safe_unicode(repo_name), safe_unicode(repo_type))
863 return repo
869 return repo
864
870
865 def _rename_filesystem_repo(self, old, new):
871 def _rename_filesystem_repo(self, old, new):
866 """
872 """
867 renames repository on filesystem
873 renames repository on filesystem
868
874
869 :param old: old name
875 :param old: old name
870 :param new: new name
876 :param new: new name
871 """
877 """
872 log.info('renaming repo from %s to %s', old, new)
878 log.info('renaming repo from %s to %s', old, new)
873
879
874 old_path = os.path.join(self.repos_path, old)
880 old_path = os.path.join(self.repos_path, old)
875 new_path = os.path.join(self.repos_path, new)
881 new_path = os.path.join(self.repos_path, new)
876 if os.path.isdir(new_path):
882 if os.path.isdir(new_path):
877 raise Exception(
883 raise Exception(
878 'Was trying to rename to already existing dir %s' % new_path
884 'Was trying to rename to already existing dir %s' % new_path
879 )
885 )
880 shutil.move(old_path, new_path)
886 shutil.move(old_path, new_path)
881
887
882 def _delete_filesystem_repo(self, repo):
888 def _delete_filesystem_repo(self, repo):
883 """
889 """
884 removes repo from filesystem, the removal is acctually made by
890 removes repo from filesystem, the removal is acctually made by
885 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
891 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
886 repository is no longer valid for rhodecode, can be undeleted later on
892 repository is no longer valid for rhodecode, can be undeleted later on
887 by reverting the renames on this repository
893 by reverting the renames on this repository
888
894
889 :param repo: repo object
895 :param repo: repo object
890 """
896 """
891 rm_path = os.path.join(self.repos_path, repo.repo_name)
897 rm_path = os.path.join(self.repos_path, repo.repo_name)
892 repo_group = repo.group
898 repo_group = repo.group
893 log.info("Removing repository %s", rm_path)
899 log.info("Removing repository %s", rm_path)
894 # disable hg/git internal that it doesn't get detected as repo
900 # disable hg/git internal that it doesn't get detected as repo
895 alias = repo.repo_type
901 alias = repo.repo_type
896
902
897 config = make_db_config(clear_session=False)
903 config = make_db_config(clear_session=False)
898 config.set('extensions', 'largefiles', '')
904 config.set('extensions', 'largefiles', '')
899 bare = getattr(repo.scm_instance(config=config), 'bare', False)
905 bare = getattr(repo.scm_instance(config=config), 'bare', False)
900
906
901 # skip this for bare git repos
907 # skip this for bare git repos
902 if not bare:
908 if not bare:
903 # disable VCS repo
909 # disable VCS repo
904 vcs_path = os.path.join(rm_path, '.%s' % alias)
910 vcs_path = os.path.join(rm_path, '.%s' % alias)
905 if os.path.exists(vcs_path):
911 if os.path.exists(vcs_path):
906 shutil.move(vcs_path, os.path.join(rm_path, 'rm__.%s' % alias))
912 shutil.move(vcs_path, os.path.join(rm_path, 'rm__.%s' % alias))
907
913
908 _now = datetime.now()
914 _now = datetime.now()
909 _ms = str(_now.microsecond).rjust(6, '0')
915 _ms = str(_now.microsecond).rjust(6, '0')
910 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
916 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
911 repo.just_name)
917 repo.just_name)
912 if repo_group:
918 if repo_group:
913 # if repository is in group, prefix the removal path with the group
919 # if repository is in group, prefix the removal path with the group
914 args = repo_group.full_path_splitted + [_d]
920 args = repo_group.full_path_splitted + [_d]
915 _d = os.path.join(*args)
921 _d = os.path.join(*args)
916
922
917 if os.path.isdir(rm_path):
923 if os.path.isdir(rm_path):
918 shutil.move(rm_path, os.path.join(self.repos_path, _d))
924 shutil.move(rm_path, os.path.join(self.repos_path, _d))
@@ -1,42 +1,48 b''
1 // # Copyright (C) 2010-2016 RhodeCode GmbH
1 // # Copyright (C) 2010-2016 RhodeCode GmbH
2 // #
2 // #
3 // # This program is free software: you can redistribute it and/or modify
3 // # This program is free software: you can redistribute it and/or modify
4 // # it under the terms of the GNU Affero General Public License, version 3
4 // # it under the terms of the GNU Affero General Public License, version 3
5 // # (only), as published by the Free Software Foundation.
5 // # (only), as published by the Free Software Foundation.
6 // #
6 // #
7 // # This program is distributed in the hope that it will be useful,
7 // # This program is distributed in the hope that it will be useful,
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 // # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 // # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // # GNU General Public License for more details.
10 // # GNU General Public License for more details.
11 // #
11 // #
12 // # You should have received a copy of the GNU Affero General Public License
12 // # You should have received a copy of the GNU Affero General Public License
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 // # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 // #
14 // #
15 // # This program is dual-licensed. If you wish to learn more about the
15 // # This program is dual-licensed. If you wish to learn more about the
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
16 // # RhodeCode Enterprise Edition, including its added features, Support services,
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
17 // # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 /**
19 /**
20 * autocomplete formatter that uses gravatar
20 * autocomplete formatter that uses gravatar
21 * */
21 * */
22 var autocompleteFormatResult = function(data, value, org_formatter) {
22 var autocompleteFormatResult = function (data, value, org_formatter) {
23 var value_display = data.value_display;
23 var activeUser = data.active || true;
24 var valueDisplay = data.value_display;
25
26 if (!activeUser) {
27 valueDisplay = '<strong>(disabled)</strong> ' + valueDisplay;
28 }
29
24 var escapeRegExChars = function (value) {
30 var escapeRegExChars = function (value) {
25 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
31 return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
26 };
32 };
27 var pattern = '(' + escapeRegExChars(value) + ')';
33 var pattern = '(' + escapeRegExChars(value) + ')';
28 value_display = value_display.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
34 valueDisplay = valueDisplay.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>');
29 var tmpl = '<div class="ac-container-wrap"><img class="gravatar" src="{0}"/>{1}</div>';
35 var tmpl = '<div class="ac-container-wrap"><img class="gravatar" src="{0}"/>{1}</div>';
30 if (data.icon_link === "") {
36 if (data.icon_link === "") {
31 tmpl = '<div class="ac-container-wrap">{0}</div>';
37 tmpl = '<div class="ac-container-wrap">{0}</div>';
32 return tmpl.format(value_display);
38 return tmpl.format(valueDisplay);
33 }
39 }
34 return tmpl.format(data.icon_link, value_display);
40 return tmpl.format(data.icon_link, valueDisplay);
35 };
41 };
36
42
37 /**
43 /**
38 * autocomplete filter that uses display value to filter
44 * autocomplete filter that uses display value to filter
39 */
45 */
40 var autocompleteFilterResult = function (suggestion, originalQuery, queryLowerCase) {
46 var autocompleteFilterResult = function (suggestion, originalQuery, queryLowerCase) {
41 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
47 return suggestion.value_display.toLowerCase().indexOf(queryLowerCase) !== -1;
42 };
48 };
General Comments 0
You need to be logged in to leave comments. Login now