dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.71k stars 1.07k forks source link

'Dotnet tool restore' doesn't update toolResolverCache file #20043

Open RomanTimv opened 3 years ago

RomanTimv commented 3 years ago

I have two folders. Each folder has dotnet-tools.json and NuGet.config where defined place for packages in the folder.

I call dotnet tool restore from first folder. Package is downloaded into first folder and its path is saved to file in c:\Users\.dotnet\toolResolverCache\1\

Then I delete first folder and call dotnet tool restore from second folder. Package is downloaded to second folder, but in toolResolverCache remains path to first folder. Tool can't be runned, it asks for restore.

dsplaisted commented 3 years ago

@wli3 for triage

wli3 commented 3 years ago

This is by design. We don't plan to support custom nuget global package folder location (we expect both project would share the same nuget directory). In this case, you can use dotnet tool install --tool-path NAME to achieve better isolation

RomanTimv commented 3 years ago

The issue is if dotnet tool restore doesn't find tool in saved location, it downloads it into another location but tries to run it from saved.

So tool doesn't work if it was somehow deleted from location saved in cache and default location for tools is changed. And only way to restore it is manually delete tool description file from toolResolverCache or part of this file. And it's not obvious solution at all. I had to debug dotnet sources to find out about toolResolverCache folder.

0x53A commented 3 years ago

If this is by design, then your design might not be perfect.

At the least please document these issues in https://docs.microsoft.com/en-us/nuget/reference/nuget-config-file.

We are currently using a globalPackagesFolder inside the repository, and this causes a lot of issues on the buildservers, where multiple builds are running in parallel and the repositories are in randomized locations.

After learning about this, I'll try to rework our build to no longer set globalPackagesFolder.

sliekens commented 8 months ago

This is also a problem when you use the machine-wide NUGET_PACKAGES environment variable.

Repro steps on Windows using command prompt:

  1. mkdir repro
  2. cd repro
  3. dotnet new tool-manifest
  4. set NUGET_PACKAGES=%cd%\packages
  5. dotnet tool install dotnetsay
  6. dotnet dotnetsay ok should work correctly
  7. dotnet nuget locals global-packages --clear
  8. set NUGET_PACKAGES=%cd%\packages2
  9. dotnet tool restore downloads the tool again to packages2
  10. dotnet dotnetsay fails because toolResolverCache is not updated

Deleting the toolResolverCache folder is the only way to make the tool work again.

image

Sorry, but this cannot be by design, rather lack thereof.

OkkeHendriks commented 5 months ago

I am having a similar problem on a build server, but instead of the environment variable my NuGet global packages folder is set through the NuGet.config file:

<config>
    <add key="globalPackagesFolder" value="packages" />
</config>

On certain bamboo build agents the cache is (apparently) wrong, I am not sure how it got corrupted:

D:\some-folder>dotnet tool list --local
Package Id                             Version      Commands             Manifest
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
dotnet-reportgenerator-globaltool      5.0.0        reportgenerator      D:\some-folder\.config\dotnet-tools.json
fantomas                               6.2.3        fantomas             D:\some-folder\.config\dotnet-tools.json

D:\some-folder>tree packages
D:\some-folder\PACKAGES
+---dotnet-reportgenerator-globaltool
    +---5.0.0
        +---tools
            +---net5.0
            �   +---any
            +---net6.0
            �   +---any
            +---netcoreapp3.1
                +---any

D:\some-folder>tree C:\Users\some-user\.nuget\packages\dotnet-reportgenerator-globaltool
C:\USERS\some-user\.NUGET\PACKAGES\DOTNET-REPORTGENERATOR-GLOBALTOOL
+---5.0.2
    +---tools
        +---net5.0
        �   +---any
        +---net6.0
        �   +---any
        +---netcoreapp3.1
            +---any

D:\some-folder>dotnet nuget locals all --list
http-cache: C:\Users\some-user\AppData\Local\NuGet\v3-cache
global-packages: D:\some-folder\packages
temp: C:\Users\some-user\AppData\Local\Temp\NuGetScratch
plugins-cache: C:\Users\some-user\AppData\Local\NuGet\plugins-cache

D:\some-folder>type C:\Users\some-user\.dotnet\toolResolverCache\1\dotnet-reportgenerator-globaltool
[{"Version":"5.0.0","TargetFramework":"net6.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.0.0\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.0.2","TargetFramework":"net6.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.0.2\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.1.4","TargetFramework":"net6.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.1.4\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.1.9","TargetFramework":"net6.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.1.9\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.0.0","TargetFramework":"net7.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.0.0\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.1.9","TargetFramework":"net7.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.1.9\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.0.2","TargetFramework":"net7.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.0.2\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.1.4","TargetFramework":"net7.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.1.4\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.0.0","TargetFramework":"net8.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.0.0\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.1.9","TargetFramework":"net8.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.1.9\\tools/net6.0/any/ReportGenerator.dll"},
 {"Version":"5.0.2","TargetFramework":"net8.0","RuntimeIdentifier":"any","Name":"reportgenerator","Runner":"dotnet","PathToExecutable":"C:\\Users\\some-user\\.nuget\\packages\\dotnet-reportgenerator-globaltool\\5.0.2\\tools/net6.0/any/ReportGenerator.dll"}]
D:\some-folder>dotnet reportgenerator -h
Run "dotnet tool restore" to make the "reportgenerator" command available

I believe the only solution/workaround is currently to install it always in a, never changing, shared global directory, otherwise 'my' install might set the cache to a project specific path which will be cleaned-up (by bamboo) at some point.

I tested this locally, after installing the tool with a custom globalPackagesFolder I changed the path in the cache to an incorrect path, the dotnet command does not execute using dotnet reportgenerator -h. So a 'cache' miss is not handled correctly. (Also the error message I get at this point is misleading, it says Run "dotnet tool restore" to make the "reportgenerator" command available. which does not solve the problem.)

If I then run dotnet tool restore (after removing the package) it reinstalls the package to my custom globalPackagesFolder but the toolResolverCache is not updated.

Are we using this in such a weird/unintended manner? Because I am seriously wondering how it can be that there aren't many more people (which use dotnet build servers sharing nuget caches) with this issue.

OkkeHendriks commented 5 months ago

Also, regarding the suggestion of @wli3 (using dotnet tool install --tool-path NAME). This method is not a viable option when one wants to use the dotnet tool manifest (for dotnet tool restore), I believe?

OkkeHendriks commented 5 months ago

See 28695.