diff --git a/src/dotnet/ToolPackage/IProjectRestorer.cs b/src/dotnet/ToolPackage/IProjectRestorer.cs index 0546c399a..343681f8d 100644 --- a/src/dotnet/ToolPackage/IProjectRestorer.cs +++ b/src/dotnet/ToolPackage/IProjectRestorer.cs @@ -9,7 +9,6 @@ namespace Microsoft.DotNet.ToolPackage internal interface IProjectRestorer { void Restore(FilePath project, - DirectoryPath assetJsonOutput, FilePath? nugetConfig = null, string verbosity = null); } diff --git a/src/dotnet/ToolPackage/ToolPackageInstaller.cs b/src/dotnet/ToolPackage/ToolPackageInstaller.cs index 14ea51d25..0814bc601 100644 --- a/src/dotnet/ToolPackage/ToolPackageInstaller.cs +++ b/src/dotnet/ToolPackage/ToolPackageInstaller.cs @@ -55,6 +55,7 @@ namespace Microsoft.DotNet.ToolPackage versionRange: versionRange, targetFramework: targetFramework ?? BundledTargetFramework.GetTargetFrameworkMoniker(), restoreDirectory: stageDirectory, + assetJsonOutputDirectory: stageDirectory, rootConfigDirectory: rootConfigDirectory, additionalFeeds: additionalFeeds); @@ -62,7 +63,6 @@ namespace Microsoft.DotNet.ToolPackage { _projectRestorer.Restore( tempProject, - stageDirectory, nugetConfig, verbosity: verbosity); } @@ -117,6 +117,7 @@ namespace Microsoft.DotNet.ToolPackage VersionRange versionRange, string targetFramework, DirectoryPath restoreDirectory, + DirectoryPath assetJsonOutputDirectory, DirectoryPath? rootConfigDirectory, string[] additionalFeeds) { @@ -133,7 +134,12 @@ namespace Microsoft.DotNet.ToolPackage var tempProjectContent = new XDocument( new XElement("Project", - new XAttribute("Sdk", "Microsoft.NET.Sdk"), + new XElement("PropertyGroup", + new XElement("BaseIntermediateOutputPath", assetJsonOutputDirectory.Value)), // change the output directory of asset.json + // due to https://github.com/Microsoft/msbuild/issues/1603 -- import SDK after setting BaseIntermediateOutputPath + new XElement(("Import"), + new XAttribute("Project", "Sdk.props"), + new XAttribute("Sdk", "Microsoft.NET.Sdk")), new XElement("PropertyGroup", new XElement("TargetFramework", targetFramework), new XElement("RestorePackagesPath", restoreDirectory.Value), @@ -149,9 +155,10 @@ namespace Microsoft.DotNet.ToolPackage new XElement("PackageReference", new XAttribute("Include", packageId.ToString()), new XAttribute("Version", - versionRange?.ToString("S", new VersionRangeFormatter()) ?? "*") // nuget will restore latest stable for * - )) - )); + versionRange?.ToString("S", new VersionRangeFormatter()) ?? "*"))), // nuget will restore latest stable for * + new XElement(("Import"), + new XAttribute("Project", "Sdk.targets"), + new XAttribute("Sdk", "Microsoft.NET.Sdk")))); File.WriteAllText(tempProject.Value, tempProjectContent.ToString()); return tempProject; diff --git a/src/dotnet/commands/dotnet-tool/install/ProjectRestorer.cs b/src/dotnet/commands/dotnet-tool/install/ProjectRestorer.cs index 7d0096b57..83ccd6f34 100644 --- a/src/dotnet/commands/dotnet-tool/install/ProjectRestorer.cs +++ b/src/dotnet/commands/dotnet-tool/install/ProjectRestorer.cs @@ -27,7 +27,6 @@ namespace Microsoft.DotNet.Tools.Tool.Install } public void Restore(FilePath project, - DirectoryPath assetJsonOutput, FilePath? nugetConfig = null, string verbosity = null) { @@ -43,8 +42,7 @@ namespace Microsoft.DotNet.Tools.Tool.Install argsToPassToRestore.AddRange(new List { "--runtime", - AnyRid, - $"-property:BaseIntermediateOutputPath={assetJsonOutput.ToXmlEncodeString()}" + AnyRid }); argsToPassToRestore.Add($"-verbosity:{verbosity ?? "quiet"}"); diff --git a/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageInstallerTests.cs b/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageInstallerTests.cs index 1b4dcadbd..e40c98c68 100644 --- a/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageInstallerTests.cs +++ b/test/Microsoft.DotNet.ToolPackage.Tests/ToolPackageInstallerTests.cs @@ -1,8 +1,9 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. +// 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 System.Globalization; using System.IO; using System.Linq; using System.Reflection; @@ -16,8 +17,10 @@ using Microsoft.DotNet.Tools.Tool.Install; using Microsoft.DotNet.Tools.Tests.ComponentMocks; using Microsoft.Extensions.DependencyModel.Tests; using Microsoft.Extensions.EnvironmentAbstractions; +using Microsoft.TemplateEngine.Cli; using NuGet.Versioning; using Xunit; +using LocalizableStrings = Microsoft.DotNet.Tools.Tool.Install.LocalizableStrings; namespace Microsoft.DotNet.ToolPackage.Tests { @@ -612,6 +615,35 @@ namespace Microsoft.DotNet.ToolPackage.Tests package.Uninstall(); } + [Fact] + public void GivenARootWithNonAsciiCharactorInstallSucceeds() + { + var nugetConfigPath = WriteNugetConfigFileToPointToTheFeed(); + + var surrogate = char.ConvertFromUtf32(int.Parse("2A601", NumberStyles.HexNumber)); + string nonAscii = "ab Ṱ̺̺̕o 田中さん åä," + surrogate; + + var root = new DirectoryPath(Path.Combine(TempRoot.Root, nonAscii, Path.GetRandomFileName())); + var reporter = new BufferedReporter(); + var fileSystem = new FileSystemWrapper(); + var store = new ToolPackageStore(root); + var installer = new ToolPackageInstaller( + store: store, + projectRestorer: new ProjectRestorer(reporter), + tempProject: GetUniqueTempProjectPathEachTest(), + offlineFeed: new DirectoryPath("does not exist")); + + var package = installer.InstallPackage( + packageId: TestPackageId, + versionRange: VersionRange.Parse(TestPackageVersion), + targetFramework: _testTargetframework, + nugetConfig: nugetConfigPath); + + AssertPackageInstall(reporter, fileSystem, package, store); + + package.Uninstall(); + } + private static void AssertPackageInstall( BufferedReporter reporter, IFileSystem fileSystem, diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ProjectRestorerMock.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ProjectRestorerMock.cs index 7d7f34849..a7548a484 100644 --- a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ProjectRestorerMock.cs +++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ProjectRestorerMock.cs @@ -57,19 +57,19 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks } public void Restore(FilePath project, - DirectoryPath assetJsonOutput, FilePath? nugetConfig = null, string verbosity = null) { string packageId; VersionRange versionRange; string targetFramework; + DirectoryPath assetJsonOutput; try { - // The mock installer wrote a mock project file containing id:version:framework + // The mock installer wrote a mock project file containing id;version;framework;stageDirectory var contents = _fileSystem.File.ReadAllText(project.Value); - var tokens = contents.Split(':'); - if (tokens.Length != 3) + var tokens = contents.Split(';'); + if (tokens.Length != 4) { throw new ToolPackageException(LocalizableStrings.ToolInstallationRestoreFailed); } @@ -77,6 +77,7 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks packageId = tokens[0]; versionRange = VersionRange.Parse(tokens[1]); targetFramework = tokens[2]; + assetJsonOutput = new DirectoryPath(tokens[3]); } catch (IOException) { diff --git a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageInstallerMock.cs b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageInstallerMock.cs index 9737ff858..6b28de63b 100644 --- a/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageInstallerMock.cs +++ b/test/Microsoft.DotNet.Tools.Tests.ComponentMocks/ToolPackageInstallerMock.cs @@ -63,12 +63,11 @@ namespace Microsoft.DotNet.Tools.Tests.ComponentMocks // Write a fake project with the requested package id, version, and framework _fileSystem.File.WriteAllText( tempProject.Value, - $"{packageId}:{versionRange?.ToString("S", new VersionRangeFormatter()) ?? "*"}:{targetFramework}"); + $"{packageId};{versionRange?.ToString("S", new VersionRangeFormatter()) ?? "*"};{targetFramework};{stageDirectory.Value}"); // Perform a restore on the fake project _projectRestorer.Restore( tempProject, - stageDirectory, nugetConfig, verbosity);