lnav icon indicating copy to clipboard operation
lnav copied to clipboard

`:config` changes cause symlink'ed config.json files to be replaced by actual files

Open tubiakou opened this issue 8 months ago • 2 comments

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

  1. Create a valid, arbitrary config.json file somewhere accessible (e.g. /tmp/config.json).
  2. Create a symlink to the arbitrary config.json (e.g. with: ln -s /tmp/config.json ~/.config/lnav/config.json).
  3. Run lnav and use the :config interface to make a change.
  4. Observe that ~/.config/lnav/config.json, previously a symlink, has now been replaced with an actual file.

tubiakou avatar Jun 13 '25 15:06 tubiakou

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.

tstack avatar Jun 14 '25 04:06 tstack

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.

tubiakou avatar Jun 15 '25 15:06 tubiakou