Merge pull request #6138 from livarcocc/tool_fallback_folder

Switched to using a FallbackPackagePathResolver to find the tool dll
This commit is contained in:
Livar 2017-03-27 10:57:55 -07:00 committed by GitHub
commit e09c33400c
11 changed files with 242 additions and 19 deletions

View file

@ -0,0 +1,15 @@
// 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;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello Fallback folder World!");
}
}
}

View file

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" />
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<AssemblyName>dotnet-fallbackfoldertool</AssemblyName>
<OutputType>Exe</OutputType>
<VersionSuffix></VersionSuffix>
<RuntimeFrameworkVersion>$(CLI_SharedFrameworkVersion)</RuntimeFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<BuiltProjectOutputGroupOutput Include="$(ProjectRuntimeConfigFilePath)">
<FinalOutputPath>$(ProjectRuntimeConfigFilePath)</FinalOutputPath>
</BuiltProjectOutputGroupOutput>
</ItemGroup>
</Project>

View file

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" />
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<OutputType>Exe</OutputType>
<RuntimeFrameworkVersion>$(CLI_SharedFrameworkVersion)</RuntimeFrameworkVersion>
<DotnetCliToolTargetFramework>netcoreapp2.0</DotnetCliToolTargetFramework>
</PropertyGroup>
<ItemGroup>
<DotNetCliToolReference Include="dotnet-fallbackfoldertool" Version="1.0.0" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="test-packages" value="../../../artifacts/testpackages" />
</packageSources>
</configuration>

View file

@ -0,0 +1,15 @@
// 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;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

View file

@ -127,6 +127,15 @@
<VersionSuffix></VersionSuffix>
<Clean>True</Clean>
</BaseTestPackageProject>
<BaseTestPackageProject Include="TestAssets/TestPackages/dotnet-fallbackfoldertool">
<Name>dotnet-fallbackfoldertool</Name>
<ProjectName>dotnet-fallbackfoldertool.csproj</ProjectName>
<IsTool>True</IsTool>
<IsApplicable>True</IsApplicable>
<VersionPrefix>1.0.0</VersionPrefix>
<VersionSuffix></VersionSuffix>
<Clean>True</Clean>
</BaseTestPackageProject>
<BaseTestPackageProject Include="TestAssets/TestPackages/dotnet-prefercliruntime">
<Name>dotnet-prefercliruntime</Name>
<ProjectName>dotnet-prefercliruntime.csproj</ProjectName>

View file

@ -18,5 +18,14 @@ namespace Microsoft.DotNet.Cli.Utils
string depsFilePath,
string runtimeConfigPath);
CommandSpec CreateCommandSpecFromLibrary(
LockFileTargetLibrary toolLibrary,
string commandName,
IEnumerable<string> commandArguments,
IEnumerable<string> allowedExtensions,
IEnumerable<string> packageFolders,
CommandResolutionStrategy commandResolutionStrategy,
string depsFilePath,
string runtimeConfigPath);
}
}

View file

