##// END OF EJS Templates
import/repo-checks: skip validating storage path in detection of SCMs.
marcink -
r3074:4cafb093 default
parent child Browse files
Show More
@@ -1,776 +1,781 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 repo group', repo_group_name)
294 log.debug('Repo called %s exist, it is not a valid repo group', repo_group_name)
295 return False
295 return False
296
296
297 try:
297 try:
298 # we need to check bare git repos at higher level
298 # we need to check bare git repos at higher level
299 # since we might match branches/hooks/info/objects or possible
299 # since we might match branches/hooks/info/objects or possible
300 # other things inside bare git repo
300 # other things inside bare git repo
301 scm_ = get_scm(os.path.dirname(full_path))
301 maybe_repo = os.path.dirname(full_path)
302 if maybe_repo == base_path:
303 # skip root level repo check, we know root location CANNOT BE a repo group
304 return False
305
306 scm_ = get_scm(maybe_repo)
302 log.debug('path: %s is a vcs object:%s, not valid repo group', full_path, scm_)
307 log.debug('path: %s is a vcs object:%s, not valid repo group', full_path, scm_)
303 return False
308 return False
304 except VCSError:
309 except VCSError:
305 pass
310 pass
306
311
307 # check if it's a valid path
312 # check if it's a valid path
308 if skip_path_check or os.path.isdir(full_path):
313 if skip_path_check or os.path.isdir(full_path):
309 log.debug('path: %s is a valid repo group !', full_path)
314 log.debug('path: %s is a valid repo group !', full_path)
310 return True
315 return True
311
316
312 log.debug('path: %s is not a valid repo group !', full_path)
317 log.debug('path: %s is not a valid repo group !', full_path)
313 return False
318 return False
314
319
315
320
316 def ask_ok(prompt, retries=4, complaint='[y]es or [n]o please!'):
321 def ask_ok(prompt, retries=4, complaint='[y]es or [n]o please!'):
317 while True:
322 while True:
318 ok = raw_input(prompt)
323 ok = raw_input(prompt)
319 if ok.lower() in ('y', 'ye', 'yes'):
324 if ok.lower() in ('y', 'ye', 'yes'):
320 return True
325 return True
321 if ok.lower() in ('n', 'no', 'nop', 'nope'):
326 if ok.lower() in ('n', 'no', 'nop', 'nope'):
322 return False
327 return False
323 retries = retries - 1
328 retries = retries - 1
324 if retries < 0:
329 if retries < 0:
325 raise IOError
330 raise IOError
326 print(complaint)
331 print(complaint)
327
332
328 # propagated from mercurial documentation
333 # propagated from mercurial documentation
329 ui_sections = [
334 ui_sections = [
330 'alias', 'auth',
335 'alias', 'auth',
331 'decode/encode', 'defaults',
336 'decode/encode', 'defaults',
332 'diff', 'email',
337 'diff', 'email',
333 'extensions', 'format',
338 'extensions', 'format',
334 'merge-patterns', 'merge-tools',
339 'merge-patterns', 'merge-tools',
335 'hooks', 'http_proxy',
340 'hooks', 'http_proxy',
336 'smtp', 'patch',
341 'smtp', 'patch',
337 'paths', 'profiling',
342 'paths', 'profiling',
338 'server', 'trusted',
343 'server', 'trusted',
339 'ui', 'web', ]
344 'ui', 'web', ]
340
345
341
346
342 def config_data_from_db(clear_session=True, repo=None):
347 def config_data_from_db(clear_session=True, repo=None):
343 """
348 """
344 Read the configuration data from the database and return configuration
349 Read the configuration data from the database and return configuration
345 tuples.
350 tuples.
346 """
351 """
347 from rhodecode.model.settings import VcsSettingsModel
352 from rhodecode.model.settings import VcsSettingsModel
348
353
349 config = []
354 config = []
350
355
351 sa = meta.Session()
356 sa = meta.Session()
352 settings_model = VcsSettingsModel(repo=repo, sa=sa)
357 settings_model = VcsSettingsModel(repo=repo, sa=sa)
353
358
354 ui_settings = settings_model.get_ui_settings()
359 ui_settings = settings_model.get_ui_settings()
355
360
356 ui_data = []
361 ui_data = []
357 for setting in ui_settings:
362 for setting in ui_settings:
358 if setting.active:
363 if setting.active:
359 ui_data.append((setting.section, setting.key, setting.value))
364 ui_data.append((setting.section, setting.key, setting.value))
360 config.append((
365 config.append((
361 safe_str(setting.section), safe_str(setting.key),
366 safe_str(setting.section), safe_str(setting.key),
362 safe_str(setting.value)))
367 safe_str(setting.value)))
363 if setting.key == 'push_ssl':
368 if setting.key == 'push_ssl':
364 # force set push_ssl requirement to False, rhodecode
369 # force set push_ssl requirement to False, rhodecode
365 # handles that
370 # handles that
366 config.append((
371 config.append((
367 safe_str(setting.section), safe_str(setting.key), False))
372 safe_str(setting.section), safe_str(setting.key), False))
368 log.debug(
373 log.debug(
369 'settings ui from db: %s',
374 'settings ui from db: %s',
370 ','.join(map(lambda s: '[{}] {}={}'.format(*s), ui_data)))
375 ','.join(map(lambda s: '[{}] {}={}'.format(*s), ui_data)))
371 if clear_session:
376 if clear_session:
372 meta.Session.remove()
377 meta.Session.remove()
373
378
374 # TODO: mikhail: probably it makes no sense to re-read hooks information.
379 # TODO: mikhail: probably it makes no sense to re-read hooks information.
375 # It's already there and activated/deactivated
380 # It's already there and activated/deactivated
376 skip_entries = []
381 skip_entries = []
377 enabled_hook_classes = get_enabled_hook_classes(ui_settings)
382 enabled_hook_classes = get_enabled_hook_classes(ui_settings)
378 if 'pull' not in enabled_hook_classes:
383 if 'pull' not in enabled_hook_classes:
379 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PULL))
384 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PULL))
380 if 'push' not in enabled_hook_classes:
385 if 'push' not in enabled_hook_classes:
381 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PUSH))
386 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRE_PUSH))
382 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRETX_PUSH))
387 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PRETX_PUSH))
383 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PUSH_KEY))
388 skip_entries.append(('hooks', RhodeCodeUi.HOOK_PUSH_KEY))
384
389
385 config = [entry for entry in config if entry[:2] not in skip_entries]
390 config = [entry for entry in config if entry[:2] not in skip_entries]
386
391
387 return config
392 return config
388
393
389
394
390 def make_db_config(clear_session=True, repo=None):
395 def make_db_config(clear_session=True, repo=None):
391 """
396 """
392 Create a :class:`Config` instance based on the values in the database.
397 Create a :class:`Config` instance based on the values in the database.
393 """
398 """
394 config = Config()
399 config = Config()
395 config_data = config_data_from_db(clear_session=clear_session, repo=repo)
400 config_data = config_data_from_db(clear_session=clear_session, repo=repo)
396 for section, option, value in config_data:
401 for section, option, value in config_data:
397 config.set(section, option, value)
402 config.set(section, option, value)
398 return config
403 return config
399
404
400
405
401 def get_enabled_hook_classes(ui_settings):
406 def get_enabled_hook_classes(ui_settings):
402 """
407 """
403 Return the enabled hook classes.
408 Return the enabled hook classes.
404
409
405 :param ui_settings: List of ui_settings as returned
410 :param ui_settings: List of ui_settings as returned
406 by :meth:`VcsSettingsModel.get_ui_settings`
411 by :meth:`VcsSettingsModel.get_ui_settings`
407
412
408 :return: a list with the enabled hook classes. The order is not guaranteed.
413 :return: a list with the enabled hook classes. The order is not guaranteed.
409 :rtype: list
414 :rtype: list
410 """
415 """
411 enabled_hooks = []
416 enabled_hooks = []
412 active_hook_keys = [
417 active_hook_keys = [
413 key for section, key, value, active in ui_settings
418 key for section, key, value, active in ui_settings
414 if section == 'hooks' and active]
419 if section == 'hooks' and active]
415
420
416 hook_names = {
421 hook_names = {
417 RhodeCodeUi.HOOK_PUSH: 'push',
422 RhodeCodeUi.HOOK_PUSH: 'push',
418 RhodeCodeUi.HOOK_PULL: 'pull',
423 RhodeCodeUi.HOOK_PULL: 'pull',
419 RhodeCodeUi.HOOK_REPO_SIZE: 'repo_size'
424 RhodeCodeUi.HOOK_REPO_SIZE: 'repo_size'
420 }
425 }
421
426
422 for key in active_hook_keys:
427 for key in active_hook_keys:
423 hook = hook_names.get(key)
428 hook = hook_names.get(key)
424 if hook:
429 if hook:
425 enabled_hooks.append(hook)
430 enabled_hooks.append(hook)
426
431
427 return enabled_hooks
432 return enabled_hooks
428
433
429
434
430 def set_rhodecode_config(config):
435 def set_rhodecode_config(config):
431 """
436 """
432 Updates pyramid config with new settings from database
437 Updates pyramid config with new settings from database
433
438
434 :param config:
439 :param config:
435 """
440 """
436 from rhodecode.model.settings import SettingsModel
441 from rhodecode.model.settings import SettingsModel
437 app_settings = SettingsModel().get_all_settings()
442 app_settings = SettingsModel().get_all_settings()
438
443
439 for k, v in app_settings.items():
444 for k, v in app_settings.items():
440 config[k] = v
445 config[k] = v
441
446
442
447
443 def get_rhodecode_realm():
448 def get_rhodecode_realm():
444 """
449 """
445 Return the rhodecode realm from database.
450 Return the rhodecode realm from database.
446 """
451 """
447 from rhodecode.model.settings import SettingsModel
452 from rhodecode.model.settings import SettingsModel
448 realm = SettingsModel().get_setting_by_name('realm')
453 realm = SettingsModel().get_setting_by_name('realm')
449 return safe_str(realm.app_settings_value)
454 return safe_str(realm.app_settings_value)
450
455
451
456
452 def get_rhodecode_base_path():
457 def get_rhodecode_base_path():
453 """
458 """
454 Returns the base path. The base path is the filesystem path which points
459 Returns the base path. The base path is the filesystem path which points
455 to the repository store.
460 to the repository store.
456 """
461 """
457 from rhodecode.model.settings import SettingsModel
462 from rhodecode.model.settings import SettingsModel
458 paths_ui = SettingsModel().get_ui_by_section_and_key('paths', '/')
463 paths_ui = SettingsModel().get_ui_by_section_and_key('paths', '/')
459 return safe_str(paths_ui.ui_value)
464 return safe_str(paths_ui.ui_value)
460
465
461
466
462 def map_groups(path):
467 def map_groups(path):
463 """
468 """
464 Given a full path to a repository, create all nested groups that this
469 Given a full path to a repository, create all nested groups that this
465 repo is inside. This function creates parent-child relationships between
470 repo is inside. This function creates parent-child relationships between
466 groups and creates default perms for all new groups.
471 groups and creates default perms for all new groups.
467
472
468 :param paths: full path to repository
473 :param paths: full path to repository
469 """
474 """
470 from rhodecode.model.repo_group import RepoGroupModel
475 from rhodecode.model.repo_group import RepoGroupModel
471 sa = meta.Session()
476 sa = meta.Session()
472 groups = path.split(Repository.NAME_SEP)
477 groups = path.split(Repository.NAME_SEP)
473 parent = None
478 parent = None
474 group = None
479 group = None
475
480
476 # last element is repo in nested groups structure
481 # last element is repo in nested groups structure
477 groups = groups[:-1]
482 groups = groups[:-1]
478 rgm = RepoGroupModel(sa)
483 rgm = RepoGroupModel(sa)
479 owner = User.get_first_super_admin()
484 owner = User.get_first_super_admin()
480 for lvl, group_name in enumerate(groups):
485 for lvl, group_name in enumerate(groups):
481 group_name = '/'.join(groups[:lvl] + [group_name])
486 group_name = '/'.join(groups[:lvl] + [group_name])
482 group = RepoGroup.get_by_group_name(group_name)
487 group = RepoGroup.get_by_group_name(group_name)
483 desc = '%s group' % group_name
488 desc = '%s group' % group_name
484
489
485 # skip folders that are now removed repos
490 # skip folders that are now removed repos
486 if REMOVED_REPO_PAT.match(group_name):
491 if REMOVED_REPO_PAT.match(group_name):
487 break
492 break
488
493
489 if group is None:
494 if group is None:
490 log.debug('creating group level: %s group_name: %s',
495 log.debug('creating group level: %s group_name: %s',
491 lvl, group_name)
496 lvl, group_name)
492 group = RepoGroup(group_name, parent)
497 group = RepoGroup(group_name, parent)
493 group.group_description = desc
498 group.group_description = desc
494 group.user = owner
499 group.user = owner
495 sa.add(group)
500 sa.add(group)
496 perm_obj = rgm._create_default_perms(group)
501 perm_obj = rgm._create_default_perms(group)
497 sa.add(perm_obj)
502 sa.add(perm_obj)
498 sa.flush()
503 sa.flush()
499
504
500 parent = group
505 parent = group
501 return group
506 return group
502
507
503
508
504 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
509 def repo2db_mapper(initial_repo_list, remove_obsolete=False):
505 """
510 """
506 maps all repos given in initial_repo_list, non existing repositories
511 maps all repos given in initial_repo_list, non existing repositories
507 are created, if remove_obsolete is True it also checks for db entries
512 are created, if remove_obsolete is True it also checks for db entries
508 that are not in initial_repo_list and removes them.
513 that are not in initial_repo_list and removes them.
509
514
510 :param initial_repo_list: list of repositories found by scanning methods
515 :param initial_repo_list: list of repositories found by scanning methods
511 :param remove_obsolete: check for obsolete entries in database
516 :param remove_obsolete: check for obsolete entries in database
512 """
517 """
513 from rhodecode.model.repo import RepoModel
518 from rhodecode.model.repo import RepoModel
514 from rhodecode.model.repo_group import RepoGroupModel
519 from rhodecode.model.repo_group import RepoGroupModel
515 from rhodecode.model.settings import SettingsModel
520 from rhodecode.model.settings import SettingsModel
516
521
517 sa = meta.Session()
522 sa = meta.Session()
518 repo_model = RepoModel()
523 repo_model = RepoModel()
519 user = User.get_first_super_admin()
524 user = User.get_first_super_admin()
520 added = []
525 added = []
521
526
522 # creation defaults
527 # creation defaults
523 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
528 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
524 enable_statistics = defs.get('repo_enable_statistics')
529 enable_statistics = defs.get('repo_enable_statistics')
525 enable_locking = defs.get('repo_enable_locking')
530 enable_locking = defs.get('repo_enable_locking')
526 enable_downloads = defs.get('repo_enable_downloads')
531 enable_downloads = defs.get('repo_enable_downloads')
527 private = defs.get('repo_private')
532 private = defs.get('repo_private')
528
533
529 for name, repo in initial_repo_list.items():
534 for name, repo in initial_repo_list.items():
530 group = map_groups(name)
535 group = map_groups(name)
531 unicode_name = safe_unicode(name)
536 unicode_name = safe_unicode(name)
532 db_repo = repo_model.get_by_repo_name(unicode_name)
537 db_repo = repo_model.get_by_repo_name(unicode_name)
533 # found repo that is on filesystem not in RhodeCode database
538 # found repo that is on filesystem not in RhodeCode database
534 if not db_repo:
539 if not db_repo:
535 log.info('repository %s not found, creating now', name)
540 log.info('repository %s not found, creating now', name)
536 added.append(name)
541 added.append(name)
537 desc = (repo.description
542 desc = (repo.description
538 if repo.description != 'unknown'
543 if repo.description != 'unknown'
539 else '%s repository' % name)
544 else '%s repository' % name)
540
545
541 db_repo = repo_model._create_repo(
546 db_repo = repo_model._create_repo(
542 repo_name=name,
547 repo_name=name,
543 repo_type=repo.alias,
548 repo_type=repo.alias,
544 description=desc,
549 description=desc,
545 repo_group=getattr(group, 'group_id', None),
550 repo_group=getattr(group, 'group_id', None),
546 owner=user,
551 owner=user,
547 enable_locking=enable_locking,
552 enable_locking=enable_locking,
548 enable_downloads=enable_downloads,
553 enable_downloads=enable_downloads,
549 enable_statistics=enable_statistics,
554 enable_statistics=enable_statistics,
550 private=private,
555 private=private,
551 state=Repository.STATE_CREATED
556 state=Repository.STATE_CREATED
552 )
557 )
553 sa.commit()
558 sa.commit()
554 # we added that repo just now, and make sure we updated server info
559 # we added that repo just now, and make sure we updated server info
555 if db_repo.repo_type == 'git':
560 if db_repo.repo_type == 'git':
556 git_repo = db_repo.scm_instance()
561 git_repo = db_repo.scm_instance()
557 # update repository server-info
562 # update repository server-info
558 log.debug('Running update server info')
563 log.debug('Running update server info')
559 git_repo._update_server_info()
564 git_repo._update_server_info()
560
565
561 db_repo.update_commit_cache()
566 db_repo.update_commit_cache()
562
567
563 config = db_repo._config
568 config = db_repo._config
564 config.set('extensions', 'largefiles', '')
569 config.set('extensions', 'largefiles', '')
565 repo = db_repo.scm_instance(config=config)
570 repo = db_repo.scm_instance(config=config)
566 repo.install_hooks()
571 repo.install_hooks()
567
572
568 removed = []
573 removed = []
569 if remove_obsolete:
574 if remove_obsolete:
570 # remove from database those repositories that are not in the filesystem
575 # remove from database those repositories that are not in the filesystem
571 for repo in sa.query(Repository).all():
576 for repo in sa.query(Repository).all():
572 if repo.repo_name not in initial_repo_list.keys():
577 if repo.repo_name not in initial_repo_list.keys():
573 log.debug("Removing non-existing repository found in db `%s`",
578 log.debug("Removing non-existing repository found in db `%s`",
574 repo.repo_name)
579 repo.repo_name)
575 try:
580 try:
576 RepoModel(sa).delete(repo, forks='detach', fs_remove=False)
581 RepoModel(sa).delete(repo, forks='detach', fs_remove=False)
577 sa.commit()
582 sa.commit()
578 removed.append(repo.repo_name)
583 removed.append(repo.repo_name)
579 except Exception:
584 except Exception:
580 # don't hold further removals on error
585 # don't hold further removals on error
581 log.error(traceback.format_exc())
586 log.error(traceback.format_exc())
582 sa.rollback()
587 sa.rollback()
583
588
584 def splitter(full_repo_name):
589 def splitter(full_repo_name):
585 _parts = full_repo_name.rsplit(RepoGroup.url_sep(), 1)
590 _parts = full_repo_name.rsplit(RepoGroup.url_sep(), 1)
586 gr_name = None
591 gr_name = None
587 if len(_parts) == 2:
592 if len(_parts) == 2:
588 gr_name = _parts[0]
593 gr_name = _parts[0]
589 return gr_name
594 return gr_name
590
595
591 initial_repo_group_list = [splitter(x) for x in
596 initial_repo_group_list = [splitter(x) for x in
592 initial_repo_list.keys() if splitter(x)]
597 initial_repo_list.keys() if splitter(x)]
593
598
594 # remove from database those repository groups that are not in the
599 # remove from database those repository groups that are not in the
595 # filesystem due to parent child relationships we need to delete them
600 # filesystem due to parent child relationships we need to delete them
596 # in a specific order of most nested first
601 # in a specific order of most nested first
597 all_groups = [x.group_name for x in sa.query(RepoGroup).all()]
602 all_groups = [x.group_name for x in sa.query(RepoGroup).all()]
598 nested_sort = lambda gr: len(gr.split('/'))
603 nested_sort = lambda gr: len(gr.split('/'))
599 for group_name in sorted(all_groups, key=nested_sort, reverse=True):
604 for group_name in sorted(all_groups, key=nested_sort, reverse=True):
600 if group_name not in initial_repo_group_list:
605 if group_name not in initial_repo_group_list:
601 repo_group = RepoGroup.get_by_group_name(group_name)
606 repo_group = RepoGroup.get_by_group_name(group_name)
602 if (repo_group.children.all() or
607 if (repo_group.children.all() or
603 not RepoGroupModel().check_exist_filesystem(
608 not RepoGroupModel().check_exist_filesystem(
604 group_name=group_name, exc_on_failure=False)):
609 group_name=group_name, exc_on_failure=False)):
605 continue
610 continue
606
611
607 log.info(
612 log.info(
608 'Removing non-existing repository group found in db `%s`',
613 'Removing non-existing repository group found in db `%s`',
609 group_name)
614 group_name)
610 try:
615 try:
611 RepoGroupModel(sa).delete(group_name, fs_remove=False)
616 RepoGroupModel(sa).delete(group_name, fs_remove=False)
612 sa.commit()
617 sa.commit()
613 removed.append(group_name)
618 removed.append(group_name)
614 except Exception:
619 except Exception:
615 # don't hold further removals on error
620 # don't hold further removals on error
616 log.exception(
621 log.exception(
617 'Unable to remove repository group `%s`',
622 'Unable to remove repository group `%s`',
618 group_name)
623 group_name)
619 sa.rollback()
624 sa.rollback()
620 raise
625 raise
621
626
622 return added, removed
627 return added, removed
623
628
624
629
625 def load_rcextensions(root_path):
630 def load_rcextensions(root_path):
626 import rhodecode
631 import rhodecode
627 from rhodecode.config import conf
632 from rhodecode.config import conf
628
633
629 path = os.path.join(root_path, 'rcextensions', '__init__.py')
634 path = os.path.join(root_path, 'rcextensions', '__init__.py')
630 if os.path.isfile(path):
635 if os.path.isfile(path):
631 rcext = create_module('rc', path)
636 rcext = create_module('rc', path)
632 EXT = rhodecode.EXTENSIONS = rcext
637 EXT = rhodecode.EXTENSIONS = rcext
633 log.debug('Found rcextensions now loading %s...', rcext)
638 log.debug('Found rcextensions now loading %s...', rcext)
634
639
635 # Additional mappings that are not present in the pygments lexers
640 # Additional mappings that are not present in the pygments lexers
636 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
641 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
637
642
638 # auto check if the module is not missing any data, set to default if is
643 # auto check if the module is not missing any data, set to default if is
639 # this will help autoupdate new feature of rcext module
644 # this will help autoupdate new feature of rcext module
640 #from rhodecode.config import rcextensions
645 #from rhodecode.config import rcextensions
641 #for k in dir(rcextensions):
646 #for k in dir(rcextensions):
642 # if not k.startswith('_') and not hasattr(EXT, k):
647 # if not k.startswith('_') and not hasattr(EXT, k):
643 # setattr(EXT, k, getattr(rcextensions, k))
648 # setattr(EXT, k, getattr(rcextensions, k))
644
649
645
650
646 def get_custom_lexer(extension):
651 def get_custom_lexer(extension):
647 """
652 """
648 returns a custom lexer if it is defined in rcextensions module, or None
653 returns a custom lexer if it is defined in rcextensions module, or None
649 if there's no custom lexer defined
654 if there's no custom lexer defined
650 """
655 """
651 import rhodecode
656 import rhodecode
652 from pygments import lexers
657 from pygments import lexers
653
658
654 # custom override made by RhodeCode
659 # custom override made by RhodeCode
655 if extension in ['mako']:
660 if extension in ['mako']:
656 return lexers.get_lexer_by_name('html+mako')
661 return lexers.get_lexer_by_name('html+mako')
657
662
658 # check if we didn't define this extension as other lexer
663 # check if we didn't define this extension as other lexer
659 extensions = rhodecode.EXTENSIONS and getattr(rhodecode.EXTENSIONS, 'EXTRA_LEXERS', None)
664 extensions = rhodecode.EXTENSIONS and getattr(rhodecode.EXTENSIONS, 'EXTRA_LEXERS', None)
660 if extensions and extension in rhodecode.EXTENSIONS.EXTRA_LEXERS:
665 if extensions and extension in rhodecode.EXTENSIONS.EXTRA_LEXERS:
661 _lexer_name = rhodecode.EXTENSIONS.EXTRA_LEXERS[extension]
666 _lexer_name = rhodecode.EXTENSIONS.EXTRA_LEXERS[extension]
662 return lexers.get_lexer_by_name(_lexer_name)
667 return lexers.get_lexer_by_name(_lexer_name)
663
668
664
669
665 #==============================================================================
670 #==============================================================================
666 # TEST FUNCTIONS AND CREATORS
671 # TEST FUNCTIONS AND CREATORS
667 #==============================================================================
672 #==============================================================================
668 def create_test_index(repo_location, config):
673 def create_test_index(repo_location, config):
669 """
674 """
670 Makes default test index.
675 Makes default test index.
671 """
676 """
672 import rc_testdata
677 import rc_testdata
673
678
674 rc_testdata.extract_search_index(
679 rc_testdata.extract_search_index(
675 'vcs_search_index', os.path.dirname(config['search.location']))
680 'vcs_search_index', os.path.dirname(config['search.location']))
676
681
677
682
678 def create_test_directory(test_path):
683 def create_test_directory(test_path):
679 """
684 """
680 Create test directory if it doesn't exist.
685 Create test directory if it doesn't exist.
681 """
686 """
682 if not os.path.isdir(test_path):
687 if not os.path.isdir(test_path):
683 log.debug('Creating testdir %s', test_path)
688 log.debug('Creating testdir %s', test_path)
684 os.makedirs(test_path)
689 os.makedirs(test_path)
685
690
686
691
687 def create_test_database(test_path, config):
692 def create_test_database(test_path, config):
688 """
693 """
689 Makes a fresh database.
694 Makes a fresh database.
690 """
695 """
691 from rhodecode.lib.db_manage import DbManage
696 from rhodecode.lib.db_manage import DbManage
692
697
693 # PART ONE create db
698 # PART ONE create db
694 dbconf = config['sqlalchemy.db1.url']
699 dbconf = config['sqlalchemy.db1.url']
695 log.debug('making test db %s', dbconf)
700 log.debug('making test db %s', dbconf)
696
701
697 dbmanage = DbManage(log_sql=False, dbconf=dbconf, root=config['here'],
702 dbmanage = DbManage(log_sql=False, dbconf=dbconf, root=config['here'],
698 tests=True, cli_args={'force_ask': True})
703 tests=True, cli_args={'force_ask': True})
699 dbmanage.create_tables(override=True)
704 dbmanage.create_tables(override=True)
700 dbmanage.set_db_version()
705 dbmanage.set_db_version()
701 # for tests dynamically set new root paths based on generated content
706 # for tests dynamically set new root paths based on generated content
702 dbmanage.create_settings(dbmanage.config_prompt(test_path))
707 dbmanage.create_settings(dbmanage.config_prompt(test_path))
703 dbmanage.create_default_user()
708 dbmanage.create_default_user()
704 dbmanage.create_test_admin_and_users()
709 dbmanage.create_test_admin_and_users()
705 dbmanage.create_permissions()
710 dbmanage.create_permissions()
706 dbmanage.populate_default_permissions()
711 dbmanage.populate_default_permissions()
707 Session().commit()
712 Session().commit()
708
713
709
714
710 def create_test_repositories(test_path, config):
715 def create_test_repositories(test_path, config):
711 """
716 """
712 Creates test repositories in the temporary directory. Repositories are
717 Creates test repositories in the temporary directory. Repositories are
713 extracted from archives within the rc_testdata package.
718 extracted from archives within the rc_testdata package.
714 """
719 """
715 import rc_testdata
720 import rc_testdata
716 from rhodecode.tests import HG_REPO, GIT_REPO, SVN_REPO
721 from rhodecode.tests import HG_REPO, GIT_REPO, SVN_REPO
717
722
718 log.debug('making test vcs repositories')
723 log.debug('making test vcs repositories')
719
724
720 idx_path = config['search.location']
725 idx_path = config['search.location']
721 data_path = config['cache_dir']
726 data_path = config['cache_dir']
722
727
723 # clean index and data
728 # clean index and data
724 if idx_path and os.path.exists(idx_path):
729 if idx_path and os.path.exists(idx_path):
725 log.debug('remove %s', idx_path)
730 log.debug('remove %s', idx_path)
726 shutil.rmtree(idx_path)
731 shutil.rmtree(idx_path)
727
732
728 if data_path and os.path.exists(data_path):
733 if data_path and os.path.exists(data_path):
729 log.debug('remove %s', data_path)
734 log.debug('remove %s', data_path)
730 shutil.rmtree(data_path)
735 shutil.rmtree(data_path)
731
736
732 rc_testdata.extract_hg_dump('vcs_test_hg', jn(test_path, HG_REPO))
737 rc_testdata.extract_hg_dump('vcs_test_hg', jn(test_path, HG_REPO))
733 rc_testdata.extract_git_dump('vcs_test_git', jn(test_path, GIT_REPO))
738 rc_testdata.extract_git_dump('vcs_test_git', jn(test_path, GIT_REPO))
734
739
735 # Note: Subversion is in the process of being integrated with the system,
740 # Note: Subversion is in the process of being integrated with the system,
736 # until we have a properly packed version of the test svn repository, this
741 # until we have a properly packed version of the test svn repository, this
737 # tries to copy over the repo from a package "rc_testdata"
742 # tries to copy over the repo from a package "rc_testdata"
738 svn_repo_path = rc_testdata.get_svn_repo_archive()
743 svn_repo_path = rc_testdata.get_svn_repo_archive()
739 with tarfile.open(svn_repo_path) as tar:
744 with tarfile.open(svn_repo_path) as tar:
740 tar.extractall(jn(test_path, SVN_REPO))
745 tar.extractall(jn(test_path, SVN_REPO))
741
746
742
747
743 def password_changed(auth_user, session):
748 def password_changed(auth_user, session):
744 # Never report password change in case of default user or anonymous user.
749 # Never report password change in case of default user or anonymous user.
745 if auth_user.username == User.DEFAULT_USER or auth_user.user_id is None:
750 if auth_user.username == User.DEFAULT_USER or auth_user.user_id is None:
746 return False
751 return False
747
752
748 password_hash = md5(auth_user.password) if auth_user.password else None
753 password_hash = md5(auth_user.password) if auth_user.password else None
749 rhodecode_user = session.get('rhodecode_user', {})
754 rhodecode_user = session.get('rhodecode_user', {})
750 session_password_hash = rhodecode_user.get('password', '')
755 session_password_hash = rhodecode_user.get('password', '')
751 return password_hash != session_password_hash
756 return password_hash != session_password_hash
752
757
753
758
754 def read_opensource_licenses():
759 def read_opensource_licenses():
755 global _license_cache
760 global _license_cache
756
761
757 if not _license_cache:
762 if not _license_cache:
758 licenses = pkg_resources.resource_string(
763 licenses = pkg_resources.resource_string(
759 'rhodecode', 'config/licenses.json')
764 'rhodecode', 'config/licenses.json')
760 _license_cache = json.loads(licenses)
765 _license_cache = json.loads(licenses)
761
766
762 return _license_cache
767 return _license_cache
763
768
764
769
765 def generate_platform_uuid():
770 def generate_platform_uuid():
766 """
771 """
767 Generates platform UUID based on it's name
772 Generates platform UUID based on it's name
768 """
773 """
769 import platform
774 import platform
770
775
771 try:
776 try:
772 uuid_list = [platform.platform()]
777 uuid_list = [platform.platform()]
773 return hashlib.sha256(':'.join(uuid_list)).hexdigest()
778 return hashlib.sha256(':'.join(uuid_list)).hexdigest()
774 except Exception as e:
779 except Exception as e:
775 log.error('Failed to generate host uuid: %s', e)
780 log.error('Failed to generate host uuid: %s', e)
776 return 'UNDEFINED'
781 return 'UNDEFINED'
General Comments 0
You need to be logged in to leave comments. Login now