summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rw-r--r--dotbot/executor/linker.py23
2 files changed, 22 insertions, 10 deletions
diff --git a/README.md b/README.md
index 86f7686..c2c46f3 100644
--- a/README.md
+++ b/README.md
@@ -131,8 +131,9 @@ Link commands support an (optional) extended configuration. In this type of
configuration, instead of specifying source locations directly, targets are
mapped to extended configuration dictionaries. These dictionaries map `path` to
the source path, specify `create` as `true` if the parent directory should be
-created if necessary, and specify `force` as `true` if the file or directory
-should be forcibly linked.
+created if necessary, specify `relink` as `true` if incorrect symbolic links
+should be automatically overwritten, and specify `force` as `true` if the file
+or directory should be forcibly linked.
#### Example
@@ -142,7 +143,9 @@ should be forcibly linked.
create: true
path: config/terminator/
~/.vim: vim/
- ~/.vimrc: vimrc
+ ~/.vimrc:
+ relink: true
+ path: vimrc
~/.zshrc:
force: true
path: zshrc
diff --git a/dotbot/executor/linker.py b/dotbot/executor/linker.py
index 9821fe7..f0e94bc 100644
--- a/dotbot/executor/linker.py
+++ b/dotbot/executor/linker.py
@@ -23,11 +23,14 @@ class Linker(Executor):
# extended config
path = source['path']
force = source.get('force', False)
+ relink = source.get('relink', False)
create = source.get('create', False)
if create:
success &= self._create(destination)
if force:
- success &= self._delete(path, destination)
+ success &= self._delete(path, destination, force=True)
+ elif relink:
+ success &= self._delete(path, destination, force=False)
else:
path = source
success &= self._link(path, destination)
@@ -71,24 +74,30 @@ class Linker(Executor):
self._log.lowinfo('Creating directory %s' % parent)
return success
- def _delete(self, source, path):
+ def _delete(self, source, path, force):
success = True
source = os.path.join(self._base_directory, source)
if ((self._is_link(path) and self._link_destination(path) != source) or
(self._exists(path) and not self._is_link(path))):
fullpath = os.path.expanduser(path)
+ removed = False
try:
if os.path.islink(fullpath):
os.unlink(fullpath)
- elif os.path.isdir(fullpath):
- shutil.rmtree(fullpath)
- else:
- os.remove(fullpath)
+ removed = True
+ elif force:
+ if os.path.isdir(fullpath):
+ shutil.rmtree(fullpath)
+ removed = True
+ else:
+ os.remove(fullpath)
+ removed = True
except OSError:
self._log.warning('Failed to remove %s' % path)
success = False
else:
- self._log.lowinfo('Removing %s' % path)
+ if removed:
+ self._log.lowinfo('Removing %s' % path)
return success
def _link(self, source, link_name):