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