diff --git a/build/DependencyVersions.props b/build/DependencyVersions.props index 3aa2d1520..a0edb6f5c 100644 --- a/build/DependencyVersions.props +++ b/build/DependencyVersions.props @@ -16,7 +16,7 @@ $(MicrosoftCodeAnalysisCSharpPackageVersion) 2.1.0-preview1-62516-03 $(MicrosoftNETSdkPackageVersion) - 2.0.0-rel-20171110-671 + 2.1.0-release21-20180126-1326543 $(MicrosoftNETSdkWebPackageVersion) $(MicrosoftNETSdkWebPackageVersion) 1.0.1-beta3-20180104-1263555 diff --git a/src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs b/src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs index 71f740131..20901eb48 100644 --- a/src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs +++ b/src/Microsoft.DotNet.Configurer/CliFolderPathCalculator.cs @@ -12,20 +12,23 @@ namespace Microsoft.DotNet.Configurer { public class CliFolderPathCalculator { - private const string ToolsFolderName = "tools"; + // ToolsShimFolderName ToolPackageFolderName cannot be the same + // or if the PackageId is the same as CommandName, they will conflict on unix. + private const string ToolsShimFolderName = "tools"; + private const string ToolPackageFolderName = "toolspkgs"; private const string DotnetProfileDirectoryName = ".dotnet"; 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 BashPathUnderHomeDirectory ExecutablePackagesPathInUnix + public string ToolsShimPath => Path.Combine(DotnetUserProfileFolderPath, ToolsShimFolderName); + public string ToolsPackagePath => Path.Combine(DotnetUserProfileFolderPath, ToolPackageFolderName); + public BashPathUnderHomeDirectory ToolsShimPathInUnix { get { return new BashPathUnderHomeDirectory(Environment.GetEnvironmentVariable("HOME"), - Path.Combine(DotnetProfileDirectoryName, ToolsFolderName)); + Path.Combine(DotnetProfileDirectoryName, ToolsShimFolderName)); } } diff --git a/src/dotnet/ShellShim/EnvironmentPathFactory.cs b/src/dotnet/ShellShim/EnvironmentPathFactory.cs index 55daa11f6..a60a4ba86 100644 --- a/src/dotnet/ShellShim/EnvironmentPathFactory.cs +++ b/src/dotnet/ShellShim/EnvironmentPathFactory.cs @@ -32,20 +32,20 @@ namespace Microsoft.DotNet.ShellShim if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { environmentPath = new WindowsEnvironmentPath( - cliFolderPathCalculator.ExecutablePackagesPath, + cliFolderPathCalculator.ToolsShimPath, Reporter.Output); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && hasSuperUserAccess) { environmentPath = new LinuxEnvironmentPath( - cliFolderPathCalculator.ExecutablePackagesPathInUnix, + cliFolderPathCalculator.ToolsShimPathInUnix, Reporter.Output, environmentProvider, new FileWrapper()); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && hasSuperUserAccess) { environmentPath = new OSXEnvironmentPath( - executablePath: cliFolderPathCalculator.ExecutablePackagesPathInUnix, + executablePath: cliFolderPathCalculator.ToolsShimPathInUnix, reporter: Reporter.Output, environmentProvider: environmentProvider, fileSystem: new FileWrapper()); diff --git a/src/dotnet/ShellShim/ShellShimMaker.cs b/src/dotnet/ShellShim/ShellShimMaker.cs index 6121cfd2a..41c21537a 100644 --- a/src/dotnet/ShellShim/ShellShimMaker.cs +++ b/src/dotnet/ShellShim/ShellShimMaker.cs @@ -30,6 +30,11 @@ namespace Microsoft.DotNet.ShellShim { FilePath shimPath = GetShimPath(shellCommandName); + if (!Directory.Exists(shimPath.GetDirectoryPath().Value)) + { + Directory.CreateDirectory(shimPath.GetDirectoryPath().Value); + } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { CreateConfigFile(shimPath.Value + ".config", entryPoint: packageExecutable, runner: "dotnet"); diff --git a/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs b/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs index f3041a12a..e8d288c82 100644 --- a/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs +++ b/src/dotnet/commands/dotnet-install/dotnet-install-tool/InstallToolCommand.cs @@ -50,10 +50,9 @@ namespace Microsoft.DotNet.Tools.Install.Tool _global = appliedCommand.ValueOrDefault("global"); var cliFolderPathCalculator = new CliFolderPathCalculator(); - var executablePackagePath = new DirectoryPath(cliFolderPathCalculator.ExecutablePackagesPath); var offlineFeedPath = new DirectoryPath(cliFolderPathCalculator.CliFallbackFolderPath); _toolPackageObtainer = toolPackageObtainer ?? new ToolPackageObtainer( - executablePackagePath, + new DirectoryPath(cliFolderPathCalculator.ToolsPackagePath), offlineFeedPath, () => new DirectoryPath(Path.GetTempPath()) .WithSubDirectories(Path.GetRandomFileName()) @@ -65,7 +64,7 @@ namespace Microsoft.DotNet.Tools.Install.Tool ?? EnvironmentPathFactory .CreateEnvironmentPathInstruction(); - _shellShimMaker = shellShimMaker ?? new ShellShimMaker(executablePackagePath.Value); + _shellShimMaker = shellShimMaker ?? new ShellShimMaker(cliFolderPathCalculator.ToolsShimPath); _reporter = reporter ?? Reporter.Output; } diff --git a/test/Microsoft.DotNet.Configurer.UnitTests/GivenAPathCalculator.cs b/test/Microsoft.DotNet.Configurer.UnitTests/GivenAPathCalculator.cs new file mode 100644 index 000000000..a4d6eb558 --- /dev/null +++ b/test/Microsoft.DotNet.Configurer.UnitTests/GivenAPathCalculator.cs @@ -0,0 +1,23 @@ +// 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.Utils; +using Microsoft.DotNet.Tools.Test.Utilities; +using FluentAssertions; + +namespace Microsoft.DotNet.Configurer.UnitTests +{ + public class GivenAPathCalculator + { + [NonWindowsOnlyFact] + public void It_does_not_return_same_path_for_tools_package_and_tool_shim() + { + // shim name will conflict with the folder that is PackageId, if commandName and packageId are the same. + var cliFolderPathCalculator = new CliFolderPathCalculator(); + cliFolderPathCalculator.ToolsPackagePath.Should().NotBe(cliFolderPathCalculator.ToolsShimPath); + cliFolderPathCalculator.ToolsPackagePath.Should().NotBe(cliFolderPathCalculator.ToolsShimPathInUnix.Path); + } + } +} diff --git a/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs b/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs index 956523926..6ff0b87f4 100644 --- a/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs +++ b/test/Microsoft.DotNet.ShellShim.Tests/ShellShimMakerTests.cs @@ -72,6 +72,20 @@ namespace Microsoft.DotNet.ShellShim.Tests stdOut.Should().Contain("Hello World"); } + [Fact] + public void GivenAnExecutablePathDirectoryThatDoesNotExistItCanGenerateShimFile() + { + var outputDll = MakeHelloWorldExecutableDll(); + var extraNonExistDirectory = Path.GetRandomFileName(); + var shellShimMaker = new ShellShimMaker(Path.Combine(TempRoot.Root, extraNonExistDirectory)); + var shellCommandName = nameof(ShellShimMakerTests) + Path.GetRandomFileName(); + + Action a = () => shellShimMaker.CreateShim( + new FilePath(outputDll.FullName), + shellCommandName); + a.ShouldNotThrow(); + } + [Theory] [InlineData("arg1 arg2", new[] { "arg1", "arg2" })] [InlineData(" \"arg1 with space\" arg2", new[] { "arg1 with space", "arg2" })]