Moving the ProjectToolsCommandResolver to dotnet out of Cli.Utils because of the dependency on Microsoft.Build. Also added a EndToEnd test for tools ref using the MSBuildTestApp.

This commit is contained in:
Livar Cunha 2016-10-03 21:40:24 -07:00
parent 12e8e8eca7
commit 1570e0fde4
21 changed files with 186 additions and 29 deletions

View file

@ -21,5 +21,11 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<DotNetCliToolsReference Include="dotnet-portable">
<Version>1.0.0</Version>
</DotNetCliToolsReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -63,7 +63,28 @@ namespace Microsoft.DotNet.Cli.Utils
string outputPath = null,
string applicationName = null)
{
var commandSpec = CommandResolver.TryResolveCommandSpec(commandName,
return Create(
new DefaultCommandResolverPolicy(),
commandName,
args,
framework,
configuration,
outputPath,
applicationName);
}
public static Command Create(
ICommandResolverPolicy commandResolverPolicy,
string commandName,
IEnumerable<string> args,
NuGetFramework framework = null,
string configuration = Constants.DefaultConfiguration,
string outputPath = null,
string applicationName = null)
{
var commandSpec = CommandResolver.TryResolveCommandSpec(
commandResolverPolicy,
commandName,
args,
framework,
configuration: configuration,

View file

@ -2,8 +2,13 @@ using Microsoft.DotNet.PlatformAbstractions;
namespace Microsoft.DotNet.Cli.Utils
{
public class DefaultCommandResolverPolicy
public class DefaultCommandResolverPolicy : ICommandResolverPolicy
{
public CompositeCommandResolver CreateCommandResolver()
{
return Create();
}
public static CompositeCommandResolver Create()
{
var environment = new EnvironmentProvider();
@ -37,7 +42,6 @@ namespace Microsoft.DotNet.Cli.Utils
compositeCommandResolver.AddCommandResolver(new MuxerCommandResolver());
compositeCommandResolver.AddCommandResolver(new RootedCommandResolver());
compositeCommandResolver.AddCommandResolver(new ProjectToolsCommandResolver(packagedCommandSpecFactory));
compositeCommandResolver.AddCommandResolver(new AppBaseDllCommandResolver());
compositeCommandResolver.AddCommandResolver(
new AppBaseCommandResolver(environment, platformCommandSpecFactory));

View file

@ -0,0 +1,7 @@
namespace Microsoft.DotNet.Cli.Utils
{
public interface ICommandResolverPolicy
{
CompositeCommandResolver CreateCommandResolver();
}
}

View file

@ -5,7 +5,7 @@ using NuGet.Frameworks;
namespace Microsoft.DotNet.Cli.Utils
{
internal static class CommandResolver
internal class CommandResolver
{
public static CommandSpec TryResolveCommandSpec(
string commandName,
@ -14,6 +14,25 @@ namespace Microsoft.DotNet.Cli.Utils
string configuration = Constants.DefaultConfiguration,
string outputPath = null,
string applicationName = null)
{
return TryResolveCommandSpec(
new DefaultCommandResolverPolicy(),
commandName,
args,
framework,
configuration,
outputPath,
applicationName);
}
public static CommandSpec TryResolveCommandSpec(
ICommandResolverPolicy commandResolverPolicy,
string commandName,
IEnumerable<string> args,
NuGetFramework framework = null,
string configuration = Constants.DefaultConfiguration,
string outputPath = null,
string applicationName = null)
{
var commandResolverArgs = new CommandResolverArguments
{
@ -26,7 +45,7 @@ namespace Microsoft.DotNet.Cli.Utils
ApplicationName = applicationName
};
var defaultCommandResolver = DefaultCommandResolverPolicy.Create();
var defaultCommandResolver = commandResolverPolicy.CreateCommandResolver();
return defaultCommandResolver.Resolve(commandResolverArgs);
}

View file

@ -12,13 +12,13 @@ using NuGet.Packaging;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.Utils
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class DependencyContextBuilder
internal class DepsJsonBuilder
{
private readonly VersionFolderPathResolver _versionFolderPathResolver;
public DependencyContextBuilder()
public DepsJsonBuilder()
{
// This resolver is only used for building file names, so that base path is not required.
_versionFolderPathResolver = new VersionFolderPathResolver(path: null);

View file

@ -2,11 +2,13 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Build.Execution;
using System.Linq;
using Microsoft.Build.Evaluation;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.Utils
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class LockFilePathCalculator
{
@ -19,12 +21,21 @@ namespace Microsoft.DotNet.Cli.Utils
private string ResolveLockFilePathUsingCSProj(string projectDirectory)
{
string csProjPath = GetCSProjPath(projectDirectory);
if(csProjPath != null)
if(csProjPath == null)
{
ProjectInstance projectInstance = new ProjectInstance(csProjPath, null, null);
return null;
}
return null;
var globalProperties = new Dictionary<string, string>()
{
{ "MSBuildExtensionsPath", AppContext.BaseDirectory }
};
Project project = new Project(csProjPath, globalProperties, null);
// TODO: This is temporary. We should use ProjectLockFile property, but for some reason, it is coming up as project.lock.json
// instead of the path to project.assets.json.
var lockFilePath = project.AllEvaluatedProperties.FirstOrDefault(p => p.Name.Equals("BaseIntermediateOutputPath")).EvaluatedValue;
return Path.Combine(lockFilePath, "project.assets.json");
}
private string ReturnProjectLockJson(string projectDirectory)

View file

@ -7,7 +7,7 @@ using System.Linq;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.Utils
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal static class LockFileTargetExtensions
{

View file

@ -8,7 +8,7 @@ using System.Linq;
using NuGet.Packaging.Core;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.Utils
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal static class NuGetUtils
{

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Common;
@ -11,7 +12,7 @@ using NuGet.ProjectModel;
using NuGet.Versioning;
using FileFormatException = Microsoft.DotNet.ProjectModel.FileFormatException;
namespace Microsoft.DotNet.Cli.Utils
namespace Microsoft.DotNet.Cli.CommandResolution
{
public class ProjectToolsCommandResolver : ICommandResolver
{
@ -52,7 +53,8 @@ namespace Microsoft.DotNet.Cli.Utils
IEnumerable<string> args,
string projectDirectory)
{
var lockFile = new LockFileFormat().Read(Path.Combine(projectDirectory, LockFileFormat.LockFileName));
var lockFilePathCalculator = new LockFilePathCalculator();
var lockFile = new LockFileFormat().Read(lockFilePathCalculator.GetLockFilePath(projectDirectory));
var tools = lockFile.Tools.Where(t => t.Name.Contains(".NETCoreApp")).SelectMany(t => t.Libraries);
return ResolveCommandSpecFromAllToolLibraries(
@ -209,7 +211,7 @@ namespace Microsoft.DotNet.Cli.Utils
toolLibrary.Version.ToFullString(),
Enumerable.Empty<ResourceAssemblyInfo>());
var dependencyContext = new DependencyContextBuilder()
var dependencyContext = new DepsJsonBuilder()
.Build(singleProjectInfo, null, toolLockFile, s_toolPackageFramework, null);
var tempDepsFile = Path.GetTempFileName();

View file

@ -0,0 +1,18 @@
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Cli.CommandResolution
{
public class ProjectToolsCommandResolverPolicy : ICommandResolverPolicy
{
public CompositeCommandResolver CreateCommandResolver()
{
var defaultCommandResolverPolicy = new DefaultCommandResolverPolicy();
var compositeCommandResolver = defaultCommandResolverPolicy.CreateCommandResolver();
var packagedCommandSpecFactory = new PackagedCommandSpecFactory();
compositeCommandResolver.AddCommandResolver(new ProjectToolsCommandResolver(packagedCommandSpecFactory));
return compositeCommandResolver;
}
}
}

View file

@ -1,7 +1,7 @@
// 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.
namespace Microsoft.DotNet.Cli.Utils
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class ResourceAssemblyInfo
{

View file

@ -3,7 +3,7 @@
using System.Collections.Generic;
namespace Microsoft.DotNet.Cli.Utils
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class SingleProjectInfo
{

View file

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.DotNet.Cli.CommandResolution;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Configurer;
using Microsoft.DotNet.PlatformAbstractions;
@ -188,7 +189,12 @@ namespace Microsoft.DotNet.Cli
}
else
{
CommandResult result = Command.Create("dotnet-" + command, appArgs, FrameworkConstants.CommonFrameworks.NetStandardApp15)
var projectToolsCommandResolver = new ProjectToolsCommandResolverPolicy();
CommandResult result = Command.Create(
projectToolsCommandResolver,
"dotnet-" + command,
appArgs,
FrameworkConstants.CommonFrameworks.NetStandardApp15)
.Execute();
exitCode = result.ExitCode;
}

View file

@ -43,5 +43,27 @@ namespace Microsoft.DotNet.Tests.EndToEnd
.HaveStdOutContaining("Hello World!");
}
}
[Fact]
public void ItCanRunToolsInACSProj()
{
var testAppName = "MSBuildTestApp";
var testInstance = TestAssetsManager
.CreateTestInstance(testAppName);
var testProjectDirectory = testInstance.TestRoot;
new Restore3Command()
.WithWorkingDirectory(testProjectDirectory)
.Execute()
.Should()
.Pass();
new DotnetCommand()
.WithWorkingDirectory(testInstance.TestRoot)
.ExecuteWithCapturedOutput("portable")
.Should()
.Pass();
}
}
}

View file

@ -17,7 +17,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
var resolvers = defaultCommandResolver.OrderedCommandResolvers;
resolvers.Should().HaveCount(7);
resolvers.Should().HaveCount(6);
resolvers.Select(r => r.GetType())
.Should()
@ -25,7 +25,6 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
new []{
typeof(MuxerCommandResolver),
typeof(RootedCommandResolver),
typeof(ProjectToolsCommandResolver),
typeof(AppBaseDllCommandResolver),
typeof(AppBaseCommandResolver),
typeof(PathCommandResolver),

View file

@ -20,10 +20,10 @@
},
"System.Diagnostics.TraceSource": "4.0.0",
"System.Runtime.Serialization.Primitives": "4.1.1",
"NuGet.Versioning": "3.6.0-beta.1.msbuild.15",
"NuGet.Packaging": "3.6.0-beta.1.msbuild.15",
"NuGet.Frameworks": "3.6.0-beta.1.msbuild.15",
"NuGet.ProjectModel": "3.6.0-beta.1.msbuild.15",
"NuGet.Versioning": "3.6.0-beta.1.msbuild.17",
"NuGet.Packaging": "3.6.0-beta.1.msbuild.17",
"NuGet.Frameworks": "3.6.0-beta.1.msbuild.17",
"NuGet.ProjectModel": "3.6.0-beta.1.msbuild.17",
"Microsoft.DotNet.ProjectModel": {
"target": "project"
},

View file

@ -22,7 +22,7 @@
},
"xunit": "2.2.0-beta3-build3330",
"dotnet-test-xunit": "1.0.0-rc2-350904-49",
"NuGet.ProjectModel": "3.6.0-beta.1.msbuild.15"
"NuGet.ProjectModel": "3.6.0-beta.1.msbuild.17"
},
"frameworks": {
"netcoreapp1.0": {

View file

@ -4,6 +4,8 @@
using System.IO;
using System.Linq;
using FluentAssertions;
using Microsoft.DotNet.Cli.CommandResolution;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
@ -12,7 +14,7 @@ using NuGet.ProjectModel;
using NuGet.Versioning;
using Xunit;
namespace Microsoft.DotNet.Cli.Utils.Tests
namespace Microsoft.DotNet.Tests
{
public class GivenAProjectToolsCommandResolver : TestBase
{

View file

@ -0,0 +1,39 @@
// 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.Linq;
using FluentAssertions;
using Microsoft.DotNet.Cli.CommandResolution;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;
namespace Microsoft.DotNet.Tests
{
public class GivenAProjectToolsCommandResolverPolicy
{
[Fact]
public void It_contains_resolvers_in_the_right_order()
{
var projectToolsCommandResolverPolicy = new ProjectToolsCommandResolverPolicy();
var defaultCommandResolver = projectToolsCommandResolverPolicy.CreateCommandResolver();
var resolvers = defaultCommandResolver.OrderedCommandResolvers;
resolvers.Should().HaveCount(7);
resolvers.Select(r => r.GetType())
.Should()
.ContainInOrder(
new []{
typeof(MuxerCommandResolver),
typeof(RootedCommandResolver),
typeof(AppBaseDllCommandResolver),
typeof(AppBaseCommandResolver),
typeof(PathCommandResolver),
typeof(PublishedPathCommandResolver),
typeof(ProjectToolsCommandResolver)
});
}
}
}

View file

@ -26,6 +26,7 @@ namespace Microsoft.DotNet.Tests
.HaveFile("project.lock.json");
new DotnetCommand()
.WithWorkingDirectory(testInstance.TestRoot)
.ExecuteWithCapturedOutput("crash")
.Should()
.Fail()