From d6c515a4a4c49beef65ae58352b7f40e8b0ab6b9 Mon Sep 17 00:00:00 2001 From: "Jiaqi (Jacky) Wang" Date: Tue, 25 Oct 2022 14:13:35 -0400 Subject: [PATCH] [dotnet tool] Add ability to check if a tool is installed (#28333) --- .../dotnet-tool/list/LocalizableStrings.resx | 6 ++ .../dotnet-tool/list/ToolListCommandParser.cs | 7 ++ .../list/ToolListGlobalOrToolPathCommand.cs | 24 ++++++- .../dotnet-tool/list/ToolListLocalCommand.cs | 23 ++++++- .../list/xlf/LocalizableStrings.cs.xlf | 10 +++ .../list/xlf/LocalizableStrings.de.xlf | 10 +++ .../list/xlf/LocalizableStrings.es.xlf | 10 +++ .../list/xlf/LocalizableStrings.fr.xlf | 10 +++ .../list/xlf/LocalizableStrings.it.xlf | 10 +++ .../list/xlf/LocalizableStrings.ja.xlf | 10 +++ .../list/xlf/LocalizableStrings.ko.xlf | 10 +++ .../list/xlf/LocalizableStrings.pl.xlf | 10 +++ .../list/xlf/LocalizableStrings.pt-BR.xlf | 10 +++ .../list/xlf/LocalizableStrings.ru.xlf | 10 +++ .../list/xlf/LocalizableStrings.tr.xlf | 10 +++ .../list/xlf/LocalizableStrings.zh-Hans.xlf | 10 +++ .../list/xlf/LocalizableStrings.zh-Hant.xlf | 10 +++ .../ToolListGlobalOrToolPathCommandTests.cs | 66 ++++++++++++++++++- .../CommandTests/ToolListLocalCommandTests.cs | 43 ++++++++++++ 19 files changed, 293 insertions(+), 6 deletions(-) diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-tool/list/LocalizableStrings.resx index 6b1c1414eef4..61853646e7cc 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-tool/list/LocalizableStrings.resx @@ -154,4 +154,10 @@ The local option(--local), the global option (--global), the tool path option (--tool-path), can only have one at a time. Specify only one of the options: {0}. + + The NuGet Package Id of the tool to list + + + PACKAGE_ID + diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/ToolListCommandParser.cs b/src/Cli/dotnet/commands/dotnet-tool/list/ToolListCommandParser.cs index 85661b04ca71..df1f7c69aff1 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/ToolListCommandParser.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/list/ToolListCommandParser.cs @@ -13,6 +13,12 @@ namespace Microsoft.DotNet.Cli { internal static class ToolListCommandParser { + public static readonly Argument PackageIdArgument = new Argument(LocalizableStrings.PackageIdArgumentName) + { + Description = LocalizableStrings.PackageIdArgumentDescription, + Arity = ArgumentArity.ZeroOrOne, + }; + public static readonly Option GlobalOption = ToolAppliedOption.GlobalOption; public static readonly Option LocalOption = ToolAppliedOption.LocalOption; @@ -30,6 +36,7 @@ private static Command ConstructCommand() { var command = new Command("list", LocalizableStrings.CommandDescription); + command.AddArgument(PackageIdArgument); command.AddOption(GlobalOption.WithHelpDescription(command, LocalizableStrings.GlobalOptionDescription)); command.AddOption(LocalOption.WithHelpDescription(command, LocalizableStrings.LocalOptionDescription)); command.AddOption(ToolPathOption.WithHelpDescription(command, LocalizableStrings.ToolPathOptionDescription)); diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/ToolListGlobalOrToolPathCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/list/ToolListGlobalOrToolPathCommand.cs index 2b9a6c0d3bb4..89c2098f58f2 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/ToolListGlobalOrToolPathCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/list/ToolListGlobalOrToolPathCommand.cs @@ -37,6 +37,13 @@ public ToolListGlobalOrToolPathCommand( public override int Execute() { var toolPathOption = _parseResult.GetValueForOption(ToolListCommandParser.ToolPathOption); + var packageIdArgument = _parseResult.GetValueForArgument(ToolListCommandParser.PackageIdArgument); + + PackageId? packageId = null; + if (!string.IsNullOrWhiteSpace(packageIdArgument)) + { + packageId = new PackageId(packageIdArgument); + } DirectoryPath? toolPath = null; if (!string.IsNullOrWhiteSpace(toolPathOption)) @@ -64,18 +71,29 @@ public override int Execute() LocalizableStrings.CommandsColumn, p => string.Join(CommandDelimiter, p.Commands.Select(c => c.Name))); - table.PrintRows(GetPackages(toolPath), l => _reporter.WriteLine(l)); + var packageEnumerable = GetPackages(toolPath, packageId); + table.PrintRows(packageEnumerable, l => _reporter.WriteLine(l)); + if (packageId.HasValue && !packageEnumerable.Any()) + { + // return 1 if target package was not found + return 1; + } return 0; } - private IEnumerable GetPackages(DirectoryPath? toolPath) + private IEnumerable GetPackages(DirectoryPath? toolPath, PackageId? packageId) { return _createToolPackageStore(toolPath).EnumeratePackages() - .Where(PackageHasCommands) + .Where((p) => PackageHasCommands(p) && PackageIdMatches(p, packageId)) .OrderBy(p => p.Id) .ToArray(); } + internal static bool PackageIdMatches(IToolPackage package, PackageId? packageId) + { + return !packageId.HasValue || package.Id.Equals(packageId); + } + private bool PackageHasCommands(IToolPackage package) { try diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/ToolListLocalCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/list/ToolListLocalCommand.cs index 9a320314e981..05c79b7d2064 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/ToolListLocalCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/list/ToolListLocalCommand.cs @@ -8,6 +8,7 @@ using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ToolManifest; +using Microsoft.DotNet.ToolPackage; using Microsoft.Extensions.EnvironmentAbstractions; namespace Microsoft.DotNet.Tools.Tool.List @@ -33,6 +34,12 @@ public ToolListLocalCommand( public override int Execute() { var table = new PrintableTable<(ToolManifestPackage toolManifestPackage, FilePath SourceManifest)>(); + var packageIdArgument = _parseResult.GetValueForArgument(ToolListCommandParser.PackageIdArgument); + PackageId? packageId = null; + if (!string.IsNullOrWhiteSpace(packageIdArgument)) + { + packageId = new PackageId(packageIdArgument); + } table.AddColumn( LocalizableStrings.PackageIdColumn, @@ -47,8 +54,22 @@ public override int Execute() LocalizableStrings.ManifestFileColumn, p => p.SourceManifest.Value); - table.PrintRows(_toolManifestInspector.Inspect(), l => _reporter.WriteLine(l)); + var packageEnumerable = _toolManifestInspector.Inspect().Where( + (t) => PackageIdMatches(t.toolManifestPackage, packageId) + ); + table.PrintRows(packageEnumerable, l => _reporter.WriteLine(l)); + + if (packageId.HasValue && !packageEnumerable.Any()) + { + // return 1 if target package was not found + return 1; + } return 0; } + + private bool PackageIdMatches(ToolManifestPackage package, PackageId? packageId) + { + return !packageId.HasValue || package.PackageId.Equals(packageId); + } } } diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.cs.xlf index 43c6b2e13f72..a63ff40b89ef 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.cs.xlf @@ -27,6 +27,16 @@ Manifest + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Verze diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.de.xlf index 673b6c27a7ae..61de2f1c30e4 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.de.xlf @@ -27,6 +27,16 @@ Manifest + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Version diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.es.xlf index 57468ba3408d..0a8206f83f47 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.es.xlf @@ -27,6 +27,16 @@ Manifiesto + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Versión diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.fr.xlf index 5632fee4468b..367e50c428e1 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.fr.xlf @@ -27,6 +27,16 @@ Manifeste + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Version diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.it.xlf index 676596d29878..45a1d3cc8a18 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.it.xlf @@ -27,6 +27,16 @@ Manifesto + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Versione diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ja.xlf index 0cd06def63aa..9ac681fa4f43 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ja.xlf @@ -27,6 +27,16 @@ マニフェスト + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version バージョン diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ko.xlf index e4700912f4d5..83d7948466db 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ko.xlf @@ -27,6 +27,16 @@ 매니페스트 + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version 버전 diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.pl.xlf index b8fa7c07d7d0..c0225fb1f0a3 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.pl.xlf @@ -27,6 +27,16 @@ Manifest + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Wersja diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.pt-BR.xlf index d4177455fc2f..41bda9338f36 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.pt-BR.xlf @@ -27,6 +27,16 @@ Manifesto + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Versão diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ru.xlf index fd30d54b48a4..691cbca449b6 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.ru.xlf @@ -27,6 +27,16 @@ Манифест + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Версия diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.tr.xlf index db3000740fe2..3612a1edc4d2 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.tr.xlf @@ -27,6 +27,16 @@ Bildirim + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version Sürüm diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.zh-Hans.xlf index 288fff1aa1de..be091152079a 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.zh-Hans.xlf @@ -27,6 +27,16 @@ 清单 + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version 版本 diff --git a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.zh-Hant.xlf index 97877fb08275..660a03f5d44e 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/list/xlf/LocalizableStrings.zh-Hant.xlf @@ -27,6 +27,16 @@ 資訊清單 + + The NuGet Package Id of the tool to list + The NuGet Package Id of the tool to list + + + + PACKAGE_ID + PACKAGE_ID + + Version 版本 diff --git a/src/Tests/dotnet.Tests/CommandTests/ToolListGlobalOrToolPathCommandTests.cs b/src/Tests/dotnet.Tests/CommandTests/ToolListGlobalOrToolPathCommandTests.cs index 1055f63d5b29..a2850b1409c9 100644 --- a/src/Tests/dotnet.Tests/CommandTests/ToolListGlobalOrToolPathCommandTests.cs +++ b/src/Tests/dotnet.Tests/CommandTests/ToolListGlobalOrToolPathCommandTests.cs @@ -241,6 +241,66 @@ private IToolPackage CreateMockToolPackage(string id, string version, IReadOnlyL return package.Object; } + [Fact] + public void GivenPackageIdArgItPrintsThatPackage() + { + var store = new Mock(MockBehavior.Strict); + store + .Setup(s => s.EnumeratePackages()) + .Returns(new[] { + CreateMockToolPackage( + "test.tool", + "1.3.5-preview", + new[] { + new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool")) + } + ), + CreateMockToolPackage( + "another.tool", + "2.7.3", + new[] { + new RestoredCommand(new ToolCommandName("bar"), "dotnet", new FilePath("tool")) + } + ), + CreateMockToolPackage( + "some.tool", + "1.0.0", + new[] { + new RestoredCommand(new ToolCommandName("fancy-foo"), "dotnet", new FilePath("tool")) + } + ) + }); + + var command = CreateCommand(store.Object, "test.tool -g"); + + command.Execute().Should().Be(0); + + _reporter.Lines.Should().Equal(EnumerateExpectedTableLines(store.Object, new PackageId("test.tool"))); + } + + [Fact] + public void GivenNotInstalledPackageItPrintsEmpty() + { + var store = new Mock(MockBehavior.Strict); + store + .Setup(s => s.EnumeratePackages()) + .Returns(new[] { + CreateMockToolPackage( + "test.tool", + "1.3.5-preview", + new[] { + new RestoredCommand(new ToolCommandName("foo"), "dotnet", new FilePath("tool")) + } + ) + }); + + var command = CreateCommand(store.Object, "not-installed-package -g"); + + command.Execute().Should().Be(1); + + _reporter.Lines.Should().Equal(EnumerateExpectedTableLines(store.Object, new PackageId("not-installed-package"))); + } + private IToolPackage CreateMockBrokenPackage(string id, string version) { var package = new Mock(MockBehavior.Strict); @@ -273,14 +333,16 @@ private void AssertExpectedToolPath(DirectoryPath? toolPath, string expectedTool } } - private IEnumerable EnumerateExpectedTableLines(IToolPackageStoreQuery store) + private IEnumerable EnumerateExpectedTableLines(IToolPackageStoreQuery store, PackageId? targetPackageId = null) { static string GetCommandsString(IToolPackage package) { return string.Join(ToolListGlobalOrToolPathCommand.CommandDelimiter, package.Commands.Select(c => c.Name)); } - var packages = store.EnumeratePackages().Where(PackageHasCommands).OrderBy(package => package.Id); + var packages = store.EnumeratePackages().Where( + (p) => PackageHasCommands(p) && ToolListGlobalOrToolPathCommand.PackageIdMatches(p, targetPackageId) + ).OrderBy(package => package.Id); var columnDelimiter = PrintableTable.ColumnDelimiter; int packageIdColumnWidth = LocalizableStrings.PackageIdColumn.Length; diff --git a/src/Tests/dotnet.Tests/CommandTests/ToolListLocalCommandTests.cs b/src/Tests/dotnet.Tests/CommandTests/ToolListLocalCommandTests.cs index 7eaeeddd5d19..80af5ab4a0e1 100644 --- a/src/Tests/dotnet.Tests/CommandTests/ToolListLocalCommandTests.cs +++ b/src/Tests/dotnet.Tests/CommandTests/ToolListLocalCommandTests.cs @@ -41,6 +41,11 @@ public ToolListLocalCommandTests() NuGetVersion.Parse("2.1.4"), new[] {new ToolCommandName("package-name")}, new DirectoryPath(_temporaryDirectory)), new FilePath(_testManifestPath)), + (new ToolManifestPackage( + new PackageId("foo.bar"), + NuGetVersion.Parse("1.0.8"), + new[] {new ToolCommandName("foo-bar")}, + new DirectoryPath(_temporaryDirectory)), new FilePath(_testManifestPath)) } ); _parseResult = Parser.Instance.Parse("dotnet tool list"); @@ -54,10 +59,15 @@ public ToolListLocalCommandTests() public void GivenManifestInspectorItPrintsTheTable() { _defaultToolListLocalCommand.Execute(); + _reporter.Lines.Count.Should().Be(4); _reporter.Lines.Should().Contain(l => l.Contains("package.id")); _reporter.Lines.Should().Contain(l => l.Contains("2.1.4")); _reporter.Lines.Should().Contain(l => l.Contains(_testManifestPath)); _reporter.Lines.Should().Contain(l => l.Contains("package-name")); + _reporter.Lines.Should().Contain(l => l.Contains("foo.bar")); + _reporter.Lines.Should().Contain(l => l.Contains("1.0.8")); + _reporter.Lines.Should().Contain(l => l.Contains(_testManifestPath)); + _reporter.Lines.Should().Contain(l => l.Contains("foo-bar")); } [Fact] @@ -66,12 +76,45 @@ public void GivenManifestInspectorWhenCalledFromRedirectCommandItPrintsTheTable( var command = new ToolListCommand(result: _parseResult, toolListLocalCommand: _defaultToolListLocalCommand); _defaultToolListLocalCommand.Execute(); + _reporter.Lines.Count.Should().Be(4); + _reporter.Lines.Should().Contain(l => l.Contains("package.id")); + _reporter.Lines.Should().Contain(l => l.Contains("2.1.4")); + _reporter.Lines.Should().Contain(l => l.Contains(_testManifestPath)); + _reporter.Lines.Should().Contain(l => l.Contains("package-name")); + _reporter.Lines.Should().Contain(l => l.Contains("foo.bar")); + _reporter.Lines.Should().Contain(l => l.Contains("1.0.8")); + _reporter.Lines.Should().Contain(l => l.Contains(_testManifestPath)); + _reporter.Lines.Should().Contain(l => l.Contains("foo-bar")); + } + + [Fact] + public void GivenPackageIdArgumentItPrintsTheCorrectPackageInfo() + { + CreateCommandWithArg("package.id").Execute().Should().Be(0); + _reporter.Lines.Count.Should().Be(3); _reporter.Lines.Should().Contain(l => l.Contains("package.id")); _reporter.Lines.Should().Contain(l => l.Contains("2.1.4")); _reporter.Lines.Should().Contain(l => l.Contains(_testManifestPath)); _reporter.Lines.Should().Contain(l => l.Contains("package-name")); } + [Fact] + public void GivenNotInstalledPackageItPrintsEmpty() + { + CreateCommandWithArg("not-installed-package").Execute().Should().Be(1); + _reporter.Lines.Count.Should().Be(2); + } + + private ToolListLocalCommand CreateCommandWithArg(string arg) + { + var parseResult = Parser.Instance.Parse("dotnet tool list " + arg); + var command = new ToolListLocalCommand( + parseResult, + _toolManifestInspector, + _reporter); + return command; + } + private class FakeManifestInspector : IToolManifestInspector { private readonly IReadOnlyCollection<(ToolManifestPackage toolManifestPackage, FilePath SourceManifest)>