-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Check every shim in SHIM_PATH instead of just the first one; break once the first diff is found #1452
Conversation
…ween prototype and existing shim file
As an update, I tried the following investigation and wanted to get your thoughts on it. TL;DR Details
Basically, other than the 3-line One final change was that I added a trivial difference to one of my current shim files to trigger the diffing condition in the
When I run
The important part to zero in on is the timestamp. I intentionally set the timestamp of the shim files to a known past date, to see if the final timestamp after the install operation would be today's date. Looks like they aren't, at least on my machine. When I add the same
I get the output I would expect from
Here we can see that the timestamp changes from the pre-determined one (1 Sept 2020) to today's date at the time I'm writing this (8 Oct 2022). Hoping this helps clarify things. I'm happy to take a crack at writing a test to cover this as well, but I might do that tomorrow as my brain is fried for the day lol. Let me know if you have any questions, and thanks for your patience with this word salad of a PR thread. I hope you don't get an email every time there's an update to a comment here, otherwise I may have wrecked your inbox today. 😛 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the in-depth look into this, but the current functionality is intentional. Per the function's documentation:
If the contents of the prototype shim file differ from the contents of the first shim in the shims directory, assume rbenv has been upgraded and the existing shims need to be removed.
All shims in the shims directory will always have the same contents (it's impossible for rbenv rehash
to produce any other result), so it doesn't make sense to check each of them; moreover, running diff
on all the shims will slow down rehash
considerably. Thus, the loop only checks the first one and breaks immediately.
} | ||
|
||
# Registers the name of a shim to be generated. | ||
register_shim() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These functions may not be used in this codebase anymore, but they are kept for backwards compatibility with plugins that may still use them.
TL;DR:
If we only check the first shim in the
SHIM_PATH
directory for diffing (and therefore removal), we might miss some edge cases (for example, if there's no diff w/ the first file but there is a diff with subsequent files). This PR changes theremove_outdated_shims
function so that it checks each shim against the prototype, and if it finds a diff, it removes all the shim files and breaks out of the loop.As a side note, this PR also removes two functions which are no longer used in
rbenv-rehash
.UPDATE:
I now understand the meaning of the comments above
remove_outdated_shims
to mean that we are intentionally only checking the first shim in theSHIM_PATH
directory. That said, is there a chance that theinstall_registered_shims
function could fail mid-way through, updating the first shim(s) in theSHIM_PATH
but leaving subsequent shims un-replaced?If so, I would think a subsequent call to
rbenv rehash
would not perform as expected as long as we're only checking the first shim file, in which case does it make sense to check the diffs of all the shim files, not just the first one? There might be a small chance of that happening, but the question is how bad is the result if it does happen. It seems to me like being unable to update those remaining shims would be a pretty bad result indeed, but y'all are the experts so I defer to you.I'm guessing that
diff
ing only the first shim in the directory is a performance optimization, which makes sense. For what it's worth, I ran this experiment on my local machine and (subjectively) it didn't feel especially slow todiff
on all the gems, but then I only have 97 gems currently installed in~/.rbenv/shims/
so I'm probably not the p99 power-user that you'd want to perf test this against.Details:
It's quite possible I'm in the wrong here, but the way this line of code reads to me, it seems like the
break
statement should be inside theif
check, shouldn't it? As it's currently written, it seems to alwaysbreak
after the first iteration of thefor
-loop. I think I replicated this phenomenon locally, via the following:Here I do the following:
shims
with 4 text files, 3 of which match the prototype and one of which does not.remove_outdated_shims
function into the shell, with only some extra loglines and a counter variable added.$SHIM_PATH
andPROTOTYPE_SHIM_PATH
.In my shell function, the counter only outputs once, and we never see the
about to delete all shims
logline, meaning we didn’t reach the shim whose contents differ from the prototype. Am I missing something, or is this a bug in the code?Just in case, here's a PR to address the issue. If the code already works as intended, I'd love to know what piece of info I appear to be missing. Thanks for maintaining a great tool.