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.
51 lines
1.9 KiB
Python
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
|