Skip to content

Instantly share code, notes, and snippets.

@sakkas-zendesk
Last active June 28, 2023 20:24
Show Gist options
  • Save sakkas-zendesk/b1612de0e7c89f18a81ed744ecc20a1a to your computer and use it in GitHub Desktop.
Save sakkas-zendesk/b1612de0e7c89f18a81ed744ecc20a1a to your computer and use it in GitHub Desktop.
Manage your symlinks in your dotfiles or anywhere [Ruby]

How to

You might need to modify default path for your symlink sources and destinations as per your preferences.

# Where we keep the original files which we track in Git
SRC_BASE = HOME + "/.dotfiles/symlinker/files/"
# Where we place them by default, if there is no override
DST_BASE = HOME + "/"

If your shell does not define ENVIRONMENT, it defaults to work for env: true items. See inventory.yaml for example.

Example structure:

$ tree -a $HOME/.dotfiles/symlinker
symlinker
├── files # Source (your files)
│   ├── .ctags
│   ├── .gitconfig-dotfiles
│   ├── .global_ignore
│   ├── .pryrc
│   ├── .pylintrc
│   ├── .rubocop.yml
│   ├── .tmux.conf
│   ├── home
│   │   ├── .gitconfig
│   │   ├── .zshrc
│   │   └── Rakefile-home-root
│   ├── nvim-init.vim
│   └── work
│       ├── .gitconfig
│       ├── .zshrc
│       └── Rakefile-home-root
└── src # Link-it tool code and its inventory
    ├── inventory.yaml
    └── link_it.rb

Recommend running dry run and verbose mode to see what it will do. [-f|--force] can be used to force replace existing symlinks. Non-forced option can be good in your task-runner or cron to sync dotfiles and create missing symlinks as per inventory.

DRY_RUN=1 VERBOSE=1 ruby link_it.rb -f

Output

cd $HOME/.dotfiles/symlinker/src && DRY_RUN=1 VERBOSE=1 ruby link_it.rb -f
Dry running...
FORCED: /Users/yourname/.dotfiles/symlinker/files/.pryrc => /Users/yourname/.pryrc
FORCED: /Users/yourname/.dotfiles/symlinker/files/.tmux.conf => /Users/yourname/.tmux.conf
FORCED: /Users/yourname/.dotfiles/symlinker/files/.global_ignore => /Users/yourname/.global_ignore
FORCED: /Users/yourname/.dotfiles/symlinker/files/.ctags => /Users/yourname/.ctags
FORCED: /Users/yourname/.dotfiles/symlinker/files/.vim => /Users/yourname/.vim
FORCED: /Users/yourname/.dotfiles/symlinker/files/work/.gitconfig => /Users/yourname/.gitconfig
FORCED: /Users/yourname/.dotfiles/symlinker/files/work/.zshrc => /Users/yourname/.zshrc
FORCED: /Users/yourname/Dev => /Users/yourname/Code
FORCED: /Users/yourname/.dotfiles/symlinker/files/nvim-init.vim => /Users/yourname/.config/nvim/init.vim
FORCED: /Users/yourname/.dotfiles/symlinker/files/.rubocop.yml => /Users/yourname/.rubocop.yml
FORCED: /Users/yourname/.dotfiles/symlinker/files/work/Rakefile-home-root => /Users/yourname/Rakefile
FORCED: /Users/yourname/.dotfiles/symlinker/files/.gitconfig-dotfiles => /Users/yourname/.dotfiles/.git/config
FORCED: /Users/yourname/.private/ssh-config => /Users/yourname/.ssh/config
FORCED: /Users/yourname/.private/keys/ssh/id_rsa => /Users/yourname/.ssh/id_rsa
FORCED: /Users/yourname/.private/keys/ssh/id_rsa.pub => /Users/yourname/.ssh/id_rsa.pub
FORCED: /Users/yourname/.dotfiles/symlinker/files/.pylintrc => /Users/yourname/.pylintrc

As a result you will get your symlinks, this is only a part of an example:

