diff --git a/dotbot/cli.py b/dotbot/cli.py index 8883a6b..6c8ee43 100644 --- a/dotbot/cli.py +++ b/dotbot/cli.py @@ -42,6 +42,8 @@ def add_options(parser): help='disable color output') parser.add_argument('--version', action='store_true', help='show program\'s version number and exit') + parser.add_argument('-x', '--exit-on-failure', dest='exit_on_failure', action='store_true', + help='exit after first failed directive') def read_config(config_file): reader = ConfigReader(config_file) @@ -107,7 +109,8 @@ def main(): # default to directory of config file base_directory = os.path.dirname(os.path.abspath(options.config_file)) os.chdir(base_directory) - dispatcher = Dispatcher(base_directory, only=options.only, skip=options.skip, options=options) + dispatcher = Dispatcher(base_directory, only=options.only, skip=options.skip, + exit_on_failure=options.exit_on_failure, options=options) success = dispatcher.dispatch(tasks) if success: log.info('\n==> All tasks executed successfully') diff --git a/dotbot/dispatcher.py b/dotbot/dispatcher.py index 856befa..afeca96 100644 --- a/dotbot/dispatcher.py +++ b/dotbot/dispatcher.py @@ -5,12 +5,14 @@ from .messenger import Messenger from .context import Context class Dispatcher(object): - def __init__(self, base_directory, only=None, skip=None, options=Namespace()): + def __init__(self, base_directory, only=None, skip=None, exit_on_failure=False, + options=Namespace()): self._log = Messenger() self._setup_context(base_directory, options) self._load_plugins() self._only = only self._skip = skip + self._exit = exit_on_failure def _setup_context(self, base_directory, options): path = os.path.abspath( @@ -36,16 +38,27 @@ class Dispatcher(object): for plugin in self._plugins: if plugin.can_handle(action): try: - success &= plugin.handle(action, task[action]) + local_success = plugin.handle(action, task[action]) + if not local_success and self._exit: + # The action has failed exit + self._log.error('Action %s failed' % action) + return False + success &= local_success handled = True except Exception as err: self._log.error( 'An error was encountered while executing action %s' % action) self._log.debug(err) + if self._exit: + # There was an execption exit + return False if not handled: success = False self._log.error('Action %s not handled' % action) + if self._exit: + # Invalid action exit + return False return success def _load_plugins(self): diff --git a/test/tests/exit-on-failure.bash b/test/tests/exit-on-failure.bash new file mode 100644 index 0000000..b55bbe9 --- /dev/null +++ b/test/tests/exit-on-failure.bash @@ -0,0 +1,19 @@ +test_description='test exit on failure' +. '../test-lib.bash' + +test_expect_success 'setup' ' +echo "apple" > ${DOTFILES}/f +' + +test_expect_failure 'run' ' +run_dotbot -x <