@ -31,6 +31,27 @@ namespace Microsoft.DotNet.Cli.Utils
CommandResolutionStrategy commandResolutionStrategy,
string depsFilePath,
string runtimeConfigPath)
{
return CreateCommandSpecFromLibrary(
toolLibrary,
commandName,
commandArguments,
allowedExtensions,
new List<string> { nugetPackagesRoot },
commandResolutionStrategy,
depsFilePath,
runtimeConfigPath);
}
public CommandSpec CreateCommandSpecFromLibrary(
LockFileTargetLibrary toolLibrary,
string commandName,
IEnumerable<string> commandArguments,
IEnumerable<string> allowedExtensions,
IEnumerable<string> packageFolders,
CommandResolutionStrategy commandResolutionStrategy,
string depsFilePath,
string runtimeConfigPath)
{
Reporter.Verbose.WriteLine(string.Format(
LocalizableStrings.AttemptingToFindCommand,
@ -51,7 +72,7 @@ namespace Microsoft.DotNet.Cli.Utils
return null;
}
var commandPath = GetCommandFilePath(nugetPackagesRoot, toolLibrary, toolAssembly);
var commandPath = GetCommandFilePath(packageFolders, toolLibrary, toolAssembly);
if (!File.Exists(commandPath))
{
@ -68,17 +89,28 @@ namespace Microsoft.DotNet.Cli.Utils
commandArguments,
depsFilePath,
commandResolutionStrategy,
nugetPackagesRoot,
packageFolders,
runtimeConfigPath);
}
private string GetCommandFilePath(
string nugetPackagesRoot,
IEnumerable<string> packageFolders,
LockFileTargetLibrary toolLibrary,
LockFileItem runtimeAssembly)
{
var packageDirectory = new VersionFolderPathResolver(nugetPackagesRoot)
.GetInstallPath(toolLibrary.Name, toolLibrary.Version);
var packageFoldersCount = packageFolders.Count();
var userPackageFolder = packageFoldersCount == 1 ? string.Empty : packageFolders.First();
var fallbackPackageFolders = packageFoldersCount > 1 ? packageFolders.Skip(1) : packageFolders;
var packageDirectory = new FallbackPackagePathResolver(userPackageFolder, fallbackPackageFolders)
.GetPackageDirectory(toolLibrary.Name, toolLibrary.Version);
if (packageDirectory == null)
{
throw new GracefulException(string.Format(
LocalizableStrings.CommandAssembliesNotFound,
toolLibrary.Name));
}
var filePath = Path.Combine(
packageDirectory,
@ -92,7 +124,7 @@ namespace Microsoft.DotNet.Cli.Utils
IEnumerable<string> commandArguments,
string depsFilePath,
CommandResolutionStrategy commandResolutionStrategy,
string nugetPackagesRoot,
IEnumerable<string> packageFolders,
string runtimeConfigPath)
{
var commandExtension = Path.GetExtension(commandPath);
@ -104,7 +136,7 @@ namespace Microsoft.DotNet.Cli.Utils
commandArguments,
depsFilePath,
commandResolutionStrategy,
nugetPackagesRoot,
packageFolders,
runtimeConfigPath);
}
@ -116,7 +148,7 @@ namespace Microsoft.DotNet.Cli.Utils
IEnumerable<string> commandArguments,
string depsFilePath,
CommandResolutionStrategy commandResolutionStrategy,
string nugetPackagesRoot,
IEnumerable<string> packageFolders,
string runtimeConfigPath)
{
var host = string.Empty;
@ -144,8 +176,11 @@ namespace Microsoft.DotNet.Cli.Utils
arguments.Add(depsFilePath);
}
arguments.Add("--additionalprobingpath");
arguments.Add(nugetPackagesRoot);
foreach (var packageFolder in packageFolders)
{
arguments.Add("--additionalprobingpath");
arguments.Add(packageFolder);
}
if(_addAdditionalArguments != null)
{

View file

@ -136,12 +136,10 @@ namespace Microsoft.DotNet.Cli.Utils
var toolPackageFramework = project.DotnetCliToolTargetFramework;
string nugetPackagesRoot;
var toolLockFile = GetToolLockFile(
toolLibraryRange,
toolPackageFramework,
possiblePackageRoots,
out nugetPackagesRoot);
possiblePackageRoots);
if (toolLockFile == null)
{
@ -174,7 +172,8 @@ namespace Microsoft.DotNet.Cli.Utils
toolLockFile,
depsFileRoot);
var normalizedNugetPackagesRoot = PathUtility.EnsureNoTrailingDirectorySeparator(nugetPackagesRoot);
var packageFolders = toolLockFile.PackageFolders.Select(p =>
PathUtility.EnsureNoTrailingDirectorySeparator(p.Path));
Reporter.Verbose.WriteLine(string.Format(
LocalizableStrings.AttemptingToCreateCommandSpec,
@ -185,7 +184,7 @@ namespace Microsoft.DotNet.Cli.Utils
commandName,
args,
_allowedCommandExtensions,
normalizedNugetPackagesRoot,
packageFolders,
s_commandResolutionStrategy,
depsFilePath,
null);
@ -215,19 +214,16 @@ namespace Microsoft.DotNet.Cli.Utils
private LockFile GetToolLockFile(
SingleProjectInfo toolLibrary,
NuGetFramework framework,
IEnumerable<string> possibleNugetPackagesRoot,
out string nugetPackagesRoot)
IEnumerable<string> possibleNugetPackagesRoot)
{
foreach (var packagesRoot in possibleNugetPackagesRoot)
{
if (TryGetToolLockFile(toolLibrary, framework, packagesRoot, out LockFile lockFile))
{
nugetPackagesRoot = packagesRoot;
return lockFile;
}
}
nugetPackagesRoot = null;
return null;
}

