Merge pull request #2620 from dotnet/pawelka/tools

Fixing ProjectDependenciesCommandFactory to resolve tools
This commit is contained in:
Pawel Kadluczka 2016-04-21 22:26:58 -07:00
commit deb3367753
12 changed files with 231 additions and 21 deletions

View file

@ -0,0 +1,12 @@
using System;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Tool with output name!");
}
}
}

View file

@ -0,0 +1,17 @@
{
"version": "1.0.0",
"compilationOptions": {
"outputName": "dotnet-tool-with-output-name",
"emitEntryPoint": true
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-rc2-*"
}
}
}
}
}

View file

@ -0,0 +1,12 @@
using System;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("App with a dependency on a tool whose package name is different from the dll name!");
}
}
}

View file

@ -0,0 +1,22 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0-rc2-*",
"type": "platform"
}
},
"frameworks": {
"netcoreapp1.0": { }
},
"tools": {
"ToolWithOutputName": {
"version": "1.0.0",
"target": "package"
}
}
}

View file

@ -0,0 +1,12 @@
using System;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Contains a dependency on a tool whose package name is different from the dll name.");
}
}
}

View file

@ -0,0 +1,27 @@
{
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"ToolWithOutputName": {
"version": "1.0.0",
"target": "package"
},
"Microsoft.NETCore.App": {
"version": "1.0.0-rc2-*",
"type": "platform"
}
},
"frameworks": {
"netcoreapp1.0": { }
},
"tools": {
"dotnet-dependency-tool-invoker": {
"version": "1.0.0-*",
"imports": [
"dnxcore50",
"portable-net45+win8"
]
}
}
}

View file

