Hi all, I've been tracking my dot files and related stuff since around 1999, and was very excited to discover this mailing list two years ago. Since then I've only been able to lurk, but finally have a bit of spare time to participate.
Since 2005 I have been using my own (as yet unpublished) Perl suite called "cfgctl" to manage my dot files, which serves a similar to purpose to mr - applying operations such as "checkout", "update" etc. to multiple repositories using multiple VCS backends. However its shortcomings have increasingly irked me, and just when I was being to resign myself to a complete rewrite, I noticed that mr had already stolen most of my thunder :-) The main differences between mr and cfgctl are: - cfgctl's repository meta-data is written in pure Perl (and then require'd at run-time) rather than one or more .INI-style .mrconfig files. When I originally wrote it, needing functionality akin to mr's "skip" parameter I naively thought that this would give me maximum flexibility, and I mistakenly underestimated the value of using a DSL. - cfgctl only has a fixup hook (i.e. post-checkout/update), and no hooks for any other actions. - cfgctl is not nearly as extensible. It doesn't support writing arbitrary new actions either globally or per repo. - With hindsight cfgctl should have been made more shell-oriented in general, because the kinds of tasks required for managing dot files/repos, building/install packages etc. are much more easily achieved in shell than in Perl. - Adding support for a new VCS backend is more work in cfgctl, because it requires writing a new Perl subclass of Cfg::Pkg::Base. - cfgctl is harder to type than 'mr'. So far mr is clearly winning :-) However, cfgctl does have one or two tricks up its sleeve: - Config modules / packages / repositories / whatever you want to call them are indexed by name within a unique namespace, rather than by directory path, and packages are grouped together into sections. This allows you to easily run any of the actions on: - all the packages (just like running mr from $HOME) - a single package, just by specifying its name without needing to know where it lives, e.g. "cfgctl --update zsh" would update just the zsh repository - a section (i.e. group of packages) just by specifying its name (e.g. "CLI" or "mail" or "Xorg") without needing to know where anything lives, e.g. "cfgctl --pull Xorg" would update all repos containing config relating to my Xorg (previously X11) environment - any packages matching a regular expression e.g. "cfgctl --update /emacs/" - cfgctl integrates out of the box with GNU stow. Based on this list's frequency of discussion on "fake bare" / detached git repos, it seems that most people here have an aversion to the symlink approach to managing dot files in $HOME. This surprises me as I have been using them very successfully for 12 years, although I will leave that debate for another thread. - cfgctl's internals have a reasonable amount of pod / comments. mr's code, whilst mostly self-explanatory at the high-level, does have a few very long subroutines which I feel would gain clarity by being refactored into some appropriately-named smaller subs. All in all, I feel that mr has a better design than cfgctl, and has greater longevity. So last night I spent an hour or two doing a quick proof of concept, to see whether I could extend mr to implement the functionality I require, in particular the integration with GNU stow. I'm pleased to say that so far it's looking very promising :-) This is pretty much all that's needed: --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- [DEFAULT] lib = STOW_DIR=$HOME/.cfg STOW_TARGET=$HOME MR_NAME="`basename $MR_REPO`" # set_stow_common_opts () { STOW_PKG_PATH="$STOW_DIR/$MR_NAME" stow_common_opts="-t $STOW_TARGET -d $STOW_DIR" } # install () { set_stow_common_opts ensure_symlink_exists "$STOW_PKG_PATH" "${MR_REPO%/}" } # ensure_symlink_exists () { [ $# = 2 ] || error "CONFIG BUG: Usage: ensure_symlink_exists SYMLINK TARGET" symlink="$1" required_target="$2" if [ -L "$symlink" ]; then actual_target="`readlink $symlink`" if [ "$actual_target" = "$required_target" ]; then return else error "Symlink $symlink already points to $actual_target, cannot point to $required_target; aborting." fi fi [ -e "$symlink" ] && error "Cannot create symlink $symlink - already exists; aborting." ln -s "$required_target" "$symlink" } # stow () { set_stow_common_opts command stow $stow_common_opts "$MR_NAME" } restow () { set_stow_common_opts command stow -R -p $stow_common_opts "$MR_NAME" } unstow () { set_stow_common_opts command stow -D -p $stow_common_opts "$MR_NAME" } post_checkout = install && stow post_update = install && restow unstow = unstow --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- However, I am already beginning to miss the lack of a native namespace for repo identifiers. For example, I would far rather type mr update zsh emacs than mr -c ~/.config/mr/config.d/zsh update mr -c ~/.config/mr/config.d/emacs update If CLI parameters following the action verb are already reserved for being passed on to the underlying VCS backend, then something like this might be appropriate: mr -f zsh,emacs update The identifier could be declared simply in the config via a special 'name' parameter. The following example shows one of the situations in which you might need the name to differ from the basename of the repository path ($MR_REPO). --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- [$HOME/.git-repos/zsh] name = zsh.git [$HOME/.cvs-working-dirs/zsh] name = zsh.cvs --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- Similar functionality for grouping multiple repos together could be achieved by something like: --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- [$HOME/.config/mr/groups.d/CLI] checkout = true include = cat ~/.config/mr/config.d/{zsh,emacs} --------- 8< --------- 8< --------- 8< --------- 8< --------- 8< --------- invoked via mr -c ~/.config/mr/groups.d/CLI update although that's kind of ugly. Native support would be nicer, e.g. mr -g CLI update I'd love to hear anyone's thoughts on these suggestions! Cheers, Adam _______________________________________________ vcs-home mailing list vcs-home@lists.madduck.net http://lists.madduck.net/listinfo/vcs-home