Handle "runtimes" section (#4503)

* Migrate "runtimes" section as a RuntimeIdentifiers property in the resulting csproj file. Also do not call restore3 from publish3 anymore.

* Fix up the publish3 tests to call restore3 first and the csproj files to have RuntimeIdentifiers
This commit is contained in:
Justin Goshi 2016-10-26 22:23:40 +00:00 committed by GitHub
parent 4aa1c1bfb4
commit 68afda8e4d
10 changed files with 183 additions and 37 deletions

View file

@ -4,6 +4,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.0</TargetFramework> <TargetFramework>netcoreapp1.0</TargetFramework>
<RuntimeIdentifiers>win7-x64;win7-x86;osx.10.10-x64;osx.10.11-x64;ubuntu.14.04-x64;ubuntu.16.04-x64;centos.7-x64;rhel.7.2-x64;debian.8-x64;fedora.23-x64;opensuse.13.2-x64</RuntimeIdentifiers>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View file

@ -16,6 +16,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
new MigrateJsonPropertiesRule(), new MigrateJsonPropertiesRule(),
new MigratePackOptionsRule(), new MigratePackOptionsRule(),
new MigrateRuntimeOptionsRule(), new MigrateRuntimeOptionsRule(),
new MigrateRuntimesRule(),
new MigratePublishOptionsRule(), new MigratePublishOptionsRule(),
new MigrateProjectDependenciesRule(), new MigrateProjectDependenciesRule(),
new MigratePackageDependenciesAndToolsRule(), new MigratePackageDependenciesAndToolsRule(),

View file

@ -0,0 +1,35 @@
// 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 Microsoft.DotNet.ProjectJsonMigration.Transforms;
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
{
public class MigrateRuntimesRule : IMigrationRule
{
AddPropertyTransform<IList<string>> RuntimeIdentifiersTransform =>
new AddPropertyTransform<IList<string>>(
"RuntimeIdentifiers",
l => String.Join(";", l),
l => l.Count > 0);
private readonly ITransformApplicator _transformApplicator;
public MigrateRuntimesRule(ITransformApplicator transformApplicator = null)
{
_transformApplicator = transformApplicator ?? new TransformApplicator();
}
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
var propertyGroup = migrationRuleInputs.CommonPropertyGroup;
_transformApplicator.Execute(
RuntimeIdentifiersTransform.Transform(migrationRuleInputs.DefaultProjectContext.ProjectFile.Runtimes),
propertyGroup,
mergeExisting: true);
}
}
}

View file

@ -71,6 +71,8 @@ namespace Microsoft.DotNet.ProjectModel
public RuntimeOptions RuntimeOptions { get; set; } public RuntimeOptions RuntimeOptions { get; set; }
public IList<string> Runtimes { get; set; }
public IDictionary<string, string> Commands { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); public IDictionary<string, string> Commands { get; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public IDictionary<string, IEnumerable<string>> Scripts { get; } = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase); public IDictionary<string, IEnumerable<string>> Scripts { get; } = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase);

View file

@ -159,6 +159,7 @@ namespace Microsoft.DotNet.ProjectModel
project.Dependencies = new List<ProjectLibraryDependency>(); project.Dependencies = new List<ProjectLibraryDependency>();
project.Tools = new List<ProjectLibraryDependency>(); project.Tools = new List<ProjectLibraryDependency>();
project.Runtimes = new List<string>();
// Project files // Project files
project.Files = new ProjectFilesCollection(rawProject, project.ProjectDirectory, project.ProjectFilePath); project.Files = new ProjectFilesCollection(rawProject, project.ProjectDirectory, project.ProjectFilePath);
@ -224,6 +225,8 @@ namespace Microsoft.DotNet.ProjectModel
"tools", "tools",
isGacOrFrameworkReference: false); isGacOrFrameworkReference: false);
PopulateRuntimes(project.Runtimes, rawProject);
JToken runtimeOptionsToken; JToken runtimeOptionsToken;
if (rawProject.TryGetValue("runtimeOptions", out runtimeOptionsToken)) if (rawProject.TryGetValue("runtimeOptions", out runtimeOptionsToken))
{ {
@ -370,6 +373,21 @@ namespace Microsoft.DotNet.ProjectModel
} }
} }
private static void PopulateRuntimes(IList<string> results, JObject settings)
{
var runtimes = settings.Value<JToken>("runtimes") as JObject;
if (runtimes != null)
{
foreach (var runtime in runtimes)
{
if (!string.IsNullOrEmpty(runtime.Key))
{
results.Add(runtime.Key);
}
}
}
}
private void BuildTargetFrameworksAndConfigurations(Project project, JObject projectJsonObject) private void BuildTargetFrameworksAndConfigurations(Project project, JObject projectJsonObject)
{ {
// Get the shared compilationOptions // Get the shared compilationOptions

View file

@ -25,12 +25,6 @@ namespace Microsoft.DotNet.Tools.Publish3
public int Execute() public int Execute()
{ {
int restoreResult = EnsureRestored();
if (restoreResult != 0)
{
throw new GracefulException("Restore failed. Please fix the errors and try publishing again.");
}
List<string> msbuildArgs = new List<string>(); List<string> msbuildArgs = new List<string>();
if (!string.IsNullOrEmpty(ProjectPath)) if (!string.IsNullOrEmpty(ProjectPath))
@ -70,19 +64,5 @@ namespace Microsoft.DotNet.Tools.Publish3
return new MSBuildForwardingApp(msbuildArgs).Execute(); return new MSBuildForwardingApp(msbuildArgs).Execute();
} }
/// <summary>
/// Ensures that the project has been restored for the specified runtime.
/// </summary>
private int EnsureRestored()
{
int result = 0;
if (!string.IsNullOrEmpty(Runtime))
{
result = Restore3Command.Run(new[] { $"/p:RuntimeIdentifiers={Runtime}" });
}
return result;
}
} }
} }

