SuperCuber / dotter

A dotfile manager and templater written in rust 🦀
The Unlicense
882 stars 46 forks source link

[BUG] dotter recurses into symlinks that point to directories #92

Closed dead10ck closed 2 years ago

dead10ck commented 2 years ago

Environment

Description

One thing I tend to do with my stow repos is to have relative symlinks that point to other parts of my system (e.g. to configure a runtime directory to point to a development version in a separate git repo). When I stow this, it works just fine: it creates a symlink at the target that points back to the dotfile repo, which in turn points back to the real target.

However, it seems dotter recurses into the symlink that's in the dotfile repo and tries to make a target for everything under there.

Reproduction

  1. Make a dotter folder
  2. Inside, make a folder foo
  3. Inside foo, symlink to anther directory on the system
  4. Make an entry in global.toml for it and deploy

Expected behavior

Dotter should make a symlink to the symlink in the package

Actual behavior

Dotter recurses into the directory and tries to symlink every file it finds

This can also lead to an infinite recursion if the symlink is a parent of the directory it's in.

SuperCuber commented 2 years ago

The dotter folder is supposed to be typically checked into source control, and I find it kinda strange to have symlinks In a repository pointing outside of it... I'm not sure I understand your use case.

But regardless, the PR you spotted would help you since you could disable recursing into the specific folders you need. I think it's abandoned at this point.

dead10ck commented 2 years ago

My current use case is a text editor called Helix. It has a "runtime" directory in ~/.config/helix/runtime that stores some config and other files that are needed at runtime to support syntax highlighting and other features. I work on the code base, and so I have the source code checked out in another directory on my system, in which the repo's development version of this directory lives. So I make a symlink from ~/.config/helix/runtime → ~/src/helix/runtime. But I want to put the dotfile manager in between here to check in this link so that I don't have to remember to do it when I set up a new machine.

Another example use case is if you want to be able to use vim and neovim with the same config file, so you'd make a symlink from ~/.config/nvim → ~/.vim. This example wouldn't even have to be outside the repo: it could be a link within the repo.

Yet another would be if you were using Ansible and wanted to use a locally checked out version of a role, so you'd make ~/.ansible/roles/myrole → ~/src/myrole.

It's really not that exotic. The dotfile repo is meant for personal configs, so having symlinks to point outside the repo isn't necessarily a bad thing.

Also #89 is related, since it could be used to fix the issue on a case-by-case basis, but it doesn't solve the issue in the general sense, because symlinks are a thing that can be checked into git, so this can be an issue any time dotter encounters a symlink. There may be cases where a user's tool makes the symlink in the config directory on their behalf, and the user wasn't even aware that a symlink might be in there when they move it into their dotfile repo.

SuperCuber commented 2 years ago

But I want to put the dotfile manager in between here to check in this link so that I don't have to remember to do it when I set up a new machine.

This wouldn't work since you don't have the ~/src/helix/runtime repo cloned yet on your new machine so you need to remember it anyways :P I would solve this differently but I see the value of supporting this.

In case you would like to contribute a PR for this, it should be simple enough to implement - the relevant function is here https://github.com/SuperCuber/dotter/blob/2bbb519dec3de5f3bd6ba10240709994ea9afd4a/src/config.rs#L479

This might impact other code that might not expect entries to be directories - in that case https://github.com/SuperCuber/dotter/blob/2bbb519dec3de5f3bd6ba10240709994ea9afd4a/src/filesystem.rs#L714 is a good starting point

dead10ck commented 2 years ago

Cool, thanks for the pointer of where to start! I might try my hand at this when I get some free time. Are you comfortable with changing this behavior, though? I think technically it is a breaking change. And if someone does have their repo in such a state that a symlink was followed, will dotter handle the change correctly, i.e. remove all of the symlinks it made by following, and replace it with one at the level of the symlink?

SuperCuber commented 2 years ago

I think technically it is a breaking change

I doubt this situation is very common but the solution would be to 1. Bump minor version 2. Explain it in the changelog

will dotter handle the change correctly, i.e. remove all of the symlinks it made by following, and replace it with one at the level of the symlink?

The logic is built around handling those kinds of changes well, but that should be tested when developing the patch of course.