2016-02-24 16:05:55 -08: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 11:45:13 -07:00
|
|
|
|
using Microsoft.DotNet.ProjectModel.Compilation;
|
2016-02-24 16:05:55 -08:00
|
|
|
|
using Microsoft.Extensions.PlatformAbstractions;
|
|
|
|
|
using NuGet.Frameworks;
|
|
|
|
|
using NuGet.Packaging;
|
|
|
|
|
|
|
|
|
|
namespace Microsoft.DotNet.Cli.Utils
|
|
|
|
|
{
|
|
|
|
|
public class PackagedCommandSpecFactory : IPackagedCommandSpecFactory
|
|
|
|
|
{
|
|
|
|
|
public CommandSpec CreateCommandSpecFromLibrary(
|
|
|
|
|
LockFilePackageLibrary library,
|
|
|
|
|
string commandName,
|
|
|
|
|
IEnumerable<string> commandArguments,
|
|
|
|
|
IEnumerable<string> allowedExtensions,
|
|
|
|
|
string nugetPackagesRoot,
|
|
|
|
|
CommandResolutionStrategy commandResolutionStrategy,
|
2016-03-17 11:45:13 -07:00
|
|
|
|
string depsFilePath,
|
|
|
|
|
LibraryExporter exporter = null,
|
|
|
|
|
bool generateRuntimeConfig = false)
|
2016-02-24 16:05:55 -08:00
|
|
|
|
{
|
|
|
|
|
var packageDirectory = GetPackageDirectoryFullPath(library, nugetPackagesRoot);
|
|
|
|
|
|
|
|
|
|
if (!Directory.Exists(packageDirectory))
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var commandFile = GetCommandFileRelativePath(library, commandName, allowedExtensions);
|
|
|
|
|
|
|
|
|
|
if (commandFile == null)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var commandPath = Path.Combine(packageDirectory, commandFile);
|
|
|
|
|
|
2016-03-17 11:45:13 -07:00
|
|
|
|
var isPortable = DetermineIfPortableApp(commandPath);
|
|
|
|
|
|
2016-02-24 16:05:55 -08:00
|
|
|
|
return CreateCommandSpecWrappingWithCorehostfDll(
|
|
|
|
|
commandPath,
|
|
|
|
|
commandArguments,
|
|
|
|
|
depsFilePath,
|
2016-03-17 11:45:13 -07:00
|
|
|
|
commandResolutionStrategy,
|
|
|
|
|
nugetPackagesRoot,
|
|
|
|
|
isPortable);
|
2016-02-24 16:05:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetPackageDirectoryFullPath(LockFilePackageLibrary library, string nugetPackagesRoot)
|
|
|
|
|
{
|
|
|
|
|
var packageDirectory = new VersionFolderPathResolver(nugetPackagesRoot)
|
|
|
|
|
.GetInstallPath(library.Name, library.Version);
|
|
|
|
|
|
|
|
|
|
return packageDirectory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string GetCommandFileRelativePath(
|
|
|
|
|
LockFilePackageLibrary library,
|
|
|
|
|
string commandName,
|
|
|
|
|
IEnumerable<string> allowedExtensions)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Should command names be case sensitive?
|
|
|
|
|
return library.Files
|
|
|
|
|
.Where(f => Path.GetFileNameWithoutExtension(f) == commandName)
|
|
|
|
|
.Where(e => allowedExtensions.Contains(Path.GetExtension(e)))
|
|
|
|
|
.FirstOrDefault();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CommandSpec CreateCommandSpecWrappingWithCorehostfDll(
|
|
|
|
|
string commandPath,
|
|
|
|
|
IEnumerable<string> commandArguments,
|
|
|
|
|
string depsFilePath,
|
2016-03-17 11:45:13 -07:00
|
|
|
|
CommandResolutionStrategy commandResolutionStrategy,
|
|
|
|
|
string nugetPackagesRoot,
|
|
|
|
|
bool isPortable)
|
2016-02-24 16:05:55 -08:00
|
|
|
|
{
|
|
|
|
|
var commandExtension = Path.GetExtension(commandPath);
|
|
|
|
|
|
|
|
|
|
if (commandExtension == FileNameSuffixes.DotNet.DynamicLib)
|
|
|
|
|
{
|
|
|
|
|
return CreatePackageCommandSpecUsingCorehost(
|
|
|
|
|
commandPath,
|
|
|
|
|
commandArguments,
|
|
|
|
|
depsFilePath,
|
2016-03-17 11:45:13 -07:00
|
|
|
|
commandResolutionStrategy,
|
|
|
|
|
nugetPackagesRoot,
|
|
|
|
|
isPortable);
|
2016-02-24 16:05:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CreateCommandSpec(commandPath, commandArguments, commandResolutionStrategy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CommandSpec CreatePackageCommandSpecUsingCorehost(
|
|
|
|
|
string commandPath,
|
|
|
|
|
IEnumerable<string> commandArguments,
|
|
|
|
|
string depsFilePath,
|
2016-03-17 11:45:13 -07:00
|
|
|
|
CommandResolutionStrategy commandResolutionStrategy,
|
|
|
|
|
string nugetPackagesRoot,
|
|
|
|
|
bool isPortable)
|
2016-02-24 16:05:55 -08:00
|
|
|
|
{
|
2016-03-17 11:45:13 -07:00
|
|
|
|
string host = string.Empty;
|
2016-02-24 16:05:55 -08:00
|
|
|
|
var arguments = new List<string>();
|
2016-03-17 11:45:13 -07:00
|
|
|
|
|
|
|
|
|
if (isPortable)
|
|
|
|
|
{
|
|
|
|
|
var muxer = new Muxer();
|
|
|
|
|
|
|
|
|
|
host = muxer.MuxerPath;
|
|
|
|
|
if (host == null)
|
|
|
|
|
{
|
|
|
|
|
throw new Exception("Unable to locate dotnet multiplexer");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
arguments.Add("exec");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
host = CoreHost.LocalHostExePath;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-24 16:05:55 -08:00
|
|
|
|
arguments.Add(commandPath);
|
|
|
|
|
|
|
|
|
|
if (depsFilePath != null)
|
|
|
|
|
{
|
2016-02-22 01:41:25 -08:00
|
|
|
|
arguments.Add("--depsfile");
|
|
|
|
|
arguments.Add(depsFilePath);
|
2016-02-24 16:05:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
2016-03-17 11:45:13 -07:00
|
|
|
|
arguments.Add("--additionalprobingpath");
|
|
|
|
|
arguments.Add(nugetPackagesRoot);
|
|
|
|
|
|
2016-02-24 16:05:55 -08:00
|
|
|
|
arguments.AddRange(commandArguments);
|
|
|
|
|
|
2016-03-17 11:45:13 -07:00
|
|
|
|
return CreateCommandSpec(host, arguments, commandResolutionStrategy);
|
2016-02-24 16:05:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private CommandSpec CreateCommandSpec(
|
|
|
|
|
string commandPath,
|
|
|
|
|
IEnumerable<string> commandArguments,
|
|
|
|
|
CommandResolutionStrategy commandResolutionStrategy)
|
|
|
|
|
{
|
|
|
|
|
var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(commandArguments);
|
|
|
|
|
|
|
|
|
|
return new CommandSpec(commandPath, escapedArgs, commandResolutionStrategy);
|
2016-03-17 11:45:13 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool DetermineIfPortableApp(string commandPath)
|
|
|
|
|
{
|
|
|
|
|
var commandDir = Path.GetDirectoryName(commandPath);
|
|
|
|
|
|
|
|
|
|
var runtimeConfig = Directory.EnumerateFiles(commandDir)
|
|
|
|
|
.FirstOrDefault(x => x.EndsWith("runtimeconfig.json"));
|
|
|
|
|
|
|
|
|
|
return runtimeConfig != null;
|
|
|
|
|
}
|
2016-02-24 16:05:55 -08:00
|
|
|
|
}
|
|
|
|
|
}
|