@ -1,8 +1,7 @@
{
"compilationOptions": {
"outputName": "MyApp",
"emitEntryPoint": true,
"preserveCompilationContext": true
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.App": "1.0.0-rc2-*"

View file

@ -61,7 +61,7 @@ namespace Microsoft.DotNet.Cli.Build
Name = "dotnet-dependency-tool-invoker",
IsTool = true,
Path = "TestAssets/TestPackages/dotnet-dependency-tool-invoker",
IsApplicable = CurrentPlatform.IsWindows,
IsApplicable = true,
VersionSuffix = s_testPackageBuildVersionSuffix,
Clean = true,
Frameworks = new [] { "netcoreapp1.0" }
@ -107,6 +107,16 @@ namespace Microsoft.DotNet.Cli.Build
Frameworks = new [] { "netcoreapp1.0" }
},
new TestPackageProject()
{
Name = "ToolWithOutputName",
IsTool = true,
Path = "TestAssets/TestPackages/ToolWithOutputName",
IsApplicable = true,
VersionSuffix = string.Empty,
Clean = true,
Frameworks = new [] { "netcoreapp1.0" }
},
new TestPackageProject()
{
Name = "Microsoft.DotNet.Cli.Utils",
IsTool = true,

View file

@ -11,7 +11,7 @@ namespace Microsoft.DotNet.Cli.Utils
{
public class ProjectDependenciesCommandResolver : ICommandResolver
{
private static readonly CommandResolutionStrategy s_commandResolutionStrategy =
private static readonly CommandResolutionStrategy s_commandResolutionStrategy =
CommandResolutionStrategy.ProjectDependenciesPackage;
private readonly IEnvironmentProvider _environment;
@ -78,7 +78,7 @@ namespace Microsoft.DotNet.Cli.Utils
var depsFilePath =
projectContext.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeFiles.DepsJson;
var runtimeConfigPath =
var runtimeConfigPath =
projectContext.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeFiles.RuntimeConfigJson;
var toolLibrary = GetToolLibraryForContext(projectContext, commandName);
@ -97,12 +97,18 @@ namespace Microsoft.DotNet.Cli.Utils
private LockFileTargetLibrary GetToolLibraryForContext(
ProjectContext projectContext, string commandName)
{
var toolLibrary = projectContext.LockFile.Targets
var toolLibraries = projectContext.LockFile.Targets
.FirstOrDefault(t => t.TargetFramework.GetShortFolderName()
.Equals(projectContext.TargetFramework.GetShortFolderName()))
?.Libraries.FirstOrDefault(l => l.Name == commandName);
?.Libraries.Where(l => l.Name == commandName ||
l.RuntimeAssemblies.Any(r => Path.GetFileNameWithoutExtension(r.Path) == commandName)).ToList();
return toolLibrary;
if (toolLibraries?.Count() > 1)
{
throw new InvalidOperationException($"Ambiguous command name: {commandName}");
}
return toolLibraries?.FirstOrDefault();
}
private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework)
@ -120,8 +126,8 @@ namespace Microsoft.DotNet.Cli.Utils
}
return ProjectContext.Create(
projectRootPath,
framework,
projectRootPath,
framework,
PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers());
}

View file

@ -22,8 +22,8 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{
public class GivenAProjectDependenciesCommandFactory : TestBase
{
private static readonly NuGetFramework s_desktopTestFramework = FrameworkConstants.CommonFrameworks.Net451;
private static readonly NuGetFramework s_desktopTestFramework = FrameworkConstants.CommonFrameworks.Net451;
[WindowsOnlyFact]
public void It_resolves_desktop_apps_defaulting_to_Debug_Configuration()
{
@ -34,7 +34,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
.WithLockFiles();
var buildCommand = new BuildCommand(
Path.Combine(testInstance.TestRoot, "project.json"),
Path.Combine(testInstance.TestRoot, "project.json"),
configuration: configuration)
.ExecuteWithCapturedOutput()
.Should()
@ -65,7 +65,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
.WithLockFiles();
var buildCommand = new BuildCommand(
Path.Combine(testInstance.TestRoot, "project.json"),
Path.Combine(testInstance.TestRoot, "project.json"),
configuration: configuration)
.ExecuteWithCapturedOutput()
.Should()
@ -96,7 +96,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
.WithLockFiles();
var buildCommand = new BuildCommand(
Path.Combine(testInstance.TestRoot, "project.json"),
Path.Combine(testInstance.TestRoot, "project.json"),
configuration: configuration)
.ExecuteWithCapturedOutput()
.Should()
@ -127,7 +127,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
.WithLockFiles();
var buildCommand = new BuildCommand(
Path.Combine(testInstance.TestRoot, "project.json"),
Path.Combine(testInstance.TestRoot, "project.json"),
configuration: configuration)
.ExecuteWithCapturedOutput()
.Should()
@ -147,5 +147,36 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
command.CommandName.Should().Contain(Path.Combine(testInstance.TestRoot, "bin", configuration));
Path.GetFileName(command.CommandName).Should().Be("dotnet-desktop-and-portable.exe");
}
[Fact]
public void It_resolves_tools_whose_package_name_is_different_than_dll_name()
{
var configuration = "Debug";
var testAssetManager = new TestAssetsManager(Path.Combine(RepoRoot, "TestAssets", "TestProjects"));
var testInstance = testAssetManager.CreateTestInstance("AppWithDirectDependencyWithOutputName")
.WithLockFiles();
var buildCommand = new BuildCommand(
Path.Combine(testInstance.TestRoot, "project.json"),
configuration: configuration)
.ExecuteWithCapturedOutput()
.Should()
.Pass();
var context = ProjectContext.Create(testInstance.TestRoot, FrameworkConstants.CommonFrameworks.NetCoreApp10);
var factory = new ProjectDependenciesCommandFactory(
FrameworkConstants.CommonFrameworks.NetCoreApp10,
configuration,
null,
null,
testInstance.TestRoot);
var command = factory.Create("dotnet-tool-with-output-name", null);
command.CommandArgs.Should().Contain(
Path.Combine("ToolWithOutputName", "1.0.0", "lib", "netcoreapp1.0", "dotnet-tool-with-output-name.dll"));
}
}
}

View file

@ -44,6 +44,43 @@ namespace Microsoft.DotNet.Tests
result.Should().Pass();
}
[Fact]
public void CanInvokeToolWhosePackageNameIsDifferentFromDllName()
{
var appDirectory = Path.Combine(_testProjectsRoot, "AppWithDependencyOnToolWithOutputName");
new BuildCommand(Path.Combine(appDirectory, "project.json"))
.Execute()
.Should()
.Pass();
CommandResult result = new GenericCommand("tool-with-output-name") { WorkingDirectory = appDirectory }
.ExecuteWithCapturedOutput();
result.Should().HaveStdOutContaining("Tool with output name!");
result.Should().NotHaveStdErr();
result.Should().Pass();
}
[Fact]
public void CanInvokeToolFromDirectDependenciesIfPackageNameDifferentFromToolName()
{
var appDirectory = Path.Combine(_testProjectsRoot, "AppWithDirectDependencyWithOutputName");
const string framework = ".NETCoreApp,Version=v1.0";
new BuildCommand(Path.Combine(appDirectory, "project.json"))
.Execute()
.Should()
.Pass();
CommandResult result = new DependencyToolInvokerCommand { WorkingDirectory = appDirectory }
.ExecuteWithCapturedOutput("tool-with-output-name", framework, string.Empty);
result.Should().HaveStdOutContaining("Tool with output name!");
result.Should().NotHaveStdErr();
result.Should().Pass();
}
// need conditional theories so we can skip on non-Windows
[Theory]
[MemberData("DependencyToolArguments")]
@ -62,7 +99,7 @@ namespace Microsoft.DotNet.Tests
.Pass();
CommandResult result = new DependencyToolInvokerCommand { WorkingDirectory = appDirectory }
.ExecuteWithCapturedOutput(framework, args);
.ExecuteWithCapturedOutput("desktop-and-portable", framework, args);
result.Should().HaveStdOutContaining(framework);
result.Should().HaveStdOutContaining(args);
@ -163,6 +200,29 @@ namespace Microsoft.DotNet.Tests
}
}
class GenericCommand : TestCommand
{
private readonly string _commandName;
public GenericCommand(string commandName)
: base("dotnet")
{
_commandName = commandName;
}
public override CommandResult Execute(string args = "")
{
args = $"{_commandName} {args}";
return base.Execute(args);
}
public override CommandResult ExecuteWithCapturedOutput(string args = "")
{
args = $"{_commandName} {args}";
return base.ExecuteWithCapturedOutput(args);
}
}
class DependencyContextTestCommand : TestCommand
{
public DependencyContextTestCommand()
@ -190,15 +250,15 @@ namespace Microsoft.DotNet.Tests
{
}
public CommandResult Execute(string framework, string additionalArgs)
public CommandResult Execute(string commandName, string framework, string additionalArgs)
{
var args = $"dependency-tool-invoker desktop-and-portable --framework {framework} {additionalArgs}";
var args = $"dependency-tool-invoker {commandName} --framework {framework} {additionalArgs}";
return base.Execute(args);
}
public CommandResult ExecuteWithCapturedOutput(string framework, string additionalArgs)
public CommandResult ExecuteWithCapturedOutput(string commandName, string framework, string additionalArgs)
{
var args = $"dependency-tool-invoker desktop-and-portable --framework {framework} {additionalArgs}";
var args = $"dependency-tool-invoker {commandName} --framework {framework} {additionalArgs}";
return base.ExecuteWithCapturedOutput(args);
}
}

View file

@ -29,8 +29,10 @@
}
},
"content": [
"../../TestAssets/TestProjects/AppWithDependencyOnToolWithOutputName/**/*",
"../../TestAssets/TestProjects/AppWithDirectAndToolDependency/**/*",
"../../TestAssets/TestProjects/AppWithDirectDependency/**/*",
"../../TestAssets/TestProjects/AppWithDirectDependencyWithOutputName/**/*",
"../../TestAssets/TestProjects/AppWithToolDependency/**/*",
"../../TestAssets/TestProjects/DependencyContextFromTool/**/*",
"../../TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/**/*"