Add functionality to overwrite broken links
This commit adds an option to the extended configuration syntax for linking files and directories. The relink option is a safe alternative to forcibly linking that only removes broken symbolic links, so it cannot result in data loss.
This commit is contained in:
parent
db8364490d
commit
3725d21684
2 changed files with 22 additions and 10 deletions
|
@ -131,8 +131,9 @@ Link commands support an (optional) extended configuration. In this type of
|
||||||
configuration, instead of specifying source locations directly, targets are
|
configuration, instead of specifying source locations directly, targets are
|
||||||
mapped to extended configuration dictionaries. These dictionaries map `path` to
|
mapped to extended configuration dictionaries. These dictionaries map `path` to
|
||||||
the source path, specify `create` as `true` if the parent directory should be
|
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
|
created if necessary, specify `relink` as `true` if incorrect symbolic links
|
||||||
should be forcibly linked.
|
should be automatically overwritten, and specify `force` as `true` if the file
|
||||||
|
or directory should be forcibly linked.
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
|
@ -142,7 +143,9 @@ should be forcibly linked.
|
||||||
create: true
|
create: true
|
||||||
path: config/terminator/
|
path: config/terminator/
|
||||||
~/.vim: vim/
|
~/.vim: vim/
|
||||||
~/.vimrc: vimrc
|
~/.vimrc:
|
||||||
|
relink: true
|
||||||
|
path: vimrc
|
||||||
~/.zshrc:
|
~/.zshrc:
|
||||||
force: true
|
force: true
|
||||||
path: zshrc
|
path: zshrc
|
||||||
|
|
|
@ -23,11 +23,14 @@ class Linker(Executor):
|
||||||
# extended config
|
# extended config
|
||||||
path = source['path']
|
path = source['path']
|
||||||
force = source.get('force', False)
|
force = source.get('force', False)
|
||||||
|
relink = source.get('relink', False)
|
||||||
create = source.get('create', False)
|
create = source.get('create', False)
|
||||||
if create:
|
if create:
|
||||||
success &= self._create(destination)
|
success &= self._create(destination)
|
||||||
if force:
|
if force:
|
||||||
success &= self._delete(path, destination)
|
success &= self._delete(path, destination, force=True)
|
||||||
|
elif relink:
|
||||||
|
success &= self._delete(path, destination, force=False)
|
||||||
else:
|
else:
|
||||||
path = source
|
path = source
|
||||||
success &= self._link(path, destination)
|
success &= self._link(path, destination)
|
||||||
|
@ -71,23 +74,29 @@ class Linker(Executor):
|
||||||
self._log.lowinfo('Creating directory %s' % parent)
|
self._log.lowinfo('Creating directory %s' % parent)
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def _delete(self, source, path):
|
def _delete(self, source, path, force):
|
||||||
success = True
|
success = True
|
||||||
source = os.path.join(self._base_directory, source)
|
source = os.path.join(self._base_directory, source)
|
||||||
if ((self._is_link(path) and self._link_destination(path) != source) or
|
if ((self._is_link(path) and self._link_destination(path) != source) or
|
||||||
(self._exists(path) and not self._is_link(path))):
|
(self._exists(path) and not self._is_link(path))):
|
||||||
fullpath = os.path.expanduser(path)
|
fullpath = os.path.expanduser(path)
|
||||||
|
removed = False
|
||||||
try:
|
try:
|
||||||
if os.path.islink(fullpath):
|
if os.path.islink(fullpath):
|
||||||
os.unlink(fullpath)
|
os.unlink(fullpath)
|
||||||
elif os.path.isdir(fullpath):
|
removed = True
|
||||||
|
elif force:
|
||||||
|
if os.path.isdir(fullpath):
|
||||||
shutil.rmtree(fullpath)
|
shutil.rmtree(fullpath)
|
||||||
|
removed = True
|
||||||
else:
|
else:
|
||||||
os.remove(fullpath)
|
os.remove(fullpath)
|
||||||
|
removed = True
|
||||||
except OSError:
|
except OSError:
|
||||||
self._log.warning('Failed to remove %s' % path)
|
self._log.warning('Failed to remove %s' % path)
|
||||||
success = False
|
success = False
|
||||||
else:
|
else:
|
||||||
|
if removed:
|
||||||
self._log.lowinfo('Removing %s' % path)
|
self._log.lowinfo('Removing %s' % path)
|
||||||
return success
|
return success
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue