From 0ce1599a214e408f80e9cd506ab756df51e84db2 Mon Sep 17 00:00:00 2001 From: Sarah Oslund Date: Wed, 28 Jul 2021 13:20:44 -0700 Subject: [PATCH 1/3] Adding arch option to tool install command --- .../ShellShim/ShellShimRepositoryFactory.cs | 4 +- .../install/LocalizableStrings.resx | 5 +- .../install/ToolInstallCommandParser.cs | 5 ++ .../ToolInstallGlobalOrToolPathCommand.cs | 54 +++++++++++++++++-- .../install/xlf/LocalizableStrings.cs.xlf | 5 ++ .../install/xlf/LocalizableStrings.de.xlf | 5 ++ .../install/xlf/LocalizableStrings.es.xlf | 5 ++ .../install/xlf/LocalizableStrings.fr.xlf | 5 ++ .../install/xlf/LocalizableStrings.it.xlf | 5 ++ .../install/xlf/LocalizableStrings.ja.xlf | 5 ++ .../install/xlf/LocalizableStrings.ko.xlf | 5 ++ .../install/xlf/LocalizableStrings.pl.xlf | 5 ++ .../install/xlf/LocalizableStrings.pt-BR.xlf | 5 ++ .../install/xlf/LocalizableStrings.ru.xlf | 5 ++ .../install/xlf/LocalizableStrings.tr.xlf | 5 ++ .../xlf/LocalizableStrings.zh-Hans.xlf | 5 ++ .../xlf/LocalizableStrings.zh-Hant.xlf | 5 ++ .../ToolUninstallGlobalOrToolPathCommand.cs | 2 +- .../ToolUpdateGlobalOrToolPathCommand.cs | 2 +- .../MockNuGetPackageInstaller.cs | 14 +++-- ...ToolInstallGlobalOrToolPathCommandTests.cs | 39 +++++++++++++- ...olUninstallGlobalOrToolPathCommandTests.cs | 6 +-- .../ToolUpdateGlobalOrToolPathCommandTests.cs | 10 ++-- 23 files changed, 185 insertions(+), 21 deletions(-) diff --git a/src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs b/src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs index d84874984f5e..d66e323cd872 100644 --- a/src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs +++ b/src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs @@ -8,9 +8,9 @@ namespace Microsoft.DotNet.ShellShim { internal static class ShellShimRepositoryFactory { - public static IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null) + public static IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null, string appHostSourceDirectory = null) { - return new ShellShimRepository(nonGlobalLocation ?? GetShimLocation()); + return new ShellShimRepository(nonGlobalLocation ?? GetShimLocation(), appHostSourceDirectory); } private static DirectoryPath GetShimLocation() diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/LocalizableStrings.resx b/src/Cli/dotnet/commands/dotnet-tool/install/LocalizableStrings.resx index 07915fd4a259..1bc70e299613 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/LocalizableStrings.resx +++ b/src/Cli/dotnet/commands/dotnet-tool/install/LocalizableStrings.resx @@ -226,4 +226,7 @@ For more reasons, including package naming enforcement, visit https://aka.ms/fai 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. - \ No newline at end of file + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallCommandParser.cs b/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallCommandParser.cs index 67b93338fcdc..729a7c7d9060 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallCommandParser.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallCommandParser.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.CommandLine; +using Microsoft.DotNet.Tools; using Microsoft.DotNet.Tools.Tool.Common; using LocalizableStrings = Microsoft.DotNet.Tools.Tool.Install.LocalizableStrings; @@ -37,6 +38,9 @@ internal static class ToolInstallCommandParser public static readonly Option VerbosityOption = CommonOptions.VerbosityOption(); + // Don't use the common options version as we don't want this to be a forwarded option + public static readonly Option ArchitectureOption = new Option(new string[] { "--arch", "-a" }, CommonLocalizableStrings.ArchitectureOptionDescription); + public static Command GetCommand() { var command = new Command("install", LocalizableStrings.CommandDescription); @@ -55,6 +59,7 @@ public static Command GetCommand() command.AddOption(ToolCommandRestorePassThroughOptions.NoCacheOption); command.AddOption(ToolCommandRestorePassThroughOptions.InteractiveRestoreOption); command.AddOption(VerbosityOption); + command.AddOption(ArchitectureOption); return command; } diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs index 6b0e9b964385..5df060eb2be3 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs @@ -6,18 +6,23 @@ using System.CommandLine.Parsing; using System.IO; using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; using System.Transactions; using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Cli.NuGetPackageDownloader; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ShellShim; using Microsoft.DotNet.ToolPackage; using Microsoft.DotNet.Tools.Tool.Common; using Microsoft.Extensions.EnvironmentAbstractions; +using NuGet.Common; +using NuGet.Frameworks; using NuGet.Versioning; namespace Microsoft.DotNet.Tools.Tool.Install { - internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null); + internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null, string appHostSourceDirectory = null); internal delegate (IToolPackageStore, IToolPackageStoreQuery, IToolPackageInstaller) CreateToolPackageStoresAndInstaller( DirectoryPath? nonGlobalLocation = null, IEnumerable forwardRestoreArguments = null); @@ -38,14 +43,18 @@ internal class ToolInstallGlobalOrToolPathCommand : CommandBase private readonly bool _global; private readonly string _verbosity; private readonly string _toolPath; + private readonly string _architectureOption; private IEnumerable _forwardRestoreArguments; + private readonly DirectoryPath _tempDir; + private readonly INuGetPackageDownloader _nugetPackageDownloader; public ToolInstallGlobalOrToolPathCommand( ParseResult parseResult, CreateToolPackageStoresAndInstaller createToolPackageStoreAndInstaller = null, CreateShellShimRepository createShellShimRepository = null, IEnvironmentPathInstruction environmentPathInstruction = null, - IReporter reporter = null) + IReporter reporter = null, + INuGetPackageDownloader nugetPackageDownloader = null) : base(parseResult) { _packageId = new PackageId(parseResult.ValueForArgument(ToolInstallCommandParser.PackageIdArgument)); @@ -56,6 +65,7 @@ public ToolInstallGlobalOrToolPathCommand( _global = parseResult.ValueForOption(ToolAppliedOption.GlobalOptionAliases.First()); _verbosity = Enum.GetName(parseResult.ValueForOption(ToolInstallCommandParser.VerbosityOption)); _toolPath = parseResult.ValueForOption(ToolAppliedOption.ToolPathOptionAlias); + _architectureOption = parseResult.ValueForOption(ToolInstallCommandParser.ArchitectureOption); _createToolPackageStoresAndInstaller = createToolPackageStoreAndInstaller ?? ToolPackageFactory.CreateToolPackageStoresAndInstaller; _forwardRestoreArguments = parseResult.OptionValuesToBeForwarded(ToolInstallCommandParser.GetCommand()); @@ -63,6 +73,8 @@ public ToolInstallGlobalOrToolPathCommand( _environmentPathInstruction = environmentPathInstruction ?? EnvironmentPathFactory.CreateEnvironmentPathInstruction(); _createShellShimRepository = createShellShimRepository ?? ShellShimRepositoryFactory.CreateShellShimRepository; + _tempDir = new DirectoryPath(Path.Combine(Path.GetTempPath(), "dotnet-tool-install")); + _nugetPackageDownloader = nugetPackageDownloader ?? new NuGetPackageDownloader(_tempDir, verboseLogger: new NullLogger()); _reporter = (reporter ?? Reporter.Output); _errorReporter = (reporter ?? Reporter.Error); @@ -93,9 +105,11 @@ public override int Execute() toolPath = new DirectoryPath(_toolPath); } + string appHostSourceDirectory = ResolveAppHostSourceDirectoryAsync(_architectureOption, _framework).Result; + (IToolPackageStore toolPackageStore, IToolPackageStoreQuery toolPackageStoreQuery, IToolPackageInstaller toolPackageInstaller) = _createToolPackageStoresAndInstaller(toolPath, _forwardRestoreArguments); - IShellShimRepository shellShimRepository = _createShellShimRepository(toolPath); + IShellShimRepository shellShimRepository = _createShellShimRepository(toolPath, appHostSourceDirectory); // Prevent installation if any version of the package is installed if (toolPackageStoreQuery.EnumeratePackageVersions(_packageId).FirstOrDefault() != null) @@ -157,5 +171,39 @@ public override int Execute() isUserError: false); } } + + private async Task ResolveAppHostSourceDirectoryAsync(string archOption, string targetFramework) + { + string rid; + var validRids = new string[] { "win-x64", "win-arm64", "osx-x64", "osx-arm64" }; + if (string.IsNullOrEmpty(archOption)) + { + if (!string.IsNullOrEmpty(targetFramework) && new NuGetFramework(targetFramework).Version < new Version("6.0") + && (OperatingSystem.IsWindows() || OperatingSystem.IsMacOS()) && !RuntimeInformation.ProcessArchitecture.Equals(Architecture.X64)) + { + rid = OperatingSystem.IsWindows() ? "win-x64" : "osx-x64"; + } + else + { + // Use the default app host + return null; + } + } + else + { + rid = CommonOptions.ResolveRidShorthandOptionsToRuntimeIdentifier(null, archOption); + } + + if (!validRids.Contains(rid)) + { + throw new GracefulException(string.Format(LocalizableStrings.InvalidRuntimeIdentifier, rid, string.Join(" ", validRids))); + } + + var packageId = new PackageId($"microsoft.netcore.app.host.{rid}"); + var packagePath = await _nugetPackageDownloader.DownloadPackageAsync(packageId); + var content = await _nugetPackageDownloader.ExtractPackageAsync(packagePath, _tempDir); + + return Path.Combine(_tempDir.Value, "runtimes", rid, "native"); + } } } diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.cs.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.cs.xlf index 05e3ad97449a..235ccc5fa9f9 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.cs.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.cs.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. Nástroj {1} (verze {2}) byl úspěšně nainstalován. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Nainstaluje nástroj a přidá ho do manifestu místního nástroje (výchozí). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.de.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.de.xlf index 28b9fc354947..1c313e8a9507 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.de.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.de.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. Das Tool "{1}" (Version {2}) wurde erfolgreich installiert. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Hiermit installieren Sie das Tool und fügen es dem lokalen Toolmanifest (Standard) hinzu. diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.es.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.es.xlf index 0d9191f941ef..e39843bf33f1 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.es.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.es.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. La herramienta "{1}" (versión '{2}') se instaló correctamente. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Instalar la herramienta y agregar al manifiesto de la herramienta local (predeterminado). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.fr.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.fr.xlf index 56cab4985662..910a2ebee461 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.fr.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.fr.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. L'outil '{1}' (version '{2}') a été installé correctement. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Installe l'outil et l'ajoute au manifeste d'outils locaux (par défaut). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.it.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.it.xlf index f860557bc017..18c3b379f164 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.it.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.it.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. Lo strumento '{1}' (versione '{2}') è stato installato. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Installa lo strumento e lo aggiunge al manifesto degli strumenti locale (impostazione predefinita). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ja.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ja.xlf index 9a165c062d4e..3afac8284290 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ja.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ja.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. ツール '{1}' (バージョン '{2}') が正常にインストールされました。 + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). ツールをインストールし、ローカル ツール マニフェスト (既定値) に追加します。 diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ko.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ko.xlf index c5f7b20ee819..54fe943b00be 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ko.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ko.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. '{1}' 도구('{2}' 버전)가 설치되었습니다. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). 도구를 설치하고 로컬 도구 매니페스트에 추가합니다(기본값). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.pl.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.pl.xlf index 6d630e0edf05..d7e606e83b59 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.pl.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.pl.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. Pomyślnie zainstalowano narzędzie „{1}” (wersja: „{2}”). + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Zainstaluj narzędzie, a następnie dodaj je do manifestu narzędzi lokalnych (ustawienie domyślne). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.pt-BR.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.pt-BR.xlf index 13ceb59baf79..8637d713d906 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.pt-BR.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. A ferramenta '{1}' (versão '{2}') foi instalada com êxito. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Instale a ferramenta e adicione o manifesto de ferramenta local (padrão). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ru.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ru.xlf index 2f63d80b8dbd..b3374fe71145 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ru.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.ru.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. Средство "{1}" (версии "{2}") успешно установлено. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Установка средства и добавление его в манифест локального средства (по умолчанию). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.tr.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.tr.xlf index 15306f3481e9..e1616e09503a 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.tr.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.tr.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. '{1}' aracı (sürüm '{2}') başarıyla yüklendi. + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). Aracı yükle ve yerel araç bildirimine ekle (varsayılan). diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.zh-Hans.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.zh-Hans.xlf index 67714234a966..200c1fc63fd0 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.zh-Hans.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. 已成功安装工具“{1}”(版本“{2}”)。 + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). 安装工具并将其添加到本地工具清单(默认)。 diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.zh-Hant.xlf b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.zh-Hant.xlf index b9bcf081814f..604490d4d083 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Cli/dotnet/commands/dotnet-tool/install/xlf/LocalizableStrings.zh-Hant.xlf @@ -14,6 +14,11 @@ Tool '{1}' (version '{2}') was successfully installed. 已成功安裝工具 '{1}' ('{2}' 版)。 + + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + The runtime identifier {0} is invalid. Valid runtime identifiers are: {1}. + + Install the tool and add to the local tool manifest (default). 安裝工具,並將其新增至本機工具資訊清單 (預設)。 diff --git a/src/Cli/dotnet/commands/dotnet-tool/uninstall/ToolUninstallGlobalOrToolPathCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/uninstall/ToolUninstallGlobalOrToolPathCommand.cs index 6bbc649dbe1f..800650489231 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/uninstall/ToolUninstallGlobalOrToolPathCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/uninstall/ToolUninstallGlobalOrToolPathCommand.cs @@ -15,7 +15,7 @@ namespace Microsoft.DotNet.Tools.Tool.Uninstall { - internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null); + internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null, string appHostSourceDirectory = null); internal delegate (IToolPackageStore, IToolPackageStoreQuery, IToolPackageUninstaller) CreateToolPackageStoresAndUninstaller(DirectoryPath? nonGlobalLocation = null); internal class ToolUninstallGlobalOrToolPathCommand : CommandBase { diff --git a/src/Cli/dotnet/commands/dotnet-tool/update/ToolUpdateGlobalOrToolPathCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/update/ToolUpdateGlobalOrToolPathCommand.cs index ce7bf0a88229..ea1ee1d44f55 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/update/ToolUpdateGlobalOrToolPathCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/update/ToolUpdateGlobalOrToolPathCommand.cs @@ -19,7 +19,7 @@ namespace Microsoft.DotNet.Tools.Tool.Update { - internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null); + internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null, string appHostSourceDirectory = null); internal delegate (IToolPackageStore, IToolPackageStoreQuery, IToolPackageInstaller, IToolPackageUninstaller) CreateToolPackageStoresAndInstallerAndUninstaller( DirectoryPath? nonGlobalLocation = null, diff --git a/src/Tests/dotnet-workload-install.Tests/MockNuGetPackageInstaller.cs b/src/Tests/dotnet-workload-install.Tests/MockNuGetPackageInstaller.cs index 446a51fbd109..288df9725951 100644 --- a/src/Tests/dotnet-workload-install.Tests/MockNuGetPackageInstaller.cs +++ b/src/Tests/dotnet-workload-install.Tests/MockNuGetPackageInstaller.cs @@ -21,11 +21,14 @@ internal class MockNuGetPackageDownloader : INuGetPackageDownloader public List<(string, DirectoryPath)> ExtractCallParams = new List<(string, DirectoryPath)>(); - public MockNuGetPackageDownloader(string dotnetRoot, bool manifestDownload = false) + public MockNuGetPackageDownloader(string dotnetRoot = null, bool manifestDownload = false) { _manifestDownload = manifestDownload; - _downloadPath = Path.Combine(dotnetRoot, "metadata", "temp"); - Directory.CreateDirectory(_downloadPath); + _downloadPath = dotnetRoot == null ? string.Empty : Path.Combine(dotnetRoot, "metadata", "temp"); + if (_downloadPath != string.Empty) + { + Directory.CreateDirectory(_downloadPath); + } } public Task DownloadPackageAsync(PackageId packageId, @@ -37,7 +40,10 @@ public Task DownloadPackageAsync(PackageId packageId, DownloadCallParams.Add((packageId, packageVersion, downloadFolder, packageSourceLocation)); var path = Path.Combine(_downloadPath, "mock.nupkg"); DownloadCallResult.Add(path); - File.WriteAllText(path, string.Empty); + if (_downloadPath != string.Empty) + { + File.WriteAllText(path, string.Empty); + } return Task.FromResult(path); } diff --git a/src/Tests/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathCommandTests.cs b/src/Tests/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathCommandTests.cs index d6a57c3db26a..b0b2b53d9c55 100644 --- a/src/Tests/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathCommandTests.cs +++ b/src/Tests/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathCommandTests.cs @@ -21,6 +21,8 @@ using Microsoft.NET.TestFramework.Utilities; using System.CommandLine.Parsing; using Parser = Microsoft.DotNet.Cli.Parser; +using Microsoft.DotNet.Cli.NuGetPackageDownloader; +using Microsoft.NET.TestFramework; namespace Microsoft.DotNet.Tests.Commands.Tool { @@ -53,7 +55,7 @@ public ToolInstallGlobalOrToolPathCommandTests() _toolPackageStore = toolPackageStoreMock; _toolPackageStoreQuery = toolPackageStoreMock; _createShellShimRepository = - (nonGlobalLocation) => new ShellShimRepository( + (nonGlobalLocation, _) => new ShellShimRepository( new DirectoryPath(_pathToPlaceShim), fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem), @@ -453,6 +455,41 @@ [new PackageId(PackageId)] = new[] {new FilePath(prepackagedShimPath)} _fileSystem.File.ReadAllText(ExpectedCommandPath()).Should().Be(tokenToIdentifyPackagedShim); } + [Fact] + public void WhenRunWithArchOptionItErrorsOnInvalidRids() + { + _reporter.Clear(); + var parseResult = Parser.Instance.Parse($"dotnet tool install -g {PackageId} -a invalid"); + var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand( + parseResult, + _createToolPackageStoreAndInstaller, + _createShellShimRepository, + _environmentPathInstructionMock, + _reporter); + + var exceptionThrown = Assert.Throws(() => toolInstallGlobalOrToolPathCommand.Execute()); + exceptionThrown.Message.Should().Contain("-invalid is invalid"); + } + + [WindowsOnlyFact] + public void WhenRunWithArchOptionItDownloadsAppHostTemplate() + { + var nugetPackageDownloader = new MockNuGetPackageDownloader(); + var parseResult = Parser.Instance.Parse($"dotnet tool install -g {PackageId} -a arm64"); + var toolInstallGlobalOrToolPathCommand = new ToolInstallGlobalOrToolPathCommand( + parseResult, + _createToolPackageStoreAndInstaller, + _createShellShimRepository, + _environmentPathInstructionMock, + _reporter, + nugetPackageDownloader); + + toolInstallGlobalOrToolPathCommand.Execute().Should().Be(0); + nugetPackageDownloader.DownloadCallParams.Count.Should().Be(1); + nugetPackageDownloader.ExtractCallParams.Count.Should().Be(1); + nugetPackageDownloader.DownloadCallParams.First().Item1.Should().Be(new PackageId("microsoft.netcore.app.host.win-arm64")); + } + private IToolPackageInstaller CreateToolPackageInstaller( List feeds = null, Action installCallback = null) diff --git a/src/Tests/dotnet.Tests/CommandTests/ToolUninstallGlobalOrToolPathCommandTests.cs b/src/Tests/dotnet.Tests/CommandTests/ToolUninstallGlobalOrToolPathCommandTests.cs index a0ad2e4f1158..e72a779d11b2 100644 --- a/src/Tests/dotnet.Tests/CommandTests/ToolUninstallGlobalOrToolPathCommandTests.cs +++ b/src/Tests/dotnet.Tests/CommandTests/ToolUninstallGlobalOrToolPathCommandTests.cs @@ -145,7 +145,7 @@ public void GivenAPackageWhenCallFromUninstallRedirectCommandItUninstalls() var toolUninstallGlobalOrToolPathCommand = new ToolUninstallGlobalOrToolPathCommand( result, CreateToolPackageStoreAndUninstaller, - (_) => new ShellShimRepository( + (_, _) => new ShellShimRepository( new DirectoryPath(_shimsDirectory), fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem)), @@ -245,7 +245,7 @@ private ToolInstallGlobalOrToolPathCommand CreateInstallCommand(string options) return new ToolInstallGlobalOrToolPathCommand( result, (location, forwardArguments) => (store, store, packageInstallerMock), - (_) => new ShellShimRepository( + (_, _) => new ShellShimRepository( new DirectoryPath(_shimsDirectory), fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem)), @@ -270,7 +270,7 @@ private ToolUninstallGlobalOrToolPathCommand CreateUninstallCommand(string optio return new ToolUninstallGlobalOrToolPathCommand( result, createToolPackageStoreAndUninstaller, - (_) => new ShellShimRepository( + (_, _) => new ShellShimRepository( new DirectoryPath(_shimsDirectory), fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem)), diff --git a/src/Tests/dotnet.Tests/CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs b/src/Tests/dotnet.Tests/CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs index 1482a95e8968..6e1d1b1c6287 100644 --- a/src/Tests/dotnet.Tests/CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs +++ b/src/Tests/dotnet.Tests/CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs @@ -131,7 +131,7 @@ public void GivenAnExistedLowerversionInstallationWhenCallFromRedirectorItCanUpd _mockFeeds )), new ToolPackageUninstallerMock(_fileSystem, _store)), - (_) => GetMockedShellShimRepository(), + (_, _) => GetMockedShellShimRepository(), _reporter); var toolUpdateCommand = new ToolUpdateCommand( @@ -231,7 +231,7 @@ public void GivenAnExistedLowerversionWhenReinstallThrowsIthasTheFirstLineIndica ), installCallback: () => throw new ToolConfigurationException("Simulated error")), new ToolPackageUninstallerMock(_fileSystem, _store)), - _ => GetMockedShellShimRepository(), + (_, _) => GetMockedShellShimRepository(), _reporter); Action a = () => command.Execute(); @@ -260,7 +260,7 @@ public void GivenAnExistedLowerversionWhenReinstallThrowsItRollsBack() ), installCallback: () => throw new ToolConfigurationException("Simulated error")), new ToolPackageUninstallerMock(_fileSystem, _store)), - _ => GetMockedShellShimRepository(), + (_, _) => GetMockedShellShimRepository(), _reporter); Action a = () => command.Execute(); @@ -283,7 +283,7 @@ private ToolInstallGlobalOrToolPathCommand CreateInstallCommand(string options) _reporter, _mockFeeds ))), - (_) => GetMockedShellShimRepository(), + (_, _) => GetMockedShellShimRepository(), _environmentPathInstructionMock, _reporter); } @@ -303,7 +303,7 @@ private ToolUpdateGlobalOrToolPathCommand CreateUpdateCommand(string options) _mockFeeds )), new ToolPackageUninstallerMock(_fileSystem, _store)), - (_) => GetMockedShellShimRepository(), + (_, _) => GetMockedShellShimRepository(), _reporter); } From 997c9f70f55c3bf547d1602145a9d8d571222d34 Mon Sep 17 00:00:00 2001 From: Sarah Oslund Date: Thu, 29 Jul 2021 13:15:42 -0700 Subject: [PATCH 2/3] PR feedback --- .../NuGetPackageDownloader.cs | 23 +++++++ .../PackageSourceLocation.cs | 14 ++-- .../dotnet/ShellShim/ShellShimRepository.cs | 3 - .../ShellShim/ShellShimTemplateFinder.cs | 69 +++++++++++++++++++ .../ToolCommandRestorePassThroughOptions.cs | 8 +-- .../ToolInstallGlobalOrToolPathCommand.cs | 51 ++++---------- 6 files changed, 116 insertions(+), 52 deletions(-) create mode 100644 src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs diff --git a/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs b/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs index 33b6062aa537..4f4996b510fc 100644 --- a/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs +++ b/src/Cli/dotnet/NugetPackageDownloader/NuGetPackageDownloader.cs @@ -319,6 +319,29 @@ private IEnumerable LoadNuGetSources(PackageSourceLocation packag PackageSourceProvider packageSourceProvider = new PackageSourceProvider(settings); defaultSources = packageSourceProvider.LoadPackageSources().Where(source => source.IsEnabled); + + if (packageSourceLocation?.AdditionalSourceFeed?.Any() ?? false) + { + foreach (string source in packageSourceLocation?.AdditionalSourceFeed) + { + if (string.IsNullOrWhiteSpace(source)) + { + continue; + } + + PackageSource packageSource = new PackageSource(source); + if (packageSource.TrySourceAsUri == null) + { + _verboseLogger.LogWarning(string.Format( + LocalizableStrings.FailedToLoadNuGetSource, + source)); + continue; + } + + defaultSources = defaultSources.Append(packageSource); + } + } + if (!packageSourceLocation?.SourceFeedOverrides.Any() ?? true) { if (!defaultSources.Any()) diff --git a/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs b/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs index f1d9b180e6ac..ffb73c2fc9ca 100644 --- a/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs +++ b/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Collections.Generic; using System.IO; using Microsoft.Extensions.EnvironmentAbstractions; @@ -13,18 +12,21 @@ internal class PackageSourceLocation public PackageSourceLocation( FilePath? nugetConfig = null, DirectoryPath? rootConfigDirectory = null, - string[] sourceFeedOverrides = null) + string[] sourceFeedOverrides = null, + string[] additionalSourceFeeds = null) { NugetConfig = nugetConfig; RootConfigDirectory = rootConfigDirectory; - ExpandLocalFeedAndAssign(sourceFeedOverrides); + SourceFeedOverrides = ExpandLocalFeed(sourceFeedOverrides); + AdditionalSourceFeed = ExpandLocalFeed(additionalSourceFeeds); } public FilePath? NugetConfig { get; } public DirectoryPath? RootConfigDirectory { get; } public string[] SourceFeedOverrides { get; private set; } + public string[] AdditionalSourceFeed { get; private set; } - private void ExpandLocalFeedAndAssign(string[] sourceFeedOverrides) + private string[] ExpandLocalFeed(string[] sourceFeedOverrides) { if (sourceFeedOverrides != null) { @@ -42,11 +44,11 @@ private void ExpandLocalFeedAndAssign(string[] sourceFeedOverrides) } } - SourceFeedOverrides = localFeedsThatIsRooted; + return localFeedsThatIsRooted; } else { - SourceFeedOverrides = Array.Empty(); + return Array.Empty(); } } } diff --git a/src/Cli/dotnet/ShellShim/ShellShimRepository.cs b/src/Cli/dotnet/ShellShim/ShellShimRepository.cs index 214c351bc33c..0099dbd152e8 100644 --- a/src/Cli/dotnet/ShellShim/ShellShimRepository.cs +++ b/src/Cli/dotnet/ShellShim/ShellShimRepository.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools; @@ -15,8 +14,6 @@ namespace Microsoft.DotNet.ShellShim { internal class ShellShimRepository : IShellShimRepository { - private const string ApphostNameWithoutExtension = "apphost"; - private readonly DirectoryPath _shimsDirectory; private readonly IFileSystem _fileSystem; private readonly IAppHostShellShimMaker _appHostShellShimMaker; diff --git a/src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs b/src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs new file mode 100644 index 000000000000..abee3751a6fb --- /dev/null +++ b/src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs @@ -0,0 +1,69 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Cli.NuGetPackageDownloader; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ToolPackage; +using Microsoft.Extensions.EnvironmentAbstractions; +using NuGet.Frameworks; +using LocalizableStrings = Microsoft.DotNet.Tools.Tool.Install.LocalizableStrings; + +namespace Microsoft.DotNet.ShellShim +{ + internal class ShellShimTemplateFinder + { + private readonly DirectoryPath _tempDir; + private readonly INuGetPackageDownloader _nugetPackageDownloader; + private readonly PackageSourceLocation _packageSourceLocation; + + public ShellShimTemplateFinder( + INuGetPackageDownloader nugetPackageDownloader, + DirectoryPath tempDir, + PackageSourceLocation packageSourceLocation) + { + _tempDir = tempDir; + _nugetPackageDownloader = nugetPackageDownloader; + _packageSourceLocation = packageSourceLocation; + } + + public async Task ResolveAppHostSourceDirectoryAsync(string archOption, string targetFramework) + { + string rid; + var validRids = new string[] { "win-x64", "win-arm64", "osx-x64", "osx-arm64" }; + if (string.IsNullOrEmpty(archOption)) + { + if (!string.IsNullOrEmpty(targetFramework) && new NuGetFramework(targetFramework).Version < new Version("6.0") + && (OperatingSystem.IsWindows() || OperatingSystem.IsMacOS()) && !RuntimeInformation.ProcessArchitecture.Equals(Architecture.X64)) + { + rid = OperatingSystem.IsWindows() ? "win-x64" : "osx-x64"; + } + else + { + // Use the default app host + return null; + } + } + else + { + rid = CommonOptions.ResolveRidShorthandOptionsToRuntimeIdentifier(null, archOption); + } + + if (!validRids.Contains(rid)) + { + throw new GracefulException(string.Format(LocalizableStrings.InvalidRuntimeIdentifier, rid, string.Join(" ", validRids))); + } + + var packageId = new PackageId($"microsoft.netcore.app.host.{rid}"); + var packagePath = await _nugetPackageDownloader.DownloadPackageAsync(packageId, packageSourceLocation: _packageSourceLocation); + var content = await _nugetPackageDownloader.ExtractPackageAsync(packagePath, _tempDir); + + return Path.Combine(_tempDir.Value, "runtimes", rid, "native"); + } + } +} diff --git a/src/Cli/dotnet/commands/dotnet-tool/ToolCommandRestorePassThroughOptions.cs b/src/Cli/dotnet/commands/dotnet-tool/ToolCommandRestorePassThroughOptions.cs index b2d9957c9ed1..6d20b8a07701 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/ToolCommandRestorePassThroughOptions.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/ToolCommandRestorePassThroughOptions.cs @@ -11,22 +11,22 @@ namespace Microsoft.DotNet.Cli { internal static class ToolCommandRestorePassThroughOptions { - public static Option DisableParallelOption = new ForwardedOption( + public static Option DisableParallelOption = new ForwardedOption( "--disable-parallel", LocalizableStrings.CmdDisableParallelOptionDescription) .ForwardAs("--disable-parallel"); - public static Option NoCacheOption = new ForwardedOption( + public static Option NoCacheOption = new ForwardedOption( "--no-cache", LocalizableStrings.CmdNoCacheOptionDescription) .ForwardAs("--no-cache"); - public static Option IgnoreFailedSourcesOption = new ForwardedOption( + public static Option IgnoreFailedSourcesOption = new ForwardedOption( "--ignore-failed-sources", LocalizableStrings.CmdIgnoreFailedSourcesOptionDescription) .ForwardAs("--ignore-failed-sources"); - public static Option InteractiveRestoreOption = new ForwardedOption( + public static Option InteractiveRestoreOption = new ForwardedOption( "--interactive", CommonLocalizableStrings.CommandInteractiveOptionDescription) .ForwardAs(Constants.RestoreInteractiveOption); diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs index 5df060eb2be3..c1a14f926a7c 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs @@ -34,6 +34,7 @@ internal class ToolInstallGlobalOrToolPathCommand : CommandBase private readonly IReporter _errorReporter; private CreateShellShimRepository _createShellShimRepository; private CreateToolPackageStoresAndInstaller _createToolPackageStoresAndInstaller; + private readonly ShellShimTemplateFinder _shellShimTemplateFinder; private readonly PackageId _packageId; private readonly string _packageVersion; @@ -45,8 +46,6 @@ internal class ToolInstallGlobalOrToolPathCommand : CommandBase private readonly string _toolPath; private readonly string _architectureOption; private IEnumerable _forwardRestoreArguments; - private readonly DirectoryPath _tempDir; - private readonly INuGetPackageDownloader _nugetPackageDownloader; public ToolInstallGlobalOrToolPathCommand( ParseResult parseResult, @@ -73,8 +72,16 @@ public ToolInstallGlobalOrToolPathCommand( _environmentPathInstruction = environmentPathInstruction ?? EnvironmentPathFactory.CreateEnvironmentPathInstruction(); _createShellShimRepository = createShellShimRepository ?? ShellShimRepositoryFactory.CreateShellShimRepository; - _tempDir = new DirectoryPath(Path.Combine(Path.GetTempPath(), "dotnet-tool-install")); - _nugetPackageDownloader = nugetPackageDownloader ?? new NuGetPackageDownloader(_tempDir, verboseLogger: new NullLogger()); + var tempDir = new DirectoryPath(Path.Combine(Path.GetTempPath(), "dotnet-tool-install")); + var configOption = parseResult.ValueForOption(ToolInstallCommandParser.ConfigOption); + var sourceOption = parseResult.ValueForOption(ToolInstallCommandParser.AddSourceOption); + var packageSourceLocation = new PackageSourceLocation(string.IsNullOrEmpty(configOption) ? null : new FilePath(configOption), additionalSourceFeeds: sourceOption); + var restoreAction = new RestoreActionConfig(DisableParallel: parseResult.ValueForOption(ToolCommandRestorePassThroughOptions.DisableParallelOption), + NoCache: parseResult.ValueForOption(ToolCommandRestorePassThroughOptions.NoCacheOption), + IgnoreFailedSources: parseResult.ValueForOption(ToolCommandRestorePassThroughOptions.IgnoreFailedSourcesOption), + Interactive: parseResult.ValueForOption(ToolCommandRestorePassThroughOptions.InteractiveRestoreOption)); + nugetPackageDownloader ??= new NuGetPackageDownloader(tempDir, verboseLogger: new NullLogger(), restoreActionConfig: restoreAction); + _shellShimTemplateFinder = new ShellShimTemplateFinder(nugetPackageDownloader, tempDir, packageSourceLocation); _reporter = (reporter ?? Reporter.Output); _errorReporter = (reporter ?? Reporter.Error); @@ -105,7 +112,7 @@ public override int Execute() toolPath = new DirectoryPath(_toolPath); } - string appHostSourceDirectory = ResolveAppHostSourceDirectoryAsync(_architectureOption, _framework).Result; + string appHostSourceDirectory = _shellShimTemplateFinder.ResolveAppHostSourceDirectoryAsync(_architectureOption, _framework).Result; (IToolPackageStore toolPackageStore, IToolPackageStoreQuery toolPackageStoreQuery, IToolPackageInstaller toolPackageInstaller) = _createToolPackageStoresAndInstaller(toolPath, _forwardRestoreArguments); @@ -171,39 +178,5 @@ public override int Execute() isUserError: false); } } - - private async Task ResolveAppHostSourceDirectoryAsync(string archOption, string targetFramework) - { - string rid; - var validRids = new string[] { "win-x64", "win-arm64", "osx-x64", "osx-arm64" }; - if (string.IsNullOrEmpty(archOption)) - { - if (!string.IsNullOrEmpty(targetFramework) && new NuGetFramework(targetFramework).Version < new Version("6.0") - && (OperatingSystem.IsWindows() || OperatingSystem.IsMacOS()) && !RuntimeInformation.ProcessArchitecture.Equals(Architecture.X64)) - { - rid = OperatingSystem.IsWindows() ? "win-x64" : "osx-x64"; - } - else - { - // Use the default app host - return null; - } - } - else - { - rid = CommonOptions.ResolveRidShorthandOptionsToRuntimeIdentifier(null, archOption); - } - - if (!validRids.Contains(rid)) - { - throw new GracefulException(string.Format(LocalizableStrings.InvalidRuntimeIdentifier, rid, string.Join(" ", validRids))); - } - - var packageId = new PackageId($"microsoft.netcore.app.host.{rid}"); - var packagePath = await _nugetPackageDownloader.DownloadPackageAsync(packageId); - var content = await _nugetPackageDownloader.ExtractPackageAsync(packagePath, _tempDir); - - return Path.Combine(_tempDir.Value, "runtimes", rid, "native"); - } } } From 24bb41cd2d0a1e4ae9be51080cfc470f8453454b Mon Sep 17 00:00:00 2001 From: Sarah Oslund Date: Fri, 30 Jul 2021 11:45:56 -0700 Subject: [PATCH 3/3] PR feedback --- .../dotnet/NugetPackageDownloader/PackageSourceLocation.cs | 2 ++ src/Cli/dotnet/ShellShim/AppHostShimMaker.cs | 6 ++---- src/Cli/dotnet/ShellShim/ShellShimRepository.cs | 2 +- src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs | 2 +- src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs | 7 ++++++- .../install/ToolInstallGlobalOrToolPathCommand.cs | 4 ++-- .../uninstall/ToolUninstallGlobalOrToolPathCommand.cs | 5 +++-- .../update/ToolUpdateGlobalOrToolPathCommand.cs | 5 +++-- .../ShellShimRepositoryTests.cs | 1 + .../ToolInstallGlobalOrToolPathCommandTests.cs | 3 ++- .../ToolUninstallGlobalOrToolPathCommandTests.cs | 3 +++ .../CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs | 1 + 12 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs b/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs index ffb73c2fc9ca..d08a98936bca 100644 --- a/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs +++ b/src/Cli/dotnet/NugetPackageDownloader/PackageSourceLocation.cs @@ -17,7 +17,9 @@ public PackageSourceLocation( { NugetConfig = nugetConfig; RootConfigDirectory = rootConfigDirectory; + // Overrides other feeds SourceFeedOverrides = ExpandLocalFeed(sourceFeedOverrides); + // Feeds to be using in addition to config AdditionalSourceFeed = ExpandLocalFeed(additionalSourceFeeds); } diff --git a/src/Cli/dotnet/ShellShim/AppHostShimMaker.cs b/src/Cli/dotnet/ShellShim/AppHostShimMaker.cs index 538dbf31bd54..143aa509e891 100644 --- a/src/Cli/dotnet/ShellShim/AppHostShimMaker.cs +++ b/src/Cli/dotnet/ShellShim/AppHostShimMaker.cs @@ -18,11 +18,9 @@ internal class AppHostShellShimMaker : IAppHostShellShimMaker private readonly IFilePermissionSetter _filePermissionSetter; private const ushort WindowsGUISubsystem = 0x2; - public AppHostShellShimMaker(string appHostSourceDirectory = null, IFilePermissionSetter filePermissionSetter = null) + public AppHostShellShimMaker(string appHostSourceDirectory, IFilePermissionSetter filePermissionSetter = null) { - _appHostSourceDirectory = - appHostSourceDirectory - ?? Path.Combine(AppContext.BaseDirectory, "AppHostTemplate"); + _appHostSourceDirectory = appHostSourceDirectory; _filePermissionSetter = filePermissionSetter diff --git a/src/Cli/dotnet/ShellShim/ShellShimRepository.cs b/src/Cli/dotnet/ShellShim/ShellShimRepository.cs index 0099dbd152e8..4dee9748d079 100644 --- a/src/Cli/dotnet/ShellShim/ShellShimRepository.cs +++ b/src/Cli/dotnet/ShellShim/ShellShimRepository.cs @@ -21,7 +21,7 @@ internal class ShellShimRepository : IShellShimRepository public ShellShimRepository( DirectoryPath shimsDirectory, - string appHostSourceDirectory = null, + string appHostSourceDirectory, IFileSystem fileSystem = null, IAppHostShellShimMaker appHostShellShimMaker = null, IFilePermissionSetter filePermissionSetter = null) diff --git a/src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs b/src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs index d66e323cd872..f2470378f3a5 100644 --- a/src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs +++ b/src/Cli/dotnet/ShellShim/ShellShimRepositoryFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.DotNet.ShellShim { internal static class ShellShimRepositoryFactory { - public static IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null, string appHostSourceDirectory = null) + public static IShellShimRepository CreateShellShimRepository(string appHostSourceDirectory, DirectoryPath? nonGlobalLocation = null) { return new ShellShimRepository(nonGlobalLocation ?? GetShimLocation(), appHostSourceDirectory); } diff --git a/src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs b/src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs index abee3751a6fb..f850c9c2a2e6 100644 --- a/src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs +++ b/src/Cli/dotnet/ShellShim/ShellShimTemplateFinder.cs @@ -46,7 +46,7 @@ public async Task ResolveAppHostSourceDirectoryAsync(string archOption, else { // Use the default app host - return null; + return GetDefaultAppHostSourceDirectory(); } } else @@ -65,5 +65,10 @@ public async Task ResolveAppHostSourceDirectoryAsync(string archOption, return Path.Combine(_tempDir.Value, "runtimes", rid, "native"); } + + public static string GetDefaultAppHostSourceDirectory() + { + return Path.Combine(AppContext.BaseDirectory, "AppHostTemplate"); + } } } diff --git a/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs index c1a14f926a7c..bd193c515e83 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/install/ToolInstallGlobalOrToolPathCommand.cs @@ -22,7 +22,7 @@ namespace Microsoft.DotNet.Tools.Tool.Install { - internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null, string appHostSourceDirectory = null); + internal delegate IShellShimRepository CreateShellShimRepository(string appHostSourceDirectory, DirectoryPath? nonGlobalLocation = null); internal delegate (IToolPackageStore, IToolPackageStoreQuery, IToolPackageInstaller) CreateToolPackageStoresAndInstaller( DirectoryPath? nonGlobalLocation = null, IEnumerable forwardRestoreArguments = null); @@ -116,7 +116,7 @@ public override int Execute() (IToolPackageStore toolPackageStore, IToolPackageStoreQuery toolPackageStoreQuery, IToolPackageInstaller toolPackageInstaller) = _createToolPackageStoresAndInstaller(toolPath, _forwardRestoreArguments); - IShellShimRepository shellShimRepository = _createShellShimRepository(toolPath, appHostSourceDirectory); + IShellShimRepository shellShimRepository = _createShellShimRepository(appHostSourceDirectory, toolPath); // Prevent installation if any version of the package is installed if (toolPackageStoreQuery.EnumeratePackageVersions(_packageId).FirstOrDefault() != null) diff --git a/src/Cli/dotnet/commands/dotnet-tool/uninstall/ToolUninstallGlobalOrToolPathCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/uninstall/ToolUninstallGlobalOrToolPathCommand.cs index 800650489231..78b6287e8353 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/uninstall/ToolUninstallGlobalOrToolPathCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/uninstall/ToolUninstallGlobalOrToolPathCommand.cs @@ -15,7 +15,7 @@ namespace Microsoft.DotNet.Tools.Tool.Uninstall { - internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null, string appHostSourceDirectory = null); + internal delegate IShellShimRepository CreateShellShimRepository(string appHostSourceDirectory, DirectoryPath? nonGlobalLocation = null); internal delegate (IToolPackageStore, IToolPackageStoreQuery, IToolPackageUninstaller) CreateToolPackageStoresAndUninstaller(DirectoryPath? nonGlobalLocation = null); internal class ToolUninstallGlobalOrToolPathCommand : CommandBase { @@ -60,7 +60,8 @@ public override int Execute() (IToolPackageStore toolPackageStore, IToolPackageStoreQuery toolPackageStoreQuery, IToolPackageUninstaller toolPackageUninstaller) = _createToolPackageStoresAndUninstaller(toolDirectoryPath); - IShellShimRepository shellShimRepository = _createShellShimRepository(toolDirectoryPath); + var appHostSourceDirectory = ShellShimTemplateFinder.GetDefaultAppHostSourceDirectory(); + IShellShimRepository shellShimRepository = _createShellShimRepository(appHostSourceDirectory, toolDirectoryPath); var packageId = new PackageId(_parseResult.ValueForArgument(ToolInstallCommandParser.PackageIdArgument)); IToolPackage package = null; diff --git a/src/Cli/dotnet/commands/dotnet-tool/update/ToolUpdateGlobalOrToolPathCommand.cs b/src/Cli/dotnet/commands/dotnet-tool/update/ToolUpdateGlobalOrToolPathCommand.cs index ea1ee1d44f55..6320c78e4090 100644 --- a/src/Cli/dotnet/commands/dotnet-tool/update/ToolUpdateGlobalOrToolPathCommand.cs +++ b/src/Cli/dotnet/commands/dotnet-tool/update/ToolUpdateGlobalOrToolPathCommand.cs @@ -19,7 +19,7 @@ namespace Microsoft.DotNet.Tools.Tool.Update { - internal delegate IShellShimRepository CreateShellShimRepository(DirectoryPath? nonGlobalLocation = null, string appHostSourceDirectory = null); + internal delegate IShellShimRepository CreateShellShimRepository(string appHostSourceDirectory, DirectoryPath? nonGlobalLocation = null); internal delegate (IToolPackageStore, IToolPackageStoreQuery, IToolPackageInstaller, IToolPackageUninstaller) CreateToolPackageStoresAndInstallerAndUninstaller( DirectoryPath? nonGlobalLocation = null, @@ -92,7 +92,8 @@ public override int Execute() IToolPackageInstaller toolPackageInstaller, IToolPackageUninstaller toolPackageUninstaller) = _createToolPackageStoreInstallerUninstaller(toolPath, _forwardRestoreArguments); - IShellShimRepository shellShimRepository = _createShellShimRepository(toolPath); + var appHostSourceDirectory = ShellShimTemplateFinder.GetDefaultAppHostSourceDirectory(); + IShellShimRepository shellShimRepository = _createShellShimRepository(appHostSourceDirectory, toolPath); IToolPackage oldPackageNullable = GetOldPackage(toolPackageStoreQuery); diff --git a/src/Tests/Microsoft.DotNet.ShellShim.Tests/ShellShimRepositoryTests.cs b/src/Tests/Microsoft.DotNet.ShellShim.Tests/ShellShimRepositoryTests.cs index 4285a0a7d5cf..8504068bed60 100644 --- a/src/Tests/Microsoft.DotNet.ShellShim.Tests/ShellShimRepositoryTests.cs +++ b/src/Tests/Microsoft.DotNet.ShellShim.Tests/ShellShimRepositoryTests.cs @@ -498,6 +498,7 @@ private ShellShimRepository GetShellShimRepositoryWithMockMaker(string pathToShi { return new ShellShimRepository( new DirectoryPath(pathToShim), + string.Empty, appHostShellShimMaker: new AppHostShellShimMakerMock()); } } diff --git a/src/Tests/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathCommandTests.cs b/src/Tests/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathCommandTests.cs index b0b2b53d9c55..1d2b57b26616 100644 --- a/src/Tests/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathCommandTests.cs +++ b/src/Tests/dotnet.Tests/CommandTests/ToolInstallGlobalOrToolPathCommandTests.cs @@ -55,8 +55,9 @@ public ToolInstallGlobalOrToolPathCommandTests() _toolPackageStore = toolPackageStoreMock; _toolPackageStoreQuery = toolPackageStoreMock; _createShellShimRepository = - (nonGlobalLocation, _) => new ShellShimRepository( + (_, nonGlobalLocation) => new ShellShimRepository( new DirectoryPath(_pathToPlaceShim), + string.Empty, fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem), filePermissionSetter: new NoOpFilePermissionSetter()); diff --git a/src/Tests/dotnet.Tests/CommandTests/ToolUninstallGlobalOrToolPathCommandTests.cs b/src/Tests/dotnet.Tests/CommandTests/ToolUninstallGlobalOrToolPathCommandTests.cs index e72a779d11b2..99957e9df89c 100644 --- a/src/Tests/dotnet.Tests/CommandTests/ToolUninstallGlobalOrToolPathCommandTests.cs +++ b/src/Tests/dotnet.Tests/CommandTests/ToolUninstallGlobalOrToolPathCommandTests.cs @@ -147,6 +147,7 @@ public void GivenAPackageWhenCallFromUninstallRedirectCommandItUninstalls() CreateToolPackageStoreAndUninstaller, (_, _) => new ShellShimRepository( new DirectoryPath(_shimsDirectory), + string.Empty, fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem)), _reporter); @@ -247,6 +248,7 @@ private ToolInstallGlobalOrToolPathCommand CreateInstallCommand(string options) (location, forwardArguments) => (store, store, packageInstallerMock), (_, _) => new ShellShimRepository( new DirectoryPath(_shimsDirectory), + string.Empty, fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem)), _environmentPathInstructionMock, @@ -272,6 +274,7 @@ private ToolUninstallGlobalOrToolPathCommand CreateUninstallCommand(string optio createToolPackageStoreAndUninstaller, (_, _) => new ShellShimRepository( new DirectoryPath(_shimsDirectory), + string.Empty, fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem)), _reporter); diff --git a/src/Tests/dotnet.Tests/CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs b/src/Tests/dotnet.Tests/CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs index 6e1d1b1c6287..51c41bb46c1a 100644 --- a/src/Tests/dotnet.Tests/CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs +++ b/src/Tests/dotnet.Tests/CommandTests/ToolUpdateGlobalOrToolPathCommandTests.cs @@ -311,6 +311,7 @@ private ShellShimRepository GetMockedShellShimRepository() { return new ShellShimRepository( new DirectoryPath(_shimsDirectory), + string.Empty, fileSystem: _fileSystem, appHostShellShimMaker: new AppHostShellShimMakerMock(_fileSystem)); }