Skip to content

Commit dc2a5fe

Browse files
authored
dotnet tool run and install roll-forward option (#37231)
2 parents 1bf5fd5 + 892811c commit dc2a5fe

File tree

63 files changed

+597
-76
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+597
-76
lines changed

src/Cli/dotnet/CommandFactory/CommandResolution/LocalToolsCommandResolver.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Linq;
45
using Microsoft.DotNet.Cli;
56
using Microsoft.DotNet.Cli.Utils;
67
using Microsoft.DotNet.ToolManifest;
@@ -27,7 +28,7 @@ public LocalToolsCommandResolver(
2728
_fileSystem = fileSystem ?? new FileSystemWrapper();
2829
}
2930

30-
public CommandSpec ResolveStrict(CommandResolverArguments arguments)
31+
public CommandSpec ResolveStrict(CommandResolverArguments arguments, bool allowRollForward = false)
3132
{
3233
if (arguments == null || string.IsNullOrWhiteSpace(arguments.CommandName))
3334
{
@@ -40,7 +41,7 @@ public CommandSpec ResolveStrict(CommandResolverArguments arguments)
4041
}
4142

4243
var resolveResult = GetPackageCommandSpecUsingMuxer(arguments,
43-
new ToolCommandName(arguments.CommandName.Substring(LeadingDotnetPrefix.Length)));
44+
new ToolCommandName(arguments.CommandName.Substring(LeadingDotnetPrefix.Length)), allowRollForward);
4445

4546
return resolveResult;
4647
}
@@ -73,7 +74,7 @@ public CommandSpec Resolve(CommandResolverArguments arguments)
7374
}
7475

7576
private CommandSpec GetPackageCommandSpecUsingMuxer(CommandResolverArguments arguments,
76-
ToolCommandName toolCommandName)
77+
ToolCommandName toolCommandName, bool allowRollForward = false)
7778
{
7879
if (!_toolManifest.TryFind(toolCommandName, out var toolManifestPackage))
7980
{
@@ -95,6 +96,11 @@ private CommandSpec GetPackageCommandSpecUsingMuxer(CommandResolverArguments arg
9596
toolCommandName.ToString()));
9697
}
9798

99+
if (toolManifestPackage.RollForward || allowRollForward)
100+
{
101+
arguments.CommandArguments = ["--allow-roll-forward", .. arguments.CommandArguments];
102+
}
103+
98104
return MuxerCommandSpecMaker.CreatePackageCommandSpecUsingMuxer(
99105
restoredCommand.Executable.Value,
100106
arguments.CommandArguments);

src/Cli/dotnet/CommandFactory/CommandResolution/MuxerCommandSpecMaker.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics.Eventing.Reader;
45
using Microsoft.DotNet.Cli.Utils;
56

67
namespace Microsoft.DotNet.CommandFactory
@@ -16,18 +17,33 @@ internal static CommandSpec CreatePackageCommandSpecUsingMuxer(
1617
var muxer = new Muxer();
1718

1819
var host = muxer.MuxerPath;
20+
1921
if (host == null)
2022
{
2123
throw new Exception(LocalizableStrings.UnableToLocateDotnetMultiplexer);
2224
}
2325

26+
var rollForwardArgument = (commandArguments ?? Enumerable.Empty<string>()).Where(arg => arg.Equals("--allow-roll-forward", StringComparison.OrdinalIgnoreCase));
27+
28+
if (rollForwardArgument.Any())
29+
{
30+
arguments.Add("--roll-forward");
31+
arguments.Add("Major");
32+
}
33+
2434
arguments.Add(commandPath);
2535

2636
if (commandArguments != null)
2737
{
28-
arguments.AddRange(commandArguments);
38+
if (rollForwardArgument.Any())
39+
{
40+
arguments.AddRange(commandArguments.Except(rollForwardArgument));
41+
}
42+
else
43+
{
44+
arguments.AddRange(commandArguments);
45+
}
2946
}
30-
3147
return CreateCommandSpec(host, arguments);
3248
}
3349

