`:config` changes cause symlink'ed config.json files to be replaced by actual files
lnav version v0.12.3
Expected Behaviour
When ~/.config/lnav/config.json is a symlink to another file, using the :config interface to make config changes should update the content of the symlink'ed source file.
Describe the bug
When ~/.config/lnav/config.json is a symlink to another file, using the :config interface causes the symlink to be removed, and replaced with an actual config file. This breaks environments using symlink-based dotfile repositories, such as is implemented by the excellent dotbot project.
To Reproduce
- Create a valid, arbitrary
config.jsonfile somewhere accessible (e.g./tmp/config.json). - Create a symlink to the arbitrary
config.json(e.g. with:ln -s /tmp/config.json ~/.config/lnav/config.json). - Run
lnavand use the:configinterface to make a change. - Observe that
~/.config/lnav/config.json, previously a symlink, has now been replaced with an actual file.
Can you give me an example of a program where this type of thing works?
lnav does an atomic write like most programs and writes to a temp file and then does an atomic rename() to overwrite the original file. I would like a reference to see how other programs handle something like this.
Vim would be the first example that comes to mind, although in our environments we also manage configs for a variety of other tools such as mutt, pine, all of our bash configs, etc.
In the specific case of vim, we have both ~/.vimrc and ~/.vim aliased to /var/data/common/dotfiles/.vimrc and /var/data/common/dotfiles/.vim respectively.
As an example scenario, suppose you use vim itself to edit it's own config file, with this command:
vim ~/.vimrc
(which is actually a symlink to /var/data/common/dotfiles/.vimrc. After saving your changes, were you to then re-source ~/.vimrc or restart vim, the changes would take effect. You could then observe that ~/.vimrc is still a symlink pointing to /var/data/common/dotfiles/.vimrc, which contains your actual changes.
I am unsure how vim is implementing this; Whether it dereferences the symlink at file-opening time, or at the point it saves changes, but it probably doesn't really matter for lnav. Would it suffice to first determine if ~/.config/lnav/config.json is a file or symlink, and if symlink then do your rewrite() on the source file? This would seem to preserve atomicity.