About this post

I have procrastinated for a while upgrading to Sierra. No moment was good enough to start the task.

The reason behind the lack of energy was quite simple: setting up my environment from scratch is painful so I decided to setup my own dotfiles, and document it in this post:

Discovery phase

Don’t reinvent the wheel, don’t reinvent the wheel…

I had a look at the dotfiles of smart-ruby guys like Thoughtbot and Zach Holman, but they exceeded my real needs because they were full of smart stuff I didn’t fully understand / need.

So, I decided to cherry-pick a few ideas from them and reinvent another wheel.

What is rcm

Thoughtbot uses a really interesting tool named rcm to automate the creation of the rc-files, so I adopted this cute piece of software for the foundation of my dotfiles.

RCM stands for rc file management. It is a management suite for dotfiles.

brew tap thoughtbot/formulae
brew install rcm

Register existing rc files.

You can register existing rc-files with mkrc(1):

$ mkrc .gitconfig
$ mkrc .gitignore
$ mkrc .gitmessage
...
$ ls -la | grep git
  .gitconfig -> /Users/pmanrubia/.dotfiles/gitconfig
  .gitignore -> /Users/pmanrubia/.dotfiles/gitignore
  .gitmessage -> /Users/pmanrubia/.dotfiles/gitmessage
  ...

From now on those files are stored in $HOME/.dotfiles: they are symlinked from the $HOME folder.

Register new rc files

You can register new rcfiles using rcup(1).

~ touch ~/.dotfiles/rspec
~ rcup
~ ls -la ~ | grep rspec
~ .rspec -> /Users/pmanrubia/.dotfiles/rspec

This is what rcup did:

  1. Create a symlink in your home folder to the new file
  2. Add a dot prefix to the symlink

Adapt rcm to your own needs with rcrc

I have a two folders in $HOME/.dotfiles that I want to be copied without the `.` prefix. So I have updated the rcrc file to ignore bin and config.

# $HOME/.dotfiles/rcrc
UNDOTTED="bin config"

An example: oh-my-zsh configuration

My oh-my-zsh setup is quite simple. I rely on a config folder where I setup the environment, alias, paths and rbenv.

These files are sourced from $HOME/.dotfiles/zshrc, and automatically symlinked in my home folder when running rcup(1).

# $HOME/.dotfiles/zshrc
export ZSH=~/.oh-my-zsh

source $ZSH/oh-my-zsh.sh
source ~/config/env
source ~/config/alias
source ~/config/paths
source ~/config/rbenv

From now on, runing `rcup` will do the heavylifting.

Homebrew-bundle for packages

As other Mac users I have chosen Homebrew as my package manager, so I was very happy to find out that I can automate the installation of packages and apps using a master file. Something similar to Gemfiles for Rails apps:

# ~/.dotfile/Brewfile
tap 'Homebrew/bundle'
brew 'autojump'
brew 'git'
brew 'rcm'
brew 'gitup'
brew 'tmux'

# Zsh
$ brew bundle
Succeeded in tapping homebrew/bundle
Succeeded in installing autojump
Succeeded in installing git
Succeeded in installing rcm
Succeeded in installing gitup
Succeeded in installing tmux

Success: 5 Fail: 0

Really easy and portable!

Homebrew-bundle for MacOS apps

Interestingly the same approach works for MacOS Apps

# ~/.dotfile/Brewfile
mas 'TaskPaper', id: 424281111
mas '1Password', id: 443987910

$ brew install mas # should go on your Brewfile :)
$ brew bundle

# Zsh
$ brew bundle
Succeeded in installing TaskPaper
Succeeded in installing 1Password

Success: 2 Fail: 0

Backups

There are a few things that are important to me in order to have a seamless transition after a reinstalling everything from scratch:

  1. My Zsh history
  2. My Rubymine configuration

So, I have created scripts to back up those documents. I have chosen a simple approach: copy them into an iCloud folder.

# zsh backup
sourceFile=~/.zsh_history
targetFile=.../zsh_history-$(date +"%Y_%m_%d_%H_%M_%S").txt
cp "$sourceFile" "$targetFile"

One command to rule them all

Finally, I have created a command that runs everything:

  1. Update dotfiles following rcm rules
  2. Update/install packages and apps described in the Brewfile
  3. Backup important stuff
# ~/.dotfiles/bin/dotme
rcup -v
(cd ~/.dotfiles && brew bundle)
backup-history
backup-rubymine