sdk: When installing a .NET local tool, create the tool manifest if one does not exist

When a user tries to install a .NET tool as a local tool on a folder that does not contain the manifest, we get an error Cannot find a manifest file.

> dotnet tool install --local Cake.Tool --version 0.38.4
Cannot find a manifest file.
For a list of locations searched, specify the "-d" option before the tool name.
If you intended to install a global tool, add `--global` to the command.
If you would like to create a manifest, use `dotnet new tool-manifest`, usually in the repo root directory.

However, if the user tries to update an existing local tool, dotnet tool is able to update the existing manifest:

dotnet new tool-manifest
dotnet tool install --local Cake.Tool --version 0.38.4
dotnet tool update --local Cake.Tool
Tool 'cake.tool' was successfully updated from version '0.38.4' to version '0.38.5' (manifest file /Users/augustoproiete/.config/dotnet-tools.json).

TL;DR; It would be great if dotnet tool install automatically created the tool manifest, if one does not exist when installing a local tool, instead of failing with an error.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 7
  • Comments: 16 (7 by maintainers)

Most upvoted comments

Finding an analog, NPM does this by default as well with package.json and puts it in the right place. Users who do npm install moment for example, get a non-global package and a package.json dropped in the right place. We should have the similar and easy experience reducing the ceremony for such things.

The side of doing that is we could potentially generating manifest file accidentally on unexpected locations. And people could run unexpected tool.

Add a --force or --trust-me parameter so users can convince dotnet tool that they know what they are doing? 😄

Sorry, I just saw this ping. I worry that an optional flag (especially a long one!) will get very little use, especially with the very low rates of tab-completion registration and usage. What if we

  • tried the walking algorithm above to locate the ‘root’
  • also provided an explicit --manifest-file option to specify the manifest to add to (and side-step the entire walking algorithm if present)
  • provide an explicit --create-manifest-if-needed false that forbids walking (and therefore requires either explicit --manifest-file usage or the .config/dotnet-tools.json to be present in the current directory

That would make the simple usage do what the user intended, while also giving automation tools to more firmly specify the inputs when required.

@wli3 The end goal is to be able to run a command (or set of commands) that ensures that a particular dotnet tool, of a particular version, is installed.

Use-case: Write a set of instructions on how to add a dotnet tool, that someone can copy/paste and run, and it always works.

Let’s examine the following example:

dotnet new tool-manifest
dotnet tool install --local toolname --version toolversion

At the moment, it’s impossible to guarantee that the instructions above will work for everyone, because:

  • dotnet new tool-manifest throws an error if a manifest already exists (exit code != 0)
  • dotnet new tool-manifest --force replaces the existing manifest - which is not the goal when you just want to add a new tool to the existing manifest
  • dotnet tool install toolname fails if the manifest does not exist (exit code != 0)

As you can see, it’s impossible to send someone a set of instructions that will always work when they run.


Would it be possible to have along the lines of the following:

dotnet new tool-manifest --ignore-if-exists
dotnet tool install toolname --ignore-if-installed

So that both commands above do not throw an error, and return exit code = 0.

I also suggested an alternative approach on https://github.com/dotnet/sdk/issues/10310#issuecomment-757602576 which aims to achieve the same goal: Ensure that a dotnet tool is installed, without throwing errors.

dotnet tool ensure --local toolname --version toolversion

The above would mean that the manifest is created automatically, so that everything can be done with one command.

Expectations:

  • If the command does not specify version, the latest version is installed. Exit code = 0
  • If the command specify version 2.0.0 and tool 2.0.0 is already installed, do nothing. Exit code = 0
  • If the command specify version 2.0.0 and tool 1.0.0 is already installed, upgrade to 2.0.0. Exit code = 0
  • If the command specify version 2.0.0 and tool 3.0.0 is already installed, downgrade to 2.0.0. Exit code = 0

/cc @KathleenDollard

The side of doing that is we could potentially generating manifest file accidentally on unexpected locations. And people could run unexpected tool.

Add a --force or --trust-me parameter so users can convince dotnet tool that they know what they are doing? 😄

The current behavior – asking the user to run dotnet new tool-manifest is about the same level of work comparing with asking the user to add a parameter to dotnet tool ... command. I think it is fine adding another option. But I don’t think it should be the default