From faf600ce71834c23afa717289b39780cb83ad6f9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Wed, 30 May 2018 10:58:10 -0700 Subject: [PATCH] Fixup the effect of cascading versions (#1187) The PR #1175 was incomplete. This fixes the cascading effect of patching to 2.1.1 Changes: - add CheckRepoGraph (ported directly from the release/2.0 branch) - Update submodules --- build/artifacts.props | 52 ++++++++ build/external-dependencies.props | 55 +------- build/repo.targets | 6 + build/submodules.props | 24 ++-- build/tasks/CheckRepoGraph.cs | 214 ++++++++++++++++++++++++++++++ build/tasks/RepoTasks.tasks | 1 + modules/AADIntegration | 2 +- modules/AzureIntegration | 2 +- modules/Diagnostics | 2 +- modules/Identity | 2 +- modules/JavaScriptServices | 2 +- modules/MetaPackages | 2 +- modules/Proxy | 2 +- modules/StaticFiles | 2 +- modules/WebHooks | 2 +- modules/WebSockets | 2 +- 16 files changed, 296 insertions(+), 76 deletions(-) create mode 100644 build/tasks/CheckRepoGraph.cs diff --git a/build/artifacts.props b/build/artifacts.props index c909b76092..a1df1c0583 100644 --- a/build/artifacts.props +++ b/build/artifacts.props @@ -23,9 +23,11 @@ + + @@ -40,12 +42,33 @@ + + + + + + + + + + + + + + + + + + + + + @@ -66,6 +89,10 @@ + + + + @@ -85,6 +112,25 @@ + + + + + + + + + + + + + + + + + + + @@ -106,6 +152,11 @@ + + + + + @@ -119,6 +170,7 @@ + diff --git a/build/external-dependencies.props b/build/external-dependencies.props index a959419737..fe426974c5 100644 --- a/build/external-dependencies.props +++ b/build/external-dependencies.props @@ -164,16 +164,11 @@ - - - - - @@ -188,12 +183,6 @@ - - - - - - @@ -208,27 +197,10 @@ - - - - - - - - - - - - - - - - - @@ -241,32 +213,12 @@ - - - - - - - - - - - - - - - - - - - - @@ -292,9 +244,7 @@ - - - + @@ -304,8 +254,6 @@ - - @@ -337,7 +285,6 @@ - diff --git a/build/repo.targets b/build/repo.targets index 32e0796db9..85b652c3e1 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -164,6 +164,12 @@ + + + + + + + + + + + + + + - - - @@ -29,7 +38,6 @@ - @@ -38,24 +46,16 @@ - - - - - - - - diff --git a/build/tasks/CheckRepoGraph.cs b/build/tasks/CheckRepoGraph.cs new file mode 100644 index 0000000000..5502d7316c --- /dev/null +++ b/build/tasks/CheckRepoGraph.cs @@ -0,0 +1,214 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.Text; +using System.Threading; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using NuGet.Frameworks; +using NuGet.Packaging.Core; +using NuGet.Versioning; +using RepoTools.BuildGraph; +using RepoTasks.ProjectModel; +using RepoTasks.Utilities; + +namespace RepoTasks +{ + public class CheckRepoGraph : Task, ICancelableTask + { + private readonly CancellationTokenSource _cts = new CancellationTokenSource(); + + [Required] + public ITaskItem[] Solutions { get; set; } + + [Required] + public ITaskItem[] Artifacts { get; set; } + + [Required] + public ITaskItem[] Repositories { get; set; } + + [Required] + public string Properties { get; set; } + + public void Cancel() + { + _cts.Cancel(); + } + + public override bool Execute() + { + var packageArtifacts = Artifacts.Select(ArtifactInfo.Parse) + .OfType() + .Where(p => !p.IsSymbolsArtifact) + .ToDictionary(p => p.PackageInfo.Id, p => p, StringComparer.OrdinalIgnoreCase); + + var factory = new SolutionInfoFactory(Log, BuildEngine5); + var props = MSBuildListSplitter.GetNamedProperties(Properties); + + if (!props.TryGetValue("Configuration", out var defaultConfig)) + { + defaultConfig = "Debug"; + } + + var solutions = factory.Create(Solutions, props, defaultConfig, _cts.Token).OrderBy(f => f.Directory).ToList(); + Log.LogMessage($"Found {solutions.Count} and {solutions.Sum(p => p.Projects.Count)} projects"); + + if (_cts.IsCancellationRequested) + { + return false; + } + + var repoGraph = new AdjacencyMatrix(solutions.Count); + var packageToProjectMap = new Dictionary(); + + for (var i = 0; i < solutions.Count; i++) + { + var sln = repoGraph[i] = solutions[i]; + + foreach (var proj in sln.Projects) + { + if (!proj.IsPackable + || proj.FullPath.Contains("samples") + || proj.FullPath.Contains("tools/Microsoft.VisualStudio.Web.CodeGeneration.Design")) + { + continue; + } + + var id = new PackageIdentity(proj.PackageId, new NuGetVersion(proj.PackageVersion)); + + if (packageToProjectMap.TryGetValue(id, out var otherProj)) + { + Log.LogError($"Both {proj.FullPath} and {otherProj.FullPath} produce {id}"); + continue; + } + + packageToProjectMap.Add(id, proj); + } + + var sharedSrc = Path.Combine(sln.Directory, "shared"); + if (Directory.Exists(sharedSrc)) + { + foreach (var dir in Directory.GetDirectories(sharedSrc, "*.Sources")) + { + var id = GetDirectoryName(dir); + var artifactInfo = packageArtifacts[id]; + var sharedSrcProj = new ProjectInfo(dir, + Array.Empty(), + Array.Empty(), + true, + artifactInfo.PackageInfo.Id, + artifactInfo.PackageInfo.Version.ToNormalizedString()); + sharedSrcProj.SolutionInfo = sln; + var identity = new PackageIdentity(artifactInfo.PackageInfo.Id, artifactInfo.PackageInfo.Version); + packageToProjectMap.Add(identity, sharedSrcProj); + } + } + } + + if (Log.HasLoggedErrors) + { + return false; + } + + for (var i = 0; i < solutions.Count; i++) + { + var src = repoGraph[i]; + + foreach (var proj in src.Projects) + { + if (!proj.IsPackable + || proj.FullPath.Contains("samples")) + { + continue; + } + + foreach (var dep in proj.Frameworks.SelectMany(f => f.Dependencies.Values)) + { + if (packageToProjectMap.TryGetValue(new PackageIdentity(dep.Id, new NuGetVersion(dep.Version)), out var target)) + { + var j = repoGraph.FindIndex(target.SolutionInfo); + repoGraph.SetLink(i, j); + } + } + + foreach (var toolDep in proj.Tools) + { + if (packageToProjectMap.TryGetValue(new PackageIdentity(toolDep.Id, new NuGetVersion(toolDep.Version)), out var target)) + { + var j = repoGraph.FindIndex(target.SolutionInfo); + repoGraph.SetLink(i, j); + } + } + } + } + + var repos = Repositories.ToDictionary(i => i.ItemSpec, i => i, StringComparer.OrdinalIgnoreCase); + + for (var i = 0; i < repoGraph.Count; i++) + { + var src = repoGraph[i]; + var repoName = GetDirectoryName(src.Directory); + var repo = repos[repoName]; + + for (var j = 0; j < repoGraph.Count; j++) + { + if (j == i) continue; + if (repoGraph.HasLink(i, j)) + { + var target = repoGraph[j]; + var targetRepoName = GetDirectoryName(target.Directory); + var targetRepo = repos[targetRepoName]; + + if (src.Shipped && !target.Shipped) + { + Log.LogError($"{repoName} cannot depend on {targetRepoName}. Repos marked as 'Shipped' cannot depend on repos that are rebuilding. Update the configuration in submodule.props."); + } + } + } + } + + return !Log.HasLoggedErrors; + } + + private static string GetDirectoryName(string path) + => Path.GetFileName(path.TrimEnd(new[] { '\\', '/' })); + + private class AdjacencyMatrix + { + private readonly bool[,] _matrix; + private readonly SolutionInfo[] _items; + + public AdjacencyMatrix(int size) + { + _matrix = new bool[size, size]; + _items = new SolutionInfo[size]; + Count = size; + } + + public SolutionInfo this[int idx] + { + get => _items[idx]; + set => _items[idx] = value; + } + + public int FindIndex(SolutionInfo item) + { + return Array.FindIndex(_items, t => t.Equals(item)); + } + + public int Count { get; } + + public bool HasLink(int source, int target) => _matrix[source, target]; + + public void SetLink(int source, int target) + { + _matrix[source, target] = true; + } + } + } +} diff --git a/build/tasks/RepoTasks.tasks b/build/tasks/RepoTasks.tasks index 6f2032d491..1122b7026d 100644 --- a/build/tasks/RepoTasks.tasks +++ b/build/tasks/RepoTasks.tasks @@ -6,6 +6,7 @@ + diff --git a/modules/AADIntegration b/modules/AADIntegration index 4342e5cae2..a35250fe3a 160000 --- a/modules/AADIntegration +++ b/modules/AADIntegration @@ -1 +1 @@ -Subproject commit 4342e5cae29c45c84e27df28218f27c6cec6cc24 +Subproject commit a35250fe3ad8125a4c6fd67feb4055e9470fe558 diff --git a/modules/AzureIntegration b/modules/AzureIntegration index b51db1fc91..c710aa8c26 160000 --- a/modules/AzureIntegration +++ b/modules/AzureIntegration @@ -1 +1 @@ -Subproject commit b51db1fc91cfe792e4f1518b728c41a0af4730d3 +Subproject commit c710aa8c2663e474c270ec48dd9dc999d38d9a46 diff --git a/modules/Diagnostics b/modules/Diagnostics index 98785fb2f5..977f85f9cc 160000 --- a/modules/Diagnostics +++ b/modules/Diagnostics @@ -1 +1 @@ -Subproject commit 98785fb2f5ddb31e298d3f52069adfd233375c65 +Subproject commit 977f85f9cc9ca2685389a740bface9e18fcf5bdd diff --git a/modules/Identity b/modules/Identity index 5403ec47ec..d18de6b00e 160000 --- a/modules/Identity +++ b/modules/Identity @@ -1 +1 @@ -Subproject commit 5403ec47ecfe5cbc2c904253fc1cfbd64675eba6 +Subproject commit d18de6b00e13f06bae43c621f17e39ed2bec4069 diff --git a/modules/JavaScriptServices b/modules/JavaScriptServices index 8c84e35392..436cdb0e96 160000 --- a/modules/JavaScriptServices +++ b/modules/JavaScriptServices @@ -1 +1 @@ -Subproject commit 8c84e353922319ff104c35afa2d6baa186aa010f +Subproject commit 436cdb0e967ab5b3e3903bb876bbd3edef844172 diff --git a/modules/MetaPackages b/modules/MetaPackages index 4e1b907743..10e735d420 160000 --- a/modules/MetaPackages +++ b/modules/MetaPackages @@ -1 +1 @@ -Subproject commit 4e1b90774367d96595eb5e990510b6ba1300ee4e +Subproject commit 10e735d42002db959e1a769a3362c84ec0ef1c27 diff --git a/modules/Proxy b/modules/Proxy index 90d90c12d6..8ec1eb26bb 160000 --- a/modules/Proxy +++ b/modules/Proxy @@ -1 +1 @@ -Subproject commit 90d90c12d61580be1738a78fde0b03c0d25338a0 +Subproject commit 8ec1eb26bbf238eac08161a83632a6260f02d234 diff --git a/modules/StaticFiles b/modules/StaticFiles index 66573b187d..5c775c9579 160000 --- a/modules/StaticFiles +++ b/modules/StaticFiles @@ -1 +1 @@ -Subproject commit 66573b187dc9a915b7726b93753b2f260b9b4b7a +Subproject commit 5c775c957991cb9e5d20c9cf3c67d56dc92d80ba diff --git a/modules/WebHooks b/modules/WebHooks index 5815691af6..e554b1e9f9 160000 --- a/modules/WebHooks +++ b/modules/WebHooks @@ -1 +1 @@ -Subproject commit 5815691af6d8c6f0841a14575609e09f5d0e35c8 +Subproject commit e554b1e9f9a07dd9af35d55bcd6f7159fc6cf752 diff --git a/modules/WebSockets b/modules/WebSockets index b3356b90b2..a1085ed31c 160000 --- a/modules/WebSockets +++ b/modules/WebSockets @@ -1 +1 @@ -Subproject commit b3356b90b20e1fdea3c49cef8f4bbbe0b991e731 +Subproject commit a1085ed31cebed4d4fa1f10cd662a462a87d41f1