##// END OF EJS Templates
import/repo-checks: skip validating storage path in detection of SCMs.
marcink -
r3037:63d95a89 stable
parent child Browse files
Show More
@@ -1,778 +1,782 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2018 RhodeCode GmbH
3 # Copyright (C) 2010-2018 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 Utilities library for RhodeCode
22 Utilities library for RhodeCode
23 """
23 """
24
24
25 import datetime
25 import datetime
26 import decorator
26 import decorator
27 import json
27 import json
28 import logging
28 import logging
29 import os
29 import os
30 import re
30 import re
31 import shutil
31 import shutil
32 import tempfile
32 import tempfile
33 import traceback
33 import traceback
34 import tarfile
34 import tarfile
35 import warnings
35 import warnings
36 import hashlib
36 import hashlib
37 from os.path import join as jn
37 from os.path import join as jn
38
38
39 import paste
39 import paste
40 import pkg_resources
40 import pkg_resources
41 from webhelpers.text import collapse, remove_formatting, strip_tags
41 from webhelpers.text import collapse, remove_formatting, strip_tags
42 from mako import exceptions
42 from mako import exceptions
43 from pyramid.threadlocal import get_current_registry
43 from pyramid.threadlocal import get_current_registry
44 from rhodecode.lib.request import Request
44 from rhodecode.lib.request import Request
45
45
46 from rhodecode.lib.fakemod import create_module
46 from rhodecode.lib.fakemod import create_module
47 from rhodecode.lib.vcs.backends.base import Config
47 from rhodecode.lib.vcs.backends.base import Config
48 from rhodecode.lib.vcs.exceptions import VCSError
48 from rhodecode.lib.vcs.exceptions import VCSError
49 from rhodecode.lib.vcs.utils.helpers import get_scm, get_scm_backend
49 from rhodecode.lib.vcs.utils.helpers import get_scm, get_scm_backend
50 from rhodecode.lib.utils2 import (
50 from rhodecode.lib.utils2 import (
51 safe_str, safe_unicode, get_current_rhodecode_user, md5, sha1)
51 safe_str, safe_unicode, get_current_rhodecode_user, md5, sha1)
52 from rhodecode.model import meta
52 from rhodecode.model import meta
53 from rhodecode.model.db import (
53 from rhodecode.model.db import (
54 Repository, User, RhodeCodeUi, UserLog, RepoGroup, UserGroup)
54 Repository, User, RhodeCodeUi, UserLog, RepoGroup, UserGroup)
55 from rhodecode.model.meta import Session
55 from rhodecode.model.meta import Session
56
56
57
57
58 log = logging.getLogger(__name__)
58 log = logging.getLogger(__name__)
59
59
60 REMOVED_REPO_PAT = re.compile(r'rm__\d{8}_\d{6}_\d{6}__.*')
60 REMOVED_REPO_PAT = re.compile(r'rm__\d{8}_\d{6}_\d{6}__.*')
61
61
62 # String which contains characters that are not allowed in slug names for
62 # String which contains characters that are not allowed in slug names for
63 # repositories or repository groups. It is properly escaped to use it in
63 # repositories or repository groups. It is properly escaped to use it in
64 # regular expressions.
64 # regular expressions.
65 SLUG_BAD_CHARS = re.escape('`?=[]\;\'"<>,/~!@#$%^&*()+{}|:')
65 SLUG_BAD_CHARS = re.escape('`?=[]\;\'"<>,/~!@#$%^&*()+{}|:')
66
66
67 # Regex that matches forbidden characters in repo/group slugs.
67 # Regex that matches forbidden characters in repo/group slugs.
68 SLUG_BAD_CHAR_RE = re.compile('[{}]'.format(SLUG_BAD_CHARS))
68 SLUG_BAD_CHAR_RE = re.compile('[{}]'.format(SLUG_BAD_CHARS))
69
69
70 # Regex that matches allowed characters in repo/group slugs.
70 # Regex that matches allowed characters in repo/group slugs.
71 SLUG_GOOD_CHAR_RE = re.compile('[^{}]'.format(SLUG_BAD_CHARS))
71 SLUG_GOOD_CHAR_RE = re.compile('[^{}]'.format(SLUG_BAD_CHARS))
72
72
73 # Regex that matches whole repo/group slugs.
73 # Regex that matches whole repo/group slugs.
74 SLUG_RE = re.compile('[^{}]+'.format(SLUG_BAD_CHARS))
74 SLUG_RE = re.compile('[^{}]+'.format(SLUG_BAD_CHARS))
75
75
76 _license_cache = None
76 _license_cache = None
77
77
78
78
79 def repo_name_slug(value):
79 def repo_name_slug(value):
80 """
80 """
81 Return slug of name of repository
81 Return slug of name of repository
82 This function is called on each creation/modification
82 This function is called on each creation/modification
83 of repository to prevent bad names in repo
83 of repository to prevent bad names in repo
84 """
84 """
85 replacement_char = '-'
85 replacement_char = '-'
86
86
87 slug = remove_formatting(value)
87 slug = remove_formatting(value)
88 slug = SLUG_BAD_CHAR_RE.sub('', slug)
88 slug = SLUG_BAD_CHAR_RE.sub('', slug)
89 slug = re.sub('[\s]+', '-', slug)
89 slug = re.sub('[\s]+', '-', slug)
90 slug = collapse(slug, replacement_char)
90 slug = collapse(slug, replacement_char)
91 return slug
91 return slug
92
92
93
93
94 #==============================================================================
94 #==============================================================================
95 # PERM DECORATOR HELPERS FOR EXTRACTING NAMES FOR PERM CHECKS
95 # PERM DECORATOR HELPERS FOR EXTRACTING NAMES FOR PERM CHECKS
96 #==============================================================================
96 #==============================================================================
97 def get_repo_slug(request):
97 def get_repo_slug(request):
98 _repo = ''
98 _repo = ''
99
99
100 if hasattr(request, 'db_repo'):
100 if hasattr(request, 'db_repo'):
101 # if our requests has set db reference use it for name, this
101 # if our requests has set db reference use it for name, this
102 # translates the example.com/_<id> into proper repo names
102 # translates the example.com/_<id> into proper repo names
103 _repo = request.db_repo.repo_name
103 _repo = request.db_repo.repo_name
104 elif getattr(request, 'matchdict', None):
104 elif getattr(request, 'matchdict', None):
105 # pyramid
105 # pyramid
106 _repo = request.matchdict.get('repo_name')
106 _repo = request.matchdict.get('repo_name')
107
107
108 if _repo:
108 if _repo:
109 _repo = _repo.rstrip('/')
109 _repo = _repo.rstrip('/')
110 return _repo
110 return _repo
111
111
112
112
113 def get_repo_group_slug(request):
113 def get_repo_group_slug(request):
114 _group = ''
114 _group = ''
115 if hasattr(request, 'db_repo_group'):
115 if hasattr(request, 'db_repo_group'):
116 # if our requests has set db reference use it for name, this
116 # if our requests has set db reference use it for name, this
117 # translates the example.com/_<id> into proper repo group names
117 # translates the example.com/_<id> into proper repo group names
118 _group = request.db_repo_group.group_name
118 _group = request.db_repo_group.group_name
119 elif getattr(request, 'matchdict', None):
119 elif getattr(request, 'matchdict', None):
120 # pyramid
120 # pyramid
121 _group = request.matchdict.get('repo_group_name')
121 _group = request.matchdict.get('repo_group_name')
122
122
123 if _group:
123 if _group:
124 _group = _group.rstrip('/')
124 _group = _group.rstrip('/')
125 return _group
125 return _group
126
126
127
127
128 def get_user_group_slug(request):
128 def get_user_group_slug(request):
129 _user_group = ''
129 _user_group = ''
130
130
131 if hasattr(request, 'db_user_group'):
131 if hasattr(request, 'db_user_group'):
132 _user_group = request.db_user_group.users_group_name
132 _user_group = request.db_user_group.users_group_name
133 elif getattr(request, 'matchdict', None):
133 elif getattr(request, 'matchdict', None):
134 # pyramid
134 # pyramid
135 _user_group = request.matchdict.get('user_group_id')
135 _user_group = request.matchdict.get('user_group_id')
136 _user_group_name = request.matchdict.get('user_group_name')
136 _user_group_name = request.matchdict.get('user_group_name')
137 try:
137 try:
138 if _user_group:
138 if _user_group:
139 _user_group = UserGroup.get(_user_group)
139 _user_group = UserGroup.get(_user_group)
140 elif _user_group_name:
140 elif _user_group_name:
141 _user_group = UserGroup.get_by_group_name(_user_group_name)
141 _user_group = UserGroup.get_by_group_name(_user_group_name)
142
142
143 if _user_group:
143 if _user_group:
144 _user_group = _user_group.users_group_name
144 _user_group = _user_group.users_group_name
145 except Exception:
145 except Exception:
146 log.exception('Failed to get user group by id and name')
146 log.exception('Failed to get user group by id and name')
147 # catch all failures here
147 # catch all failures here
148 return None
148 return None
149
149
150 return _user_group
150 return _user_group
151
151
152
152
153 def get_filesystem_repos(path, recursive=False, skip_removed_repos=True):
153 def get_filesystem_repos(path, recursive=False, skip_removed_repos=True):
154 """
154 """
155 Scans given path for repos and return (name,(type,path)) tuple
155 Scans given path for repos and return (name,(type,path)) tuple
156
156
157 :param path: path to scan for repositories
157 :param path: path to scan for repositories
158 :param recursive: recursive search and return names with subdirs in front
158 :param recursive: recursive search and return names with subdirs in front
159 """
159 """
160
160
161 # remove ending slash for better results
161 # remove ending slash for better results
162 path = path.rstrip(os.sep)
162 path = path.rstrip(os.sep)
163 log.debug('now scanning in %s location recursive:%s...', path, recursive)
163 log.debug('now scanning in %s location recursive:%s...', path, recursive)
164
164
165 def _get_repos(p):
165 def _get_repos(p):
166 dirpaths = _get_dirpaths(p)
166 dirpaths = _get_dirpaths(p)
167 if not _is_dir_writable(p):
167 if not _is_dir_writable(p):
168 log.warning('repo path without write access: %s', p)
168 log.warning('repo path without write access: %s', p)
169
169
170 for dirpath in dirpaths:
170 for dirpath in dirpaths:
171 if os.path.isfile(os.path.join(p, dirpath)):
171 if os.path.isfile(os.path.join(p, dirpath)):
172 continue
172 continue
173 cur_path = os.path.join(p, dirpath)
173 cur_path = os.path.join(p, dirpath)
174
174
175 # skip removed repos
175 # skip removed repos
176 if skip_removed_repos and REMOVED_REPO_PAT.match(dirpath):
176 if skip_removed_repos and REMOVED_REPO_PAT.match(dirpath):
177 continue
177 continue
178
178
179 #skip .<somethin> dirs
179 #skip .<somethin> dirs
180 if dirpath.startswith('.'):
180 if dirpath.startswith('.'):
181 continue
181 continue
182
182
183 try:
183 try:
184 scm_info = get_scm(cur_path)
184 scm_info = get_scm(cur_path)
185 yield scm_info[1].split(path, 1)[-1].lstrip(os.sep), scm_info
185 yield scm_info[1].split(path, 1)[-1].lstrip(os.sep), scm_info
186 except VCSError:
186 except VCSError:
187 if not recursive:
187 if not recursive:
188 continue
188 continue
189 #check if this dir containts other repos for recursive scan
189 #check if this dir containts other repos for recursive scan
190 rec_path = os.path.join(p, dirpath)
190 rec_path = os.path.join(p, dirpath)
191 if os.path.isdir(rec_path):
191 if os.path.isdir(rec_path):
192 for inner_scm in _get_repos(rec_path):
192 for inner_scm in _get_repos(rec_path):
193 yield inner_scm
193 yield inner_scm
194
194
195 return _get_repos(path)
195 return _get_repos(path)
196
196
197
197
198 def _get_dirpaths(p):
198 def _get_dirpaths(p):
199 try:
199 try:
200 # OS-independable way of checking if we have at least read-only
200 # OS-independable way of checking if we have at least read-only
201 # access or not.
201 # access or not.
202 dirpaths = os.listdir(p)
202 dirpaths = os.listdir(p)
203 except OSError:
203 except OSError:
204 log.warning('ignoring repo path without read access: %s', p)
204 log.warning('ignoring repo path without read access: %s', p)
205 return []
205 return []
206
206
207 # os.listpath has a tweak: If a unicode is passed into it, then it tries to
207 # os.listpath has a tweak: If a unicode is passed into it, then it tries to
208 # decode paths and suddenly returns unicode objects itself. The items it
208 # decode paths and suddenly returns unicode objects itself. The items it
209 # cannot decode are returned as strings and cause issues.
209 # cannot decode are returned as strings and cause issues.
210 #
210 #
211 # Those paths are ignored here until a solid solution for path handling has
211 # Those paths are ignored here until a solid solution for path handling has
212 # been built.
212 # been built.
213 expected_type = type(p)
213 expected_type = type(p)
214
214
215 def _has_correct_type(item):
215 def _has_correct_type(item):
216 if type(item) is not expected_type:
216 if type(item) is not expected_type:
217 log.error(
217 log.error(
218 u"Ignoring path %s since it cannot be decoded into unicode.",
218 u"Ignoring path %s since it cannot be decoded into unicode.",
219 # Using "repr" to make sure that we see the byte value in case
219 # Using "repr" to make sure that we see the byte value in case
220 # of support.
220 # of support.
221 repr(item))
221 repr(item))
222 return False
222 return False
223 return True
223 return True
224
224
225 dirpaths = [item for item in dirpaths if _has_correct_type(item)]
225 dirpaths = [item for item in dirpaths if _has_correct_type(item)]
226
226
227 return dirpaths
227 return dirpaths
228
228
229
229
230 def _is_dir_writable(path):
230 def _is_dir_writable(path):
231 """
231 """
232 Probe if `path` is writable.
232 Probe if `path` is writable.
233
233
234 Due to trouble on Cygwin / Windows, this is actually probing if it is
234 Due to trouble on Cygwin / Windows, this is actually probing if it is
235 possible to create a file inside of `path`, stat does not produce reliable
235 possible to create a file inside of `path`, stat does not produce reliable
236 results in this case.
236 results in this case.
237 """
237 """
238 try:
238 try:
239 with tempfile.TemporaryFile(dir=path):
239 with tempfile.TemporaryFile(dir=path):
240 pass
240 pass
241 except OSError:
241 except OSError:
242 return False
242 return False
243 return True
243 return True
244
244
245
245
246 def is_valid_repo(repo_name, base_path, expect_scm=None, explicit_scm=None, config=None):
246 def is_valid_repo(repo_name, base_path, expect_scm=None, explicit_scm=None, config=None):
247 """
247 """
248 Returns True if given path is a valid repository False otherwise.
248 Returns True if given path is a valid repository False otherwise.
249 If expect_scm param is given also, compare if given scm is the same
249 If expect_scm param is given also, compare if given scm is the same
250 as expected from scm parameter. If explicit_scm is given don't try to
250 as expected from scm parameter. If explicit_scm is given don't try to
251 detect the scm, just use the given one to check if repo is valid
251 detect the scm, just use the given one to check if repo is valid
252
252
253 :param repo_name:
253 :param repo_name:
254 :param base_path:
254 :param base_path:
255 :param expect_scm:
255 :param expect_scm:
256 :param explicit_scm:
256 :param explicit_scm:
257 :param config:
257 :param config:
258
258
259 :return True: if given path is a valid repository
259 :return True: if given path is a valid repository
260 """
260 """
261 full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
261 full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
262 log.debug('Checking if `%s` is a valid path for repository. '
262 log.debug('Checking if `%s` is a valid path for repository. '
263 'Explicit type: %s', repo_name, explicit_scm)
263 'Explicit type: %s', repo_name, explicit_scm)
264
264
265 try:
265 try:
266 if explicit_scm:
266 if explicit_scm:
267 detected_scms = [get_scm_backend(explicit_scm)(
267 detected_scms = [get_scm_backend(explicit_scm)(
268 full_path, config=config).alias]
268 full_path, config=config).alias]
269 else:
269 else:
270 detected_scms = get_scm(full_path)
270 detected_scms = get_scm(full_path)
271
271
272 if expect_scm:
272 if expect_scm:
273 return detected_scms[0] == expect_scm
273 return detected_scms[0] == expect_scm
274 log.debug('path: %s is an vcs object:%s', full_path, detected_scms)
274 log.debug('path: %s is an vcs object:%s', full_path, detected_scms)
275 return True
275 return True
276 except VCSError:
276 except VCSError:
277 log.debug('path: %s is not a valid repo !', full_path)
277 log.debug('path: %s is not a valid repo !', full_path)
278 return False
278 return False
279
279
280
280
281 def is_valid_repo_group(repo_group_name, base_path, skip_path_check=False):
281 def is_valid_repo_group(repo_group_name, base_path, skip_path_check=False):
282 """
282 """
283 Returns True if given path is a repository group, False otherwise
283 Returns True if given path is a repository group, False otherwise
284
284
285 :param repo_name:
285 :param repo_name:
286 :param base_path:
286 :param base_path:
287 """
287 """
288 full_path = os.path.join(safe_str(base_path), safe_str(repo_group_name))
288 full_path = os.path.join(safe_str(base_path), safe_str(repo_group_name))
289 log.debug('Checking if `%s` is a valid path for repository group',
289 log.debug('Checking if `%s` is a valid path for repository group',
290 repo_group_name)
290 repo_group_name)
291
291
292 # check if it's not a repo
292 # check if it's not a repo
293 if is_valid_repo(repo_group_name, base_path):
293 if is_valid_repo(repo_group_name, base_path):
294 log.debug('Repo called %s exist, it is not a valid '
294 log.debug('Repo called %s exist, it is not a valid '
295 'repo group' % repo_group_name)
295 'repo group' % repo_group_name)
296 return False
296 return False
297
297
298 try:
298 try:
299 # we need to check bare git repos at higher level
299 # we need to check bare git repos at higher level
300 # since we might match branches/hooks/info/objects or possible
300 # since we might match branches/hooks/info/objects or possible
301 # other things inside bare git repo
301 # other things inside bare git repo
302 scm_ = get_scm(os.path.dirname(full_path))
302 maybe_repo = os.path.dirname(full_path)
303 log.debug('path: %s is a vcs object:%s, not valid '
303 if maybe_repo == base_path:
304 'repo group' % (full_path, scm_))
304 # skip root level repo check, we know root location CANNOT BE a repo group
305 return False
306
307 scm_ = get_scm(maybe_repo)
308 log.debug('path: %s is a vcs object:%s, not valid repo group', full_path, scm_)
305 return False
309 return False
306 except VCSError:
310 except VCSError:
307 pass
311 pass
308
312
309 # check if it's a valid path
313 # check if it's a valid path
310 if skip_path_check or os.path.isdir(full_path):
314 if skip_path_check or os.path.isdir(full_path):
311 log.debug('path: %s is a valid repo group !', full_path)
315 log.debug('path: %s is a valid repo group !', full_path)
312 return True
316 return True
313
317
314 log.debug('path: %s is not a valid repo group !', full_path)
318 log.debug('path: %s is not a valid repo group !', full_path)
315 return False
319 return False
316
320
317
321
318 def ask_ok(prompt, retries=4, complaint='[y]es or [n]o please!'):
322 def ask_ok(prompt, retries=4, complaint='[y]es or [n]o please!'):
319 while True:
323 while True:
320 ok = raw_input(prompt)
324 ok = raw_input(prompt)
321 if ok.lower() in ('y', 'ye', 'yes'):
325 if ok.lower() in ('y', 'ye', 'yes'):
322 return True
326 return True
323 if ok.lower() in ('n', 'no', 'nop', 'nope'):
327 if ok.lower() in ('n', 'no', 'nop', 'nope'):
324 return False
328 return False
325 retries = retries - 1
329 retries = retries - 1
326 if retries < 0:
330 if retries < 0:
327 raise IOError
331 raise IOError
328 print(complaint)
332 print(complaint)
329
333
330 # propagated from mercurial documentation
334 # propagated from mercurial documentation
331 ui_sections = [
335 ui_sections = [
332 'alias', 'auth',
336 'alias', 'auth',
333 'decode/encode', 'defaults',
337 'decode/encode', 'defaults',
334 'diff', 'email',
338 'diff', 'email',
335 'extensions', 'format',
339 'extensions', 'format',
336 'merge-patterns', 'merge-tools',
340 'merge-patterns', 'merge-tools',
337 'hooks', 'http_proxy',
341 'hooks', 'http_proxy',
338 'smtp', 'patch',
342 'smtp', 'patch',
339 'paths', 'profiling',
343 'paths', 'profiling',
340 'server', 'trusted',
344 'server', 'trusted',
341 'ui', 'web', ]
345 'ui', 'web', ]
342
346
343
347
344 def config_data_from_db(clear_session=True, repo=None):
348 def config_data_from_db(clear_session=True, repo=None):
345 """
349 """
346 Read the configuration data from the database and return configuration
350 Read the configuration data from the database and return configuration
347 tuples.
351 tuples.
348 """
352 """
349 from rhodecode.model.settings import VcsSettingsModel
353 from rhodecode.model.settings import VcsSettingsModel
350
354
351 config = []
355 config = []
352
356
353 sa = meta.Session()
357 sa = meta.Session()
354 settings_model = VcsSettingsModel(repo=repo, sa=sa)
358 settings_model = VcsSettingsModel(repo=repo, sa=sa)
355
359
356 ui_settings = settings_model.get_ui_settings()
360 ui_settings = settings_model.get_ui_settings()
357
361
358 ui_data = []
362 ui_data = []
359 for setting in ui_settings:
363 for setting in ui_settings:
360 if setting.active:
364 if setting.active:
361 ui_data.append((setting.section, setting.key, setting.value))
365 ui_data.append((setting.section, setting.key, setting.value))
362 config.append((
366 config.append((
363 safe_str(setting.section), safe_str(setting.key),
367 safe_str(setting.section), safe_str(setting.key),
364 safe_str(setting.value)))
368 safe_str(setting.value)))
365 if setting.key == 'push_ssl':
369 if setting.key == 'push_ssl':
366 # force set push_ssl requirement to False, rhodecode
370 # force set push_ssl requirement to False, rhodecode
367 # handles that
371 # handles that
368 config.append((
372 config.append((
369 safe_str(setting.section), safe_str(setting.key), False))
373 safe_str(setting.section), safe_str(setting.key), False))
370 log.debug(
374 log.debug(
371 'settings ui from db: %s',
375 'settings ui from db: %s',
372 ','.join(map(lambda s: '[{}] {}={}'.format(*s), ui_data)))
376 ','.join(map(lambda s: '[{}] {}={}'.format(*s), ui_data)))
373 if clear_session:
377 if clear_session:
374 meta.Session.remove()
378 meta.Session.remove()
375
379
376 # TODO: mikhail: probably it makes no sense to re-read hooks information.
380 # TODO: mikhail: probably it makes no sense to re-read hooks information.
377 # It's already there and activated/deactivated
381 # It's already there and activated/deactivated
378 skip_entries = []
382 skip_entries = []
379 enabled_hook_classes = get_enabled_hook_classes(ui_settings)
383 enabled_hook_classes = get_enabled_hook_classes(ui_settings)
380 if 'pull' not in enabled_hook_classes:
384 if 'pull' not in enabled_hook_classes:
381 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PULL))
385 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PULL))
382 if 'push' not in enabled_hook_classes:
386 if 'push' not in enabled_hook_classes:
383 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PUSH))
387 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PUSH))
384 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRETX_PUSH))
388 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRETX_PUSH))
385 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PUSH_KEY))
389 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PUSH_KEY))
386
390
387 config = [entry for entry in config if entry[:2] not in skip_entries]
391 config = [entry for entry in config if entry[:2] not in skip_entries]
388
392
389 return config
393 return config
390
394
391
395
392 def make_db_config(clear_session=True, repo=None):
396 def make_db_config(clear_session=True, repo=None):
393 """
397 """
394 Create a :class:`Config` instance based on the values in the database.
398 Create a :class:`Config` instance based on the values in the database.
395 """
399 """
396 config = Config()
400 config = Config()
397 config_data = config_data_from_db(clear_session=clear_session, repo=repo)
401 config_data = config_data_from_db(clear_session=clear_session, repo=repo)
398 for section, option, value in config_data:
402 for section, option, value in config_data:
399 config.set(section, option, value)
403 config.set(section, option, value)
400 return config
404 return config
401
405
402
406
403 def get_enabled_hook_classes(ui_settings):
407 def get_enabled_hook_classes(ui_settings):
404 """
408 """
405 Return the enabled hook classes.
409 Return the enabled hook classes.
406
410
407 :param ui_settings: List of ui_settings as returned
411 :param ui_settings: List of ui_settings as returned
408 by :meth:`VcsSettingsModel.get_ui_settings`
412 by :meth:`VcsSettingsModel.get_ui_settings`
409
413
410 :return: a list with the enabled hook classes. The order is not guaranteed.
414 :return: a list with the enabled hook classes. The order is not guaranteed.
411 :rtype: list
415 :rtype: list
412 """
416 """
413 enabled_hooks = []
417 enabled_hooks = []
414 active_hook_keys = [
418 active_hook_keys = [
415 key for section, key, value, active in ui_settings
419 key for section, key, value, active in ui_settings
416 if section == 'hooks' and active]
420 if section == 'hooks' and active]
417
421
418 hook_names = {
422 hook_names = {
419 RhodeCodeUi.HOOK_PUSH: 'push',
423 RhodeCodeUi.HOOK_PUSH: 'push',
420 RhodeCodeUi.HOOK_PULL: 'pull',
424 RhodeCodeUi.HOOK_PULL: 'pull',
421 RhodeCodeUi.HOOK_REPO_SIZE: 'repo_size'
425 RhodeCodeUi.HOOK_REPO_SIZE: 'repo_size'
422 }
426 }
423
427
424 for key in active_hook_keys:
428 for key in active_hook_keys:
425 hook = hook_names.get(key)
429 hook = hook_names.get(key)
426 if hook:
430 if hook:
427 enabled_hooks.append(hook)
431 enabled_hooks.append(hook)
428
432
429 return enabled_hooks
433 return enabled_hooks
430
434
431
435
432 def set_rhodecode_config(config):
436 def set_rhodecode_config(config):
433 """
437 """
434 Updates pyramid config with new settings from database
438 Updates pyramid config with new settings from database
435
439
436 :param config:
440 :param config:
437 """
441 """
438 from rhodecode.model.settings import SettingsModel
442 from rhodecode.model.settings import SettingsModel
439 app_settings = SettingsModel().get_all_settings()
443 app_settings = SettingsModel().get_all_settings()
440
444
441 for k, v in app_settings.items():
445 for k, v in app_settings.items():
442 config[k] = v
446 config[k] = v
443
447
444
448
445 def get_rhodecode_realm():
449 def get_rhodecode_realm():
446 """
450 """
447 Return the rhodecode realm from database.
451 Return the rhodecode realm from database.
448 """
452 """
449 from rhodecode.model.settings import SettingsModel
453 from rhodecode.model.settings import SettingsModel
450 realm = SettingsModel().get_setting_by_name('realm')
454 realm = SettingsModel().get_setting_by_name('realm')
451 return safe_str(realm.app_settings_value)
455 return safe_str(realm.app_settings_value)
452
456
453
457
454 def get_rhodecode_base_path():
458 def get_rhodecode_base_path():
455 """
459 """
456 Returns the base path. The base path is the filesystem path which points
460 Returns the base path. The base path is the filesystem path which points
457 to the repository store.
461 to the repository store.
458 """
462 """
459 from rhodecode.model.settings import SettingsModel
463 from rhodecode.model.settings import SettingsModel
460 paths_ui = SettingsModel().get_ui_by_section_and_key('paths', '/')
464 paths_ui = SettingsModel().get_ui_by_section_and_key('paths', '/')
461 return safe_str(paths_ui.ui_value)
465 return safe_str(paths_ui.ui_value)
462
466
463
467
464 def map_groups(path):
468 def map_groups(path):
465 """
469 """
466 Given a full path to a repository, create all nested groups that this
470 Given a full path to a repository, create all nested groups that this
467 repo is inside. This function creates parent-child relationships between
471 repo is inside. This function creates parent-child relationships between
468 groups and creates default perms for all new groups.
472 groups and creates default perms for all new groups.
469
473
470 :param paths: full path to repository
474 :param paths: full path to repository
471 """
475 """
472 from rhodecode.model.repo_group import RepoGroupModel
476 from rhodecode.model.repo_group import RepoGroupModel
473 sa = meta.Session()
477 sa = meta.Session()
474 groups = path.split(Repository.NAME_SEP)
478 groups = path.split(Repository.NAME_SEP)
475 parent = None
479 parent = None
476 group = None
480 group = None
477
481
478 # last element is repo in nested groups structure
482 # last element is repo in nested groups structure
479 groups = groups[:-1]
483 groups = groups[:-1]
480 rgm = RepoGroupModel(sa)
484 rgm = RepoGroupModel(sa)
481 owner = User.get_first_super_admin()
485 owner = User.get_first_super_admin()
482 for lvl, group_name in enumerate(groups):
486 for lvl, group_name in enumerate(groups):
483 group_name = '/'.join(groups[:lvl] + [group_name])
487 group_name = '/'.join(groups[:lvl] + [group_name])
484 group = RepoGroup.get_by_group_name(group_name)
488 group = RepoGroup.get_by_group_name(group_name)
485 desc = '%s group' % group_name
489 desc = '%s group' % group_name
486
490
487 # skip folders that are now removed repos
491 # skip folders that are now removed repos
488 if REMOVED_REPO_PAT.match(group_name):
492 if REMOVED_REPO_PAT.match(group_name):
489 break
493 break
490
494
491 if group is None:
495 if group is None:
492 log.debug('creating group level: %s group_name: %s',
496 log.debug('creating group level: %s group_name: %s',
493 lvl, group_name)
497 lvl, group_name)
494 group = RepoGroup(group_name, parent)
498 group = RepoGroup(group_name, parent)
495 group.group_description = desc
499 group.group_description = desc
496 group.user = owner
500 group.user = owner
497 sa.add(group)
501 sa.add(group)
498 perm_obj = rgm._create_default_perms(group)
502 perm_obj = rgm._create_default_perms(group)
499 sa.add(perm_obj)
503 sa.add(perm_obj)
500 sa.flush()
504 sa.flush()
501
505
502 parent = group
506 parent = group
503 return group
507 return group
504
508
505
509
506 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
510 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
507 """
511 """
508 maps all repos given in initial_repo_list, non existing repositories
512 maps all repos given in initial_repo_list, non existing repositories
509 are created, if remove_obsolete is True it also checks for db entries
513 are created, if remove_obsolete is True it also checks for db entries
510 that are not in initial_repo_list and removes them.
514 that are not in initial_repo_list and removes them.
511
515
512 :param initial_repo_list: list of repositories found by scanning methods
516 :param initial_repo_list: list of repositories found by scanning methods
513 :param remove_obsolete: check for obsolete entries in database
517 :param remove_obsolete: check for obsolete entries in database
514 """
518 """
515 from rhodecode.model.repo import RepoModel
519 from rhodecode.model.repo import RepoModel
516 from rhodecode.model.repo_group import RepoGroupModel
520 from rhodecode.model.repo_group import RepoGroupModel
517 from rhodecode.model.settings import SettingsModel
521 from rhodecode.model.settings import SettingsModel
518
522
519 sa = meta.Session()
523 sa = meta.Session()
520 repo_model = RepoModel()
524 repo_model = RepoModel()
521 user = User.get_first_super_admin()
525 user = User.get_first_super_admin()
522 added = []
526 added = []
523
527
524 # creation defaults
528 # creation defaults
525 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
529 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
526 enable_statistics = defs.get('repo_enable_statistics')
530 enable_statistics = defs.get('repo_enable_statistics')
527 enable_locking = defs.get('repo_enable_locking')
531 enable_locking = defs.get('repo_enable_locking')
528 enable_downloads = defs.get('repo_enable_downloads')
532 enable_downloads = defs.get('repo_enable_downloads')
529 private = defs.get('repo_private')
533 private = defs.get('repo_private')
530
534
531 for name, repo in initial_repo_list.items():
535 for name, repo in initial_repo_list.items():
532 group = map_groups(name)
536 group = map_groups(name)
533 unicode_name = safe_unicode(name)
537 unicode_name = safe_unicode(name)
534 db_repo = repo_model.get_by_repo_name(unicode_name)
538 db_repo = repo_model.get_by_repo_name(unicode_name)
535 # found repo that is on filesystem not in RhodeCode database
539 # found repo that is on filesystem not in RhodeCode database
536 if not db_repo:
540 if not db_repo:
537 log.info('repository %s not found, creating now', name)
541 log.info('repository %s not found, creating now', name)
538 added.append(name)
542 added.append(name)
539 desc = (repo.description
543 desc = (repo.description
540 if repo.description != 'unknown'
544 if repo.description != 'unknown'
541 else '%s repository' % name)
545 else '%s repository' % name)
542
546
543 db_repo = repo_model._create_repo(
547 db_repo = repo_model._create_repo(
544 repo_name=name,
548 repo_name=name,
545 repo_type=repo.alias,
549 repo_type=repo.alias,
546 description=desc,
550 description=desc,
547 repo_group=getattr(group, 'group_id', None),
551 repo_group=getattr(group, 'group_id', None),
548 owner=user,
552 owner=user,
549 enable_locking=enable_locking,
553 enable_locking=enable_locking,
550 enable_downloads=enable_downloads,
554 enable_downloads=enable_downloads,
551 enable_statistics=enable_statistics,
555 enable_statistics=enable_statistics,
552 private=private,
556 private=private,
553 state=Repository.STATE_CREATED
557 state=Repository.STATE_CREATED
554 )
558 )
555 sa.commit()
559 sa.commit()
556 # we added that repo just now, and make sure we updated server info
560 # we added that repo just now, and make sure we updated server info
557 if db_repo.repo_type == 'git':
561 if db_repo.repo_type == 'git':
558 git_repo = db_repo.scm_instance()
562 git_repo = db_repo.scm_instance()
559 # update repository server-info
563 # update repository server-info
560 log.debug('Running update server info')
564 log.debug('Running update server info')
561 git_repo._update_server_info()
565 git_repo._update_server_info()
562
566
563 db_repo.update_commit_cache()
567 db_repo.update_commit_cache()
564
568
565 config = db_repo._config
569 config = db_repo._config
566 config.set('extensions', 'largefiles', '')
570 config.set('extensions', 'largefiles', '')
567 repo = db_repo.scm_instance(config=config)
571 repo = db_repo.scm_instance(config=config)
568 repo.install_hooks()
572 repo.install_hooks()
569
573
570 removed = []
574 removed = []
571 if remove_obsolete:
575 if remove_obsolete:
572 # remove from database those repositories that are not in the filesystem
576 # remove from database those repositories that are not in the filesystem
573 for repo in sa.query(Repository).all():
577 for repo in sa.query(Repository).all():
574 if repo.repo_name not in initial_repo_list.keys():
578 if repo.repo_name not in initial_repo_list.keys():
575 log.debug("Removing non-existing repository found in db `%s`",
579 log.debug("Removing non-existing repository found in db `%s`",
576 repo.repo_name)
580 repo.repo_name)
577 try:
581 try:
578 RepoModel(sa).delete(repo, forks='detach', fs_remove=False)
582 RepoModel(sa).delete(repo, forks='detach', fs_remove=False)
579 sa.commit()
583 sa.commit()
580 removed.append(repo.repo_name)
584 removed.append(repo.repo_name)
581 except Exception:
585 except Exception:
582 # don't hold further removals on error
586 # don't hold further removals on error
583 log.error(traceback.format_exc())
587 log.error(traceback.format_exc())
584 sa.rollback()
588 sa.rollback()
585
589
586 def splitter(full_repo_name):
590 def splitter(full_repo_name):
587 _parts = full_repo_name.rsplit(RepoGroup.url_sep(), 1)
591 _parts = full_repo_name.rsplit(RepoGroup.url_sep(), 1)
588 gr_name = None
592 gr_name = None
589 if len(_parts) == 2:
593 if len(_parts) == 2:
590 gr_name = _parts[0]
594 gr_name = _parts[0]
591 return gr_name
595 return gr_name
592
596
593 initial_repo_group_list = [splitter(x) for x in
597 initial_repo_group_list = [splitter(x) for x in
594 initial_repo_list.keys() if splitter(x)]
598 initial_repo_list.keys() if splitter(x)]
595
599
596 # remove from database those repository groups that are not in the
600 # remove from database those repository groups that are not in the
597 # filesystem due to parent child relationships we need to delete them
601 # filesystem due to parent child relationships we need to delete them
598 # in a specific order of most nested first
602 # in a specific order of most nested first
599 all_groups = [x.group_name for x in sa.query(RepoGroup).all()]
603 all_groups = [x.group_name for x in sa.query(RepoGroup).all()]
600 nested_sort = lambda gr: len(gr.split('/'))
604 nested_sort = lambda gr: len(gr.split('/'))
601 for group_name in sorted(all_groups, key=nested_sort, reverse=True):
605 for group_name in sorted(all_groups, key=nested_sort, reverse=True):
602 if group_name not in initial_repo_group_list:
606 if group_name not in initial_repo_group_list:
603 repo_group = RepoGroup.get_by_group_name(group_name)
607 repo_group = RepoGroup.get_by_group_name(group_name)
604 if (repo_group.children.all() or
608 if (repo_group.children.all() or
605 not RepoGroupModel().check_exist_filesystem(
609 not RepoGroupModel().check_exist_filesystem(
606 group_name=group_name, exc_on_failure=False)):
610 group_name=group_name, exc_on_failure=False)):
607 continue
611 continue
608
612
609 log.info(
613 log.info(
610 'Removing non-existing repository group found in db `%s`',
614 'Removing non-existing repository group found in db `%s`',
611 group_name)
615 group_name)
612 try:
616 try:
613 RepoGroupModel(sa).delete(group_name, fs_remove=False)
617 RepoGroupModel(sa).delete(group_name, fs_remove=False)
614 sa.commit()
618 sa.commit()
615 removed.append(group_name)
619 removed.append(group_name)
616 except Exception:
620 except Exception:
617 # don't hold further removals on error
621 # don't hold further removals on error
618 log.exception(
622 log.exception(
619 'Unable to remove repository group `%s`',
623 'Unable to remove repository group `%s`',
620 group_name)
624 group_name)
621 sa.rollback()
625 sa.rollback()
622 raise
626 raise
623
627
624 return added, removed
628 return added, removed
625
629
626
630
627 def load_rcextensions(root_path):
631 def load_rcextensions(root_path):
628 import rhodecode
632 import rhodecode
629 from rhodecode.config import conf
633 from rhodecode.config import conf
630
634
631 path = os.path.join(root_path, 'rcextensions', '__init__.py')
635 path = os.path.join(root_path, 'rcextensions', '__init__.py')
632 if os.path.isfile(path):
636 if os.path.isfile(path):
633 rcext = create_module('rc', path)
637 rcext = create_module('rc', path)
634 EXT = rhodecode.EXTENSIONS = rcext
638 EXT = rhodecode.EXTENSIONS = rcext
635 log.debug('Found rcextensions now loading %s...', rcext)
639 log.debug('Found rcextensions now loading %s...', rcext)
636
640
637 # Additional mappings that are not present in the pygments lexers
641 # Additional mappings that are not present in the pygments lexers
638 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
642 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
639
643
640 # auto check if the module is not missing any data, set to default if is
644 # auto check if the module is not missing any data, set to default if is
641 # this will help autoupdate new feature of rcext module
645 # this will help autoupdate new feature of rcext module
642 #from rhodecode.config import rcextensions
646 #from rhodecode.config import rcextensions
643 #for k in dir(rcextensions):
647 #for k in dir(rcextensions):
644 # if not k.startswith('_') and not hasattr(EXT, k):
648 # if not k.startswith('_') and not hasattr(EXT, k):
645 # setattr(EXT, k, getattr(rcextensions, k))
649 # setattr(EXT, k, getattr(rcextensions, k))
646
650
647
651
648 def get_custom_lexer(extension):
652 def get_custom_lexer(extension):
649 """
653 """
650 returns a custom lexer if it is defined in rcextensions module, or None
654 returns a custom lexer if it is defined in rcextensions module, or None
651 if there's no custom lexer defined
655 if there's no custom lexer defined
652 """
656 """
653 import rhodecode
657 import rhodecode
654 from pygments import lexers
658 from pygments import lexers
655
659
656 # custom override made by RhodeCode
660 # custom override made by RhodeCode
657 if extension in ['mako']:
661 if extension in ['mako']:
658 return lexers.get_lexer_by_name('html+mako')
662 return lexers.get_lexer_by_name('html+mako')
659
663
660 # check if we didn't define this extension as other lexer
664 # check if we didn't define this extension as other lexer
661 extensions = rhodecode.EXTENSIONS and getattr(rhodecode.EXTENSIONS, 'EXTRA_LEXERS', None)
665 extensions = rhodecode.EXTENSIONS and getattr(rhodecode.EXTENSIONS, 'EXTRA_LEXERS', None)
662 if extensions and extension in rhodecode.EXTENSIONS.EXTRA_LEXERS:
666 if extensions and extension in rhodecode.EXTENSIONS.EXTRA_LEXERS:
663 _lexer_name = rhodecode.EXTENSIONS.EXTRA_LEXERS[extension]
667 _lexer_name = rhodecode.EXTENSIONS.EXTRA_LEXERS[extension]
664 return lexers.get_lexer_by_name(_lexer_name)
668 return lexers.get_lexer_by_name(_lexer_name)
665
669
666
670
667 #==============================================================================
671 #==============================================================================
668 # TEST FUNCTIONS AND CREATORS
672 # TEST FUNCTIONS AND CREATORS
669 #==============================================================================
673 #==============================================================================
670 def create_test_index(repo_location, config):
674 def create_test_index(repo_location, config):
671 """
675 """
672 Makes default test index.
676 Makes default test index.
673 """
677 """
674 import rc_testdata
678 import rc_testdata
675
679
676 rc_testdata.extract_search_index(
680 rc_testdata.extract_search_index(
677 'vcs_search_index', os.path.dirname(config['search.location']))
681 'vcs_search_index', os.path.dirname(config['search.location']))
678
682
679
683
680 def create_test_directory(test_path):
684 def create_test_directory(test_path):
681 """
685 """
682 Create test directory if it doesn't exist.
686 Create test directory if it doesn't exist.
683 """
687 """
684 if not os.path.isdir(test_path):
688 if not os.path.isdir(test_path):
685 log.debug('Creating testdir %s', test_path)
689 log.debug('Creating testdir %s', test_path)
686 os.makedirs(test_path)
690 os.makedirs(test_path)
687
691
688
692
689 def create_test_database(test_path, config):
693 def create_test_database(test_path, config):
690 """
694 """
691 Makes a fresh database.
695 Makes a fresh database.
692 """
696 """
693 from rhodecode.lib.db_manage import DbManage
697 from rhodecode.lib.db_manage import DbManage
694
698
695 # PART ONE create db
699 # PART ONE create db
696 dbconf = config['sqlalchemy.db1.url']
700 dbconf = config['sqlalchemy.db1.url']
697 log.debug('making test db %s', dbconf)
701 log.debug('making test db %s', dbconf)
698
702
699 dbmanage = DbManage(log_sql=False, dbconf=dbconf, root=config['here'],
703 dbmanage = DbManage(log_sql=False, dbconf=dbconf, root=config['here'],
700 tests=True, cli_args={'force_ask': True})
704 tests=True, cli_args={'force_ask': True})
701 dbmanage.create_tables(override=True)
705 dbmanage.create_tables(override=True)
702 dbmanage.set_db_version()
706 dbmanage.set_db_version()
703 # for tests dynamically set new root paths based on generated content
707 # for tests dynamically set new root paths based on generated content
704 dbmanage.create_settings(dbmanage.config_prompt(test_path))
708 dbmanage.create_settings(dbmanage.config_prompt(test_path))
705 dbmanage.create_default_user()
709 dbmanage.create_default_user()
706 dbmanage.create_test_admin_and_users()
710 dbmanage.create_test_admin_and_users()
707 dbmanage.create_permissions()
711 dbmanage.create_permissions()
708 dbmanage.populate_default_permissions()
712 dbmanage.populate_default_permissions()
709 Session().commit()
713 Session().commit()
710
714
711
715
712 def create_test_repositories(test_path, config):
716 def create_test_repositories(test_path, config):
713 """
717 """
714 Creates test repositories in the temporary directory. Repositories are
718 Creates test repositories in the temporary directory. Repositories are
715 extracted from archives within the rc_testdata package.
719 extracted from archives within the rc_testdata package.
716 """
720 """
717 import rc_testdata
721 import rc_testdata
718 from rhodecode.tests import HG_REPO, GIT_REPO, SVN_REPO
722 from rhodecode.tests import HG_REPO, GIT_REPO, SVN_REPO
719
723
720 log.debug('making test vcs repositories')
724 log.debug('making test vcs repositories')
721
725
722 idx_path = config['search.location']
726 idx_path = config['search.location']
723 data_path = config['cache_dir']
727 data_path = config['cache_dir']
724
728
725 # clean index and data
729 # clean index and data
726 if idx_path and os.path.exists(idx_path):
730 if idx_path and os.path.exists(idx_path):
727 log.debug('remove %s', idx_path)
731 log.debug('remove %s', idx_path)
728 shutil.rmtree(idx_path)
732 shutil.rmtree(idx_path)
729
733
730 if data_path and os.path.exists(data_path):
734 if data_path and os.path.exists(data_path):
731 log.debug('remove %s', data_path)
735 log.debug('remove %s', data_path)
732 shutil.rmtree(data_path)
736 shutil.rmtree(data_path)
733
737
734 rc_testdata.extract_hg_dump('vcs_test_hg', jn(test_path, HG_REPO))
738 rc_testdata.extract_hg_dump('vcs_test_hg', jn(test_path, HG_REPO))
735 rc_testdata.extract_git_dump('vcs_test_git', jn(test_path, GIT_REPO))
739 rc_testdata.extract_git_dump('vcs_test_git', jn(test_path, GIT_REPO))
736
740
737 # Note: Subversion is in the process of being integrated with the system,
741 # Note: Subversion is in the process of being integrated with the system,
738 # until we have a properly packed version of the test svn repository, this
742 # until we have a properly packed version of the test svn repository, this
739 # tries to copy over the repo from a package "rc_testdata"
743 # tries to copy over the repo from a package "rc_testdata"
740 svn_repo_path = rc_testdata.get_svn_repo_archive()
744 svn_repo_path = rc_testdata.get_svn_repo_archive()
741 with tarfile.open(svn_repo_path) as tar:
745 with tarfile.open(svn_repo_path) as tar:
742 tar.extractall(jn(test_path, SVN_REPO))
746 tar.extractall(jn(test_path, SVN_REPO))
743
747
744
748
745 def password_changed(auth_user, session):
749 def password_changed(auth_user, session):
746 # Never report password change in case of default user or anonymous user.
750 # Never report password change in case of default user or anonymous user.
747 if auth_user.username == User.DEFAULT_USER or auth_user.user_id is None:
751 if auth_user.username == User.DEFAULT_USER or auth_user.user_id is None:
748 return False
752 return False
749
753
750 password_hash = md5(auth_user.password) if auth_user.password else None
754 password_hash = md5(auth_user.password) if auth_user.password else None
751 rhodecode_user = session.get('rhodecode_user', {})
755 rhodecode_user = session.get('rhodecode_user', {})
752 session_password_hash = rhodecode_user.get('password', '')
756 session_password_hash = rhodecode_user.get('password', '')
753 return password_hash != session_password_hash
757 return password_hash != session_password_hash
754
758
755
759
756 def read_opensource_licenses():
760 def read_opensource_licenses():
757 global _license_cache
761 global _license_cache
758
762
759 if not _license_cache:
763 if not _license_cache:
760 licenses = pkg_resources.resource_string(
764 licenses = pkg_resources.resource_string(
761 'rhodecode', 'config/licenses.json')
765 'rhodecode', 'config/licenses.json')
762 _license_cache = json.loads(licenses)
766 _license_cache = json.loads(licenses)
763
767
764 return _license_cache
768 return _license_cache
765
769
766
770
767 def generate_platform_uuid():
771 def generate_platform_uuid():
768 """
772 """
769 Generates platform UUID based on it's name
773 Generates platform UUID based on it's name
770 """
774 """
771 import platform
775 import platform
772
776
773 try:
777 try:
774 uuid_list = [platform.platform()]
778 uuid_list = [platform.platform()]
775 return hashlib.sha256(':'.join(uuid_list)).hexdigest()
779 return hashlib.sha256(':'.join(uuid_list)).hexdigest()
776 except Exception as e:
780 except Exception as e:
777 log.error('Failed to generate host uuid: %s' % e)
781 log.error('Failed to generate host uuid: %s' % e)
778 return 'UNDEFINED'
782 return 'UNDEFINED'
General Comments 0
You need to be logged in to leave comments. Login now