From 55f62d9d646b558d53c56e226a9ddc3dc003a23b Mon Sep 17 00:00:00 2001 From: William Lee Date: Mon, 4 Dec 2017 14:13:24 -0800 Subject: [PATCH] Add install tool command (#8132) * compose all the parts * Fix on obtain and shim maker for better end to end experience * Fix error when there is space in the middle of path of nuget config * Fix path in profile.d is the tmp home path during install * better handle of ~home * remove profile.d file in uninstall script * Fix test since it looks up current directory * folder structure inside nupkg to tools/TFM/RID/mytool.dll * Add check for config file existence * Rename name space to Microsoft.DotNet.ShellShim * Rename name space to Microsoft.DotNet.ToolPackage --- Microsoft.DotNet.Cli.sln | 104 +++++++------- .../dotnet-uninstall-debian-packages.sh | 3 + .../obtain/uninstall/dotnet-uninstall-pkgs.sh | 2 + .../dotnet-uninstall-rpm-packages.sh | 3 + .../Properties/AssemblyInfo.cs | 2 +- .../BashPathUnderHomeDirectory.cs | 23 ++++ .../CliFolderPathCalculator.cs | 12 +- .../Properties/Properties.cs | 2 +- src/dotnet/BuiltInCommandsCatalog.cs | 7 +- src/dotnet/Parser.cs | 3 +- src/dotnet/Program.cs | 2 +- src/dotnet/Properties/AssemblyInfo.cs | 4 +- .../DoNothingEnvironmentPath.cs | 2 +- .../EnvironmentPathFactory.cs | 7 +- .../LinuxEnvironmentPath.cs | 21 +-- .../OsxEnvironmentPath.cs | 24 ++-- .../ShellShimMaker.cs | 2 +- .../WindowsEnvironmentPath.cs | 4 +- .../IPackageToProjectFileAdder.cs | 2 +- .../IProjectRestorer.cs | 2 +- .../PackageObtainException.cs | 2 +- .../PackageVersion.cs | 2 +- .../ToolConfiguration.cs | 8 +- ...ToolConfigurationAndExecutableDirectory.cs | 2 +- .../DotNetCliTool.cs | 2 +- .../DotNetCliToolCommand.cs | 2 +- .../ToolConfigurationDeserializer.cs | 12 +- .../ToolConfigurationException.cs | 2 +- .../ToolPackageObtainer.cs | 50 +++++-- .../commands/dotnet-install/InstallCommand.cs | 36 +++++ .../dotnet-install/InstallCommandParser.cs | 19 +++ .../dotnet-install-tool/InstallToolCommand.cs | 130 ++++++++++++++++++ .../InstallToolCommandParser.cs | 32 +++++ .../PackageToProjectFileAdder.cs | 6 +- .../ProjectRestorer.cs | 9 +- src/dotnet/dotnet.csproj | 2 +- test/Microsoft.DotNet.Cli.Tests.sln | 52 +++---- .../FakeEnvironmentProvider.cs | 2 +- .../FakeFile.cs | 2 +- .../FakeReporter.cs | 2 +- .../LinuxEnvironmentPathTests.cs | 19 +-- .../Microsoft.DotNet.ShellShim.Tests.csproj} | 0 .../OsxEnvironmentPathTests.cs | 18 ++- .../ShellShimMakerTests.cs | 2 +- .../DotnetToolSettingsGolden.xml} | 0 .../DotnetToolSettingsMalformed.xml} | 0 .../DotnetToolSettingsMissing.xml} | 0 ...Microsoft.DotNet.ToolPackage.Tests.csproj} | 8 +- .../SampleGlobalTool/DotnetToolSettings.xml} | 0 .../SampleGlobalTool/Program.cs | 0 .../SampleGlobalTool/consoledemo.csproj | 0 .../SampleGlobalTool/includepublish.nuspec | 4 +- .../ToolConfigurationDeserializerTests.cs | 16 +-- .../ToolPackageObtainerTests.cs | 67 +++++++-- .../ParserTests/InstallToolParserTests.cs | 52 +++++++ 55 files changed, 587 insertions(+), 204 deletions(-) create mode 100644 src/Microsoft.DotNet.Configurer/BashPathUnderHomeDirectory.cs rename src/dotnet/{ShellShimMaker => ShellShim}/DoNothingEnvironmentPath.cs (92%) rename src/dotnet/{ShellShimMaker => ShellShim}/EnvironmentPathFactory.cs (90%) rename src/dotnet/{ShellShimMaker => ShellShim}/LinuxEnvironmentPath.cs (79%) rename src/dotnet/{ShellShimMaker => ShellShim}/OsxEnvironmentPath.cs (73%) rename src/dotnet/{ShellShimMaker => ShellShim}/ShellShimMaker.cs (98%) rename src/dotnet/{ShellShimMaker => ShellShim}/WindowsEnvironmentPath.cs (95%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/IPackageToProjectFileAdder.cs (88%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/IProjectRestorer.cs (90%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/PackageObtainException.cs (92%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/PackageVersion.cs (93%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/ToolConfiguration.cs (78%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/ToolConfigurationAndExecutableDirectory.cs (93%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/ToolConfigurationDeserialization/DotNetCliTool.cs (78%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/ToolConfigurationDeserialization/DotNetCliToolCommand.cs (83%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/ToolConfigurationDeserializer.cs (75%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/ToolConfigurationException.cs (88%) rename src/dotnet/{ToolPackageObtainer => ToolPackage}/ToolPackageObtainer.cs (79%) create mode 100644 src/dotnet/commands/dotnet-install/InstallCommand.cs create mode 100644 src/dotnet/commands/dotnet-install/InstallCommandParser.cs create mode 100644 src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs create mode 100644 src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommandParser.cs rename src/dotnet/commands/dotnet-install/{ => dotnet-install-tool}/PackageToProjectFileAdder.cs (93%) rename src/dotnet/commands/dotnet-install/{ => dotnet-install-tool}/ProjectRestorer.cs (89%) rename test/{Microsoft.DotNet.ShellShimMaker.Tests => Microsoft.DotNet.ShellShim.Tests}/FakeEnvironmentProvider.cs (97%) rename test/{Microsoft.DotNet.ShellShimMaker.Tests => Microsoft.DotNet.ShellShim.Tests}/FakeFile.cs (96%) rename test/{Microsoft.DotNet.ShellShimMaker.Tests => Microsoft.DotNet.ShellShim.Tests}/FakeReporter.cs (93%) rename test/{Microsoft.DotNet.ShellShimMaker.Tests => Microsoft.DotNet.ShellShim.Tests}/LinuxEnvironmentPathTests.cs (78%) rename test/{Microsoft.DotNet.ShellShimMaker.Tests/Microsoft.DotNet.ShellShimMaker.Tests.csproj => Microsoft.DotNet.ShellShim.Tests/Microsoft.DotNet.ShellShim.Tests.csproj} (100%) rename test/{Microsoft.DotNet.ShellShimMaker.Tests => Microsoft.DotNet.ShellShim.Tests}/OsxEnvironmentPathTests.cs (84%) rename test/{Microsoft.DotNet.ShellShimMaker.Tests => Microsoft.DotNet.ShellShim.Tests}/ShellShimMakerTests.cs (98%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigGolden.xml => Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsGolden.xml} (100%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigMalformed.xml => Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsMalformed.xml} (100%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigMissing.xml => Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsMissing.xml} (100%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests/Microsoft.DotNet.ToolPackageObtainer.Tests.csproj => Microsoft.DotNet.ToolPackage.Tests/Microsoft.DotNet.ToolPackage.Tests.csproj} (91%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/DotnetToolsConfig.xml => Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/DotnetToolSettings.xml} (100%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests => Microsoft.DotNet.ToolPackage.Tests}/SampleGlobalTool/Program.cs (100%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests => Microsoft.DotNet.ToolPackage.Tests}/SampleGlobalTool/consoledemo.csproj (100%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests => Microsoft.DotNet.ToolPackage.Tests}/SampleGlobalTool/includepublish.nuspec (77%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests => Microsoft.DotNet.ToolPackage.Tests}/ToolConfigurationDeserializerTests.cs (73%) rename test/{Microsoft.DotNet.ToolPackageObtainer.Tests => Microsoft.DotNet.ToolPackage.Tests}/ToolPackageObtainerTests.cs (78%) create mode 100644 test/dotnet.Tests/ParserTests/InstallToolParserTests.cs diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln index 714749883..945a54aec 100644 --- a/Microsoft.DotNet.Cli.sln +++ b/Microsoft.DotNet.Cli.sln @@ -230,9 +230,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.TestFramew EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Msbuild.Tests.Utilities", "test\Msbuild.Tests.Utilities\Msbuild.Tests.Utilities.csproj", "{E7C72EF2-8480-48B4-AAE8-A596F1A6048E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackageObtainer.Tests", "test\Microsoft.DotNet.ToolPackageObtainer.Tests\Microsoft.DotNet.ToolPackageObtainer.Tests.csproj", "{F0D50831-9468-4ACB-8FD8-E9883DD553FB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ShellShim.Tests", "test\Microsoft.DotNet.ShellShim.Tests\Microsoft.DotNet.ShellShim.Tests.csproj", "{E84C08C9-70D7-48B0-9507-ADB8B9A2694C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ShellShimMaker.Tests", "test\Microsoft.DotNet.ShellShimMaker.Tests\Microsoft.DotNet.ShellShimMaker.Tests.csproj", "{20376E28-68EB-4BE5-81A5-51500F1235E2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackage.Tests", "test\Microsoft.DotNet.ToolPackage.Tests\Microsoft.DotNet.ToolPackage.Tests.csproj", "{91BFE800-1624-4A58-A1CE-339705A8FFD0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1618,54 +1618,54 @@ Global {E7C72EF2-8480-48B4-AAE8-A596F1A6048E}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {E7C72EF2-8480-48B4-AAE8-A596F1A6048E}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU {E7C72EF2-8480-48B4-AAE8-A596F1A6048E}.RelWithDebInfo|x86.Build.0 = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Debug|x64.ActiveCfg = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Debug|x64.Build.0 = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Debug|x86.ActiveCfg = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Debug|x86.Build.0 = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.MinSizeRel|x86.Build.0 = Debug|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Release|Any CPU.Build.0 = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Release|x64.ActiveCfg = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Release|x64.Build.0 = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Release|x86.ActiveCfg = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.Release|x86.Build.0 = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU - {F0D50831-9468-4ACB-8FD8-E9883DD553FB}.RelWithDebInfo|x86.Build.0 = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|x64.ActiveCfg = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|x64.Build.0 = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|x86.ActiveCfg = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Debug|x86.Build.0 = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.MinSizeRel|x86.Build.0 = Debug|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|Any CPU.Build.0 = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|x64.ActiveCfg = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|x64.Build.0 = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|x86.ActiveCfg = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.Release|x86.Build.0 = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU - {20376E28-68EB-4BE5-81A5-51500F1235E2}.RelWithDebInfo|x86.Build.0 = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Debug|x64.ActiveCfg = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Debug|x64.Build.0 = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Debug|x86.ActiveCfg = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Debug|x86.Build.0 = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.MinSizeRel|x86.Build.0 = Debug|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Release|Any CPU.Build.0 = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Release|x64.ActiveCfg = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Release|x64.Build.0 = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Release|x86.ActiveCfg = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.Release|x86.Build.0 = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C}.RelWithDebInfo|x86.Build.0 = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Debug|x64.ActiveCfg = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Debug|x64.Build.0 = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Debug|x86.ActiveCfg = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Debug|x86.Build.0 = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.MinSizeRel|x86.Build.0 = Debug|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Release|Any CPU.Build.0 = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Release|x64.ActiveCfg = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Release|x64.Build.0 = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Release|x86.ActiveCfg = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.Release|x86.Build.0 = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU + {91BFE800-1624-4A58-A1CE-339705A8FFD0}.RelWithDebInfo|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1738,8 +1738,8 @@ Global {B4EE3671-C103-4A37-8DEB-C74E0134104E} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {44759218-B558-4AF0-8991-515F1100DCF5} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {E7C72EF2-8480-48B4-AAE8-A596F1A6048E} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} - {F0D50831-9468-4ACB-8FD8-E9883DD553FB} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} - {20376E28-68EB-4BE5-81A5-51500F1235E2} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} + {E84C08C9-70D7-48B0-9507-ADB8B9A2694C} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} + {91BFE800-1624-4A58-A1CE-339705A8FFD0} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B526D2CE-EE2D-4AD4-93EF-1867D90FF1F5} diff --git a/scripts/obtain/uninstall/dotnet-uninstall-debian-packages.sh b/scripts/obtain/uninstall/dotnet-uninstall-debian-packages.sh index a62ce9ed4..1cc21b428 100755 --- a/scripts/obtain/uninstall/dotnet-uninstall-debian-packages.sh +++ b/scripts/obtain/uninstall/dotnet-uninstall-debian-packages.sh @@ -25,6 +25,9 @@ is_dotnet_host_installed(){ [ -z "$out" ] } +dotnet_tool_path_file="/etc/profile.d/dotnet-cli-tools-bin-path.sh" +rm -f "$dotnet_tool_path_file" + is_dotnet_host_installed [ "$?" -eq 0 ] && echo "Unable to find dotnet installation to remove." >&2 \ && exit 0 diff --git a/scripts/obtain/uninstall/dotnet-uninstall-pkgs.sh b/scripts/obtain/uninstall/dotnet-uninstall-pkgs.sh index 31a5d8e99..647ae4a61 100755 --- a/scripts/obtain/uninstall/dotnet-uninstall-pkgs.sh +++ b/scripts/obtain/uninstall/dotnet-uninstall-pkgs.sh @@ -16,6 +16,7 @@ fi dotnet_pkg_name_suffix="com.microsoft.dotnet" dotnet_install_root="/usr/local/share/dotnet" dotnet_path_file="/etc/paths.d/dotnet" +dotnet_tool_path_file="/etc/paths.d/dotnet-cli-tools" remove_dotnet_pkgs(){ installed_pkgs=($(pkgutil --pkgs | grep $dotnet_pkg_name_suffix)) @@ -33,6 +34,7 @@ remove_dotnet_pkgs echo "Deleting install root - $dotnet_install_root" >&2 rm -rf "$dotnet_install_root" rm -f "$dotnet_path_file" +rm -f "$dotnet_tool_path_file" echo "dotnet packages removal succeeded." >&2 exit 0 diff --git a/scripts/obtain/uninstall/dotnet-uninstall-rpm-packages.sh b/scripts/obtain/uninstall/dotnet-uninstall-rpm-packages.sh index ef7be91af..5f339d1ad 100755 --- a/scripts/obtain/uninstall/dotnet-uninstall-rpm-packages.sh +++ b/scripts/obtain/uninstall/dotnet-uninstall-rpm-packages.sh @@ -25,6 +25,9 @@ is_dotnet_host_installed(){ [ -z "$out" ] } +dotnet_tool_path_file="/etc/profile.d/dotnet-cli-tools-bin-path.sh" +rm -f "$dotnet_tool_path_file" + is_dotnet_host_installed [ "$?" -eq 0 ] && echo "Unable to find dotnet installation to remove." >&2 \ && exit 0 diff --git a/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs b/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs index b1d6f09ca..119f225c7 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Properties/AssemblyInfo.cs @@ -12,4 +12,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.DotNet.TestFramework, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Tests.Utilities, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.DotNet.ProjectJsonMigration, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShimMaker.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShim.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.DotNet.Configurer/BashPathUnderHomeDirectory.cs b/src/Microsoft.DotNet.Configurer/BashPathUnderHomeDirectory.cs new file mode 100644 index 000000000..1bf9b4c73 --- /dev/null +++ b/src/Microsoft.DotNet.Configurer/BashPathUnderHomeDirectory.cs @@ -0,0 +1,23 @@ +using System; + +namespace Microsoft.DotNet.Configurer +{ + public struct BashPathUnderHomeDirectory + { + private readonly string _fullHomeDirectoryPath; + private readonly string _pathRelativeToHome; + + public BashPathUnderHomeDirectory(string fullHomeDirectoryPath, string pathRelativeToHome) + { + _fullHomeDirectoryPath = + fullHomeDirectoryPath ?? throw new ArgumentNullException(nameof(fullHomeDirectoryPath)); + _pathRelativeToHome = pathRelativeToHome ?? throw new ArgumentNullException(nameof(pathRelativeToHome)); + } + + public string PathWithTilde => $"~/{_pathRelativeToHome}"; + + public string PathWithDollar => $"$HOME/{_pathRelativeToHome}"; + + public string Path => $"{_fullHomeDirectoryPath}/{_pathRelativeToHome}"; + } +} diff --git a/src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs b/src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs index bdc5dbfe6..71f740131 100644 --- a/src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs +++ b/src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs @@ -18,8 +18,16 @@ namespace Microsoft.DotNet.Configurer public string CliFallbackFolderPath => Environment.GetEnvironmentVariable("DOTNET_CLI_TEST_FALLBACKFOLDER") ?? Path.Combine(new DirectoryInfo(AppContext.BaseDirectory).Parent.FullName, "NuGetFallbackFolder"); - public string ExecutablePackagesPath => Path.Combine(DotnetUserProfileFolderPath, ToolsFolderName) ; - public readonly string ExecutablePackagesPathOnMacEnvPath = $"~/{DotnetProfileDirectoryName}/{ToolsFolderName}"; + public string ExecutablePackagesPath => Path.Combine(DotnetUserProfileFolderPath, ToolsFolderName); + + public BashPathUnderHomeDirectory ExecutablePackagesPathInUnix + { + get + { + return new BashPathUnderHomeDirectory(Environment.GetEnvironmentVariable("HOME"), + Path.Combine(DotnetProfileDirectoryName, ToolsFolderName)); + } + } public static string DotnetUserProfileFolderPath { diff --git a/src/Microsoft.DotNet.InternalAbstractions/Properties/Properties.cs b/src/Microsoft.DotNet.InternalAbstractions/Properties/Properties.cs index 3b1a181ad..4b08b51db 100644 --- a/src/Microsoft.DotNet.InternalAbstractions/Properties/Properties.cs +++ b/src/Microsoft.DotNet.InternalAbstractions/Properties/Properties.cs @@ -14,4 +14,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] [assembly: InternalsVisibleTo("dotnet-test.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100039ac461fa5c82c7dd2557400c4fd4e9dcdf7ac47e3d572548c04cd4673e004916610f4ea5cbf86f2b1ca1cb824f2a7b3976afecfcf4eb72d9a899aa6786effa10c30399e6580ed848231fec48374e41b3acf8811931343fc2f73acf72dae745adbcb7063cc4b50550618383202875223fc75401351cd89c44bf9b50e7fa3796")] [assembly: InternalsVisibleTo("Microsoft.DotNet.Tools.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShimMaker.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShim.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/dotnet/BuiltInCommandsCatalog.cs b/src/dotnet/BuiltInCommandsCatalog.cs index 25c69fdbd..dd2c242d6 100644 --- a/src/dotnet/BuiltInCommandsCatalog.cs +++ b/src/dotnet/BuiltInCommandsCatalog.cs @@ -20,6 +20,7 @@ using Microsoft.DotNet.Tools.Store; using Microsoft.DotNet.Tools.Test; using Microsoft.DotNet.Tools.VSTest; using System.Collections.Generic; +using Microsoft.DotNet.Tools.Install; namespace Microsoft.DotNet.Cli { @@ -144,10 +145,14 @@ namespace Microsoft.DotNet.Cli { Command = ParseCommand.Run }, + ["install"] = new BuiltInCommandMetadata + { + Command = InstallCommand.Run + }, ["internal-reportinstallsuccess"] = new BuiltInCommandMetadata { Command = InternalReportinstallsuccess.Run } }; } -} \ No newline at end of file +} diff --git a/src/dotnet/Parser.cs b/src/dotnet/Parser.cs index 239cb81b8..07639b3ab 100644 --- a/src/dotnet/Parser.cs +++ b/src/dotnet/Parser.cs @@ -55,9 +55,10 @@ namespace Microsoft.DotNet.Cli Create.Command("vstest", ""), CompleteCommandParser.Complete(), InternalReportinstallsuccessCommandParser.InternalReportinstallsuccess(), + InstallCommandParser.Install(), CommonOptions.HelpOption(), Create.Option("--info", ""), Create.Option("-d", ""), Create.Option("--debug", ""))); } -} \ No newline at end of file +} diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs index 7e6cafe8c..37a4ebd7c 100644 --- a/src/dotnet/Program.cs +++ b/src/dotnet/Program.cs @@ -11,7 +11,7 @@ using Microsoft.DotNet.Cli.Telemetry; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Configurer; using Microsoft.DotNet.PlatformAbstractions; -using Microsoft.DotNet.ShellShimMaker; +using Microsoft.DotNet.ShellShim; using Microsoft.DotNet.Tools.Help; using Microsoft.Extensions.EnvironmentAbstractions; using NuGet.Frameworks; diff --git a/src/dotnet/Properties/AssemblyInfo.cs b/src/dotnet/Properties/AssemblyInfo.cs index 334c80f95..249576dc2 100644 --- a/src/dotnet/Properties/AssemblyInfo.cs +++ b/src/dotnet/Properties/AssemblyInfo.cs @@ -17,5 +17,5 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("dotnet-sln-remove.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("dotnet-msbuild.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("dotnet-run.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.DotNet.ToolPackageObtainer.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShimMaker.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.DotNet.ToolPackage.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.DotNet.ShellShim.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/dotnet/ShellShimMaker/DoNothingEnvironmentPath.cs b/src/dotnet/ShellShim/DoNothingEnvironmentPath.cs similarity index 92% rename from src/dotnet/ShellShimMaker/DoNothingEnvironmentPath.cs rename to src/dotnet/ShellShim/DoNothingEnvironmentPath.cs index 79ee09564..336abab29 100644 --- a/src/dotnet/ShellShimMaker/DoNothingEnvironmentPath.cs +++ b/src/dotnet/ShellShim/DoNothingEnvironmentPath.cs @@ -7,7 +7,7 @@ using System.IO; using System.Linq; using Microsoft.DotNet.Cli.Utils; -namespace Microsoft.DotNet.ShellShimMaker +namespace Microsoft.DotNet.ShellShim { public class DoNothingEnvironmentPath : IEnvironmentPath { diff --git a/src/dotnet/ShellShimMaker/EnvironmentPathFactory.cs b/src/dotnet/ShellShim/EnvironmentPathFactory.cs similarity index 90% rename from src/dotnet/ShellShimMaker/EnvironmentPathFactory.cs rename to src/dotnet/ShellShim/EnvironmentPathFactory.cs index 48ffce82f..a777bd78a 100644 --- a/src/dotnet/ShellShimMaker/EnvironmentPathFactory.cs +++ b/src/dotnet/ShellShim/EnvironmentPathFactory.cs @@ -9,7 +9,7 @@ using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Configurer; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ShellShimMaker +namespace Microsoft.DotNet.ShellShim { internal static class EnvironmentPathFactory { @@ -39,15 +39,14 @@ namespace Microsoft.DotNet.ShellShimMaker else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && hasSuperUserAccess) { environmentPath = new LinuxEnvironmentPath( - cliFolderPathCalculator.ExecutablePackagesPath, + cliFolderPathCalculator.ExecutablePackagesPathInUnix, Reporter.Output, environmentProvider, new FileWrapper()); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && hasSuperUserAccess) { environmentPath = new OSXEnvironmentPath( - packageExecutablePathWithTilde: cliFolderPathCalculator.ExecutablePackagesPathOnMacEnvPath, - fullPackageExecutablePath: cliFolderPathCalculator.ExecutablePackagesPath, + executablePath: cliFolderPathCalculator.ExecutablePackagesPathInUnix, reporter: Reporter.Output, environmentProvider: environmentProvider, fileSystem: new FileWrapper()); diff --git a/src/dotnet/ShellShimMaker/LinuxEnvironmentPath.cs b/src/dotnet/ShellShim/LinuxEnvironmentPath.cs similarity index 79% rename from src/dotnet/ShellShimMaker/LinuxEnvironmentPath.cs rename to src/dotnet/ShellShim/LinuxEnvironmentPath.cs index 0868a6fcf..2c9dc050e 100644 --- a/src/dotnet/ShellShimMaker/LinuxEnvironmentPath.cs +++ b/src/dotnet/ShellShim/LinuxEnvironmentPath.cs @@ -4,9 +4,10 @@ using System; using System.Linq; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Configurer; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ShellShimMaker +namespace Microsoft.DotNet.ShellShim { internal class LinuxEnvironmentPath : IEnvironmentPath { @@ -14,14 +15,14 @@ namespace Microsoft.DotNet.ShellShimMaker private readonly IEnvironmentProvider _environmentProvider; private readonly IReporter _reporter; private const string PathName = "PATH"; - private readonly string _packageExecutablePath; + private readonly BashPathUnderHomeDirectory _packageExecutablePath; private readonly string _profiledDotnetCliToolsPath = Environment.GetEnvironmentVariable("DOTNET_CLI_TEST_LINUX_PROFILED_PATH") ?? @"/etc/profile.d/dotnet-cli-tools-bin-path.sh"; internal LinuxEnvironmentPath( - string packageExecutablePath, + BashPathUnderHomeDirectory packageExecutablePath, IReporter reporter, IEnvironmentProvider environmentProvider, IFile fileSystem) @@ -31,8 +32,7 @@ namespace Microsoft.DotNet.ShellShimMaker = environmentProvider ?? throw new ArgumentNullException(nameof(environmentProvider)); _reporter = reporter ?? throw new ArgumentNullException(nameof(reporter)); - _packageExecutablePath - = packageExecutablePath ?? throw new ArgumentNullException(nameof(packageExecutablePath)); + _packageExecutablePath = packageExecutablePath; } public void AddPackageExecutablePathToUserPath() @@ -42,7 +42,7 @@ namespace Microsoft.DotNet.ShellShimMaker return; } - var script = $"export PATH=\"$PATH:{_packageExecutablePath}\""; + var script = $"export PATH=\"$PATH:{_packageExecutablePath.PathWithDollar}\""; _fileSystem.WriteAllText(_profiledDotnetCliToolsPath, script); } @@ -50,7 +50,7 @@ namespace Microsoft.DotNet.ShellShimMaker { return _environmentProvider .GetEnvironmentVariable(PathName) - .Split(':').Contains(_packageExecutablePath); + .Split(':').Contains(_packageExecutablePath.Path); } public void PrintAddPathInstructionIfPathDoesNotExist() @@ -59,17 +59,18 @@ namespace Microsoft.DotNet.ShellShimMaker { if (_fileSystem.Exists(_profiledDotnetCliToolsPath)) { - _reporter.WriteLine("Since you just installed the .NET Core SDK, you will need to logout or restart your session before running the tool you installed."); + _reporter.WriteLine( + "Since you just installed the .NET Core SDK, you will need to logout or restart your session before running the tool you installed."); } else { // similar to https://code.visualstudio.com/docs/setup/mac _reporter.WriteLine( - $"Cannot find the tools executable path. Please ensure {_packageExecutablePath} is added to your PATH.{Environment.NewLine}" + + $"Cannot find the tools executable path. Please ensure {_packageExecutablePath.Path} is added to your PATH.{Environment.NewLine}" + $"If you are using bash. You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" + $"cat << EOF >> ~/.bash_profile{Environment.NewLine}" + $"# Add .NET Core SDK tools{Environment.NewLine}" + - $"export PATH=\"$PATH:{_packageExecutablePath}\"{Environment.NewLine}" + + $"export PATH=\"$PATH:{_packageExecutablePath.Path}\"{Environment.NewLine}" + $"EOF"); } } diff --git a/src/dotnet/ShellShimMaker/OsxEnvironmentPath.cs b/src/dotnet/ShellShim/OsxEnvironmentPath.cs similarity index 73% rename from src/dotnet/ShellShimMaker/OsxEnvironmentPath.cs rename to src/dotnet/ShellShim/OsxEnvironmentPath.cs index cc8f8eac8..e682d25d6 100644 --- a/src/dotnet/ShellShimMaker/OsxEnvironmentPath.cs +++ b/src/dotnet/ShellShim/OsxEnvironmentPath.cs @@ -4,15 +4,15 @@ using System; using System.Linq; using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Configurer; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ShellShimMaker +namespace Microsoft.DotNet.ShellShim { internal class OSXEnvironmentPath : IEnvironmentPath { private const string PathName = "PATH"; - private readonly string _packageExecutablePathWithTilde; - private readonly string _fullPackageExecutablePath; + private readonly BashPathUnderHomeDirectory _packageExecutablePath; private readonly IFile _fileSystem; private readonly IEnvironmentProvider _environmentProvider; private readonly IReporter _reporter; @@ -22,17 +22,13 @@ namespace Microsoft.DotNet.ShellShimMaker ?? @"/etc/paths.d/dotnet-cli-tools"; public OSXEnvironmentPath( - string packageExecutablePathWithTilde, - string fullPackageExecutablePath, + BashPathUnderHomeDirectory executablePath, IReporter reporter, IEnvironmentProvider environmentProvider, IFile fileSystem ) { - _fullPackageExecutablePath = fullPackageExecutablePath ?? - throw new ArgumentNullException(nameof(fullPackageExecutablePath)); - _packageExecutablePathWithTilde = packageExecutablePathWithTilde ?? - throw new ArgumentNullException(nameof(packageExecutablePathWithTilde)); + _packageExecutablePath = executablePath; _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _environmentProvider = environmentProvider ?? throw new ArgumentNullException(nameof(environmentProvider)); @@ -47,16 +43,16 @@ namespace Microsoft.DotNet.ShellShimMaker return; } - var script = $"{_packageExecutablePathWithTilde}"; + var script = $"{_packageExecutablePath.PathWithTilde}"; _fileSystem.WriteAllText(PathDDotnetCliToolsPath, script); } private bool PackageExecutablePathExists() { return _environmentProvider.GetEnvironmentVariable(PathName).Split(':') - .Contains(_packageExecutablePathWithTilde) || + .Contains(_packageExecutablePath.PathWithTilde) || _environmentProvider.GetEnvironmentVariable(PathName).Split(':') - .Contains(_fullPackageExecutablePath); + .Contains(_packageExecutablePath.Path); } public void PrintAddPathInstructionIfPathDoesNotExist() @@ -72,11 +68,11 @@ namespace Microsoft.DotNet.ShellShimMaker { // similar to https://code.visualstudio.com/docs/setup/mac _reporter.WriteLine( - $"Cannot find the tools executable path. Please ensure {_fullPackageExecutablePath} is added to your PATH.{Environment.NewLine}" + + $"Cannot find the tools executable path. Please ensure {_packageExecutablePath.Path} is added to your PATH.{Environment.NewLine}" + $"If you are using bash, You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" + $"cat << EOF >> ~/.bash_profile{Environment.NewLine}" + $"# Add .NET Core SDK tools{Environment.NewLine}" + - $"export PATH=\"$PATH:{_fullPackageExecutablePath}\"{Environment.NewLine}" + + $"export PATH=\"$PATH:{_packageExecutablePath.Path}\"{Environment.NewLine}" + $"EOF"); } } diff --git a/src/dotnet/ShellShimMaker/ShellShimMaker.cs b/src/dotnet/ShellShim/ShellShimMaker.cs similarity index 98% rename from src/dotnet/ShellShimMaker/ShellShimMaker.cs rename to src/dotnet/ShellShim/ShellShimMaker.cs index 6a56f226b..d4c15233e 100644 --- a/src/dotnet/ShellShimMaker/ShellShimMaker.cs +++ b/src/dotnet/ShellShim/ShellShimMaker.cs @@ -8,7 +8,7 @@ using System.Text; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ShellShimMaker +namespace Microsoft.DotNet.ShellShim { public class ShellShimMaker { diff --git a/src/dotnet/ShellShimMaker/WindowsEnvironmentPath.cs b/src/dotnet/ShellShim/WindowsEnvironmentPath.cs similarity index 95% rename from src/dotnet/ShellShimMaker/WindowsEnvironmentPath.cs rename to src/dotnet/ShellShim/WindowsEnvironmentPath.cs index bc229d04d..eee4861bd 100644 --- a/src/dotnet/ShellShimMaker/WindowsEnvironmentPath.cs +++ b/src/dotnet/ShellShim/WindowsEnvironmentPath.cs @@ -6,7 +6,7 @@ using System.Linq; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ShellShimMaker +namespace Microsoft.DotNet.ShellShim { internal class WindowsEnvironmentPath : IEnvironmentPath { @@ -62,7 +62,7 @@ namespace Microsoft.DotNet.ShellShimMaker _reporter.WriteLine( $"Cannot find the tools executable path. Please ensure {_packageExecutablePath} is added to your PATH.{Environment.NewLine}" + $"You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" + - $"setx PATH \\\"%PATH%;{_packageExecutablePath}\"{Environment.NewLine}"); + $"setx PATH \"%PATH%;{_packageExecutablePath}\"{Environment.NewLine}"); } } } diff --git a/src/dotnet/ToolPackageObtainer/IPackageToProjectFileAdder.cs b/src/dotnet/ToolPackage/IPackageToProjectFileAdder.cs similarity index 88% rename from src/dotnet/ToolPackageObtainer/IPackageToProjectFileAdder.cs rename to src/dotnet/ToolPackage/IPackageToProjectFileAdder.cs index 00a8d2e66..cdde79c06 100644 --- a/src/dotnet/ToolPackageObtainer/IPackageToProjectFileAdder.cs +++ b/src/dotnet/ToolPackage/IPackageToProjectFileAdder.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal interface IPackageToProjectFileAdder { diff --git a/src/dotnet/ToolPackageObtainer/IProjectRestorer.cs b/src/dotnet/ToolPackage/IProjectRestorer.cs similarity index 90% rename from src/dotnet/ToolPackageObtainer/IProjectRestorer.cs rename to src/dotnet/ToolPackage/IProjectRestorer.cs index d53898427..868c5764e 100644 --- a/src/dotnet/ToolPackageObtainer/IProjectRestorer.cs +++ b/src/dotnet/ToolPackage/IProjectRestorer.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal interface IProjectRestorer { diff --git a/src/dotnet/ToolPackageObtainer/PackageObtainException.cs b/src/dotnet/ToolPackage/PackageObtainException.cs similarity index 92% rename from src/dotnet/ToolPackageObtainer/PackageObtainException.cs rename to src/dotnet/ToolPackage/PackageObtainException.cs index db15e8b1b..b165e0e5d 100644 --- a/src/dotnet/ToolPackageObtainer/PackageObtainException.cs +++ b/src/dotnet/ToolPackage/PackageObtainException.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal class PackageObtainException : Exception { diff --git a/src/dotnet/ToolPackageObtainer/PackageVersion.cs b/src/dotnet/ToolPackage/PackageVersion.cs similarity index 93% rename from src/dotnet/ToolPackageObtainer/PackageVersion.cs rename to src/dotnet/ToolPackage/PackageVersion.cs index da7d6aa3d..d66748ad1 100644 --- a/src/dotnet/ToolPackageObtainer/PackageVersion.cs +++ b/src/dotnet/ToolPackage/PackageVersion.cs @@ -3,7 +3,7 @@ using System.IO; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal class PackageVersion { diff --git a/src/dotnet/ToolPackageObtainer/ToolConfiguration.cs b/src/dotnet/ToolPackage/ToolConfiguration.cs similarity index 78% rename from src/dotnet/ToolPackageObtainer/ToolConfiguration.cs rename to src/dotnet/ToolPackage/ToolConfiguration.cs index 1b0a32cb3..8ae9b345e 100644 --- a/src/dotnet/ToolPackageObtainer/ToolConfiguration.cs +++ b/src/dotnet/ToolPackage/ToolConfiguration.cs @@ -2,8 +2,9 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.IO; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal class ToolConfiguration { @@ -29,13 +30,12 @@ namespace Microsoft.DotNet.ToolPackageObtainer private void EnsureNoInvalidFilenameCharacters(string commandName, string nameOfParam) { - // https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names - char[] invalidCharactors = {'/', '<', '>', ':', '"', '/', '\\', '|', '?', '*'}; + char[] invalidCharactors = Path.GetInvalidFileNameChars(); if (commandName.IndexOfAny(invalidCharactors) != -1) { throw new ArgumentException( paramName: nameof(nameOfParam), - message: "Cannot contain following character " + new string(invalidCharactors)); + message: "Contains one or more invalid characters: " + new string(invalidCharactors)); } } diff --git a/src/dotnet/ToolPackageObtainer/ToolConfigurationAndExecutableDirectory.cs b/src/dotnet/ToolPackage/ToolConfigurationAndExecutableDirectory.cs similarity index 93% rename from src/dotnet/ToolPackageObtainer/ToolConfigurationAndExecutableDirectory.cs rename to src/dotnet/ToolPackage/ToolConfigurationAndExecutableDirectory.cs index 4dc6a220d..06539b0a8 100644 --- a/src/dotnet/ToolPackageObtainer/ToolConfigurationAndExecutableDirectory.cs +++ b/src/dotnet/ToolPackage/ToolConfigurationAndExecutableDirectory.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal class ToolConfigurationAndExecutableDirectory { diff --git a/src/dotnet/ToolPackageObtainer/ToolConfigurationDeserialization/DotNetCliTool.cs b/src/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliTool.cs similarity index 78% rename from src/dotnet/ToolPackageObtainer/ToolConfigurationDeserialization/DotNetCliTool.cs rename to src/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliTool.cs index b64db01e2..91fd9fde4 100644 --- a/src/dotnet/ToolPackageObtainer/ToolConfigurationDeserialization/DotNetCliTool.cs +++ b/src/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliTool.cs @@ -1,7 +1,7 @@ using System.Diagnostics; using System.Xml.Serialization; -namespace Microsoft.DotNet.ToolPackageObtainer.ToolConfigurationDeserialization +namespace Microsoft.DotNet.ToolPackage.ToolConfigurationDeserialization { [DebuggerStepThrough] [XmlRoot(Namespace = "", IsNullable = false)] diff --git a/src/dotnet/ToolPackageObtainer/ToolConfigurationDeserialization/DotNetCliToolCommand.cs b/src/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliToolCommand.cs similarity index 83% rename from src/dotnet/ToolPackageObtainer/ToolConfigurationDeserialization/DotNetCliToolCommand.cs rename to src/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliToolCommand.cs index 159f6e993..84b6ffb44 100644 --- a/src/dotnet/ToolPackageObtainer/ToolConfigurationDeserialization/DotNetCliToolCommand.cs +++ b/src/dotnet/ToolPackage/ToolConfigurationDeserialization/DotNetCliToolCommand.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.Xml.Serialization; -namespace Microsoft.DotNet.ToolPackageObtainer.ToolConfigurationDeserialization +namespace Microsoft.DotNet.ToolPackage.ToolConfigurationDeserialization { [Serializable] [DebuggerStepThrough] diff --git a/src/dotnet/ToolPackageObtainer/ToolConfigurationDeserializer.cs b/src/dotnet/ToolPackage/ToolConfigurationDeserializer.cs similarity index 75% rename from src/dotnet/ToolPackageObtainer/ToolConfigurationDeserializer.cs rename to src/dotnet/ToolPackage/ToolConfigurationDeserializer.cs index 534cbf50c..002206168 100644 --- a/src/dotnet/ToolPackageObtainer/ToolConfigurationDeserializer.cs +++ b/src/dotnet/ToolPackage/ToolConfigurationDeserializer.cs @@ -5,9 +5,9 @@ using System; using System.IO; using System.Xml; using System.Xml.Serialization; -using Microsoft.DotNet.ToolPackageObtainer.ToolConfigurationDeserialization; +using Microsoft.DotNet.ToolPackage.ToolConfigurationDeserialization; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal static class ToolConfigurationDeserializer { @@ -28,7 +28,7 @@ namespace Microsoft.DotNet.ToolPackageObtainer catch (InvalidOperationException e) when (e.InnerException is XmlException) { throw new ToolConfigurationException( - "Failed to retrive tool configuration exception, configuration is malformed xml. " + + $"The tool's settings file is invalid xml. {Environment.NewLine}" + e.InnerException.Message); } } @@ -36,13 +36,13 @@ namespace Microsoft.DotNet.ToolPackageObtainer if (dotNetCliTool.Commands.Length != 1) { throw new ToolConfigurationException( - "Failed to retrive tool configuration exception, one and only one command is supported."); + "The tool's settings file has more than one command defined."); } if (dotNetCliTool.Commands[0].Runner != "dotnet") { throw new ToolConfigurationException( - "Failed to retrive tool configuration exception, only dotnet as runner is supported."); + "The tool's settings file has non \"dotnet\" as runner."); } var commandName = dotNetCliTool.Commands[0].Name; @@ -54,7 +54,7 @@ namespace Microsoft.DotNet.ToolPackageObtainer } catch (ArgumentException e) { - throw new ToolConfigurationException("Configuration content error. " + e.Message); + throw new ToolConfigurationException($"The tool's settings file contains error {Environment.NewLine}" + e.Message); } } } diff --git a/src/dotnet/ToolPackageObtainer/ToolConfigurationException.cs b/src/dotnet/ToolPackage/ToolConfigurationException.cs similarity index 88% rename from src/dotnet/ToolPackageObtainer/ToolConfigurationException.cs rename to src/dotnet/ToolPackage/ToolConfigurationException.cs index 074010aa0..97c49b421 100644 --- a/src/dotnet/ToolPackageObtainer/ToolConfigurationException.cs +++ b/src/dotnet/ToolPackage/ToolConfigurationException.cs @@ -3,7 +3,7 @@ using System; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal class ToolConfigurationException : ArgumentException { diff --git a/src/dotnet/ToolPackageObtainer/ToolPackageObtainer.cs b/src/dotnet/ToolPackage/ToolPackageObtainer.cs similarity index 79% rename from src/dotnet/ToolPackageObtainer/ToolPackageObtainer.cs rename to src/dotnet/ToolPackage/ToolPackageObtainer.cs index faf4ed461..96df3fb85 100644 --- a/src/dotnet/ToolPackageObtainer/ToolPackageObtainer.cs +++ b/src/dotnet/ToolPackage/ToolPackageObtainer.cs @@ -1,10 +1,11 @@ using System; +using System.Diagnostics; using System.IO; using System.Linq; using System.Xml.Linq; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ToolPackageObtainer +namespace Microsoft.DotNet.ToolPackage { internal class ToolPackageObtainer { @@ -41,6 +42,14 @@ namespace Microsoft.DotNet.ToolPackageObtainer throw new ArgumentNullException(nameof(packageId)); } + if (nugetconfig != null) + { + if (!File.Exists(nugetconfig.Value.Value)) + { + throw new PackageObtainException($"NuGet configuration file {Path.GetFullPath(nugetconfig.Value.Value)} does not exist."); + } + } + if (targetframework == null) { targetframework = _bundledTargetFrameworkMoniker.Value; @@ -48,14 +57,14 @@ namespace Microsoft.DotNet.ToolPackageObtainer var packageVersionOrPlaceHolder = new PackageVersion(packageVersion); - DirectoryPath individualToolVersion = + DirectoryPath toolDirectory = CreateIndividualToolVersionDirectory(packageId, packageVersionOrPlaceHolder); FilePath tempProjectPath = CreateTempProject( packageId, packageVersionOrPlaceHolder, targetframework, - individualToolVersion); + toolDirectory); if (packageVersionOrPlaceHolder.IsPlaceholder) { @@ -65,31 +74,45 @@ namespace Microsoft.DotNet.ToolPackageObtainer packageId); } - InvokeRestore(nugetconfig, tempProjectPath, individualToolVersion); + InvokeRestore(nugetconfig: nugetconfig, tempProjectPath: tempProjectPath, individualToolVersion: toolDirectory); if (packageVersionOrPlaceHolder.IsPlaceholder) { var concreteVersion = new DirectoryInfo( Directory.GetDirectories( - individualToolVersion.WithSubDirectories(packageId).Value).Single()).Name; - DirectoryPath concreteVersionIndividualToolVersion = - individualToolVersion.GetParentPath().WithSubDirectories(concreteVersion); - Directory.Move(individualToolVersion.Value, concreteVersionIndividualToolVersion.Value); + toolDirectory.WithSubDirectories(packageId).Value).Single()).Name; + DirectoryPath versioned = + toolDirectory.GetParentPath().WithSubDirectories(concreteVersion); - individualToolVersion = concreteVersionIndividualToolVersion; + MoveToVersionedDirectory(versioned, toolDirectory); + + toolDirectory = versioned; packageVersion = concreteVersion; } - ToolConfiguration toolConfiguration = GetConfiguration(packageId, packageVersion, individualToolVersion); + ToolConfiguration toolConfiguration = GetConfiguration(packageId: packageId, packageVersion: packageVersion, individualToolVersion: toolDirectory); return new ToolConfigurationAndExecutableDirectory( toolConfiguration, - individualToolVersion.WithSubDirectories( + toolDirectory.WithSubDirectories( packageId, packageVersion, "tools", - targetframework)); + targetframework, + "any")); + } + + private static void MoveToVersionedDirectory( + DirectoryPath versioned, + DirectoryPath temporary) + { + if (Directory.Exists(versioned.Value)) + { + Directory.Delete(versioned.Value, recursive: true); + } + + Directory.Move(temporary.Value, versioned.Value); } private static ToolConfiguration GetConfiguration( @@ -100,7 +123,7 @@ namespace Microsoft.DotNet.ToolPackageObtainer FilePath toolConfigurationPath = individualToolVersion .WithSubDirectories(packageId, packageVersion, "tools") - .WithFile("DotnetToolsConfig.xml"); + .WithFile("DotnetToolSettings.xml"); ToolConfiguration toolConfiguration = ToolConfigurationDeserializer.Deserialize(toolConfigurationPath.Value); @@ -135,6 +158,7 @@ namespace Microsoft.DotNet.ToolPackageObtainer new XElement("PropertyGroup", new XElement("TargetFramework", targetframework), new XElement("RestorePackagesPath", individualToolVersion.Value), + new XElement("RestoreSolutionDirectory", Directory.GetCurrentDirectory()), // https://github.com/NuGet/Home/issues/6199 new XElement("DisableImplicitFrameworkReferences", "true") ), packageVersion.IsConcreteValue diff --git a/src/dotnet/commands/dotnet-install/InstallCommand.cs b/src/dotnet/commands/dotnet-install/InstallCommand.cs new file mode 100644 index 000000000..c984a94f5 --- /dev/null +++ b/src/dotnet/commands/dotnet-install/InstallCommand.cs @@ -0,0 +1,36 @@ +// 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.Collections.Generic; +using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Cli.CommandLine; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Tools.Add; +using Microsoft.DotNet.Tools.Install.Tool; + +namespace Microsoft.DotNet.Tools.Install +{ + public class InstallCommand : DotNetTopLevelCommandBase + { + protected override string CommandName => "install"; + protected override string FullCommandNameLocalized => "NetInstallCommand"; + protected override string ArgumentName => Constants.ProjectArgumentName; + protected override string ArgumentDescriptionLocalized => CommonLocalizableStrings.ArgumentsProjectDescription; + + internal override Dictionary> SubCommands => + new Dictionary> + { + ["tool"] = + appliedOption => new InstallToolCommand( + appliedOption["tool"], + ParseResult) + }; + + public static int Run(string[] args) + { + var command = new InstallCommand(); + return command.RunCommand(args); + } + } +} diff --git a/src/dotnet/commands/dotnet-install/InstallCommandParser.cs b/src/dotnet/commands/dotnet-install/InstallCommandParser.cs new file mode 100644 index 000000000..2592fd4e3 --- /dev/null +++ b/src/dotnet/commands/dotnet-install/InstallCommandParser.cs @@ -0,0 +1,19 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class InstallCommandParser + { + public static Command Install() + { + return Create.Command( + "install", "", + Accept.NoArguments(), + CommonOptions.HelpOption(), + InstallToolCommandParser.InstallTool()); + } + } +} diff --git a/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs b/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs new file mode 100644 index 000000000..798203459 --- /dev/null +++ b/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs @@ -0,0 +1,130 @@ +// 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 Microsoft.DotNet.Cli; +using Microsoft.DotNet.Cli.CommandLine; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.Configurer; +using Microsoft.DotNet.ShellShim; +using Microsoft.DotNet.ToolPackage; +using Microsoft.Extensions.EnvironmentAbstractions; + +namespace Microsoft.DotNet.Tools.Install.Tool +{ + public class InstallToolCommand : CommandBase + { + private static string _packageId; + private static string _packageVersion; + private static string _configFilePath; + private static string _framework; + + public InstallToolCommand( + AppliedOption appliedCommand, + ParseResult parseResult) + : base(parseResult) + { + if (appliedCommand == null) + { + throw new ArgumentNullException(nameof(appliedCommand)); + } + + _packageId = appliedCommand.Arguments.Single(); + _packageVersion = appliedCommand.ValueOrDefault("version"); + _configFilePath = appliedCommand.ValueOrDefault("configfile"); + _framework = appliedCommand.ValueOrDefault("framework"); + } + + public override int Execute() + { + FilePath? configFile = null; + + if (_configFilePath != null) + { + configFile = new FilePath(_configFilePath); + } + + var executablePackagePath = new DirectoryPath(new CliFolderPathCalculator().ExecutablePackagesPath); + + var toolConfigurationAndExecutableDirectory = ObtainPackage( + _packageId, + _packageVersion, + configFile, + _framework, + executablePackagePath); + + DirectoryPath executable = toolConfigurationAndExecutableDirectory + .ExecutableDirectory + .WithSubDirectories( + toolConfigurationAndExecutableDirectory + .Configuration + .ToolAssemblyEntryPoint); + + var shellShimMaker = new ShellShimMaker(executablePackagePath.Value); + var commandName = toolConfigurationAndExecutableDirectory.Configuration.CommandName; + shellShimMaker.EnsureCommandNameUniqueness(commandName); + + shellShimMaker.CreateShim( + executable.Value, + commandName); + + EnvironmentPathFactory + .CreateEnvironmentPathInstruction() + .PrintAddPathInstructionIfPathDoesNotExist(); + + Reporter.Output.WriteLine( + $"{Environment.NewLine}The installation succeeded. If there is no other instruction. You can type the following command in shell directly to invoke: {commandName}"); + + return 0; + } + + private static ToolConfigurationAndExecutableDirectory ObtainPackage( + string packageId, + string packageVersion, + FilePath? configFile, + string framework, + DirectoryPath executablePackagePath) + { + try + { + var toolPackageObtainer = + new ToolPackageObtainer( + executablePackagePath, + () => new DirectoryPath(Path.GetTempPath()) + .WithSubDirectories(Path.GetRandomFileName()) + .WithFile(Path.GetRandomFileName() + ".csproj"), + new Lazy(BundledTargetFramework.GetTargetFrameworkMoniker), + new PackageToProjectFileAdder(), + new ProjectRestorer()); + + return toolPackageObtainer.ObtainAndReturnExecutablePath( + packageId: packageId, + packageVersion: packageVersion, + nugetconfig: configFile, + targetframework: framework); + } + catch (PackageObtainException ex) + { + throw new GracefulException( + message: + $"Install failed. Failed to download package:{Environment.NewLine}" + + $"NuGet returned:{Environment.NewLine}" + + $"{Environment.NewLine}" + + $"{ex.Message}", + innerException: ex); + } + catch (ToolConfigurationException ex) + { + throw new GracefulException( + message: + $"Install failed. The settings file in the tool's NuGet package is not valid. Please contact the owner of the NuGet package.{Environment.NewLine}" + + $"The error was:{Environment.NewLine}" + + $"{Environment.NewLine}" + + $"{ex.Message}", + innerException: ex); + } + } + } +} diff --git a/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommandParser.cs b/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommandParser.cs new file mode 100644 index 000000000..610c7d8f3 --- /dev/null +++ b/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommandParser.cs @@ -0,0 +1,32 @@ +// 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 Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Cli +{ + internal static class InstallToolCommandParser + { + public static Command InstallTool() + { + return Create.Command("tool", + "Install tool", + Accept.ExactlyOneArgument(o => "packageId") + .With(name: "packageId", + description: "Package Id in NuGet"), + Create.Option( + "--version", + "Version of the package in NuGet", + Accept.ExactlyOneArgument()), + Create.Option( + "--configfile", + "NuGet configuration file", + Accept.ExactlyOneArgument()), + Create.Option( + "-f|--framework", + "Target framework to publish for. The target framework has to be specified in the project file.", + Accept.ExactlyOneArgument()), + CommonOptions.HelpOption()); + } + } +} diff --git a/src/dotnet/commands/dotnet-install/PackageToProjectFileAdder.cs b/src/dotnet/commands/dotnet-install/dotnet-install-tool/PackageToProjectFileAdder.cs similarity index 93% rename from src/dotnet/commands/dotnet-install/PackageToProjectFileAdder.cs rename to src/dotnet/commands/dotnet-install/dotnet-install-tool/PackageToProjectFileAdder.cs index 21de01ddb..0716f6d15 100644 --- a/src/dotnet/commands/dotnet-install/PackageToProjectFileAdder.cs +++ b/src/dotnet/commands/dotnet-install/dotnet-install-tool/PackageToProjectFileAdder.cs @@ -3,12 +3,12 @@ using System; using System.Collections.Generic; -using Microsoft.DotNet.ToolPackageObtainer; +using Microsoft.DotNet.Cli; +using Microsoft.DotNet.ToolPackage; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.Cli +namespace Microsoft.DotNet.Tools.Install.Tool { - internal class PackageToProjectFileAdder : IPackageToProjectFileAdder { public void Add(FilePath projectPath, string packageId) diff --git a/src/dotnet/commands/dotnet-install/ProjectRestorer.cs b/src/dotnet/commands/dotnet-install/dotnet-install-tool/ProjectRestorer.cs similarity index 89% rename from src/dotnet/commands/dotnet-install/ProjectRestorer.cs rename to src/dotnet/commands/dotnet-install/dotnet-install-tool/ProjectRestorer.cs index a9717ed69..0e22d7530 100644 --- a/src/dotnet/commands/dotnet-install/ProjectRestorer.cs +++ b/src/dotnet/commands/dotnet-install/dotnet-install-tool/ProjectRestorer.cs @@ -3,11 +3,12 @@ using System; using System.Collections.Generic; -using Microsoft.DotNet.ToolPackageObtainer; +using Microsoft.DotNet.Cli; +using Microsoft.DotNet.ToolPackage; using Microsoft.DotNet.PlatformAbstractions; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.Cli +namespace Microsoft.DotNet.Tools.Install.Tool { internal class ProjectRestorer : IProjectRestorer { @@ -18,11 +19,11 @@ namespace Microsoft.DotNet.Cli { var argsToPassToRestore = new List(); - argsToPassToRestore.Add(projectPath.ToQuotedString()); + argsToPassToRestore.Add(projectPath.Value); if (nugetconfig != null) { argsToPassToRestore.Add("--configfile"); - argsToPassToRestore.Add(nugetconfig.Value.ToQuotedString()); + argsToPassToRestore.Add(nugetconfig.Value.Value); } argsToPassToRestore.AddRange(new List diff --git a/src/dotnet/dotnet.csproj b/src/dotnet/dotnet.csproj index f0c913b9d..642c96ad4 100644 --- a/src/dotnet/dotnet.csproj +++ b/src/dotnet/dotnet.csproj @@ -73,4 +73,4 @@ - \ No newline at end of file + diff --git a/test/Microsoft.DotNet.Cli.Tests.sln b/test/Microsoft.DotNet.Cli.Tests.sln index 5f0d406d3..863d564db 100644 --- a/test/Microsoft.DotNet.Cli.Tests.sln +++ b/test/Microsoft.DotNet.Cli.Tests.sln @@ -82,9 +82,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-clean.Tests", "dotne EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.TestFramework", "Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.csproj", "{D23AFC9C-8FD5-45DD-A84C-0E6528C42F0E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackageObtainer.Tests", "Microsoft.DotNet.ToolPackageObtainer.Tests\Microsoft.DotNet.ToolPackageObtainer.Tests.csproj", "{C2A907A3-677B-4C73-9AA4-E53613E13C78}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ShellShim.Tests", "Microsoft.DotNet.ShellShim.Tests\Microsoft.DotNet.ShellShim.Tests.csproj", "{1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ShellShimMaker.Tests", "Microsoft.DotNet.ShellShimMaker.Tests\Microsoft.DotNet.ShellShimMaker.Tests.csproj", "{1146EAAC-E434-404A-8198-B4F0CB23BC57}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.DotNet.ToolPackage.Tests", "Microsoft.DotNet.ToolPackage.Tests\Microsoft.DotNet.ToolPackage.Tests.csproj", "{453C809B-40FC-4A93-93B8-DE449D48B9FF}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -540,30 +540,30 @@ Global {D23AFC9C-8FD5-45DD-A84C-0E6528C42F0E}.Release|x64.Build.0 = Release|Any CPU {D23AFC9C-8FD5-45DD-A84C-0E6528C42F0E}.Release|x86.ActiveCfg = Release|Any CPU {D23AFC9C-8FD5-45DD-A84C-0E6528C42F0E}.Release|x86.Build.0 = Release|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Debug|x64.ActiveCfg = Debug|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Debug|x64.Build.0 = Debug|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Debug|x86.ActiveCfg = Debug|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Debug|x86.Build.0 = Debug|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|Any CPU.Build.0 = Release|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x64.ActiveCfg = Release|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x64.Build.0 = Release|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x86.ActiveCfg = Release|Any CPU - {C2A907A3-677B-4C73-9AA4-E53613E13C78}.Release|x86.Build.0 = Release|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|x64.ActiveCfg = Debug|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|x64.Build.0 = Debug|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|x86.ActiveCfg = Debug|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Debug|x86.Build.0 = Debug|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|Any CPU.Build.0 = Release|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|x64.ActiveCfg = Release|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|x64.Build.0 = Release|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|x86.ActiveCfg = Release|Any CPU - {1146EAAC-E434-404A-8198-B4F0CB23BC57}.Release|x86.Build.0 = Release|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Debug|x64.ActiveCfg = Debug|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Debug|x64.Build.0 = Debug|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Debug|x86.ActiveCfg = Debug|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Debug|x86.Build.0 = Debug|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Release|Any CPU.Build.0 = Release|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Release|x64.ActiveCfg = Release|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Release|x64.Build.0 = Release|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Release|x86.ActiveCfg = Release|Any CPU + {1BBF0DFE-2138-4E29-BFA1-49A2F0B4C913}.Release|x86.Build.0 = Release|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Debug|x64.ActiveCfg = Debug|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Debug|x64.Build.0 = Debug|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Debug|x86.ActiveCfg = Debug|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Debug|x86.Build.0 = Debug|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|Any CPU.Build.0 = Release|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|x64.ActiveCfg = Release|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|x64.Build.0 = Release|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|x86.ActiveCfg = Release|Any CPU + {453C809B-40FC-4A93-93B8-DE449D48B9FF}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/Microsoft.DotNet.ShellShimMaker.Tests/FakeEnvironmentProvider.cs b/test/Microsoft.DotNet.ShellShim.Tests/FakeEnvironmentProvider.cs similarity index 97% rename from test/Microsoft.DotNet.ShellShimMaker.Tests/FakeEnvironmentProvider.cs rename to test/Microsoft.DotNet.ShellShim.Tests/FakeEnvironmentProvider.cs index 4057febef..e33918512 100644 --- a/test/Microsoft.DotNet.ShellShimMaker.Tests/FakeEnvironmentProvider.cs +++ b/test/Microsoft.DotNet.ShellShim.Tests/FakeEnvironmentProvider.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using Microsoft.DotNet.Cli.Utils; -namespace Microsoft.DotNet.ShellShimMaker.Tests +namespace Microsoft.DotNet.ShellShim.Tests { internal class FakeEnvironmentProvider : IEnvironmentProvider { diff --git a/test/Microsoft.DotNet.ShellShimMaker.Tests/FakeFile.cs b/test/Microsoft.DotNet.ShellShim.Tests/FakeFile.cs similarity index 96% rename from test/Microsoft.DotNet.ShellShimMaker.Tests/FakeFile.cs rename to test/Microsoft.DotNet.ShellShim.Tests/FakeFile.cs index a881758b9..bb9d46d6d 100644 --- a/test/Microsoft.DotNet.ShellShimMaker.Tests/FakeFile.cs +++ b/test/Microsoft.DotNet.ShellShim.Tests/FakeFile.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.IO; using Microsoft.Extensions.EnvironmentAbstractions; -namespace Microsoft.DotNet.ShellShimMaker.Tests +namespace Microsoft.DotNet.ShellShim.Tests { internal class FakeFile : IFile { diff --git a/test/Microsoft.DotNet.ShellShimMaker.Tests/FakeReporter.cs b/test/Microsoft.DotNet.ShellShim.Tests/FakeReporter.cs similarity index 93% rename from test/Microsoft.DotNet.ShellShimMaker.Tests/FakeReporter.cs rename to test/Microsoft.DotNet.ShellShim.Tests/FakeReporter.cs index 3075cf470..a75956df7 100644 --- a/test/Microsoft.DotNet.ShellShimMaker.Tests/FakeReporter.cs +++ b/test/Microsoft.DotNet.ShellShim.Tests/FakeReporter.cs @@ -4,7 +4,7 @@ using System; using Microsoft.DotNet.Cli.Utils; -namespace Microsoft.DotNet.ShellShimMaker.Tests +namespace Microsoft.DotNet.ShellShim.Tests { internal class FakeReporter : IReporter { diff --git a/test/Microsoft.DotNet.ShellShimMaker.Tests/LinuxEnvironmentPathTests.cs b/test/Microsoft.DotNet.ShellShim.Tests/LinuxEnvironmentPathTests.cs similarity index 78% rename from test/Microsoft.DotNet.ShellShimMaker.Tests/LinuxEnvironmentPathTests.cs rename to test/Microsoft.DotNet.ShellShim.Tests/LinuxEnvironmentPathTests.cs index 910721210..080dc4c65 100644 --- a/test/Microsoft.DotNet.ShellShimMaker.Tests/LinuxEnvironmentPathTests.cs +++ b/test/Microsoft.DotNet.ShellShim.Tests/LinuxEnvironmentPathTests.cs @@ -6,11 +6,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using FluentAssertions; +using Microsoft.DotNet.Configurer; using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.Extensions.DependencyModel.Tests; using Xunit; -namespace Microsoft.DotNet.ShellShimMaker.Tests +namespace Microsoft.DotNet.ShellShim.Tests { public class LinuxEnvironmentPathTests { @@ -19,7 +20,7 @@ namespace Microsoft.DotNet.ShellShimMaker.Tests { var fakeReporter = new FakeReporter(); var linuxEnvironmentPath = new LinuxEnvironmentPath( - @"executable\path", + new BashPathUnderHomeDirectory("/myhome", "executable/path"), fakeReporter, new FakeEnvironmentProvider( new Dictionary @@ -32,11 +33,11 @@ namespace Microsoft.DotNet.ShellShimMaker.Tests // similar to https://code.visualstudio.com/docs/setup/mac fakeReporter.Message.Should().Be( - $"Cannot find the tools executable path. Please ensure executable\\path is added to your PATH.{Environment.NewLine}" + + $"Cannot find the tools executable path. Please ensure /myhome/executable/path is added to your PATH.{Environment.NewLine}" + $"If you are using bash. You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" + $"cat << EOF >> ~/.bash_profile{Environment.NewLine}" + $"# Add .NET Core SDK tools{Environment.NewLine}" + - $"export PATH=\"$PATH:executable\\path\"{Environment.NewLine}" + + $"export PATH=\"$PATH:/myhome/executable/path\"{Environment.NewLine}" + $"EOF"); } @@ -45,12 +46,12 @@ namespace Microsoft.DotNet.ShellShimMaker.Tests { var fakeReporter = new FakeReporter(); var linuxEnvironmentPath = new LinuxEnvironmentPath( - @"executable\path", + new BashPathUnderHomeDirectory("/myhome", "executable/path"), fakeReporter, new FakeEnvironmentProvider( new Dictionary { - {"PATH", @"executable\path"} + {"PATH", @"/myhome/executable/path"} }), FakeFile.Empty); @@ -64,7 +65,7 @@ namespace Microsoft.DotNet.ShellShimMaker.Tests { var fakeReporter = new FakeReporter(); var linuxEnvironmentPath = new LinuxEnvironmentPath( - @"executable\path", + new BashPathUnderHomeDirectory("/myhome", "executable/path"), fakeReporter, new FakeEnvironmentProvider( new Dictionary @@ -76,7 +77,9 @@ namespace Microsoft.DotNet.ShellShimMaker.Tests linuxEnvironmentPath.PrintAddPathInstructionIfPathDoesNotExist(); - fakeReporter.Message.Should().Be("Since you just installed the .NET Core SDK, you will need to logout or restart your session before running the tool you installed."); + fakeReporter.Message.Should() + .Be( + "Since you just installed the .NET Core SDK, you will need to logout or restart your session before running the tool you installed."); } } } diff --git a/test/Microsoft.DotNet.ShellShimMaker.Tests/Microsoft.DotNet.ShellShimMaker.Tests.csproj b/test/Microsoft.DotNet.ShellShim.Tests/Microsoft.DotNet.ShellShim.Tests.csproj similarity index 100% rename from test/Microsoft.DotNet.ShellShimMaker.Tests/Microsoft.DotNet.ShellShimMaker.Tests.csproj rename to test/Microsoft.DotNet.ShellShim.Tests/Microsoft.DotNet.ShellShim.Tests.csproj diff --git a/test/Microsoft.DotNet.ShellShimMaker.Tests/OsxEnvironmentPathTests.cs b/test/Microsoft.DotNet.ShellShim.Tests/OsxEnvironmentPathTests.cs similarity index 84% rename from test/Microsoft.DotNet.ShellShimMaker.Tests/OsxEnvironmentPathTests.cs rename to test/Microsoft.DotNet.ShellShim.Tests/OsxEnvironmentPathTests.cs index 23b5e9462..ea2a6f1a0 100644 --- a/test/Microsoft.DotNet.ShellShimMaker.Tests/OsxEnvironmentPathTests.cs +++ b/test/Microsoft.DotNet.ShellShim.Tests/OsxEnvironmentPathTests.cs @@ -6,11 +6,12 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using FluentAssertions; +using Microsoft.DotNet.Configurer; using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.Extensions.DependencyModel.Tests; using Xunit; -namespace Microsoft.DotNet.ShellShimMaker.Tests +namespace Microsoft.DotNet.ShellShim.Tests { public class OsxEnvironmentPathTests { @@ -19,8 +20,7 @@ namespace Microsoft.DotNet.ShellShimMaker.Tests { var fakeReporter = new FakeReporter(); var osxEnvironmentPath = new OSXEnvironmentPath( - @"~/executable/path", - @"/Users/name/executable/path", + new BashPathUnderHomeDirectory("/myhome", "executable/path"), fakeReporter, new FakeEnvironmentProvider( new Dictionary @@ -33,23 +33,22 @@ namespace Microsoft.DotNet.ShellShimMaker.Tests // similar to https://code.visualstudio.com/docs/setup/mac fakeReporter.Message.Should().Be( - $"Cannot find the tools executable path. Please ensure /Users/name/executable/path is added to your PATH.{Environment.NewLine}" + + $"Cannot find the tools executable path. Please ensure /myhome/executable/path is added to your PATH.{Environment.NewLine}" + $"If you are using bash, You can do this by running the following command:{Environment.NewLine}{Environment.NewLine}" + $"cat << EOF >> ~/.bash_profile{Environment.NewLine}" + $"# Add .NET Core SDK tools{Environment.NewLine}" + - $"export PATH=\"$PATH:/Users/name/executable/path\"{Environment.NewLine}" + + $"export PATH=\"$PATH:/myhome/executable/path\"{Environment.NewLine}" + $"EOF"); } [Theory] - [InlineData("/Users/name/executable/path")] + [InlineData("/myhome/executable/path")] [InlineData("~/executable/path")] public void GivenEnvironmentAndReporterItPrintsNothingWhenenvironmentExists(string existingPath) { var fakeReporter = new FakeReporter(); var osxEnvironmentPath = new OSXEnvironmentPath( - @"~/executable/path", - @"/Users/name/executable/path", + new BashPathUnderHomeDirectory("/myhome", "executable/path"), fakeReporter, new FakeEnvironmentProvider( new Dictionary @@ -68,8 +67,7 @@ namespace Microsoft.DotNet.ShellShimMaker.Tests { var fakeReporter = new FakeReporter(); var osxEnvironmentPath = new OSXEnvironmentPath( - @"~/executable/path", - @"/Users/name/executable/path", + new BashPathUnderHomeDirectory("/myhome", "executable/path"), fakeReporter, new FakeEnvironmentProvider( new Dictionary diff --git a/test/Microsoft.DotNet.ShellShimMaker.Tests/ShellShimMakerTests.cs b/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs similarity index 98% rename from test/Microsoft.DotNet.ShellShimMaker.Tests/ShellShimMakerTests.cs rename to test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs index d9391729e..5b9d9946c 100644 --- a/test/Microsoft.DotNet.ShellShimMaker.Tests/ShellShimMakerTests.cs +++ b/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs @@ -12,7 +12,7 @@ using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.Tools.Test.Utilities; using Xunit; -namespace Microsoft.DotNet.ShellShimMaker.Tests +namespace Microsoft.DotNet.ShellShim.Tests { public class ShellShimMakerTests : TestBase { diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigGolden.xml b/test/Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsGolden.xml similarity index 100% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigGolden.xml rename to test/Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsGolden.xml diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigMalformed.xml b/test/Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsMalformed.xml similarity index 100% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigMalformed.xml rename to test/Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsMalformed.xml diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigMissing.xml b/test/Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsMissing.xml similarity index 100% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/DotnetToolsConfigMissing.xml rename to test/Microsoft.DotNet.ToolPackage.Tests/DotnetToolSettingsMissing.xml diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/Microsoft.DotNet.ToolPackageObtainer.Tests.csproj b/test/Microsoft.DotNet.ToolPackage.Tests/Microsoft.DotNet.ToolPackage.Tests.csproj similarity index 91% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/Microsoft.DotNet.ToolPackageObtainer.Tests.csproj rename to test/Microsoft.DotNet.ToolPackage.Tests/Microsoft.DotNet.ToolPackage.Tests.csproj index cf8b5f9cd..884dffcd4 100644 --- a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/Microsoft.DotNet.ToolPackageObtainer.Tests.csproj +++ b/test/Microsoft.DotNet.ToolPackage.Tests/Microsoft.DotNet.ToolPackage.Tests.csproj @@ -24,13 +24,13 @@ - + Always - + Always - + Always @@ -47,7 +47,7 @@ $(BaseOutputPath)/TestAsset/SampleGlobalTool - + diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/DotnetToolsConfig.xml b/test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/DotnetToolSettings.xml similarity index 100% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/DotnetToolsConfig.xml rename to test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/DotnetToolSettings.xml diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/Program.cs b/test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/Program.cs similarity index 100% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/Program.cs rename to test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/Program.cs diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/consoledemo.csproj b/test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/consoledemo.csproj similarity index 100% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/consoledemo.csproj rename to test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/consoledemo.csproj diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/includepublish.nuspec b/test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/includepublish.nuspec similarity index 77% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/includepublish.nuspec rename to test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/includepublish.nuspec index 89686425e..181fe3f74 100644 --- a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/SampleGlobalTool/includepublish.nuspec +++ b/test/Microsoft.DotNet.ToolPackage.Tests/SampleGlobalTool/includepublish.nuspec @@ -7,7 +7,7 @@ testauthor - - + + \ No newline at end of file diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/ToolConfigurationDeserializerTests.cs b/test/Microsoft.DotNet.ToolPackage.Tests/ToolConfigurationDeserializerTests.cs similarity index 73% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/ToolConfigurationDeserializerTests.cs rename to test/Microsoft.DotNet.ToolPackage.Tests/ToolConfigurationDeserializerTests.cs index 4c81f787a..f30923a0a 100644 --- a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/ToolConfigurationDeserializerTests.cs +++ b/test/Microsoft.DotNet.ToolPackage.Tests/ToolConfigurationDeserializerTests.cs @@ -9,14 +9,14 @@ using FluentAssertions; using NuGet.Protocol.Core.Types; using Xunit; -namespace Microsoft.DotNet.ToolPackageObtainer.Tests +namespace Microsoft.DotNet.ToolPackage.Tests { public class ToolConfigurationDeserializerTests { [Fact] public void GivenXmlPathItShouldGetToolConfiguration() { - ToolConfiguration toolConfiguration = ToolConfigurationDeserializer.Deserialize("DotnetToolsConfigGolden.xml"); + ToolConfiguration toolConfiguration = ToolConfigurationDeserializer.Deserialize("DotnetToolSettingsGolden.xml"); toolConfiguration.CommandName.Should().Be("sayhello"); toolConfiguration.ToolAssemblyEntryPoint.Should().Be("console.dll"); @@ -25,28 +25,28 @@ namespace Microsoft.DotNet.ToolPackageObtainer.Tests [Fact] public void GivenMalformedPathItThrows() { - Action a = () => ToolConfigurationDeserializer.Deserialize("DotnetToolsConfigMalformed.xml"); + Action a = () => ToolConfigurationDeserializer.Deserialize("DotnetToolSettingsMalformed.xml"); a.ShouldThrow() .And.Message.Should() - .Contain("Failed to retrive tool configuration exception, configuration is malformed xml"); + .Contain("The tool's settings file is invalid xml"); } [Fact] public void GivenMissingContentItThrows() { - Action a = () => ToolConfigurationDeserializer.Deserialize("DotnetToolsConfigMissing.xml"); + Action a = () => ToolConfigurationDeserializer.Deserialize("DotnetToolSettingsMissing.xml"); a.ShouldThrow() .And.Message.Should() - .Contain("Configuration content error"); + .Contain("The tool's settings file contains error"); } [Fact] public void GivenInvalidCharAsFileNameItThrows() { - Action a = () => new ToolConfiguration("na***me", "my.dll"); + Action a = () => new ToolConfiguration("na\0me", "my.dll"); a.ShouldThrow() .And.Message.Should() - .Contain("Cannot contain following character"); + .Contain("Contains one or more invalid characters"); } } } diff --git a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/ToolPackageObtainerTests.cs b/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageObtainerTests.cs similarity index 78% rename from test/Microsoft.DotNet.ToolPackageObtainer.Tests/ToolPackageObtainerTests.cs rename to test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageObtainerTests.cs index 01606f251..6c4b20b19 100644 --- a/test/Microsoft.DotNet.ToolPackageObtainer.Tests/ToolPackageObtainerTests.cs +++ b/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageObtainerTests.cs @@ -7,9 +7,10 @@ using FluentAssertions; using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Tools.Install.Tool; using Xunit; -namespace Microsoft.DotNet.ToolPackageObtainer.Tests +namespace Microsoft.DotNet.ToolPackage.Tests { public class ToolPackageObtainerTests : TestBase { @@ -60,6 +61,7 @@ namespace Microsoft.DotNet.ToolPackageObtainer.Tests .GetParentPath() .GetParentPath() .GetParentPath() + .GetParentPath() .WithFile("project.assets.json").Value; File.Exists(assetJsonPath) @@ -78,13 +80,10 @@ namespace Microsoft.DotNet.ToolPackageObtainer.Tests Directory.CreateDirectory(tempProjectDirectory.Value); /* - * No nuget config means you don't need nuget config passed in during call - * NuGet needs a way to find the package, in production, it will keep look up folders for Nuget.Config - * and use the feed there. - * In test, we don't want NuGet to keep look up, so we just copy paste beside the project. + * In test, we don't want NuGet to keep look up, so we point current directory to nugetconfig. */ - File.Copy(nugetConfigPath.Value, - tempProjectDirectory.WithFile("nuget.config").Value); + + Directory.SetCurrentDirectory(nugetConfigPath.GetDirectoryPath().Value); var packageObtainer = new ToolPackageObtainer( @@ -135,6 +134,29 @@ namespace Microsoft.DotNet.ToolPackageObtainer.Tests .BeTrue(executable + " should have the executable"); } + [Fact] + public void GivenAllButNoPackageVersionAndInvokeTwiceItShouldNotThrow() + { + var nugetConfigPath = WriteNugetConfigFileToPointToTheFeed(); + var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName()); + + var packageObtainer = + ConstructDefaultPackageObtainer(toolsPath); + + packageObtainer.ObtainAndReturnExecutablePath( + packageId: TestPackageId, + nugetconfig: nugetConfigPath, + targetframework: _testTargetframework); + + Action secondCall = () => packageObtainer.ObtainAndReturnExecutablePath( + packageId: TestPackageId, + nugetconfig: nugetConfigPath, + targetframework: _testTargetframework); + + secondCall.ShouldNotThrow(); + } + + [Fact] public void GivenAllButNoTargetFrameworkItCanDownloadThePackage() { @@ -166,6 +188,25 @@ namespace Microsoft.DotNet.ToolPackageObtainer.Tests .BeTrue(executable + " should have the executable"); } + [Fact] + public void GivenNonExistentNugetConfigFileItThrows() + { + var toolsPath = Path.Combine(Directory.GetCurrentDirectory(), Path.GetRandomFileName()); + + var packageObtainer = + ConstructDefaultPackageObtainer(toolsPath); + Action a = () => packageObtainer.ObtainAndReturnExecutablePath( + packageId: TestPackageId, + packageVersion: TestPackageVersion, + nugetconfig: new FilePath("NonExistent.file"), + targetframework: _testTargetframework); + + a.ShouldThrow() + .And + .Message.Should().Contain("does not exist"); + + } + private static readonly Func GetUniqueTempProjectPathEachTest = () => { var tempProjectDirectory = @@ -187,18 +228,24 @@ namespace Microsoft.DotNet.ToolPackageObtainer.Tests private static FilePath WriteNugetConfigFileToPointToTheFeed() { - var nugetConfigName = Path.GetRandomFileName() + ".config"; + var nugetConfigName = "nuget.config"; var executeDirectory = Path.GetDirectoryName( System.Reflection .Assembly .GetExecutingAssembly() .Location); + + var tempPathForNugetConfigWithWhiteSpace = + Path.Combine(Path.GetTempPath(), + Path.GetRandomFileName() + " " + Path.GetRandomFileName()); + Directory.CreateDirectory(tempPathForNugetConfigWithWhiteSpace); + NuGetConfig.Write( - directory: executeDirectory, + directory: tempPathForNugetConfigWithWhiteSpace, configname: nugetConfigName, localFeedPath: Path.Combine(executeDirectory, "TestAssetLocalNugetFeed")); - return new FilePath(Path.GetFullPath(nugetConfigName)); + return new FilePath(Path.GetFullPath(Path.Combine(tempPathForNugetConfigWithWhiteSpace, nugetConfigName))); } private readonly string _testTargetframework = BundledTargetFramework.GetTargetFrameworkMoniker(); diff --git a/test/dotnet.Tests/ParserTests/InstallToolParserTests.cs b/test/dotnet.Tests/ParserTests/InstallToolParserTests.cs new file mode 100644 index 000000000..b6cfa06ca --- /dev/null +++ b/test/dotnet.Tests/ParserTests/InstallToolParserTests.cs @@ -0,0 +1,52 @@ +// 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.Linq; +using FluentAssertions; +using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Cli.CommandLine; +using Xunit; +using Xunit.Abstractions; +using Parser = Microsoft.DotNet.Cli.Parser; + +namespace Microsoft.DotNet.Tests.ParserTests +{ + public class InstallToolParserTests + { + private readonly ITestOutputHelper output; + + public InstallToolParserTests(ITestOutputHelper output) + { + this.output = output; + } + + [Fact] + public void InstallGlobaltoolParserCanGetPackageIdAndPackageVersion() + { + var command = Parser.Instance; + var result = command.Parse("dotnet install tool console.test.app --version 1.0.1"); + + var parseResult = result["dotnet"]["install"]["tool"]; + + var packageId = parseResult.Arguments.Single(); + var packageVersion = parseResult.ValueOrDefault("version"); + + packageId.Should().Be("console.test.app"); + packageVersion.Should().Be("1.0.1"); + } + + [Fact] + public void InstallGlobaltoolParserCanGetFollowingArguments() + { + var command = Parser.Instance; + var result = + command.Parse( + @"dotnet install tool console.test.app --version 1.0.1 --framework netcoreapp2.0 --configfile C:\TestAssetLocalNugetFeed"); + + var parseResult = result["dotnet"]["install"]["tool"]; + + parseResult.ValueOrDefault("configfile").Should().Be(@"C:\TestAssetLocalNugetFeed"); + parseResult.ValueOrDefault("framework").Should().Be("netcoreapp2.0"); + } + } +}