Wednesday, January 23, 2008

Dotfile replication with subversion

Whenever I got a new *nix account, the first thing I did was copy over dotfiles (.bashrc, .vimrc, .screenrc, etc.). Managing these copies was a pain, since I had to manually replicate changes. For example, if I thought of something clever to add to .vimrc, I had to manually add it to .vimrc on every account. Of course, this meant my dotfiles got hopelessly out of sync. This in turn made copying dotfiles to a new account even more painful, since I had to remember which copies were the latest.

To address this annoyance, I now keep all my dotfiles in a subversion repository. I assume by now everyone knows of subversion. If not, in short, it's a version control system, like CVS. If you don't know what that is either, chances are you're not worried about managing dotfiles.

The process was actually pretty simple, comprising only four steps (I'll assume basic familiarity with subversion, or at least a willingness to read the subversion handbook):

1. Create the subversion repository

See here for creating subversion repositories, and here for serving them. I called my repository "dotfiles".

2. Create the .dotfiles/ directory

I'll assume your most recent dotfiles are all on one account. First, on this account, create a .dotfiles/ directory in your home directory. Then, copy the following shell script to .dotfiles/linkToDotFiles.sh:

~/.dotfiles/linkToDotFiles.sh
#!/bin/sh

SCRIPT_DIR=$(echo $0 | sed -e 's/\(.*\)\/.*/\1/')
SCRIPT_FILE=$(echo $0 | sed -e 's/.*\///')
[ "$SCRIPT_DIR" = "." ] && SCRIPT_DIR=$(pwd)

for F in $(/bin/ls $SCRIPT_DIR | grep -v $SCRIPT_FILE)
do
   echo -n "$SCRIPT_DIR/$F: "
   if [ -e "$HOME/.$F" ]; then
       echo "~/.$F already exists, skipping."
   else
       if ln -s "$SCRIPT_DIR/$F" "$HOME/.$F"; then
           echo "linked to ~/.$F."
       fi
   fi
done

We'll use this script shortly to create symlinks (i.e., shortcuts) from your home directory to dotfiles in the .dotfiles/.

Finally, import .dotfiles/ to your subversion repository

3. Add dotfiles to .dotfiles/ and the repository

First, copy any dotfile you want to replicate to other accounts into .dotfiles/, but renaming them to remove the leading dot. For example, copy .vimrc to .dotfiles/vimrc. You can do the same for configuration directories, like .vim/. Then, add and commit these additions to the repository.

4. Replicate dotfiles to a new account

First, in the home directory of a new account (not the one where you created the .dotfiles/), checkout your repository. This will create a .dotfiles/ directory in the new account.

Then, run the linkToDotfiles.sh script by using this command from your home directory: bash .dotfiles/linkToDotfiles.sh. This creates symlinks in your home directory to files in .dotfiles/. For instance, it will create a symlink from ~/.vimrc to ~/.dotfiles/vimrc.

That's pretty much it. You can add new dotfiles by repeating step 3, and you can modify existing dotfiles and commit them from within .dotfiles/. If you commit changes, you can update .dotfiles/ in each account, which will preserve local, uncommitted modifications.

No comments: