Skip to content

Commit 1ee15a6

Browse files
authored
tool install/update: Support package@version syntax (#48085)
1 parent 4965b59 commit 1ee15a6

30 files changed

+408
-37
lines changed

src/Cli/dotnet/CliStrings.resx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,4 +784,17 @@ For a list of locations searched, specify the "-d" option before the tool name.<
784784
<value>An issue was encountered verifying workloads. For more information, run "dotnet workload update".</value>
785785
<comment>{Locked="dotnet workload update"}</comment>
786786
</data>
787+
<data name="PackageIdentityArgumentDescription" xml:space="preserve">
788+
<value>Package reference in the form of a package identifier like 'Newtonsoft.Json' or package identifier and version separated by '@' like '[email protected]'.</value>
789+
</data>
790+
<data name="PackageIdentityArgumentIdOrVersionIsNull" xml:space="preserve">
791+
<value>Package reference id and version must not be null.</value>
792+
</data>
793+
<data name="InvalidVersion" xml:space="preserve">
794+
<value>Invalid version string: {0}</value>
795+
</data>
796+
<data name="PackageIdentityArgumentVersionOptionConflict" xml:space="preserve">
797+
<value>Cannot specify --version when the package argument already contains a version.</value>
798+
<comment>{Locked="--version"}</comment>
799+
</data>
787800
</root>

src/Cli/dotnet/Commands/Tool/Install/ParseResultExtension.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ internal static class ParseResultExtension
1111
{
1212
public static VersionRange GetVersionRange(this ParseResult parseResult)
1313
{
14-
string packageVersion = parseResult.GetValue(ToolInstallCommandParser.VersionOption);
14+
string packageVersion = parseResult.GetValue(ToolInstallCommandParser.PackageIdentityArgument)?.Version?.ToString() ??
15+
parseResult.GetValue(ToolInstallCommandParser.VersionOption);
1516
bool prerelease = parseResult.GetValue(ToolInstallCommandParser.PrereleaseOption);
1617

1718
if (!string.IsNullOrEmpty(packageVersion) && prerelease)

src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommand.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ internal class ToolInstallCommand(
1818
private readonly string _toolPath = parseResult.GetValue(ToolAppliedOption.ToolPathOption);
1919
private readonly string _framework = parseResult.GetValue(ToolInstallCommandParser.FrameworkOption);
2020

21+
22+
internal static void EnsureNoConflictPackageIdentityVersionOption(ParseResult parseResult)
23+
{
24+
if (!string.IsNullOrEmpty(parseResult.GetValue(ToolInstallCommandParser.PackageIdentityArgument)?.Version?.ToString()) &&
25+
!string.IsNullOrEmpty(parseResult.GetValue(ToolInstallCommandParser.VersionOption)))
26+
{
27+
throw new GracefulException(CliStrings.PackageIdentityArgumentVersionOptionConflict);
28+
}
29+
}
30+
2131
public override int Execute()
2232
{
2333
ToolAppliedOption.EnsureNoConflictGlobalLocalToolPathOption(
@@ -27,6 +37,8 @@ public override int Execute()
2737
ToolAppliedOption.EnsureToolManifestAndOnlyLocalFlagCombination(
2838
_parseResult);
2939

40+
EnsureNoConflictPackageIdentityVersionOption(_parseResult);
41+
3042
if (_global || !string.IsNullOrWhiteSpace(_toolPath))
3143
{
3244
return (_toolInstallGlobalOrToolPathCommand ?? new ToolInstallGlobalOrToolPathCommand(_parseResult)).Execute();

src/Cli/dotnet/Commands/Tool/Install/ToolInstallCommandParser.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,17 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.CommandLine;
5+
using System.CommandLine.Parsing;
56
using Microsoft.DotNet.Cli.Commands.Tool.Common;
67
using Microsoft.DotNet.Cli.Commands.Tool.Search;
78
using Microsoft.DotNet.Cli.Extensions;
9+
using NuGet.Packaging.Core;
810

911
namespace Microsoft.DotNet.Cli.Commands.Tool.Install;
1012

1113
internal static class ToolInstallCommandParser
1214
{
13-
public static readonly CliArgument<string> PackageIdArgument = new("packageId")
14-
{
15-
HelpName = CliCommandStrings.ToolInstallPackageIdArgumentName,
16-
Description = CliCommandStrings.ToolInstallPackageIdArgumentDescription
17-
};
15+
public static readonly CliArgument<PackageIdentity?> PackageIdentityArgument = CommonArguments.PackageIdentityArgument();
1816

1917
public static readonly CliOption<string> VersionOption = new("--version")
2018
{
@@ -92,7 +90,7 @@ public static CliCommand GetCommand()
9290
private static CliCommand ConstructCommand()
9391
{
9492
CliCommand command = new("install", CliCommandStrings.ToolInstallCommandDescription);
95-
command.Arguments.Add(PackageIdArgument);
93+
command.Arguments.Add(PackageIdentityArgument);
9694

9795
AddCommandOptions(command);
9896

src/Cli/dotnet/Commands/Tool/Install/ToolInstallGlobalOrToolPathCommand.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ public ToolInstallGlobalOrToolPathCommand(
6868
{
6969
_verifySignatures = verifySignatures;
7070
_currentWorkingDirectory = currentWorkingDirectory;
71-
var packageIdArgument = parseResult.GetValue(ToolInstallCommandParser.PackageIdArgument);
71+
72+
var packageIdArgument = parseResult.GetValue(ToolInstallCommandParser.PackageIdentityArgument)?.Id;
73+
7274
_packageId = packageId ?? (packageIdArgument is not null ? new PackageId(packageIdArgument) : null);
7375
_configFilePath = parseResult.GetValue(ToolInstallCommandParser.ConfigOption);
7476
_framework = parseResult.GetValue(ToolInstallCommandParser.FrameworkOption);

src/Cli/dotnet/Commands/Tool/Install/ToolInstallLocalCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public ToolInstallLocalCommand(
4444
: base(parseResult)
4545
{
4646
_updateAll = parseResult.GetValue(ToolUpdateCommandParser.UpdateAllOption);
47-
var packageIdArgument = parseResult.GetValue(ToolInstallCommandParser.PackageIdArgument);
47+
var packageIdArgument = parseResult.GetValue(ToolInstallCommandParser.PackageIdentityArgument)?.Id;
4848
_packageId = packageId ?? (packageIdArgument is not null ? new PackageId(packageIdArgument) : null);
4949
_explicitManifestFile = parseResult.GetValue(ToolAppliedOption.ToolManifestOption);
5050

src/Cli/dotnet/Commands/Tool/Uninstall/ToolUninstallCommandParser.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@
55
using Microsoft.DotNet.Cli.Commands.Tool.Common;
66
using Microsoft.DotNet.Cli.Commands.Tool.Install;
77
using Microsoft.DotNet.Cli.Extensions;
8+
using NuGet.Packaging.Core;
89

910
namespace Microsoft.DotNet.Cli.Commands.Tool.Uninstall;
1011

1112
internal static class ToolUninstallCommandParser
1213
{
13-
public static readonly CliArgument<string> PackageIdArgument = ToolInstallCommandParser.PackageIdArgument;
14+
public static readonly CliArgument<string> PackageIdArgument = new("packageId")
15+
{
16+
HelpName = "PACKAGE_ID",
17+
Description = CliStrings.PackageReference,
18+
Arity = ArgumentArity.ExactlyOne
19+
};
1420

1521
public static readonly CliOption<bool> GlobalOption = ToolAppliedOption.GlobalOption;
1622

src/Cli/dotnet/Commands/Tool/Uninstall/ToolUninstallGlobalOrToolPathCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public override int Execute()
5151
var appHostSourceDirectory = ShellShimTemplateFinder.GetDefaultAppHostSourceDirectory();
5252
IShellShimRepository shellShimRepository = _createShellShimRepository(appHostSourceDirectory, toolDirectoryPath);
5353

54-
var packageId = new PackageId(_parseResult.GetValue(ToolInstallCommandParser.PackageIdArgument));
55-
IToolPackage package;
54+
var packageId = new PackageId(_parseResult.GetValue(ToolUninstallCommandParser.PackageIdArgument));
55+
IToolPackage package = null;
5656
try
5757
{
5858
package = toolPackageStoreQuery.EnumeratePackageVersions(packageId).SingleOrDefault();

src/Cli/dotnet/Commands/Tool/Update/ToolUpdateCommand.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ internal static void EnsureEitherUpdateAllOrUpdateOption(
6767
options.Add(ToolAppliedOption.UpdateAllOption.Name);
6868
}
6969

70-
if (parseResult.GetResult(ToolUpdateCommandParser.PackageIdArgument) is not null)
70+
if (parseResult.GetResult(ToolUpdateCommandParser.PackageIdentityArgument) is not null)
7171
{
72-
options.Add(ToolUpdateCommandParser.PackageIdArgument.Name);
72+
options.Add(ToolUpdateCommandParser.PackageIdentityArgument.Name);
7373
}
7474

7575
if (options.Count != 1)
@@ -78,6 +78,15 @@ internal static void EnsureEitherUpdateAllOrUpdateOption(
7878
}
7979
}
8080

81+
internal static void EnsureNoConflictPackageIdentityVersionOption(ParseResult parseResult)
82+
{
83+
if (!string.IsNullOrEmpty(parseResult.GetValue(ToolUpdateCommandParser.PackageIdentityArgument)?.Version?.ToString()) &&
84+
!string.IsNullOrEmpty(parseResult.GetValue(ToolAppliedOption.VersionOption)))
85+
{
86+
throw new GracefulException(CliStrings.PackageIdentityArgumentVersionOptionConflict);
87+
}
88+
}
89+
8190
public override int Execute()
8291
{
8392
ToolAppliedOption.EnsureNoConflictGlobalLocalToolPathOption(
@@ -94,6 +103,8 @@ public override int Execute()
94103
_parseResult,
95104
CliCommandStrings.UpdateToolCommandInvalidAllAndPackageId);
96105

106+
EnsureNoConflictPackageIdentityVersionOption(_parseResult);
107+
97108
if (_global || !string.IsNullOrWhiteSpace(_toolPath))
98109
{
99110
return _toolUpdateGlobalOrToolPathCommand.Execute();

src/Cli/dotnet/Commands/Tool/Update/ToolUpdateCommandParser.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,13 @@
44
using System.CommandLine;
55
using Microsoft.DotNet.Cli.Commands.Tool.Common;
66
using Microsoft.DotNet.Cli.Commands.Tool.Install;
7+
using NuGet.Packaging.Core;
78

89
namespace Microsoft.DotNet.Cli.Commands.Tool.Update;
910

1011
internal static class ToolUpdateCommandParser
1112
{
12-
public static readonly CliArgument<string> PackageIdArgument = new("packageId")
13-
{
14-
HelpName = CliCommandStrings.ToolUpdatePackageIdArgumentName,
15-
Description = CliCommandStrings.ToolUpdatePackageIdArgumentDescription,
16-
Arity = ArgumentArity.ZeroOrOne
17-
};
13+
public static readonly CliArgument<PackageIdentity?> PackageIdentityArgument = CommonArguments.PackageIdentityArgument(requireArgument: false);
1814

1915
public static readonly CliOption<bool> UpdateAllOption = ToolAppliedOption.UpdateAllOption;
2016

@@ -31,7 +27,7 @@ private static CliCommand ConstructCommand()
3127
{
3228
CliCommand command = new("update", CliCommandStrings.ToolUpdateCommandDescription);
3329

34-
command.Arguments.Add(PackageIdArgument);
30+
command.Arguments.Add(PackageIdentityArgument);
3531

3632
ToolInstallCommandParser.AddCommandOptions(command);
3733
command.Options.Add(AllowPackageDowngradeOption);
@@ -42,4 +38,3 @@ private static CliCommand ConstructCommand()
4238
return command;
4339
}
4440
}
45-

0 commit comments

Comments
 (0)