mirror of
1
0
Fork 0

Add functionality to forcibly link items

This commit introduces an extended configuration syntax for linking
files and directories. Currently, this syntax allows for specifying
items to be forcibly linked, overwriting existing files or directories
if necessary.

The extended configuration syntax was proposed by Travers McInerney
<travers@mcinerney.me>.
This commit is contained in:
Anish Athalye 2014-10-22 13:27:34 -04:00
parent 58e4fb50b1
commit 13c925be87
2 changed files with 39 additions and 3 deletions

View File

@ -91,6 +91,8 @@ have a defined ordering.
### Link
Link commands specify how files and directories should be symbolically linked.
If desired, items can be specified to be forcibly linked, overwriting existing
files if necessary.
#### Format
@ -99,13 +101,23 @@ locations. Source locations are specified relative to the base directory (that
is specified when running the installer). Source directory names should contain
a trailing "/" character.
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, and specify "force" as true if the file or directory should be
forcibly linked.
##### Example
```json
{
"link": {
"~/.vimrc": "vimrc",
"~/.vim": "vim/"
"~/.vim": "vim/",
"~/.zshrc": {
"path": "zshrc",
"force": true
}
}
}
```

View File

@ -1,4 +1,4 @@
import os
import os, shutil
from . import Executor
class Linker(Executor):
@ -19,7 +19,15 @@ class Linker(Executor):
def _process_links(self, links):
success = True
for destination, source in links.items():
success &= self._link(source, destination)
if isinstance(source, dict):
# extended config
path = source['path']
force = source.get('force', False)
if force:
success &= self._delete(destination)
else:
path = source
success &= self._link(path, destination)
if success:
self._log.info('All links have been set up')
else:
@ -47,6 +55,22 @@ class Linker(Executor):
path = os.path.expanduser(path)
return os.path.exists(path)
def _delete(self, path):
success = True
if self._exists(path) and not self._is_link(path):
fullpath = os.path.expanduser(path)
try:
if os.path.isdir(fullpath):
shutil.rmtree(fullpath)
else:
os.remove(fullpath)
except OSError:
self._log.warning('Failed to remove %s' % path)
success = False
else:
self._log.lowinfo('Removing %s' % path)
return success
def _link(self, source, link_name):
'''
Links link_name to source.