src/Cli/dotnet/CommonLocalizableStrings.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,4 +733,7 @@ The default is 'false.' However, when targeting .NET 7 or lower, the default is
733733
<data name="ArtifactsPathArgumentName" xml:space="preserve">
734734
<value>ARTIFACTS_DIR</value>
735735
</data>
736+
<data name="ToolSettingsNotFound" xml:space="preserve">
737+
<value>Tool settings file does not exist for the tool {0}.</value>
738+
</data>
736739
</root>

src/Cli/dotnet/ToolManifest/IToolManifestEditor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Microsoft.DotNet.ToolManifest
1010
{
1111
internal interface IToolManifestEditor
1212
{
13-
void Add(FilePath manifest, PackageId packageId, NuGetVersion nuGetVersion, ToolCommandName[] toolCommandNames);
13+
void Add(FilePath manifest, PackageId packageId, NuGetVersion nuGetVersion, ToolCommandName[] toolCommandNames, bool RollForward = false);
1414
void Remove(FilePath manifest, PackageId packageId);
1515
void Edit(FilePath manifest, PackageId packageId, NuGetVersion newNuGetVersion, ToolCommandName[] newToolCommandNames);
1616
}

src/Cli/dotnet/ToolManifest/LocalizableStrings.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,7 @@ For a list of locations searched, specify the "-d" option before the tool name.<
169169
<data name="MultipleSamePackageId" xml:space="preserve">
170170
<value>More than one entry exists for package(s): {0}.</value>
171171
</data>
172+
<data name="ToolMissingRollForward" xml:space="preserve">
173+
<value>Missing 'rollForward' entry.</value>
174+
</data>
172175
</root>

src/Cli/dotnet/ToolManifest/ToolManifestEditor.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ internal class ToolManifestEditor : IToolManifestEditor
2121
private const string JsonPropertyIsRoot = "isRoot";
2222
private const string JsonPropertyCommands = "commands";
2323
private const string JsonPropertyTools = "tools";
24+
private const string JsonPropertyRollForward = "rollForward";
2425

2526
public ToolManifestEditor(IFileSystem fileSystem = null, IDangerousFileDetector dangerousFileDetector = null)
2627
{
@@ -32,7 +33,8 @@ public void Add(
3233
FilePath manifest,
3334
PackageId packageId,
3435
NuGetVersion nuGetVersion,
35-
ToolCommandName[] toolCommandNames)
36+
ToolCommandName[] toolCommandNames,
37+
bool rollForward = false)
3638
{
3739
SerializableLocalToolsManifest deserializedManifest =
3840
DeserializeLocalToolsManifest(manifest);
@@ -45,10 +47,14 @@ public void Add(
4547
{
4648
var existingPackage = existing.Single();
4749

50+
// Update the tool manifest if --roll-forward changes
4851
if (existingPackage.PackageId.Equals(packageId)
4952
&& existingPackage.Version == nuGetVersion
5053
&& CommandNamesEqual(existingPackage.CommandNames, toolCommandNames))
5154
{
55+
var toEdit = deserializedManifest.Tools.Single(t => new PackageId(t.PackageId).Equals(packageId));
56+
toEdit.RollForward = rollForward;
57+
_fileSystem.File.WriteAllText(manifest.Value, deserializedManifest.ToJson());
5258
return;
5359
}
5460

@@ -70,7 +76,8 @@ public void Add(
7076
{
7177
PackageId = packageId.ToString(),
7278
Version = nuGetVersion.ToNormalizedString(),
73-
Commands = toolCommandNames.Select(c => c.Value).ToArray()
79+
Commands = toolCommandNames.Select(c => c.Value).ToArray(),
80+
RollForward = rollForward,
7481
});
7582

7683
_fileSystem.File.WriteAllText(manifest.Value, deserializedManifest.ToJson());
@@ -199,6 +206,11 @@ private SerializableLocalToolsManifest DeserializeLocalToolsManifest(FilePath po
199206
serializableLocalToolSinglePackage.Commands = commands.ToArray();
200207
}
201208

209+
if (toolJson.Value.TryGetBooleanValue(JsonPropertyRollForward, out var rollForwardJson))
210+
{
211+
serializableLocalToolSinglePackage.RollForward = rollForwardJson;
212+
}
213+
202214
serializableLocalToolsManifest.Tools.Add(serializableLocalToolSinglePackage);
203215
}
204216
}
@@ -269,6 +281,8 @@ private List<ToolManifestPackage> GetToolManifestPackageFromOneManifestFile(
269281
packageLevelErrors.Add(LocalizableStrings.FieldCommandsIsMissing);
270282
}
271283

284+
bool rollForward = tools.RollForward;
285+
272286
if (packageLevelErrors.Any())
273287
{
274288
var joinedWithIndentation = string.Join(Environment.NewLine,
@@ -282,7 +296,8 @@ private List<ToolManifestPackage> GetToolManifestPackageFromOneManifestFile(
282296
packageId,
283297
version,
284298
ToolCommandName.Convert(tools.Commands),
285-
correspondingDirectory));
299+
correspondingDirectory,
300+
rollForward));
286301
}
287302
}
288303

