Making ProjectDependenciesCommandResolver handle msbuild projects as well by using the ProjectFactory and IProject.

Moving the CommandResolution classes that depend on msbuild back into Cli.Utils.

Updating the src projects to a netstandard compatible with Cli.Utils moving to netstandard1.5
This commit is contained in:
Livar Cunha 2016-10-10 17:13:46 -07:00
parent a97d44eded
commit 318c9f3e44
49 changed files with 859 additions and 331 deletions

View file

@ -0,0 +1,27 @@
using System;
using System.IO;
using Microsoft.DotNet.Cli.Utils;
using NuGet.Frameworks;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
var environment = new EnvironmentProvider();
var packagedCommandSpecFactory = new PackagedCommandSpecFactory();
var projectDependenciesCommandFactory = new ProjectDependenciesCommandFactory(
FrameworkConstants.CommonFrameworks.NetCoreApp10,
"Debug",
null,
null,
Directory.GetCurrentDirectory());
var command = projectDependenciesCommandFactory.Create("dotnet-portable", null);
command.Execute();
}
}
}

View file

@ -0,0 +1,22 @@
{
"version": "1.0.0-rc-*",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.DotNet.Cli.Utils": {
"target": "project"
},
"NuGet.Frameworks": "3.6.0-rc-1954"
},
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
}
}
}
}

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp1.0</TargetFrameworks>
<OutputPath>bin\$(Configuration)</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="**\*.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.App">
<Version>1.0.1</Version>
</PackageReference>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>1.0.0-alpha-20161010-1</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="dotnet-portable">
<Version>1.0.0</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="dotnet-dependency-tool-invoker">
<Version>1.0.0-rc-*</Version>
</DotNetCliToolReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,12 @@
using System;
namespace MSBuildTestApp
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

View file

@ -142,6 +142,15 @@
<Clean>True</Clean> <Clean>True</Clean>
<Frameworks>netcoreapp1.0</Frameworks> <Frameworks>netcoreapp1.0</Frameworks>
</BaseTestPackageProject> </BaseTestPackageProject>
<BaseTestPackageProject Include="TestAssets/TestPackages/dotnet-invoke-portable">
<Name>dotnet-invoke-portable</Name>
<IsTool>True</IsTool>
<IsApplicable>True</IsApplicable>
<VersionPrefix>1.0.0-rc-</VersionPrefix>
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
<Clean>True</Clean>
<Frameworks>netcoreapp1.0</Frameworks>
</BaseTestPackageProject>
<BaseTestPackageProject Include="TestAssets/TestPackages/ToolWithOutputName"> <BaseTestPackageProject Include="TestAssets/TestPackages/ToolWithOutputName">
<Name>dotnet-tool-with-output-name</Name> <Name>dotnet-tool-with-output-name</Name>
<NuPkgName>ToolWithOutputName</NuPkgName> <NuPkgName>ToolWithOutputName</NuPkgName>
@ -159,7 +168,7 @@
<VersionPrefix>1.0.0-preview3-</VersionPrefix> <VersionPrefix>1.0.0-preview3-</VersionPrefix>
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix> <VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
<Clean>False</Clean> <Clean>False</Clean>
<Frameworks>netstandard1.3</Frameworks> <Frameworks>netstandard1.5</Frameworks>
</BaseTestPackageProject> </BaseTestPackageProject>
<BaseTestPackageProject Include="src/Microsoft.DotNet.ProjectModel"> <BaseTestPackageProject Include="src/Microsoft.DotNet.ProjectModel">
<Name>Microsoft.DotNet.ProjectModel</Name> <Name>Microsoft.DotNet.ProjectModel</Name>
@ -186,7 +195,7 @@
<VersionPrefix>1.0.0-preview3-</VersionPrefix> <VersionPrefix>1.0.0-preview3-</VersionPrefix>
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix> <VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
<Clean>False</Clean> <Clean>False</Clean>
<Frameworks>netstandard1.3</Frameworks> <Frameworks>netstandard1.5</Frameworks>
</BaseTestPackageProject> </BaseTestPackageProject>
<BaseTestPackageProject Include="src/Microsoft.DotNet.InternalAbstractions"> <BaseTestPackageProject Include="src/Microsoft.DotNet.InternalAbstractions">
<Name>Microsoft.DotNet.InternalAbstractions</Name> <Name>Microsoft.DotNet.InternalAbstractions</Name>
@ -213,7 +222,7 @@
<VersionPrefix>1.0.0-preview3-</VersionPrefix> <VersionPrefix>1.0.0-preview3-</VersionPrefix>
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix> <VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
<Clean>False</Clean> <Clean>False</Clean>
<Frameworks>netstandard1.3</Frameworks> <Frameworks>netstandard1.5</Frameworks>
</BaseTestPackageProject> </BaseTestPackageProject>
<BaseTestPackageProject Include="src/Microsoft.DotNet.Files"> <BaseTestPackageProject Include="src/Microsoft.DotNet.Files">
<Name>Microsoft.DotNet.Files</Name> <Name>Microsoft.DotNet.Files</Name>
@ -222,7 +231,7 @@
<VersionPrefix>1.0.0-preview3-</VersionPrefix> <VersionPrefix>1.0.0-preview3-</VersionPrefix>
<VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix> <VersionSuffix>$(TestPackageBuildVersionSuffix)</VersionSuffix>
<Clean>False</Clean> <Clean>False</Clean>
<Frameworks>netstandard1.3</Frameworks> <Frameworks>netstandard1.5</Frameworks>
</BaseTestPackageProject> </BaseTestPackageProject>
<TestPackageProjectFrameworksExcludes Condition=" '$(IsDesktopAvailable)' != 'True' " Include="net45" /> <TestPackageProjectFrameworksExcludes Condition=" '$(IsDesktopAvailable)' != 'True' " Include="net45" />

View file

