diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln index 6fd724e43..8ca363601 100644 --- a/Microsoft.DotNet.Cli.sln +++ b/Microsoft.DotNet.Cli.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.25029.0 +VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{ED2FE3E2-F7E7-4389-8231-B65123F2076F}" EndProject @@ -95,6 +95,12 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.Extensions.Testin 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}" 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 GlobalSection(SolutionConfigurationPlatforms) = preSolution 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|x64.ActiveCfg = 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 GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -727,5 +749,8 @@ Global {7B0EFBB4-4669-4B83-B47C-7F3E6DB07AF9} = {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} + {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 EndGlobal diff --git a/TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/Program.cs b/TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/Program.cs new file mode 100644 index 000000000..51233cffa --- /dev/null +++ b/TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace ConsoleApplication +{ + public class Program + { + public static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/project.json b/TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/project.json new file mode 100644 index 000000000..d07947c6b --- /dev/null +++ b/TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/project.json @@ -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" + ] + } + } +} diff --git a/TestAssets/TestPackages/dotnet-dependency-tool-invoker/DotnetBaseParams.cs b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/DotnetBaseParams.cs new file mode 100644 index 000000000..5e092fdef --- /dev/null +++ b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/DotnetBaseParams.cs @@ -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 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 under which to build", + CommandOptionType.SingleValue); + _outputOption = _app.Option( + "-o|--output ", + "Directory in which to find the binaries to be run", + CommandOptionType.SingleValue); + _buildBasePath = _app.Option( + "-b|--build-base-path ", + "Directory in which to find temporary outputs", + CommandOptionType.SingleValue); + _frameworkOption = _app.Option( + "-f|--framework ", + "Looks for test binaries for a specific framework", + CommandOptionType.SingleValue); + _runtimeOption = _app.Option( + "-r|--runtime ", + "Look for test binaries for a for the specified runtime", + CommandOptionType.SingleValue); + _projectPath = _app.Option( + "-p|--project-path ", + "Path to Project.json that contains the tool dependency", + CommandOptionType.SingleValue); + _command = _app.Argument( + "", + "The command to execute."); + } + } +} diff --git a/TestAssets/TestPackages/dotnet-dependency-tool-invoker/NuGet.Config b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/NuGet.Config new file mode 100644 index 000000000..e80222c1f --- /dev/null +++ b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/NuGet.Config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/TestAssets/TestPackages/dotnet-dependency-tool-invoker/Program.cs b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/Program.cs new file mode 100644 index 000000000..8ba883d6e --- /dev/null +++ b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/Program.cs @@ -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 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); + } + } +} diff --git a/TestAssets/TestPackages/dotnet-dependency-tool-invoker/dotnet-dependency-tool-invoker.xproj b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/dotnet-dependency-tool-invoker.xproj new file mode 100644 index 000000000..7811e7531 --- /dev/null +++ b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/dotnet-dependency-tool-invoker.xproj @@ -0,0 +1,19 @@ + + + + 14.0.23107 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + c26a48bb-193f-450c-ab09-4d3324c78188 + dotnet-dependency-tool-invoker + ..\..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/TestAssets/TestPackages/dotnet-dependency-tool-invoker/project.json b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/project.json new file mode 100644 index 000000000..95029451b --- /dev/null +++ b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/project.json @@ -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" + ] + } + } +} diff --git a/TestAssets/TestPackages/dotnet-desktop-and-portable/NuGet.Config b/TestAssets/TestPackages/dotnet-desktop-and-portable/NuGet.Config new file mode 100644 index 000000000..e80222c1f --- /dev/null +++ b/TestAssets/TestPackages/dotnet-desktop-and-portable/NuGet.Config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/TestAssets/TestPackages/dotnet-desktop-and-portable/Program.cs b/TestAssets/TestPackages/dotnet-desktop-and-portable/Program.cs new file mode 100644 index 000000000..de299bfc4 --- /dev/null +++ b/TestAssets/TestPackages/dotnet-desktop-and-portable/Program.cs @@ -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 + } + } +} diff --git a/TestAssets/TestPackages/dotnet-desktop-and-portable/project.json b/TestAssets/TestPackages/dotnet-desktop-and-portable/project.json new file mode 100644 index 000000000..011f32ca8 --- /dev/null +++ b/TestAssets/TestPackages/dotnet-desktop-and-portable/project.json @@ -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": {} + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json b/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json index c77008eb2..ade3068b3 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json @@ -3,7 +3,7 @@ "dependencies": { "NETStandard.Library": "1.5.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": { "netstandard1.3": { diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs index b7c993a78..990cc77da 100644 --- a/scripts/dotnet-cli-build/TestTargets.cs +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -13,11 +13,19 @@ namespace Microsoft.DotNet.Cli.Build { public class TestTargets { - public static readonly string[] TestPackageProjects = new[] + public static readonly dynamic[] TestPackageProjects = new[] { - "dotnet-hello/v1/dotnet-hello", - "dotnet-hello/v2/dotnet-hello", - "dotnet-portable" + new { Name = "Microsoft.DotNet.Cli.Utils", IsTool = false, Path = "src/Microsoft.DotNet.Cli.Utils", IsApplicable = new Func(() => CurrentPlatform.IsWindows) }, + new { Name = "Microsoft.DotNet.ProjectModel", IsTool = false, Path = "src/Microsoft.DotNet.ProjectModel", IsApplicable = new Func(() => CurrentPlatform.IsWindows) }, + new { Name = "Microsoft.DotNet.Compiler.Common", IsTool = false, Path = "src/Microsoft.DotNet.Compiler.Common", IsApplicable = new Func(() => CurrentPlatform.IsWindows) }, + new { Name = "Microsoft.Extensions.DependencyModel", IsTool = false, Path = "src/Microsoft.Extensions.DependencyModel", IsApplicable = new Func(() => CurrentPlatform.IsWindows) }, + new { Name = "Microsoft.DotNet.Files", IsTool = false, Path = "src/Microsoft.DotNet.Files", IsApplicable = new Func(() => CurrentPlatform.IsWindows) }, + new { Name = "Microsoft.DotNet.InternalAbstractions", IsTool = false, Path = "src/Microsoft.DotNet.InternalAbstractions", IsApplicable = new Func(() => CurrentPlatform.IsWindows) }, + new { Name = "dotnet-dependency-tool-invoker", IsTool = true, Path = "TestAssets/TestPackages/dotnet-dependency-tool-invoker", IsApplicable = new Func(() => CurrentPlatform.IsWindows) }, + new { Name = "dotnet-desktop-and-portable", IsTool = true, Path = "TestAssets/TestPackages/dotnet-desktop-and-portable", IsApplicable = new Func(() => CurrentPlatform.IsWindows) }, + new { Name = "dotnet-hello", IsTool = true, Path = "TestAssets/TestPackages/dotnet-hello/v1/dotnet-hello", IsApplicable = new Func(() => true) }, + new { Name = "dotnet-hello", IsTool = true, Path = "TestAssets/TestPackages/dotnet-hello/v2/dotnet-hello", IsApplicable = new Func(() => true) }, + new { Name = "dotnet-portable", IsTool = true, Path = "TestAssets/TestPackages/dotnet-portable", IsApplicable = new Func(() => true) } }; public static readonly string[] TestProjects = new[] @@ -40,6 +48,11 @@ namespace Microsoft.DotNet.Cli.Build "dotnet-test.UnitTests", "dotnet-test.Tests" }; + + public static readonly dynamic[] ConditionalTestAssets = new[] + { + new { Path = "AppWithDirectDependencyDesktopAndPortable", Skip = new Func(() => !CurrentPlatform.IsWindows) } + }; [Target(nameof(PrepareTargets.Init), nameof(SetupTests), nameof(RestoreTests), nameof(BuildTests), nameof(RunTests), nameof(ValidateDependencies))] public static BuildTargetResult Test(BuildTargetContext c) => c.Success(); @@ -50,7 +63,7 @@ namespace Microsoft.DotNet.Cli.Build [Target(nameof(RestoreTestAssetPackages), nameof(BuildTestAssetPackages))] 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(); [Target] @@ -93,6 +106,19 @@ namespace Microsoft.DotNet.Cli.Build 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))] public static BuildTargetResult BuildTestAssetPackages(BuildTargetContext c) { @@ -103,9 +129,9 @@ namespace Microsoft.DotNet.Cli.Build Rmdir(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}"); dotnet.Pack("--output", Dirs.TestPackages) .WorkingDirectory(fullPath) @@ -119,9 +145,14 @@ namespace Microsoft.DotNet.Cli.Build [Target] public static BuildTargetResult CleanTestPackages(BuildTargetContext c) { - Rmdir(Path.Combine(Dirs.NuGetPackages, "dotnet-hello")); - Rmdir(Path.Combine(Dirs.NuGetPackages, "dotnet-portable")); - Rmdir(Path.Combine(Dirs.NuGetPackages, ".tools", "dotnet-portable")); + foreach (var packageProject in TestPackageProjects.Where(p => p.IsApplicable())) + { + Rmdir(Path.Combine(Dirs.NuGetPackages, packageProject.Name)); + if(packageProject.IsTool) + { + Rmdir(Path.Combine(Dirs.NuGetPackages, ".tools", packageProject.Name)); + } + } return c.Success(); } @@ -135,6 +166,7 @@ namespace Microsoft.DotNet.Cli.Build var nobuildFileName = ".noautobuild"; string testProjectsRoot = Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects"); 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))); foreach (var project in projects) diff --git a/scripts/dotnet-cli-build/project.json b/scripts/dotnet-cli-build/project.json index 5bf907371..50dad3d04 100755 --- a/scripts/dotnet-cli-build/project.json +++ b/scripts/dotnet-cli-build/project.json @@ -5,12 +5,14 @@ "emitEntryPoint": true }, "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.Xml.XmlSerializer": "4.0.11-rc2-23928", - "Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*", - "WindowsAzure.Storage": "6.2.2-preview", - "System.Reflection.Metadata": "1.3.0-rc2-23928" + "WindowsAzure.Storage": "6.2.2-preview" }, "frameworks": { "netstandardapp1.5": { diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs index 626dcf9cc..61990262f 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/IPackagedCommandSpecFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.DotNet.Cli.Utils public interface IPackagedCommandSpecFactory { CommandSpec CreateCommandSpecFromLibrary( - LockFilePackageLibrary library, + LockFileTargetLibrary toolLibrary, string commandName, IEnumerable commandArguments, IEnumerable allowedExtensions, diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs index 8b3ff0ca3..c07f75e65 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/PackagedCommandSpecFactory.cs @@ -2,12 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Graph; -using Microsoft.DotNet.ProjectModel.Compilation; -using Microsoft.Extensions.PlatformAbstractions; -using NuGet.Frameworks; using NuGet.Packaging; namespace Microsoft.DotNet.Cli.Utils @@ -15,7 +11,7 @@ namespace Microsoft.DotNet.Cli.Utils public class PackagedCommandSpecFactory : IPackagedCommandSpecFactory { public CommandSpec CreateCommandSpecFromLibrary( - LockFilePackageLibrary library, + LockFileTargetLibrary toolLibrary, string commandName, IEnumerable commandArguments, IEnumerable allowedExtensions, @@ -23,25 +19,25 @@ namespace Microsoft.DotNet.Cli.Utils CommandResolutionStrategy commandResolutionStrategy, 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; } - var commandFile = GetCommandFileRelativePath(library, commandName, allowedExtensions); + var isPortable = IsPortableApp(commandPath); - if (commandFile == null) - { - return null; - } - - var commandPath = Path.Combine(packageDirectory, commandFile); - - var isPortable = DetermineIfPortableApp(commandPath); - - return CreateCommandSpecWrappingWithCorehostfDll( + return CreateCommandSpecWrappingWithCorehostIfDll( commandPath, commandArguments, depsFilePath, @@ -50,27 +46,17 @@ namespace Microsoft.DotNet.Cli.Utils isPortable); } - private string GetPackageDirectoryFullPath(LockFilePackageLibrary library, string nugetPackagesRoot) + private string GetCommandFilePath(string nugetPackagesRoot, LockFileTargetLibrary toolLibrary, LockFileItem runtimeAssembly) { 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( - LockFilePackageLibrary library, - string commandName, - IEnumerable 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( + private CommandSpec CreateCommandSpecWrappingWithCorehostIfDll( string commandPath, IEnumerable commandArguments, string depsFilePath, @@ -102,7 +88,7 @@ namespace Microsoft.DotNet.Cli.Utils string nugetPackagesRoot, bool isPortable) { - string host = string.Empty; + var host = string.Empty; var arguments = new List(); if (isPortable) @@ -148,7 +134,7 @@ namespace Microsoft.DotNet.Cli.Utils return new CommandSpec(commandPath, escapedArgs, commandResolutionStrategy); } - private bool DetermineIfPortableApp(string commandPath) + private bool IsPortableApp(string commandPath) { var commandDir = Path.GetDirectoryName(commandPath); diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs index ac2e93891..921561690 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectDependenciesCommandResolver.cs @@ -2,12 +2,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.Extensions.PlatformAbstractions; using NuGet.Frameworks; -using NuGet.Packaging; namespace Microsoft.DotNet.Cli.Utils { @@ -16,8 +14,8 @@ namespace Microsoft.DotNet.Cli.Utils private static readonly CommandResolutionStrategy s_commandResolutionStrategy = CommandResolutionStrategy.ProjectDependenciesPackage; - private IEnvironmentProvider _environment; - private IPackagedCommandSpecFactory _packagedCommandSpecFactory; + private readonly IEnvironmentProvider _environment; + private readonly IPackagedCommandSpecFactory _packagedCommandSpecFactory; public ProjectDependenciesCommandResolver( IEnvironmentProvider environment, @@ -80,10 +78,10 @@ namespace Microsoft.DotNet.Cli.Utils var depsFilePath = projectContext.GetOutputPaths(configuration, buildBasePath, outputPath).RuntimeFiles.DepsJson; - var dependencyLibraries = GetAllDependencyLibraries(projectContext); + var toolLibrary = GetToolLibraryForContext(projectContext, commandName); - return ResolveFromDependencyLibraries( - dependencyLibraries, + return ResolveFromDependencyLibrary( + toolLibrary, depsFilePath, commandName, allowedExtensions, @@ -91,35 +89,8 @@ namespace Microsoft.DotNet.Cli.Utils projectContext); } - private CommandSpec ResolveFromDependencyLibraries( - IEnumerable dependencyLibraries, - string depsFilePath, - string commandName, - IEnumerable allowedExtensions, - IEnumerable 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( - LockFilePackageLibrary dependencyLibrary, + LockFileTargetLibrary toolLibrary, string depsFilePath, string commandName, IEnumerable allowedExtensions, @@ -127,7 +98,7 @@ namespace Microsoft.DotNet.Cli.Utils ProjectContext projectContext) { return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( - dependencyLibrary, + toolLibrary, commandName, commandArguments, allowedExtensions, @@ -136,13 +107,15 @@ namespace Microsoft.DotNet.Cli.Utils depsFilePath); } - private IEnumerable GetAllDependencyLibraries( - ProjectContext projectContext) + private LockFileTargetLibrary GetToolLibraryForContext( + ProjectContext projectContext, string commandName) { - return projectContext.LibraryManager.GetLibraries() - .Where(l => l.GetType() == typeof(PackageDescription)) - .Select(l => l as PackageDescription) - .Select(p => p.Library); + var toolLibrary = projectContext.LockFile.Targets + .FirstOrDefault(t => t.TargetFramework.GetShortFolderName() + .Equals(projectContext.TargetFramework.GetShortFolderName())) + ?.Libraries.FirstOrDefault(l => l.Name == commandName); + + return toolLibrary; } private ProjectContext GetProjectContextFromDirectory(string directory, NuGetFramework framework) diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs index 6fb25415a..fa3bb8e04 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolution/ProjectToolsCommandResolver.cs @@ -95,28 +95,29 @@ namespace Microsoft.DotNet.Cli.Utils } private CommandSpec ResolveCommandSpecFromToolLibrary( - LibraryRange toolLibrary, + LibraryRange toolLibraryRange, string commandName, IEnumerable args, ProjectContext projectContext) { var nugetPackagesRoot = projectContext.PackagesDirectory; + + var lockFile = GetToolLockFile(toolLibraryRange, nugetPackagesRoot); - var lockFile = GetToolLockFile(toolLibrary, nugetPackagesRoot); - var lockFilePackageLibrary = lockFile.PackageLibraries.FirstOrDefault(l => l.Name == toolLibrary.Name); + var toolLibrary = lockFile.Targets + .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 depsFilePath = GetToolDepsFilePath(toolLibrary, lockFile, depsFileRoot); - - var toolProjectContext = new ProjectContextBuilder() - .WithLockFile(lockFile) - .WithTargetFramework(s_toolPackageFramework.ToString()) - .Build(); - - var exporter = toolProjectContext.CreateExporter(Constants.DefaultConfiguration); - + var depsFilePath = GetToolDepsFilePath(toolLibraryRange, lockFile, depsFileRoot); + return _packagedCommandSpecFactory.CreateCommandSpecFromLibrary( - lockFilePackageLibrary, + toolLibrary, commandName, args, _allowedCommandExtensions, diff --git a/src/Microsoft.DotNet.Cli.Utils/project.json b/src/Microsoft.DotNet.Cli.Utils/project.json index d16f7da20..21d7460b5 100644 --- a/src/Microsoft.DotNet.Cli.Utils/project.json +++ b/src/Microsoft.DotNet.Cli.Utils/project.json @@ -6,7 +6,7 @@ }, "dependencies": { "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.Packaging": "3.5.0-beta-1083", "NuGet.Frameworks": "3.5.0-beta-1083", diff --git a/src/Microsoft.DotNet.InternalAbstractions/project.json b/src/Microsoft.DotNet.InternalAbstractions/project.json index df1d0d126..e529be150 100644 --- a/src/Microsoft.DotNet.InternalAbstractions/project.json +++ b/src/Microsoft.DotNet.InternalAbstractions/project.json @@ -10,7 +10,7 @@ "keyFile": "../../tools/Key.snk" }, "dependencies": { - "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100" }, "frameworks": { "net451": {}, diff --git a/src/Microsoft.Extensions.DependencyModel/project.json b/src/Microsoft.Extensions.DependencyModel/project.json index fd658e49a..b1fb858ee 100644 --- a/src/Microsoft.Extensions.DependencyModel/project.json +++ b/src/Microsoft.Extensions.DependencyModel/project.json @@ -19,7 +19,7 @@ "version": "1.0.0-*" }, "Newtonsoft.Json": "7.0.1", - "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100" }, "frameworks": { "net451": {}, diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs index df8b1fa8d..2296af394 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs @@ -13,6 +13,8 @@ namespace Microsoft.DotNet.Tools.Test.Utilities { protected string _command; + public string WorkingDirectory { get; set; } + public Dictionary Environment { get; } = new Dictionary(); public TestCommand(string command) @@ -53,7 +55,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities return RunProcess(commandPath, args, stdOut, stdErr); } - + private void ResolveCommand(ref string executable, ref string args) { if (executable.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) @@ -89,9 +91,14 @@ namespace Microsoft.DotNet.Tools.Test.Utilities psi.Environment[item.Key] = item.Value; } + if (!string.IsNullOrWhiteSpace(WorkingDirectory)) + { + psi.WorkingDirectory = WorkingDirectory; + } + var process = new Process { - StartInfo = psi, + StartInfo = psi }; process.EnableRaisingEvents = true; diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json index 056bca1c7..f6a90f095 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/project.json @@ -14,7 +14,7 @@ "Microsoft.DotNet.TestFramework": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "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": { "target": "project", "version": "1.0.0-*" diff --git a/test/dotnet.Tests/PackagedCommandTests.cs b/test/dotnet.Tests/PackagedCommandTests.cs index 7b4a91b28..3fee9f023 100644 --- a/test/dotnet.Tests/PackagedCommandTests.cs +++ b/test/dotnet.Tests/PackagedCommandTests.cs @@ -5,6 +5,7 @@ using System; using System.IO; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools.Test.Utilities; +using System.Runtime.InteropServices; using Xunit; using FluentAssertions; @@ -13,10 +14,12 @@ namespace Microsoft.DotNet.Tests public class PackagedCommandTests : TestBase { private readonly string _testProjectsRoot; + private readonly string _desktopTestProjectsRoot; public PackagedCommandTests() { _testProjectsRoot = Path.Combine(AppContext.BaseDirectory, "TestAssets", "TestProjects"); + _desktopTestProjectsRoot = Path.Combine(AppContext.BaseDirectory, "TestAssets", "DesktopTestProjects"); } [Theory] @@ -31,21 +34,39 @@ namespace Microsoft.DotNet.Tests .Should() .Pass(); - var currentDirectory = Directory.GetCurrentDirectory(); - Directory.SetCurrentDirectory(appDirectory); + CommandResult result = new PortableCommand { WorkingDirectory = 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().Pass(); - } - finally - { - Directory.SetCurrentDirectory(currentDirectory); - } } [Fact] @@ -114,5 +135,25 @@ namespace Microsoft.DotNet.Tests 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); + } + } } } diff --git a/test/dotnet.Tests/project.json b/test/dotnet.Tests/project.json index bd660ae76..ffe169ac1 100644 --- a/test/dotnet.Tests/project.json +++ b/test/dotnet.Tests/project.json @@ -24,7 +24,8 @@ "content": [ "../../TestAssets/TestProjects/AppWithDirectAndToolDependency/**/*", "../../TestAssets/TestProjects/AppWithDirectDependency/**/*", - "../../TestAssets/TestProjects/AppWithToolDependency/**/*" + "../../TestAssets/TestProjects/AppWithToolDependency/**/*", + "../../TestAssets/DesktopTestProjects/AppWithDirectDependencyDesktopAndPortable/**/*" ], "testRunner": "xunit" } diff --git a/tools/RuntimeGraphGenerator/project.json b/tools/RuntimeGraphGenerator/project.json index a95979daa..efdb944b8 100644 --- a/tools/RuntimeGraphGenerator/project.json +++ b/tools/RuntimeGraphGenerator/project.json @@ -10,7 +10,7 @@ "System.Runtime.Serialization.Json": "4.0.2-rc2-23928", "Microsoft.DotNet.ProjectModel": "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", "NETStandard.Library": "1.5.0-rc2-23928" },