View file

@ -71,6 +71,8 @@ namespace Microsoft.DotNet.Cli.Utils
public const string NoExecutableFoundMatchingCommand = "No executable found matching command \"{0}\"";
public const string CommandAssembliesNotFound = "The command executable for \"{0}\" was not found. The project may not have been restored or restore failed - run `dotnet restore`";
public const string WaitingForDebuggerToAttach = "Waiting for debugger to attach. Press ENTER to continue";
public const string ProcessId = "Process ID: {0}";

View file

@ -335,6 +335,111 @@ namespace Microsoft.DotNet.Tests
result.Args.Should().NotContain("--fx-version");
}
[Fact]
public void ItFindsToolsLocatedInTheNuGetFallbackFolder()
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
var testInstance = TestAssets.Get("AppWithFallbackFolderToolDependency")
.CreateInstance()
.WithSourceFiles();
var testProjectDirectory = testInstance.Root.FullName;
var fallbackFolder = Path.Combine(testProjectDirectory, "fallbackFolder");
PopulateFallbackFolder(testProjectDirectory, fallbackFolder);
var nugetConfig = UseNuGetConfigWithFallbackFolder(testInstance, fallbackFolder);
new RestoreCommand()
.WithWorkingDirectory(testProjectDirectory)
.Execute($"--configfile {nugetConfig}")
.Should()
.Pass();
var commandResolverArguments = new CommandResolverArguments()
{
CommandName = "dotnet-fallbackfoldertool",
CommandArguments = null,
ProjectDirectory = testProjectDirectory
};
var result = projectToolsCommandResolver.Resolve(commandResolverArguments);
result.Should().NotBeNull();
var commandPath = result.Args.Trim('"');
commandPath.Should().Contain(Path.Combine(
fallbackFolder,
"dotnet-fallbackfoldertool",
"1.0.0",
"lib",
"netcoreapp2.0",
"dotnet-fallbackfoldertool.dll"));
}
[Fact]
public void ItXXXWhenTheToolDllIsNotFound()
{
var projectToolsCommandResolver = SetupProjectToolsCommandResolver();
var testInstance = TestAssets.Get("AppWithFallbackFolderToolDependency")
.CreateInstance()
.WithSourceFiles();
var testProjectDirectory = testInstance.Root.FullName;
var fallbackFolder = Path.Combine(testProjectDirectory, "fallbackFolder");
PopulateFallbackFolder(testProjectDirectory, fallbackFolder);
var nugetConfig = UseNuGetConfigWithFallbackFolder(testInstance, fallbackFolder);
new RestoreCommand()
.WithWorkingDirectory(testProjectDirectory)
.Execute($"--configfile {nugetConfig}")
.Should()
.Pass();
Directory.Delete(Path.Combine(fallbackFolder, "dotnet-fallbackfoldertool"), true);
var commandResolverArguments = new CommandResolverArguments()
{
CommandName = "dotnet-fallbackfoldertool",
CommandArguments = null,
ProjectDirectory = testProjectDirectory
};
Action action = () => projectToolsCommandResolver.Resolve(commandResolverArguments);
action.ShouldThrow<GracefulException>().WithMessage(
"The command executable for \"dotnet-fallbackfoldertool\" was not found. The project may not have been restored or restore failed - run `dotnet restore`");
}
private void PopulateFallbackFolder(string testProjectDirectory, string fallbackFolder)
{
new RestoreCommand()
.WithWorkingDirectory(testProjectDirectory)
.Execute($"--packages {fallbackFolder}")
.Should()
.Pass();
Directory.Delete(Path.Combine(fallbackFolder, ".tools"), true);
}
private string UseNuGetConfigWithFallbackFolder(TestAssetInstance testInstance, string fallbackFolder)
{
var nugetConfig = testInstance.Root.GetFile("NuGet.Config").FullName;
File.WriteAllText(
nugetConfig,
$@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<fallbackPackageFolders>
<add key=""MachineWide"" value=""{fallbackFolder}""/>
</fallbackPackageFolders>
</configuration>
");
return nugetConfig;
}
private ProjectToolsCommandResolver SetupProjectToolsCommandResolver()
{
Environment.SetEnvironmentVariable(