-
Notifications
You must be signed in to change notification settings - Fork 914
(#1670) Add noshims options for install and upgrade #2003
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
base: master
Are you sure you want to change the base?
Conversation
The --noshims and --noshimsglobal options allow the user to stop shims being created for either the package, or the package and its dependencies. In addition to this new behaviour, the implementation handles the creation and removal of shims more robustly, so that shims from other packages (or the same package) cannot be unintentionally overwritten or removed. The new ShimRegistry class keeps track of the currently installed shims and their corresponding packages. It does this by examining all the exe files in the shim directory (so old-style .bat and unixy shims are not supported) and extracting the target file from the binary. If this target path contains the lib folder, then the package name can be obtained. ShimRegistry is updated for each package, just before the Powershell scripts are run, using `ShimGenerationService::take_snapshot`. When ShimGenerationService installs any shims for the package, ShimRegistry provides its existing shim files (ie. those that were not modified or removed since the last update) so that they can be deleted prior to installing any new ones. To stop shims being added from Install-BinFile, a new environment variable `chocolateyNoShims` is used when running the Powershell scripts. If a package sets a shim this way, but then forgets to call Uninstall-BinFile when uninstalling, the shim will be removed anyway if its target is in the package folder.
@johnstevenson thanks for this - apologies we haven't reviewed it until just now. I'm going to take a look at this and start providing feedback. |
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.
Hi @johnstevenson! This is likely the most complete first time contribution I've ever seen coming to this codebase! This is awesome!
Can I ask that you take a look as a couple of minor things here?
#### when uninstalling a package that forgets to call uninstall bin file | ||
|
||
* should have had a shim | ||
* should have removed the 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.
Awesome, thanks for doing this!
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.
Of course, this only applies to packages that install into ..\chocolatey\lib\<package-name>
, so shims targetting binaries somewhere else would not get removed.
If Shimgen accepted the package name as a parameter and stored this in the shim's FileVersionInfo data (together with the target binary, as suggested elsewhere), then this limitation disappears.
@@ -933,6 +983,16 @@ | |||
* should upgrade the package | |||
* should upgrade where install location reports | |||
|
|||
#### when upgrading a package with shims |
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.
What about when upgrading a package that has existing shims with no shims in the upgrade? What's the expected behavior for that use case?
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.
The default behaviour in install and upgrade scenarios is to remove all shims for the package first, then install any shims if not prohibited by --noshims or --noshimsglobal.
So the existing shims will be removed and the new shims will not be installed.
Write-Debug "Removing any existing shim for `'$name`'." | ||
Uninstall-BinFile $name $path | ||
return | ||
} |
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.
Following my last comment, I see you have code to remove shims if no shims is called. Might be good to add a scenario for that use case
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.
Not quite sure what you want here, so I have added an extra upgrade scenario in b496390
This tests an upgrade to a package that has a shim, with the --noshims flag.
Is this the sort of thing you wanted?
} | ||
|
||
return target; | ||
} |
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.
Ha! That's a very interesting way to get at the data! How does it handle with a large number of shims (300+)?
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.
Guessing a lot better than running and text parsing for sure!
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.
It's fine with a large number of shims (like mingw and other unixy packages), but as I mentioned in Concerns 1 it is hacky and brittle. Far better would be for shimgen to write the target file to a field in its FileVersionInfo data in a simple formatted way. The SpecialBuild
field looks like it would be appropriate location.
We already use this data to check for a shimgen exe anyway:
choco/src/chocolatey/infrastructure.app/domain/ShimRegistry.cs
Lines 189 to 192 in 26ac2df
FileVersionInfo info = FileVersionInfo.GetVersionInfo(exeFile); | |
// note that this will not catch chocolatey specific shims | |
if (!info.ProductName.contains("shimgen")) return item; |
So it would be even faster to grab the target file from info.SpecialBuild
, for example.
{ | ||
this.Log().Error(() => " ShimGen cannot overwrite shim {0} in {1} package".format_with(_fileSystem.get_file_name(file), record.PackageName)); | ||
this.Log().Debug(() => " Shim: {0}{1} Target: {2}{1} New target: {3}{1}".format_with(shimLocation, Environment.NewLine, record.TargetFile, file)); | ||
Environment.ExitCode = 1; |
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.
I'm not sure shim generation would be one of those things I would count as causing an exit code of an error. I would see if enhanced exit codes are turned on and let's specify an exit code specific for this. As in a type of inconclusive installation.
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.
Okay. I'll use enhanced exit code 3 (since 2 has been used for no results)
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.
On second thoughts (or rather getting my head around it again):
I'm not sure shim generation would be one of those things I would count as causing an exit code of an error.
I am actually copying existing behaviour, because an error exit code is specifically returned if shimgen.exe itself fails.
choco/src/chocolatey/infrastructure.app/services/ShimGenerationService.cs
Lines 173 to 176 in 26ac2df
if (exitCode != 0) | |
{ | |
Environment.ExitCode = exitCode; | |
} |
Yeah, the resharper headers tend to put in spaces where none are necessary. That's something we are using a VS extension now to automatically correct for us. The inconsistent line endings we try to fix as we find them. Certainly comes about with multiple editors and contributors bringing things in over the years. 😄 |
NOTE: CLA hub was signed, so new CLA won't be necessary. |
Sorry, I haven't forgotten about this, but it got pushed to the back of a long list of stuff after the initial impetus was lost! Should get around to it later this week. |
@ferventcoder just a tip, you can upload a csv delimited file to cla-assistent with the names of each contributor that have already signed the cla using clahub (if I remember correctly, just put the name github handle of the user seperately on each line, and then run a recheck on the necessary PR's). I think you can also add the date the user signed the cla as well (but that isn't something I have tested). |
@AdmiringWorm the old CLA agreement was with RealDimensions Software, LLC and the new on is with Chocolatey Software, Inc. Legally speaking, that would not be a good thing to do. |
@ferventcoder fair enough, but considering that this is then a new CLA, then legally speaking, I believe it would be appropriate to require users to sign the new CLA before any PR is pulled in. Even in cases where there are open pull requests that had signed the old CLA, the CLA had been changed before the changes were pulled into the codebase. That is just my take on it, though, and I can't speak of what would be required from a legal perspective. But anyway, I was just giving a tip based on what I had done when it had been necessary to sign the CLA for a bot user, and thought it was still the same CLA. |
Updated CLA signed. |
Dear contributor, As this PR seems to have been inactive for 30 days after changes / additional information |
Seems a shame that this has been automatically closed. If you don't want to use it, then no problems at all. However, @ferventcoder did assign this to me: I get that things have changed and this PR might no longer be relevant, but a more personalized closing comment would have been appreciated. |
This was closed automatically. But I'm not entirely sure it should have been. Let me speak to the team tomorrow and update. |
@johnstevenson apologies again about this automatically getting closed, this was caused due to some new infrastructure we have put in place. If you are interested, would you be willing to fix up this PR to re-target the develop branch, and we can look to include this change in an upcoming release of Chocolatey CLI? |
Many thanks for your swift response and re-opening this.
I'm certainly interested, but it is a matter of having the time at the moment. I personally thought that this was a useful addition to the API, so I would appreciate some indication if this is something you would actually use. |
The --noshims and --noshimsglobal options allow the user to stop shims
being created for either the package, or the package and its
dependencies.
In addition to this new behaviour, the implementation handles the
creation and removal of shims more robustly, so that shims from other
packages (or the same package) cannot be unintentionally overwritten or
removed.
The new ShimRegistry class keeps track of the currently installed shims
and their corresponding packages. It does this by examining all the exe
files in the shim directory (so old-style .bat and unixy shims are not
supported) and extracting the target file from the binary. If this
target path contains the lib folder, then the package name can be
obtained.
ShimRegistry is updated for each package, just before the Powershell
scripts are run, using
ShimGenerationService::take_snapshot
. WhenShimGenerationService installs any shims for the package, ShimRegistry
provides its existing shim files (ie. those that were not modified or
removed since the last update) so that they can be deleted prior to
installing any new ones.
To stop shims being added from Install-BinFile, a new environment
variable
chocolateyNoShims
is used when running the Powershellscripts. If a package sets a shim this way, but then forgets to call
Uninstall-BinFile when uninstalling, the shim will be removed anyway if
its target is in the package folder.
Concerns
--shimgen-noop
is way too slow). Better would be if shimgen.exe wrote the data to the file version info: theSpecialBuild
field looks like it would be appropriate.A bit of a moan
I've spent far too much time fighting against trailing whitespace (and occasionally inconsistent line endings) in this repo. That aside, nice work - it's certainly a complex beast.