-
Notifications
You must be signed in to change notification settings - Fork 258
Global Tools NuGet Implementation
Status: Implementing
This specification is the NuGet side of a new dotnet cli experience, tentatively called "Global Tools". Related specifications are here:
Each of these design specs are still evolving.
NuGet Github Collector issue #6200
NuGet currently helps provide tools per dotnet cli 1.x requirements through the DotnetCLIToolReference feature. The reasoning for adding a new feature is described in the above linked specs. We believe most tool publishers will move to global tools.
We will introduce a new "PackageType" and a well-defined format how to create such tools.
NuGet will provide APIs for the CLI to be able to install mentioned global tools to a pre-determined location. To do this, they will create a temporary project that will indicate that it's a global tool restore project, and will contain a global tool reference as a "PackageReference". Then the CLI will call NuGet restore with these parameters, which NuGet needs to respect and interpret correctly. NuGet will block adding tool packages into standard package reference project. Additionally, only 1 global tool package reference per fake project is allowed.
Since pack is very extensible, the pack experience doesn't need additional work from the NuGet side. From NuGet side, we will require authors to mark their packages with a PackageType metadata, as described in here. The will be included in the following path in the nupkg:
tools\{tfm}\{rid}\*.dll
- tfm is all accepted frameworks
- rid is all known rids + "Any"
- Rob - we should be enforcing this 1 package type today. Update: We are not enforcing it on pack. We only do when we explicitly install a package. Created Task 6298 as a result.
- What should the package type be? Options: CommandLineTool, GlobalTool, Tool, DotnetTool Are these packages command line only? They can pull up a UI etc. Is global tools the correct branding considering there are local tools as well. Tool is too generic, and per .NET principle, don’t waste a great name. DotnetTool is a misnomer, because it implies dotnet(portable), but eventually the dotnet CLI will/might support .NET full framework. Need to work with the CLI team to understand the branding.
NuGet.org will need to make a few changes based on the new package type.
- NuGet.org should reject packages that include the global package tool and any other package type Gallery Task 5182
- Packages with this package type should display a “dotnet install packageId packageVersion” tab only, rather than the standard tabs. Gallery Task 5182
- Search by packageType should be consider in the package applicability search work. Task 5725
Dotnet CLI will create a temporary project and provide all details regarding restore there, including
- Install directory (where to install and extract nupkg and dependencies) c:\users\username.nuget was returned by an API that they called on us to find machinewide place for tools The packageId is provided by the CLI team, and the package version if passed. The CLI will handle cases where the version is not passed by creating a dummy folder name and then renaming the folder when they get the package version from NuGet.
- BaseIntermediateOutputPath (where assets file goes) We need to qualify the scenario for local tools
- Target Framework (used by restore to select assets)
- Runtime Identifier (used by restore to select assets)
- RestoreRootConfigDirectory(the CLI working directory, from where the nuget.config graph will be walked)
- RestoreFallbackFolders (for global tools, this needs to be "clear" in order to make the tools self-containing)
- RestoreAdditionalProjectSources, RestoreAdditionalProjectFallbackFolders, RestoreAdditionalProjectFallbackFoldersExcludes are values brought in through the SDK. Same as above, for global tools this compromises the principle of the tools needing to be self-containing.
In addition, this project should contain a restore project style property, named DotnetToolReference. (another option would be to do PR, but then have another property). I am proposing that because we already have a DotnetCLiTool restore style type. An example temporary project would be:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RestoreProjectStyle>DotnetToolReference</RestoreProjectStyle>
<TargetFramework>netcoreapp2.1</TargetFramework>
<RestorePackagesPath>C:\Users\username\.nuget\tools\packageId\packageVersion</RestorePackagesPath>
<BaseIntermediateOutputPath>C:\Users\username\.nuget\toools\packageId\versionVersion</BaseIntermediateOutputPath>
<RestoreRootConfigDirectory>C:\Users\username\code\Library</RestoreRootConfigDirectory>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
<RestoreFallbackFolders>clear</RestoreFallbackFolders>
<RestoreAdditionalProjectSources></RestoreAdditionalProjectSources>
<RestoreAdditionalProjectFallbackFolders></RestoreAdditionalProjectFallbackFolders>
<RestoreAdditionalProjectFallbackFoldersExcludes></RestoreAdditionalProjectFallbackFoldersExcludes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="my.tool" Version="1.2" />
</ItemGroup>
</Project>
Task 6260 to return the machine wide tools folder.
NuGet will also provide a way to walk the settings based on the CLI working directory. Update: Added RestoreRootConfigDirectory Task 6199
The install directory will be a V3 style directory.
The assets file will need to be extended to include the tools folder when packages are marked with the DotnetTool PackageType. Task 6197
CLI will read the assets once restore is done to find the correct tool path. NuGet will add the tools assets to the assets file, and then CLI will use the respective APIs to get that asset path.
If restore fails, the CLI will be able to get the restore status from the assets file/restore exit code.
Example:
C:\Users\username\.nuget\tools\my.tool\1.2\project.assets.json
CLI will handle the restore failure cases, and partial file left on disk. They can use the VersionPathResolver to figure that out.
NuGet restore will not succeed in the following scenarios. Task 6198
Scenario | Status |
---|---|
More than 1 reference in ToolReference RestoreProjectStyle Project | Restore fails |
Tool reference in a non-ToolReference project style | Restore fails with an incompatibility error |
Non Tool reference in a ToolReference project style | Restore fails with an incompatibility error |
Users must not author projects like this and load them in VS. Above mentioned errors will happen for incorrect hybrid projects.
- How do we handle the scenario where the global packages folder is at the root of a drive? Example F:
The tools folder cannot be at the same level as this. Related task: Task 6260 - NuGet will persist a cache file by default in the same directory as the assets file. CLI can consider cleaning this up.
- NuGet version currently does not support a way to "request" the latest prerelease version. Tracking issues, Task 4699 Task 912
- Clarify the experience once implemented, if someone tries to load a proper ToolReference project. Visual Studio will currently treat it as a package reference project since the restore project style property is not nominated.
- My initial idea is for nuget.exe to not "treat" projects like this as restorable. So you will only be able to restore this type of projects through the restore task.
Help settle on the package type name, by considering their branding.
- How does the CLI make a decision about the RestorePackagesPath/baseintermediateOutputPath for local tools?
- Would this cause a confusion? Is the branding correct?
Does the CLI provide a remove command? NuGet does not need to add tools to clean this global tools folder. However, we have had occasional complaints about the size of the .nuget folder. This increases it drastically
CLI needs to make sure they clean when the restore fails for whatever reason. Be it an incompatibility error, or where only 1/2 packages gets installed etc.
Currently there is no plans to block users from being able to use DotnetCLIToolReference.
Check out the proposals in the accepted
& proposed
folders on the repository, and active PRs for proposals being discussed today.