Merge pull request #2087 from dotnet/piotrpMSFT/Issue2020/DesktopCommands

Enable execution of Target-specific commands
This commit is contained in:
Piotr Puszkiewicz 2016-03-28 20:07:09 -07:00
commit 5572326e0a
26 changed files with 550 additions and 126 deletions

View file

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.25029.0 VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED2FE3E2-F7E7-4389-8231-B65123F2076F}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED2FE3E2-F7E7-4389-8231-B65123F2076F}"
EndProject EndProject
@ -95,6 +95,12 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Testin
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Testing.Abstractions.UnitTests", "test\TestingAbstractions\Microsoft.Extensions.Testing.Abstractions.UnitTests\Microsoft.Extensions.Testing.Abstractions.UnitTests.xproj", "{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}" Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Testing.Abstractions.UnitTests", "test\TestingAbstractions\Microsoft.Extensions.Testing.Abstractions.UnitTests\Microsoft.Extensions.Testing.Abstractions.UnitTests.xproj", "{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestAssets", "TestAssets", "{ADA7052B-884B-4776-8B8D-D04191D0AA70}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestPackages", "TestPackages", "{1AB5B24B-B317-4142-A5D1-A6E84F15BA34}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-dependency-tool-invoker", "TestAssets\TestPackages\dotnet-dependency-tool-invoker\dotnet-dependency-tool-invoker.xproj", "{C26A48BB-193F-450C-AB09-4D3324C78188}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -683,6 +689,22 @@ Global
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.Debug|x64.ActiveCfg = Debug|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.Debug|x64.Build.0 = Debug|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.Release|Any CPU.Build.0 = Release|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.Release|x64.ActiveCfg = Release|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.Release|x64.Build.0 = Release|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
{C26A48BB-193F-450C-AB09-4D3324C78188}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -727,5 +749,8 @@ Global
{7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF} {7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF}
{09C61BD7-C6DB-4F89-85BF-4EB3C196049D} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF} {09C61BD7-C6DB-4F89-85BF-4EB3C196049D} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF}
{DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF} {DEB3AB06-FCD8-4119-B8CA-B7AA6CE2F22D} = {EB0F5F8C-0991-49AC-B188-A9869476C7DF}
{ADA7052B-884B-4776-8B8D-D04191D0AA70} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
{1AB5B24B-B317-4142-A5D1-A6E84F15BA34} = {ADA7052B-884B-4776-8B8D-D04191D0AA70}
{C26A48BB-193F-450C-AB09-4D3324C78188} = {1AB5B24B-B317-4142-A5D1-A6E84F15BA34}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View file

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

View file

@ -0,0 +1,33 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"dotnet-desktop-and-portable": "1.0.0"
},
"frameworks": {
"netstandardapp1.5": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-rc2-23928"
}
},
"imports": [
"portable-net45+win8",
"dnxcore50"
]
},
"net451":{}
},
"tools": {
"dotnet-dependency-tool-invoker": {
"version": "1.0.0-*",
"imports": [
"dnxcore50",
"portable-net45+win8"
]
}
}
}

View file

@ -0,0 +1,117 @@
// 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.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.Dnx.Runtime.Common.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using NuGet.Frameworks;
using static System.Int32;
namespace Microsoft.DotNet.Tools.DependencyInvoker
{
public class DotnetBaseParams
{
private readonly CommandLineApplication _app;
private CommandOption _outputOption;
private CommandOption _buildBasePath;
private CommandOption _frameworkOption;
private CommandOption _runtimeOption;
private CommandOption _configurationOption;
private CommandOption _projectPath;
private CommandArgument _command;
public string Runtime { get; set; }
public string Config { get; set; }
public string BuildBasePath { get; set; }
public string Output { get; set; }
public string ProjectPath { get; set; }
public NuGetFramework Framework { get; set; }
public string Command {get; set; }
public List<string> RemainingArguments { get; set; }
public DotnetBaseParams(string name, string fullName, string description)
{
_app = new CommandLineApplication(false)
{
Name = name,
FullName = fullName,
Description = description
};
AddDotnetBaseParameters();
}
public void Parse(string[] args)
{
_app.OnExecute(() =>
{
// Locate the project and get the name and full path
ProjectPath = _projectPath.Value();
Output = _outputOption.Value();
BuildBasePath = _buildBasePath.Value();
Config = _configurationOption.Value() ?? Constants.DefaultConfiguration;
Runtime = _runtimeOption.Value();
if (_frameworkOption.HasValue())
{
Framework = NuGetFramework.Parse(_frameworkOption.Value());
}
Command = _command.Value;
RemainingArguments = _app.RemainingArguments;
if (string.IsNullOrEmpty(ProjectPath))
{
ProjectPath = Directory.GetCurrentDirectory();
}
return 0;
});
_app.Execute(args);
}
private void AddDotnetBaseParameters()
{
_app.HelpOption("-?|-h|--help");
_configurationOption = _app.Option(
"-c|--configuration <CONFIGURATION>",
"Configuration under which to build",
CommandOptionType.SingleValue);
_outputOption = _app.Option(
"-o|--output <OUTPUT_DIR>",
"Directory in which to find the binaries to be run",
CommandOptionType.SingleValue);
_buildBasePath = _app.Option(
"-b|--build-base-path <OUTPUT_DIR>",
"Directory in which to find temporary outputs",
CommandOptionType.SingleValue);
_frameworkOption = _app.Option(
"-f|--framework <FRAMEWORK>",
"Looks for test binaries for a specific framework",
CommandOptionType.SingleValue);
_runtimeOption = _app.Option(
"-r|--runtime <RUNTIME_IDENTIFIER>",
"Look for test binaries for a for the specified runtime",
CommandOptionType.SingleValue);
_projectPath = _app.Option(
"-p|--project-path <PROJECT_JSON_PATH>",
"Path to Project.json that contains the tool dependency",
CommandOptionType.SingleValue);
_command = _app.Argument(
"<COMMAND>",
"The command to execute.");
}
}
}

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View file

