#355·dotbot

New feature: copy/initialize a file instead of linking

Author: denilsonsaCreated Feb 14, 2024Updated Sep 22, 2024

The problem

With the current capabilities of dotbot, I can have a ~/.vim/vimrc file in my dotfiles, and dotbot will correctly create the link. Inside that file, I am sourcing another file ~/.vimrc/vimrc-local, which should contain local changes that should not be stored in the dotfiles. So far, so good.

However, the tricky part is initializing the -local file. It should have a certain structure, it should declare a few functions. In other words, there is some boilerplate it should have.

The proposed solution

I am proposing a new directive: skel (or initialize or seed or copy or copy_without_overwriting or… well, naming is hard!)

It would be declared in a similar way to the link directive, but instead of creating a symlink, it would just copy the file over there. Look:

yaml
- link:
    '~/.vim/vimrc': 'base/.vim/vimrc'
- skel:
    '~/.vim/vimrc-local': 'base/.vim/vimrc-local'

On a fresh machine, the outcome would be:

  • ~/.vim/vimrc~/dotfiles/base/.vim/vimrc (symlink)
  • ~/.vim/vimrc-local (regular file, copied from ~/dotfiles/base/.vim/vimrc)

On subsequent runs on the same machine:

  • ~/.vim/vimrc~/dotfiles/base/.vim/vimrc (the tool ensures the symlink is still correct)
  • ~/.vim/vimrc-local
    • If it still exists, it is not touched at all. It is assumed to have local changes.
    • If it doesn't exist, it is recreated (copied) from ~/dotfiles/base/.vim/vimrc

The proposed behavior reminds me of /etc/skel/.

Additional configuration

Maybe the name should be copy, and it should have the same configuration keys as link:

  • path
  • create parent directories as needed.
  • relink not relevant.
  • force overwrites the existing file. Dangerous, should be off by default, but maybe useful in some exotic configuration. (e.g. A separate YAML config could be used to "reset" a certain application configuration to a known state.)
  • canonicalize, if, ignore-missing
  • glob, exclude, prefix

Alternatives

  1. I keep the -local file in my dotfiles, and I have to remember to copy/create it manually.
  2. I keep the -local file in my dotfiles, and I add some custom shell directive to copy only if it doesn't exist.
  3. I can keep different versions of -local, one for each machine. Many people do that, but it is not desirable for files that contain sensitive information (such as API keys or tokens).
  4. Templating as requested in #117. It has the same drawbacks as alternative 3, plus the additional complexity of requiring additional Python modules.

Compared to the alternatives, the skel/copy solution has the following advantages:

  • Automatic, I don't have to remember to copy it manually.
  • Clean configuration. I don't have to write shell script code inside an YAML file.
  • Easy to learn and easy to understand, as it is very similar to link.
  • Simple to implement, can be implemented using the standard library, should require no additional modules. In fact, most of the behavior would be identical to link.