Managing dotfiles with GNU Stow
taihen.org
taihen.org
Please application developers, follow the XDG Base Directory spec (or the equivalent in Windows and Mac OS X).
See https://specifications.freedesktop.org/basedir-spec/basedir-... and https://wiki.archlinux.org/index.php/XDG_Base_Directory_supp...
Whereas classical Unix applications simply have one easy to identify dotfile in ~/.
It may be subjective. I don't like the XDG specs. Have you peeked in to OS X $HOME/Library? That's what you end up having. (Let's not talk about windows registries, but I guess systemd people like it.) Is that any better than dot files under $HOME? Hardly so.
ZDOTDIR="${XDG_CONFIG_HOME}/zsh"
in `/etc/zshrc`, then moving all miscellaneous files to the same place: # ~/.config/zsh/.zshenv
export HISTFILE="${ZDOTDIR}/history"
# ~/.config/.zshrc
compinit -d ${ZDOTDIR}/zcompdump
zstyle ':completion:*' cache-path "${ZDOTDIR}/cache"
## separate files for easier and quicker editing:
for file in $ext_files; do
[[ -f ${ZDOTDIR}/${file} ]] && source ${ZDOTDIR}/${file}
done
This method removed quite a few files (history, compdump, cache, zkbd, zshrc, zshenv, zprofile, zlogin, etc.) from my home dir.I'm sure bash has something similar, but like you said, it would be nice if programs didn't junk up $HOME by default.
ZDOTDIR="${XDG_CONFIG_HOME}/zsh"
Congratulations, you have just broken your zsh configuration.
$XDG_CONFIG_HOME may not be set (e.g. when logging with SSH or in console, and
even not always in X11).I guess I assumed people would not read my post and then start editing a system-wide shell config file unless they knew what they were doing.
But if someone did manage to "break" their shell this way, recovery would be trivial because they will still be able to login and the shell will still run, they just might not have all of their configs loaded.
I also often hear it's confusing and hard to follow correctly (which is true) so I'll make it simple: if you are an app author now, please don't use dot files in $HOME. Instead:
* ${XDG_CONFIG_HOME:-~/.config}/<appname>/ for your app's configuration directory
* ${XDG_CACHE_HOME:-~/.cache}/<appname>/ for your app's cache directory (in other words, all files which are safe to delete at any time without impact)
* ${XDG_DATA_HOME:-~/.local/share}/<appname>/ for your app's data files directory. If you're confused about what this is, just use the former two, no big deal.
*
git tracks modifications to your dotfiles. And on the rare occasion that you need to add a new file, just force-add it: git add -f ~/.foorc
If you need a script to "install" your dotfiles, you're doing it wrong.I've been using stow for years to manage my dotfiles and it's never been more involved than
$ stow dotfiles/urxvt
or what have you. In fact I would say that managing a git repository is more of a waste of time and far more over-engineered for a task easily solved by a tiny binary.
Not sure what you're referring to by an 'install script', have you ever used stow?
In any case, the real answer is that you should be using whatever works best for your use case, and for me that's stow.
Undefined subroutine &main::error called at /usr/bin/stow line 568, <DATA> line 18.
where line 568 of /usr/bin/stow is: error("Slashes are not permitted in package names");
What version of stow do you have? I'm using stow 2.2.0-r2 on Gentoo Linux.>A package directory is the root of a tree containing the installation image for a particular package. Each package directory must reside in a stow directory — e.g., the package directory /usr/local/stow/perl must reside in the stow directory /usr/local/stow. The name of a package is the name of its directory within the stow directory — e.g., perl.
https://www.gnu.org/software/stow/manual/stow.html
The article in the OP also doesn't use this format. Instead it's prefaced with a `cd` command, so you would need to do:
cd foo; stow barexport GIT_CEILING_DIRECTORIES=~
to your .bashrc (or equivalent)
If your project has its own .git directory, no, it won't add to ~/.git.
So I have a script that manages the symlinks for multiple such repos, knows to remove the broken links as needed, and I have something I can just paste into the terminal of any machine and it'll set that box up with my public/work/private dotfiles as appropriate.
It's not perfect, but it works, just pointing out that even for relatively simple cases having a dotfile manager (or writing your own) can make sense.
My .bashrc will run a bootstrap_work_dotfiles function when bash starts: https://github.com/avar/dotfiles/blob/master/.bashrc#L410
This then clones my ~/g/avar-dotfiles-work repo if I'm at work and it hasn't been cloned: https://github.com/avar/dotfiles/blob/master/.bashrc#L355
I have a "dud" function (dotfile update) function that'll update both, it basically does a git pull, re-chmods ~/.ssh/config: https://github.com/avar/dotfiles/blob/master/.bashrc#L381
And also, and what you asked for, removes any stale symlinks via this one-liner: https://github.com/avar/dotfiles/blob/master/.bashrc#L348
Basically doing a find on my ~ directory and finding any broken links pointing to the known location of the overlay repo.
I see now that there's a potential bug in it where it narrows its search in such a way that it could miss it if you add/remove new ~/.??* files. This could be solved, but I have it like that because I only ever add/remove stuff in e.g. ~/.bashrc.d/ or ~/.screenrc.d/, so this way the find takes less time to run.
Then I have a generated one-liner that I can paste into new machines that clones my dotfiles.git into ~/g/, moves the .git to ~/, then sources bashrc which bootstraps the rest.
The problem was I wanted something I could easily install on effectively any system, including live servers, without needing to install dependencies or otherwise change the underlying global system state. Stow manages to solve this beautifully as pretty much all Unix-like systems do have a Perl interpreter and Stow has no unusual dependencies beyond the core runtime. That, and it can be included in your dotfiles collection itself, so you can literally "stow stow" to "bootstrap" itself and then carry along!
If anyone's interested you can find my dotfiles below which may be nice as reference material if you're wanting to "stow-ify" your dotfiles. I've also written some Bash scripts to automatically stow the available components on a given system (dot-manage) and easily fetch updates from an upstream repository, re-run component detection and update Vim bundles via Vundle (dot-update). There's also a metadata-esque system which augments detection of which components are available for where simply checking if a binary named after the relevant folder exists on the system is insufficient (e.g. for libraries like readline).
Works very well for keeping my configuration synced between multiple machines (via git).
My `update.sh` script does un-and-re-`stow`ing:
The only change I'd make is to deploy by copying (and not by symlinking).
But then you lose any changes you make to those files...
I didn't see it in what I read (honestly I just breezed through it), does this prevent secret keys from being uploaded accidentally?
git init
git remote add origin ...
git fetch origin
git checkout -t origin/masterNow if I could only figure out an equally good method for managing my ssh keys...
A small tip for those working on locked-down systems: if you can't install GNU Stow, you can use XStow[1] instead. It is a C++ version of Stow (instead of Perl). It is very easy to build and has very few (if any) dependencies.
It also works great when you create git submodules for your external dependencies and manage installing them via stow.
Turns out .gitignore is on the default ignore list. But you if you add a .stow-local-ignore file to the directory where your .gitignore is then it works.
Uninstalled and stuck with my 5 line shell script.