ls -ltrha $HOME | grep '^l'
lrwxr-xr-x    1 yourname  staff    44B May 16 20:53 .vim -> /Users/yourname/.dotfiles/symlinker/files/.vim
lrwxr-xr-x    1 yourname  staff    17B May 16 23:26 Code -> /Users/yourname/Dev
lrwxr-xr-x    1 yourname  staff    46B May 25 12:50 .pryrc -> /Users/yourname/.dotfiles/symlinker/files/.pryrc
lrwxr-xr-x    1 yourname  staff    50B May 25 12:50 .tmux.conf -> /Users/yourname/.dotfiles/symlinker/files/.tmux.conf
lrwxr-xr-x    1 yourname  staff    54B May 25 12:50 .global_ignore -> /Users/yourname/.dotfiles/symlinker/files/.global_ignore
lrwxr-xr-x    1 yourname  staff    46B May 25 12:50 .ctags -> /Users/yourname/.dotfiles/symlinker/files/.ctags
lrwxr-xr-x    1 yourname  staff    55B May 25 12:50 .gitconfig -> /Users/yourname/.dotfiles/symlinker/files/work/.gitconfig
lrwxr-xr-x    1 yourname  staff    51B May 25 12:50 .zshrc -> /Users/yourname/.dotfiles/symlinker/files/work/.zshrc
lrwxr-xr-x    1 yourname  staff    52B May 25 12:50 .rubocop.yml -> /Users/yourname/.dotfiles/symlinker/files/.rubocop.yml
lrwxr-xr-x    1 yourname  staff    63B May 25 12:50 Rakefile -> /Users/yourname/.dotfiles/symlinker/files/work/Rakefile-home-root
lrwxr-xr-x    1 yourname  staff    49B May 25 12:50 .pylintrc -> /Users/yourname/.dotfiles/symlinker/files/.pylintrc

Notes

Will probably need modifications to adapt to your local workflow. Out of box your mileage might vary.

Supported params

Mandatory

# Both need not be same
src: [filename]
dst: [filename]

Optional

env: [true]
override_dst: [true]
override_src: [true]

Why though?

If you setup laptops, VMs, remote workstations often and want to keep consistency between them all, it helps, to some degree. Also you can keep different symlink sources between different 'environments'.

---
symlinks:
- pry:
src: .pryrc
dst: .pryrc
- tmux:
src: .tmux.conf
dst: .tmux.conf
- git-global-ignore:
src: .global_ignore
dst: .global_ignore
- ctags-excludes:
src: .ctags
dst: .ctags
- vim-dir:
src: .vim
dst: .vim
- git-config:
src: .gitconfig
dst: .gitconfig
env: true
- zshrc:
src: .zshrc
dst: .zshrc
env: true
- Code:
override_src: true
src: ${HOME}/Dev
# Implicitly not needed. Just for testing
override_dst: true
dst: ${HOME}/Code
- kubechain:
override_src: true
src: ${HOME}/.private/kubechain
dst: .kubechain
- nvim-init:
src: nvim-init.vim
override_dst: true
dst: ${HOME}/.config/nvim/init.vim
- rubocop-global:
src: .rubocop.yml
dst: .rubocop.yml
- rake:
# This is for running `rake` in your $HOME
# Not to be confused with environment [home|work]
src: Rakefile-home-root
dst: Rakefile
env: true
- dotfiles-gitconfig:
src: .gitconfig-dotfiles
dst: ${HOME}/.dotfiles/.git/config
override_dst: true
- ssh-config:
src: ${HOME}/.private/ssh-config
override_src: true
dst: ${HOME}/.ssh/config
override_dst: true
- ssh-private-key:
src: ${HOME}/.private/keys/ssh/id_rsa
override_src: true
dst: ${HOME}/.ssh/id_rsa
override_dst: true
- ssh-public-key:
src: ${HOME}/.private/keys/ssh/id_rsa.pub
override_src: true
dst: ${HOME}/.ssh/id_rsa.pub
override_dst: true
- pylintrc:
src: .pylintrc
dst: .pylintrc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment