From e95773672116fcc987148f467111eaff000ce4b1 Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 18 Mar 2016 14:36:50 -0700 Subject: [PATCH 01/11] Don't use PowerShell to download WiX - Don't use PowerShell to download WiX, instead just use HttpClient. - Rehome WiX on our Azure blob storage, not only does this remove an dependency of our build, it also fixes an issue where CodePlex 302's from HTTPS to HTTP which HttpClient doesn't like. - Bake version numbers into paths, to help in cases where we upgrade WiX tool versions but the artifacts folder is not cleaned between builds. --- scripts/dotnet-cli-build/MsiTargets.cs | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/scripts/dotnet-cli-build/MsiTargets.cs b/scripts/dotnet-cli-build/MsiTargets.cs index f71e868b0..4e7422be6 100644 --- a/scripts/dotnet-cli-build/MsiTargets.cs +++ b/scripts/dotnet-cli-build/MsiTargets.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; +using System.Net.Http; using System.Runtime.InteropServices; using Microsoft.DotNet.Cli.Build.Framework; using Microsoft.Extensions.PlatformAbstractions; @@ -14,11 +15,13 @@ namespace Microsoft.DotNet.Cli.Build { private const string ENGINE = "engine.exe"; + private const string WixVersion = "3.10.2"; + private static string WixRoot { get { - return Path.Combine(Dirs.Output, "WixTools"); + return Path.Combine(Dirs.Output, $"WixTools.{WixVersion}"); } } @@ -52,14 +55,24 @@ namespace Microsoft.DotNet.Cli.Build Directory.CreateDirectory(WixRoot); c.Info("Downloading WixTools.."); - // Download Wix version 3.10.2 - https://wix.codeplex.com/releases/view/619491 - Cmd("powershell", "-NoProfile", "-NoLogo", - $"Invoke-WebRequest -Uri https://wix.codeplex.com/downloads/get/1540241 -Method Get -OutFile {WixRoot}\\WixTools.zip") - .Execute() - .EnsureSuccessful(); + + DownloadFile($"https://dotnetcli.blob.core.windows.net/build/wix/wix.{WixVersion}.zip", Path.Combine(WixRoot, "WixTools.zip")); c.Info("Extracting WixTools.."); - ZipFile.ExtractToDirectory($"{WixRoot}\\WixTools.zip", WixRoot); + ZipFile.ExtractToDirectory(Path.Combine(WixRoot, "WixTools.zip"), WixRoot); + } + + private static void DownloadFile(string uri, string destinationPath) + { + using (var httpClient = new HttpClient()) + { + var getTask = httpClient.GetStreamAsync(uri); + + using (var outStream = File.OpenWrite(destinationPath)) + { + getTask.Result.CopyTo(outStream); + } + } } [Target] From 9cec3e31521cc32128874149717d99f911313e30 Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Sun, 3 Apr 2016 19:29:23 -0700 Subject: [PATCH 02/11] Add two tests for project model server --- .../src/EmptyNetCoreApp/Program.cs | 13 ++ .../src/EmptyNetCoreApp/project.json | 15 +++ .../DthTests.cs | 118 ++++++++++++++++-- .../Helpers/JArrayExtensions.cs | 15 +++ 4 files changed, 153 insertions(+), 8 deletions(-) create mode 100644 TestAssets/ProjectModelServer/DthTestProjects/src/EmptyNetCoreApp/Program.cs create mode 100644 TestAssets/ProjectModelServer/DthTestProjects/src/EmptyNetCoreApp/project.json diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyNetCoreApp/Program.cs b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyNetCoreApp/Program.cs new file mode 100644 index 000000000..9e6dde0c3 --- /dev/null +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyNetCoreApp/Program.cs @@ -0,0 +1,13 @@ +using System; + +namespace Misc.DthTestProjects.SimpleConsoleApp +{ + public class Program + { + public int Main(string[] args) + { + Console.WriteLine("Hello, world."); + return 0; + } + } +} diff --git a/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyNetCoreApp/project.json b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyNetCoreApp/project.json new file mode 100644 index 000000000..3621ef882 --- /dev/null +++ b/TestAssets/ProjectModelServer/DthTestProjects/src/EmptyNetCoreApp/project.json @@ -0,0 +1,15 @@ +{ + "dependencies": {}, + "frameworks": { + "netcoreapp1.0": { + "imports": "dnxcore50", + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-23931" + }, + "Newtonsoft.Json": "8.0.3" + } + } + } +} \ No newline at end of file diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 92df20c70..878bf8acd 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -412,13 +412,13 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests } } } - + [Fact] public void MSBuildReferenceTest() { var testProject = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", - "MSBuildReferencesProjects", + "MSBuildReferencesProjects", "ValidCase01", "src", "MainApp"); @@ -428,12 +428,12 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests { client.Initialize(testProject); var messages = client.DrainAllMessages(); - + var classLibraries = new HashSet(new string[] { "ClassLibrary1", "ClassLibrary2", "ClassLibrary3" }); var dependencies = messages.RetrieveSingleMessage(MessageTypes.Dependencies); var testProjectRoot = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MSBuildReferencesProjects", "ValidCase01"); foreach (var classLibrary in classLibraries) - { + { dependencies.RetrieveDependency(classLibrary) .AssertProperty("Type", LibraryType.MSBuildProject.ToString()) .AssertProperty("Path", NormalizePathString(Path.Combine(testProjectRoot, classLibrary, $"{classLibrary}.csproj"))) @@ -442,21 +442,21 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests .AssertProperty("Errors", array => array.Count == 0) .AssertProperty("Warnings", array => array.Count == 0); } - + var references = messages.RetrieveSingleMessage(MessageTypes.References) .RetrievePayloadAs(); - + var projectReferences = references.RetrievePropertyAs("ProjectReferences"); Assert.Equal(3, projectReferences.Count); for (int i = 0; i < 3; ++i) { var projectRef = projectReferences.RetrieveArraryElementAs(i); var name = projectRef["Name"].Value(); - + Assert.True(classLibraries.Contains(name)); projectRef.AssertProperty("Path", NormalizePathString(Path.Combine(testProjectRoot, name, $"{name}.csproj"))); } - + var fileReferences = references.RetrievePropertyAs("FileReferences") .Select(each => each.Value()) .ToArray(); @@ -467,9 +467,111 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests } } + [Fact] + public void RemovePackageDependencyFromProjectJson() + { + // Remove a package dependency from project.json and then request refreshing dependency before + // restore. + + var appName = "EmptyNetCoreApp"; + var projectPath = _testAssetsManager.CreateTestInstance(appName) + .WithLockFiles() + .TestRoot; + + using (var server = new DthTestServer(_loggerFactory)) + using (var client = new DthTestClient(server, _loggerFactory)) + { + client.Initialize(projectPath); + + client.DrainAllMessages() + .AssertDoesNotContain(MessageTypes.Error) + .RetrieveSingleMessage(MessageTypes.Dependencies) + .RetrieveDependency(appName) + .RetrievePropertyAs("Dependencies") + .AssertJArrayCount(2); + + var projectFilePath = Path.Combine(projectPath, Project.FileName); + var projectJson = JsonConvert.DeserializeObject(File.ReadAllText(projectFilePath)); + + // Remove newtonsoft.json dependency + var dependencies = projectJson["frameworks"]["netcoreapp1.0"]["dependencies"] as JObject; + dependencies.Remove("Newtonsoft.Json"); + + File.WriteAllText(projectFilePath, JsonConvert.SerializeObject(projectJson)); + + client.SendPayLoad(projectPath, MessageTypes.RefreshDependencies); + + var afterDependencies = client.DrainTillFirst(MessageTypes.Dependencies); + afterDependencies.RetrieveDependency(appName) + .RetrievePropertyAs("Dependencies") + .AssertJArrayCount(1) + .RetrieveArraryElementAs(0) + .AssertProperty("Name", "Microsoft.NETCore.App"); + afterDependencies.RetrieveDependency("Newtonsoft.Json"); + } + } + + [Fact] + public void RemoveMSBuildDependencyFromProjectJson() + { + // Remove a msbuild project dependency from project.json and then request refreshing dependency before + // restore. + + var tam = new TestAssetsManager( + Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MSBuildReferencesProjects")); + + // var appName = "EmptyNetCoreApp"; + var projectPath = tam.CreateTestInstance("ValidCase01").WithLockFiles().TestRoot; + projectPath = Path.Combine(projectPath, "src", "MainApp"); + + using (var server = new DthTestServer(_loggerFactory)) + using (var client = new DthTestClient(server, _loggerFactory)) + { + client.Initialize(projectPath); + + client.DrainAllMessages() + .AssertDoesNotContain(MessageTypes.Error) + .RetrieveSingleMessage(MessageTypes.Dependencies) + .RetrieveDependency("MainApp") + .RetrievePropertyAs("Dependencies") + .AssertJArrayContains(dep => dep["Name"].Value() == "ClassLibrary1") + .AssertJArrayContains(dep => dep["Name"].Value() == "ClassLibrary2") + .AssertJArrayContains(dep => dep["Name"].Value() == "ClassLibrary3"); + + var projectFilePath = Path.Combine(projectPath, Project.FileName); + var projectJson = JsonConvert.DeserializeObject(File.ReadAllText(projectFilePath)); + + // Remove ClassLibrary2 and ClassLibrary3 dependency + var dependencies = projectJson["frameworks"]["net46"]["dependencies"] as JObject; + dependencies.Remove("ClassLibrary2"); + dependencies.Remove("ClassLibrary3"); + + File.WriteAllText(projectFilePath, JsonConvert.SerializeObject(projectJson)); + + client.SendPayLoad(projectPath, MessageTypes.RefreshDependencies); + + var afterDependencies = client.DrainTillFirst(MessageTypes.Dependencies); + afterDependencies.RetrieveDependency("MainApp") + .RetrievePropertyAs("Dependencies") + .AssertJArrayNotContains(dep => dep["Name"].Value() == "ClassLibrary2") + .AssertJArrayNotContains(dep => dep["Name"].Value() == "ClassLibrary3"); + + afterDependencies.RetrieveDependency("ClassLibrary2"); + afterDependencies.RetrieveDependency("ClassLibrary3"); + } + } + private static string NormalizePathString(string original) { return original.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); } + + private static void PrintAllMessages(IEnumerable messages) + { + foreach (var message in messages) + { + Console.WriteLine($"{message.MessageType} => {message.Payload.ToString()}"); + } + } } } diff --git a/test/dotnet-projectmodel-server.Tests/Helpers/JArrayExtensions.cs b/test/dotnet-projectmodel-server.Tests/Helpers/JArrayExtensions.cs index f7cddb8bb..8dcd21861 100644 --- a/test/dotnet-projectmodel-server.Tests/Helpers/JArrayExtensions.cs +++ b/test/dotnet-projectmodel-server.Tests/Helpers/JArrayExtensions.cs @@ -70,6 +70,21 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests return array; } + public static JArray AssertJArrayNotContains(this JArray array, Func critiera) + { + foreach (var element in array) + { + var value = element.Value(); + + if (critiera(value)) + { + Assert.True(false, "JArray contains unexpected element."); + } + } + + return array; + } + public static T RetrieveArraryElementAs(this JArray json, int index) where T : JToken { From ea317f9386c039f6db199f9705086ab1b369853b Mon Sep 17 00:00:00 2001 From: Matt Ellis Date: Fri, 18 Mar 2016 14:39:40 -0700 Subject: [PATCH 03/11] Chain in VC++ Redist to Bundle --- packaging/windows/clisdk/bundle.wxs | 34 ++++++++++++++++++++ packaging/windows/inc/crtvariables.wxi | 25 ++++++++++++++ packaging/windows/sharedframework/bundle.wxs | 34 ++++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 packaging/windows/inc/crtvariables.wxi diff --git a/packaging/windows/clisdk/bundle.wxs b/packaging/windows/clisdk/bundle.wxs index ffa1ca597..cfd89df67 100644 --- a/packaging/windows/clisdk/bundle.wxs +++ b/packaging/windows/clisdk/bundle.wxs @@ -4,6 +4,7 @@ xmlns:swid="http://schemas.microsoft.com/wix/TagExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> + + + + @@ -45,6 +62,23 @@ + + + diff --git a/packaging/windows/inc/crtvariables.wxi b/packaging/windows/inc/crtvariables.wxi new file mode 100644 index 000000000..12263d2bf --- /dev/null +++ b/packaging/windows/inc/crtvariables.wxi @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packaging/windows/sharedframework/bundle.wxs b/packaging/windows/sharedframework/bundle.wxs index 8c5a9b845..85cb613ff 100644 --- a/packaging/windows/sharedframework/bundle.wxs +++ b/packaging/windows/sharedframework/bundle.wxs @@ -4,6 +4,7 @@ xmlns:swid="http://schemas.microsoft.com/wix/TagExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> + + + + @@ -38,6 +55,23 @@ + + + From e7718b716335c4201ee2eb5e43e7c0297889de95 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Mon, 4 Apr 2016 18:38:49 -0500 Subject: [PATCH 04/11] Enhance the update-dependencies script: - Add the new version number to the commit and PR message. - Check if anything has been updated and no-op if there wasn't anything updated. - Add support to CC indviduals on the PR. --- .../BuildContextProperties.cs | 30 ++++++++ scripts/update-dependencies/Config.cs | 8 ++- scripts/update-dependencies/DependencyInfo.cs | 15 ++++ scripts/update-dependencies/PushPRTargets.cs | 68 +++++++++++++++++-- .../update-dependencies/UpdateFilesTargets.cs | 36 ++-------- 5 files changed, 118 insertions(+), 39 deletions(-) create mode 100644 scripts/update-dependencies/BuildContextProperties.cs create mode 100644 scripts/update-dependencies/DependencyInfo.cs diff --git a/scripts/update-dependencies/BuildContextProperties.cs b/scripts/update-dependencies/BuildContextProperties.cs new file mode 100644 index 000000000..6cd488398 --- /dev/null +++ b/scripts/update-dependencies/BuildContextProperties.cs @@ -0,0 +1,30 @@ +// 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.Collections.Generic; +using Microsoft.DotNet.Cli.Build.Framework; + +namespace Microsoft.DotNet.Scripts +{ + public static class BuildContextProperties + { + public static List GetDependencyInfos(this BuildTargetContext c) + { + const string propertyName = "DependencyInfos"; + + List dependencyInfos; + object dependencyInfosObj; + if (c.BuildContext.Properties.TryGetValue(propertyName, out dependencyInfosObj)) + { + dependencyInfos = (List)dependencyInfosObj; + } + else + { + dependencyInfos = new List(); + c.BuildContext[propertyName] = dependencyInfos; + } + + return dependencyInfos; + } + } +} diff --git a/scripts/update-dependencies/Config.cs b/scripts/update-dependencies/Config.cs index c0e446ec3..7772bba52 100644 --- a/scripts/update-dependencies/Config.cs +++ b/scripts/update-dependencies/Config.cs @@ -23,6 +23,7 @@ namespace Microsoft.DotNet.Scripts /// GITHUB_UPSTREAM_OWNER - The owner of the GitHub base repo to create the PR to. (ex. "dotnet") /// GITHUB_PROJECT - The repo name under the ORIGIN and UPSTREAM owners. (ex. "cli") /// GITHUB_UPSTREAM_BRANCH - The branch in the GitHub base repo to create the PR to. (ex. "rel/1.0.0") + /// GITHUB_PULL_REQUEST_NOTIFICATIONS - A semi-colon ';' separated list of GitHub users to notify on the PR. /// public class Config { @@ -36,6 +37,7 @@ namespace Microsoft.DotNet.Scripts public string GitHubUpstreamOwner { get; set; } public string GitHubProject { get; set; } public string GitHubUpstreamBranch { get; set; } + public string[] GitHubPullRequestNotifications { get; set; } private static Config Read() { @@ -52,18 +54,20 @@ namespace Microsoft.DotNet.Scripts GitHubUpstreamOwner = GetEnvironmentVariable("GITHUB_UPSTREAM_OWNER", "dotnet"), GitHubProject = GetEnvironmentVariable("GITHUB_PROJECT", "cli"), GitHubUpstreamBranch = GetEnvironmentVariable("GITHUB_UPSTREAM_BRANCH", "rel/1.0.0"), + GitHubPullRequestNotifications = GetEnvironmentVariable("GITHUB_PULL_REQUEST_NOTIFICATIONS", "") + .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) }; } private static string GetEnvironmentVariable(string name, string defaultValue = null) { string value = Environment.GetEnvironmentVariable(name); - if (string.IsNullOrEmpty(value)) + if (value == null) { value = defaultValue; } - if (string.IsNullOrEmpty(value)) + if (value == null) { throw new BuildFailureException($"Can't find environment variable '{name}'."); } diff --git a/scripts/update-dependencies/DependencyInfo.cs b/scripts/update-dependencies/DependencyInfo.cs new file mode 100644 index 000000000..68cf4f45d --- /dev/null +++ b/scripts/update-dependencies/DependencyInfo.cs @@ -0,0 +1,15 @@ +// 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. + +namespace Microsoft.DotNet.Scripts +{ + public class DependencyInfo + { + public string Name { get; set; } + public string IdPattern { get; set; } + public string IdExclusionPattern { get; set; } + public string NewReleaseVersion { get; set; } + + public bool IsUpdated { get; set; } + } +} diff --git a/scripts/update-dependencies/PushPRTargets.cs b/scripts/update-dependencies/PushPRTargets.cs index 4d9ca44c1..2d989a79e 100644 --- a/scripts/update-dependencies/PushPRTargets.cs +++ b/scripts/update-dependencies/PushPRTargets.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Linq; using Microsoft.DotNet.Cli.Build.Framework; using Octokit; @@ -14,8 +15,6 @@ namespace Microsoft.DotNet.Scripts /// public static class PushPRTargets { - private const string PullRequestTitle = "Updating dependencies from last known good builds"; - private static readonly Config s_config = Config.Instance; [Target(nameof(CommitChanges), nameof(CreatePR))] @@ -28,14 +27,31 @@ namespace Microsoft.DotNet.Scripts [Target] public static BuildTargetResult CommitChanges(BuildTargetContext c) { - Cmd("git", "add", ".") - .Execute() - .EnsureSuccessful(); + CommandResult statusResult = Cmd("git", "status", "--porcelain") + .CaptureStdOut() + .Execute(); + statusResult.EnsureSuccessful(); + + bool hasModifiedFiles = !string.IsNullOrWhiteSpace(statusResult.StdOut); + bool hasUpdatedDependencies = c.GetDependencyInfos().Where(d => d.IsUpdated).Any(); + + if (hasModifiedFiles != hasUpdatedDependencies) + { + return c.Failed($"'git status' does not match DependencyInfo information. Git has modified files: {hasModifiedFiles}. DependencyInfo is updated: {hasUpdatedDependencies}."); + } + + if (!hasUpdatedDependencies) + { + c.Warn("Dependencies are currently up to date"); + return c.Success(); + } string userName = s_config.UserName; string email = s_config.Email; - Cmd("git", "commit", "-m", PullRequestTitle, "--author", $"{userName} <{email}>") + string commitMessage = GetCommitMessage(c); + + Cmd("git", "commit", "-a", "-m", commitMessage, "--author", $"{userName} <{email}>") .EnvironmentVariable("GIT_COMMITTER_NAME", userName) .EnvironmentVariable("GIT_COMMITTER_EMAIL", email) .Execute() @@ -79,12 +95,19 @@ namespace Microsoft.DotNet.Scripts public static BuildTargetResult CreatePR(BuildTargetContext c) { string remoteBranchName = c.GetRemoteBranchName(); + string commitMessage = c.GetCommitMessage(); NewPullRequest prInfo = new NewPullRequest( - PullRequestTitle, + commitMessage, s_config.GitHubOriginOwner + ":" + remoteBranchName, s_config.GitHubUpstreamBranch); + string[] prNotifications = s_config.GitHubPullRequestNotifications; + if (prNotifications.Length > 0) + { + prInfo.Body = $"/cc @{string.Join(" @", prNotifications)}"; + } + GitHubClient gitHub = new GitHubClient(new ProductHeaderValue("dotnetDependencyUpdater")); gitHub.Credentials = new Credentials(s_config.Password); @@ -104,5 +127,36 @@ namespace Microsoft.DotNet.Scripts { c.BuildContext["RemoteBranchName"] = value; } + + private static string GetCommitMessage(this BuildTargetContext c) + { + const string commitMessagePropertyName = "CommitMessage"; + + string message; + object messageObject; + if (c.BuildContext.Properties.TryGetValue(commitMessagePropertyName, out messageObject)) + { + message = (string)messageObject; + } + else + { + DependencyInfo[] updatedDependencies = c.GetDependencyInfos() + .Where(d => d.IsUpdated) + .ToArray(); + + string updatedDependencyNames = string.Join(", ", updatedDependencies.Select(d => d.Name)); + string updatedDependencyVersions = string.Join(", ", updatedDependencies.Select(d => d.NewReleaseVersion)); + + message = $"Updating {updatedDependencyNames} to {updatedDependencyVersions}"; + if (updatedDependencies.Count() > 1) + { + message += " respectively"; + } + + c.BuildContext[commitMessagePropertyName] = message; + } + + return message; + } } } diff --git a/scripts/update-dependencies/UpdateFilesTargets.cs b/scripts/update-dependencies/UpdateFilesTargets.cs index 31527ce59..ab4eca931 100644 --- a/scripts/update-dependencies/UpdateFilesTargets.cs +++ b/scripts/update-dependencies/UpdateFilesTargets.cs @@ -34,7 +34,7 @@ namespace Microsoft.DotNet.Scripts const string coreFxIdPattern = @"^(?i)((System\..*)|(NETStandard\.Library)|(Microsoft\.CSharp)|(Microsoft\.NETCore.*)|(Microsoft\.TargetingPack\.Private\.(CoreCLR|NETNative))|(Microsoft\.Win32\..*)|(Microsoft\.VisualBasic))$"; const string coreFxIdExclusionPattern = @"System.CommandLine"; - List dependencyInfos = c.GetDependencyInfo(); + List dependencyInfos = c.GetDependencyInfos(); dependencyInfos.Add(new DependencyInfo() { Name = "CoreFx", @@ -46,25 +46,6 @@ namespace Microsoft.DotNet.Scripts return c.Success(); } - private static List GetDependencyInfo(this BuildTargetContext c) - { - const string propertyName = "DependencyInfo"; - - List dependencyInfos; - object dependencyInfosObj; - if (c.BuildContext.Properties.TryGetValue(propertyName, out dependencyInfosObj)) - { - dependencyInfos = (List)dependencyInfosObj; - } - else - { - dependencyInfos = new List(); - c.BuildContext[propertyName] = dependencyInfos; - } - - return dependencyInfos; - } - [Target(nameof(ReplaceProjectJson), nameof(ReplaceCrossGen))] public static BuildTargetResult ReplaceVersions(BuildTargetContext c) => c.Success(); @@ -74,7 +55,7 @@ namespace Microsoft.DotNet.Scripts [Target] public static BuildTargetResult ReplaceProjectJson(BuildTargetContext c) { - List dependencyInfos = c.GetDependencyInfo(); + List dependencyInfos = c.GetDependencyInfos(); IEnumerable projectJsonFiles = Enumerable.Union( Directory.GetFiles(Dirs.RepoRoot, "project.json", SearchOption.AllDirectories), @@ -157,6 +138,9 @@ namespace Microsoft.DotNet.Scripts dependencyProperty.Value = newVersion; } + // mark the DependencyInfo as updated so we can tell which dependencies were updated + dependencyInfo.IsUpdated = true; + return true; } } @@ -194,21 +178,13 @@ namespace Microsoft.DotNet.Scripts .SelectMany(o => o.Children()); } - private class DependencyInfo - { - public string Name { get; set; } - public string IdPattern { get; set; } - public string IdExclusionPattern { get; set; } - public string NewReleaseVersion { get; set; } - } - /// /// Replaces version number that is hard-coded in the CrossGen script. /// [Target] public static BuildTargetResult ReplaceCrossGen(BuildTargetContext c) { - DependencyInfo coreFXInfo = c.GetDependencyInfo().Single(d => d.Name == "CoreFx"); + DependencyInfo coreFXInfo = c.GetDependencyInfos().Single(d => d.Name == "CoreFx"); string compileTargetsPath = Path.Combine(Dirs.RepoRoot, @"scripts\dotnet-cli-build\CompileTargets.cs"); string compileTargetsContent = File.ReadAllText(compileTargetsPath); From 10aeb9e6f1c3d68bfa2223eddff6d1466e152397 Mon Sep 17 00:00:00 2001 From: Bryan Thornbury Date: Mon, 4 Apr 2016 20:13:13 -0700 Subject: [PATCH 05/11] Add a Sdk Debug Archive --- scripts/dotnet-cli-build/CompileTargets.cs | 15 ++++++++++++++- scripts/dotnet-cli-build/PackageTargets.cs | 4 ++++ scripts/dotnet-cli-build/PrepareTargets.cs | 1 + scripts/dotnet-cli-build/PublishTargets.cs | 14 +++++++++++++- scripts/dotnet-cli-build/Utils/Dirs.cs | 2 ++ 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index 79fccf0b3..b32e956ae 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -243,6 +243,9 @@ namespace Microsoft.DotNet.Cli.Build outputDir: Dirs.Stage1); CleanOutputDir(Path.Combine(Dirs.Stage1, "sdk")); + FS.CopyRecursive(Dirs.Stage1, Dirs.Stage1Symbols); + + RemovePdbsFromDir(Path.Combine(Dirs.Stage1, "sdk")); return result; } @@ -293,13 +296,23 @@ namespace Microsoft.DotNet.Cli.Build } CleanOutputDir(Path.Combine(Dirs.Stage2, "sdk")); + FS.CopyRecursive(Dirs.Stage2, Dirs.Stage2Symbols); + + RemovePdbsFromDir(Path.Combine(Dirs.Stage2, "sdk")); return c.Success(); } private static void CleanOutputDir(string directory) { - FS.RmFilesInDirRecursive(directory, "vbc.exe"); + foreach (var file in FilesToClean) + { + FS.RmFilesInDirRecursive(directory, file); + } + } + + private static void RemovePdbsFromDir(string directory) + { FS.RmFilesInDirRecursive(directory, "*.pdb"); } diff --git a/scripts/dotnet-cli-build/PackageTargets.cs b/scripts/dotnet-cli-build/PackageTargets.cs index 40bc5e3bc..75ba0fb3d 100644 --- a/scripts/dotnet-cli-build/PackageTargets.cs +++ b/scripts/dotnet-cli-build/PackageTargets.cs @@ -175,6 +175,8 @@ namespace Microsoft.DotNet.Cli.Build CreateZipFromDirectory(c.BuildContext.Get("CombinedFrameworkSDKHostRoot"), c.BuildContext.Get("CombinedFrameworkSDKHostCompressedFile")); CreateZipFromDirectory(c.BuildContext.Get("CombinedFrameworkHostRoot"), c.BuildContext.Get("CombinedFrameworkHostCompressedFile")); + CreateZipFromDirectory(Path.Combine(Dirs.Stage2Symbols, "sdk"), c.BuildContext.Get("SdkSymbolsCompressedFile")); + return c.Success(); } @@ -185,6 +187,8 @@ namespace Microsoft.DotNet.Cli.Build CreateTarBallFromDirectory(c.BuildContext.Get("CombinedFrameworkSDKHostRoot"), c.BuildContext.Get("CombinedFrameworkSDKHostCompressedFile")); CreateTarBallFromDirectory(c.BuildContext.Get("CombinedFrameworkHostRoot"), c.BuildContext.Get("CombinedFrameworkHostCompressedFile")); + CreateTarBallFromDirectory(Path.Combine(Dirs.Stage2Symbols, "sdk"), c.BuildContext.Get("SdkSymbolsCompressedFile")); + return c.Success(); } diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs index ac44561eb..69bd7bd74 100644 --- a/scripts/dotnet-cli-build/PrepareTargets.cs +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -130,6 +130,7 @@ namespace Microsoft.DotNet.Cli.Build AddInstallerArtifactToContext(c, "dotnet-sharedframework", "SharedFramework", sharedFrameworkVersion); AddInstallerArtifactToContext(c, "dotnet-dev", "CombinedFrameworkSDKHost", cliVersion); AddInstallerArtifactToContext(c, "dotnet", "CombinedFrameworkHost", sharedFrameworkVersion); + AddInstallerArtifactToContext(c, "dotnet-sdk-debug", "SdkSymbols", cliVersion); return c.Success(); } diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index 10f4bb6a7..8ed4997a3 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -68,7 +68,8 @@ namespace Microsoft.DotNet.Cli.Build [Target( nameof(PublishTargets.PublishCombinedHostFrameworkArchiveToAzure), - nameof(PublishTargets.PublishCombinedHostFrameworkSdkArchiveToAzure))] + nameof(PublishTargets.PublishCombinedHostFrameworkSdkArchiveToAzure), + nameof(PublishTargets.PublishSDKSymbolsArchiveToAzure))] public static BuildTargetResult PublishArchivesToAzure(BuildTargetContext c) => c.Success(); [Target( @@ -176,6 +177,17 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } + [Target] + public static BuildTargetResult PublishSDKSymbolsArchiveToAzure(BuildTargetContext c) + { + var version = CliNuGetVersion; + var archiveFile = c.BuildContext.Get("SdkSymbolsCompressedFile"); + + AzurePublisherTool.PublishArchiveAndLatest(archiveFile, Channel, version); + + return c.Success(); + } + [Target] public static BuildTargetResult PublishCombinedHostFrameworkArchiveToAzure(BuildTargetContext c) { diff --git a/scripts/dotnet-cli-build/Utils/Dirs.cs b/scripts/dotnet-cli-build/Utils/Dirs.cs index 62ebe8f73..cec5db1cb 100644 --- a/scripts/dotnet-cli-build/Utils/Dirs.cs +++ b/scripts/dotnet-cli-build/Utils/Dirs.cs @@ -17,8 +17,10 @@ namespace Microsoft.DotNet.Cli.Build public static readonly string Packages = Path.Combine(Output, "packages"); public static readonly string Stage1 = Path.Combine(Output, "stage1"); public static readonly string Stage1Compilation = Path.Combine(Output, "stage1compilation"); + public static readonly string Stage1Symbols = Path.Combine(Output, "stage1symbols"); public static readonly string Stage2 = Path.Combine(Output, "stage2"); public static readonly string Stage2Compilation = Path.Combine(Output, "stage2compilation"); + public static readonly string Stage2Symbols = Path.Combine(Output, "stage2symbols"); public static readonly string Corehost = Path.Combine(Output, "corehost"); public static readonly string TestOutput = Path.Combine(Output, "tests"); public static readonly string TestArtifacts = Path.Combine(TestOutput, "artifacts"); From 8831bb4a8bd4d2acb5b86500701fedffad63b3c9 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 1 Apr 2016 21:52:08 -0700 Subject: [PATCH 06/11] Do not trim refs --- .../DependencyContextValidator/.noautobuild | 0 .../DependencyContextValidator/Validator.cs | 7 +- .../DependencyContextValidator/project.json | 10 +- .../TestAppFullClr/.noautobuild | 0 .../TestAppFullClr/Program.cs | 16 +++ .../TestAppFullClr/project.json | 14 ++ .../TestAppPortable/.noautobuild | 0 .../TestAppPortable/Program.cs | 16 +++ .../TestAppPortable/project.json | 19 +++ .../TestAppPortableDeps/.noautobuild | 0 .../TestAppPortableDeps/Program.cs | 16 +++ .../TestAppPortableDeps/project.json | 18 +++ .../.noautobuild | 0 .../PortableAppCompilationContext/Program.cs | 12 ++ .../project.json | 21 +++ scripts/dotnet-cli-build/CompileTargets.cs | 43 +++++- scripts/dotnet-cli-build/PrepareTargets.cs | 4 +- scripts/dotnet-cli-build/Utils/FS.cs | 2 +- scripts/dotnet-cli-build/Utils/Utils.cs | 20 ++- .../Compilation/LibraryExporter.cs | 2 +- src/Microsoft.DotNet.ProjectModel/Project.cs | 3 +- .../ProjectContext.cs | 7 +- .../DependencyContextExtensions.cs | 60 ++++++++ .../DependencyContextJsonReader.cs | 3 +- .../commands/dotnet-publish/PublishCommand.cs | 87 +++--------- test/Installer/testmsi.ps1 | 1 + .../TestBase.cs | 8 +- .../FunctionalTests.cs | 133 ++++++++++++++++++ .../project.json | 3 + test/dotnet-compile.Tests/CompilerTests.cs | 20 --- .../PublishPortableTests.cs | 18 +++ 31 files changed, 455 insertions(+), 108 deletions(-) create mode 100644 TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/.noautobuild create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/.noautobuild create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/Program.cs create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/project.json create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/.noautobuild create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/Program.cs create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/project.json create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/.noautobuild create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/Program.cs create mode 100644 TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/project.json create mode 100644 TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/.noautobuild create mode 100644 TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/Program.cs create mode 100644 TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/project.json create mode 100644 test/Microsoft.Extensions.DependencyModel.Tests/FunctionalTests.cs diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/.noautobuild b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/.noautobuild new file mode 100644 index 000000000..e69de29bb diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs index 4195d928d..b34b4c93b 100644 --- a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs +++ b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/Validator.cs @@ -44,6 +44,7 @@ namespace Microsoft.Extensions.DependencyModel var resolvedPaths = compilationLibrary.ResolveReferencePaths(); foreach (var resolvedPath in resolvedPaths) { + Console.WriteLine($"Compilation {compilationLibrary.Name}:{Path.GetFileName(resolvedPath)}"); if (!File.Exists(resolvedPath)) { Error($"Compilataion library resolved to non existent path {resolvedPath}"); @@ -55,8 +56,10 @@ namespace Microsoft.Extensions.DependencyModel foreach (var runtimeLibrary in context.RuntimeLibraries) { CheckMetadata(runtimeLibrary); - foreach (var assembly in runtimeLibrary.GetDefaultNativeAssets(context)) {} - foreach (var native in runtimeLibrary.GetDefaultAssemblyNames(context)) {} + foreach (var native in runtimeLibrary.GetDefaultNativeAssets(context)) {} + foreach (var assembly in runtimeLibrary.GetDefaultAssemblyNames(context)) { + Console.WriteLine($"Runtime {runtimeLibrary.Name}:{assembly.Name}"); + } } foreach (var native in context.GetDefaultNativeAssets()) {} diff --git a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json index 5501c0f42..c160bb47f 100644 --- a/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json +++ b/TestAssets/TestProjects/DependencyContextValidator/DependencyContextValidator/project.json @@ -1,15 +1,19 @@ { "version": "1.0.0-*", "dependencies": { - "NETStandard.Library": "1.5.0-rc2-23931", "Microsoft.Extensions.DependencyModel": { "target": "project", "version": "1.0.0-*" } }, "frameworks": { - "netstandardapp1.5": { - "imports": "dnxcore50" + "netstandard1.5": { + "imports": "dnxcore50", + "dependencies": { + "NETStandard.Library": "1.5.0-rc2-23931", + } + }, + "net451": { } } } diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/.noautobuild b/TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/.noautobuild new file mode 100644 index 000000000..e69de29bb diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/Program.cs b/TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/Program.cs new file mode 100644 index 000000000..28b8f8435 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/Program.cs @@ -0,0 +1,16 @@ +// 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.Diagnostics; + +namespace TestApp +{ + public class Program + { + public static void Main(string[] args) + { + Microsoft.Extensions.DependencyModel.DependencyContextValidator.Validate(true); + } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/project.json b/TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/project.json new file mode 100644 index 000000000..c5331b23d --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppFullClr/project.json @@ -0,0 +1,14 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true + }, + "dependencies": { + "DependencyContextValidator": "1.0.0-*" + }, + "frameworks": { + "net451": { + } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/.noautobuild b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/.noautobuild new file mode 100644 index 000000000..e69de29bb diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/Program.cs b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/Program.cs new file mode 100644 index 000000000..28b8f8435 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/Program.cs @@ -0,0 +1,16 @@ +// 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.Diagnostics; + +namespace TestApp +{ + public class Program + { + public static void Main(string[] args) + { + Microsoft.Extensions.DependencyModel.DependencyContextValidator.Validate(true); + } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/project.json b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/project.json new file mode 100644 index 000000000..f3fc18046 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortable/project.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true + }, + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-23931" + }, + "DependencyContextValidator": "1.0.0-*" + }, + "frameworks": { + "netstandard1.5": { + "imports" : "dnxcore50" + } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/.noautobuild b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/.noautobuild new file mode 100644 index 000000000..e69de29bb diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/Program.cs b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/Program.cs new file mode 100644 index 000000000..28b8f8435 --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/Program.cs @@ -0,0 +1,16 @@ +// 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.Diagnostics; + +namespace TestApp +{ + public class Program + { + public static void Main(string[] args) + { + Microsoft.Extensions.DependencyModel.DependencyContextValidator.Validate(true); + } + } +} diff --git a/TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/project.json b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/project.json new file mode 100644 index 000000000..2036c6d1a --- /dev/null +++ b/TestAssets/TestProjects/DependencyContextValidator/TestAppPortableDeps/project.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true, + }, + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-23931" + }, + "DependencyContextValidator": "1.0.0-*" + }, + "frameworks": { + "netstandard1.5": { + "imports" : "dnxcore50" + } + } +} diff --git a/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/.noautobuild b/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/.noautobuild new file mode 100644 index 000000000..e69de29bb diff --git a/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/Program.cs b/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/Program.cs new file mode 100644 index 000000000..fbe8e9b0e --- /dev/null +++ b/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace PortableApp +{ + public static class Program + { + public static void Main(string[] args) + { + Console.WriteLine("Hello, World!"); + } + } +} diff --git a/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/project.json b/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/project.json new file mode 100644 index 000000000..54c2fde9b --- /dev/null +++ b/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/project.json @@ -0,0 +1,21 @@ +{ + "compilationOptions": { + "emitEntryPoint": true, + "preserveCompilationContext": true + }, + "dependencies": {}, + "frameworks": { + "netstandard1.5": { + "imports": [ + "dnxcore50", + "portable-net45+win8" + ], + "dependencies": { + "Microsoft.NETCore.App": { + "type": "platform", + "version": "1.0.0-rc2-23931" + } + } + } + } +} diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index 79fccf0b3..00be6b47a 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Runtime.InteropServices; using Microsoft.DotNet.Cli.Build.Framework; using Microsoft.Extensions.PlatformAbstractions; @@ -9,6 +10,8 @@ using static Microsoft.DotNet.Cli.Build.FS; using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; using System.Text.RegularExpressions; using System.Reflection.PortableExecutable; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; namespace Microsoft.DotNet.Cli.Build { @@ -352,6 +355,7 @@ namespace Microsoft.DotNet.Cli.Build // Rename the .deps file var destinationDeps = Path.Combine(SharedFrameworkNameAndVersionRoot, $"{SharedFrameworkName}.deps.json"); File.Move(Path.Combine(SharedFrameworkNameAndVersionRoot, "framework.deps.json"), destinationDeps); + ChangeEntryPointLibraryName(destinationDeps, null); // Generate RID fallback graph string runtimeGraphGeneratorRuntime = null; @@ -445,7 +449,7 @@ namespace Microsoft.DotNet.Cli.Build "--output", outputDir, "--framework", - "netstandard1.5") + "netstandard1.5") .Execute() .EnsureSuccessful(); @@ -468,6 +472,7 @@ namespace Microsoft.DotNet.Cli.Build File.Delete(Path.Combine(binaryToCorehostifyOutDir, $"{binaryToCorehostify}.exe")); File.Copy(compilersDeps, Path.Combine(outputDir, binaryToCorehostify + ".deps.json")); File.Copy(compilersRuntimeConfig, Path.Combine(outputDir, binaryToCorehostify + ".runtimeconfig.json")); + ChangeEntryPointLibraryName(Path.Combine(outputDir, binaryToCorehostify + ".deps.json"), binaryToCorehostify); } catch (Exception ex) { @@ -577,6 +582,42 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } + private static void ChangeEntryPointLibraryName(string depsFile, string newName) + { + JToken deps; + using (var file = File.OpenText(depsFile)) + using (JsonTextReader reader = new JsonTextReader(file)) + { + deps = JObject.ReadFrom(reader); + } + + var target = deps["targets"][deps["runtimeTarget"]["name"].Value()]; + var library = target.Children().First(); + var version = library.Name.Substring(library.Name.IndexOf('/') + 1); + if (newName == null) + { + library.Remove(); + } + else + { + library.Replace(new JProperty(newName + '/' + version, library.Value)); + } + library = deps["libraries"].Children().First(); + if (newName == null) + { + library.Remove(); + } + else + { + library.Replace(new JProperty(newName + '/' + version, library.Value)); + } + using (var file = File.CreateText(depsFile)) + using (var writer = new JsonTextWriter(file) { Formatting = Formatting.Indented}) + { + deps.WriteTo(writer); + } + } + private static void DeleteMainPublishOutput(string path, string name) { File.Delete(Path.Combine(path, $"{name}{Constants.ExeSuffix}")); diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs index ac44561eb..d029d4f1b 100644 --- a/scripts/dotnet-cli-build/PrepareTargets.cs +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -205,8 +205,8 @@ namespace Microsoft.DotNet.Cli.Build { var dotnet = DotNetCli.Stage0; - dotnet.Restore("--verbosity", "verbose").WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "src")).Execute().EnsureSuccessful(); - dotnet.Restore("--verbosity", "verbose", "--infer-runtimes").WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "tools")).Execute().EnsureSuccessful(); + dotnet.Restore("--verbosity", "verbose", "--disable-parallel", "--infer-runtimes").WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "src")).Execute().EnsureSuccessful(); + dotnet.Restore("--verbosity", "verbose", "--disable-parallel", "--infer-runtimes").WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "tools")).Execute().EnsureSuccessful(); return c.Success(); } diff --git a/scripts/dotnet-cli-build/Utils/FS.cs b/scripts/dotnet-cli-build/Utils/FS.cs index d425c7ce2..80cddcff2 100644 --- a/scripts/dotnet-cli-build/Utils/FS.cs +++ b/scripts/dotnet-cli-build/Utils/FS.cs @@ -111,7 +111,7 @@ namespace Microsoft.DotNet.Cli.Build if (string.Equals(Path.GetFileName(candidate), "bin") || string.Equals(Path.GetFileName(candidate), "obj")) { - Directory.Delete(candidate, recursive: true); + Utils.DeleteDirectory(candidate); } else { diff --git a/scripts/dotnet-cli-build/Utils/Utils.cs b/scripts/dotnet-cli-build/Utils/Utils.cs index bd7e5ad71..799bda56f 100644 --- a/scripts/dotnet-cli-build/Utils/Utils.cs +++ b/scripts/dotnet-cli-build/Utils/Utils.cs @@ -96,8 +96,24 @@ namespace Microsoft.DotNet.Cli.Build File.SetAttributes(file, FileAttributes.Normal); File.Delete(file); } - System.Threading.Thread.Sleep(1); - Directory.Delete(path, true); + var retry = 5; + while (retry >= 0) + { + try + { + Directory.Delete(path, true); + return; + } + catch (IOException ex) + { + if (retry == 0) + { + throw; + } + System.Threading.Thread.Sleep(200); + retry--; + } + } } } diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index ce43b4b0b..8fc68ba34 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs @@ -424,7 +424,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation private IEnumerable PopulateAssets(TargetLibraryWithAssets library, IEnumerable section) { - foreach (var assemblyPath in section) + foreach (var assemblyPath in section.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a.Path))) { yield return LibraryAsset.CreateFromRelativePath(library.Path, assemblyPath.Path); } diff --git a/src/Microsoft.DotNet.ProjectModel/Project.cs b/src/Microsoft.DotNet.ProjectModel/Project.cs index 2df027c5b..9e1c26437 100644 --- a/src/Microsoft.DotNet.ProjectModel/Project.cs +++ b/src/Microsoft.DotNet.ProjectModel/Project.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Microsoft.DotNet.ProjectModel.Files; using Microsoft.DotNet.ProjectModel.Graph; using NuGet.Frameworks; @@ -91,7 +92,7 @@ namespace Microsoft.DotNet.ProjectModel public string RawRuntimeOptions { get; set; } public bool IsTestProject => !string.IsNullOrEmpty(TestRunner); - + public IEnumerable GetTargetFrameworks() { return _targetFrameworks.Values; diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs index 7fe2e7622..b64c0dcef 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs @@ -145,11 +145,8 @@ namespace Microsoft.DotNet.ProjectModel { return this; } - - // Check if there are any runtime targets (i.e. are we portable) - var standalone = LockFile.Targets - .Where(t => t.TargetFramework.Equals(TargetFramework)) - .Any(t => !string.IsNullOrEmpty(t.RuntimeIdentifier)); + + var standalone = !ProjectFile.Dependencies.Any(d => d.Type.Equals(LibraryDependencyType.Platform)); var context = CreateBuilder(ProjectFile.ProjectFilePath, TargetFramework) .WithRuntimeIdentifiers(standalone ? runtimeIdentifiers : Enumerable.Empty()) diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextExtensions.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextExtensions.cs index fd0e7ed39..59f73ea61 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextExtensions.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextExtensions.cs @@ -12,41 +12,101 @@ namespace Microsoft.Extensions.DependencyModel public static IEnumerable GetDefaultNativeAssets(this DependencyContext self) { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } return self.RuntimeLibraries.SelectMany(library => library.GetDefaultNativeAssets(self)); } public static IEnumerable GetRuntimeNativeAssets(this DependencyContext self, string runtimeIdentifier) { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + if (runtimeIdentifier == null) + { + throw new ArgumentNullException(nameof(runtimeIdentifier)); + } return self.RuntimeLibraries.SelectMany(library => library.GetRuntimeNativeAssets(self, runtimeIdentifier)); } public static IEnumerable GetDefaultNativeAssets(this RuntimeLibrary self, DependencyContext context) { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } return ResolveAssets(context, string.Empty, self.NativeLibraryGroups); } public static IEnumerable GetRuntimeNativeAssets(this RuntimeLibrary self, DependencyContext context, string runtimeIdentifier) { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + if (runtimeIdentifier == null) + { + throw new ArgumentNullException(nameof(runtimeIdentifier)); + } return ResolveAssets(context, runtimeIdentifier, self.NativeLibraryGroups); } public static IEnumerable GetDefaultAssemblyNames(this DependencyContext self) { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } return self.RuntimeLibraries.SelectMany(library => library.GetDefaultAssemblyNames(self)); } public static IEnumerable GetRuntimeAssemblyNames(this DependencyContext self, string runtimeIdentifier) { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + if (runtimeIdentifier == null) + { + throw new ArgumentNullException(nameof(runtimeIdentifier)); + } return self.RuntimeLibraries.SelectMany(library => library.GetRuntimeAssemblyNames(self, runtimeIdentifier)); } public static IEnumerable GetDefaultAssemblyNames(this RuntimeLibrary self, DependencyContext context) { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } return ResolveAssets(context, string.Empty, self.RuntimeAssemblyGroups).Select(GetAssemblyName); } public static IEnumerable GetRuntimeAssemblyNames(this RuntimeLibrary self, DependencyContext context, string runtimeIdentifier) { + if (self == null) + { + throw new ArgumentNullException(nameof(self)); + } + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + if (runtimeIdentifier == null) + { + throw new ArgumentNullException(nameof(runtimeIdentifier)); + } return ResolveAssets(context, runtimeIdentifier, self.RuntimeAssemblyGroups).Select(GetAssemblyName); } diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs index 13bee633d..57a0573a2 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextJsonReader.cs @@ -141,7 +141,8 @@ namespace Microsoft.Extensions.DependencyModel } return new CompilationOptions( - compilationOptionsObject[DependencyContextStrings.DefinesPropertyName]?.Values() ?? Enumerable.Empty(), + compilationOptionsObject[DependencyContextStrings.DefinesPropertyName]?.Values().ToArray() ?? Enumerable.Empty(), + // ToArray is here to prevent IEnumerable holding to json object graph compilationOptionsObject[DependencyContextStrings.LanguageVersionPropertyName]?.Value(), compilationOptionsObject[DependencyContextStrings.PlatformPropertyName]?.Value(), compilationOptionsObject[DependencyContextStrings.AllowUnsafePropertyName]?.Value(), diff --git a/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs index abe835442..5c42f70e5 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs @@ -131,22 +131,26 @@ namespace Microsoft.DotNet.Tools.Publish var isPortable = string.IsNullOrEmpty(context.RuntimeIdentifier); // Collect all exports and organize them - var exports = exporter.GetAllExports() + var packageExports = exporter.GetAllExports() .Where(e => e.Library.Identity.Type.Equals(LibraryType.Package)) .ToDictionary(e => e.Library.Identity.Name); - var collectExclusionList = isPortable ? GetExclusionList(context, exports) : new HashSet(); + var collectExclusionList = isPortable ? GetExclusionList(context, packageExports) : new HashSet(); - foreach (var export in exporter.GetAllExports().Where(e => !collectExclusionList.Contains(e.Library.Identity.Name))) + var exports = exporter.GetAllExports(); + foreach (var export in exports.Where(e => !collectExclusionList.Contains(e.Library.Identity.Name))) { Reporter.Verbose.WriteLine($"Publishing {export.Library.Identity.ToString().Green().Bold()} ..."); PublishAssetGroups(export.RuntimeAssemblyGroups, outputPath, nativeSubdirectories: false, includeRuntimeGroups: isPortable); PublishAssetGroups(export.NativeLibraryGroups, outputPath, nativeSubdirectories, includeRuntimeGroups: isPortable); export.RuntimeAssets.StructuredCopyTo(outputPath, outputPaths.IntermediateOutputDirectoryPath); + } - if (options.PreserveCompilationContext.GetValueOrDefault()) + if (options.PreserveCompilationContext.GetValueOrDefault()) + { + foreach (var export in exports) { - PublishRefs(export, outputPath); + PublishRefs(export, outputPath, !collectExclusionList.Contains(export.Library.Identity.Name)); } } @@ -248,19 +252,19 @@ namespace Microsoft.DotNet.Tools.Publish } } - private static void PublishRefs(LibraryExport export, string outputPath) + private static void PublishRefs(LibraryExport export, string outputPath, bool deduplicate) { var refsPath = Path.Combine(outputPath, "refs"); if (!Directory.Exists(refsPath)) { Directory.CreateDirectory(refsPath); } - + // Do not copy compilation assembly if it's in runtime assemblies var runtimeAssemblies = new HashSet(export.RuntimeAssemblyGroups.GetDefaultAssets()); foreach (var compilationAssembly in export.CompilationAssemblies) { - if (!runtimeAssemblies.Contains(compilationAssembly)) + if (!deduplicate || !runtimeAssemblies.Contains(compilationAssembly)) { var destFileName = Path.Combine(refsPath, Path.GetFileName(compilationAssembly.ResolvedPath)); File.Copy(compilationAssembly.ResolvedPath, destFileName, overwrite: true); @@ -358,67 +362,16 @@ namespace Microsoft.DotNet.Tools.Publish private IEnumerable SelectContexts(string projectPath, NuGetFramework framework, string runtime) { - var allContexts = ProjectContext.CreateContextForEachTarget(projectPath).ToList(); - var frameworks = framework == null ? - allContexts.Select(c => c.TargetFramework).Distinct().ToArray() : - new[] { framework }; + var allContexts = framework == null ? + ProjectContext.CreateContextForEachFramework(projectPath) : + new[] { ProjectContext.Create(projectPath, framework) }; - if (string.IsNullOrEmpty(runtime)) - { - // For each framework, find the best matching RID item - var candidates = PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers(); - return frameworks.Select(f => FindBestTarget(f, allContexts, candidates)); - } - else - { - return frameworks.SelectMany(f => allContexts.Where(c => - Equals(c.TargetFramework, f) && - string.Equals(c.RuntimeIdentifier, runtime, StringComparison.Ordinal))); - } + var runtimes = !string.IsNullOrEmpty(runtime) ? + new [] {runtime} : + PlatformServices.Default.Runtime.GetAllCandidateRuntimeIdentifiers(); + return allContexts.Select(c => c.CreateRuntimeContext(runtimes)); } - - private ProjectContext FindBestTarget(NuGetFramework f, List allContexts, IEnumerable candidates) - { - foreach (var candidate in candidates) - { - var target = allContexts.FirstOrDefault(c => - Equals(c.TargetFramework, f) && - string.Equals(c.RuntimeIdentifier, candidate, StringComparison.Ordinal)); - if (target != null) - { - return target; - } - } - - // No RID-specific target found, use the RID-less target and publish portable - return allContexts.FirstOrDefault(c => - Equals(c.TargetFramework, f) && - string.IsNullOrEmpty(c.RuntimeIdentifier)); - } - - /// - /// Return the matching framework/runtime ProjectContext. - /// If 'framework' or 'runtimeIdentifier' is null or empty then it matches with any. - /// - private static IEnumerable GetMatchingProjectContexts(IEnumerable contexts, NuGetFramework framework, string runtimeIdentifier) - { - foreach (var context in contexts) - { - if (context.TargetFramework == null || string.IsNullOrEmpty(context.RuntimeIdentifier)) - { - continue; - } - - if (string.IsNullOrEmpty(runtimeIdentifier) || string.Equals(runtimeIdentifier, context.RuntimeIdentifier, StringComparison.OrdinalIgnoreCase)) - { - if (framework == null || framework.Equals(context.TargetFramework)) - { - yield return context; - } - } - } - } - + private static void CopyContents(ProjectContext context, string outputPath) { var contentFiles = context.ProjectFile.Files.GetContentFiles(); diff --git a/test/Installer/testmsi.ps1 b/test/Installer/testmsi.ps1 index d1b82f67b..f3d12cdbb 100644 --- a/test/Installer/testmsi.ps1 +++ b/test/Installer/testmsi.ps1 @@ -42,6 +42,7 @@ pushd "$Stage2Dir" try { .\dotnet restore ` + --infer-runtimes ` $testDir ` -f https://www.myget.org/F/dotnet-buildtools/api/v3/index.json | Out-Host diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs index 0d5f4a0a0..a72b7b18f 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/TestBase.cs @@ -103,7 +103,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities string.Equals("on", val, StringComparison.OrdinalIgnoreCase)); } - protected void TestExecutable(string outputDir, + protected CommandResult TestExecutable(string outputDir, string executableName, string expectedOutput) { @@ -123,9 +123,13 @@ namespace Microsoft.DotNet.Tools.Test.Utilities var result = executableCommand.ExecuteWithCapturedOutput(string.Join(" ", args)); - result.Should().HaveStdOut(expectedOutput); + if (!string.IsNullOrEmpty(expectedOutput)) + { + result.Should().HaveStdOut(expectedOutput); + } result.Should().NotHaveStdErr(); result.Should().Pass(); + return result; } protected void TestOutputExecutable( diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/FunctionalTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/FunctionalTests.cs new file mode 100644 index 000000000..e051f178a --- /dev/null +++ b/test/Microsoft.Extensions.DependencyModel.Tests/FunctionalTests.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.TestFramework; +using Microsoft.DotNet.Tools.Test.Utilities; +using FluentAssertions; +using Xunit; + +namespace Microsoft.Extensions.DependencyModel +{ + public class FunctionalTests : TestBase + { + private readonly string _testProjectsRoot; + + public FunctionalTests() + { + _testProjectsRoot = Path.Combine(AppContext.BaseDirectory, "TestAssets", "TestProjects"); + } + + [Theory] + [InlineData("TestApp", true)] + [InlineData("TestAppPortable", true)] + [InlineData("TestAppDeps", false)] + [InlineData("TestAppPortableDeps", false)] + public void RunTest(string appname, bool checkCompilation) + { + var testProjectPath = Path.Combine(RepoRoot, "TestAssets", "TestProjects", "DependencyContextValidator", appname); + var testProject = Path.Combine(testProjectPath, "project.json"); + + var runCommand = new RunCommand(testProject); + var result = runCommand.ExecuteWithCapturedOutput(); + result.Should().Pass(); + ValidateRuntimeLibrarites(result, appname); + if (checkCompilation) + { + ValidateCompilationLibraries(result, appname); + } + } + + [Theory] + [InlineData("TestApp", false, true)] + [InlineData("TestAppPortable", true, true)] + [InlineData("TestAppDeps", false, false)] + [InlineData("TestAppPortableDeps", true, false)] + public void PublishTest(string appname, bool portable, bool checkCompilation) + { + var testProjectPath = Path.Combine(RepoRoot, "TestAssets", "TestProjects", "DependencyContextValidator", appname); + var testProject = Path.Combine(testProjectPath, "project.json"); + + var publishCommand = new PublishCommand(testProject); + publishCommand.Execute().Should().Pass(); + + var exeName = portable ? publishCommand.GetPortableOutputName() : publishCommand.GetOutputExecutable(); + + var result = TestExecutable(publishCommand.GetOutputDirectory(portable).FullName, exeName, string.Empty); + ValidateRuntimeLibrarites(result, appname); + if (checkCompilation) + { + ValidateCompilationLibraries(result, appname); + } + } + + [WindowsOnlyFact] + public void RunTestFullClr() + { + var testProjectPath = Path.Combine(RepoRoot, "TestAssets", "TestProjects", "DependencyContextValidator", "TestAppFullClr"); + var testProject = Path.Combine(testProjectPath, "project.json"); + + var runCommand = new RunCommand(testProject); + var result = runCommand.ExecuteWithCapturedOutput(); + result.Should().Pass(); + ValidateRuntimeLibraritesFullClr(result, "TestAppFullClr"); + ValidateCompilationLibrariesFullClr(result, "TestAppFullClr"); + } + + [WindowsOnlyFact] + public void PublishTestFullClr() + { + var testProjectPath = Path.Combine(RepoRoot, "TestAssets", "TestProjects", "DependencyContextValidator", "TestAppFullClr"); + var testProject = Path.Combine(testProjectPath, "project.json"); + + var publishCommand = new PublishCommand(testProject); + publishCommand.Execute().Should().Pass(); + + var result = TestExecutable(publishCommand.GetOutputDirectory().FullName, publishCommand.GetOutputExecutable(), string.Empty); + ValidateRuntimeLibraritesFullClr(result, "TestAppFullClr"); + ValidateCompilationLibrariesFullClr(result, "TestAppFullClr"); + } + + private void ValidateRuntimeLibraritesFullClr(CommandResult result, string appname) + { + // entry assembly + result.Should().HaveStdOutContaining($"Runtime {appname}:{appname}"); + // project dependency + result.Should().HaveStdOutContaining("Runtime DependencyContextValidator:DependencyContextValidator"); + } + + private void ValidateCompilationLibrariesFullClr(CommandResult result, string appname) + { + // entry assembly + result.Should().HaveStdOutContaining($"Compilation {appname}:{appname}.exe"); + // project dependency + result.Should().HaveStdOutContaining("Compilation DependencyContextValidator:DependencyContextValidator.dll"); + // system assembly + result.Should().HaveStdOutContaining("Compilation mscorlib:mscorlib.dll"); + } + + + private void ValidateRuntimeLibrarites(CommandResult result, string appname) + { + // entry assembly + result.Should().HaveStdOutContaining($"Runtime {appname}:{appname}"); + // project dependency + result.Should().HaveStdOutContaining("Runtime DependencyContextValidator:DependencyContextValidator"); + // system assembly + result.Should().HaveStdOutContaining("Runtime System.Linq:System.Linq"); + } + + private void ValidateCompilationLibraries(CommandResult result, string appname) + { + // entry assembly + result.Should().HaveStdOutContaining($"Compilation {appname}:{appname}.dll"); + // project dependency + result.Should().HaveStdOutContaining("Compilation DependencyContextValidator:DependencyContextValidator.dll"); + // system assembly + result.Should().HaveStdOutContaining("Compilation System.Linq:System.Linq.dll"); + } + + } +} diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/project.json b/test/Microsoft.Extensions.DependencyModel.Tests/project.json index 82a324b4f..b1ca04ba3 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/project.json +++ b/test/Microsoft.Extensions.DependencyModel.Tests/project.json @@ -9,6 +9,9 @@ "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, + "Microsoft.DotNet.Cli.Utils": { + "target": "project" + }, "FluentAssertions": "4.0.0", "moq.netcore": "4.4.0-beta8", "xunit": "2.1.0", diff --git a/test/dotnet-compile.Tests/CompilerTests.cs b/test/dotnet-compile.Tests/CompilerTests.cs index 3151c0230..efbb5abf9 100644 --- a/test/dotnet-compile.Tests/CompilerTests.cs +++ b/test/dotnet-compile.Tests/CompilerTests.cs @@ -147,26 +147,6 @@ namespace Microsoft.DotNet.Tools.Compiler.Tests result.StdOut.Should().Contain("MyNamespace.Util"); } - [Fact] - public void EmbeddedDependencyContextIsValidOnBuild() - { - var testProjectPath = Path.Combine(RepoRoot, "TestAssets", "TestProjects", "DependencyContextValidator", "TestApp"); - var testProject = Path.Combine(testProjectPath, "project.json"); - - var runCommand = new RunCommand(testProject); - runCommand.Execute().Should().Pass(); - } - - [Fact] - public void DepsDependencyContextIsValidOnBuild() - { - var testProjectPath = Path.Combine(RepoRoot, "TestAssets", "TestProjects", "DependencyContextValidator", "TestAppDeps"); - var testProject = Path.Combine(testProjectPath, "project.json"); - - var runCommand = new RunCommand(testProject); - runCommand.Execute().Should().Pass(); - } - [Fact] public void CanSetOutputAssemblyNameForLibraries() { diff --git a/test/dotnet-publish.Tests/PublishPortableTests.cs b/test/dotnet-publish.Tests/PublishPortableTests.cs index 8a551e6ca..9283b85dd 100644 --- a/test/dotnet-publish.Tests/PublishPortableTests.cs +++ b/test/dotnet-publish.Tests/PublishPortableTests.cs @@ -81,6 +81,24 @@ namespace Microsoft.DotNet.Tools.Publish.Tests publishDir.Should().NotHaveFile("PortableAppWithNative.runtimeconfig.dev.json"); } + [Fact] + public void RefsPublishTest() + { + TestInstance instance = TestAssetsManager.CreateTestInstance("PortableTests") + .WithLockFiles(); + + var publishCommand = new PublishCommand(Path.Combine(instance.TestRoot, "PortableAppCompilationContext")); + publishCommand.Execute().Should().Pass(); + + publishCommand.GetOutputDirectory(true).Should().HaveFile("PortableAppCompilationContext.dll"); + + var refsDirectory = new DirectoryInfo(Path.Combine(publishCommand.GetOutputDirectory(true).FullName, "refs")); + // Should have compilation time assemblies + refsDirectory.Should().HaveFile("System.IO.dll"); + // Libraries in which lib==ref should be deduped + refsDirectory.Should().NotHaveFile("PortableAppCompilationContext.dll"); + } + private DirectoryInfo Publish(TestInstance testInstance) { var publishCommand = new PublishCommand(Path.Combine(testInstance.TestRoot, "PortableAppWithNative")); From c6eb0fa59a5592090049e691c2a2099984759fed Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Sun, 3 Apr 2016 20:52:36 -0700 Subject: [PATCH 07/11] Add test cover adding MSBuild reference scenario --- .../DthTests.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 878bf8acd..56969c2e9 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; @@ -413,6 +414,39 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests } } + [Fact] + public void AddMSBuildReferenceBeforeRestore() + { + var tam = new TestAssetsManager( + Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MSBuildReferencesProjects")); + + // var appName = "EmptyNetCoreApp"; + var projectPath = tam.CreateTestInstance("ValidCase01").WithLockFiles().TestRoot; + projectPath = Path.Combine(projectPath, "src", "MainApp"); + + var projectFilePath = Path.Combine(projectPath, Project.FileName); + var projectJson = JsonConvert.DeserializeObject(File.ReadAllText(projectFilePath)); + + ((JObject)projectJson["frameworks"]["net46"]["dependencies"]) + .Add("ClassLibrary4", JToken.FromObject(new { target = "project" })); + + File.WriteAllText(projectFilePath, JsonConvert.SerializeObject(projectJson)); + + using (var server = new DthTestServer(_loggerFactory)) + using (var client = new DthTestClient(server, _loggerFactory)) + { + client.Initialize(projectPath); + var messages = client.DrainAllMessages(); + messages.AssertDoesNotContain(MessageTypes.Error); + messages.RetrieveSingleMessage(MessageTypes.Dependencies) + .RetrieveDependency("ClassLibrary4") + .AssertProperty( + "Version", + v => !string.IsNullOrEmpty(v.ToString()), + v => "Version string shouldn't be empty."); + } + } + [Fact] public void MSBuildReferenceTest() { From e63c0f82c9fa288f3faa73868342295940e00d0a Mon Sep 17 00:00:00 2001 From: Troy Dai Date: Sun, 3 Apr 2016 22:03:06 -0700 Subject: [PATCH 08/11] Use default version for unresolved MSBuild reference --- .../Models/DependencyDescription.cs | 5 +++-- test/dotnet-projectmodel-server.Tests/DthTests.cs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs b/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs index 07aa58a64..32c3854e5 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.DotNet.ProjectModel.Compilation; using Microsoft.DotNet.ProjectModel.Graph; +using NuGet.Versioning; namespace Microsoft.DotNet.ProjectModel.Server.Models { @@ -23,7 +24,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models public string Type { get; private set; } public bool Resolved { get; private set; } - + public IEnumerable Dependencies { get; private set; } public IEnumerable Errors { get; private set; } @@ -60,7 +61,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models { Name = library.Identity.Name, DisplayName = library.Identity.Name, - Version = library.Identity.Version?.ToNormalizedString(), + Version = (library.Identity.Version ?? new NuGetVersion("1.0.0")).ToNormalizedString(), Type = library.Identity.Type.Value, Resolved = library.Resolved, Path = library.Path, diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 56969c2e9..4a36cd9f0 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -438,12 +438,13 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests client.Initialize(projectPath); var messages = client.DrainAllMessages(); messages.AssertDoesNotContain(MessageTypes.Error); + // PrintAllMessages(new[] { messages.RetrieveSingleMessage(MessageTypes.Dependencies) }); messages.RetrieveSingleMessage(MessageTypes.Dependencies) .RetrieveDependency("ClassLibrary4") .AssertProperty( "Version", v => !string.IsNullOrEmpty(v.ToString()), - v => "Version string shouldn't be empty."); + v => $"Version string shouldn't be empty. Value [{v.ToString()}]"); } } From e0542adf51fed1554cb660fceaffcadfabc17438 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 5 Apr 2016 10:46:08 -0500 Subject: [PATCH 09/11] Add corehost/packaging/dir.props CoreFX version replacement to the UpdateDependencies script. --- .../update-dependencies/UpdateFilesTargets.cs | 68 ++++++++++++++----- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/scripts/update-dependencies/UpdateFilesTargets.cs b/scripts/update-dependencies/UpdateFilesTargets.cs index ab4eca931..cc4f75bc5 100644 --- a/scripts/update-dependencies/UpdateFilesTargets.cs +++ b/scripts/update-dependencies/UpdateFilesTargets.cs @@ -46,7 +46,7 @@ namespace Microsoft.DotNet.Scripts return c.Success(); } - [Target(nameof(ReplaceProjectJson), nameof(ReplaceCrossGen))] + [Target(nameof(ReplaceProjectJson), nameof(ReplaceCrossGen), nameof(ReplaceCoreHostPackaging))] public static BuildTargetResult ReplaceVersions(BuildTargetContext c) => c.Success(); /// @@ -184,26 +184,62 @@ namespace Microsoft.DotNet.Scripts [Target] public static BuildTargetResult ReplaceCrossGen(BuildTargetContext c) { - DependencyInfo coreFXInfo = c.GetDependencyInfos().Single(d => d.Name == "CoreFx"); - - string compileTargetsPath = Path.Combine(Dirs.RepoRoot, @"scripts\dotnet-cli-build\CompileTargets.cs"); - string compileTargetsContent = File.ReadAllText(compileTargetsPath); - - Regex regex = new Regex(@"CoreCLRVersion = ""(?\d.\d.\d)-(?.*)"";"); - compileTargetsContent = regex.Replace(compileTargetsContent, m => + ReplaceFileContents(@"scripts\dotnet-cli-build\CompileTargets.cs", compileTargetsContent => { - string replacedValue = m.Value; - Group releaseGroup = m.Groups["release"]; + DependencyInfo coreFXInfo = c.GetCoreFXDependency(); + Regex regex = new Regex(@"CoreCLRVersion = ""(?\d.\d.\d)-(?.*)"";"); - replacedValue = replacedValue.Remove(releaseGroup.Index - m.Index, releaseGroup.Length); - replacedValue = replacedValue.Insert(releaseGroup.Index - m.Index, coreFXInfo.NewReleaseVersion); - - return replacedValue; + return regex.ReplaceGroupValue(compileTargetsContent, "release", coreFXInfo.NewReleaseVersion); }); - File.WriteAllText(compileTargetsPath, compileTargetsContent, Encoding.UTF8); - return c.Success(); } + + /// + /// Replaces version number that is hard-coded in the corehost packaging dir.props file. + /// + [Target] + public static BuildTargetResult ReplaceCoreHostPackaging(BuildTargetContext c) + { + ReplaceFileContents(@"src\corehost\packaging\dir.props", contents => + { + DependencyInfo coreFXInfo = c.GetCoreFXDependency(); + Regex regex = new Regex(@"Microsoft\.NETCore\.Platforms\\(?\d\.\d\.\d)-(?.*)\\runtime\.json"); + + return regex.ReplaceGroupValue(contents, "release", coreFXInfo.NewReleaseVersion); + }); + + return c.Success(); + } + + private static DependencyInfo GetCoreFXDependency(this BuildTargetContext c) + { + return c.GetDependencyInfos().Single(d => d.Name == "CoreFx"); + } + + private static void ReplaceFileContents(string repoRelativePath, Func replacement) + { + string fullPath = Path.Combine(Dirs.RepoRoot, repoRelativePath); + string contents = File.ReadAllText(fullPath); + + contents = replacement(contents); + + File.WriteAllText(fullPath, contents, Encoding.UTF8); + } + + private static string ReplaceGroupValue(this Regex regex, string input, string groupName, string newValue) + { + return regex.Replace(input, m => + { + string replacedValue = m.Value; + Group group = m.Groups[groupName]; + int startIndex = group.Index - m.Index; + + replacedValue = replacedValue.Remove(startIndex, group.Length); + replacedValue = replacedValue.Insert(startIndex, newValue); + + return replacedValue; + }); + } } } From 40cd8650ce3d81949881119fa5de9e65d9d24633 Mon Sep 17 00:00:00 2001 From: Livar Cunha Date: Tue, 5 Apr 2016 11:14:36 -0700 Subject: [PATCH 10/11] Removing linq from projectmodel net45 dependencies. It got there accidently. --- src/Microsoft.DotNet.ProjectModel/project.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Microsoft.DotNet.ProjectModel/project.json b/src/Microsoft.DotNet.ProjectModel/project.json index 8bcb9120e..e802dbaeb 100644 --- a/src/Microsoft.DotNet.ProjectModel/project.json +++ b/src/Microsoft.DotNet.ProjectModel/project.json @@ -32,9 +32,6 @@ "System.IO": { "type": "build" } - }, - "dependencies": { - "System.Linq": "4.0.1-rc3-23727" } }, "netstandard1.5": { From ed82fd2e660e6a8e8bf904a4bb9f2875a7301395 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 5 Apr 2016 09:19:31 -0500 Subject: [PATCH 11/11] Update NuGet to 3.5.0-beta-1130 --- scripts/update-dependencies/project.json | 2 +- src/Microsoft.DotNet.Cli.Utils/project.json | 8 ++++---- src/Microsoft.DotNet.ProjectModel/project.json | 2 +- src/dotnet/project.json | 4 ++-- test/Microsoft.DotNet.Cli.Utils.Tests/project.json | 8 ++++---- tools/RuntimeGraphGenerator/project.json | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/scripts/update-dependencies/project.json b/scripts/update-dependencies/project.json index 1a2b48caf..63e87a442 100644 --- a/scripts/update-dependencies/project.json +++ b/scripts/update-dependencies/project.json @@ -9,7 +9,7 @@ "Microsoft.CSharp": "4.0.1-rc2-23931", "System.Runtime.Serialization.Primitives": "4.1.1-rc2-23931", "Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*", - "NuGet.Versioning": "3.5.0-beta-1123", + "NuGet.Versioning": "3.5.0-beta-1130", "Newtonsoft.Json": "7.0.1", "Octokit": "0.18.0", "Microsoft.Net.Http": "2.2.29" diff --git a/src/Microsoft.DotNet.Cli.Utils/project.json b/src/Microsoft.DotNet.Cli.Utils/project.json index 6519d4aa7..07a1fd577 100644 --- a/src/Microsoft.DotNet.Cli.Utils/project.json +++ b/src/Microsoft.DotNet.Cli.Utils/project.json @@ -7,10 +7,10 @@ "dependencies": { "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-20100", - "NuGet.Versioning": "3.5.0-beta-1123", - "NuGet.Packaging": "3.5.0-beta-1123", - "NuGet.Frameworks": "3.5.0-beta-1123", - "NuGet.ProjectModel": "3.5.0-beta-1123" + "NuGet.Versioning": "3.5.0-beta-1130", + "NuGet.Packaging": "3.5.0-beta-1130", + "NuGet.Frameworks": "3.5.0-beta-1130", + "NuGet.ProjectModel": "3.5.0-beta-1130" }, "frameworks": { "net451": { diff --git a/src/Microsoft.DotNet.ProjectModel/project.json b/src/Microsoft.DotNet.ProjectModel/project.json index bb4601866..ade6d127c 100644 --- a/src/Microsoft.DotNet.ProjectModel/project.json +++ b/src/Microsoft.DotNet.ProjectModel/project.json @@ -6,7 +6,7 @@ "description": "Types to model a .NET Project", "dependencies": { "System.Reflection.Metadata": "1.3.0-rc2-23931", - "NuGet.Packaging": "3.5.0-beta-1123", + "NuGet.Packaging": "3.5.0-beta-1130", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15996", "Microsoft.Extensions.JsonParser.Sources": { "type": "build", diff --git a/src/dotnet/project.json b/src/dotnet/project.json index b09efdd7b..3878fe1ba 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -17,10 +17,10 @@ ], "dependencies": { "NuGet.Commands": { - "version": "3.5.0-beta-1123", + "version": "3.5.0-beta-1130", "exclude": "compile" }, - "NuGet.CommandLine.XPlat": "3.5.0-beta-1123", + "NuGet.CommandLine.XPlat": "3.5.0-beta-1130", "Newtonsoft.Json": "7.0.1", "System.Text.Encoding.CodePages": "4.0.1-rc2-23931", "System.Diagnostics.FileVersionInfo": "4.0.0-rc2-23931", diff --git a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json index bd59f0d4b..f2613b8aa 100644 --- a/test/Microsoft.DotNet.Cli.Utils.Tests/project.json +++ b/test/Microsoft.DotNet.Cli.Utils.Tests/project.json @@ -6,10 +6,10 @@ "dependencies": { "Microsoft.NETCore.App": "1.0.0-rc2-23931", "System.Runtime.Serialization.Primitives": "4.1.1-rc2-23931", - "NuGet.Versioning": "3.5.0-beta-1123", - "NuGet.Packaging": "3.5.0-beta-1123", - "NuGet.Frameworks": "3.5.0-beta-1123", - "NuGet.ProjectModel": "3.5.0-beta-1123", + "NuGet.Versioning": "3.5.0-beta-1130", + "NuGet.Packaging": "3.5.0-beta-1130", + "NuGet.Frameworks": "3.5.0-beta-1130", + "NuGet.ProjectModel": "3.5.0-beta-1130", "Microsoft.DotNet.ProjectModel": { "target": "project" }, diff --git a/tools/RuntimeGraphGenerator/project.json b/tools/RuntimeGraphGenerator/project.json index 78776f9a8..24ce6bd02 100644 --- a/tools/RuntimeGraphGenerator/project.json +++ b/tools/RuntimeGraphGenerator/project.json @@ -4,8 +4,8 @@ "emitEntryPoint": true }, "dependencies": { - "NuGet.RuntimeModel": "3.5.0-beta-1123", - "NuGet.Versioning": "3.5.0-beta-1123", + "NuGet.RuntimeModel": "3.5.0-beta-1130", + "NuGet.Versioning": "3.5.0-beta-1130", "System.CommandLine": "0.1.0-e160119-1", "System.Runtime.Serialization.Json": "4.0.2-rc2-23931", "Microsoft.DotNet.ProjectModel": "1.0.0-*",