If you are at all like me, you have customized configuration files for various CLI programs, so-called “dotfiles” such as ~/.zshrc or ~/.vimrc. If you use more than one computer system, you probably re-use these dotfiles on many of them. Unfortunately, this can make management of the dotfiles, and keeping them up-to-date on differing systems, challenging. Particularly if you use them on a large number of computers.
One solution is to use version control to manage these files, such as with subversion, CVS, or git. This can easily be accomplished by making a subversion repository for storing these files. For instance, on a “master” system that is accessible by the others (via ssh, perhaps), create the repository and store the files in it. A working copy of the repository might exist in ~/svn/configs/ with sub-directories for each type of dotfile: ~/svn/configs/zsh, ~/svn/configs/procmail, ~/svn/configs/zsh, and so on.
Using subversion as a means of distributing these files to varying computers works well, but copying files and keeping them up-to-date may be cumbersome. You could use symlinks so that the actual dotfile points to the working copy: such as symlinking ~/.zshrc to ~/svn/configs/zsh/zshrc.
Another method is to use the standard “make” command to manage them. This solution takes a bit of time to set up at the outset, but only really has to be done once (and updated for new dotfiles you may create later). What follows is an example Makefile that would be placed in the top-level directory of the working copy, such as ~/svn/configs/Makefile:
# Makefile to update dot-files
# $Id$
ifndef SRCDIR
SRCDIR := $(shell pwd)
endif
DOTDIRS = $(shell find . -type d -depth 1 \! -name .svn | cut -d ‘/’ -f 2 )
REPO_FETCHMAILRC = $(SRCDIR)/fetchmail/fetchmailrc
LOCAL_FETCHMAILRC = $(HOME)/.fetchmailrc
REPO_ZSHRC = $(SRCDIR)/zsh/zshrc
REPO_ZSHENV = $(SRCDIR)/zshenv
REPO_ZSH_HOSTS = $(SRCDIR)/zsh_hosts
LOCAL_ZSHRC = $(HOME)/.zshrc
LOCAL_ZSHENV = $(HOME)/.zshenv
LOCAL_ZSH_HOSTS = $(HOME)/.zsh_hosts
.PHONY: fetchmail zsh
fetchmail:
@test -d $(SRCDIR)/fetchmail || ( echo “fetchmail sourcedir does not exist!” ; exit 1 )
cp -afv $(REPO_FETCHMAILRC) $(LOCAL_FETCHMAILRC)
fetchmail-diff:
@test -d $(SRCDIR)/fetchmail || ( echo “fetchmail sourcedir does not exist!” ; exit 1 )
@diff -uN $(REPO_FETCHMAILRC) $(LOCAL_FETCHMAILRC) || ( echo “”)
fetchmail-commit:
@test -d $(SRCDIR)/fetchmail || ( echo “fetchmail sourcedir does not exist!” ; exit 1 )
svn commit $(SRCDIR)/fetchmail
fetchmail-updaterepo:
@test -d $(SRCDIR)/fetchmail || ( echo “fetchmail sourcedir does not exist!” ; exit 1 )
cp -afv $(LOCAL_FETCHMAILRC) $(REPO_FETCHMAILRC)
zsh:
@test -d $(SRCDIR)/zsh || ( echo “zsh sourcedir does not exist!” ; exit 1 )
cp -afv $(REPO_ZSHRC) $(LOCAL_ZSHRC)
cp -afv $(REPO_ZSHENV) $(LOCAL_ZSHENV)
cp -afv $(REPO_ZSH_HOSTS) $(LOCAL_ZSH_HOSTS)
zsh-diff:
@test -d $(SRCDIR)/zsh || ( echo “zsh sourcedir does not exist!” ; exit 1 )
@diff -uN $(REPO_ZSHRC) $(LOCAL_ZSHRC) || ( echo “”)
@diff -uN $(REPO_ZSHENV) $(LOCAL_ZSHENV) || ( echo “”)
@diff -uN $(REPO_ZSH_HOSTS) $(LOCAL_ZSH_HOSTS) || ( echo “”)
zsh-commit:
@test -d $(SRCDIR)/zsh || ( echo “zsh sourcedir does not exist!” ; exit 1 )
svn commit $(SRCDIR)/zsh
zsh-updaterepo:
@test -d $(SRCDIR)/zsh || ( echo “zsh sourcedir does not exist!” ; exit 1 )
cp -fv $(LOCAL_ZSHRC) $(REPO_ZSHRC)
cp -fv $(LOCAL_ZSHENV) $(REPO_ZSHENV)
cp -fv $(LOCAL_ZSH_HOSTS) $(REPO_ZSH_HOSTS)
install: fetchmail zsh
diff: fetchmail-diff zsh-diff
commit: fetchmail-commit zsh-commit
updaterepo: fetchmail-updaterepo zsh-updaterepo
help:
@echo “Usage: make <target>”
@echo “Available targets are:”
@echo “help Show this text”
@echo “install Install all dotfiles”
@echo “diff Diff all dotfiles”
@echo “updaterepo Update repository from local dotfiles”
@echo “”
@echo “The following dotfiles are available for use with the below commands:”
@echo ” $(DOTDIRS)”
@echo “”
@echo “[dotfile]-install Install [dotfile] configs”
@echo “[dotfile]-diff Diff local [dotfile] configs to that in repository working copy”
@echo “[dotfile]-commit Commit [dotfile] from working copy to repository”
@echo “[dotfile]-updaterepo Update working copy for [dotfile] from local files”
This Makefile handles zsh and fetchmail and allows for a variety of functions (use “make help” if you need a refresher of the commands). With it, you can manage all the dotfiles at once using the “make install” or “make diff” commands. You can also operate on single dotfile types alone with “make zsh-install” or “make fetchmail-commit”. This Makefile, of course, assumes the use of subversion and also assumes you are in ~/svn/configs/ (or wherever it is installed) when you call it.
The REPO_* and LOCAL_* variables are pointers to the various dotfiles, used largely to reduce typing in the Makefile. The Makefile itself is quite self-explanatory and can easily be customized to handle all kinds of files. There may be more efficient ways to create dynamic assignments to reduce the size and complexity of the Makefile; if you have any suggestions for improvement, please share them.
Delivered each Tuesday, TechRepublic’s free Linux and Open Source newsletter provides tips, articles, and other resources to help you hone your Linux skills. Automatically sign up today!