From daf8d82e02c2bcc476932790fa25076631c4c312 Mon Sep 17 00:00:00 2001 From: Anish Athalye Date: Sun, 14 Feb 2016 22:39:48 -0500 Subject: [PATCH] Add functionality to create relative links 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. --- README.md | 15 ++++++++------- plugins/link.py | 12 +++++++++--- test/tests/link-relative.bash | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 test/tests/link-relative.bash diff --git a/README.md b/README.md index 00c654d..3ed74f5 100644 --- a/README.md +++ b/README.md @@ -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: @@ -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" } }, @@ -147,7 +147,7 @@ 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 @@ -155,8 +155,9 @@ 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 @@ -164,8 +165,8 @@ or directory should be forcibly linked. - link: ~/.config/terminator: create: true - path: config/terminator/ - ~/.vim: vim/ + path: config/terminator + ~/.vim: vim ~/.vimrc: relink: true path: vimrc diff --git a/plugins/link.py b/plugins/link.py index 429158d..3bb5686 100644 --- a/plugins/link.py +++ b/plugins/link.py @@ -23,6 +23,7 @@ class Link(dotbot.Plugin): 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) @@ -33,8 +34,9 @@ class Link(dotbot.Plugin): 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: @@ -101,7 +103,7 @@ class Link(dotbot.Plugin): 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. @@ -115,7 +117,11 @@ class Link(dotbot.Plugin): (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: diff --git a/test/tests/link-relative.bash b/test/tests/link-relative.bash new file mode 100644 index 0000000..ac55c17 --- /dev/null +++ b/test/tests/link-relative.bash @@ -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 <