View file

@ -0,0 +1,79 @@
using Microsoft.Build.Construction;
using Microsoft.DotNet.ProjectJsonMigration;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.Tools.Test.Utilities;
using NuGet.Frameworks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using FluentAssertions;
using Microsoft.DotNet.ProjectJsonMigration.Rules;
namespace Microsoft.DotNet.ProjectJsonMigration.Tests
{
public class GivenThatIWantToMigrateRuntimes : TestBase
{
[Fact]
public void It_migrates_runtimes()
{
var projectJson = @"
{
""runtimes"": {
""win7-x64"": { },
""win7-x86"": { },
""osx.10.10-x64"": { }
}
}
";
var testDirectory = Temp.CreateDirectory().Path;
var migratedProj = TemporaryProjectFileRuleRunner.RunRules(new IMigrationRule[]
{
new MigrateRuntimesRule()
}, projectJson, testDirectory);
migratedProj.Properties.Count(p => p.Name == "RuntimeIdentifiers").Should().Be(1);
migratedProj.Properties.First(p => p.Name == "RuntimeIdentifiers").Value
.Should().Be("win7-x64;win7-x86;osx.10.10-x64");
}
[Fact]
public void It_has_an_empty_runtime_node_to_migrate()
{
var projectJson = @"
{
""runtimes"": {
}
}
";
var testDirectory = Temp.CreateDirectory().Path;
var migratedProj = TemporaryProjectFileRuleRunner.RunRules(new IMigrationRule[]
{
new MigrateRuntimesRule()
}, projectJson, testDirectory);
migratedProj.Properties.Count(p => p.Name == "RuntimeIdentifiers").Should().Be(0);
}
[Fact]
public void It_has_no_runtimes_to_migrate()
{
var projectJson = @"
{
}
";
var testDirectory = Temp.CreateDirectory().Path;
var migratedProj = TemporaryProjectFileRuleRunner.RunRules(new IMigrationRule[]
{
new MigrateRuntimesRule()
}, projectJson, testDirectory);
migratedProj.Properties.Count(p => p.Name == "RuntimeIdentifiers").Should().Be(0);
}
}
}

View file

@ -29,13 +29,13 @@ namespace Microsoft.DotNet.Tools.Test.Utilities
public override CommandResult Execute(string args = "") public override CommandResult Execute(string args = "")
{ {
args = $"publish3 {args} {BuildArgs()}"; args = $"publish3 {BuildArgs()} {args} ";
return base.Execute(args); return base.Execute(args);
} }
public override CommandResult ExecuteWithCapturedOutput(string args = "") public override CommandResult ExecuteWithCapturedOutput(string args = "")
{ {
args = $"publish3 {args} {BuildArgs()}"; args = $"publish3 {BuildArgs()} {args}";
return base.ExecuteWithCapturedOutput(args); return base.ExecuteWithCapturedOutput(args);
} }

View file

