##// END OF EJS Templates
fix for issue #602, enforce str when setting mercurial UI object. When this is used together with mercurial internal translation system...
marcink -
r2989:190e2ff4 beta
parent child Browse files
Show More
@@ -1,712 +1,714
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.utils
4 4 ~~~~~~~~~~~~~~~~~~~
5 5
6 6 Utilities library for RhodeCode
7 7
8 8 :created_on: Apr 18, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
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 26 import os
27 27 import re
28 28 import logging
29 29 import datetime
30 30 import traceback
31 31 import paste
32 32 import beaker
33 33 import tarfile
34 34 import shutil
35 35 from os.path import abspath
36 36 from os.path import dirname as dn, join as jn
37 37
38 38 from paste.script.command import Command, BadCommand
39 39
40 40 from mercurial import ui, config
41 41
42 42 from webhelpers.text import collapse, remove_formatting, strip_tags
43 43
44 44 from rhodecode.lib.vcs import get_backend
45 45 from rhodecode.lib.vcs.backends.base import BaseChangeset
46 46 from rhodecode.lib.vcs.utils.lazy import LazyProperty
47 47 from rhodecode.lib.vcs.utils.helpers import get_scm
48 48 from rhodecode.lib.vcs.exceptions import VCSError
49 49
50 50 from rhodecode.lib.caching_query import FromCache
51 51
52 52 from rhodecode.model import meta
53 53 from rhodecode.model.db import Repository, User, RhodeCodeUi, \
54 54 UserLog, RepoGroup, RhodeCodeSetting, CacheInvalidation
55 55 from rhodecode.model.meta import Session
56 56 from rhodecode.model.repos_group import ReposGroupModel
57 57 from rhodecode.lib.utils2 import safe_str, safe_unicode
58 58 from rhodecode.lib.vcs.utils.fakemod import create_module
59 59
60 60 log = logging.getLogger(__name__)
61 61
62 62 REMOVED_REPO_PAT = re.compile(r'rm__\d{8}_\d{6}_\d{6}__.*')
63 63
64 64
65 65 def recursive_replace(str_, replace=' '):
66 66 """
67 67 Recursive replace of given sign to just one instance
68 68
69 69 :param str_: given string
70 70 :param replace: char to find and replace multiple instances
71 71
72 72 Examples::
73 73 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
74 74 'Mighty-Mighty-Bo-sstones'
75 75 """
76 76
77 77 if str_.find(replace * 2) == -1:
78 78 return str_
79 79 else:
80 80 str_ = str_.replace(replace * 2, replace)
81 81 return recursive_replace(str_, replace)
82 82
83 83
84 84 def repo_name_slug(value):
85 85 """
86 86 Return slug of name of repository
87 87 This function is called on each creation/modification
88 88 of repository to prevent bad names in repo
89 89 """
90 90
91 91 slug = remove_formatting(value)
92 92 slug = strip_tags(slug)
93 93
94 94 for c in """`?=[]\;'"<>,/~!@#$%^&*()+{}|: """:
95 95 slug = slug.replace(c, '-')
96 96 slug = recursive_replace(slug, '-')
97 97 slug = collapse(slug, '-')
98 98 return slug
99 99
100 100
101 101 def get_repo_slug(request):
102 102 _repo = request.environ['pylons.routes_dict'].get('repo_name')
103 103 if _repo:
104 104 _repo = _repo.rstrip('/')
105 105 return _repo
106 106
107 107
108 108 def get_repos_group_slug(request):
109 109 _group = request.environ['pylons.routes_dict'].get('group_name')
110 110 if _group:
111 111 _group = _group.rstrip('/')
112 112 return _group
113 113
114 114
115 115 def action_logger(user, action, repo, ipaddr='', sa=None, commit=False):
116 116 """
117 117 Action logger for various actions made by users
118 118
119 119 :param user: user that made this action, can be a unique username string or
120 120 object containing user_id attribute
121 121 :param action: action to log, should be on of predefined unique actions for
122 122 easy translations
123 123 :param repo: string name of repository or object containing repo_id,
124 124 that action was made on
125 125 :param ipaddr: optional ip address from what the action was made
126 126 :param sa: optional sqlalchemy session
127 127
128 128 """
129 129
130 130 if not sa:
131 131 sa = meta.Session()
132 132
133 133 try:
134 134 if hasattr(user, 'user_id'):
135 135 user_obj = user
136 136 elif isinstance(user, basestring):
137 137 user_obj = User.get_by_username(user)
138 138 else:
139 139 raise Exception('You have to provide a user object or a username')
140 140
141 141 if hasattr(repo, 'repo_id'):
142 142 repo_obj = Repository.get(repo.repo_id)
143 143 repo_name = repo_obj.repo_name
144 144 elif isinstance(repo, basestring):
145 145 repo_name = repo.lstrip('/')
146 146 repo_obj = Repository.get_by_repo_name(repo_name)
147 147 else:
148 148 repo_obj = None
149 149 repo_name = ''
150 150
151 151 user_log = UserLog()
152 152 user_log.user_id = user_obj.user_id
153 153 user_log.action = safe_unicode(action)
154 154
155 155 user_log.repository = repo_obj
156 156 user_log.repository_name = repo_name
157 157
158 158 user_log.action_date = datetime.datetime.now()
159 159 user_log.user_ip = ipaddr
160 160 sa.add(user_log)
161 161
162 162 log.info(
163 163 'Adding user %s, action %s on %s' % (user_obj, action,
164 164 safe_unicode(repo))
165 165 )
166 166 if commit:
167 167 sa.commit()
168 168 except:
169 169 log.error(traceback.format_exc())
170 170 raise
171 171
172 172
173 173 def get_repos(path, recursive=False):
174 174 """
175 175 Scans given path for repos and return (name,(type,path)) tuple
176 176
177 177 :param path: path to scan for repositories
178 178 :param recursive: recursive search and return names with subdirs in front
179 179 """
180 180
181 181 # remove ending slash for better results
182 182 path = path.rstrip(os.sep)
183 183
184 184 def _get_repos(p):
185 185 if not os.access(p, os.W_OK):
186 186 return
187 187 for dirpath in os.listdir(p):
188 188 if os.path.isfile(os.path.join(p, dirpath)):
189 189 continue
190 190 cur_path = os.path.join(p, dirpath)
191 191 try:
192 192 scm_info = get_scm(cur_path)
193 193 yield scm_info[1].split(path, 1)[-1].lstrip(os.sep), scm_info
194 194 except VCSError:
195 195 if not recursive:
196 196 continue
197 197 #check if this dir containts other repos for recursive scan
198 198 rec_path = os.path.join(p, dirpath)
199 199 if os.path.isdir(rec_path):
200 200 for inner_scm in _get_repos(rec_path):
201 201 yield inner_scm
202 202
203 203 return _get_repos(path)
204 204
205 205
206 206 def is_valid_repo(repo_name, base_path, scm=None):
207 207 """
208 208 Returns True if given path is a valid repository False otherwise.
209 209 If scm param is given also compare if given scm is the same as expected
210 210 from scm parameter
211 211
212 212 :param repo_name:
213 213 :param base_path:
214 214 :param scm:
215 215
216 216 :return True: if given path is a valid repository
217 217 """
218 218 full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
219 219
220 220 try:
221 221 scm_ = get_scm(full_path)
222 222 if scm:
223 223 return scm_[0] == scm
224 224 return True
225 225 except VCSError:
226 226 return False
227 227
228 228
229 229 def is_valid_repos_group(repos_group_name, base_path):
230 230 """
231 231 Returns True if given path is a repos group False otherwise
232 232
233 233 :param repo_name:
234 234 :param base_path:
235 235 """
236 236 full_path = os.path.join(safe_str(base_path), safe_str(repos_group_name))
237 237
238 238 # check if it's not a repo
239 239 if is_valid_repo(repos_group_name, base_path):
240 240 return False
241 241
242 242 try:
243 243 # we need to check bare git repos at higher level
244 244 # since we might match branches/hooks/info/objects or possible
245 245 # other things inside bare git repo
246 246 get_scm(os.path.dirname(full_path))
247 247 return False
248 248 except VCSError:
249 249 pass
250 250
251 251 # check if it's a valid path
252 252 if os.path.isdir(full_path):
253 253 return True
254 254
255 255 return False
256 256
257 257
258 258 def ask_ok(prompt, retries=4, complaint='Yes or no please!'):
259 259 while True:
260 260 ok = raw_input(prompt)
261 261 if ok in ('y', 'ye', 'yes'):
262 262 return True
263 263 if ok in ('n', 'no', 'nop', 'nope'):
264 264 return False
265 265 retries = retries - 1
266 266 if retries < 0:
267 267 raise IOError
268 268 print complaint
269 269
270 270 #propagated from mercurial documentation
271 271 ui_sections = ['alias', 'auth',
272 272 'decode/encode', 'defaults',
273 273 'diff', 'email',
274 274 'extensions', 'format',
275 275 'merge-patterns', 'merge-tools',
276 276 'hooks', 'http_proxy',
277 277 'smtp', 'patch',
278 278 'paths', 'profiling',
279 279 'server', 'trusted',
280 280 'ui', 'web', ]
281 281
282 282
283 283 def make_ui(read_from='file', path=None, checkpaths=True, clear_session=True):
284 284 """
285 285 A function that will read python rc files or database
286 286 and make an mercurial ui object from read options
287 287
288 288 :param path: path to mercurial config file
289 289 :param checkpaths: check the path
290 290 :param read_from: read from 'file' or 'db'
291 291 """
292 292
293 293 baseui = ui.ui()
294 294
295 295 # clean the baseui object
296 296 baseui._ocfg = config.config()
297 297 baseui._ucfg = config.config()
298 298 baseui._tcfg = config.config()
299 299
300 300 if read_from == 'file':
301 301 if not os.path.isfile(path):
302 302 log.debug('hgrc file is not present at %s, skipping...' % path)
303 303 return False
304 304 log.debug('reading hgrc from %s' % path)
305 305 cfg = config.config()
306 306 cfg.read(path)
307 307 for section in ui_sections:
308 308 for k, v in cfg.items(section):
309 309 log.debug('settings ui from file[%s]%s:%s' % (section, k, v))
310 baseui.setconfig(section, k, v)
310 baseui.setconfig(safe_str(section), safe_str(k), safe_str(v))
311 311
312 312 elif read_from == 'db':
313 313 sa = meta.Session()
314 314 ret = sa.query(RhodeCodeUi)\
315 315 .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\
316 316 .all()
317 317
318 318 hg_ui = ret
319 319 for ui_ in hg_ui:
320 320 if ui_.ui_active:
321 321 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
322 322 ui_.ui_key, ui_.ui_value)
323 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
323 baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
324 safe_str(ui_.ui_value))
324 325 if ui_.ui_key == 'push_ssl':
325 326 # force set push_ssl requirement to False, rhodecode
326 327 # handles that
327 baseui.setconfig(ui_.ui_section, ui_.ui_key, False)
328 baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
329 False)
328 330 if clear_session:
329 331 meta.Session.remove()
330 332 return baseui
331 333
332 334
333 335 def set_rhodecode_config(config):
334 336 """
335 337 Updates pylons config with new settings from database
336 338
337 339 :param config:
338 340 """
339 341 hgsettings = RhodeCodeSetting.get_app_settings()
340 342
341 343 for k, v in hgsettings.items():
342 344 config[k] = v
343 345
344 346
345 347 def invalidate_cache(cache_key, *args):
346 348 """
347 349 Puts cache invalidation task into db for
348 350 further global cache invalidation
349 351 """
350 352
351 353 from rhodecode.model.scm import ScmModel
352 354
353 355 if cache_key.startswith('get_repo_cached_'):
354 356 name = cache_key.split('get_repo_cached_')[-1]
355 357 ScmModel().mark_for_invalidation(name)
356 358
357 359
358 360 def map_groups(path):
359 361 """
360 362 Given a full path to a repository, create all nested groups that this
361 363 repo is inside. This function creates parent-child relationships between
362 364 groups and creates default perms for all new groups.
363 365
364 366 :param paths: full path to repository
365 367 """
366 368 sa = meta.Session()
367 369 groups = path.split(Repository.url_sep())
368 370 parent = None
369 371 group = None
370 372
371 373 # last element is repo in nested groups structure
372 374 groups = groups[:-1]
373 375 rgm = ReposGroupModel(sa)
374 376 for lvl, group_name in enumerate(groups):
375 377 group_name = '/'.join(groups[:lvl] + [group_name])
376 378 group = RepoGroup.get_by_group_name(group_name)
377 379 desc = '%s group' % group_name
378 380
379 381 # skip folders that are now removed repos
380 382 if REMOVED_REPO_PAT.match(group_name):
381 383 break
382 384
383 385 if group is None:
384 386 log.debug('creating group level: %s group_name: %s' % (lvl,
385 387 group_name))
386 388 group = RepoGroup(group_name, parent)
387 389 group.group_description = desc
388 390 sa.add(group)
389 391 rgm._create_default_perms(group)
390 392 sa.flush()
391 393 parent = group
392 394 return group
393 395
394 396
395 397 def repo2db_mapper(initial_repo_list, remove_obsolete=False,
396 398 install_git_hook=False):
397 399 """
398 400 maps all repos given in initial_repo_list, non existing repositories
399 401 are created, if remove_obsolete is True it also check for db entries
400 402 that are not in initial_repo_list and removes them.
401 403
402 404 :param initial_repo_list: list of repositories found by scanning methods
403 405 :param remove_obsolete: check for obsolete entries in database
404 406 :param install_git_hook: if this is True, also check and install githook
405 407 for a repo if missing
406 408 """
407 409 from rhodecode.model.repo import RepoModel
408 410 from rhodecode.model.scm import ScmModel
409 411 sa = meta.Session()
410 412 rm = RepoModel()
411 413 user = sa.query(User).filter(User.admin == True).first()
412 414 if user is None:
413 415 raise Exception('Missing administrative account!')
414 416 added = []
415 417
416 418 # # clear cache keys
417 419 # log.debug("Clearing cache keys now...")
418 420 # CacheInvalidation.clear_cache()
419 421 # sa.commit()
420 422
421 423 for name, repo in initial_repo_list.items():
422 424 group = map_groups(name)
423 425 db_repo = rm.get_by_repo_name(name)
424 426 # found repo that is on filesystem not in RhodeCode database
425 427 if not db_repo:
426 428 log.info('repository %s not found, creating now' % name)
427 429 added.append(name)
428 430 desc = (repo.description
429 431 if repo.description != 'unknown'
430 432 else '%s repository' % name)
431 433 new_repo = rm.create_repo(
432 434 repo_name=name,
433 435 repo_type=repo.alias,
434 436 description=desc,
435 437 repos_group=getattr(group, 'group_id', None),
436 438 owner=user,
437 439 just_db=True
438 440 )
439 441 # we added that repo just now, and make sure it has githook
440 442 # installed
441 443 if new_repo.repo_type == 'git':
442 444 ScmModel().install_git_hook(new_repo.scm_instance)
443 445 elif install_git_hook:
444 446 if db_repo.repo_type == 'git':
445 447 ScmModel().install_git_hook(db_repo.scm_instance)
446 448 # during starting install all cache keys for all repositories in the
447 449 # system, this will register all repos and multiple instances
448 450 key, _prefix, _org_key = CacheInvalidation._get_key(name)
449 451 log.debug("Creating a cache key for %s instance_id:`%s`" % (name, _prefix))
450 452 CacheInvalidation._get_or_create_key(key, _prefix, _org_key, commit=False)
451 453 sa.commit()
452 454 removed = []
453 455 if remove_obsolete:
454 456 # remove from database those repositories that are not in the filesystem
455 457 for repo in sa.query(Repository).all():
456 458 if repo.repo_name not in initial_repo_list.keys():
457 459 log.debug("Removing non-existing repository found in db `%s`" %
458 460 repo.repo_name)
459 461 try:
460 462 sa.delete(repo)
461 463 sa.commit()
462 464 removed.append(repo.repo_name)
463 465 except:
464 466 #don't hold further removals on error
465 467 log.error(traceback.format_exc())
466 468 sa.rollback()
467 469
468 470 return added, removed
469 471
470 472
471 473 # set cache regions for beaker so celery can utilise it
472 474 def add_cache(settings):
473 475 cache_settings = {'regions': None}
474 476 for key in settings.keys():
475 477 for prefix in ['beaker.cache.', 'cache.']:
476 478 if key.startswith(prefix):
477 479 name = key.split(prefix)[1].strip()
478 480 cache_settings[name] = settings[key].strip()
479 481 if cache_settings['regions']:
480 482 for region in cache_settings['regions'].split(','):
481 483 region = region.strip()
482 484 region_settings = {}
483 485 for key, value in cache_settings.items():
484 486 if key.startswith(region):
485 487 region_settings[key.split('.')[1]] = value
486 488 region_settings['expire'] = int(region_settings.get('expire',
487 489 60))
488 490 region_settings.setdefault('lock_dir',
489 491 cache_settings.get('lock_dir'))
490 492 region_settings.setdefault('data_dir',
491 493 cache_settings.get('data_dir'))
492 494
493 495 if 'type' not in region_settings:
494 496 region_settings['type'] = cache_settings.get('type',
495 497 'memory')
496 498 beaker.cache.cache_regions[region] = region_settings
497 499
498 500
499 501 def load_rcextensions(root_path):
500 502 import rhodecode
501 503 from rhodecode.config import conf
502 504
503 505 path = os.path.join(root_path, 'rcextensions', '__init__.py')
504 506 if os.path.isfile(path):
505 507 rcext = create_module('rc', path)
506 508 EXT = rhodecode.EXTENSIONS = rcext
507 509 log.debug('Found rcextensions now loading %s...' % rcext)
508 510
509 511 # Additional mappings that are not present in the pygments lexers
510 512 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
511 513
512 514 #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
513 515
514 516 if getattr(EXT, 'INDEX_EXTENSIONS', []) != []:
515 517 log.debug('settings custom INDEX_EXTENSIONS')
516 518 conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', [])
517 519
518 520 #ADDITIONAL MAPPINGS
519 521 log.debug('adding extra into INDEX_EXTENSIONS')
520 522 conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', []))
521 523
522 524
523 525 #==============================================================================
524 526 # TEST FUNCTIONS AND CREATORS
525 527 #==============================================================================
526 528 def create_test_index(repo_location, config, full_index):
527 529 """
528 530 Makes default test index
529 531
530 532 :param config: test config
531 533 :param full_index:
532 534 """
533 535
534 536 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
535 537 from rhodecode.lib.pidlock import DaemonLock, LockHeld
536 538
537 539 repo_location = repo_location
538 540
539 541 index_location = os.path.join(config['app_conf']['index_dir'])
540 542 if not os.path.exists(index_location):
541 543 os.makedirs(index_location)
542 544
543 545 try:
544 546 l = DaemonLock(file_=jn(dn(index_location), 'make_index.lock'))
545 547 WhooshIndexingDaemon(index_location=index_location,
546 548 repo_location=repo_location)\
547 549 .run(full_index=full_index)
548 550 l.release()
549 551 except LockHeld:
550 552 pass
551 553
552 554
553 555 def create_test_env(repos_test_path, config):
554 556 """
555 557 Makes a fresh database and
556 558 install test repository into tmp dir
557 559 """
558 560 from rhodecode.lib.db_manage import DbManage
559 561 from rhodecode.tests import HG_REPO, GIT_REPO, TESTS_TMP_PATH
560 562
561 563 # PART ONE create db
562 564 dbconf = config['sqlalchemy.db1.url']
563 565 log.debug('making test db %s' % dbconf)
564 566
565 567 # create test dir if it doesn't exist
566 568 if not os.path.isdir(repos_test_path):
567 569 log.debug('Creating testdir %s' % repos_test_path)
568 570 os.makedirs(repos_test_path)
569 571
570 572 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=config['here'],
571 573 tests=True)
572 574 dbmanage.create_tables(override=True)
573 575 dbmanage.create_settings(dbmanage.config_prompt(repos_test_path))
574 576 dbmanage.create_default_user()
575 577 dbmanage.admin_prompt()
576 578 dbmanage.create_permissions()
577 579 dbmanage.populate_default_permissions()
578 580 Session().commit()
579 581 # PART TWO make test repo
580 582 log.debug('making test vcs repositories')
581 583
582 584 idx_path = config['app_conf']['index_dir']
583 585 data_path = config['app_conf']['cache_dir']
584 586
585 587 #clean index and data
586 588 if idx_path and os.path.exists(idx_path):
587 589 log.debug('remove %s' % idx_path)
588 590 shutil.rmtree(idx_path)
589 591
590 592 if data_path and os.path.exists(data_path):
591 593 log.debug('remove %s' % data_path)
592 594 shutil.rmtree(data_path)
593 595
594 596 #CREATE DEFAULT TEST REPOS
595 597 cur_dir = dn(dn(abspath(__file__)))
596 598 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz"))
597 599 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
598 600 tar.close()
599 601
600 602 cur_dir = dn(dn(abspath(__file__)))
601 603 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_git.tar.gz"))
602 604 tar.extractall(jn(TESTS_TMP_PATH, GIT_REPO))
603 605 tar.close()
604 606
605 607 #LOAD VCS test stuff
606 608 from rhodecode.tests.vcs import setup_package
607 609 setup_package()
608 610
609 611
610 612 #==============================================================================
611 613 # PASTER COMMANDS
612 614 #==============================================================================
613 615 class BasePasterCommand(Command):
614 616 """
615 617 Abstract Base Class for paster commands.
616 618
617 619 The celery commands are somewhat aggressive about loading
618 620 celery.conf, and since our module sets the `CELERY_LOADER`
619 621 environment variable to our loader, we have to bootstrap a bit and
620 622 make sure we've had a chance to load the pylons config off of the
621 623 command line, otherwise everything fails.
622 624 """
623 625 min_args = 1
624 626 min_args_error = "Please provide a paster config file as an argument."
625 627 takes_config_file = 1
626 628 requires_config_file = True
627 629
628 630 def notify_msg(self, msg, log=False):
629 631 """Make a notification to user, additionally if logger is passed
630 632 it logs this action using given logger
631 633
632 634 :param msg: message that will be printed to user
633 635 :param log: logging instance, to use to additionally log this message
634 636
635 637 """
636 638 if log and isinstance(log, logging):
637 639 log(msg)
638 640
639 641 def run(self, args):
640 642 """
641 643 Overrides Command.run
642 644
643 645 Checks for a config file argument and loads it.
644 646 """
645 647 if len(args) < self.min_args:
646 648 raise BadCommand(
647 649 self.min_args_error % {'min_args': self.min_args,
648 650 'actual_args': len(args)})
649 651
650 652 # Decrement because we're going to lob off the first argument.
651 653 # @@ This is hacky
652 654 self.min_args -= 1
653 655 self.bootstrap_config(args[0])
654 656 self.update_parser()
655 657 return super(BasePasterCommand, self).run(args[1:])
656 658
657 659 def update_parser(self):
658 660 """
659 661 Abstract method. Allows for the class's parser to be updated
660 662 before the superclass's `run` method is called. Necessary to
661 663 allow options/arguments to be passed through to the underlying
662 664 celery command.
663 665 """
664 666 raise NotImplementedError("Abstract Method.")
665 667
666 668 def bootstrap_config(self, conf):
667 669 """
668 670 Loads the pylons configuration.
669 671 """
670 672 from pylons import config as pylonsconfig
671 673
672 674 self.path_to_ini_file = os.path.realpath(conf)
673 675 conf = paste.deploy.appconfig('config:' + self.path_to_ini_file)
674 676 pylonsconfig.init_app(conf.global_conf, conf.local_conf)
675 677
676 678
677 679 def check_git_version():
678 680 """
679 681 Checks what version of git is installed in system, and issues a warning
680 682 if it's too old for RhodeCode to properly work.
681 683 """
682 684 import subprocess
683 685 from distutils.version import StrictVersion
684 686 from rhodecode import BACKENDS
685 687
686 688 p = subprocess.Popen('git --version', shell=True,
687 689 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
688 690 stdout, stderr = p.communicate()
689 691 ver = (stdout.split(' ')[-1] or '').strip() or '0.0.0'
690 692 if len(ver.split('.')) > 3:
691 693 #StrictVersion needs to be only 3 element type
692 694 ver = '.'.join(ver.split('.')[:3])
693 695 try:
694 696 _ver = StrictVersion(ver)
695 697 except:
696 698 _ver = StrictVersion('0.0.0')
697 699 stderr = traceback.format_exc()
698 700
699 701 req_ver = '1.7.4'
700 702 to_old_git = False
701 703 if _ver <= StrictVersion(req_ver):
702 704 to_old_git = True
703 705
704 706 if 'git' in BACKENDS:
705 707 log.debug('GIT version detected: %s' % stdout)
706 708 if stderr:
707 709 log.warning('Unable to detect git version org error was:%r' % stderr)
708 710 elif to_old_git:
709 711 log.warning('RhodeCode detected git version %s, which is too old '
710 712 'for the system to function properly. Make sure '
711 713 'its version is at least %s' % (ver, req_ver))
712 714 return _ver
General Comments 0
You need to be logged in to leave comments. Login now