Skip to content

Commit

Permalink
Add functionality to create relative links
Browse files Browse the repository at this point in the history
This commit adds an option to the extended configuration syntax for
linking files and directories. Enabling the relative option makes it so
that symbolic links are created with relative paths instead of absolute
paths.
  • Loading branch information
anishathalye committed Feb 15, 2016
1 parent c402396 commit daf8d82
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 10 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ The conventional name for the configuration file is `install.conf.yaml`.
- link:
~/.dotfiles: ''
~/.tmux.conf: tmux.conf
~/.vim: vim/
~/.vim: vim
~/.vimrc: vimrc

- shell:
Expand All @@ -104,7 +104,7 @@ The conventional name for this file is `install.conf.json`.
"link": {
"~/.dotfiles": "",
"~/.tmux.conf": "tmux.conf",
"~/.vim": "vim/",
"~/.vim": "vim",
"~/.vimrc": "vimrc"
}
},
Expand Down Expand Up @@ -147,25 +147,26 @@ files if necessary. Environment variables in paths are automatically expanded.

Link commands are specified as a dictionary mapping targets to source
locations. Source locations are specified relative to the base directory (that
is specified when running the installer). Source directory names should contain
is specified when running the installer). Directory names should *not* 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, specify `create` as `true` if the parent directory should be
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.
should be automatically overwritten, specify `force` as `true` if the file or
directory should be forcibly linked, and specify `relative` as `true` if the
symbolic link should have a relative path.

#### Example

```yaml
- link:
~/.config/terminator:
create: true
path: config/terminator/
~/.vim: vim/
path: config/terminator
~/.vim: vim
~/.vimrc:
relink: true
path: vimrc
Expand Down
12 changes: 9 additions & 3 deletions plugins/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def _process_links(self, links):
if isinstance(source, dict):
# extended config
path = source['path']
relative = source.get('relative', False)
force = source.get('force', False)
relink = source.get('relink', False)
create = source.get('create', False)
Expand All @@ -33,8 +34,9 @@ def _process_links(self, links):
elif relink:
success &= self._delete(path, destination, force=False)
else:
relative = False
path = source
success &= self._link(path, destination)
success &= self._link(path, destination, relative)
if success:
self._log.info('All links have been set up')
else:
Expand Down Expand Up @@ -101,7 +103,7 @@ def _delete(self, source, path, force):
self._log.lowinfo('Removing %s' % path)
return success

def _link(self, source, link_name):
def _link(self, source, link_name, relative):
'''
Links link_name to source.
Expand All @@ -115,7 +117,11 @@ def _link(self, source, link_name):
(link_name, self._link_destination(link_name)))
elif not self._exists(link_name) and self._exists(source):
try:
os.symlink(source, os.path.expanduser(link_name))
destination = os.path.expanduser(link_name)
if relative:
destination_dir = os.path.dirname(destination)
source = os.path.relpath(source, destination_dir)
os.symlink(source, destination)
except OSError:
self._log.warning('Linking failed %s -> %s' % (link_name, source))
else:
Expand Down
36 changes: 36 additions & 0 deletions test/tests/link-relative.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
test_description='relative linking works'
. '../test-lib.bash'

test_expect_success 'setup' '
echo "apple" > ${DOTFILES}/f &&
mkdir ${DOTFILES}/d &&
echo "grape" > ${DOTFILES}/d/e
'

test_expect_success 'run' '
run_dotbot <<EOF
- link:
~/.f:
path: f
~/.frel:
path: f
relative: true
~/nested/.frel:
path: f
create: true
relative: true
~/.d:
path: d
relative: true
EOF
'

test_expect_success 'test' '
grep "apple" ~/.f &&
grep "apple" ~/.frel &&
[[ "$(readlink ~/.f)" == "$(readlink -f dotfiles/f)" ]] &&
[[ "$(readlink ~/.frel)" == "dotfiles/f" ]] &&
[[ "$(readlink ~/nested/.frel)" == "../dotfiles/f" ]] &&
grep "grape" ~/.d/e &&
[[ "$(readlink ~/.d)" == "dotfiles/d" ]]
'

0 comments on commit daf8d82

Please sign in to comment.