@ -29,6 +29,11 @@ namespace Microsoft.DotNet.Cli.Utils
UseShellExecute = false UseShellExecute = false
}; };
foreach(var environmentVariable in commandSpec.EnvironmentVariables)
{
psi.Environment.Add(environmentVariable);
}
_process = new Process _process = new Process
{ {
StartInfo = psi StartInfo = psi

View file

@ -42,13 +42,15 @@ namespace Microsoft.DotNet.Cli.Utils
compositeCommandResolver.AddCommandResolver(new MuxerCommandResolver()); compositeCommandResolver.AddCommandResolver(new MuxerCommandResolver());
compositeCommandResolver.AddCommandResolver(new RootedCommandResolver()); compositeCommandResolver.AddCommandResolver(new RootedCommandResolver());
compositeCommandResolver.AddCommandResolver(
new ProjectToolsCommandResolver(packagedCommandSpecFactory, environment));
compositeCommandResolver.AddCommandResolver(new AppBaseDllCommandResolver()); compositeCommandResolver.AddCommandResolver(new AppBaseDllCommandResolver());
compositeCommandResolver.AddCommandResolver( compositeCommandResolver.AddCommandResolver(
new AppBaseCommandResolver(environment, platformCommandSpecFactory)); new AppBaseCommandResolver(environment, platformCommandSpecFactory));
compositeCommandResolver.AddCommandResolver( compositeCommandResolver.AddCommandResolver(
new PathCommandResolver(environment, platformCommandSpecFactory)); new PathCommandResolver(environment, platformCommandSpecFactory));
compositeCommandResolver.AddCommandResolver( compositeCommandResolver.AddCommandResolver(
new PublishedPathCommandResolver(environment, publishedPathCommandSpecFactory)); new PublishedPathCommandResolver(environment, publishedPathCommandSpecFactory));
return compositeCommandResolver; return compositeCommandResolver;
} }

View file

