##// END OF EJS Templates
fix strict version of git check if we have 1.7.4 it's ok !
marcink -
r2997:da3926d9 beta
parent child Browse files
Show More
@@ -1,714 +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 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 323 baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
324 324 safe_str(ui_.ui_value))
325 325 if ui_.ui_key == 'push_ssl':
326 326 # force set push_ssl requirement to False, rhodecode
327 327 # handles that
328 328 baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
329 329 False)
330 330 if clear_session:
331 331 meta.Session.remove()
332 332 return baseui
333 333
334 334
335 335 def set_rhodecode_config(config):
336 336 """
337 337 Updates pylons config with new settings from database
338 338
339 339 :param config:
340 340 """
341 341 hgsettings = RhodeCodeSetting.get_app_settings()
342 342
343 343 for k, v in hgsettings.items():
344 344 config[k] = v
345 345
346 346
347 347 def invalidate_cache(cache_key, *args):
348 348 """
349 349 Puts cache invalidation task into db for
350 350 further global cache invalidation
351 351 """
352 352
353 353 from rhodecode.model.scm import ScmModel
354 354
355 355 if cache_key.startswith('get_repo_cached_'):
356 356 name = cache_key.split('get_repo_cached_')[-1]
357 357 ScmModel().mark_for_invalidation(name)
358 358
359 359
360 360 def map_groups(path):
361 361 """
362 362 Given a full path to a repository, create all nested groups that this
363 363 repo is inside. This function creates parent-child relationships between
364 364 groups and creates default perms for all new groups.
365 365
366 366 :param paths: full path to repository
367 367 """
368 368 sa = meta.Session()
369 369 groups = path.split(Repository.url_sep())
370 370 parent = None
371 371 group = None
372 372
373 373 # last element is repo in nested groups structure
374 374 groups = groups[:-1]
375 375 rgm = ReposGroupModel(sa)
376 376 for lvl, group_name in enumerate(groups):
377 377 group_name = '/'.join(groups[:lvl] + [group_name])
378 378 group = RepoGroup.get_by_group_name(group_name)
379 379 desc = '%s group' % group_name
380 380
381 381 # skip folders that are now removed repos
382 382 if REMOVED_REPO_PAT.match(group_name):
383 383 break
384 384
385 385 if group is None:
386 386 log.debug('creating group level: %s group_name: %s' % (lvl,
387 387 group_name))
388 388 group = RepoGroup(group_name, parent)
389 389 group.group_description = desc
390 390 sa.add(group)
391 391 rgm._create_default_perms(group)
392 392 sa.flush()
393 393 parent = group
394 394 return group
395 395
396 396
397 397 def repo2db_mapper(initial_repo_list, remove_obsolete=False,
398 398 install_git_hook=False):
399 399 """
400 400 maps all repos given in initial_repo_list, non existing repositories
401 401 are created, if remove_obsolete is True it also check for db entries
402 402 that are not in initial_repo_list and removes them.
403 403
404 404 :param initial_repo_list: list of repositories found by scanning methods
405 405 :param remove_obsolete: check for obsolete entries in database
406 406 :param install_git_hook: if this is True, also check and install githook
407 407 for a repo if missing
408 408 """
409 409 from rhodecode.model.repo import RepoModel
410 410 from rhodecode.model.scm import ScmModel
411 411 sa = meta.Session()
412 412 rm = RepoModel()
413 413 user = sa.query(User).filter(User.admin == True).first()
414 414 if user is None:
415 415 raise Exception('Missing administrative account!')
416 416 added = []
417 417
418 418 # # clear cache keys
419 419 # log.debug("Clearing cache keys now...")
420 420 # CacheInvalidation.clear_cache()
421 421 # sa.commit()
422 422
423 423 for name, repo in initial_repo_list.items():
424 424 group = map_groups(name)
425 425 db_repo = rm.get_by_repo_name(name)
426 426 # found repo that is on filesystem not in RhodeCode database
427 427 if not db_repo:
428 428 log.info('repository %s not found, creating now' % name)
429 429 added.append(name)
430 430 desc = (repo.description
431 431 if repo.description != 'unknown'
432 432 else '%s repository' % name)
433 433 new_repo = rm.create_repo(
434 434 repo_name=name,
435 435 repo_type=repo.alias,
436 436 description=desc,
437 437 repos_group=getattr(group, 'group_id', None),
438 438 owner=user,
439 439 just_db=True
440 440 )
441 441 # we added that repo just now, and make sure it has githook
442 442 # installed
443 443 if new_repo.repo_type == 'git':
444 444 ScmModel().install_git_hook(new_repo.scm_instance)
445 445 elif install_git_hook:
446 446 if db_repo.repo_type == 'git':
447 447 ScmModel().install_git_hook(db_repo.scm_instance)
448 448 # during starting install all cache keys for all repositories in the
449 449 # system, this will register all repos and multiple instances
450 450 key, _prefix, _org_key = CacheInvalidation._get_key(name)
451 451 log.debug("Creating a cache key for %s instance_id:`%s`" % (name, _prefix))
452 452 CacheInvalidation._get_or_create_key(key, _prefix, _org_key, commit=False)
453 453 sa.commit()
454 454 removed = []
455 455 if remove_obsolete:
456 456 # remove from database those repositories that are not in the filesystem
457 457 for repo in sa.query(Repository).all():
458 458 if repo.repo_name not in initial_repo_list.keys():
459 459 log.debug("Removing non-existing repository found in db `%s`" %
460 460 repo.repo_name)
461 461 try:
462 462 sa.delete(repo)
463 463 sa.commit()
464 464 removed.append(repo.repo_name)
465 465 except:
466 466 #don't hold further removals on error
467 467 log.error(traceback.format_exc())
468 468 sa.rollback()
469 469
470 470 return added, removed
471 471
472 472
473 473 # set cache regions for beaker so celery can utilise it
474 474 def add_cache(settings):
475 475 cache_settings = {'regions': None}
476 476 for key in settings.keys():
477 477 for prefix in ['beaker.cache.', 'cache.']:
478 478 if key.startswith(prefix):
479 479 name = key.split(prefix)[1].strip()
480 480 cache_settings[name] = settings[key].strip()
481 481 if cache_settings['regions']:
482 482 for region in cache_settings['regions'].split(','):
483 483 region = region.strip()
484 484 region_settings = {}
485 485 for key, value in cache_settings.items():
486 486 if key.startswith(region):
487 487 region_settings[key.split('.')[1]] = value
488 488 region_settings['expire'] = int(region_settings.get('expire',
489 489 60))
490 490 region_settings.setdefault('lock_dir',
491 491 cache_settings.get('lock_dir'))
492 492 region_settings.setdefault('data_dir',
493 493 cache_settings.get('data_dir'))
494 494
495 495 if 'type' not in region_settings:
496 496 region_settings['type'] = cache_settings.get('type',
497 497 'memory')
498 498 beaker.cache.cache_regions[region] = region_settings
499 499
500 500
501 501 def load_rcextensions(root_path):
502 502 import rhodecode
503 503 from rhodecode.config import conf
504 504
505 505 path = os.path.join(root_path, 'rcextensions', '__init__.py')
506 506 if os.path.isfile(path):
507 507 rcext = create_module('rc', path)
508 508 EXT = rhodecode.EXTENSIONS = rcext
509 509 log.debug('Found rcextensions now loading %s...' % rcext)
510 510
511 511 # Additional mappings that are not present in the pygments lexers
512 512 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
513 513
514 514 #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
515 515
516 516 if getattr(EXT, 'INDEX_EXTENSIONS', []) != []:
517 517 log.debug('settings custom INDEX_EXTENSIONS')
518 518 conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', [])
519 519
520 520 #ADDITIONAL MAPPINGS
521 521 log.debug('adding extra into INDEX_EXTENSIONS')
522 522 conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', []))
523 523
524 524
525 525 #==============================================================================
526 526 # TEST FUNCTIONS AND CREATORS
527 527 #==============================================================================
528 528 def create_test_index(repo_location, config, full_index):
529 529 """
530 530 Makes default test index
531 531
532 532 :param config: test config
533 533 :param full_index:
534 534 """
535 535
536 536 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
537 537 from rhodecode.lib.pidlock import DaemonLock, LockHeld
538 538
539 539 repo_location = repo_location
540 540
541 541 index_location = os.path.join(config['app_conf']['index_dir'])
542 542 if not os.path.exists(index_location):
543 543 os.makedirs(index_location)
544 544
545 545 try:
546 546 l = DaemonLock(file_=jn(dn(index_location), 'make_index.lock'))
547 547 WhooshIndexingDaemon(index_location=index_location,
548 548 repo_location=repo_location)\
549 549 .run(full_index=full_index)
550 550 l.release()
551 551 except LockHeld:
552 552 pass
553 553
554 554
555 555 def create_test_env(repos_test_path, config):
556 556 """
557 557 Makes a fresh database and
558 558 install test repository into tmp dir
559 559 """
560 560 from rhodecode.lib.db_manage import DbManage
561 561 from rhodecode.tests import HG_REPO, GIT_REPO, TESTS_TMP_PATH
562 562
563 563 # PART ONE create db
564 564 dbconf = config['sqlalchemy.db1.url']
565 565 log.debug('making test db %s' % dbconf)
566 566
567 567 # create test dir if it doesn't exist
568 568 if not os.path.isdir(repos_test_path):
569 569 log.debug('Creating testdir %s' % repos_test_path)
570 570 os.makedirs(repos_test_path)
571 571
572 572 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=config['here'],
573 573 tests=True)
574 574 dbmanage.create_tables(override=True)
575 575 dbmanage.create_settings(dbmanage.config_prompt(repos_test_path))
576 576 dbmanage.create_default_user()
577 577 dbmanage.admin_prompt()
578 578 dbmanage.create_permissions()
579 579 dbmanage.populate_default_permissions()
580 580 Session().commit()
581 581 # PART TWO make test repo
582 582 log.debug('making test vcs repositories')
583 583
584 584 idx_path = config['app_conf']['index_dir']
585 585 data_path = config['app_conf']['cache_dir']
586 586
587 587 #clean index and data
588 588 if idx_path and os.path.exists(idx_path):
589 589 log.debug('remove %s' % idx_path)
590 590 shutil.rmtree(idx_path)
591 591
592 592 if data_path and os.path.exists(data_path):
593 593 log.debug('remove %s' % data_path)
594 594 shutil.rmtree(data_path)
595 595
596 596 #CREATE DEFAULT TEST REPOS
597 597 cur_dir = dn(dn(abspath(__file__)))
598 598 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz"))
599 599 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
600 600 tar.close()
601 601
602 602 cur_dir = dn(dn(abspath(__file__)))
603 603 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_git.tar.gz"))
604 604 tar.extractall(jn(TESTS_TMP_PATH, GIT_REPO))
605 605 tar.close()
606 606
607 607 #LOAD VCS test stuff
608 608 from rhodecode.tests.vcs import setup_package
609 609 setup_package()
610 610
611 611
612 612 #==============================================================================
613 613 # PASTER COMMANDS
614 614 #==============================================================================
615 615 class BasePasterCommand(Command):
616 616 """
617 617 Abstract Base Class for paster commands.
618 618
619 619 The celery commands are somewhat aggressive about loading
620 620 celery.conf, and since our module sets the `CELERY_LOADER`
621 621 environment variable to our loader, we have to bootstrap a bit and
622 622 make sure we've had a chance to load the pylons config off of the
623 623 command line, otherwise everything fails.
624 624 """
625 625 min_args = 1
626 626 min_args_error = "Please provide a paster config file as an argument."
627 627 takes_config_file = 1
628 628 requires_config_file = True
629 629
630 630 def notify_msg(self, msg, log=False):
631 631 """Make a notification to user, additionally if logger is passed
632 632 it logs this action using given logger
633 633
634 634 :param msg: message that will be printed to user
635 635 :param log: logging instance, to use to additionally log this message
636 636
637 637 """
638 638 if log and isinstance(log, logging):
639 639 log(msg)
640 640
641 641 def run(self, args):
642 642 """
643 643 Overrides Command.run
644 644
645 645 Checks for a config file argument and loads it.
646 646 """
647 647 if len(args) < self.min_args:
648 648 raise BadCommand(
649 649 self.min_args_error % {'min_args': self.min_args,
650 650 'actual_args': len(args)})
651 651
652 652 # Decrement because we're going to lob off the first argument.
653 653 # @@ This is hacky
654 654 self.min_args -= 1
655 655 self.bootstrap_config(args[0])
656 656 self.update_parser()
657 657 return super(BasePasterCommand, self).run(args[1:])
658 658
659 659 def update_parser(self):
660 660 """
661 661 Abstract method. Allows for the class's parser to be updated
662 662 before the superclass's `run` method is called. Necessary to
663 663 allow options/arguments to be passed through to the underlying
664 664 celery command.
665 665 """
666 666 raise NotImplementedError("Abstract Method.")
667 667
668 668 def bootstrap_config(self, conf):
669 669 """
670 670 Loads the pylons configuration.
671 671 """
672 672 from pylons import config as pylonsconfig
673 673
674 674 self.path_to_ini_file = os.path.realpath(conf)
675 675 conf = paste.deploy.appconfig('config:' + self.path_to_ini_file)
676 676 pylonsconfig.init_app(conf.global_conf, conf.local_conf)
677 677
678 678
679 679 def check_git_version():
680 680 """
681 681 Checks what version of git is installed in system, and issues a warning
682 682 if it's too old for RhodeCode to properly work.
683 683 """
684 684 import subprocess
685 685 from distutils.version import StrictVersion
686 686 from rhodecode import BACKENDS
687 687
688 688 p = subprocess.Popen('git --version', shell=True,
689 689 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
690 690 stdout, stderr = p.communicate()
691 691 ver = (stdout.split(' ')[-1] or '').strip() or '0.0.0'
692 692 if len(ver.split('.')) > 3:
693 693 #StrictVersion needs to be only 3 element type
694 694 ver = '.'.join(ver.split('.')[:3])
695 695 try:
696 696 _ver = StrictVersion(ver)
697 697 except:
698 698 _ver = StrictVersion('0.0.0')
699 699 stderr = traceback.format_exc()
700 700
701 701 req_ver = '1.7.4'
702 702 to_old_git = False
703 if _ver <= StrictVersion(req_ver):
703 if _ver < StrictVersion(req_ver):
704 704 to_old_git = True
705 705
706 706 if 'git' in BACKENDS:
707 707 log.debug('GIT version detected: %s' % stdout)
708 708 if stderr:
709 709 log.warning('Unable to detect git version org error was:%r' % stderr)
710 710 elif to_old_git:
711 711 log.warning('RhodeCode detected git version %s, which is too old '
712 712 'for the system to function properly. Make sure '
713 713 'its version is at least %s' % (ver, req_ver))
714 714 return _ver
General Comments 0
You need to be logged in to leave comments. Login now