@ -10,8 +10,8 @@ using System.IO;
using Microsoft.DotNet.Tools.Migrate; using Microsoft.DotNet.Tools.Migrate;
using Build3Command = Microsoft.DotNet.Tools.Test.Utilities.Build3Command; using Build3Command = Microsoft.DotNet.Tools.Test.Utilities.Build3Command;
using BuildCommand = Microsoft.DotNet.Tools.Test.Utilities.BuildCommand; using BuildCommand = Microsoft.DotNet.Tools.Test.Utilities.BuildCommand;
using Publish3Command = Microsoft.DotNet.Tools.Test.Utilities.Publish3Command;
using System.Runtime.Loader; using System.Runtime.Loader;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace Microsoft.DotNet.Migration.Tests namespace Microsoft.DotNet.Migration.Tests
@ -346,6 +346,19 @@ namespace Microsoft.DotNet.Migration.Tests
result.StdErr.Should().Contain("Migration failed."); result.StdErr.Should().Contain("Migration failed.");
} }
[Fact]
public void It_migrates_and_publishes_projects_with_runtimes()
{
var projectName = "TestAppSimple";
var projectDirectory = TestAssetsManager.CreateTestInstance(projectName, callingMethod: "i")
.WithLockFiles()
.Path;
CleanBinObj(projectDirectory);
BuildProjectJsonMigrateBuildMSBuild(projectDirectory, projectName);
PublishMSBuild(projectDirectory, projectName, "win7-x64");
}
[WindowsOnlyTheory] [WindowsOnlyTheory]
[InlineData("DesktopTestProjects", "AutoAddDesktopReferencesDuringMigrate", true)] [InlineData("DesktopTestProjects", "AutoAddDesktopReferencesDuringMigrate", true)]
[InlineData("TestProjects", "TestAppSimple", false)] [InlineData("TestProjects", "TestAppSimple", false)]
@ -558,6 +571,25 @@ namespace Microsoft.DotNet.Migration.Tests
return result.StdOut; return result.StdOut;
} }
private string PublishMSBuild(string projectDirectory, string projectName, string runtime, string configuration = "Debug")
{
if (projectName != null)
{
projectName = projectName + ".csproj";
}
DeleteXproj(projectDirectory);
var result = new Publish3Command()
.WithRuntime(runtime)
.WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput($"{projectName} /p:Configuration={configuration}");
result.Should().Pass();
return result.StdOut;
}
private void DeleteXproj(string projectDirectory) private void DeleteXproj(string projectDirectory)
{ {
var xprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj"); var xprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj");

View file

@ -25,24 +25,20 @@ namespace Microsoft.DotNet.Cli.Publish3.Tests
new Restore3Command() new Restore3Command()
.WithWorkingDirectory(testProjectDirectory) .WithWorkingDirectory(testProjectDirectory)
.Execute() .Execute()
.Should() .Should().Pass();
.Pass();
new Publish3Command() new Publish3Command()
.WithWorkingDirectory(testProjectDirectory) .WithWorkingDirectory(testProjectDirectory)
.Execute("--framework netcoreapp1.0") .Execute("--framework netcoreapp1.0")
.Should() .Should().Pass();
.Pass();
var configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug"; var configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug";
var outputDll = Path.Combine(testProjectDirectory, "bin", configuration, "netcoreapp1.0", "publish", $"{testAppName}.dll"); var outputDll = Path.Combine(testProjectDirectory, "bin", configuration, "netcoreapp1.0", "publish", $"{testAppName}.dll");
new TestCommand("dotnet") new TestCommand("dotnet")
.ExecuteWithCapturedOutput(outputDll) .ExecuteWithCapturedOutput(outputDll)
.Should() .Should().Pass()
.Pass() .And.HaveStdOutContaining("Hello World");
.And
.HaveStdOutContaining("Hello World");
} }
[Fact] [Fact]
@ -55,23 +51,25 @@ namespace Microsoft.DotNet.Cli.Publish3.Tests
var testProjectDirectory = testInstance.TestRoot; var testProjectDirectory = testInstance.TestRoot;
var rid = DotnetLegacyRuntimeIdentifiers.InferLegacyRestoreRuntimeIdentifier(); var rid = DotnetLegacyRuntimeIdentifiers.InferLegacyRestoreRuntimeIdentifier();
new Restore3Command()
.WithWorkingDirectory(testProjectDirectory)
.Execute()
.Should().Pass();
new Publish3Command() new Publish3Command()
.WithFramework("netcoreapp1.0") .WithFramework("netcoreapp1.0")
.WithRuntime(rid) .WithRuntime(rid)
.WithWorkingDirectory(testProjectDirectory) .WithWorkingDirectory(testProjectDirectory)
.Execute() .Execute()
.Should() .Should().Pass();
.Pass();
var configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug"; var configuration = Environment.GetEnvironmentVariable("CONFIGURATION") ?? "Debug";
var outputProgram = Path.Combine(testProjectDirectory, "bin", configuration, "netcoreapp1.0", rid, "publish", $"{testAppName}{Constants.ExeSuffix}"); var outputProgram = Path.Combine(testProjectDirectory, "bin", configuration, "netcoreapp1.0", rid, "publish", $"{testAppName}{Constants.ExeSuffix}");
new TestCommand(outputProgram) new TestCommand(outputProgram)
.ExecuteWithCapturedOutput() .ExecuteWithCapturedOutput()
.Should() .Should().Pass()
.Pass() .And.HaveStdOutContaining("Hello World");
.And
.HaveStdOutContaining("Hello World");
} }
} }
} }