-
-
Notifications
You must be signed in to change notification settings - Fork 329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/shfmt: replaces symlinks with regular files #843
Comments
I think the expected behavior should rather be to skip symbolic links entirely; otherwise In general, if one runs shfmt over an entire source repository, I assume that the symlink targets would already get formatted, so I think skipping the links will generally be fine. Do you want to send a patch with a test? |
-w
is passed
I'm not sure about ignoring symbolic links entirely — if a symbolic link was specified as an explicit parameter then I think it would be surprising for it to be ignored. However, I think you're right that it should be safe to ignore symbolic links when recursing. (I think this is the default for tools like However, this has made me realise the problem is not limited to symbolic links but also occurs with hard links:
I don't think it's feasible to ignore files with hard links; every hard link is semantically identical, unlike symlinks, so it's not possible just to decide to ignore some and not others; and ignoring every file with multiple hard links seems wrong too. It also seems like it would present the same concern for parallelism. I think the behaviour I would like (for both symbolic and hard links) is for the file to be written in-place, preserving any links. However I'm not sure how practical that is (something like reading the file, formatting its contents, then rewinding to the beginning of the file and overwriting it?). On the other hand, I think that breaking hard links (i.e., leaving behind two files) is probably more reasonable than overwriting symlinks, so fixing this behaviour for symlinks and not hard links makes sense. |
Tools like shfmt and gofmt (which shfmt is modelled after) are used on source code, which is generally kept in a VCS like git - and those almost universally do not support hard links, mainly because they aren't portable. So I honestly don't think we need to worry about hard links. Always formatting files passed explicitly is right - I failed to clarify that I meant the "skip" to only kick in when walking directories.
That's an interesting idea that could be more generic to support non-regular files. However:
|
That is, we skip all symlinks when walking, but if the tool gets passed a symlink to a shell file directly, that gets formatted. There's nothing to fix for the original issue beyond adding a test, as we concluded that we want the behavior that's already in place. Fixes #843.
That is, we skip all symlinks when walking, but if the tool gets passed a symlink to a shell file directly, that gets formatted. There's nothing to fix for the original issue beyond adding a test, as we concluded that we want the behavior that's already in place. Fixes #843.
I'm not quite sure if that PR addresses this issue, which was not about walking but about breaking symlinks that are explicitly specified. You mentioned that symlinks should be ignored when walking, and I agree, but I think the correct behaviour for a symlink that is explicitly specified on the commandline would be to format the link target and preserve the link. (That is, for example, |
No, we haven't changed any behavior with symlinks. I thought we already settled that we shouldn't change the behavior with explicit symlink arguments; see the second half of my response in #843 (comment). |
I agree that shfmt should not attempt to preserve hard links, and nor should it follow symlinks found when recursing; but I think the correct behaviour for explicitly-specified symbolic links is to preserve the link and format its target. (Apologies, I think I complicated matters by bringing up hard links which are a very different issue.) Currently if a symbolic link is specified on the command line, shfmt will replace it with a formatted copy of the link target; I'd consider this to be data loss. Actually, I think it would be preferable to ignore symlinks even when they are mentioned on the commandline than to replace a symlink with a regular file. (Note for example that git, at least, and I assume other VCSes do track symbolic links.) It also does not match gofmt's behaviour: as mentioned, gofmt will follow explicitly-specified symlinks and format their target. To repeat my initial example with go instead:
|
To be clear, I never really thought about hard links in my previous responses. They're almost never present in VCS repositories, for example. You're right that gofmt will replace the target. But that's because the way gofmt modifies files is not atomic - it opens the file, reads it, and writes to it in-place. If two gofmt processes run in parallel, they may result in weird parse errors or a corrupted result. I'd also consider replacing the destination of the link to be the wrong behavior, because then
We could certainly refuse to format symlinks given as explicit arguments, with the understanding that we would break the symlink otherwise. I'll reopen for that purpose. |
If
shfmt
is run on a file that is a symbolic link, and writes to that file, it breaks the symbolic link and replaces it with a copy of the original file (formatted accordingly).Expected behaviour would be to write to the underlying file, preserving the symbolic link.
The text was updated successfully, but these errors were encountered: