2022-04-30 21:19:22 -04:00
|
|
|
import glob
|
2022-04-30 21:46:09 -04:00
|
|
|
import os
|
|
|
|
import subprocess
|
2020-08-22 19:02:26 -04:00
|
|
|
import sys
|
2020-12-02 22:49:17 -05:00
|
|
|
from argparse import ArgumentParser, RawTextHelpFormatter
|
2022-04-30 21:46:09 -04:00
|
|
|
|
|
|
|
import dotbot
|
|
|
|
|
2014-03-19 23:07:30 -04:00
|
|
|
from .config import ConfigReader, ReadingError
|
|
|
|
from .dispatcher import Dispatcher, DispatchError
|
2022-04-30 21:46:09 -04:00
|
|
|
from .messenger import Level, Messenger
|
2022-04-30 21:19:22 -04:00
|
|
|
from .plugins import Clean, Create, Link, Shell
|
2016-01-16 22:00:15 -05:00
|
|
|
from .util import module
|
2014-03-19 23:07:30 -04:00
|
|
|
|
2022-01-30 18:48:30 -05:00
|
|
|
|
2014-03-19 23:07:30 -04:00
|
|
|
def add_options(parser):
|
2022-01-30 18:48:30 -05:00
|
|
|
parser.add_argument(
|
|
|
|
"-Q", "--super-quiet", action="store_true", help="suppress almost all output"
|
|
|
|
)
|
|
|
|
parser.add_argument("-q", "--quiet", action="store_true", help="suppress most output")
|
|
|
|
parser.add_argument(
|
|
|
|
"-v",
|
|
|
|
"--verbose",
|
|
|
|
action="count",
|
|
|
|
default=0,
|
|
|
|
help="enable verbose output\n"
|
|
|
|
"-v: typical verbose\n"
|
|
|
|
"-vv: also, set shell commands stderr/stdout to true",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-d", "--base-directory", help="execute commands from within BASEDIR", metavar="BASEDIR"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-c", "--config-file", help="run commands given in CONFIGFILE", metavar="CONFIGFILE"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"-p",
|
|
|
|
"--plugin",
|
|
|
|
action="append",
|
|
|
|
dest="plugins",
|
|
|
|
default=[],
|
|
|
|
help="load PLUGIN as a plugin",
|
|
|
|
metavar="PLUGIN",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--disable-built-in-plugins", action="store_true", help="disable built-in plugins"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--plugin-dir",
|
|
|
|
action="append",
|
|
|
|
dest="plugin_dirs",
|
|
|
|
default=[],
|
|
|
|
metavar="PLUGIN_DIR",
|
|
|
|
help="load all plugins in PLUGIN_DIR",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--only", nargs="+", help="only run specified directives", metavar="DIRECTIVE"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--except", nargs="+", dest="skip", help="skip specified directives", metavar="DIRECTIVE"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--force-color", dest="force_color", action="store_true", help="force color output"
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--no-color", dest="no_color", action="store_true", 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",
|
|
|
|
)
|
|
|
|
|
2014-03-19 23:07:30 -04:00
|
|
|
|
|
|
|
def read_config(config_file):
|
|
|
|
reader = ConfigReader(config_file)
|
|
|
|
return reader.get_config()
|
|
|
|
|
2022-01-30 18:48:30 -05:00
|
|
|
|
2014-03-19 23:07:30 -04:00
|
|
|
def main():
|
|
|
|
log = Messenger()
|
|
|
|
try:
|
2020-12-02 22:49:17 -05:00
|
|
|
parser = ArgumentParser(formatter_class=RawTextHelpFormatter)
|
2014-03-19 23:07:30 -04:00
|
|
|
add_options(parser)
|
|
|
|
options = parser.parse_args()
|
2018-05-30 09:41:55 -04:00
|
|
|
if options.version:
|
2021-02-27 14:34:52 -05:00
|
|
|
try:
|
|
|
|
with open(os.devnull) as devnull:
|
2022-01-30 18:48:30 -05:00
|
|
|
git_hash = subprocess.check_output(
|
|
|
|
["git", "rev-parse", "HEAD"],
|
|
|
|
cwd=os.path.dirname(os.path.abspath(__file__)),
|
|
|
|
stderr=devnull,
|
2023-07-09 14:51:45 -04:00
|
|
|
).decode("ascii")
|
2022-01-30 18:48:30 -05:00
|
|
|
hash_msg = " (git %s)" % git_hash[:10]
|
2021-02-27 14:34:52 -05:00
|
|
|
except (OSError, subprocess.CalledProcessError):
|
2022-01-30 18:48:30 -05:00
|
|
|
hash_msg = ""
|
|
|
|
print("Dotbot version %s%s" % (dotbot.__version__, hash_msg))
|
2018-05-30 09:41:55 -04:00
|
|
|
exit(0)
|
2016-01-16 22:00:15 -05:00
|
|
|
if options.super_quiet:
|
2014-03-19 23:07:30 -04:00
|
|
|
log.set_level(Level.WARNING)
|
2016-01-16 22:00:15 -05:00
|
|
|
if options.quiet:
|
2014-03-19 23:07:30 -04:00
|
|
|
log.set_level(Level.INFO)
|
2020-12-02 22:49:17 -05:00
|
|
|
if options.verbose > 0:
|
2014-03-19 23:07:30 -04:00
|
|
|
log.set_level(Level.DEBUG)
|
2020-08-22 19:02:26 -04:00
|
|
|
|
|
|
|
if options.force_color and options.no_color:
|
|
|
|
log.error("`--force-color` and `--no-color` cannot both be provided")
|
|
|
|
exit(1)
|
|
|
|
elif options.force_color:
|
|
|
|
log.use_color(True)
|
|
|
|
elif options.no_color:
|
2018-10-06 19:08:26 -04:00
|
|
|
log.use_color(False)
|
2020-08-22 19:02:26 -04:00
|
|
|
else:
|
|
|
|
log.use_color(sys.stdout.isatty())
|
|
|
|
|
2022-04-30 21:19:22 -04:00
|
|
|
plugins = []
|
2016-01-16 22:00:15 -05:00
|
|
|
plugin_directories = list(options.plugin_dirs)
|
|
|
|
if not options.disable_built_in_plugins:
|
2022-04-30 21:19:22 -04:00
|
|
|
plugins.extend([Clean, Create, Link, Shell])
|
2016-01-16 22:00:15 -05:00
|
|
|
plugin_paths = []
|
|
|
|
for directory in plugin_directories:
|
2022-01-30 18:48:30 -05:00
|
|
|
for plugin_path in glob.glob(os.path.join(directory, "*.py")):
|
|
|
|
plugin_paths.append(plugin_path)
|
2016-01-16 22:00:15 -05:00
|
|
|
for plugin_path in options.plugins:
|
|
|
|
plugin_paths.append(plugin_path)
|
|
|
|
for plugin_path in plugin_paths:
|
|
|
|
abspath = os.path.abspath(plugin_path)
|
2022-04-30 21:19:22 -04:00
|
|
|
plugins.extend(module.load(abspath))
|
2018-05-30 09:41:55 -04:00
|
|
|
if not options.config_file:
|
2022-01-30 18:48:30 -05:00
|
|
|
log.error("No configuration file specified")
|
2018-05-30 09:41:55 -04:00
|
|
|
exit(1)
|
2018-05-24 12:00:13 -04:00
|
|
|
tasks = read_config(options.config_file)
|
2020-06-25 15:56:42 -04:00
|
|
|
if tasks is None:
|
2022-01-30 18:48:30 -05:00
|
|
|
log.warning("Configuration file is empty, no work to do")
|
2020-06-25 15:56:42 -04:00
|
|
|
tasks = []
|
2015-04-26 19:46:14 -04:00
|
|
|
if not isinstance(tasks, list):
|
2022-01-30 18:48:30 -05:00
|
|
|
raise ReadingError("Configuration file must be a list of tasks")
|
2018-05-30 09:41:55 -04:00
|
|
|
if options.base_directory:
|
2020-01-03 16:07:44 -05:00
|
|
|
base_directory = os.path.abspath(options.base_directory)
|
2018-05-30 09:41:55 -04:00
|
|
|
else:
|
|
|
|
# default to directory of config file
|
2020-01-03 16:07:44 -05:00
|
|
|
base_directory = os.path.dirname(os.path.abspath(options.config_file))
|
2018-05-30 09:41:55 -04:00
|
|
|
os.chdir(base_directory)
|
2022-01-30 18:48:30 -05:00
|
|
|
dispatcher = Dispatcher(
|
|
|
|
base_directory,
|
|
|
|
only=options.only,
|
|
|
|
skip=options.skip,
|
|
|
|
exit_on_failure=options.exit_on_failure,
|
|
|
|
options=options,
|
2022-04-30 21:19:22 -04:00
|
|
|
plugins=plugins,
|
2022-01-30 18:48:30 -05:00
|
|
|
)
|
2014-03-19 23:07:30 -04:00
|
|
|
success = dispatcher.dispatch(tasks)
|
|
|
|
if success:
|
2022-01-30 18:48:30 -05:00
|
|
|
log.info("\n==> All tasks executed successfully")
|
2014-03-19 23:07:30 -04:00
|
|
|
else:
|
2022-01-30 18:48:30 -05:00
|
|
|
raise DispatchError("\n==> Some tasks were not executed successfully")
|
2014-03-19 23:07:30 -04:00
|
|
|
except (ReadingError, DispatchError) as e:
|
2022-01-30 18:48:30 -05:00
|
|
|
log.error("%s" % e)
|
2014-03-19 23:07:30 -04:00
|
|
|
exit(1)
|
2014-07-19 03:12:51 -04:00
|
|
|
except KeyboardInterrupt:
|
2022-01-30 18:48:30 -05:00
|
|
|
log.error("\n==> Operation aborted")
|
2014-07-19 03:12:51 -04:00
|
|
|
exit(1)
|