@ -0,0 +1,83 @@
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Tools.DependencyInvoker
{
public class Program
{
public static void Main(string[] args)
{
DebugHelper.HandleDebugSwitch(ref args);
var dotnetParams = new DotnetBaseParams("dotnet-dependency-tool-invoker", "DotNet Dependency Tool Invoker", "Invokes tools declared as NuGet dependencies of a project");
dotnetParams.Parse(args);
if (string.IsNullOrEmpty(dotnetParams.Command))
{
Console.WriteLine("A command name must be provided");
return;
}
var projectContexts =
CreateProjectContexts(dotnetParams.ProjectPath)
.Where(p => dotnetParams.Framework == null ||
dotnetParams.Framework.GetShortFolderName()
.Equals(p.TargetFramework.GetShortFolderName()));
var commandFactory =
new ProjectDependenciesCommandFactory(
dotnetParams.Framework,
dotnetParams.Config,
dotnetParams.Output,
dotnetParams.BuildBasePath,
projectContexts.First().ProjectDirectory);
foreach (var projectContext in projectContexts)
{
Console.WriteLine($"Invoking '{dotnetParams.Command}' for '{projectContext.TargetFramework}'.");
try
{
var exitCode = commandFactory.Create(
$"dotnet-{dotnetParams.Command}",
dotnetParams.RemainingArguments,
projectContext.TargetFramework,
dotnetParams.Config)
.ForwardStdErr()
.ForwardStdOut()
.Execute()
.ExitCode;
Console.WriteLine($"Command returned {exitCode}");
}
catch (CommandUnknownException)
{
Console.WriteLine($"Command not found");
}
}
}
private static IEnumerable<ProjectContext> CreateProjectContexts(string projectPath = null)
{
projectPath = projectPath ?? Directory.GetCurrentDirectory();
if (!projectPath.EndsWith(Project.FileName))
{
projectPath = Path.Combine(projectPath, Project.FileName);
}
if (!File.Exists(projectPath))
{
throw new InvalidOperationException($"{projectPath} does not exist.");
}
return ProjectContext.CreateContextForEachFramework(projectPath);
}
}
}

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.23107" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.23107</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>c26a48bb-193f-450c-ab09-4d3324c78188</ProjectGuid>
<RootNamespace>dotnet-dependency-tool-invoker</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View file

@ -0,0 +1,36 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-rc2-23928"
},
"Microsoft.DotNet.Cli.Utils":"1.0.0-*",
"Microsoft.DotNet.ProjectModel": "1.0.0-*",
"Microsoft.DotNet.Compiler.Common": "1.0.0-*",
"Microsoft.Extensions.CommandLineUtils.Sources": {
"type": "build",
"version": "1.0.0-rc2-16453"
},
"Microsoft.Dnx.Runtime.CommandParsing.Sources": {
"version": "1.0.0-rc2-16453",
"type": "build"
},
"Microsoft.Dnx.Runtime.Sources": {
"version": "1.0.0-rc2-16453",
"type": "build"
},
"System.CommandLine": "0.1.0-e160323-1"
},
"frameworks": {
"netstandard1.5": {
"imports": [
"portable-net45+win8",
"dnxcore50"
]
}
}
}

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>

View file

