##// END OF EJS Templates
utils/conf...
marcink -
r2109:8ecfed1d beta
parent child Browse files
Show More
@@ -0,0 +1,58 b''
1 # -*- coding: utf-8 -*-
2 """
3 package.rhodecode.config.conf
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 Various config settings for RhodeCode
7
8 :created_on: Mar 7, 2012
9 :author: marcink
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
11 :license: <name>, see LICENSE_FILE for more details.
12 """
13 from rhodecode import EXTENSIONS
14
15 from rhodecode.lib.utils2 import __get_lem
16
17
18 # language map is also used by whoosh indexer, which for those specified
19 # extensions will index it's content
20 LANGUAGES_EXTENSIONS_MAP = __get_lem()
21
22 #==============================================================================
23 # WHOOSH INDEX EXTENSIONS
24 #==============================================================================
25 # EXTENSIONS WE WANT TO INDEX CONTENT OFF USING WHOOSH
26 INDEX_EXTENSIONS = LANGUAGES_EXTENSIONS_MAP.keys()
27
28 # list of readme files to search in file tree and display in summary
29 # attached weights defines the search order lower is first
30 ALL_READMES = [
31 ('readme', 0), ('README', 0), ('Readme', 0),
32 ('doc/readme', 1), ('doc/README', 1), ('doc/Readme', 1),
33 ('Docs/readme', 2), ('Docs/README', 2), ('Docs/Readme', 2),
34 ('DOCS/readme', 2), ('DOCS/README', 2), ('DOCS/Readme', 2),
35 ('docs/readme', 2), ('docs/README', 2), ('docs/Readme', 2),
36 ]
37
38 # extension together with weights to search lower is first
39 RST_EXTS = [
40 ('', 0), ('.rst', 1), ('.rest', 1),
41 ('.RST', 2), ('.REST', 2),
42 ('.txt', 3), ('.TXT', 3)
43 ]
44
45 MARKDOWN_EXTS = [
46 ('.md', 1), ('.MD', 1),
47 ('.mkdn', 2), ('.MKDN', 2),
48 ('.mdown', 3), ('.MDOWN', 3),
49 ('.markdown', 4), ('.MARKDOWN', 4)
50 ]
51
52 PLAIN_EXTS = [('.text', 2), ('.TEXT', 2)]
53
54 ALL_EXTS = MARKDOWN_EXTS + RST_EXTS + PLAIN_EXTS
55
56 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
57
58 DATE_FORMAT = "%Y-%m-%d"
@@ -0,0 +1,405 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.lib.utils
4 ~~~~~~~~~~~~~~~~~~~
5
6 Some simple helper functions
7
8 :created_on: Jan 5, 2011
9 :author: marcink
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
26 import re
27 from rhodecode.lib.vcs.utils.lazy import LazyProperty
28
29
30 def __get_lem():
31 """
32 Get language extension map based on what's inside pygments lexers
33 """
34 from pygments import lexers
35 from string import lower
36 from collections import defaultdict
37
38 d = defaultdict(lambda: [])
39
40 def __clean(s):
41 s = s.lstrip('*')
42 s = s.lstrip('.')
43
44 if s.find('[') != -1:
45 exts = []
46 start, stop = s.find('['), s.find(']')
47
48 for suffix in s[start + 1:stop]:
49 exts.append(s[:s.find('[')] + suffix)
50 return map(lower, exts)
51 else:
52 return map(lower, [s])
53
54 for lx, t in sorted(lexers.LEXERS.items()):
55 m = map(__clean, t[-2])
56 if m:
57 m = reduce(lambda x, y: x + y, m)
58 for ext in m:
59 desc = lx.replace('Lexer', '')
60 d[ext].append(desc)
61
62 return dict(d)
63
64 def str2bool(_str):
65 """
66 returs True/False value from given string, it tries to translate the
67 string into boolean
68
69 :param _str: string value to translate into boolean
70 :rtype: boolean
71 :returns: boolean from given string
72 """
73 if _str is None:
74 return False
75 if _str in (True, False):
76 return _str
77 _str = str(_str).strip().lower()
78 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
79
80
81 def convert_line_endings(line, mode):
82 """
83 Converts a given line "line end" accordingly to given mode
84
85 Available modes are::
86 0 - Unix
87 1 - Mac
88 2 - DOS
89
90 :param line: given line to convert
91 :param mode: mode to convert to
92 :rtype: str
93 :return: converted line according to mode
94 """
95 from string import replace
96
97 if mode == 0:
98 line = replace(line, '\r\n', '\n')
99 line = replace(line, '\r', '\n')
100 elif mode == 1:
101 line = replace(line, '\r\n', '\r')
102 line = replace(line, '\n', '\r')
103 elif mode == 2:
104 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
105 return line
106
107
108 def detect_mode(line, default):
109 """
110 Detects line break for given line, if line break couldn't be found
111 given default value is returned
112
113 :param line: str line
114 :param default: default
115 :rtype: int
116 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
117 """
118 if line.endswith('\r\n'):
119 return 2
120 elif line.endswith('\n'):
121 return 0
122 elif line.endswith('\r'):
123 return 1
124 else:
125 return default
126
127
128 def generate_api_key(username, salt=None):
129 """
130 Generates unique API key for given username, if salt is not given
131 it'll be generated from some random string
132
133 :param username: username as string
134 :param salt: salt to hash generate KEY
135 :rtype: str
136 :returns: sha1 hash from username+salt
137 """
138 from tempfile import _RandomNameSequence
139 import hashlib
140
141 if salt is None:
142 salt = _RandomNameSequence().next()
143
144 return hashlib.sha1(username + salt).hexdigest()
145
146
147 def safe_unicode(str_, from_encoding=None):
148 """
149 safe unicode function. Does few trick to turn str_ into unicode
150
151 In case of UnicodeDecode error we try to return it with encoding detected
152 by chardet library if it fails fallback to unicode with errors replaced
153
154 :param str_: string to decode
155 :rtype: unicode
156 :returns: unicode object
157 """
158 if isinstance(str_, unicode):
159 return str_
160
161 if not from_encoding:
162 import rhodecode
163 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
164 from_encoding = DEFAULT_ENCODING
165
166 try:
167 return unicode(str_)
168 except UnicodeDecodeError:
169 pass
170
171 try:
172 return unicode(str_, from_encoding)
173 except UnicodeDecodeError:
174 pass
175
176 try:
177 import chardet
178 encoding = chardet.detect(str_)['encoding']
179 if encoding is None:
180 raise Exception()
181 return str_.decode(encoding)
182 except (ImportError, UnicodeDecodeError, Exception):
183 return unicode(str_, from_encoding, 'replace')
184
185
186 def safe_str(unicode_, to_encoding=None):
187 """
188 safe str function. Does few trick to turn unicode_ into string
189
190 In case of UnicodeEncodeError we try to return it with encoding detected
191 by chardet library if it fails fallback to string with errors replaced
192
193 :param unicode_: unicode to encode
194 :rtype: str
195 :returns: str object
196 """
197
198 # if it's not basestr cast to str
199 if not isinstance(unicode_, basestring):
200 return str(unicode_)
201
202 if isinstance(unicode_, str):
203 return unicode_
204
205 if not to_encoding:
206 import rhodecode
207 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
208 to_encoding = DEFAULT_ENCODING
209
210 try:
211 return unicode_.encode(to_encoding)
212 except UnicodeEncodeError:
213 pass
214
215 try:
216 import chardet
217 encoding = chardet.detect(unicode_)['encoding']
218 print encoding
219 if encoding is None:
220 raise UnicodeEncodeError()
221
222 return unicode_.encode(encoding)
223 except (ImportError, UnicodeEncodeError):
224 return unicode_.encode(to_encoding, 'replace')
225
226 return safe_str
227
228
229 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
230 """
231 Custom engine_from_config functions that makes sure we use NullPool for
232 file based sqlite databases. This prevents errors on sqlite. This only
233 applies to sqlalchemy versions < 0.7.0
234
235 """
236 import sqlalchemy
237 from sqlalchemy import engine_from_config as efc
238 import logging
239
240 if int(sqlalchemy.__version__.split('.')[1]) < 7:
241
242 # This solution should work for sqlalchemy < 0.7.0, and should use
243 # proxy=TimerProxy() for execution time profiling
244
245 from sqlalchemy.pool import NullPool
246 url = configuration[prefix + 'url']
247
248 if url.startswith('sqlite'):
249 kwargs.update({'poolclass': NullPool})
250 return efc(configuration, prefix, **kwargs)
251 else:
252 import time
253 from sqlalchemy import event
254 from sqlalchemy.engine import Engine
255
256 log = logging.getLogger('sqlalchemy.engine')
257 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
258 engine = efc(configuration, prefix, **kwargs)
259
260 def color_sql(sql):
261 COLOR_SEQ = "\033[1;%dm"
262 COLOR_SQL = YELLOW
263 normal = '\x1b[0m'
264 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
265
266 if configuration['debug']:
267 #attach events only for debug configuration
268
269 def before_cursor_execute(conn, cursor, statement,
270 parameters, context, executemany):
271 context._query_start_time = time.time()
272 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
273
274
275 def after_cursor_execute(conn, cursor, statement,
276 parameters, context, executemany):
277 total = time.time() - context._query_start_time
278 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
279
280 event.listen(engine, "before_cursor_execute",
281 before_cursor_execute)
282 event.listen(engine, "after_cursor_execute",
283 after_cursor_execute)
284
285 return engine
286
287
288 def age(curdate):
289 """
290 turns a datetime into an age string.
291
292 :param curdate: datetime object
293 :rtype: unicode
294 :returns: unicode words describing age
295 """
296
297 from datetime import datetime
298 from webhelpers.date import time_ago_in_words
299
300 _ = lambda s: s
301
302 if not curdate:
303 return ''
304
305 agescales = [(_(u"year"), 3600 * 24 * 365),
306 (_(u"month"), 3600 * 24 * 30),
307 (_(u"day"), 3600 * 24),
308 (_(u"hour"), 3600),
309 (_(u"minute"), 60),
310 (_(u"second"), 1), ]
311
312 age = datetime.now() - curdate
313 age_seconds = (age.days * agescales[2][1]) + age.seconds
314 pos = 1
315 for scale in agescales:
316 if scale[1] <= age_seconds:
317 if pos == 6:
318 pos = 5
319 return '%s %s' % (time_ago_in_words(curdate,
320 agescales[pos][0]), _('ago'))
321 pos += 1
322
323 return _(u'just now')
324
325
326 def uri_filter(uri):
327 """
328 Removes user:password from given url string
329
330 :param uri:
331 :rtype: unicode
332 :returns: filtered list of strings
333 """
334 if not uri:
335 return ''
336
337 proto = ''
338
339 for pat in ('https://', 'http://'):
340 if uri.startswith(pat):
341 uri = uri[len(pat):]
342 proto = pat
343 break
344
345 # remove passwords and username
346 uri = uri[uri.find('@') + 1:]
347
348 # get the port
349 cred_pos = uri.find(':')
350 if cred_pos == -1:
351 host, port = uri, None
352 else:
353 host, port = uri[:cred_pos], uri[cred_pos + 1:]
354
355 return filter(None, [proto, host, port])
356
357
358 def credentials_filter(uri):
359 """
360 Returns a url with removed credentials
361
362 :param uri:
363 """
364
365 uri = uri_filter(uri)
366 #check if we have port
367 if len(uri) > 2 and uri[2]:
368 uri[2] = ':' + uri[2]
369
370 return ''.join(uri)
371
372
373 def get_changeset_safe(repo, rev):
374 """
375 Safe version of get_changeset if this changeset doesn't exists for a
376 repo it returns a Dummy one instead
377
378 :param repo:
379 :param rev:
380 """
381 from rhodecode.lib.vcs.backends.base import BaseRepository
382 from rhodecode.lib.vcs.exceptions import RepositoryError
383 if not isinstance(repo, BaseRepository):
384 raise Exception('You must pass an Repository '
385 'object as first argument got %s', type(repo))
386
387 try:
388 cs = repo.get_changeset(rev)
389 except RepositoryError:
390 from rhodecode.lib.utils import EmptyChangeset
391 cs = EmptyChangeset(requested_revision=rev)
392 return cs
393
394
395 def extract_mentioned_users(s):
396 """
397 Returns unique usernames from given string s that have @mention
398
399 :param s: string to get mentions
400 """
401 usrs = {}
402 for username in re.findall(r'(?:^@|\s@)(\w+)', s):
403 usrs[username] = username
404
405 return sorted(usrs.keys())
@@ -2,40 +2,45 b''
2 2
3 3 import os
4 4 import logging
5 import rhodecode
5 6
6 7 from mako.lookup import TemplateLookup
7 8 from pylons.configuration import PylonsConfig
8 9 from pylons.error import handle_mako_error
9 10
10 import rhodecode
11 # don't remove this import it does magic for celery
12 from rhodecode.lib import celerypylons
13
11 14 import rhodecode.lib.app_globals as app_globals
12 import rhodecode.lib.helpers
13 15
14 16 from rhodecode.config.routing import make_map
15 # don't remove this import it does magic for celery
16 from rhodecode.lib import celerypylons, str2bool
17 from rhodecode.lib import engine_from_config
17
18 from rhodecode.lib import helpers
18 19 from rhodecode.lib.auth import set_available_permissions
19 from rhodecode.lib.utils import repo2db_mapper, make_ui, set_rhodecode_config
20 from rhodecode.lib.utils import repo2db_mapper, make_ui, set_rhodecode_config,\
21 load_rcextensions
22 from rhodecode.lib.utils2 import engine_from_config, str2bool
20 23 from rhodecode.model import init_model
21 24 from rhodecode.model.scm import ScmModel
22 from rhodecode.lib.vcs.utils.fakemod import create_module
23 25
24 26 log = logging.getLogger(__name__)
25 27
26 28
27 29 def load_environment(global_conf, app_conf, initial=False):
28 """Configure the Pylons environment via the ``pylons.config``
30 """
31 Configure the Pylons environment via the ``pylons.config``
29 32 object
30 33 """
31 34 config = PylonsConfig()
32 35
33 36 # Pylons paths
34 37 root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
35 paths = dict(root=root,
36 controllers=os.path.join(root, 'controllers'),
37 static_files=os.path.join(root, 'public'),
38 templates=[os.path.join(root, 'templates')])
38 paths = dict(
39 root=root,
40 controllers=os.path.join(root, 'controllers'),
41 static_files=os.path.join(root, 'public'),
42 templates=[os.path.join(root, 'templates')]
43 )
39 44
40 45 # Initialize config with the basic options
41 46 config.init_app(global_conf, app_conf, package='rhodecode', paths=paths)
@@ -45,14 +50,11 b' def load_environment(global_conf, app_co'
45 50
46 51 config['routes.map'] = make_map(config)
47 52 config['pylons.app_globals'] = app_globals.Globals(config)
48 config['pylons.h'] = rhodecode.lib.helpers
53 config['pylons.h'] = helpers
49 54 rhodecode.CONFIG = config
50 55
51 path = os.path.join(config['here'], 'rcextensions', '__init__.py')
52 if os.path.isfile(path):
53 rcext = create_module('rc', path)
54 rhodecode.EXTENSIONS = rcext
55 log.debug('Found rcextensions now loading %s...' % rcext)
56 load_rcextensions(root_path=config['here'])
57
56 58 # Setup cache object as early as possible
57 59 import pylons
58 60 pylons.cache._push_object(config['pylons.app_globals'].cache)
@@ -77,5 +77,3 b' class MakeRcExt(BasePasterCommand):'
77 77
78 78 def update_parser(self):
79 79 pass
80
81
@@ -32,8 +32,9 b' from pylons import request, session, tmp'
32 32 from pylons.controllers.util import abort, redirect
33 33 from pylons.i18n.translation import _
34 34
35 from rhodecode.lib import helpers as h
35 36 from rhodecode.lib.exceptions import UsersGroupsAssignedException
36 from rhodecode.lib import helpers as h, safe_unicode
37 from rhodecode.lib.utils2 import safe_unicode
37 38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 39 from rhodecode.lib.base import BaseController, render
39 40
@@ -31,7 +31,7 b' import binascii'
31 31 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
32 32 from rhodecode.lib.base import BaseRepoController, render
33 33 from rhodecode.lib.compat import OrderedDict
34 from rhodecode.lib import safe_unicode
34 from rhodecode.lib.utils2 import safe_unicode
35 35 log = logging.getLogger(__name__)
36 36
37 37
@@ -28,7 +28,7 b' import logging'
28 28 from pylons import url, response, tmpl_context as c
29 29 from pylons.i18n.translation import _
30 30
31 from rhodecode.lib import safe_unicode
31 from rhodecode.lib.utils2 import safe_unicode
32 32 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
33 33 from rhodecode.lib.base import BaseRepoController
34 34
@@ -32,24 +32,26 b' from pylons.i18n.translation import _'
32 32 from pylons.controllers.util import redirect
33 33 from pylons.decorators import jsonify
34 34
35 from rhodecode.lib.vcs.conf import settings
36 from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
37 EmptyRepositoryError, ImproperArchiveTypeError, VCSError, \
38 NodeAlreadyExistsError
39 from rhodecode.lib.vcs.nodes import FileNode
35 from rhodecode.lib import diffs
36 from rhodecode.lib import helpers as h
40 37
41 38 from rhodecode.lib.compat import OrderedDict
42 from rhodecode.lib import convert_line_endings, detect_mode, safe_str
39 from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str
43 40 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
44 41 from rhodecode.lib.base import BaseRepoController, render
45 42 from rhodecode.lib.utils import EmptyChangeset
46 from rhodecode.lib import diffs
47 import rhodecode.lib.helpers as h
43 from rhodecode.lib.vcs.conf import settings
44 from rhodecode.lib.vcs.exceptions import RepositoryError, \
45 ChangesetDoesNotExistError, EmptyRepositoryError, \
46 ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError
47 from rhodecode.lib.vcs.nodes import FileNode
48
48 49 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.scm import ScmModel
51
49 52 from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\
50 53 _context_url, get_line_ctx, get_ignore_ws
51 from rhodecode.lib.diffs import wrapped_diff
52 from rhodecode.model.scm import ScmModel
54
53 55
54 56 log = logging.getLogger(__name__)
55 57
@@ -447,7 +449,7 b' class FilesController(BaseRepoController'
447 449 ign_whitespace_lcl = get_ignore_ws(fid, request.GET)
448 450
449 451 lim = request.GET.get('fulldiff') or self.cut_off_limit
450 _, cs1, cs2, diff, st = wrapped_diff(filenode_old=node1,
452 _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1,
451 453 filenode_new=node2,
452 454 cut_off_limit=lim,
453 455 ignore_whitespace=ign_whitespace_lcl,
@@ -40,15 +40,15 b' from pylons.i18n.translation import _'
40 40
41 41 from beaker.cache import cache_region, region_invalidate
42 42
43 from rhodecode.config.conf import ALL_READMES, ALL_EXTS, LANGUAGES_EXTENSIONS_MAP
43 44 from rhodecode.model.db import Statistics, CacheInvalidation
44 from rhodecode.lib import ALL_READMES, ALL_EXTS, safe_unicode
45 from rhodecode.lib.utils2 import safe_unicode
45 46 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
46 47 from rhodecode.lib.base import BaseRepoController, render
47 48 from rhodecode.lib.utils import EmptyChangeset
48 49 from rhodecode.lib.markup_renderer import MarkupRenderer
49 50 from rhodecode.lib.celerylib import run_task
50 from rhodecode.lib.celerylib.tasks import get_commits_stats, \
51 LANGUAGES_EXTENSIONS_MAP
51 from rhodecode.lib.celerylib.tasks import get_commits_stats
52 52 from rhodecode.lib.helpers import RepoPage
53 53 from rhodecode.lib.compat import json, OrderedDict
54 54
@@ -1,444 +1,4 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.lib.__init__
4 ~~~~~~~~~~~~~~~~~~~~~~~
5
6 Some simple helper functions
7
8 :created_on: Jan 5, 2011
9 :author: marcink
10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
26 1 import os
27 import re
28 from rhodecode import EXTENSIONS
29 from rhodecode.lib.vcs.utils.lazy import LazyProperty
30
31
32 def __get_lem():
33 from pygments import lexers
34 from string import lower
35 from collections import defaultdict
36
37 d = defaultdict(lambda: [])
38
39 def __clean(s):
40 s = s.lstrip('*')
41 s = s.lstrip('.')
42
43 if s.find('[') != -1:
44 exts = []
45 start, stop = s.find('['), s.find(']')
46
47 for suffix in s[start + 1:stop]:
48 exts.append(s[:s.find('[')] + suffix)
49 return map(lower, exts)
50 else:
51 return map(lower, [s])
52
53 for lx, t in sorted(lexers.LEXERS.items()):
54 m = map(__clean, t[-2])
55 if m:
56 m = reduce(lambda x, y: x + y, m)
57 for ext in m:
58 desc = lx.replace('Lexer', '')
59 d[ext].append(desc)
60
61 return dict(d)
62
63 # language map is also used by whoosh indexer, which for those specified
64 # extensions will index it's content
65 LANGUAGES_EXTENSIONS_MAP = __get_lem()
66
67 # Additional mappings that are not present in the pygments lexers
68 LANGUAGES_EXTENSIONS_MAP.update(getattr(EXTENSIONS, 'EXTRA_MAPPINGS', {}))
69
70 #==============================================================================
71 # WHOOSH INDEX EXTENSIONS
72 #==============================================================================
73 # EXTENSIONS WE WANT TO INDEX CONTENT OFF USING WHOOSH
74 INDEX_EXTENSIONS = LANGUAGES_EXTENSIONS_MAP.keys()
75
76 #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
77
78 if getattr(EXTENSIONS, 'INDEX_EXTENSIONS', []) != []:
79 INDEX_EXTENSIONS = getattr(EXTENSIONS, 'INDEX_EXTENSIONS', [])
80
81 #ADDITIONAL MAPPINGS
82 INDEX_EXTENSIONS.extend(getattr(EXTENSIONS, 'EXTRA_INDEX_EXTENSIONS', []))
83
84 # list of readme files to search in file tree and display in summary
85 # attached weights defines the search order lower is first
86 ALL_READMES = [
87 ('readme', 0), ('README', 0), ('Readme', 0),
88 ('doc/readme', 1), ('doc/README', 1), ('doc/Readme', 1),
89 ('Docs/readme', 2), ('Docs/README', 2), ('Docs/Readme', 2),
90 ('DOCS/readme', 2), ('DOCS/README', 2), ('DOCS/Readme', 2),
91 ('docs/readme', 2), ('docs/README', 2), ('docs/Readme', 2),
92 ]
93
94 # extension together with weights to search lower is first
95 RST_EXTS = [
96 ('', 0), ('.rst', 1), ('.rest', 1),
97 ('.RST', 2), ('.REST', 2),
98 ('.txt', 3), ('.TXT', 3)
99 ]
100
101 MARKDOWN_EXTS = [
102 ('.md', 1), ('.MD', 1),
103 ('.mkdn', 2), ('.MKDN', 2),
104 ('.mdown', 3), ('.MDOWN', 3),
105 ('.markdown', 4), ('.MARKDOWN', 4)
106 ]
107
108 PLAIN_EXTS = [('.text', 2), ('.TEXT', 2)]
109
110 ALL_EXTS = MARKDOWN_EXTS + RST_EXTS + PLAIN_EXTS
111
112
113 def str2bool(_str):
114 """
115 returs True/False value from given string, it tries to translate the
116 string into boolean
117
118 :param _str: string value to translate into boolean
119 :rtype: boolean
120 :returns: boolean from given string
121 """
122 if _str is None:
123 return False
124 if _str in (True, False):
125 return _str
126 _str = str(_str).strip().lower()
127 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
128
129
130 def convert_line_endings(line, mode):
131 """
132 Converts a given line "line end" accordingly to given mode
133
134 Available modes are::
135 0 - Unix
136 1 - Mac
137 2 - DOS
138
139 :param line: given line to convert
140 :param mode: mode to convert to
141 :rtype: str
142 :return: converted line according to mode
143 """
144 from string import replace
145
146 if mode == 0:
147 line = replace(line, '\r\n', '\n')
148 line = replace(line, '\r', '\n')
149 elif mode == 1:
150 line = replace(line, '\r\n', '\r')
151 line = replace(line, '\n', '\r')
152 elif mode == 2:
153 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
154 return line
155
156
157 def detect_mode(line, default):
158 """
159 Detects line break for given line, if line break couldn't be found
160 given default value is returned
161
162 :param line: str line
163 :param default: default
164 :rtype: int
165 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
166 """
167 if line.endswith('\r\n'):
168 return 2
169 elif line.endswith('\n'):
170 return 0
171 elif line.endswith('\r'):
172 return 1
173 else:
174 return default
175
176
177 def generate_api_key(username, salt=None):
178 """
179 Generates unique API key for given username, if salt is not given
180 it'll be generated from some random string
181
182 :param username: username as string
183 :param salt: salt to hash generate KEY
184 :rtype: str
185 :returns: sha1 hash from username+salt
186 """
187 from tempfile import _RandomNameSequence
188 import hashlib
189
190 if salt is None:
191 salt = _RandomNameSequence().next()
192
193 return hashlib.sha1(username + salt).hexdigest()
194
195
196 def safe_unicode(str_, from_encoding=None):
197 """
198 safe unicode function. Does few trick to turn str_ into unicode
199
200 In case of UnicodeDecode error we try to return it with encoding detected
201 by chardet library if it fails fallback to unicode with errors replaced
202
203 :param str_: string to decode
204 :rtype: unicode
205 :returns: unicode object
206 """
207 if isinstance(str_, unicode):
208 return str_
209
210 if not from_encoding:
211 import rhodecode
212 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
213 from_encoding = DEFAULT_ENCODING
214
215 try:
216 return unicode(str_)
217 except UnicodeDecodeError:
218 pass
219
220 try:
221 return unicode(str_, from_encoding)
222 except UnicodeDecodeError:
223 pass
224
225 try:
226 import chardet
227 encoding = chardet.detect(str_)['encoding']
228 if encoding is None:
229 raise Exception()
230 return str_.decode(encoding)
231 except (ImportError, UnicodeDecodeError, Exception):
232 return unicode(str_, from_encoding, 'replace')
233
234
235 def safe_str(unicode_, to_encoding=None):
236 """
237 safe str function. Does few trick to turn unicode_ into string
238
239 In case of UnicodeEncodeError we try to return it with encoding detected
240 by chardet library if it fails fallback to string with errors replaced
241
242 :param unicode_: unicode to encode
243 :rtype: str
244 :returns: str object
245 """
246
247 # if it's not basestr cast to str
248 if not isinstance(unicode_, basestring):
249 return str(unicode_)
250
251 if isinstance(unicode_, str):
252 return unicode_
253
254 if not to_encoding:
255 import rhodecode
256 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
257 to_encoding = DEFAULT_ENCODING
258
259 try:
260 return unicode_.encode(to_encoding)
261 except UnicodeEncodeError:
262 pass
263
264 try:
265 import chardet
266 encoding = chardet.detect(unicode_)['encoding']
267 print encoding
268 if encoding is None:
269 raise UnicodeEncodeError()
270
271 return unicode_.encode(encoding)
272 except (ImportError, UnicodeEncodeError):
273 return unicode_.encode(to_encoding, 'replace')
274
275 return safe_str
276
277
278 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
279 """
280 Custom engine_from_config functions that makes sure we use NullPool for
281 file based sqlite databases. This prevents errors on sqlite. This only
282 applies to sqlalchemy versions < 0.7.0
283
284 """
285 import sqlalchemy
286 from sqlalchemy import engine_from_config as efc
287 import logging
288
289 if int(sqlalchemy.__version__.split('.')[1]) < 7:
290
291 # This solution should work for sqlalchemy < 0.7.0, and should use
292 # proxy=TimerProxy() for execution time profiling
293
294 from sqlalchemy.pool import NullPool
295 url = configuration[prefix + 'url']
296
297 if url.startswith('sqlite'):
298 kwargs.update({'poolclass': NullPool})
299 return efc(configuration, prefix, **kwargs)
300 else:
301 import time
302 from sqlalchemy import event
303 from sqlalchemy.engine import Engine
304
305 log = logging.getLogger('sqlalchemy.engine')
306 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
307 engine = efc(configuration, prefix, **kwargs)
308
309 def color_sql(sql):
310 COLOR_SEQ = "\033[1;%dm"
311 COLOR_SQL = YELLOW
312 normal = '\x1b[0m'
313 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
314
315 if configuration['debug']:
316 #attach events only for debug configuration
317
318 def before_cursor_execute(conn, cursor, statement,
319 parameters, context, executemany):
320 context._query_start_time = time.time()
321 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
322
323
324 def after_cursor_execute(conn, cursor, statement,
325 parameters, context, executemany):
326 total = time.time() - context._query_start_time
327 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
328
329 event.listen(engine, "before_cursor_execute",
330 before_cursor_execute)
331 event.listen(engine, "after_cursor_execute",
332 after_cursor_execute)
333
334 return engine
335
336
337 def age(curdate):
338 """
339 turns a datetime into an age string.
340
341 :param curdate: datetime object
342 :rtype: unicode
343 :returns: unicode words describing age
344 """
345
346 from datetime import datetime
347 from webhelpers.date import time_ago_in_words
348
349 _ = lambda s: s
350
351 if not curdate:
352 return ''
353
354 agescales = [(_(u"year"), 3600 * 24 * 365),
355 (_(u"month"), 3600 * 24 * 30),
356 (_(u"day"), 3600 * 24),
357 (_(u"hour"), 3600),
358 (_(u"minute"), 60),
359 (_(u"second"), 1), ]
360
361 age = datetime.now() - curdate
362 age_seconds = (age.days * agescales[2][1]) + age.seconds
363 pos = 1
364 for scale in agescales:
365 if scale[1] <= age_seconds:
366 if pos == 6:
367 pos = 5
368 return '%s %s' % (time_ago_in_words(curdate,
369 agescales[pos][0]), _('ago'))
370 pos += 1
371
372 return _(u'just now')
373
374
375 def uri_filter(uri):
376 """
377 Removes user:password from given url string
378
379 :param uri:
380 :rtype: unicode
381 :returns: filtered list of strings
382 """
383 if not uri:
384 return ''
385
386 proto = ''
387
388 for pat in ('https://', 'http://'):
389 if uri.startswith(pat):
390 uri = uri[len(pat):]
391 proto = pat
392 break
393
394 # remove passwords and username
395 uri = uri[uri.find('@') + 1:]
396
397 # get the port
398 cred_pos = uri.find(':')
399 if cred_pos == -1:
400 host, port = uri, None
401 else:
402 host, port = uri[:cred_pos], uri[cred_pos + 1:]
403
404 return filter(None, [proto, host, port])
405
406
407 def credentials_filter(uri):
408 """
409 Returns a url with removed credentials
410
411 :param uri:
412 """
413
414 uri = uri_filter(uri)
415 #check if we have port
416 if len(uri) > 2 and uri[2]:
417 uri[2] = ':' + uri[2]
418
419 return ''.join(uri)
420
421
422 def get_changeset_safe(repo, rev):
423 """
424 Safe version of get_changeset if this changeset doesn't exists for a
425 repo it returns a Dummy one instead
426
427 :param repo:
428 :param rev:
429 """
430 from rhodecode.lib.vcs.backends.base import BaseRepository
431 from rhodecode.lib.vcs.exceptions import RepositoryError
432 if not isinstance(repo, BaseRepository):
433 raise Exception('You must pass an Repository '
434 'object as first argument got %s', type(repo))
435
436 try:
437 cs = repo.get_changeset(rev)
438 except RepositoryError:
439 from rhodecode.lib.utils import EmptyChangeset
440 cs = EmptyChangeset(requested_revision=rev)
441 return cs
442 2
443 3
444 4 def get_current_revision(quiet=False):
@@ -462,16 +22,3 b' def get_current_revision(quiet=False):'
462 22 print ("Cannot retrieve rhodecode's revision. Original error "
463 23 "was: %s" % err)
464 24 return None
465
466
467 def extract_mentioned_users(s):
468 """
469 Returns unique usernames from given string s that have @mention
470
471 :param s: string to get mentions
472 """
473 usrs = {}
474 for username in re.findall(r'(?:^@|\s@)(\w+)', s):
475 usrs[username] = username
476
477 return sorted(usrs.keys())
@@ -43,7 +43,7 b' if __platform__ in PLATFORM_WIN:'
43 43 if __platform__ in PLATFORM_OTHERS:
44 44 import bcrypt
45 45
46 from rhodecode.lib import str2bool, safe_unicode
46 from rhodecode.lib.utils2 import str2bool, safe_unicode
47 47 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
48 48 from rhodecode.lib.utils import get_repo_slug, get_repos_group_slug
49 49 from rhodecode.lib.auth_ldap import AuthLdap
@@ -795,7 +795,7 b' class HasPermissionAnyMiddleware(object)'
795 795 try:
796 796 self.user_perms = set([usr.permissions['repositories'][repo_name]])
797 797 except Exception:
798 log.error('Exception while accessing permissions %s' %
798 log.error('Exception while accessing permissions %s' %
799 799 traceback.format_exc())
800 800 self.user_perms = set()
801 801 self.granted_for = ''
@@ -15,7 +15,7 b' from pylons.templating import render_mak'
15 15
16 16 from rhodecode import __version__, BACKENDS
17 17
18 from rhodecode.lib import str2bool, safe_unicode
18 from rhodecode.lib.utils2 import str2bool, safe_unicode
19 19 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
20 20 HasPermissionAnyMiddleware, CookieStoreWrapper
21 21 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
@@ -24,7 +24,7 b' from beaker.exceptions import BeakerExce'
24 24 from sqlalchemy.orm.interfaces import MapperOption
25 25 from sqlalchemy.orm.query import Query
26 26 from sqlalchemy.sql import visitors
27 from rhodecode.lib import safe_str
27 from rhodecode.lib.utils2 import safe_str
28 28
29 29
30 30 class CachingQuery(Query):
@@ -36,7 +36,7 b' from decorator import decorator'
36 36
37 37 from rhodecode.lib.vcs.utils.lazy import LazyProperty
38 38 from rhodecode import CELERY_ON
39 from rhodecode.lib import str2bool, safe_str
39 from rhodecode.lib.utils2 import str2bool, safe_str
40 40 from rhodecode.lib.pidlock import DaemonLock, LockHeld
41 41 from rhodecode.model import init_model
42 42 from rhodecode.model import meta
@@ -40,7 +40,7 b' from pylons.i18n.translation import _'
40 40 from rhodecode.lib.vcs import get_backend
41 41
42 42 from rhodecode import CELERY_ON
43 from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, safe_str
43 from rhodecode.lib.utils2 import safe_str
44 44 from rhodecode.lib.celerylib import run_task, locked_task, dbsession, \
45 45 str2bool, __get_lockkey, LockHeld, DaemonLock, get_session
46 46 from rhodecode.lib.helpers import person
@@ -147,6 +147,7 b' def get_commits_stats(repo_name, ts_min_'
147 147 last_rev, last_rev + parse_limit)
148 148 )
149 149 for cs in repo[last_rev:last_rev + parse_limit]:
150 log.debug('parsing %s' % cs)
150 151 last_cs = cs # remember last parsed changeset
151 152 k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
152 153 cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
@@ -233,10 +234,10 b' def get_commits_stats(repo_name, ts_min_'
233 234 lock.release()
234 235 return False
235 236
236 #final release
237 # final release
237 238 lock.release()
238 239
239 #execute another task if celery is enabled
240 # execute another task if celery is enabled
240 241 if len(repo.revisions) > 1 and CELERY_ON:
241 242 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
242 243 return True
@@ -395,6 +396,7 b' def create_repo_fork(form_data, cur_user'
395 396 DBS.commit()
396 397
397 398 def __get_codes_stats(repo_name):
399 from rhodecode.config.conf import LANGUAGES_EXTENSIONS_MAP
398 400 repo = Repository.get_by_repo_name(repo_name).scm_instance
399 401
400 402 tip = repo.get_changeset()
@@ -1,9 +1,9 b''
1 1 import rhodecode
2 from rhodecode.lib.utils import BasePasterCommand, Command
2 from rhodecode.lib.utils import BasePasterCommand, Command, load_rcextensions
3 3 from celery.app import app_or_default
4 4 from celery.bin import camqadm, celerybeat, celeryd, celeryev
5 5
6 from rhodecode.lib import str2bool
6 from rhodecode.lib.utils2 import str2bool
7 7
8 8 __all__ = ['CeleryDaemonCommand', 'CeleryBeatCommand',
9 9 'CAMQPAdminCommand', 'CeleryEventCommand']
@@ -39,9 +39,11 b' class CeleryCommand(BasePasterCommand):'
39 39 raise Exception('Please enable celery_on in .ini config '
40 40 'file before running celeryd')
41 41 rhodecode.CELERY_ON = CELERY_ON
42 load_rcextensions(config['here'])
42 43 cmd = self.celery_command(app_or_default())
43 44 return cmd.run(**vars(self.options))
44 45
46
45 47 class CeleryDaemonCommand(CeleryCommand):
46 48 """Start the celery worker
47 49
@@ -82,6 +84,7 b' class CAMQPAdminCommand(CeleryCommand):'
82 84 parser = Command.standard_parser(quiet=True)
83 85 celery_command = camqadm.AMQPAdminCommand
84 86
87
85 88 class CeleryEventCommand(CeleryCommand):
86 89 """Celery event command.
87 90
@@ -71,9 +71,6 b' class InvalidScriptError(ScriptError):'
71 71 """Invalid script error."""
72 72
73 73
74 class InvalidVersionError(Error):
75 """Invalid version error."""
76
77 74 # migrate.changeset
78 75
79 76 class NotSupportedError(Error):
@@ -39,7 +39,7 b' from rhodecode.lib.vcs.utils.helpers imp'
39 39 from rhodecode.lib.vcs.exceptions import VCSError
40 40 from rhodecode.lib.vcs.utils.lazy import LazyProperty
41 41
42 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
42 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
43 43 generate_api_key, safe_unicode
44 44 from rhodecode.lib.exceptions import UsersGroupsAssignedException
45 45 from rhodecode.lib.compat import json
@@ -717,7 +717,7 b' class Repository(Base, BaseModel):'
717 717 return repo
718 718
719 719
720 class RepoGroup(Base, BaseModel):
720 class Group(Base, BaseModel):
721 721 __tablename__ = 'groups'
722 722 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
723 723 CheckConstraint('group_id != group_parent_id'), {'extend_existing':True},)
@@ -728,8 +728,7 b' class RepoGroup(Base, BaseModel):'
728 728 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
729 729 group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
730 730
731 parent_group = relationship('RepoGroup', remote_side=group_id)
732
731 parent_group = relationship('Group', remote_side=group_id)
733 732
734 733 def __init__(self, group_name='', parent_group=None):
735 734 self.group_name = group_name
@@ -39,7 +39,8 b' from webhelpers.html.tags import _set_in'
39 39
40 40 from rhodecode.lib.annotate import annotate_highlight
41 41 from rhodecode.lib.utils import repo_name_slug
42 from rhodecode.lib import str2bool, safe_unicode, safe_str, get_changeset_safe
42 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
43 get_changeset_safe
43 44 from rhodecode.lib.markup_renderer import MarkupRenderer
44 45
45 46 log = logging.getLogger(__name__)
@@ -319,7 +320,7 b' flash = _Flash()'
319 320 # SCM FILTERS available via h.
320 321 #==============================================================================
321 322 from rhodecode.lib.vcs.utils import author_name, author_email
322 from rhodecode.lib import credentials_filter, age as _age
323 from rhodecode.lib.utils2 import credentials_filter, age as _age
323 324 from rhodecode.model.db import User
324 325
325 326 age = lambda x: _age(x)
@@ -139,7 +139,7 b' def log_push_action(ui, repo, **kwargs):'
139 139 def log_create_repository(repository_dict, created_by, **kwargs):
140 140 """
141 141 Post create repository Hook. This is a dummy function for admins to re-use
142 if needed. It's taken from rhodecode-extensions module and executed
142 if needed. It's taken from rhodecode-extensions module and executed
143 143 if present
144 144
145 145 :param repository: dict dump of repository object
@@ -47,9 +47,9 b' from rhodecode.model import init_model'
47 47 from rhodecode.model.scm import ScmModel
48 48 from rhodecode.model.repo import RepoModel
49 49 from rhodecode.config.environment import load_environment
50 from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, INDEX_EXTENSIONS, \
51 LazyProperty
52 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
50 from rhodecode.lib.utils2 import LazyProperty
51 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache,\
52 load_rcextensions
53 53
54 54 # CUSTOM ANALYZER wordsplit + lowercase filter
55 55 ANALYZER = RegexTokenizer(expression=r"\w+") | LowercaseFilter()
@@ -88,13 +88,12 b' class MakeIndex(BasePasterCommand):'
88 88 add_cache(config)
89 89 engine = engine_from_config(config, 'sqlalchemy.db1.')
90 90 init_model(engine)
91
92 91 index_location = config['index_dir']
93 92 repo_location = self.options.repo_location \
94 93 if self.options.repo_location else RepoModel().repos_path
95 94 repo_list = map(strip, self.options.repo_list.split(',')) \
96 95 if self.options.repo_list else None
97
96 load_rcextensions(config['here'])
98 97 #======================================================================
99 98 # WHOOSH DAEMON
100 99 #======================================================================
@@ -104,7 +103,7 b' class MakeIndex(BasePasterCommand):'
104 103 l = DaemonLock(file_=jn(dn(dn(index_location)), 'make_index.lock'))
105 104 WhooshIndexingDaemon(index_location=index_location,
106 105 repo_location=repo_location,
107 repo_list=repo_list)\
106 repo_list=repo_list,)\
108 107 .run(full_index=self.options.full_index)
109 108 l.release()
110 109 except LockHeld:
@@ -38,10 +38,10 b' from os.path import join as jn'
38 38 project_path = dn(dn(dn(dn(os.path.realpath(__file__)))))
39 39 sys.path.append(project_path)
40 40
41
41 from rhodecode.config.conf import INDEX_EXTENSIONS
42 42 from rhodecode.model.scm import ScmModel
43 from rhodecode.lib import safe_unicode
44 from rhodecode.lib.indexers import INDEX_EXTENSIONS, SCHEMA, IDX_NAME
43 from rhodecode.lib.utils2 import safe_unicode
44 from rhodecode.lib.indexers import SCHEMA, IDX_NAME
45 45
46 46 from rhodecode.lib.vcs.exceptions import ChangesetError, RepositoryError, \
47 47 NodeDoesNotExistError
@@ -117,10 +117,9 b' class WhooshIndexingDaemon(object):'
117 117 """
118 118
119 119 node = self.get_node(repo, path)
120
120 indexed = indexed_w_content = 0
121 121 # we just index the content of chosen files, and skip binary files
122 122 if node.extension in INDEX_EXTENSIONS and not node.is_binary:
123
124 123 u_content = node.content
125 124 if not isinstance(u_content, unicode):
126 125 log.warning(' >> %s Could not get this content as unicode '
@@ -128,11 +127,13 b' class WhooshIndexingDaemon(object):'
128 127 u_content = u''
129 128 else:
130 129 log.debug(' >> %s [WITH CONTENT]' % path)
130 indexed_w_content += 1
131 131
132 132 else:
133 133 log.debug(' >> %s' % path)
134 134 # just index file name without it's content
135 135 u_content = u''
136 indexed += 1
136 137
137 138 writer.add_document(
138 139 owner=unicode(repo.contact),
@@ -142,6 +143,7 b' class WhooshIndexingDaemon(object):'
142 143 modtime=self.get_node_mtime(node),
143 144 extension=node.extension
144 145 )
146 return indexed, indexed_w_content
145 147
146 148 def build_index(self):
147 149 if os.path.exists(self.index_location):
@@ -153,19 +155,25 b' class WhooshIndexingDaemon(object):'
153 155
154 156 idx = create_in(self.index_location, SCHEMA, indexname=IDX_NAME)
155 157 writer = idx.writer()
156
158 log.debug('BUILDIN INDEX FOR EXTENSIONS %s' % INDEX_EXTENSIONS)
157 159 for repo_name, repo in self.repo_paths.items():
158 160 log.debug('building index @ %s' % repo.path)
159
161 i_cnt = iwc_cnt = 0
160 162 for idx_path in self.get_paths(repo):
161 self.add_doc(writer, idx_path, repo, repo_name)
163 i, iwc = self.add_doc(writer, idx_path, repo, repo_name)
164 i_cnt += i
165 iwc_cnt += iwc
166 log.debug('added %s files %s with content for repo %s' % (
167 i_cnt + iwc_cnt, iwc_cnt, repo.path)
168 )
162 169
163 170 log.debug('>> COMMITING CHANGES <<')
164 171 writer.commit(merge=True)
165 172 log.debug('>>> FINISHED BUILDING INDEX <<<')
166 173
167 174 def update_index(self):
168 log.debug('STARTING INCREMENTAL INDEXING UPDATE')
175 log.debug('STARTING INCREMENTAL INDEXING UPDATE FOR EXTENSIONS %s' %
176 INDEX_EXTENSIONS)
169 177
170 178 idx = open_dir(self.index_location, indexname=self.indexname)
171 179 # The set of all paths in the index
@@ -204,14 +212,19 b' class WhooshIndexingDaemon(object):'
204 212 # Loop over the files in the filesystem
205 213 # Assume we have a function that gathers the filenames of the
206 214 # documents to be indexed
215 ri_cnt = riwc_cnt = 0
207 216 for repo_name, repo in self.repo_paths.items():
208 217 for path in self.get_paths(repo):
209 218 if path in to_index or path not in indexed_paths:
210 219 # This is either a file that's changed, or a new file
211 220 # that wasn't indexed before. So index it!
212 self.add_doc(writer, path, repo, repo_name)
221 i, iwc = self.add_doc(writer, path, repo, repo_name)
213 222 log.debug('re indexing %s' % path)
214
223 ri_cnt += i
224 riwc_cnt += iwc
225 log.debug('added %s files %s with content for repo %s' % (
226 ri_cnt + riwc_cnt, riwc_cnt, repo.path)
227 )
215 228 log.debug('>> COMMITING CHANGES <<')
216 229 writer.commit(merge=True)
217 230 log.debug('>>> FINISHED REBUILDING INDEX <<<')
@@ -27,7 +27,7 b''
27 27 import re
28 28 import logging
29 29
30 from rhodecode.lib import safe_unicode
30 from rhodecode.lib.utils2 import safe_unicode
31 31
32 32 log = logging.getLogger(__name__)
33 33
@@ -23,7 +23,7 b''
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 from rhodecode.lib import str2bool
26 from rhodecode.lib.utils2 import str2bool
27 27
28 28
29 29 class HttpsFixup(object):
@@ -69,7 +69,7 b' from dulwich.web import HTTPGitApplicati'
69 69
70 70 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
71 71
72 from rhodecode.lib import safe_str
72 from rhodecode.lib.utils2 import safe_str
73 73 from rhodecode.lib.base import BaseVCSController
74 74 from rhodecode.lib.auth import get_container_username
75 75 from rhodecode.lib.utils import is_valid_repo
@@ -34,7 +34,7 b' from mercurial.hgweb import hgweb_mod'
34 34
35 35 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
36 36
37 from rhodecode.lib import safe_str
37 from rhodecode.lib.utils2 import safe_str
38 38 from rhodecode.lib.base import BaseVCSController
39 39 from rhodecode.lib.auth import get_container_username
40 40 from rhodecode.lib.utils import make_ui, is_valid_repo, ui_sections
@@ -54,7 +54,8 b' from rhodecode.model.db import Repositor'
54 54 UserLog, RepoGroup, RhodeCodeSetting, UserRepoGroupToPerm
55 55 from rhodecode.model.meta import Session
56 56 from rhodecode.model.repos_group import ReposGroupModel
57 from rhodecode.lib import safe_str, safe_unicode
57 from rhodecode.lib.utils2 import safe_str, safe_unicode
58 from rhodecode.lib.vcs.utils.fakemod import create_module
58 59
59 60 log = logging.getLogger(__name__)
60 61
@@ -62,7 +63,8 b" REMOVED_REPO_PAT = re.compile(r'rm__\\d{8"
62 63
63 64
64 65 def recursive_replace(str_, replace=' '):
65 """Recursive replace of given sign to just one instance
66 """
67 Recursive replace of given sign to just one instance
66 68
67 69 :param str_: given string
68 70 :param replace: char to find and replace multiple instances
@@ -80,7 +82,8 b" def recursive_replace(str_, replace=' ')"
80 82
81 83
82 84 def repo_name_slug(value):
83 """Return slug of name of repository
85 """
86 Return slug of name of repository
84 87 This function is called on each creation/modification
85 88 of repository to prevent bad names in repo
86 89 """
@@ -263,7 +266,8 b" ui_sections = ['alias', 'auth',"
263 266
264 267
265 268 def make_ui(read_from='file', path=None, checkpaths=True):
266 """A function that will read python rc files or database
269 """
270 A function that will read python rc files or database
267 271 and make an mercurial ui object from read options
268 272
269 273 :param path: path to mercurial config file
@@ -489,6 +493,30 b' def add_cache(settings):'
489 493 beaker.cache.cache_regions[region] = region_settings
490 494
491 495
496 def load_rcextensions(root_path):
497 import rhodecode
498 from rhodecode.config import conf
499
500 path = os.path.join(root_path, 'rcextensions', '__init__.py')
501 if os.path.isfile(path):
502 rcext = create_module('rc', path)
503 EXT = rhodecode.EXTENSIONS = rcext
504 log.debug('Found rcextensions now loading %s...' % rcext)
505
506 # Additional mappings that are not present in the pygments lexers
507 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
508
509 #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
510
511 if getattr(EXT, 'INDEX_EXTENSIONS', []) != []:
512 log.debug('settings custom INDEX_EXTENSIONS')
513 conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', [])
514
515 #ADDITIONAL MAPPINGS
516 log.debug('adding extra into INDEX_EXTENSIONS')
517 conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', []))
518
519
492 520 #==============================================================================
493 521 # TEST FUNCTIONS AND CREATORS
494 522 #==============================================================================
@@ -29,7 +29,7 b' import traceback'
29 29 from pylons.i18n.translation import _
30 30 from sqlalchemy.util.compat import defaultdict
31 31
32 from rhodecode.lib import extract_mentioned_users
32 from rhodecode.lib.utils2 import extract_mentioned_users
33 33 from rhodecode.lib import helpers as h
34 34 from rhodecode.model import BaseModel
35 35 from rhodecode.model.db import ChangesetComment, User, Repository, Notification
@@ -39,7 +39,8 b' from rhodecode.lib.vcs.utils.helpers imp'
39 39 from rhodecode.lib.vcs.exceptions import VCSError
40 40 from rhodecode.lib.vcs.utils.lazy import LazyProperty
41 41
42 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, safe_unicode
42 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
43 safe_unicode
43 44 from rhodecode.lib.compat import json
44 45 from rhodecode.lib.caching_query import FromCache
45 46
@@ -32,6 +32,7 b' import datetime'
32 32 from pylons.i18n.translation import _
33 33
34 34 import rhodecode
35 from rhodecode.config.conf import DATETIME_FORMAT
35 36 from rhodecode.lib import helpers as h
36 37 from rhodecode.model import BaseModel
37 38 from rhodecode.model.db import Notification, User, UserNotification
@@ -176,8 +177,6 b' class NotificationModel(BaseModel):'
176 177 notification.TYPE_REGISTRATION: _('registered in RhodeCode')
177 178 }
178 179
179 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
180
181 180 tmpl = "%(user)s %(action)s %(when)s"
182 181 if show_age:
183 182 when = h.age(notification.created_on)
@@ -30,8 +30,7 b' from datetime import datetime'
30 30
31 31 from rhodecode.lib.vcs.backends import get_backend
32 32
33 from rhodecode.lib import LazyProperty
34 from rhodecode.lib import safe_str, safe_unicode
33 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode
35 34 from rhodecode.lib.caching_query import FromCache
36 35 from rhodecode.lib.hooks import log_create_repository
37 36
@@ -28,7 +28,7 b' import logging'
28 28 import traceback
29 29 import shutil
30 30
31 from rhodecode.lib import LazyProperty
31 from rhodecode.lib.utils2 import LazyProperty
32 32
33 33 from rhodecode.model import BaseModel
34 34 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
@@ -35,7 +35,7 b' from rhodecode.lib.vcs.nodes import File'
35 35
36 36 from rhodecode import BACKENDS
37 37 from rhodecode.lib import helpers as h
38 from rhodecode.lib import safe_str
38 from rhodecode.lib.utils2 import safe_str
39 39 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
40 40 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
41 41 action_logger, EmptyChangeset, REMOVED_REPO_PAT
@@ -29,7 +29,7 b' import traceback'
29 29 from pylons import url
30 30 from pylons.i18n.translation import _
31 31
32 from rhodecode.lib import safe_unicode
32 from rhodecode.lib.utils2 import safe_unicode, generate_api_key
33 33 from rhodecode.lib.caching_query import FromCache
34 34
35 35 from rhodecode.model import BaseModel
@@ -40,7 +40,7 b' from rhodecode.lib.exceptions import Def'
40 40 UserOwnsReposException
41 41
42 42 from sqlalchemy.exc import DatabaseError
43 from rhodecode.lib import generate_api_key
43
44 44 from sqlalchemy.orm import joinedload
45 45
46 46 log = logging.getLogger(__name__)
@@ -3112,7 +3112,12 b' table.code-browser .browser-dir {'
3112 3112 top: 5px;
3113 3113 width: 16px;
3114 3114 }
3115
3115 div#legend_data{
3116 padding-left:10px;
3117 }
3118 div#legend_container table{
3119 border: none !important;
3120 }
3116 3121 div#legend_container table,div#legend_choices table {
3117 3122 width: auto !important;
3118 3123 }
@@ -1,10 +1,11 b''
1 1 # -*- coding: utf-8 -*-
2 2 from rhodecode.tests import *
3 3 from rhodecode.model.db import User, Notification
4 from rhodecode.lib import generate_api_key
4 from rhodecode.lib.utils2 import generate_api_key
5 5 from rhodecode.lib.auth import check_password
6 6 from rhodecode.model.meta import Session
7 7
8
8 9 class TestLoginController(TestController):
9 10
10 11 def tearDown(self):
@@ -65,22 +65,20 b' TEST_URLS += ['
65 65
66 66 class TestLibs(unittest.TestCase):
67 67
68
69 68 def test_uri_filter(self):
70 from rhodecode.lib import uri_filter
69 from rhodecode.lib.utils2 import uri_filter
71 70
72 71 for url in TEST_URLS:
73 72 self.assertEqual(uri_filter(url[0]), url[1])
74 73
75 74 def test_credentials_filter(self):
76 from rhodecode.lib import credentials_filter
75 from rhodecode.lib.utils2 import credentials_filter
77 76
78 77 for url in TEST_URLS:
79 78 self.assertEqual(credentials_filter(url[0]), url[2])
80 79
81
82 80 def test_str2bool(self):
83 from rhodecode.lib import str2bool
81 from rhodecode.lib.utils2 import str2bool
84 82 test_cases = [
85 83 ('t', True),
86 84 ('true', True),
@@ -103,9 +101,8 b' class TestLibs(unittest.TestCase):'
103 101 for case in test_cases:
104 102 self.assertEqual(str2bool(case[0]), case[1])
105 103
106
107 104 def test_mention_extractor(self):
108 from rhodecode.lib import extract_mentioned_users
105 from rhodecode.lib.utils2 import extract_mentioned_users
109 106 sample = ("@first hi there @marcink here's my email marcin@email.com "
110 107 "@lukaszb check it pls @ ttwelve @D[] @one@two@three "
111 108 "@MARCIN @maRCiN @2one_more22")
General Comments 0
You need to be logged in to leave comments. Login now