mirror of
1
0
Fork 0

Add Cleaner executor

This commit is contained in:
Anish Athalye 2014-06-08 11:30:10 -07:00
parent 24f49603c8
commit abb825048b
3 changed files with 58 additions and 3 deletions

View File

@ -88,8 +88,9 @@ Configuration
------------- -------------
Dotbot uses json-formatted configuration files to let you specify how to set up Dotbot uses json-formatted configuration files to let you specify how to set up
your dotfiles. Currently, Dotbot knows how to `link` files and execute `shell` your dotfiles. Currently, Dotbot knows how to `link` files, execute `shell`
commands. Dotbot executes tasks in the order that they are specified in. commands, and `clean` directories of broken symbolic links. Dotbot executes
tasks in the order that they are specified in.
**Ideally, bootstrap configurations should be idempotent. That is, the **Ideally, bootstrap configurations should be idempotent. That is, the
installer should be able to be run multiple times without causing any installer should be able to be run multiple times without causing any
@ -100,7 +101,8 @@ dictionary that contains a command name mapping to data for that command. For
`link`, you specify how files should be linked in a dictionary. For `shell`, `link`, you specify how files should be linked in a dictionary. For `shell`,
you specify an array consisting of commands, where each command is an array you specify an array consisting of commands, where each command is an array
consisting of the shell command as the first element and a description as the consisting of the shell command as the first element and a description as the
second. second. For `clean`, you specify an array consisting of targets, where each
target is a path to a directory.
Dotbot is aware of a base directory (that is specified when running the Dotbot is aware of a base directory (that is specified when running the
installer), so link targets can be specified relative to that, and shell installer), so link targets can be specified relative to that, and shell
@ -111,6 +113,9 @@ started. The convention for configuration file names is `install.conf.json`.
```json ```json
[ [
{
"clean": ["~"]
},
{ {
"link": { "link": {
"~/.tmux.conf": "tmux.conf", "~/.tmux.conf": "tmux.conf",

View File

@ -1,3 +1,4 @@
from .executor import Executor from .executor import Executor
from .linker import Linker from .linker import Linker
from .cleaner import Cleaner
from .commandrunner import CommandRunner from .commandrunner import CommandRunner

View File

@ -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