From 8b13b3e5797dbe37444f99991100da0eb5c1b7a6 Mon Sep 17 00:00:00 2001 From: Daniel Plaisted Date: Fri, 5 May 2017 13:13:18 -0700 Subject: [PATCH] Fall back to tools restored for .NET Core 1.x if they haven't been restored for .NET Core 2.0 --- .../ProjectToolsCommandResolver.cs | 26 ++++++++- test/dotnet.Tests/PackagedCommandTests.cs | 55 ++++++++++++++++++- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs index 7cd9a6113..8f952c950 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs @@ -141,9 +141,33 @@ namespace Microsoft.DotNet.Cli.Utils toolPackageFramework, possiblePackageRoots); + + // NuGet restore in Visual Studio may restore for netcoreapp1.0. So if that happens, fall back to + // looking for a netcoreapp1.0 or netcoreapp1.1 tool restore. if (toolLockFile == null) { - return null; + if (toolPackageFramework.Framework == FrameworkConstants.FrameworkIdentifiers.NetCoreApp && + toolPackageFramework.Version >= new Version(2, 0, 0)) + { + foreach (var fallbackFramework in new [] { "netcoreapp1.1", "netcoreapp1.0"}) + { + toolPackageFramework = NuGetFramework.Parse(fallbackFramework); + toolLockFile = GetToolLockFile( + toolLibraryRange, + toolPackageFramework, + possiblePackageRoots); + + if (toolLockFile != null) + { + break; + } + } + } + + if (toolLockFile == null) + { + return null; + } } Reporter.Verbose.WriteLine(string.Format( diff --git a/test/dotnet.Tests/PackagedCommandTests.cs b/test/dotnet.Tests/PackagedCommandTests.cs index bb75131d5..d5c83d97a 100644 --- a/test/dotnet.Tests/PackagedCommandTests.cs +++ b/test/dotnet.Tests/PackagedCommandTests.cs @@ -16,6 +16,7 @@ using Xunit.Abstractions; using Microsoft.Build.Construction; using System.Linq; using Microsoft.Build.Evaluation; +using System.Xml.Linq; namespace Microsoft.DotNet.Tests { @@ -161,10 +162,62 @@ namespace Microsoft.DotNet.Tests .Execute(toolPrefersCLIRuntime ? "portable-v1-prefercli" : "portable-v1"); result.Should().Pass() - .And.HaveStdOutContaining("I'm running on shared framework version 1.1.1!"); + .And.HaveStdOutContaining("I'm running on shared framework version 1.1.1!"); } + [RequiresSpecificFrameworkFact("netcoreapp1.1")] + public void IfAToolHasNotBeenRestoredForNetCoreApp2_0ItFallsBackToNetCoreApp1_x() + { + string toolName = "dotnet-portable-v1"; + + var toolFolder = Path.Combine(new RepoDirectoriesProvider().NugetPackages, + ".tools", + toolName); + + // Other tests may have restored the tool for netcoreapp2.0, so delete its tools folder + if (Directory.Exists(toolFolder)) + { + Directory.Delete(toolFolder, true); + } + + var testInstance = TestAssets.Get("AppWithToolDependency") + .CreateInstance() + .WithSourceFiles() + .WithNuGetConfig(new RepoDirectoriesProvider().TestPackages); + + testInstance = testInstance.WithProjectChanges(project => + { + var ns = project.Root.Name.Namespace; + + // Remove reference to tool that won't restore on 1.x + project.Descendants(ns + "DotNetCliToolReference") + .Where(tr => tr.Attribute("Include").Value == "dotnet-PreferCliRuntime") + .Remove(); + + var toolReference = project.Descendants(ns + "DotNetCliToolReference") + .Where(tr => tr.Attribute("Include").Value == "dotnet-portable") + .Single(); + + toolReference.Attribute("Include").Value = toolName; + + // Restore tools for .NET Core 1.1 + project.Root.Element(ns + "PropertyGroup") + .Add(new XElement(ns + "DotnetCliToolTargetFramework", "netcoreapp1.1")); + + }); + + testInstance = testInstance.WithRestoreFiles(); + + var result = + new DotnetCommand(DotnetUnderTest.WithBackwardsCompatibleRuntimes) + .WithWorkingDirectory(testInstance.Root) + .Execute("portable-v1"); + + result.Should().Pass() + .And.HaveStdOutContaining("I'm running on shared framework version 1.1.1!"); + } + [Fact] public void CanInvokeToolWhosePackageNameIsDifferentFromDllName() {