diff --git a/build/mach_bootstrap.py b/build/mach_bootstrap.py index c67637c9412a..fb0dc3272bfa 100644 --- a/build/mach_bootstrap.py +++ b/build/mach_bootstrap.py @@ -131,6 +131,7 @@ def bootstrap(topsrcdir, mozilla_dir=None): os.makedirs(state_env_dir, mode=0o770) print('Please re-run mach.') sys.exit(1) + state_dir = state_env_dir else: if not os.path.exists(state_user_dir): print(STATE_DIR_FIRST_RUN.format(userdir=state_user_dir)) @@ -146,6 +147,7 @@ def bootstrap(topsrcdir, mozilla_dir=None): os.mkdir(state_user_dir) print('Please re-run mach.') sys.exit(1) + state_dir = state_user_dir try: import mach.main @@ -153,7 +155,12 @@ def bootstrap(topsrcdir, mozilla_dir=None): sys.path[0:0] = [os.path.join(mozilla_dir, path) for path in SEARCH_PATHS] import mach.main + def populate_context(context): + context.state_dir = state_dir + mach = mach.main.Mach(topsrcdir) + mach.populate_context_handler = populate_context + for category, meta in CATEGORIES.items(): mach.define_category(category, meta['short'], meta['long'], meta['priority']) diff --git a/python/mach/mach/base.py b/python/mach/mach/base.py index fea6d38869e7..c21962678fd4 100644 --- a/python/mach/mach/base.py +++ b/python/mach/mach/base.py @@ -4,11 +4,16 @@ from __future__ import unicode_literals -from collections import namedtuple -# Holds mach run-time state so it can easily be passed to command providers. -CommandContext = namedtuple('CommandContext', ['topdir', 'cwd', - 'settings', 'log_manager', 'commands']) +class CommandContext(object): + """Holds run-time state so it can easily be passed to command providers.""" + def __init__(self, topdir=None, cwd=None, settings=None, log_manager=None, + commands=None): + self.topdir = topdir + self.cwd = cwd + self.settings = settings + self.log_manager = log_manager + self.commands = commands class MachError(Exception): diff --git a/python/mach/mach/main.py b/python/mach/mach/main.py index 2b6b27334dff..ed22533f5b67 100644 --- a/python/mach/mach/main.py +++ b/python/mach/mach/main.py @@ -127,7 +127,20 @@ class ArgumentParser(argparse.ArgumentParser): @CommandProvider class Mach(object): - """Contains code for the command-line `mach` interface.""" + """Main mach driver type. + + This type is responsible for holding global mach state and dispatching + a command from arguments. + + The following attributes may be assigned to the instance to influence + behavior: + + populate_context_handler -- If defined, it must be a callable. The + callable will be called with the mach.base.CommandContext instance + as its single argument right before command dispatch. This allows + modification of the context instance and thus passing of + arbitrary data to command handlers. + """ USAGE = """%(prog)s [global arguments] command [command arguments] @@ -154,6 +167,8 @@ To see more help for a specific command, run: self.logger = logging.getLogger(__name__) self.settings = ConfigSettings() + self.populate_context_handler = None + self.log_manager.register_structured_logger(self.logger) def load_commands_from_directory(self, path): @@ -303,6 +318,9 @@ To see more help for a specific command, run: settings=self.settings, log_manager=self.log_manager, commands=Registrar) + if self.populate_context_handler: + self.populate_context_handler(context) + handler = getattr(args, 'mach_handler') cls = handler.cls