summaryrefslogtreecommitdiff
path: root/dotbot
diff options
context:
space:
mode:
authorAnish Athalye <me@anishathalye.com>2014-06-08 11:30:10 -0700
committerAnish Athalye <me@anishathalye.com>2014-06-08 11:32:45 -0700
commitabb825048b348e3892902fa92df1edacd3dd248f (patch)
tree204149781376e1bea4a0e776b410e5ae94dc9343 /dotbot
parent24f49603c8aeb7161ad83ff792dfa63baadb7362 (diff)
Add Cleaner executor
Diffstat (limited to 'dotbot')
-rw-r--r--dotbot/executor/__init__.py1
-rw-r--r--dotbot/executor/cleaner.py49
2 files changed, 50 insertions, 0 deletions
diff --git a/dotbot/executor/__init__.py b/dotbot/executor/__init__.py
index 1762f78..d87ca4b 100644
--- a/dotbot/executor/__init__.py
+++ b/dotbot/executor/__init__.py
@@ -1,3 +1,4 @@
from .executor import Executor
from .linker import Linker
+from .cleaner import Cleaner
from .commandrunner import CommandRunner
diff --git a/dotbot/executor/cleaner.py b/dotbot/executor/cleaner.py
new file mode 100644
index 0000000..59b9259
--- /dev/null
+++ b/dotbot/executor/cleaner.py
@@ -0,0 +1,49 @@
+import os
+from . import Executor
+
+class Cleaner(Executor):
+ '''
+ 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('Cleaner cannot handle directive %s' % directive)
+ return self._process_clean(data)
+
+ def _process_clean(self, targets):
+ success = True
+ for target in targets:
+ success &= self._clean(target)
+ if success:
+ self._log.info('All targets have been cleaned')
+ else:
+ self._log.error('Some targets were not succesfully cleaned')
+ return success
+
+ def _clean(self, target):
+ '''
+ Cleans all the broken symbolic links in target that point to
+ a subdirectory of the base directory.
+ '''
+ 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):
+ if self._in_directory(path, self._base_directory):
+ self._log.lowinfo('Removing invalid link %s -> %s' %
+ (path, os.path.join(os.path.dirname(path), os.readlink(path))))
+ os.remove(path)
+ 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