2016-02-25 00:05:55 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using Microsoft.DotNet.ProjectModel;
|
|
|
|
|
using Microsoft.DotNet.ProjectModel.Graph;
|
2016-03-17 18:45:13 +00:00
|
|
|
|
using Microsoft.DotNet.ProjectModel.Compilation;
|
|
|
|
|
using Microsoft.Extensions.DependencyModel;
|
2016-02-25 00:05:55 +00:00
|
|
|
|
using Microsoft.Extensions.PlatformAbstractions;
|
|
|
|
|
using NuGet.Frameworks;
|
|
|
|
|
using NuGet.Packaging;
|
2016-03-17 18:45:13 +00:00
|
|
|
|
using NuGet.ProjectModel;
|
|
|
|
|
|
|
|
|
|
using LockFile = Microsoft.DotNet.ProjectModel.Graph.LockFile;
|
|
|
|
|
using FileFormatException = Microsoft.DotNet.ProjectModel.FileFormatException;
|
2016-02-25 00:05:55 +00:00
|
|
|
|
|
|
|
|
|
namespace Microsoft.DotNet.Cli.Utils
|
|
|
|
|
{
|
|
|
|
|
public class ProjectToolsCommandResolver : ICommandResolver
|
|
|
|
|
{
|
|
|
|
|
private static readonly NuGetFramework s_toolPackageFramework = FrameworkConstants.CommonFrameworks.NetStandardApp15;
|
2016-03-17 18:45:13 +00:00
|
|
|
|
|
2016-02-25 00:05:55 +00:00
|
|
|
|
private static readonly CommandResolutionStrategy s_commandResolutionStrategy =
|
|
|
|
|
CommandResolutionStrategy.ProjectToolsPackage;
|
|
|
|
|
|
2016-03-17 18:45:13 +00:00
|
|
|
|
private static readonly string s_currentRuntimeIdentifier = PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier();
|
|
|
|
|
|
|
|
|
|
|
2016-02-25 00:05:55 +00:00
|
|
|
|
private List<string> _allowedCommandExtensions;
|
|
|
|
|
private IPackagedCommandSpecFactory _packagedCommandSpecFactory;
|
|
|
|
|
|
|
|
|
|
public ProjectToolsCommandResolver(IPackagedCommandSpecFactory packagedCommandSpecFactory)
|
|
|
|
|
{
|
|
|
|
|
_packagedCommandSpecFactory = packagedCommandSpecFactory;
|
|
|
|
|
|
|
|
|
|
_allowedCommandExtensions = new List<string>()
|
|
|
|
|
{
|
|
|
|
|
FileNameSuffixes.DotNet.DynamicLib
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public CommandSpec Resolve(CommandResolverArguments commandResolverArguments)
|
|
|
|
|
{
|
2016-03-07 19:50:52 +00:00
|
|
|
|
if (commandResolverArguments.CommandName == null
|
|
|
|
|
|| commandResolverArguments.ProjectDirectory == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-25 00:05:55 +00:00
|
|
|
|
return ResolveFromProjectTools(
|
|
|
|
|
commandResolverArguments.CommandName,
|
2016-03-07 19:50:52 +00:00
|
|
|
|
commandResolverArguments.CommandArguments.OrEmptyIfNull(),
|
2016-02-25 00:05:55 +00:00
|
|
|
|
commandResolverArguments.ProjectDirectory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CommandSpec ResolveFromProjectTools(
|
|
|
|
|
string commandName,
|
|
|
|
|
IEnumerable<string> args,
|
|
|
|
|
string projectDirectory)
|
|
|
|
|
{
|
2016-03-23 19:40:10 +00:00
|
|
|
|
var projectContext = GetProjectContextFromDirectoryForFirstTarget(projectDirectory);
|
2016-02-25 00:05:55 +00:00
|
|
|
|
|
|
|
|
|
if (projectContext == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-07 19:50:52 +00:00
|
|
|
|
var toolsLibraries = projectContext.ProjectFile.Tools.OrEmptyIfNull();
|
2016-02-25 00:05:55 +00:00
|
|
|
|
|
|
|
|
|
return ResolveCommandSpecFromAllToolLibraries(
|
|
|
|
|
toolsLibraries,
|
|
|
|
|
commandName,
|
|
|
|
|
args,
|
|
|
|
|
projectContext);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CommandSpec ResolveCommandSpecFromAllToolLibraries(
|
|
|
|
|
IEnumerable<LibraryRange> toolsLibraries,
|
|
|
|
|
string commandName,
|
|
|
|
|
IEnumerable<string> args,
|
|
|
|
|
ProjectContext projectContext)
|
|
|
|
|
{
|
|
|
|
|
foreach (var toolLibrary in toolsLibraries)
|
|
|
|
|
{
|
|
|
|
|
var commandSpec = ResolveCommandSpecFromToolLibrary(toolLibrary, commandName, args, projectContext);
|
|
|
|
|
|
|
|
|
|
if (commandSpec != null)
|
|
|
|
|
{
|
|
|
|
|
return commandSpec;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CommandSpec ResolveCommandSpecFromToolLibrary(
|
|
|
|
|
LibraryRange toolLibrary,
|
|
|
|
|
string commandName,
|
|
|
|
|
IEnumerable<string> args,
|
|
|
|
|
ProjectContext projectContext)
|
|
|
|
|
{
|
2016-03-17 18:45:13 +00:00
|
|
|
|
var nugetPackagesRoot = projectContext.PackagesDirectory;
|
2016-02-25 00:05:55 +00:00
|
|
|
|
|
2016-03-17 18:45:13 +00:00
|
|
|
|
var lockFile = GetToolLockFile(toolLibrary, nugetPackagesRoot);
|
|
|
|
|
var lockFilePackageLibrary = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == toolLibrary.Name);
|
2016-02-25 00:05:55 +00:00
|
|
|
|
|
2016-03-17 18:45:13 +00:00
|
|
|
|
var depsFileRoot = Path.GetDirectoryName(lockFile.LockFilePath);
|
|
|
|
|
var depsFilePath = GetToolDepsFilePath(toolLibrary, lockFile, depsFileRoot);
|
2016-02-25 00:05:55 +00:00
|
|
|
|
|
2016-03-17 18:45:13 +00:00
|
|
|
|
var toolProjectContext = new ProjectContextBuilder()
|
|
|
|
|
.WithLockFile(lockFile)
|
|
|
|
|
.WithTargetFramework(s_toolPackageFramework.ToString())
|
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
var exporter = toolProjectContext.CreateExporter(Constants.DefaultConfiguration);
|
2016-02-25 00:05:55 +00:00
|
|
|
|
|
|
|
|
|
return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary(
|
|
|
|
|
lockFilePackageLibrary,
|
|
|
|
|
commandName,
|
|
|
|
|
args,
|
|
|
|
|
_allowedCommandExtensions,
|
|
|
|
|
projectContext.PackagesDirectory,
|
|
|
|
|
s_commandResolutionStrategy,
|
2016-03-17 18:45:13 +00:00
|
|
|
|
depsFilePath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private LockFile GetToolLockFile(
|
|
|
|
|
LibraryRange toolLibrary,
|
|
|
|
|
string nugetPackagesRoot)
|
|
|
|
|
{
|
|
|
|
|
var lockFilePath = GetToolLockFilePath(toolLibrary, nugetPackagesRoot);
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(lockFilePath))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LockFile lockFile = null;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
lockFile = LockFileReader.Read(lockFilePath);
|
|
|
|
|
}
|
|
|
|
|
catch (FileFormatException ex)
|
|
|
|
|
{
|
|
|
|
|
throw ex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return lockFile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetToolLockFilePath(
|
|
|
|
|
LibraryRange toolLibrary,
|
|
|
|
|
string nugetPackagesRoot)
|
|
|
|
|
{
|
|
|
|
|
var toolPathCalculator = new ToolPathCalculator(nugetPackagesRoot);
|
|
|
|
|
|
|
|
|
|
return toolPathCalculator.GetBestLockFilePath(
|
|
|
|
|
toolLibrary.Name,
|
|
|
|
|
toolLibrary.VersionRange,
|
|
|
|
|
s_toolPackageFramework);
|
2016-02-25 00:05:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-23 19:40:10 +00:00
|
|
|
|
private ProjectContext GetProjectContextFromDirectoryForFirstTarget(string projectRootPath)
|
2016-02-25 00:05:55 +00:00
|
|
|
|
{
|
2016-03-23 19:40:10 +00:00
|
|
|
|
if (projectRootPath == null)
|
2016-02-25 00:05:55 +00:00
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(Path.Combine(projectRootPath, Project.FileName)))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-23 19:40:10 +00:00
|
|
|
|
var projectContext = ProjectContext.CreateContextForEachTarget(projectRootPath).FirstOrDefault();
|
2016-02-25 00:05:55 +00:00
|
|
|
|
|
|
|
|
|
return projectContext;
|
|
|
|
|
}
|
2016-03-17 18:45:13 +00:00
|
|
|
|
|
|
|
|
|
private string GetToolDepsFilePath(
|
|
|
|
|
LibraryRange toolLibrary,
|
|
|
|
|
LockFile toolLockFile,
|
|
|
|
|
string depsPathRoot)
|
|
|
|
|
{
|
|
|
|
|
var depsJsonPath = Path.Combine(
|
|
|
|
|
depsPathRoot,
|
|
|
|
|
toolLibrary.Name + FileNameSuffixes.DepsJson);
|
|
|
|
|
|
|
|
|
|
EnsureToolJsonDepsFileExists(toolLibrary, toolLockFile, depsJsonPath);
|
|
|
|
|
|
|
|
|
|
return depsJsonPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void EnsureToolJsonDepsFileExists(
|
|
|
|
|
LibraryRange toolLibrary,
|
|
|
|
|
LockFile toolLockFile,
|
|
|
|
|
string depsPath)
|
|
|
|
|
{
|
|
|
|
|
if (!File.Exists(depsPath))
|
|
|
|
|
{
|
|
|
|
|
var projectContext = new ProjectContextBuilder()
|
|
|
|
|
.WithLockFile(toolLockFile)
|
|
|
|
|
.WithTargetFramework(s_toolPackageFramework.ToString())
|
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
var exporter = projectContext.CreateExporter(Constants.DefaultConfiguration);
|
|
|
|
|
|
|
|
|
|
var dependencyContext = new DependencyContextBuilder()
|
|
|
|
|
.Build(null,
|
|
|
|
|
null,
|
|
|
|
|
exporter.GetAllExports(),
|
|
|
|
|
true,
|
|
|
|
|
s_toolPackageFramework,
|
|
|
|
|
string.Empty);
|
|
|
|
|
|
|
|
|
|
using (var fileStream = File.Create(depsPath))
|
|
|
|
|
{
|
|
|
|
|
var dependencyContextWriter = new DependencyContextWriter();
|
|
|
|
|
|
|
|
|
|
dependencyContextWriter.Write(dependencyContext, fileStream);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-02-25 00:05:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|