##// END OF EJS Templates
complete rewrite of paster commands,...
marcink -
r785:277427ac beta
parent child Browse files
Show More
@@ -2,7 +2,6 b' from celery.decorators import task'
2
2
3 import os
3 import os
4 import traceback
4 import traceback
5 import beaker
6 from time import mktime
5 from time import mktime
7 from operator import itemgetter
6 from operator import itemgetter
8
7
@@ -12,7 +11,7 b' from pylons.i18n.translation import _'
12 from rhodecode.lib.celerylib import run_task, locked_task, str2bool
11 from rhodecode.lib.celerylib import run_task, locked_task, str2bool
13 from rhodecode.lib.helpers import person
12 from rhodecode.lib.helpers import person
14 from rhodecode.lib.smtp_mailer import SmtpMailer
13 from rhodecode.lib.smtp_mailer import SmtpMailer
15 from rhodecode.lib.utils import OrderedDict
14 from rhodecode.lib.utils import OrderedDict, add_cache
16 from rhodecode.model import init_model
15 from rhodecode.model import init_model
17 from rhodecode.model import meta
16 from rhodecode.model import meta
18 from rhodecode.model.db import RhodeCodeUi
17 from rhodecode.model.db import RhodeCodeUi
@@ -21,29 +20,6 b' from vcs.backends import get_repo'
21
20
22 from sqlalchemy import engine_from_config
21 from sqlalchemy import engine_from_config
23
22
24 #set cache regions for beaker so celery can utilise it
25 def add_cache(settings):
26 cache_settings = {'regions':None}
27 for key in settings.keys():
28 for prefix in ['beaker.cache.', 'cache.']:
29 if key.startswith(prefix):
30 name = key.split(prefix)[1].strip()
31 cache_settings[name] = settings[key].strip()
32 if cache_settings['regions']:
33 for region in cache_settings['regions'].split(','):
34 region = region.strip()
35 region_settings = {}
36 for key, value in cache_settings.items():
37 if key.startswith(region):
38 region_settings[key.split('.')[1]] = value
39 region_settings['expire'] = int(region_settings.get('expire',
40 60))
41 region_settings.setdefault('lock_dir',
42 cache_settings.get('lock_dir'))
43 if 'type' not in region_settings:
44 region_settings['type'] = cache_settings.get('type',
45 'memory')
46 beaker.cache.cache_regions[region] = region_settings
47 add_cache(config)
23 add_cache(config)
48
24
49 try:
25 try:
@@ -1,64 +1,11 b''
1 import os
1 from rhodecode.lib.utils import BasePasterCommand, Command
2 from paste.script.command import Command, BadCommand
3 import paste.deploy
4 from pylons import config
5
2
6
3
7 __all__ = ['CeleryDaemonCommand', 'CeleryBeatCommand',
4 __all__ = ['CeleryDaemonCommand', 'CeleryBeatCommand',
8 'CAMQPAdminCommand', 'CeleryEventCommand']
5 'CAMQPAdminCommand', 'CeleryEventCommand']
9
6
10
7
11 class CeleryCommand(Command):
8 class CeleryDaemonCommand(BasePasterCommand):
12 """
13 Abstract Base Class for celery commands.
14
15 The celery commands are somewhat aggressive about loading
16 celery.conf, and since our module sets the `CELERY_LOADER`
17 environment variable to our loader, we have to bootstrap a bit and
18 make sure we've had a chance to load the pylons config off of the
19 command line, otherwise everything fails.
20 """
21 min_args = 1
22 min_args_error = "Please provide a paster config file as an argument."
23 takes_config_file = 1
24 requires_config_file = True
25
26 def run(self, args):
27 """
28 Overrides Command.run
29
30 Checks for a config file argument and loads it.
31 """
32 if len(args) < self.min_args:
33 raise BadCommand(
34 self.min_args_error % {'min_args': self.min_args,
35 'actual_args': len(args)})
36 # Decrement because we're going to lob off the first argument.
37 # @@ This is hacky
38 self.min_args -= 1
39 self.bootstrap_config(args[0])
40 self.update_parser()
41 return super(CeleryCommand, self).run(args[1:])
42
43 def update_parser(self):
44 """
45 Abstract method. Allows for the class's parser to be updated
46 before the superclass's `run` method is called. Necessary to
47 allow options/arguments to be passed through to the underlying
48 celery command.
49 """
50 raise NotImplementedError("Abstract Method.")
51
52 def bootstrap_config(self, conf):
53 """
54 Loads the pylons configuration.
55 """
56 path_to_ini_file = os.path.realpath(conf)
57 conf = paste.deploy.appconfig('config:' + path_to_ini_file)
58 config.init_app(conf.global_conf, conf.local_conf)
59
60
61 class CeleryDaemonCommand(CeleryCommand):
62 """Start the celery worker
9 """Start the celery worker
63
10
64 Starts the celery worker that uses a paste.deploy configuration
11 Starts the celery worker that uses a paste.deploy configuration
@@ -80,7 +27,7 b' class CeleryDaemonCommand(CeleryCommand)'
80 return celeryd.WorkerCommand().run(**vars(self.options))
27 return celeryd.WorkerCommand().run(**vars(self.options))
81
28
82
29
83 class CeleryBeatCommand(CeleryCommand):
30 class CeleryBeatCommand(BasePasterCommand):
84 """Start the celery beat server
31 """Start the celery beat server
85
32
86 Starts the celery beat server using a paste.deploy configuration
33 Starts the celery beat server using a paste.deploy configuration
@@ -101,7 +48,7 b' class CeleryBeatCommand(CeleryCommand):'
101 from celery.bin import celerybeat
48 from celery.bin import celerybeat
102 return celerybeat.BeatCommand(**vars(self.options))
49 return celerybeat.BeatCommand(**vars(self.options))
103
50
104 class CAMQPAdminCommand(CeleryCommand):
51 class CAMQPAdminCommand(BasePasterCommand):
105 """CAMQP Admin
52 """CAMQP Admin
106
53
107 CAMQP celery admin tool.
54 CAMQP celery admin tool.
@@ -122,7 +69,7 b' class CAMQPAdminCommand(CeleryCommand):'
122 return camqadm.camqadm(*self.args, **vars(self.options))
69 return camqadm.camqadm(*self.args, **vars(self.options))
123
70
124
71
125 class CeleryEventCommand(CeleryCommand):
72 class CeleryEventCommand(BasePasterCommand):
126 """Celery event commandd.
73 """Celery event commandd.
127
74
128 Capture celery events.
75 Capture celery events.
@@ -1,23 +1,28 b''
1 import os
1 import os
2 import sys
2 import sys
3 import traceback
3 from os.path import dirname as dn, join as jn
4 from os.path import dirname as dn, join as jn
4
5
5 #to get the rhodecode import
6 #to get the rhodecode import
6 sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
7 sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
7
8
9 from rhodecode.model import init_model
10 from rhodecode.model.scm import ScmModel
8 from rhodecode.config.environment import load_environment
11 from rhodecode.config.environment import load_environment
9 from rhodecode.model.scm import ScmModel
12 from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
13
10 from shutil import rmtree
14 from shutil import rmtree
11 from webhelpers.html.builder import escape
15 from webhelpers.html.builder import escape
12 from vcs.utils.lazy import LazyProperty
16 from vcs.utils.lazy import LazyProperty
13
17
18 from sqlalchemy import engine_from_config
19
14 from whoosh.analysis import RegexTokenizer, LowercaseFilter, StopFilter
20 from whoosh.analysis import RegexTokenizer, LowercaseFilter, StopFilter
15 from whoosh.fields import TEXT, ID, STORED, Schema, FieldType
21 from whoosh.fields import TEXT, ID, STORED, Schema, FieldType
16 from whoosh.index import create_in, open_dir
22 from whoosh.index import create_in, open_dir
17 from whoosh.formats import Characters
23 from whoosh.formats import Characters
18 from whoosh.highlight import highlight, SimpleFragmenter, HtmlFormatter
24 from whoosh.highlight import highlight, SimpleFragmenter, HtmlFormatter
19
25
20 import traceback
21
26
22 #EXTENSIONS WE WANT TO INDEX CONTENT OFF
27 #EXTENSIONS WE WANT TO INDEX CONTENT OFF
23 INDEX_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx', 'aspx', 'asx', 'axd', 'c',
28 INDEX_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx', 'aspx', 'asx', 'axd', 'c',
@@ -45,10 +50,8 b" IDX_NAME = 'HG_INDEX'"
45 FORMATTER = HtmlFormatter('span', between='\n<span class="break">...</span>\n')
50 FORMATTER = HtmlFormatter('span', between='\n<span class="break">...</span>\n')
46 FRAGMENTER = SimpleFragmenter(200)
51 FRAGMENTER = SimpleFragmenter(200)
47
52
48 from paste.script import command
49 import ConfigParser
50
53
51 class MakeIndex(command.Command):
54 class MakeIndex(BasePasterCommand):
52
55
53 max_args = 1
56 max_args = 1
54 min_args = 1
57 min_args = 1
@@ -57,26 +60,16 b' class MakeIndex(command.Command):'
57 summary = "Creates index for full text search given configuration file"
60 summary = "Creates index for full text search given configuration file"
58 group_name = "RhodeCode"
61 group_name = "RhodeCode"
59 takes_config_file = -1
62 takes_config_file = -1
60 parser = command.Command.standard_parser(verbose=True)
63 parser = Command.standard_parser(verbose=True)
61 parser.add_option('--repo-location',
64
62 action='store',
63 dest='repo_location',
64 help="Specifies repositories location to index REQUIRED",
65 )
66 parser.add_option('-f',
67 action='store_true',
68 dest='full_index',
69 help="Specifies that index should be made full i.e"
70 " destroy old and build from scratch",
71 default=False)
72 def command(self):
65 def command(self):
73 config_name = self.args[0]
74 p = config_name.split('/')
75 root = '.' if len(p) == 1 else '/'.join(p[:-1])
76 config = ConfigParser.ConfigParser({'here':root})
77 config.read(config_name)
78
66
79 index_location = dict(config.items('app:main'))['index_dir']
67 from pylons import config
68 add_cache(config)
69 engine = engine_from_config(config, 'sqlalchemy.db1.')
70 init_model(engine)
71
72 index_location = config['index_dir']
80 repo_location = self.options.repo_location
73 repo_location = self.options.repo_location
81
74
82 #======================================================================
75 #======================================================================
@@ -93,6 +86,18 b' class MakeIndex(command.Command):'
93 except LockHeld:
86 except LockHeld:
94 sys.exit(1)
87 sys.exit(1)
95
88
89 def update_parser(self):
90 self.parser.add_option('--repo-location',
91 action='store',
92 dest='repo_location',
93 help="Specifies repositories location to index REQUIRED",
94 )
95 self.parser.add_option('-f',
96 action='store_true',
97 dest='full_index',
98 help="Specifies that index should be made full i.e"
99 " destroy old and build from scratch",
100 default=False)
96
101
97 class ResultWrapper(object):
102 class ResultWrapper(object):
98 def __init__(self, search_type, searcher, matcher, highlight_items):
103 def __init__(self, search_type, searcher, matcher, highlight_items):
@@ -36,7 +36,10 b' from UserDict import DictMixin'
36 from mercurial import ui, config, hg
36 from mercurial import ui, config, hg
37 from mercurial.error import RepoError
37 from mercurial.error import RepoError
38
38
39 from paste.script import command
39 import paste
40 import beaker
41 from paste.script.command import Command, BadCommand
42
40 from vcs.backends.base import BaseChangeset
43 from vcs.backends.base import BaseChangeset
41 from vcs.utils.lazy import LazyProperty
44 from vcs.utils.lazy import LazyProperty
42
45
@@ -416,6 +419,31 b' class OrderedDict(dict, DictMixin):'
416 return not self == other
419 return not self == other
417
420
418
421
422 #set cache regions for beaker so celery can utilise it
423 def add_cache(settings):
424 cache_settings = {'regions':None}
425 for key in settings.keys():
426 for prefix in ['beaker.cache.', 'cache.']:
427 if key.startswith(prefix):
428 name = key.split(prefix)[1].strip()
429 cache_settings[name] = settings[key].strip()
430 if cache_settings['regions']:
431 for region in cache_settings['regions'].split(','):
432 region = region.strip()
433 region_settings = {}
434 for key, value in cache_settings.items():
435 if key.startswith(region):
436 region_settings[key.split('.')[1]] = value
437 region_settings['expire'] = int(region_settings.get('expire',
438 60))
439 region_settings.setdefault('lock_dir',
440 cache_settings.get('lock_dir'))
441 if 'type' not in region_settings:
442 region_settings['type'] = cache_settings.get('type',
443 'memory')
444 beaker.cache.cache_regions[region] = region_settings
445
446
419 #===============================================================================
447 #===============================================================================
420 # TEST FUNCTIONS AND CREATORS
448 # TEST FUNCTIONS AND CREATORS
421 #===============================================================================
449 #===============================================================================
@@ -498,7 +526,66 b' def create_test_env(repos_test_path, con'
498 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
526 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
499 tar.close()
527 tar.close()
500
528
501 class UpgradeDb(command.Command):
529
530 #==============================================================================
531 # PASTER COMMANDS
532 #==============================================================================
533
534 class BasePasterCommand(Command):
535 """
536 Abstract Base Class for paster commands.
537
538 The celery commands are somewhat aggressive about loading
539 celery.conf, and since our module sets the `CELERY_LOADER`
540 environment variable to our loader, we have to bootstrap a bit and
541 make sure we've had a chance to load the pylons config off of the
542 command line, otherwise everything fails.
543 """
544 min_args = 1
545 min_args_error = "Please provide a paster config file as an argument."
546 takes_config_file = 1
547 requires_config_file = True
548
549 def run(self, args):
550 """
551 Overrides Command.run
552
553 Checks for a config file argument and loads it.
554 """
555 if len(args) < self.min_args:
556 raise BadCommand(
557 self.min_args_error % {'min_args': self.min_args,
558 'actual_args': len(args)})
559
560 # Decrement because we're going to lob off the first argument.
561 # @@ This is hacky
562 self.min_args -= 1
563 self.bootstrap_config(args[0])
564 self.update_parser()
565 return super(BasePasterCommand, self).run(args[1:])
566
567 def update_parser(self):
568 """
569 Abstract method. Allows for the class's parser to be updated
570 before the superclass's `run` method is called. Necessary to
571 allow options/arguments to be passed through to the underlying
572 celery command.
573 """
574 raise NotImplementedError("Abstract Method.")
575
576 def bootstrap_config(self, conf):
577 """
578 Loads the pylons configuration.
579 """
580 from pylons import config as pylonsconfig
581
582 path_to_ini_file = os.path.realpath(conf)
583 conf = paste.deploy.appconfig('config:' + path_to_ini_file)
584 pylonsconfig.init_app(conf.global_conf, conf.local_conf)
585
586
587
588 class UpgradeDb(BasePasterCommand):
502 """Command used for paster to upgrade our database to newer version
589 """Command used for paster to upgrade our database to newer version
503 """
590 """
504
591
@@ -509,16 +596,16 b' class UpgradeDb(command.Command):'
509 summary = "Upgrades current db to newer version given configuration file"
596 summary = "Upgrades current db to newer version given configuration file"
510 group_name = "RhodeCode"
597 group_name = "RhodeCode"
511
598
512 parser = command.Command.standard_parser(verbose=True)
599 parser = Command.standard_parser(verbose=True)
513
600
514 parser.add_option('--sql',
601 def command(self):
602 from pylons import config
603 raise NotImplementedError('Not implemented yet')
604
605
606 def update_parser(self):
607 self.parser.add_option('--sql',
515 action='store_true',
608 action='store_true',
516 dest='just_sql',
609 dest='just_sql',
517 help="Prints upgrade sql for further investigation",
610 help="Prints upgrade sql for further investigation",
518 default=False)
611 default=False)
519 def command(self):
520 config_name = self.args[0]
521 p = config_name.split('/')
522 root = '.' if len(p) == 1 else '/'.join(p[:-1])
523 config = ConfigParser.ConfigParser({'here':root})
524 config.read(config_name)
General Comments 0
You need to be logged in to leave comments. Login now