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.65k stars 1.05k forks source link

`dotnet tool install` on non-tool package causes DirectoryNotFoundException #37010

Open KalleOlaviNiemitalo opened 9 months ago

KalleOlaviNiemitalo commented 9 months ago

Describe the bug

When I use dotnet tool install on a package that is not a .NET tool package, it fails with an unhandled DirectoryNotFoundException. It should instead report that the package type is wrong.

I initially hit this when I noticed https://github.com/dotnet/sourcelink/pull/678 and attempted to install dotnet-sourcelink, which turned out to be an older package that has <packageType name="DotnetCliTool" /> rather than <packageType name="DotnetTool" />, and does not contain a tools directory.

To Reproduce

dotnet tool install --global System.ValueTuple --version 4.5.0

Exceptions (if any)

Unhandled exception: System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\Kalle\.dotnet\tools\.store\system.valuetuple\4.5.0\system.valuetuple\4.5.0\tools'.
   at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path, Boolean ignoreNotFound)
   at System.IO.Enumeration.FileSystemEnumerator`1.Init()
   at System.IO.Enumeration.FileSystemEnumerable`1..ctor(String directory, FindTransform transform, EnumerationOptions options, Boolean isNormalized)
   at System.IO.Enumeration.FileSystemEnumerableFactory.UserDirectories(String directory, String expression, EnumerationOptions options)
   at System.IO.Directory.InternalEnumeratePaths(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
   at System.IO.Directory.GetDirectories(String path, String searchPattern, EnumerationOptions enumerationOptions)
   at Microsoft.DotNet.ToolPackage.ToolPackageInstance..ctor(PackageId id, NuGetVersion version, DirectoryPath packageDirectory, DirectoryPath assetsJsonParentDirectory)
   at Microsoft.DotNet.Cli.ToolPackage.ToolPackageDownloader.<>c__DisplayClass8_0.<InstallPackage>b__0()
   at Microsoft.DotNet.Cli.TransactionalAction.Run[T](Func`1 action, Action commit, Action rollback)
   at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.Execute()
   at System.CommandLine.Invocation.InvocationPipeline.Invoke(ParseResult parseResult)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)

Further technical details

$ dotnet --info
.NET SDK:
 Version:           8.0.100
 Commit:            57efcf1350
 Workload version:  8.0.100-manifests.71b9f198

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19045
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.100\

.NET workloads installed:
 Workload version: 8.0.100-manifests.71b9f198
 [aspire]
   Installation Source: SDK 8.0.100
   Manifest Version:    8.0.0-preview.1.23557.2/8.0.100
   Manifest Path:       C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.0.0-preview.1.23557.2\WorkloadManifest.json
   Install Type:              Msi

Host:
  Version:      8.0.0
  Architecture: x64
  Commit:       5535e31a71

.NET SDKs installed:
  2.1.526 [C:\Program Files\dotnet\sdk]
  6.0.417 [C:\Program Files\dotnet\sdk]
  8.0.100 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 6.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

No IDE.

JL03-Yue commented 9 months ago

Thanks for reporting that

baronfel commented 8 months ago

Quick note here that it doesn't look like the ToolPackageDownloader is validating that the given package id is a tool or not, so we should do that and fail with a validation error instead of allowing non-tool packages to be downloaded.

ibobak commented 6 months ago

I have the same issue. I am on Linux, Ubuntu 22.04, 6.4.6-060406-generic. I am running this command

dotnet tool install --global MathNet.Numerics --version 5.0.0

and I am getting this error:

~/.dotnet$ dotnet tool install --global MathNet.Numerics --version 5.0.0
Skipping NuGet package signature verification.
Unhandled exception: System.IO.DirectoryNotFoundException: Could not find a part of the path '/home/ihor/.dotnet/tools/.store/mathnet.numerics/5.0.0/mathnet.numerics/5.0.0/tools'.
   at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path, Boolean ignoreNotFound)
   at System.IO.Enumeration.FileSystemEnumerator`1.Init()
   at System.IO.Enumeration.FileSystemEnumerable`1..ctor(String directory, FindTransform transform, EnumerationOptions options, Boolean isNormalized)
   at System.IO.Enumeration.FileSystemEnumerableFactory.UserDirectories(String directory, String expression, EnumerationOptions options)
   at System.IO.Directory.InternalEnumeratePaths(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
   at System.IO.Directory.GetDirectories(String path, String searchPattern, EnumerationOptions enumerationOptions)
   at Microsoft.DotNet.ToolPackage.ToolPackageInstance..ctor(PackageId id, NuGetVersion version, DirectoryPath packageDirectory, DirectoryPath assetsJsonParentDirectory)
   at Microsoft.DotNet.Cli.ToolPackage.ToolPackageDownloader.<>c__DisplayClass8_0.<InstallPackage>b__0()
   at Microsoft.DotNet.Cli.TransactionalAction.Run[T](Func`1 action, Action commit, Action rollback)
   at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.<>c__DisplayClass18_0.<Execute>b__1()
   at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.RunWithHandlingInstallError(Action installAction)
   at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.Execute()
   at System.CommandLine.Invocation.InvocationPipeline.Invoke(ParseResult parseResult)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)

My dotnet --info:

.NET SDK:
 Version:           8.0.201
 Commit:            4c2d78f037
 Workload version:  8.0.200-manifests.3097af8b

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  22.04
 OS Platform: Linux
 RID:         linux-x64
 Base Path:   /home/ihor/.dotnet/sdk/8.0.201/

.NET workloads installed:
There are no installed workloads to display.

Host:
  Version:      8.0.2
  Architecture: x64
  Commit:       1381d5ebd2

.NET SDKs installed:
  5.0.408 [/home/ihor/.dotnet/sdk]
  8.0.201 [/home/ihor/.dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 5.0.17 [/home/ihor/.dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.2 [/home/ihor/.dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 5.0.17 [/home/ihor/.dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.2 [/home/ihor/.dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
  None

Environment variables:
  DOTNET_ROOT       [/home/ihor/.dotnet]

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download
KalleOlaviNiemitalo commented 6 months ago

@ibobak, if this bug is fixed, then dotnet tool install MathNet.Numerics --version 5.0.0 will still fail; it will just detect the problem earlier and display the error in a prettier way.