import os import subprocess import dotbot import dotbot.util class Shell(dotbot.Plugin): ''' Run arbitrary shell commands. ''' _directive = 'shell' _has_shown_override_message = False def can_handle(self, directive): return directive == self._directive def handle(self, directive, data): if directive != self._directive: raise ValueError('Shell cannot handle directive %s' % directive) return self._process_commands(data) def _process_commands(self, data): success = True defaults = self._context.defaults().get('shell', {}) options = self._get_option_overrides() for item in data: stdin = defaults.get('stdin', False) stdout = defaults.get('stdout', False) stderr = defaults.get('stderr', False) quiet = defaults.get('quiet', False) if isinstance(item, dict): cmd = item['command'] msg = item.get('description', None) stdin = item.get('stdin', stdin) stdout = item.get('stdout', stdout) stderr = item.get('stderr', stderr) quiet = item.get('quiet', quiet) elif isinstance(item, list): cmd = item[0] msg = item[1] if len(item) > 1 else None else: cmd = item msg = None if msg is None: self._log.lowinfo(cmd) elif quiet: self._log.lowinfo('%s' % msg) else: self._log.lowinfo('%s [%s]' % (msg, cmd)) stdout = options.get('stdout', stdout) stderr = options.get('stderr', stderr) ret = dotbot.util.shell_command( cmd, cwd=self._context.base_directory(), enable_stdin=stdin, enable_stdout=stdout, enable_stderr=stderr ) if ret != 0: success = False self._log.warning('Command [%s] failed' % cmd) if success: self._log.info('All commands have been executed') else: self._log.error('Some commands were not successfully executed') return success def _get_option_overrides(self): ret = {} options = self._context.options() if options.verbose > 1: ret['stderr'] = True ret['stdout'] = True if not self._has_shown_override_message: self._log.debug("Shell: Found cli option to force show stderr and stdout.") self._has_shown_override_message = True return ret