diff --git a/src/Cli/dotnet/CliStrings.resx b/src/Cli/dotnet/CliStrings.resx
index cf4b6b130d54..a426175c77cd 100644
--- a/src/Cli/dotnet/CliStrings.resx
+++ b/src/Cli/dotnet/CliStrings.resx
@@ -803,4 +803,10 @@ For a list of locations searched, specify the "-d" option before the tool name.<
Cannot specify --version when the package argument already contains a version.{Locked="--version"}
+
+ Overrides confirmation prompt with "yes" value.
+
+
+ Overrides confirmation prompt with "no" value.
+
diff --git a/src/Cli/dotnet/Commands/CliCommandStrings.resx b/src/Cli/dotnet/Commands/CliCommandStrings.resx
index 82b2f559d0f4..30e37fd39d52 100644
--- a/src/Cli/dotnet/Commands/CliCommandStrings.resx
+++ b/src/Cli/dotnet/Commands/CliCommandStrings.resx
@@ -2062,6 +2062,9 @@ If you would like to create a manifest, use the `--create-manifest-if-needed` fl
Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Arguments forwarded to the tool
+
Search dotnet tools in nuget.org
@@ -2483,6 +2486,18 @@ To display a value, specify the corresponding command-line option without provid
Zero tests ran
+
+ Executes a tool from source without permanently installing it.
+
+
+ Missing package ID
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+
+ Run from source approval denied by the user
+
Recursively add projects' ReferencedProjects to solution
diff --git a/src/Cli/dotnet/Commands/Tool/Execute/ToolExecuteCommand.cs b/src/Cli/dotnet/Commands/Tool/Execute/ToolExecuteCommand.cs
new file mode 100644
index 000000000000..4d5f1fd8cc20
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Execute/ToolExecuteCommand.cs
@@ -0,0 +1,106 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using Microsoft.DotNet.Cli.CommandFactory;
+using Microsoft.DotNet.Cli.CommandFactory.CommandResolution;
+using Microsoft.DotNet.Cli.Commands.Tool.Install;
+using Microsoft.DotNet.Cli.ToolPackage;
+using Microsoft.DotNet.Cli.Utils;
+using NuGet.Common;
+using NuGet.Packaging.Core;
+using NuGet.Versioning;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Execute
+{
+ internal class ToolExecuteCommand(ParseResult result) : CommandBase(result)
+ {
+ private readonly PackageIdentity? _packageToolIdentityArgument = result.GetValue(ToolExecuteCommandParser.PackageIdentityArgument);
+ private readonly IEnumerable _forwardArguments = result.GetValue(ToolExecuteCommandParser.CommandArgument) ?? [];
+ private readonly bool _allowRollForward = result.GetValue(ToolExecuteCommandParser.RollForwardOption);
+ private readonly string? _configFile = result.GetValue(ToolExecuteCommandParser.ConfigOption);
+ private readonly string[] _sources = result.GetValue(ToolExecuteCommandParser.SourceOption) ?? [];
+ private readonly string[] _addSource = result.GetValue(ToolExecuteCommandParser.AddSourceOption) ?? [];
+ private readonly bool _ignoreFailedSources = result.GetValue(ToolCommandRestorePassThroughOptions.IgnoreFailedSourcesOption);
+ private readonly bool _interactive = result.GetValue(ToolExecuteCommandParser.InteractiveOption);
+ private readonly VerbosityOptions _verbosity = result.GetValue(ToolExecuteCommandParser.VerbosityOption);
+ private readonly bool _yes = result.GetValue(ToolExecuteCommandParser.YesOption);
+ private readonly bool _prerelease = result.GetValue(ToolExecuteCommandParser.PrereleaseOption);
+
+ public override int Execute()
+ {
+ if (_packageToolIdentityArgument is null)
+ {
+ // System.CommandLine will throw an error if the argument is not provided, but we can still check here for clarity.
+ return 1;
+ }
+
+ if (!UserAgreedToRunFromSource())
+ {
+ throw new GracefulException(CliCommandStrings.ToolRunFromSourceUserConfirmationFailed, isUserError: true);
+ }
+
+ if (_allowRollForward)
+ {
+ _forwardArguments.Append("--allow-roll-forward");
+ }
+
+ PackageId packageId = new PackageId(_packageToolIdentityArgument.Id);
+
+ VersionRange versionRange = _parseResult.GetVersionRange();
+
+ string tempDirectory = NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp);
+
+ ToolPackageStoreAndQuery toolPackageStoreAndQuery = new(new(tempDirectory));
+ ToolPackageDownloader toolPackageDownloader = new(toolPackageStoreAndQuery);
+
+ IToolPackage toolPackage = toolPackageDownloader.InstallPackage(
+ new PackageLocation(
+ nugetConfig: _configFile != null ? new(_configFile) : null,
+ sourceFeedOverrides: _sources,
+ additionalFeeds: _addSource),
+ packageId: packageId,
+ verbosity: _verbosity,
+ versionRange: versionRange,
+ isGlobalToolRollForward: _allowRollForward, // Needed to update .runtimeconfig.json
+ restoreActionConfig: new(
+ IgnoreFailedSources: _ignoreFailedSources,
+ Interactive: _interactive));
+
+ CommandSpec commandSpec = MuxerCommandSpecMaker.CreatePackageCommandSpecUsingMuxer(toolPackage.Command.Executable.ToString(), _forwardArguments);
+ var command = CommandFactoryUsingResolver.Create(commandSpec);
+ var result = command.Execute();
+ return result.ExitCode;
+ }
+
+ private bool UserAgreedToRunFromSource()
+ {
+ if (_yes)
+ {
+ return true;
+ }
+
+ if (!_interactive)
+ {
+ return false;
+ }
+
+ // TODO: Use a better way to ask for user input
+ Console.Write(CliCommandStrings.ToolRunFromSourceUserConfirmationPrompt);
+ bool userAccepted = Console.ReadKey().Key == ConsoleKey.Y;
+
+ if (_verbosity >= VerbosityOptions.detailed)
+ {
+ Console.WriteLine();
+ Console.WriteLine(new String('-', CliCommandStrings.ToolRunFromSourceUserConfirmationPrompt.Length));
+ }
+ else
+ {
+ // Clear the line
+ Console.Write("\r" + new string(' ', CliCommandStrings.ToolRunFromSourceUserConfirmationPrompt.Length + 1) + "\r");
+ }
+
+ return userAccepted;
+ }
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Execute/ToolExecuteCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Execute/ToolExecuteCommandParser.cs
new file mode 100644
index 000000000000..8ab1f8fa0e02
--- /dev/null
+++ b/src/Cli/dotnet/Commands/Tool/Execute/ToolExecuteCommandParser.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.CommandLine;
+using System.Text;
+using Microsoft.DotNet.Cli.Commands.Tool.Install;
+using NuGet.Packaging.Core;
+
+namespace Microsoft.DotNet.Cli.Commands.Tool.Execute
+{
+ internal static class ToolExecuteCommandParser
+
+ {
+ public static readonly Argument PackageIdentityArgument = ToolInstallCommandParser.PackageIdentityArgument;
+
+ public static readonly Argument> CommandArgument = new("commandArguments")
+ {
+ Description = CliCommandStrings.ToolRunArguementsDescription
+ };
+
+ public static readonly Option VersionOption = ToolInstallCommandParser.VersionOption;
+ public static readonly Option RollForwardOption = ToolInstallCommandParser.RollForwardOption;
+ public static readonly Option PrereleaseOption = ToolInstallCommandParser.PrereleaseOption;
+ public static readonly Option ConfigOption = ToolInstallCommandParser.ConfigOption;
+ public static readonly Option SourceOption = ToolInstallCommandParser.SourceOption;
+ public static readonly Option AddSourceOption = ToolInstallCommandParser.AddSourceOption;
+ public static readonly Option IgnoreFailedSourcesOption = ToolCommandRestorePassThroughOptions.IgnoreFailedSourcesOption;
+ public static readonly Option InteractiveOption = CommonOptions.InteractiveOption();
+ public static readonly Option YesOption = CommonOptions.YesOption;
+ public static readonly Option VerbosityOption = ToolInstallCommandParser.VerbosityOption;
+
+
+ public static readonly Command Command = ConstructCommand();
+ public static Command GetCommand()
+ {
+ return Command;
+ }
+
+ private static Command ConstructCommand()
+ {
+ Command command = new("execute", CliCommandStrings.ToolExecuteCommandDescription);
+
+ command.Aliases.Add("exec");
+
+ command.Arguments.Add(PackageIdentityArgument);
+ command.Arguments.Add(CommandArgument);
+
+ command.Options.Add(VersionOption);
+ command.Options.Add(RollForwardOption);
+ command.Options.Add(PrereleaseOption);
+ command.Options.Add(ConfigOption);
+ command.Options.Add(SourceOption);
+ command.Options.Add(AddSourceOption);
+ command.Options.Add(IgnoreFailedSourcesOption);
+ command.Options.Add(InteractiveOption);
+ command.Options.Add(YesOption);
+ command.Options.Add(VerbosityOption);
+
+ command.SetAction((parseResult) => new ToolExecuteCommand(parseResult).Execute());
+
+ return command;
+ }
+ }
+}
diff --git a/src/Cli/dotnet/Commands/Tool/Install/ParseResultExtension.cs b/src/Cli/dotnet/Commands/Tool/Install/ParseResultExtension.cs
index 33d08add9800..b79d3bffbde4 100644
--- a/src/Cli/dotnet/Commands/Tool/Install/ParseResultExtension.cs
+++ b/src/Cli/dotnet/Commands/Tool/Install/ParseResultExtension.cs
@@ -13,8 +13,17 @@ internal static class ParseResultExtension
{
public static VersionRange GetVersionRange(this ParseResult parseResult)
{
- string packageVersion = parseResult.GetValue(ToolInstallCommandParser.PackageIdentityArgument)?.Version?.ToString() ??
- parseResult.GetValue(ToolInstallCommandParser.VersionOption);
+ var packageVersionFromIdentityArgument = parseResult.GetValue(ToolInstallCommandParser.PackageIdentityArgument)?.Version?.ToString();
+ var packageVersionFromVersionOption = parseResult.GetValue(ToolInstallCommandParser.VersionOption);
+
+ // Check that only one of these has a value
+ if (!string.IsNullOrEmpty(packageVersionFromIdentityArgument) && !string.IsNullOrEmpty(packageVersionFromVersionOption))
+ {
+ throw new GracefulException(CliStrings.PackageIdentityArgumentVersionOptionConflict);
+ }
+
+ string packageVersion = packageVersionFromIdentityArgument ?? packageVersionFromVersionOption;
+
bool prerelease = parseResult.GetValue(ToolInstallCommandParser.PrereleaseOption);
if (!string.IsNullOrEmpty(packageVersion) && prerelease)
diff --git a/src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommand.cs b/src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommand.cs
index 61557ebc884f..9d24cfabe7c0 100644
--- a/src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommand.cs
+++ b/src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommand.cs
@@ -21,15 +21,6 @@ internal class ToolInstallCommand(
private readonly string _framework = parseResult.GetValue(ToolInstallCommandParser.FrameworkOption);
- internal static void EnsureNoConflictPackageIdentityVersionOption(ParseResult parseResult)
- {
- if (!string.IsNullOrEmpty(parseResult.GetValue(ToolInstallCommandParser.PackageIdentityArgument)?.Version?.ToString()) &&
- !string.IsNullOrEmpty(parseResult.GetValue(ToolInstallCommandParser.VersionOption)))
- {
- throw new GracefulException(CliStrings.PackageIdentityArgumentVersionOptionConflict);
- }
- }
-
public override int Execute()
{
ToolAppliedOption.EnsureNoConflictGlobalLocalToolPathOption(
@@ -39,8 +30,6 @@ public override int Execute()
ToolAppliedOption.EnsureToolManifestAndOnlyLocalFlagCombination(
_parseResult);
- EnsureNoConflictPackageIdentityVersionOption(_parseResult);
-
if (_global || !string.IsNullOrWhiteSpace(_toolPath))
{
return (_toolInstallGlobalOrToolPathCommand ?? new ToolInstallGlobalOrToolPathCommand(_parseResult)).Execute();
diff --git a/src/Cli/dotnet/Commands/Tool/Run/ToolRunCommand.cs b/src/Cli/dotnet/Commands/Tool/Run/ToolRunCommand.cs
index 5a8a7fb7721a..822c0826ee2f 100644
--- a/src/Cli/dotnet/Commands/Tool/Run/ToolRunCommand.cs
+++ b/src/Cli/dotnet/Commands/Tool/Run/ToolRunCommand.cs
@@ -6,7 +6,10 @@
using System.CommandLine;
using Microsoft.DotNet.Cli.CommandFactory;
using Microsoft.DotNet.Cli.CommandFactory.CommandResolution;
+using Microsoft.DotNet.Cli.Commands.Tool.Install;
+using Microsoft.DotNet.Cli.NuGetPackageDownloader;
using Microsoft.DotNet.Cli.ToolManifest;
+using Microsoft.DotNet.Cli.ToolPackage;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.EnvironmentAbstractions;
@@ -18,14 +21,14 @@ internal class ToolRunCommand(
ToolManifestFinder toolManifest = null) : CommandBase(result)
{
private readonly string _toolCommandName = result.GetValue(ToolRunCommandParser.CommandNameArgument);
- private readonly LocalToolsCommandResolver _localToolsCommandResolver = localToolsCommandResolver ?? new LocalToolsCommandResolver();
private readonly IEnumerable _forwardArgument = result.GetValue(ToolRunCommandParser.CommandArgument);
+
+ private readonly LocalToolsCommandResolver _localToolsCommandResolver = localToolsCommandResolver ?? new LocalToolsCommandResolver(toolManifest);
public bool _allowRollForward = result.GetValue(ToolRunCommandParser.RollForwardOption);
- private readonly ToolManifestFinder _toolManifest = toolManifest ?? new ToolManifestFinder(new DirectoryPath(Directory.GetCurrentDirectory()));
public override int Execute()
{
- CommandSpec commandspec = _localToolsCommandResolver.ResolveStrict(new CommandResolverArguments()
+ CommandSpec commandSpec = _localToolsCommandResolver.ResolveStrict(new CommandResolverArguments()
{
// since LocalToolsCommandResolver is a resolver, and all resolver input have dotnet-
CommandName = $"dotnet-{_toolCommandName}",
@@ -33,12 +36,12 @@ public override int Execute()
}, _allowRollForward);
- if (commandspec == null)
+ if (commandSpec == null)
{
throw new GracefulException([string.Format(CliCommandStrings.CannotFindCommandName, _toolCommandName)], isUserError: false);
}
- var result = CommandFactoryUsingResolver.Create(commandspec).Execute();
+ var result = CommandFactoryUsingResolver.Create(commandSpec).Execute();
return result.ExitCode;
}
}
diff --git a/src/Cli/dotnet/Commands/Tool/Run/ToolRunCommandParser.cs b/src/Cli/dotnet/Commands/Tool/Run/ToolRunCommandParser.cs
index 62902224054f..b12437c1cbe0 100644
--- a/src/Cli/dotnet/Commands/Tool/Run/ToolRunCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Tool/Run/ToolRunCommandParser.cs
@@ -17,7 +17,7 @@ internal static class ToolRunCommandParser
public static readonly Argument> CommandArgument = new("toolArguments")
{
- Description = "arguments forwarded to the tool"
+ Description = CliCommandStrings.ToolRunArguementsDescription
};
public static readonly Option RollForwardOption = new("--allow-roll-forward")
diff --git a/src/Cli/dotnet/Commands/Tool/ToolCommandParser.cs b/src/Cli/dotnet/Commands/Tool/ToolCommandParser.cs
index afc8ef9fb707..0392bde15d3f 100644
--- a/src/Cli/dotnet/Commands/Tool/ToolCommandParser.cs
+++ b/src/Cli/dotnet/Commands/Tool/ToolCommandParser.cs
@@ -4,6 +4,7 @@
#nullable disable
using System.CommandLine;
+using Microsoft.DotNet.Cli.Commands.Tool.Execute;
using Microsoft.DotNet.Cli.Commands.Tool.Install;
using Microsoft.DotNet.Cli.Commands.Tool.List;
using Microsoft.DotNet.Cli.Commands.Tool.Restore;
@@ -37,6 +38,7 @@ private static Command ConstructCommand()
command.Subcommands.Add(ToolRunCommandParser.GetCommand());
command.Subcommands.Add(ToolSearchCommandParser.GetCommand());
command.Subcommands.Add(ToolRestoreCommandParser.GetCommand());
+ command.Subcommands.Add(ToolExecuteCommandParser.GetCommand());
command.SetAction((parseResult) => parseResult.HandleMissingCommand());
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
index 905e767f24ab..726a51ce1a89 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.cs.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
index 3896c64b9e61..54eca34d651c 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
index 20afd4520f23..00981e728b92 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
index 71ff36a7e759..fa6e9f8833cc 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
index 3a29e67f41db..49335311ee76 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
index 5c1579261b1a..1d143abc9e04 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
index 2b3218faac44..da67d252b53c 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
index 9a75d810dd44..072630e7a336 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
index 72a2415040df..97e7916f16ee 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
index 04df2e5813ca..bbcf59c7de78 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
index 892aecbdce6b..a44be38d45f5 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
index 08f128a0eeab..3c3dff6b801e 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
index 61319bc77d40..2a040fb4fc23 100644
--- a/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
+++ b/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
@@ -2926,6 +2926,16 @@ Your project targets multiple frameworks. Specify which framework to run using '
Install or manage tools that extend the .NET experience.
+
+ Executes a tool from source without permanently installing it.
+ Executes a tool from source without permanently installing it.
+
+
+
+ Missing package ID
+ Missing package ID
+
+ Add an additional NuGet package source to use during installation.Add an additional NuGet package source to use during installation.
@@ -3151,11 +3161,26 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai
Path to the manifest file.
+
+ Arguments forwarded to the tool
+ Arguments forwarded to the tool
+
+ Run a local tool. Note that this command cannot be used to run a global tool. Run a local tool. Note that this command cannot be used to run a global tool.
+
+ Run from source approval denied by the user
+ Run from source approval denied by the user
+
+
+
+ Tool not found on the system. Do you want to run it from source? [y/n]
+ Tool not found on the system. Do you want to run it from source? [y/n]
+
+ Search dotnet tools in nuget.orgSearch dotnet tools in nuget.org
diff --git a/src/Cli/dotnet/CommonOptions.cs b/src/Cli/dotnet/CommonOptions.cs
index fe784d6757a1..c33b84664910 100644
--- a/src/Cli/dotnet/CommonOptions.cs
+++ b/src/Cli/dotnet/CommonOptions.cs
@@ -12,6 +12,13 @@ namespace Microsoft.DotNet.Cli;
internal static class CommonOptions
{
+ public static Option YesOption =
+ new DynamicOption("--yes", "-y")
+ {
+ Description = CliStrings.YesOptionDescription,
+ Arity = ArgumentArity.Zero
+ };
+
public static Option PropertiesOption =
// these are all of the forms that the property switch can be understood by in MSBuild
new ForwardedOption("--property", "-property", "/property", "/p", "-p", "--p")
diff --git a/src/Cli/dotnet/ToolManifest/IToolManifestEditor.cs b/src/Cli/dotnet/ToolManifest/IToolManifestEditor.cs
index 9c6f14290830..1c3047698dd2 100644
--- a/src/Cli/dotnet/ToolManifest/IToolManifestEditor.cs
+++ b/src/Cli/dotnet/ToolManifest/IToolManifestEditor.cs
@@ -12,7 +12,7 @@ namespace Microsoft.DotNet.Cli.ToolManifest;
internal interface IToolManifestEditor
{
- void Add(FilePath manifest, PackageId packageId, NuGetVersion nuGetVersion, ToolCommandName[] toolCommandNames, bool RollForward = false);
+ void Add(FilePath manifest, PackageId packageId, NuGetVersion nuGetVersion, ToolCommandName[] toolCommandNames, bool rollForward = false);
void Remove(FilePath manifest, PackageId packageId);
void Edit(FilePath manifest, PackageId packageId, NuGetVersion newNuGetVersion, ToolCommandName[] newToolCommandNames);
}
diff --git a/src/Cli/dotnet/ToolManifest/ToolManifestFinder.cs b/src/Cli/dotnet/ToolManifest/ToolManifestFinder.cs
index d7889b0a4532..a235bcd2d227 100644
--- a/src/Cli/dotnet/ToolManifest/ToolManifestFinder.cs
+++ b/src/Cli/dotnet/ToolManifest/ToolManifestFinder.cs
@@ -191,7 +191,7 @@ public FilePath FindFirst(bool createIfNotFound = false)
/*
The --create-manifest-if-needed will use the following priority to choose the folder where the tool manifest goes:
- 1. Walk up the directory tree searching for one that has a.git subfolder
+ 1. Walk up the directory tree searching for one that has a .git subfolder
2. Walk up the directory tree searching for one that has a .sln(x)/git file in it
3. Use the current working directory
*/
diff --git a/src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs b/src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs
index 0b50a69f48d1..adc55c6df98c 100644
--- a/src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs
+++ b/src/Cli/dotnet/ToolPackage/ToolPackageDownloader.cs
@@ -54,13 +54,14 @@ internal class ToolPackageDownloader : IToolPackageDownloader
public ToolPackageDownloader(
IToolPackageStore store,
string runtimeJsonPathForTests = null,
- string currentWorkingDirectory = null
+ string currentWorkingDirectory = null,
+ string localToolDownloadDir = null
)
{
_toolPackageStore = store ?? throw new ArgumentNullException(nameof(store));
_globalToolStageDir = _toolPackageStore.GetRandomStagingDirectory();
ISettings settings = Settings.LoadDefaultSettings(currentWorkingDirectory ?? Directory.GetCurrentDirectory());
- _localToolDownloadDir = new DirectoryPath(SettingsUtility.GetGlobalPackagesFolder(settings));
+ _localToolDownloadDir = new DirectoryPath(localToolDownloadDir ?? SettingsUtility.GetGlobalPackagesFolder(settings));
_currentWorkingDirectory = currentWorkingDirectory;
_localToolAssetDir = new DirectoryPath(PathUtilities.CreateTempSubdirectory());
diff --git a/src/Cli/dotnet/xlf/CliStrings.cs.xlf b/src/Cli/dotnet/xlf/CliStrings.cs.xlf
index 271dc12ceb98..1277b078740a 100644
--- a/src/Cli/dotnet/xlf/CliStrings.cs.xlf
+++ b/src/Cli/dotnet/xlf/CliStrings.cs.xlf
@@ -682,6 +682,11 @@ setx PATH "%PATH%;{0}"
New
+
+ Overrides confirmation prompt with "no" value.
+ Overrides confirmation prompt with "no" value.
+
+ No projects found in the solution.No projects found in the solution.
@@ -1157,6 +1162,11 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
An issue was encountered verifying workloads. For more information, run "dotnet workload update".{Locked="dotnet workload update"}
+
+ Overrides confirmation prompt with "yes" value.
+ Overrides confirmation prompt with "yes" value.
+
+