@@ -325,6 +340,7 @@ private class SerializableLocalToolSinglePackage
325340
public string PackageId { get; set; }
326341
public string Version { get; set; }
327342
public string[] Commands { get; set; }
343+
public bool RollForward { get; set; }
328344
}
329345

330346
private static bool CommandNamesEqual(ToolCommandName[] left, ToolCommandName[] right)
@@ -379,8 +395,8 @@ public string ToJson()
379395
{
380396
writer.WriteStringValue(toolCommandName);
381397
}
382-
383398
writer.WriteEndArray();
399+
writer.WriteBoolean(JsonPropertyRollForward, tool.RollForward);
384400
writer.WriteEndObject();
385401
}
386402

src/Cli/dotnet/ToolManifest/ToolManifestPackage.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ internal struct ToolManifestPackage : IEquatable<ToolManifestPackage>
1313
public PackageId PackageId { get; }
1414
public NuGetVersion Version { get; }
1515
public ToolCommandName[] CommandNames { get; }
16+
public bool RollForward { get; }
1617
/// <summary>
1718
/// The directory that will take effect first.
1819
/// When it is under .config directory, it is not .config directory
@@ -23,12 +24,14 @@ internal struct ToolManifestPackage : IEquatable<ToolManifestPackage>
2324
public ToolManifestPackage(PackageId packagePackageId,
2425
NuGetVersion version,
2526
ToolCommandName[] toolCommandNames,
26-
DirectoryPath firstEffectDirectory)
27+
DirectoryPath firstEffectDirectory,
28+
bool rollForward)
2729
{
2830
FirstEffectDirectory = firstEffectDirectory;
2931
PackageId = packagePackageId;
3032
Version = version ?? throw new ArgumentNullException(nameof(version));
3133
CommandNames = toolCommandNames ?? throw new ArgumentNullException(nameof(toolCommandNames));
34+
RollForward = rollForward;
3235
}
3336

3437
public override bool Equals(object obj)
@@ -43,7 +46,8 @@ public bool Equals(ToolManifestPackage other)
4346
EqualityComparer<NuGetVersion>.Default.Equals(Version, other.Version) &&
4447
CommandNamesEqual(other.CommandNames) &&
4548
FirstEffectDirectory.Value.TrimEnd('/', '\\')
46-
.Equals(other.FirstEffectDirectory.Value.TrimEnd('/', '\\'), StringComparison.Ordinal);
49+
.Equals(other.FirstEffectDirectory.Value.TrimEnd('/', '\\'), StringComparison.Ordinal) &&
50+
RollForward.Equals(other.RollForward);
4751
}
4852

4953
private bool CommandNamesEqual(ToolCommandName[] otherCommandNames)
@@ -63,7 +67,7 @@ private bool CommandNamesEqual(ToolCommandName[] otherCommandNames)
6367

6468
public override int GetHashCode()
6569
{
66-
return HashCode.Combine(PackageId, Version, CommandNames);
70+
return HashCode.Combine(PackageId, Version, CommandNames, RollForward);
6771
}
6872

6973
public static bool operator ==(ToolManifestPackage tool1,

src/Cli/dotnet/ToolManifest/xlf/LocalizableStrings.cs.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Cli/dotnet/ToolManifest/xlf/LocalizableStrings.de.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Cli/dotnet/ToolManifest/xlf/LocalizableStrings.es.xlf

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)