1
0
Fork 0
mirror of synced 2024-06-28 03:31:09 -04:00
dotbot/dotbot/dispatcher.py
Robin Schneider edc87576ce
Add --no-realpath-base switch to keep symbolic links in BASEDIR
dotbot had a hardcoded behaviour that the BASEDIR was always passed to
os.path.realpath which "returns the canonical path of the specified
filename, eliminating any symbolic links encountered in the path".

This might not always be desirable so this commit makes it configurable
using a command line flag, `--no-realpath-base`.

The use case where `--no-realpath-base` comes in handy is the following:
You want to provide dotfiles in the Filesystem Hierarchy Standard under
`/usr/local/share/ypid_dotfiles/`. Now you want to provide
`.config/dotfiles` as a default in `/etc/skel`. When you now
pre-configure `/etc/skel` by running dotbot in it set has HOME, dotfiles
will refer to `/usr/local/share/ypid_dotfiles/` and not
`/etc/skel/.config/dotfiles` which does not look nice.

This is related to but not the same as the `relative` parameter used
with link commands.
2018-05-21 18:11:28 +02:00

51 lines
1.9 KiB
Python

import os
from .plugin import Plugin
from .messenger import Messenger
from .context import Context
class Dispatcher(object):
def __init__(self, base_directory, base_directory_real_path):
self._log = Messenger()
self._setup_context(base_directory, base_directory_real_path)
self._load_plugins()
def _setup_context(self, base_directory, base_directory_real_path):
path = os.path.abspath(
os.path.expanduser(base_directory))
if base_directory_real_path:
path = os.path.realpath(path)
if not os.path.exists(path):
raise DispatchError('Nonexistent base directory')
self._context = Context(path)
def dispatch(self, tasks):
success = True
for task in tasks:
for action in task:
handled = False
if action == 'defaults':
self._context.set_defaults(task[action]) # replace, not update
handled = True
# keep going, let other plugins handle this if they want
for plugin in self._plugins:
if plugin.can_handle(action):
try:
success &= plugin.handle(action, task[action])
handled = True
except Exception as err:
self._log.error(
'An error was encountered while executing action %s' %
action)
self._log.debug(err)
if not handled:
success = False
self._log.error('Action %s not handled' % action)
return success
def _load_plugins(self):
self._plugins = [plugin(self._context)
for plugin in Plugin.__subclasses__()]
class DispatchError(Exception):
pass