summaryrefslogtreecommitdiff
path: root/dotbot/plugins/clean.py
diff options
context:
space:
mode:
Diffstat (limited to 'dotbot/plugins/clean.py')
-rw-r--r--dotbot/plugins/clean.py57
1 files changed, 57 insertions, 0 deletions
diff --git a/dotbot/plugins/clean.py b/dotbot/plugins/clean.py
new file mode 100644
index 0000000..7e6cba1
--- /dev/null
+++ b/dotbot/plugins/clean.py
@@ -0,0 +1,57 @@
+import os, dotbot
+
+class Clean(dotbot.Plugin):
+ '''
+ Cleans broken symbolic links.
+ '''
+
+ _directive = 'clean'
+
+ def can_handle(self, directive):
+ return directive == self._directive
+
+ def handle(self, directive, data):
+ if directive != self._directive:
+ raise ValueError('Clean cannot handle directive %s' % directive)
+ return self._process_clean(data)
+
+ def _process_clean(self, targets):
+ success = True
+ defaults = self._context.defaults().get(self._directive, {})
+ force = defaults.get('force', False)
+ for target in targets:
+ if isinstance(targets, dict):
+ force = targets[target].get('force', force)
+ success &= self._clean(target, force)
+ if success:
+ self._log.info('All targets have been cleaned')
+ else:
+ self._log.error('Some targets were not successfully cleaned')
+ return success
+
+ def _clean(self, target, force):
+ '''
+ Cleans all the broken symbolic links in target if they point to
+ a subdirectory of the base directory or if forced to clean.
+ '''
+ if not os.path.isdir(os.path.expanduser(target)):
+ self._log.debug('Ignoring nonexistent directory %s' % target)
+ return True
+ for item in os.listdir(os.path.expanduser(target)):
+ path = os.path.join(os.path.expanduser(target), item)
+ if not os.path.exists(path) and os.path.islink(path):
+ points_at = os.path.join(os.path.dirname(path), os.readlink(path))
+ if self._in_directory(path, self._context.base_directory()) or force:
+ self._log.lowinfo('Removing invalid link %s -> %s' % (path, points_at))
+ os.remove(path)
+ else:
+ self._log.lowinfo('Link %s -> %s not removed.' % (path, points_at))
+ return True
+
+ def _in_directory(self, path, directory):
+ '''
+ Returns true if the path is in the directory.
+ '''
+ directory = os.path.join(os.path.realpath(directory), '')
+ path = os.path.realpath(path)
+ return os.path.commonprefix([path, directory]) == directory