@ -0,0 +1,16 @@
using System;
namespace ConsoleApplication
{
public class Program
{
public static void Main(string[] args)
{
#if NET451
Console.WriteLine($"Hello {string.Join(" ", args)} From .NETFramework,Version=v4.5.1");
#elif NETSTANDARD1_5
Console.WriteLine($"Hello {string.Join(" ", args)} From .NETStandardApp,Version=v1.5");
#endif
}
}
}

View file

@ -0,0 +1,22 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true
},
"frameworks": {
"netstandard1.5": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-rc2-23928"
}
},
"imports": [
"portable-net45+win8",
"dnxcore50"
]
},
"net451": {}
}
}

View file

@ -3,7 +3,7 @@
"dependencies": { "dependencies": {
"NETStandard.Library": "1.5.0-rc2-23928", "NETStandard.Library": "1.5.0-rc2-23928",
"System.Diagnostics.Process": "4.1.0-rc2-23928", "System.Diagnostics.Process": "4.1.0-rc2-23928",
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100"
}, },
"frameworks": { "frameworks": {
"netstandard1.3": { "netstandard1.3": {

View file

@ -13,11 +13,19 @@ namespace Microsoft.DotNet.Cli.Build
{ {
public class TestTargets public class TestTargets
{ {
public static readonly string[] TestPackageProjects = new[] public static readonly dynamic[] TestPackageProjects = new[]
{ {
"dotnet-hello/v1/dotnet-hello", new { Name = "Microsoft.DotNet.Cli.Utils", IsTool = false, Path = "src/Microsoft.DotNet.Cli.Utils", IsApplicable = new Func<bool>(() => CurrentPlatform.IsWindows) },
"dotnet-hello/v2/dotnet-hello", new { Name = "Microsoft.DotNet.ProjectModel", IsTool = false, Path = "src/Microsoft.DotNet.ProjectModel", IsApplicable = new Func<bool>(() => CurrentPlatform.IsWindows) },
"dotnet-portable" new { Name = "Microsoft.DotNet.Compiler.Common", IsTool = false, Path = "src/Microsoft.DotNet.Compiler.Common", IsApplicable = new Func<bool>(() => CurrentPlatform.IsWindows) },
new { Name = "Microsoft.Extensions.DependencyModel", IsTool = false, Path = "src/Microsoft.Extensions.DependencyModel", IsApplicable = new Func<bool>(() => CurrentPlatform.IsWindows) },
new { Name = "Microsoft.DotNet.Files", IsTool = false, Path = "src/Microsoft.DotNet.Files", IsApplicable = new Func<bool>(() => CurrentPlatform.IsWindows) },
new { Name = "Microsoft.DotNet.InternalAbstractions", IsTool = false, Path = "src/Microsoft.DotNet.InternalAbstractions", IsApplicable = new Func<bool>(() => CurrentPlatform.IsWindows) },
new { Name = "dotnet-dependency-tool-invoker", IsTool = true, Path = "TestAssets/TestPackages/dotnet-dependency-tool-invoker", IsApplicable = new Func<bool>(() => CurrentPlatform.IsWindows) },
new { Name = "dotnet-desktop-and-portable", IsTool = true, Path = "TestAssets/TestPackages/dotnet-desktop-and-portable", IsApplicable = new Func<bool>(() => CurrentPlatform.IsWindows) },
new { Name = "dotnet-hello", IsTool = true, Path = "TestAssets/TestPackages/dotnet-hello/v1/dotnet-hello", IsApplicable = new Func<bool>(() => true) },
new { Name = "dotnet-hello", IsTool = true, Path = "TestAssets/TestPackages/dotnet-hello/v2/dotnet-hello", IsApplicable = new Func<bool>(() => true) },
new { Name = "dotnet-portable", IsTool = true, Path = "TestAssets/TestPackages/dotnet-portable", IsApplicable = new Func<bool>(() => true) }
}; };
public static readonly string[] TestProjects = new[] public static readonly string[] TestProjects = new[]
@ -40,6 +48,11 @@ namespace Microsoft.DotNet.Cli.Build
"dotnet-test.UnitTests", "dotnet-test.UnitTests",
"dotnet-test.Tests" "dotnet-test.Tests"
}; };
public static readonly dynamic[] ConditionalTestAssets = new[]
{
new { Path = "AppWithDirectDependencyDesktopAndPortable", Skip = new Func<bool>(() => !CurrentPlatform.IsWindows) }
};
[Target(nameof(PrepareTargets.Init), nameof(SetupTests), nameof(RestoreTests), nameof(BuildTests), nameof(RunTests), nameof(ValidateDependencies))] [Target(nameof(PrepareTargets.Init), nameof(SetupTests), nameof(RestoreTests), nameof(BuildTests), nameof(RunTests), nameof(ValidateDependencies))]
public static BuildTargetResult Test(BuildTargetContext c) => c.Success(); public static BuildTargetResult Test(BuildTargetContext c) => c.Success();
@ -50,7 +63,7 @@ namespace Microsoft.DotNet.Cli.Build
[Target(nameof(RestoreTestAssetPackages), nameof(BuildTestAssetPackages))] [Target(nameof(RestoreTestAssetPackages), nameof(BuildTestAssetPackages))]
public static BuildTargetResult SetupTestPackages(BuildTargetContext c) => c.Success(); public static BuildTargetResult SetupTestPackages(BuildTargetContext c) => c.Success();
[Target(nameof(RestoreTestAssetProjects), nameof(BuildTestAssetProjects))] [Target(nameof(RestoreTestAssetProjects), nameof(RestoreDesktopTestAssetProjects), nameof(BuildTestAssetProjects))]
public static BuildTargetResult SetupTestProjects(BuildTargetContext c) => c.Success(); public static BuildTargetResult SetupTestProjects(BuildTargetContext c) => c.Success();
[Target] [Target]
@ -93,6 +106,19 @@ namespace Microsoft.DotNet.Cli.Build
return c.Success(); return c.Success();
} }
[Target]
[BuildPlatforms(BuildPlatform.Windows)]
public static BuildTargetResult RestoreDesktopTestAssetProjects(BuildTargetContext c)
{
var dotnet = DotNetCli.Stage2;
dotnet.Restore("--verbosity", "verbose", "--disable-parallel", "--fallbacksource", Dirs.TestPackages)
.WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "DesktopTestProjects"))
.Execute().EnsureSuccessful();
return c.Success();
}
[Target(nameof(CleanTestPackages))] [Target(nameof(CleanTestPackages))]
public static BuildTargetResult BuildTestAssetPackages(BuildTargetContext c) public static BuildTargetResult BuildTestAssetPackages(BuildTargetContext c)
{ {
@ -103,9 +129,9 @@ namespace Microsoft.DotNet.Cli.Build
Rmdir(Dirs.TestPackages); Rmdir(Dirs.TestPackages);
Mkdirp(Dirs.TestPackages); Mkdirp(Dirs.TestPackages);
foreach (var relativePath in TestPackageProjects) foreach (var relativePath in TestPackageProjects.Where(p => p.IsApplicable()).Select(p => p.Path))
{ {
var fullPath = Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestPackages", relativePath.Replace('/', Path.DirectorySeparatorChar)); var fullPath = Path.Combine(c.BuildContext.BuildDirectory, relativePath.Replace('/', Path.DirectorySeparatorChar));
c.Info($"Packing: {fullPath}"); c.Info($"Packing: {fullPath}");
dotnet.Pack("--output", Dirs.TestPackages) dotnet.Pack("--output", Dirs.TestPackages)
.WorkingDirectory(fullPath) .WorkingDirectory(fullPath)
@ -119,9 +145,14 @@ namespace Microsoft.DotNet.Cli.Build
[Target] [Target]
public static BuildTargetResult CleanTestPackages(BuildTargetContext c) public static BuildTargetResult CleanTestPackages(BuildTargetContext c)
{ {
Rmdir(Path.Combine(Dirs.NuGetPackages, "dotnet-hello")); foreach (var packageProject in TestPackageProjects.Where(p => p.IsApplicable()))
Rmdir(Path.Combine(Dirs.NuGetPackages, "dotnet-portable")); {
Rmdir(Path.Combine(Dirs.NuGetPackages, ".tools", "dotnet-portable")); Rmdir(Path.Combine(Dirs.NuGetPackages, packageProject.Name));
if(packageProject.IsTool)
{
Rmdir(Path.Combine(Dirs.NuGetPackages, ".tools", packageProject.Name));
}
}
return c.Success(); return c.Success();
} }
@ -135,6 +166,7 @@ namespace Microsoft.DotNet.Cli.Build
var nobuildFileName = ".noautobuild"; var nobuildFileName = ".noautobuild";
string testProjectsRoot = Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects"); string testProjectsRoot = Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects");
var projects = Directory.GetFiles(testProjectsRoot, "project.json", SearchOption.AllDirectories) var projects = Directory.GetFiles(testProjectsRoot, "project.json", SearchOption.AllDirectories)
.Where(p => !ConditionalTestAssets.Where(s => !s.Skip() && p.EndsWith(Path.Combine(s.Path, "project.json"))).Any())
.Where(p => !File.Exists(Path.Combine(Path.GetDirectoryName(p), nobuildFileName))); .Where(p => !File.Exists(Path.Combine(Path.GetDirectoryName(p), nobuildFileName)));
foreach (var project in projects) foreach (var project in projects)

View file

@ -5,12 +5,14 @@
"emitEntryPoint": true "emitEntryPoint": true
}, },
"dependencies": { "dependencies": {
"NETStandard.Library": "1.5.0-rc2-23928", "NETStandard.Library": "1.5.0-rc2-23928",
"Microsoft.CSharp": "4.0.1-rc2-23928",
"Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*",
"System.Dynamic.Runtime": "4.0.11-rc2-23928",
"System.Reflection.Metadata": "1.3.0-rc2-23928",
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23928", "System.Runtime.Serialization.Primitives": "4.1.1-rc2-23928",
"System.Xml.XmlSerializer": "4.0.11-rc2-23928", "System.Xml.XmlSerializer": "4.0.11-rc2-23928",
"Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*", "WindowsAzure.Storage": "6.2.2-preview"
"WindowsAzure.Storage": "6.2.2-preview",
"System.Reflection.Metadata": "1.3.0-rc2-23928"
}, },
"frameworks": { "frameworks": {
"netstandardapp1.5": { "netstandardapp1.5": {

View file

@ -11,7 +11,7 @@ namespace Microsoft.DotNet.Cli.Utils
public interface IPackagedCommandSpecFactory public interface IPackagedCommandSpecFactory
{ {
CommandSpec CreateCommandSpecFromLibrary( CommandSpec CreateCommandSpecFromLibrary(
LockFilePackageLibrary library, LockFileTargetLibrary toolLibrary,
string commandName, string commandName,
IEnumerable<string> commandArguments, IEnumerable<string> commandArguments,
IEnumerable<string> allowedExtensions, IEnumerable<string> allowedExtensions,

View file

@ -2,12 +2,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.ProjectModel.Compilation;
using Microsoft.Extensions.PlatformAbstractions;
using NuGet.Frameworks;
using NuGet.Packaging; using NuGet.Packaging;
namespace Microsoft.DotNet.Cli.Utils namespace Microsoft.DotNet.Cli.Utils
@ -15,7 +11,7 @@ namespace Microsoft.DotNet.Cli.Utils
public class PackagedCommandSpecFactory : IPackagedCommandSpecFactory public class PackagedCommandSpecFactory : IPackagedCommandSpecFactory
{ {
public CommandSpec CreateCommandSpecFromLibrary( public CommandSpec CreateCommandSpecFromLibrary(
LockFilePackageLibrary library, LockFileTargetLibrary toolLibrary,
string commandName, string commandName,
IEnumerable<string> commandArguments, IEnumerable<string> commandArguments,
IEnumerable<string> allowedExtensions, IEnumerable<string> allowedExtensions,
@ -23,25 +19,25 @@ namespace Microsoft.DotNet.Cli.Utils
CommandResolutionStrategy commandResolutionStrategy, CommandResolutionStrategy commandResolutionStrategy,
string depsFilePath) string depsFilePath)
{ {
var packageDirectory = GetPackageDirectoryFullPath(library, nugetPackagesRoot);
if (!Directory.Exists(packageDirectory)) var toolAssembly = toolLibrary?.RuntimeAssemblies
.FirstOrDefault(r => Path.GetFileNameWithoutExtension(r.Path) == commandName);
if (toolAssembly == null)
{
return null;
}
var commandPath = GetCommandFilePath(nugetPackagesRoot, toolLibrary, toolAssembly);
if (!File.Exists(commandPath))
{ {
return null; return null;
} }
var commandFile = GetCommandFileRelativePath(library, commandName, allowedExtensions); var isPortable = IsPortableApp(commandPath);
if (commandFile == null) return CreateCommandSpecWrappingWithCorehostIfDll(
{
return null;
}
var commandPath = Path.Combine(packageDirectory, commandFile);
var isPortable = DetermineIfPortableApp(commandPath);
return CreateCommandSpecWrappingWithCorehostfDll(
commandPath, commandPath,
commandArguments, commandArguments,
depsFilePath, depsFilePath,
@ -50,27 +46,17 @@ namespace Microsoft.DotNet.Cli.Utils
isPortable); isPortable);
} }
private string GetPackageDirectoryFullPath(LockFilePackageLibrary library, string nugetPackagesRoot) private string GetCommandFilePath(string nugetPackagesRoot, LockFileTargetLibrary toolLibrary, LockFileItem runtimeAssembly)
{ {
var packageDirectory = new VersionFolderPathResolver(nugetPackagesRoot) var packageDirectory = new VersionFolderPathResolver(nugetPackagesRoot)
.GetInstallPath(library.Name, library.Version); .GetInstallPath(toolLibrary.Name, toolLibrary.Version);
return packageDirectory; var filePath = Path.Combine(packageDirectory, runtimeAssembly.Path);
return filePath;
} }
private string GetCommandFileRelativePath( private CommandSpec CreateCommandSpecWrappingWithCorehostIfDll(
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, string commandPath,
IEnumerable<string> commandArguments, IEnumerable<string> commandArguments,
string depsFilePath, string depsFilePath,
@ -102,7 +88,7 @@ namespace Microsoft.DotNet.Cli.Utils
string nugetPackagesRoot, string nugetPackagesRoot,
bool isPortable) bool isPortable)
{ {
string host = string.Empty; var host = string.Empty;
var arguments = new List<string>(); var arguments = new List<string>();
if (isPortable) if (isPortable)
@ -148,7 +134,7 @@ namespace Microsoft.DotNet.Cli.Utils
return new CommandSpec(commandPath, escapedArgs, commandResolutionStrategy); return new CommandSpec(commandPath, escapedArgs, commandResolutionStrategy);
} }
private bool DetermineIfPortableApp(string commandPath) private bool IsPortableApp(string commandPath)
{ {
var commandDir = Path.GetDirectoryName(commandPath); var commandDir = Path.GetDirectoryName(commandPath);

View file

@ -2,12 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.PlatformAbstractions;
using NuGet.Frameworks; using NuGet.Frameworks;
using NuGet.Packaging;
namespace Microsoft.DotNet.Cli.Utils namespace Microsoft.DotNet.Cli.Utils
{ {
@ -16,8 +14,8 @@ namespace Microsoft.DotNet.Cli.Utils
private static readonly CommandResolutionStrategy s_commandResolutionStrategy = private static readonly CommandResolutionStrategy s_commandResolutionStrategy =
CommandResolutionStrategy.ProjectDependenciesPackage; CommandResolutionStrategy.ProjectDependenciesPackage;
private IEnvironmentProvider _environment; private readonly IEnvironmentProvider _environment;
private IPackagedCommandSpecFactory _packagedCommandSpecFactory; private readonly IPackagedCommandSpecFactory _packagedCommandSpecFactory;
public ProjectDependenciesCommandResolver( public ProjectDependenciesCommandResolver(
IEnvironmentProvider environment, IEnvironmentProvider environment,
@ -80,10 +78,10 @@ namespace Microsoft.DotNet.Cli.Utils
var depsFilePath = var depsFilePath =
projectContext.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeFiles.DepsJson; projectContext.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeFiles.DepsJson;
var dependencyLibraries = GetAllDependencyLibraries(projectContext); var toolLibrary = GetToolLibraryForContext(projectContext, commandName);
return ResolveFromDependencyLibraries( return ResolveFromDependencyLibrary(
dependencyLibraries, toolLibrary,
depsFilePath, depsFilePath,
commandName, commandName,
allowedExtensions, allowedExtensions,
@ -91,35 +89,8 @@ namespace Microsoft.DotNet.Cli.Utils
projectContext); projectContext);
} }
private CommandSpec ResolveFromDependencyLibraries(
IEnumerable<LockFilePackageLibrary> dependencyLibraries,
string depsFilePath,
string commandName,
IEnumerable<string> allowedExtensions,
IEnumerable<string> commandArguments,
ProjectContext projectContext)
{
foreach (var dependencyLibrary in dependencyLibraries)
{
var commandSpec = ResolveFromDependencyLibrary(
dependencyLibrary,
depsFilePath,
commandName,
allowedExtensions,
commandArguments,
projectContext);
if (commandSpec != null)
{
return commandSpec;
}
}
return null;
}
private CommandSpec ResolveFromDependencyLibrary( private CommandSpec ResolveFromDependencyLibrary(
LockFilePackageLibrary dependencyLibrary, LockFileTargetLibrary toolLibrary,
string depsFilePath, string depsFilePath,
string commandName, string commandName,
IEnumerable<string> allowedExtensions, IEnumerable<string> allowedExtensions,
@ -127,7 +98,7 @@ namespace Microsoft.DotNet.Cli.Utils
ProjectContext projectContext) ProjectContext projectContext)
{ {
return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary(
dependencyLibrary, toolLibrary,
commandName, commandName,
commandArguments, commandArguments,
allowedExtensions, allowedExtensions,
@ -136,13 +107,15 @@ namespace Microsoft.DotNet.Cli.Utils
depsFilePath); depsFilePath);
} }
private IEnumerable<LockFilePackageLibrary> GetAllDependencyLibraries( private LockFileTargetLibrary GetToolLibraryForContext(
ProjectContext projectContext) ProjectContext projectContext, string commandName)
{ {
return projectContext.LibraryManager.GetLibraries() var toolLibrary = projectContext.LockFile.Targets
.Where(l => l.GetType() == typeof(PackageDescription)) .FirstOrDefault(t => t.TargetFramework.GetShortFolderName()
.Select(l => l as PackageDescription) .Equals(projectContext.TargetFramework.GetShortFolderName()))
.Select(p => p.Library); ?.Libraries.FirstOrDefault(l => l.Name == commandName);
return toolLibrary;
} }
private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework) private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework)

View file

@ -95,28 +95,29 @@ namespace Microsoft.DotNet.Cli.Utils
} }
private CommandSpec ResolveCommandSpecFromToolLibrary( private CommandSpec ResolveCommandSpecFromToolLibrary(
LibraryRange toolLibrary, LibraryRange toolLibraryRange,
string commandName, string commandName,
IEnumerable<string> args, IEnumerable<string> args,
ProjectContext projectContext) ProjectContext projectContext)
{ {
var nugetPackagesRoot = projectContext.PackagesDirectory; var nugetPackagesRoot = projectContext.PackagesDirectory;
var lockFile = GetToolLockFile(toolLibraryRange, nugetPackagesRoot);
var lockFile = GetToolLockFile(toolLibrary, nugetPackagesRoot); var toolLibrary = lockFile.Targets
var lockFilePackageLibrary = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == toolLibrary.Name); .FirstOrDefault(t => t.TargetFramework.GetShortFolderName().Equals(s_toolPackageFramework.GetShortFolderName()))
?.Libraries.FirstOrDefault(l => l.Name == toolLibraryRange.Name);
if (toolLibrary == null)
{
return null;
}
var depsFileRoot = Path.GetDirectoryName(lockFile.LockFilePath); var depsFileRoot = Path.GetDirectoryName(lockFile.LockFilePath);
var depsFilePath = GetToolDepsFilePath(toolLibrary, lockFile, depsFileRoot); var depsFilePath = GetToolDepsFilePath(toolLibraryRange, lockFile, depsFileRoot);
var toolProjectContext = new ProjectContextBuilder()
.WithLockFile(lockFile)
.WithTargetFramework(s_toolPackageFramework.ToString())
.Build();
var exporter = toolProjectContext.CreateExporter(Constants.DefaultConfiguration);
return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary(
lockFilePackageLibrary, toolLibrary,
commandName, commandName,
args, args,
_allowedCommandExtensions, _allowedCommandExtensions,

View file

@ -6,7 +6,7 @@
}, },
"dependencies": { "dependencies": {
"Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.ProjectModel": "1.0.0-*",
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100",
"NuGet.Versioning": "3.5.0-beta-1083", "NuGet.Versioning": "3.5.0-beta-1083",
"NuGet.Packaging": "3.5.0-beta-1083", "NuGet.Packaging": "3.5.0-beta-1083",
"NuGet.Frameworks": "3.5.0-beta-1083", "NuGet.Frameworks": "3.5.0-beta-1083",

View file

@ -10,7 +10,7 @@
"keyFile": "../../tools/Key.snk" "keyFile": "../../tools/Key.snk"
}, },
"dependencies": { "dependencies": {
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100"
}, },
"frameworks": { "frameworks": {
"net451": {}, "net451": {},

View file

@ -19,7 +19,7 @@
"version": "1.0.0-*" "version": "1.0.0-*"
}, },
"Newtonsoft.Json": "7.0.1", "Newtonsoft.Json": "7.0.1",
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100"
}, },
"frameworks": { "frameworks": {
"net451": {}, "net451": {},

View file

@ -13,6 +13,8 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
{ {
protected string _command; protected string _command;
public string WorkingDirectory { get; set; }
public Dictionary<string, string> Environment { get; } = new Dictionary<string, string>(); public Dictionary<string, string> Environment { get; } = new Dictionary<string, string>();
public TestCommand(string command) public TestCommand(string command)
@ -53,7 +55,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
return RunProcess(commandPath, args, stdOut, stdErr); return RunProcess(commandPath, args, stdOut, stdErr);
} }
private void ResolveCommand(ref string executable, ref string args) private void ResolveCommand(ref string executable, ref string args)
{ {
if (executable.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) if (executable.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
@ -89,9 +91,14 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
psi.Environment[item.Key] = item.Value; psi.Environment[item.Key] = item.Value;
} }
if (!string.IsNullOrWhiteSpace(WorkingDirectory))
{
psi.WorkingDirectory = WorkingDirectory;
}
var process = new Process var process = new Process
{ {
StartInfo = psi, StartInfo = psi
}; };
process.EnableRaisingEvents = true; process.EnableRaisingEvents = true;

View file

@ -14,7 +14,7 @@
"Microsoft.DotNet.TestFramework": "1.0.0-*", "Microsoft.DotNet.TestFramework": "1.0.0-*",
"Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*",
"Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.ProjectModel": "1.0.0-*",
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100",
"Microsoft.DotNet.InternalAbstractions": { "Microsoft.DotNet.InternalAbstractions": {
"target": "project", "target": "project",
"version": "1.0.0-*" "version": "1.0.0-*"

View file

@ -5,6 +5,7 @@ using System;
using System.IO; using System.IO;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Test.Utilities; using Microsoft.DotNet.Tools.Test.Utilities;
using System.Runtime.InteropServices;
using Xunit; using Xunit;
using FluentAssertions; using FluentAssertions;
@ -13,10 +14,12 @@ namespace Microsoft.DotNet.Tests
public class PackagedCommandTests : TestBase public class PackagedCommandTests : TestBase
{ {
private readonly string _testProjectsRoot; private readonly string _testProjectsRoot;
private readonly string _desktopTestProjectsRoot;
public PackagedCommandTests() public PackagedCommandTests()
{ {
_testProjectsRoot = Path.Combine(AppContext.BaseDirectory, "TestAssets", "TestProjects"); _testProjectsRoot = Path.Combine(AppContext.BaseDirectory, "TestAssets", "TestProjects");
_desktopTestProjectsRoot = Path.Combine(AppContext.BaseDirectory, "TestAssets", "DesktopTestProjects");
} }
[Theory] [Theory]
@ -31,21 +34,39 @@ namespace Microsoft.DotNet.Tests
.Should() .Should()
.Pass(); .Pass();
var currentDirectory = Directory.GetCurrentDirectory(); CommandResult result = new PortableCommand { WorkingDirectory = appDirectory }
Directory.SetCurrentDirectory(appDirectory); .ExecuteWithCapturedOutput();
try result.Should().HaveStdOut("Hello Portable World!" + Environment.NewLine);
result.Should().NotHaveStdErr();
result.Should().Pass();
}
// need conditional theories so we can skip on non-Windows
[Theory]
[InlineData(".NETStandardApp,Version=v1.5", "CoreFX")]
[InlineData(".NETFramework,Version=v4.5.1", "NetFX")]
public void TestFrameworkSpecificDependencyToolsCanBeInvoked(string framework, string args)
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
CommandResult result = new PortableCommand().ExecuteWithCapturedOutput(); return;
}
var appDirectory = Path.Combine(_desktopTestProjectsRoot, "AppWithDirectDependencyDesktopAndPortable");
result.Should().HaveStdOut("Hello Portable World!" + Environment.NewLine); new BuildCommand(Path.Combine(appDirectory, "project.json"))
.Execute()
.Should()
.Pass();
CommandResult result = new DependencyToolInvokerCommand { WorkingDirectory = appDirectory }
.ExecuteWithCapturedOutput(framework, args);
result.Should().HaveStdOutContaining(framework);
result.Should().HaveStdOutContaining(args);
result.Should().NotHaveStdErr(); result.Should().NotHaveStdErr();
result.Should().Pass(); result.Should().Pass();
}
finally
{
Directory.SetCurrentDirectory(currentDirectory);
}
} }
[Fact] [Fact]
@ -114,5 +135,25 @@ namespace Microsoft.DotNet.Tests
return base.ExecuteWithCapturedOutput(args); return base.ExecuteWithCapturedOutput(args);
} }
} }
class DependencyToolInvokerCommand : TestCommand
{
public DependencyToolInvokerCommand()
: base("dotnet")
{
}
public CommandResult Execute(string framework, string additionalArgs)
{
var args = $"dependency-tool-invoker desktop-and-portable --framework {framework} {additionalArgs}";
return base.Execute(args);
}
public CommandResult ExecuteWithCapturedOutput(string framework, string additionalArgs)
{
var args = $"dependency-tool-invoker desktop-and-portable --framework {framework} {additionalArgs}";
return base.ExecuteWithCapturedOutput(args);
}
}
} }
} }

View file

@ -24,7 +24,8 @@
"content": [ "content": [
"../../TestAssets/TestProjects/AppWithDirectAndToolDependency/**/*", "../../TestAssets/TestProjects/AppWithDirectAndToolDependency/**/*",
"../../TestAssets/TestProjects/AppWithDirectDependency/**/*", "../../TestAssets/TestProjects/AppWithDirectDependency/**/*",
"../../TestAssets/TestProjects/AppWithToolDependency/**/*" "../../TestAssets/TestProjects/AppWithToolDependency/**/*",
"../../TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/**/*"
], ],
"testRunner": "xunit" "testRunner": "xunit"
} }

View file

@ -10,7 +10,7 @@
"System.Runtime.Serialization.Json": "4.0.2-rc2-23928", "System.Runtime.Serialization.Json": "4.0.2-rc2-23928",
"Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.ProjectModel": "1.0.0-*",
"Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*",
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100",
"Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-23928", "Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-23928",
"NETStandard.Library": "1.5.0-rc2-23928" "NETStandard.Library": "1.5.0-rc2-23928"
}, },