@ -12,7 +12,7 @@ using NuGet.Packaging;
using NuGet.Packaging.Core; using NuGet.Packaging.Core;
using NuGet.ProjectModel; using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution namespace Microsoft.DotNet.Cli.Utils
{ {
internal class DepsJsonBuilder internal class DepsJsonBuilder
{ {

View file

@ -4,12 +4,18 @@
using System.Collections.Generic; using System.Collections.Generic;
using NuGet.ProjectModel; using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution namespace Microsoft.DotNet.Cli.Utils
{ {
internal interface IProject internal interface IProject
{ {
LockFile GetLockFile(); LockFile GetLockFile();
IEnumerable<SingleProjectInfo> GetTools(); IEnumerable<SingleProjectInfo> GetTools();
string DepsJsonPath { get; }
string RuntimeConfigJsonPath { get; }
Dictionary<string, string> EnvironmentVariables { get; }
} }
} }

View file

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

View file

@ -0,0 +1,125 @@
// 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.IO;
using System.Linq;
using Microsoft.Build.Evaluation;
using NuGet.Frameworks;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.Utils
{
internal class MSBuildProject : IProject
{
private Project _project;
private string _msBuildExePath;
public string DepsJsonPath
{
get
{
return _project
.AllEvaluatedProperties
.FirstOrDefault(p => p.Name.Equals("_ProjectDepsFilePath"))
.EvaluatedValue;
}
}
public string RuntimeConfigJsonPath
{
get
{
return _project
.AllEvaluatedProperties
.FirstOrDefault(p => p.Name.Equals("_ProjectRuntimeConfigFilePath"))
.EvaluatedValue;
}
}
public Dictionary<string, string> EnvironmentVariables
{
get
{
return new Dictionary<string, string>
{
{ Constants.MSBUILD_EXE_PATH, _msBuildExePath }
};
}
}
public MSBuildProject(
string msBuildProjectPath,
NuGetFramework framework,
string configuration,
string outputPath,
string msBuildExePath)
{
var globalProperties = new Dictionary<string, string>()
{
{ "MSBuildExtensionsPath", Path.GetDirectoryName(msBuildExePath) }
};
if(framework != null)
{
globalProperties.Add("TargetFramework", framework.GetShortFolderName());
}
if(outputPath != null)
{
globalProperties.Add("OutputPath", outputPath);
}
if(configuration != null)
{
globalProperties.Add("Configuration", configuration);
}
_project = ProjectCollection.GlobalProjectCollection.LoadedProjects.FirstOrDefault(p =>
p.FullPath == msBuildProjectPath);
_project = _project ?? new Project(msBuildProjectPath, globalProperties, null);
_msBuildExePath = msBuildExePath;
}
public IEnumerable<SingleProjectInfo> GetTools()
{
var toolsReferences = _project.AllEvaluatedItems.Where(i => i.ItemType.Equals("DotNetCliToolReference"));
var tools = toolsReferences.Select(t => new SingleProjectInfo(
t.EvaluatedInclude,
t.GetMetadataValue("Version"),
Enumerable.Empty<ResourceAssemblyInfo>()));
return tools;
}
public LockFile GetLockFile()
{
var lockFilePath = GetLockFilePathFromProjectLockFileProperty() ??
GetLockFilePathFromIntermediateBaseOutputPath();
return new LockFileFormat().Read(lockFilePath);
}
private string GetLockFilePathFromProjectLockFileProperty()
{
return _project
.AllEvaluatedProperties
.Where(p => p.Name.Equals("ProjectLockFile"))
.Select(p => p.EvaluatedValue)
.FirstOrDefault(p => File.Exists(p));
}
private string GetLockFilePathFromIntermediateBaseOutputPath()
{
var intermediateOutputPath = _project
.AllEvaluatedProperties
.FirstOrDefault(p => p.Name.Equals("BaseIntermediateOutputPath"))
.EvaluatedValue;
return Path.Combine(intermediateOutputPath, "project.assets.json");
}
}
}

View file

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

View file

@ -1,7 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions; using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.Common;
@ -67,37 +68,41 @@ namespace Microsoft.DotNet.Cli.Utils
{ {
var allowedExtensions = GetAllowedCommandExtensionsFromEnvironment(_environment); var allowedExtensions = GetAllowedCommandExtensionsFromEnvironment(_environment);
var projectContext = GetProjectContextFromDirectory( var projectFactory = new ProjectFactory(_environment);
var project = projectFactory.GetProject(
projectDirectory, projectDirectory,
framework); framework,
configuration,
buildBasePath,
outputPath);
if (projectContext == null) if (project == null)
{ {
return null; return null;
} }
var depsFilePath = var depsFilePath = project.DepsJsonPath;
projectContext.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeFiles.DepsJson;
if (! File.Exists(depsFilePath)) if (!File.Exists(depsFilePath))
{ {
Reporter.Verbose.WriteLine($"projectdependenciescommandresolver: {depsFilePath} does not exist"); Reporter.Verbose.WriteLine($"projectdependenciescommandresolver: {depsFilePath} does not exist");
return null; return null;
} }
var runtimeConfigPath = var runtimeConfigPath = project.RuntimeConfigJsonPath;
projectContext.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeFiles.RuntimeConfigJson;
if (! File.Exists(runtimeConfigPath)) if (!File.Exists(runtimeConfigPath))
{ {
Reporter.Verbose.WriteLine($"projectdependenciescommandresolver: {runtimeConfigPath} does not exist"); Reporter.Verbose.WriteLine($"projectdependenciescommandresolver: {runtimeConfigPath} does not exist");
return null; return null;
} }
var toolLibrary = GetToolLibraryForContext(projectContext, commandName); var lockFile = project.GetLockFile();
var normalizedNugetPackagesRoot = PathUtility.EnsureNoTrailingDirectorySeparator(projectContext.PackagesDirectory); var toolLibrary = GetToolLibraryForContext(lockFile, commandName, framework);
var normalizedNugetPackagesRoot =
PathUtility.EnsureNoTrailingDirectorySeparator(lockFile.PackageFolders.First().Path);
return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( var commandSpec = _packagedCommandSpecFactory.CreateCommandSpecFromLibrary(
toolLibrary, toolLibrary,
commandName, commandName,
commandArguments, commandArguments,
@ -106,14 +111,18 @@ namespace Microsoft.DotNet.Cli.Utils
s_commandResolutionStrategy, s_commandResolutionStrategy,
depsFilePath, depsFilePath,
runtimeConfigPath); runtimeConfigPath);
commandSpec?.AddEnvironmentVariablesFromProject(project);
return commandSpec;
} }
private LockFileTargetLibrary GetToolLibraryForContext( private LockFileTargetLibrary GetToolLibraryForContext(
ProjectContext projectContext, string commandName) LockFile lockFile, string commandName, NuGetFramework targetFramework)
{ {
var toolLibraries = projectContext.LockFile.Targets var toolLibraries = lockFile.Targets
.FirstOrDefault(t => t.TargetFramework.GetShortFolderName() .FirstOrDefault(t => t.TargetFramework.GetShortFolderName()
.Equals(projectContext.TargetFramework.GetShortFolderName())) .Equals(targetFramework.GetShortFolderName()))
?.Libraries.Where(l => l.Name == commandName || ?.Libraries.Where(l => l.Name == commandName ||
l.RuntimeAssemblies.Any(r => Path.GetFileNameWithoutExtension(r.Path) == commandName)).ToList(); l.RuntimeAssemblies.Any(r => Path.GetFileNameWithoutExtension(r.Path) == commandName)).ToList();
@ -125,26 +134,6 @@ namespace Microsoft.DotNet.Cli.Utils
return toolLibraries?.FirstOrDefault(); return toolLibraries?.FirstOrDefault();
} }
private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework)
{
if (directory == null || framework == null)
{
return null;
}
var projectRootPath = directory;
if (!File.Exists(Path.Combine(projectRootPath, Project.FileName)))
{
return null;
}
return ProjectContext.Create(
projectRootPath,
framework,
RuntimeEnvironmentRidExtensions.GetAllCandidateRuntimeIdentifiers());
}
private IEnumerable<string> GetAllowedCommandExtensionsFromEnvironment(IEnvironmentProvider environment) private IEnumerable<string> GetAllowedCommandExtensionsFromEnvironment(IEnvironmentProvider environment)
{ {
var allowedCommandExtensions = new List<string>(); var allowedCommandExtensions = new List<string>();

View file

@ -0,0 +1,92 @@
// 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.IO;
using System.Linq;
using Microsoft.Build.Exceptions;
using Microsoft.DotNet.ProjectModel;
using NuGet.Frameworks;
namespace Microsoft.DotNet.Cli.Utils
{
internal class ProjectFactory
{
private IEnvironmentProvider _environment;
public ProjectFactory(IEnvironmentProvider environment)
{
_environment = environment;
}
public IProject GetProject(
string projectDirectory,
NuGetFramework framework,
string configuration,
string buildBasePath,
string outputPath)
{
return GetMSBuildProj(projectDirectory, framework, configuration, outputPath) ??
GetProjectJsonProject(projectDirectory, framework, configuration, buildBasePath, outputPath);
}
private IProject GetMSBuildProj(string projectDirectory, NuGetFramework framework, string configuration, string outputPath)
{
var msBuildExePath = _environment.GetEnvironmentVariable(Constants.MSBUILD_EXE_PATH);
msBuildExePath = string.IsNullOrEmpty(msBuildExePath) ?
Path.Combine(AppContext.BaseDirectory, "msbuild.exe") :
msBuildExePath;
string msBuildProjectPath = GetMSBuildProjPath(projectDirectory);
if(msBuildProjectPath == null)
{
return null;
}
try
{
return new MSBuildProject(msBuildProjectPath, framework, configuration, outputPath, msBuildExePath);
}
catch (InvalidProjectFileException ex)
{
Reporter.Verbose.WriteLine(ex.ToString().Red());
return null;
}
}
private IProject GetProjectJsonProject(
string projectDirectory,
NuGetFramework framework,
string configuration,
string buildBasePath,
string outputPath)
{
if (!File.Exists(Path.Combine(projectDirectory, Project.FileName)))
{
return null;
}
return new ProjectJsonProject(projectDirectory, framework, configuration, buildBasePath, outputPath);
}
private string GetMSBuildProjPath(string projectDirectory)
{
IEnumerable<string> projectFiles = Directory
.GetFiles(projectDirectory, "*.*proj")
.Where(d => !d.EndsWith(".xproj"));
if (projectFiles.Count() == 0)
{
return null;
}
else if (projectFiles.Count() > 1)
{
throw new InvalidOperationException(
$"Specify which project file to use because this '{projectDirectory}' contains more than one project file.");
}
return projectFiles.First();
}
}
}

View file

@ -0,0 +1,110 @@
// 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.IO;
using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel;
using NuGet.Frameworks;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.Utils
{
internal class ProjectJsonProject : IProject
{
private LockFile _lockFile;
private ProjectContext _projectContext;
private string _projectDirectory;
private string _configuration;
private string _outputPath;
private string _buildBasePath;
private NuGetFramework _framework;
private ProjectContext ProjectContext
{
get
{
if(_projectContext == null)
{
_projectContext = ProjectContext.Create(
_projectDirectory,
_framework,
DotnetRuntimeIdentifiers.InferCurrentRuntimeIdentifiers(DotnetFiles.VersionFileObject));
}
return _projectContext;
}
}
public string DepsJsonPath
{
get
{
return ProjectContext.GetOutputPaths(
_configuration,
_buildBasePath,
_outputPath).RuntimeFiles.DepsJson;
}
}
public string RuntimeConfigJsonPath
{
get
{
return ProjectContext.GetOutputPaths(
_configuration,
_buildBasePath,
_outputPath).RuntimeFiles.RuntimeConfigJson;
}
}
public Dictionary<string, string> EnvironmentVariables
{
get
{
return new Dictionary<string, string>();
}
}
public ProjectJsonProject(
string projectDirectory,
NuGetFramework framework,
string configuration,
string buildBasePath,
string outputPath)
{
var lockFilePath = Path.Combine(projectDirectory, LockFileFormat.LockFileName);
_lockFile = new LockFileFormat().Read(lockFilePath);
_projectDirectory = projectDirectory;
_framework = framework;
_configuration = configuration;
_buildBasePath = buildBasePath;
_outputPath = outputPath;
}
public LockFile GetLockFile()
{
return _lockFile;
}
public IEnumerable<SingleProjectInfo> GetTools()
{
var tools = _lockFile.Tools.Where(t => t.Name.Contains(".NETCoreApp")).SelectMany(t => t.Libraries);
return tools.Select(t => new SingleProjectInfo(
t.Name,
t.Version.ToFullString(),
Enumerable.Empty<ResourceAssemblyInfo>()));
}
}
}

View file

@ -5,8 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.Common;
using Microsoft.Extensions.DependencyModel; using Microsoft.Extensions.DependencyModel;
@ -15,7 +13,7 @@ using NuGet.ProjectModel;
using NuGet.Versioning; using NuGet.Versioning;
using FileFormatException = Microsoft.DotNet.ProjectModel.FileFormatException; using FileFormatException = Microsoft.DotNet.ProjectModel.FileFormatException;
namespace Microsoft.DotNet.Cli.CommandResolution namespace Microsoft.DotNet.Cli.Utils
{ {
public class ProjectToolsCommandResolver : ICommandResolver public class ProjectToolsCommandResolver : ICommandResolver
{ {
@ -27,9 +25,14 @@ namespace Microsoft.DotNet.Cli.CommandResolution
private List<string> _allowedCommandExtensions; private List<string> _allowedCommandExtensions;
private IPackagedCommandSpecFactory _packagedCommandSpecFactory; private IPackagedCommandSpecFactory _packagedCommandSpecFactory;
public ProjectToolsCommandResolver(IPackagedCommandSpecFactory packagedCommandSpecFactory) private IEnvironmentProvider _environment;
public ProjectToolsCommandResolver(
IPackagedCommandSpecFactory packagedCommandSpecFactory,
IEnvironmentProvider environment)
{ {
_packagedCommandSpecFactory = packagedCommandSpecFactory; _packagedCommandSpecFactory = packagedCommandSpecFactory;
_environment = environment;
_allowedCommandExtensions = new List<string>() _allowedCommandExtensions = new List<string>()
{ {
@ -45,37 +48,43 @@ namespace Microsoft.DotNet.Cli.CommandResolution
return null; return null;
} }
return ResolveFromProjectTools( return ResolveFromProjectTools(commandResolverArguments);
commandResolverArguments.CommandName,
commandResolverArguments.CommandArguments.OrEmptyIfNull(),
commandResolverArguments.ProjectDirectory);
} }
private CommandSpec ResolveFromProjectTools( private CommandSpec ResolveFromProjectTools(CommandResolverArguments commandResolverArguments)
string commandName,
IEnumerable<string> args,
string projectDirectory)
{ {
var projectFactory = new ProjectFactory(); var projectFactory = new ProjectFactory(_environment);
var project = projectFactory.GetProject(projectDirectory); var project = projectFactory.GetProject(
commandResolverArguments.ProjectDirectory,
commandResolverArguments.Framework,
commandResolverArguments.Configuration,
commandResolverArguments.BuildBasePath,
commandResolverArguments.OutputPath);
var tools = project.GetTools(); var tools = project.GetTools();
return ResolveCommandSpecFromAllToolLibraries( return ResolveCommandSpecFromAllToolLibraries(
tools, tools,
commandName, commandResolverArguments.CommandName,
args, commandResolverArguments.CommandArguments.OrEmptyIfNull(),
project.GetLockFile()); project.GetLockFile(),
project);
} }
private CommandSpec ResolveCommandSpecFromAllToolLibraries( private CommandSpec ResolveCommandSpecFromAllToolLibraries(
IEnumerable<SingleProjectInfo> toolsLibraries, IEnumerable<SingleProjectInfo> toolsLibraries,
string commandName, string commandName,
IEnumerable<string> args, IEnumerable<string> args,
LockFile lockFile) LockFile lockFile,
IProject project)
{ {
foreach (var toolLibrary in toolsLibraries) foreach (var toolLibrary in toolsLibraries)
{ {
var commandSpec = ResolveCommandSpecFromToolLibrary(toolLibrary, commandName, args, lockFile); var commandSpec = ResolveCommandSpecFromToolLibrary(
toolLibrary,
commandName,
args,
lockFile,
project);
if (commandSpec != null) if (commandSpec != null)
{ {
@ -90,7 +99,8 @@ namespace Microsoft.DotNet.Cli.CommandResolution
SingleProjectInfo toolLibraryRange, SingleProjectInfo toolLibraryRange,
string commandName, string commandName,
IEnumerable<string> args, IEnumerable<string> args,
LockFile lockFile) LockFile lockFile,
IProject project)
{ {
var nugetPackagesRoot = lockFile.PackageFolders.First().Path; var nugetPackagesRoot = lockFile.PackageFolders.First().Path;
@ -111,7 +121,7 @@ namespace Microsoft.DotNet.Cli.CommandResolution
var normalizedNugetPackagesRoot = PathUtility.EnsureNoTrailingDirectorySeparator(nugetPackagesRoot); var normalizedNugetPackagesRoot = PathUtility.EnsureNoTrailingDirectorySeparator(nugetPackagesRoot);
return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( var commandSpec = _packagedCommandSpecFactory.CreateCommandSpecFromLibrary(
toolLibrary, toolLibrary,
commandName, commandName,
args, args,
@ -120,6 +130,10 @@ namespace Microsoft.DotNet.Cli.CommandResolution
s_commandResolutionStrategy, s_commandResolutionStrategy,
depsFilePath, depsFilePath,
null); null);
commandSpec?.AddEnvironmentVariablesFromProject(project);
return commandSpec;
} }
private LockFile GetToolLockFile( private LockFile GetToolLockFile(
@ -155,7 +169,7 @@ namespace Microsoft.DotNet.Cli.CommandResolution
return toolPathCalculator.GetBestLockFilePath( return toolPathCalculator.GetBestLockFilePath(
toolLibrary.Name, toolLibrary.Name,
new VersionRange(new NuGetVersion(toolLibrary.Version)), VersionRange.Parse(toolLibrary.Version),
s_toolPackageFramework); s_toolPackageFramework);
} }
@ -184,7 +198,6 @@ namespace Microsoft.DotNet.Cli.CommandResolution
} }
} }
// Need to unit test this, so public
internal void GenerateDepsJsonFile( internal void GenerateDepsJsonFile(
LockFile toolLockFile, LockFile toolLockFile,
string depsPath, string depsPath,

View file

@ -1,7 +1,7 @@
// 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. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.DotNet.Cli.CommandResolution namespace Microsoft.DotNet.Cli.Utils
{ {
internal class ResourceAssemblyInfo internal class ResourceAssemblyInfo
{ {

View file

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

View file

@ -1,18 +1,35 @@
using System.Collections.Generic;
namespace Microsoft.DotNet.Cli.Utils namespace Microsoft.DotNet.Cli.Utils
{ {
public class CommandSpec public class CommandSpec
{ {
public CommandSpec(string path, string args, CommandResolutionStrategy resolutionStrategy) public CommandSpec(
string path,
string args,
CommandResolutionStrategy resolutionStrategy,
Dictionary<string, string> environmentVariables = null)
{ {
Path = path; Path = path;
Args = args; Args = args;
ResolutionStrategy = resolutionStrategy; ResolutionStrategy = resolutionStrategy;
EnvironmentVariables = environmentVariables ?? new Dictionary<string, string>();
} }
public string Path { get; } public string Path { get; }
public string Args { get; } public string Args { get; }
public Dictionary<string, string> EnvironmentVariables { get; }
public CommandResolutionStrategy ResolutionStrategy { get; } public CommandResolutionStrategy ResolutionStrategy { get; }
internal void AddEnvironmentVariablesFromProject(IProject project)
{
foreach (var environmentVariable in project.EnvironmentVariables)
{
EnvironmentVariables.Add(environmentVariable.Key, environmentVariable.Value);
}
}
} }
} }

View file

@ -47,5 +47,6 @@ namespace Microsoft.DotNet.Cli.Utils
"libcoreclr.dylib" "libcoreclr.dylib"
}; };
public static readonly string MSBUILD_EXE_PATH = "MSBUILD_EXE_PATH";
} }
} }

View file

@ -93,6 +93,11 @@ namespace Microsoft.DotNet.Cli.Utils
return GetCommandPathFromRootPath(rootPath, commandName, extensionsArr); return GetCommandPathFromRootPath(rootPath, commandName, extensionsArr);
} }
public string GetEnvironmentVariable(string name)
{
return Environment.GetEnvironmentVariable(name);
}
public bool GetEnvironmentVariableAsBool(string name, bool defaultValue) public bool GetEnvironmentVariableAsBool(string name, bool defaultValue)
{ {
var str = Environment.GetEnvironmentVariable(name); var str = Environment.GetEnvironmentVariable(name);

View file

@ -13,5 +13,7 @@ namespace Microsoft.DotNet.Cli.Utils
string GetCommandPathFromRootPath(string rootPath, string commandName, IEnumerable<string> extensions); string GetCommandPathFromRootPath(string rootPath, string commandName, IEnumerable<string> extensions);
bool GetEnvironmentVariableAsBool(string name, bool defaultValue); bool GetEnvironmentVariableAsBool(string name, bool defaultValue);
string GetEnvironmentVariable(string name);
} }
} }

View file

@ -2,20 +2,30 @@
"version": "1.0.0-preview3-*", "version": "1.0.0-preview3-*",
"buildOptions": { "buildOptions": {
"keyFile": "../../tools/Key.snk", "keyFile": "../../tools/Key.snk",
"warningsAsErrors": true "warningsAsErrors": true,
"compile": {
"include": [
"**/*.cs",
"../../src/dotnet/DotnetFiles.cs"
]
}
}, },
"dependencies": { "dependencies": {
"Microsoft.DotNet.ProjectModel": { "Microsoft.DotNet.ProjectModel": {
"target": "project" "target": "project"
}, },
"Microsoft.DotNet.PlatformAbstractions": "1.0.1-beta-000933", "Microsoft.DotNet.PlatformAbstractions": "1.0.1-beta-000933",
"NuGet.Versioning": "3.6.0-rc-1984", "NuGet.Versioning": "3.6.0-rc-1984",
"NuGet.Packaging": "3.6.0-rc-1984", "NuGet.Packaging": "3.6.0-rc-1984",
"NuGet.Frameworks": "3.6.0-rc-1984", "NuGet.Frameworks": "3.6.0-rc-1984",
"NuGet.ProjectModel": "3.6.0-rc-1984" "NuGet.ProjectModel": "3.6.0-rc-1984",
"Microsoft.Build": "15.1.316-preview5",
"Microsoft.Build.Utilities.Core": "15.1.316-preview5"
}, },
"frameworks": { "frameworks": {
"netstandard1.3": { "netstandard1.5": {
"imports": [ "imports": [
"portable-net45+wp80+win8+wpa81+dnxcore50" "portable-net45+wp80+win8+wpa81+dnxcore50"
], ],

View file

@ -17,7 +17,7 @@
"NuGet.ProjectModel": "3.6.0-rc-1984" "NuGet.ProjectModel": "3.6.0-rc-1984"
}, },
"frameworks": { "frameworks": {
"netstandard1.3": { "netstandard1.5": {
"imports": [ "imports": [
"portable-net45+wp80+win8+wpa81+dnxcore50" "portable-net45+wp80+win8+wpa81+dnxcore50"
] ]

View file

@ -19,7 +19,7 @@
} }
}, },
"frameworks": { "frameworks": {
"netstandard1.6": { "netstandard1.5": {
"imports": [ "imports": [
"portable-net45+wp80+win8+wpa81+dnxcore50" "portable-net45+wp80+win8+wpa81+dnxcore50"
] ]

View file

@ -14,7 +14,7 @@
"System.Linq.Expressions": "4.1.0" "System.Linq.Expressions": "4.1.0"
}, },
"frameworks": { "frameworks": {
"netstandard1.3": { "netstandard1.5": {
"imports": [ "imports": [
"portable-net45+wp80+win8+wpa81+dnxcore50" "portable-net45+wp80+win8+wpa81+dnxcore50"
] ]

View file

@ -14,7 +14,7 @@
"Microsoft.DotNet.ProjectModel": { "Microsoft.DotNet.ProjectModel": {
"target": "project" "target": "project"
}, },
"Microsoft.Build": "0.1.0-preview-00034-160909" "Microsoft.Build": "15.1.316-preview5"
}, },
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {

View file

@ -14,7 +14,7 @@
"Microsoft.DotNet.PlatformAbstractions": "1.0.1-beta-000933" "Microsoft.DotNet.PlatformAbstractions": "1.0.1-beta-000933"
}, },
"frameworks": { "frameworks": {
"netstandard1.3": { "netstandard1.5": {
"imports": [ "imports": [
"portable-net45+wp80+win8+wpa81+dnxcore50", "portable-net45+wp80+win8+wpa81+dnxcore50",
"portable-net45+win8" "portable-net45+win8"

View file

@ -120,4 +120,4 @@ namespace Microsoft.DotNet.ProjectModel.Utilities
return sb.ToString(); return sb.ToString();
} }
} }
} }

View file

@ -10,7 +10,7 @@
} }
}, },
"frameworks": { "frameworks": {
"netstandard1.3": { "netstandard1.5": {
"imports": [ "imports": [
"portable-net45+wp80+win8+wpa81+dnxcore50" "portable-net45+wp80+win8+wpa81+dnxcore50"
] ]

View file

@ -1,48 +0,0 @@
// 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.IO;
using System.Linq;
using Microsoft.Build.Evaluation;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class MSBuildProject : IProject
{
private Project _project;
public MSBuildProject(string msBuildProjectPath)
{
var globalProperties = new Dictionary<string, string>()
{
{ "MSBuildExtensionsPath", AppContext.BaseDirectory }
};
_project = new Project(msBuildProjectPath, globalProperties, null);
}
public LockFile GetLockFile()
{
var intermediateOutputPath = _project
.AllEvaluatedProperties
.FirstOrDefault(p => p.Name.Equals("BaseIntermediateOutputPath"))
.EvaluatedValue;
var lockFilePath = Path.Combine(intermediateOutputPath, "project.assets.json");
return new LockFileFormat().Read(lockFilePath);
}
public IEnumerable<SingleProjectInfo> GetTools()
{
var toolsReferences = _project.AllEvaluatedItems.Where(i => i.ItemType.Equals("DotNetCliToolReference"));
var tools = toolsReferences.Select(t => new SingleProjectInfo(
t.EvaluatedInclude,
t.GetMetadataValue("Version"),
Enumerable.Empty<ResourceAssemblyInfo>()));
return tools;
}
}
}

View file

@ -1,50 +0,0 @@
// 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.IO;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class ProjectFactory
{
public IProject GetProject(string projectDirectory)
{
return GetMSBuildProj(projectDirectory) ??
GetProjectJsonProject(projectDirectory);
}
private IProject GetMSBuildProj(string projectDirectory)
{
string msBuildProjectPath = GetMSBuildProjPath(projectDirectory);
if(msBuildProjectPath == null)
{
return null;
}
return new MSBuildProject(msBuildProjectPath);
}
private IProject GetProjectJsonProject(string projectDirectory)
{
return new ProjectJsonProject(projectDirectory);
}
private string GetMSBuildProjPath(string projectDirectory)
{
string[] projectFiles = Directory.GetFiles(projectDirectory, "*.*proj");
if (projectFiles.Length == 0)
{
return null;
}
else if (projectFiles.Length > 1)
{
throw new InvalidOperationException(
$"Specify which project file to use because this '{projectDirectory}' contains more than one project file.");
}
return projectFiles[0];
}
}
}

View file

@ -1,37 +0,0 @@
// 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.IO;
using System.Linq;
using NuGet.ProjectModel;
namespace Microsoft.DotNet.Cli.CommandResolution
{
internal class ProjectJsonProject : IProject
{
private LockFile _lockFile;
public ProjectJsonProject(string projectDirectory)
{
var lockFilePath = Path.Combine(projectDirectory, LockFileFormat.LockFileName);
_lockFile = new LockFileFormat().Read(lockFilePath);
}
public LockFile GetLockFile()
{
return _lockFile;
}
public IEnumerable<SingleProjectInfo> GetTools()
{
var tools = _lockFile.Tools.Where(t => t.Name.Contains(".NETCoreApp")).SelectMany(t => t.Libraries);
return tools.Select(t => new SingleProjectInfo(
t.Name,
t.Version.ToFullString(),
Enumerable.Empty<ResourceAssemblyInfo>()));
}
}
}

View file

@ -1,21 +0,0 @@
// 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 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

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

View file

@ -83,5 +83,36 @@ namespace Microsoft.DotNet.Tests.EndToEnd
.And .And
.HaveStdOutContaining("Hello Portable World!");; .HaveStdOutContaining("Hello Portable World!");;
} }
[Fact]
public void ItCanRunAToolThatInvokesADependencyToolInACSProj()
{
var repoDirectoriesProvider = new RepoDirectoriesProvider();
var testAppName = "MSBuildTestAppWithToolInDependencies";
var testInstance = TestAssetsManager
.CreateTestInstance(testAppName);
var testProjectDirectory = testInstance.TestRoot;
new Restore3Command()
.WithWorkingDirectory(testProjectDirectory)
.Execute($"-s {repoDirectoriesProvider.TestPackages}")
.Should()
.Pass();
new Build3Command()
.WithWorkingDirectory(testProjectDirectory)
.Execute()
.Should()
.Pass();
new DotnetCommand()
.WithWorkingDirectory(testProjectDirectory)
.ExecuteWithCapturedOutput("invoke-portable")
.Should()
.Pass()
.And
.HaveStdOutContaining("Hello Portable World!");;
}
} }
} }

View file

@ -1,7 +1,15 @@
{ {
"version": "1.0.0-*", "version": "1.0.0-*",
"buildOptions": { "buildOptions": {
"emitEntryPoint": true "emitEntryPoint": true,
"copyToOutput": {
"include": [
"../../artifacts/*/stage2/sdk/*/.version"
],
"mappings": {
".version": "../../artifacts/*/stage2/sdk/*/.version"
}
}
}, },
"dependencies": { "dependencies": {
"Microsoft.NETCore.App": { "Microsoft.NETCore.App": {

View file

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

View file

@ -8,6 +8,7 @@ using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions; using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.DotNet.Tools.Test.Utilities;
using NuGet.Frameworks; using NuGet.Frameworks;
using Xunit; using Xunit;
@ -17,7 +18,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
public class GivenAProjectDependenciesCommandResolver : TestBase public class GivenAProjectDependenciesCommandResolver : TestBase
{ {
private const string TestProjectName = "AppWithDirectDep"; private const string ProjectJsonTestProjectName = "AppWithDirectDep";
[Fact] [Fact]
public void It_returns_null_when_CommandName_is_null() public void It_returns_null_when_CommandName_is_null()
@ -62,7 +63,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithLockFiles(); .WithLockFiles();
var commandResolverArguments = new CommandResolverArguments() var commandResolverArguments = new CommandResolverArguments()
@ -84,7 +85,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithLockFiles(); .WithLockFiles();
var commandResolverArguments = new CommandResolverArguments() var commandResolverArguments = new CommandResolverArguments()
@ -106,7 +107,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithLockFiles(); .WithLockFiles();
var commandResolverArguments = new CommandResolverArguments() var commandResolverArguments = new CommandResolverArguments()
@ -128,7 +129,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithBuildArtifacts() .WithBuildArtifacts()
.WithLockFiles(); .WithLockFiles();
@ -157,7 +158,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithBuildArtifacts() .WithBuildArtifacts()
.WithLockFiles(); .WithLockFiles();
@ -181,7 +182,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithBuildArtifacts() .WithBuildArtifacts()
.WithLockFiles(); .WithLockFiles();
@ -205,7 +206,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithLockFiles(); .WithLockFiles();
var outputDir = Path.Combine(testInstance.Path, "outdir"); var outputDir = Path.Combine(testInstance.Path, "outdir");
@ -245,7 +246,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithLockFiles(); .WithLockFiles();
var buildBasePath = Path.Combine(testInstance.Path, "basedir"); var buildBasePath = Path.Combine(testInstance.Path, "basedir");
@ -285,7 +286,7 @@ namespace Microsoft.DotNet.Cli.Utils.Tests
{ {
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver(); var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance(TestProjectName) var testInstance = TestAssetsManager.CreateTestInstance(ProjectJsonTestProjectName)
.WithBuildArtifacts() .WithBuildArtifacts()
.WithLockFiles(); .WithLockFiles();

View file

@ -0,0 +1,161 @@
// 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.IO;
using FluentAssertions;
using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
using NuGet.Frameworks;
using Xunit;
namespace Microsoft.DotNet.Cli.Utils.Tests
{
public class GivenAProjectDependencyCommandResolverBeingUsedWithMSBuild : TestBase
{
private TestInstance MSBuildTestProjectInstance;
private RepoDirectoriesProvider _repoDirectoriesProvider;
public GivenAProjectDependencyCommandResolverBeingUsedWithMSBuild()
{
MSBuildTestProjectInstance =
TestAssetsManager.CreateTestInstance("MSBuildTestAppWithToolInDependencies");
_repoDirectoriesProvider = new RepoDirectoriesProvider();
new Restore3Command()
.WithWorkingDirectory(MSBuildTestProjectInstance.Path)
.Execute($"-s {_repoDirectoriesProvider.TestPackages}")
.Should()
.Pass();
new Build3Command()
.WithWorkingDirectory(MSBuildTestProjectInstance.Path)
.Execute()
.Should()
.Pass();
Environment.SetEnvironmentVariable(
Constants.MSBUILD_EXE_PATH,
Path.Combine(_repoDirectoriesProvider.Stage2Sdk, "msbuild.exe"));
}
[Fact]
public void It_returns_a_CommandSpec_with_Dotnet_as_FileName_and_CommandName_in_Args_when_CommandName_exists_in_MSBuild_ProjectDependencies()
{
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var commandResolverArguments = new CommandResolverArguments()
{
CommandName = "dotnet-portable",
CommandArguments = null,
ProjectDirectory = MSBuildTestProjectInstance.Path,
Configuration = "Debug",
Framework = FrameworkConstants.CommonFrameworks.NetCoreApp10
};
var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments);
result.Should().NotBeNull();
var commandFile = Path.GetFileNameWithoutExtension(result.Path);
commandFile.Should().Be("dotnet");
result.Args.Should().Contain(commandResolverArguments.CommandName);
}
[Fact]
public void It_passes_depsfile_arg_to_host_when_returning_a_CommandSpec_for_MSBuild_project()
{
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var commandResolverArguments = new CommandResolverArguments()
{
CommandName = "dotnet-portable",
CommandArguments = null,
ProjectDirectory = MSBuildTestProjectInstance.Path,
Configuration = "Debug",
Framework = FrameworkConstants.CommonFrameworks.NetCoreApp10
};
var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments);
result.Should().NotBeNull();
result.Args.Should().Contain("--depsfile");
}
[Fact]
public void It_returns_null_when_CommandName_does_not_exist_in_ProjectDependencies_for_MSBuild_project()
{
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var commandResolverArguments = new CommandResolverArguments()
{
CommandName = "nonexistent-command",
CommandArguments = null,
ProjectDirectory = MSBuildTestProjectInstance.Path,
Configuration = "Debug",
Framework = FrameworkConstants.CommonFrameworks.NetCoreApp10
};
var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments);
result.Should().BeNull();
}
[Fact]
public void It_sets_depsfile_in_output_path_in_commandspec_for_MSBuild_project()
{
var projectDependenciesCommandResolver = SetupProjectDependenciesCommandResolver();
var testInstance = TestAssetsManager.CreateTestInstance("MSBuildTestAppWithToolInDependencies");
var outputDir = Path.Combine(testInstance.Path, "outdir");
var commandResolverArguments = new CommandResolverArguments()
{
CommandName = "dotnet-portable",
CommandArguments = null,
ProjectDirectory = testInstance.Path,
Configuration = "Debug",
Framework = FrameworkConstants.CommonFrameworks.NetCoreApp10,
OutputPath = outputDir
};
new Restore3Command()
.WithWorkingDirectory(testInstance.Path)
.Execute($"-s {_repoDirectoriesProvider.TestPackages}")
.Should()
.Pass();
new Build3Command()
.WithWorkingDirectory(testInstance.Path)
.Execute($"-o {outputDir}")
.Should()
.Pass();
var result = projectDependenciesCommandResolver.Resolve(commandResolverArguments);
var depsFilePath = Path.Combine(outputDir, "MSBuildTestAppWithToolInDependencies.deps.json");
result.Should().NotBeNull();
result.Args.Should().Contain($"--depsfile {depsFilePath}");
}
private ProjectDependenciesCommandResolver SetupProjectDependenciesCommandResolver(
IEnvironmentProvider environment = null,
IPackagedCommandSpecFactory packagedCommandSpecFactory = null)
{
environment = environment ?? new EnvironmentProvider();
packagedCommandSpecFactory = packagedCommandSpecFactory ?? new PackagedCommandSpecFactory();
var projectDependenciesCommandResolver = new ProjectDependenciesCommandResolver(environment, packagedCommandSpecFactory);
return projectDependenciesCommandResolver;
}
}
}

View file

@ -4,7 +4,6 @@
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using Microsoft.DotNet.Cli.CommandResolution;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.TestFramework;
@ -236,7 +235,7 @@ namespace Microsoft.DotNet.Tests
{ {
packagedCommandSpecFactory = packagedCommandSpecFactory ?? new PackagedCommandSpecFactory(); packagedCommandSpecFactory = packagedCommandSpecFactory ?? new PackagedCommandSpecFactory();
var projectToolsCommandResolver = new ProjectToolsCommandResolver(packagedCommandSpecFactory); var projectToolsCommandResolver = new ProjectToolsCommandResolver(packagedCommandSpecFactory, new EnvironmentProvider());
return projectToolsCommandResolver; return projectToolsCommandResolver;
} }

View file

@ -46,7 +46,8 @@
"moq.netcore": "4.4.0-beta8", "moq.netcore": "4.4.0-beta8",
"xunit": "2.2.0-beta3-build3330", "xunit": "2.2.0-beta3-build3330",
"dotnet-test-xunit": "1.0.0-rc2-350904-49", "dotnet-test-xunit": "1.0.0-rc2-350904-49",
"Microsoft.DotNet.PlatformAbstractions": "1.0.1-beta-000933" "Microsoft.DotNet.PlatformAbstractions": "1.0.1-beta-000933",
"Microsoft.Build.Runtime": "15.1.316-preview5"
}, },
"frameworks": { "frameworks": {
"netcoreapp1.0": { "netcoreapp1.0": {

View file

@ -0,0 +1,75 @@
using System;
using System.IO;
using System.Linq;
namespace Microsoft.DotNet.Tools.Test.Utilities
{
public class RepoDirectoriesProvider
{
private static string s_repoRoot;
private string _artifacts;
private string _builtDotnet;
private string _nugetPackages;
private string _corehostPackages;
private string _corehostDummyPackages;
private string _stage2Sdk;
private string _testPackages;
public static string RepoRoot
{
get
{
if (!string.IsNullOrEmpty(s_repoRoot))
{
return s_repoRoot;
}
#if NET451
string directory = AppDomain.CurrentDomain.BaseDirectory;
#else
string directory = AppContext.BaseDirectory;
#endif
while (!Directory.Exists(Path.Combine(directory, ".git")) && directory != null)
{
directory = Directory.GetParent(directory).FullName;
}
if (directory == null)
{
throw new Exception("Cannot find the git repository root");
}
s_repoRoot = directory;
return s_repoRoot;
}
}
public string Artifacts => _artifacts;
public string BuiltDotnet => _builtDotnet;
public string NugetPackages => _nugetPackages;
public string CorehostPackages => _corehostPackages;
public string CorehostDummyPackages => _corehostDummyPackages;
public string Stage2Sdk => _stage2Sdk;
public string TestPackages => _testPackages;
public RepoDirectoriesProvider(
string artifacts = null,
string builtDotnet = null,
string nugetPackages = null,
string corehostPackages = null,
string corehostDummyPackages = null)
{
var currentRid = DotnetLegacyRuntimeIdentifiers.InferLegacyRestoreRuntimeIdentifier();
_artifacts = artifacts ?? Path.Combine(RepoRoot, "artifacts", currentRid);
_nugetPackages = nugetPackages ?? Path.Combine(RepoRoot, ".nuget", "packages");
_corehostPackages = corehostPackages ?? Path.Combine(_artifacts, "corehost");
_corehostDummyPackages = corehostDummyPackages ?? Path.Combine(_artifacts, "corehostdummypackages");
_builtDotnet = builtDotnet ?? Path.Combine(_artifacts, "intermediate", "sharedFrameworkPublish");
_stage2Sdk = Directory.EnumerateDirectories(Path.Combine(_artifacts, "stage2", "sdk")).First();
_testPackages = Path.Combine(_artifacts, "tests", "packages");
}
}
}

View file

@ -22,35 +22,13 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
protected const string DefaultLibraryFramework = "netstandard1.5"; protected const string DefaultLibraryFramework = "netstandard1.5";
private TempRoot _temp; private TempRoot _temp;
private static TestAssetsManager s_testsAssetsMgr; private static TestAssetsManager s_testsAssetsMgr;
private static string s_repoRoot;
protected static string RepoRoot protected static string RepoRoot
{ {
get get
{ {
if (!string.IsNullOrEmpty(s_repoRoot)) return RepoDirectoriesProvider.RepoRoot;
{
return s_repoRoot;
}
#if NET451
string directory = AppDomain.CurrentDomain.BaseDirectory;
#else
string directory = AppContext.BaseDirectory;
#endif
while (!Directory.Exists(Path.Combine(directory, ".git")) && directory != null)
{
directory = Directory.GetParent(directory).FullName;
}
if (directory == null)
{
throw new Exception("Cannot find the git repository root");
}
s_repoRoot = directory;
return s_repoRoot;
} }
} }

View file

@ -36,13 +36,6 @@
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-24022", "System.Runtime.Serialization.Primitives": "4.1.1-rc2-24022",
"System.Collections.Immutable": "1.2.0-rc2-24022", "System.Collections.Immutable": "1.2.0-rc2-24022",
"System.Net.NetworkInformation": "4.1.0-rc2-24022" "System.Net.NetworkInformation": "4.1.0-rc2-24022"
},
"net46": {
"frameworkAssemblies": {
"System.Runtime": {
"type": "build"
}
}
} }
} }
} }

View file

@ -8,7 +8,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
using FluentAssertions; using FluentAssertions;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit; using Xunit;
namespace Microsoft.DotNet.Tests namespace Microsoft.DotNet.Tests

View file

@ -4,7 +4,6 @@
using System.IO; using System.IO;
using Microsoft.DotNet.InternalAbstractions; using Microsoft.DotNet.InternalAbstractions;
using Microsoft.DotNet.TestFramework; using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
namespace Microsoft.DotNet.Tests namespace Microsoft.DotNet.Tests
{ {

View file

@ -3,10 +3,7 @@
"dependencies": { "dependencies": {
"xunit": "2.2.0-beta3-build3330", "xunit": "2.2.0-beta3-build3330",
"dotnet-test-xunit": "1.0.0-rc2-350904-49", "dotnet-test-xunit": "1.0.0-rc2-350904-49",
"Microsoft.NETCore.Platforms": "1.0.1", "Microsoft.NETCore.Platforms": "1.0.1"
"Microsoft.DotNet.Tools.Tests.Utilities": {
"target": "project"
}
}, },
"frameworks": { "frameworks": {
"net46": { "net46": {

View file

@ -1,39 +0,0 @@
// 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)
});
}
}
}