From a0547c7b9fc2532045578fa85b47e48ede81a7f9 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Fri, 15 Sep 2017 16:10:24 -0700 Subject: [PATCH] Generate a file that contains all of the dependencies and their versions --- build/repo.targets | 8 +++ build/tasks/AnalyzeBuildGraph.cs | 42 ++++--------- build/tasks/GenerateLineup.cs | 85 +++++++++++++++++++++++++++ build/tasks/RepoTasks.tasks | 1 + build/tasks/Utilities/ArtifactInfo.cs | 61 +++++++++++++++++++ korebuild-lock.txt | 4 +- 6 files changed, 169 insertions(+), 32 deletions(-) create mode 100644 build/tasks/GenerateLineup.cs create mode 100644 build/tasks/Utilities/ArtifactInfo.cs diff --git a/build/repo.targets b/build/repo.targets index eca755d4ba..a07cbf6e65 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -146,9 +146,17 @@ Properties="Configuration=$(Configuration);BuildNumber=$(BuildNumber)"> + + + + diff --git a/build/tasks/AnalyzeBuildGraph.cs b/build/tasks/AnalyzeBuildGraph.cs index 0d56e6a62d..8116088414 100644 --- a/build/tasks/AnalyzeBuildGraph.cs +++ b/build/tasks/AnalyzeBuildGraph.cs @@ -49,7 +49,9 @@ namespace RepoTasks public override bool Execute() { - var packageArtifacts = GetPackageInfo(Artifacts); + var packageArtifacts = Artifacts.Select(ArtifactInfo.Parse) + .OfType() + .Where(p => !p.IsSymbolsArtifact); var factory = new SolutionInfoFactory(Log, BuildEngine5); var props = MSBuildListSplitter.GetNamedProperties(Properties); @@ -64,7 +66,7 @@ namespace RepoTasks return false; } - EnsureConsistentGraph(packageArtifacts.Select(p => p.Item1), solutions); + EnsureConsistentGraph(packageArtifacts, solutions); RepositoryBuildOrder = GetRepositoryBuildOrder(packageArtifacts, solutions.Where(s => s.ShouldBuild)); return !Log.HasLoggedErrors; @@ -79,10 +81,10 @@ namespace RepoTasks public NuGetVersion ExpectedVersion; } - private void EnsureConsistentGraph(IEnumerable packages, IEnumerable solutions) + private void EnsureConsistentGraph(IEnumerable packages, IEnumerable solutions) { // ensure versions cascade - var lookup = packages.ToDictionary(p => p.Id, p => p, StringComparer.OrdinalIgnoreCase); + var lookup = packages.ToDictionary(p => p.PackageInfo.Id, p => p, StringComparer.OrdinalIgnoreCase); var inconsistentVersions = new List(); @@ -95,9 +97,9 @@ namespace RepoTasks if (!lookup.TryGetValue(dependency.Key, out var package)) continue; var refVersion = VersionRange.Parse(dependency.Value.Version); - if (refVersion.IsFloating && refVersion.Float.Satisfies(package.Version)) + if (refVersion.IsFloating && refVersion.Float.Satisfies(package.PackageInfo.Version)) continue; - else if (package.Version.Equals(refVersion)) + else if (package.PackageInfo.Version.Equals(refVersion)) continue; inconsistentVersions.Add(new VersionMismatch @@ -106,7 +108,7 @@ namespace RepoTasks Project = proj, PackageId = dependency.Key, ActualVersion = dependency.Value.Version, - ExpectedVersion = package.Version, + ExpectedVersion = package.PackageInfo.Version, }); } @@ -133,37 +135,17 @@ namespace RepoTasks } } - private IEnumerable<(PackageInfo, string repoName)> GetPackageInfo(IEnumerable items) - { - return items - .Where(a => "NuGetPackage".Equals(a.GetMetadata("ArtifactType"), StringComparison.OrdinalIgnoreCase)) - .Select(a => - { - var info = new PackageInfo( - a.GetMetadata("PackageId"), - a.GetMetadata("Version"), - string.IsNullOrEmpty(a.GetMetadata("TargetFramework")) - ? MSBuildListSplitter.SplitItemList(a.GetMetadata("TargetFramework")).Select(s => NuGetFramework.Parse(s)).ToArray() - : new [] { NuGetFramework.Parse(a.GetMetadata("TargetFramework")) }, - Path.GetDirectoryName(a.ItemSpec), - a.GetMetadata("PackageType")); - - var repoName = Path.GetFileName(a.GetMetadata("RepositoryRoot").TrimEnd(new [] { '\\', '/' })); - return (info, repoName); - }); - } - - private ITaskItem[] GetRepositoryBuildOrder(IEnumerable<(PackageInfo pkg, string repoName)> artifacts, IEnumerable solutions) + private ITaskItem[] GetRepositoryBuildOrder(IEnumerable artifacts, IEnumerable solutions) { var repositories = solutions.Select(s => { var repoName = Path.GetFileName(Path.GetDirectoryName(s.FullPath)); var repo = new Repository(repoName); - var packages = artifacts.Where(a => a.repoName.Equals(repoName, StringComparison.OrdinalIgnoreCase)).ToList(); + var packages = artifacts.Where(a => a.RepoName.Equals(repoName, StringComparison.OrdinalIgnoreCase)).ToList(); foreach (var proj in s.Projects) { - var projectGroup = packages.Any(p => p.pkg.Id == proj.PackageId) + var projectGroup = packages.Any(p => p.PackageInfo.Id == proj.PackageId) ? repo.Projects : repo.SupportProjects; diff --git a/build/tasks/GenerateLineup.cs b/build/tasks/GenerateLineup.cs new file mode 100644 index 0000000000..92c2de9eb9 --- /dev/null +++ b/build/tasks/GenerateLineup.cs @@ -0,0 +1,85 @@ +// 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.Generic; +using System.Linq; +using System.IO; +using System.Xml; +using System.Xml.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using RepoTasks.ProjectModel; +using RepoTasks.Utilities; + +namespace RepoTasks +{ + public class GenerateLineup : Task + { + [Required] + public ITaskItem[] Artifacts { get; set; } + + [Required] + public string OutputPath { get; set; } + + public bool UseFloatingVersions { get; set; } + + public string BuildNumber { get; set; } + + public override bool Execute() + { + OutputPath = OutputPath.Replace('\\', '/'); + Directory.CreateDirectory(Path.GetDirectoryName(OutputPath)); + + if (UseFloatingVersions && string.IsNullOrEmpty(BuildNumber)) + { + Log.LogWarning("Cannot compute floating versions when BuildNumber is not specified"); + } + + var items = new XElement("ItemGroup"); + var root = new XElement("Project", items); + var doc = new XDocument(root); + + var packages = new List(); + + foreach (var item in Artifacts) + { + var info = ArtifactInfo.Parse(item); + switch (info) + { + case ArtifactInfo.Package pkg when (!pkg.IsSymbolsArtifact): + packages.Add(pkg.PackageInfo); + break; + } + } + + foreach (var pkg in packages.OrderBy(i => i.Id)) + { + var version = pkg.Version.ToString(); + if (UseFloatingVersions && version.EndsWith(BuildNumber)) + { + version = version.Substring(0, version.Length - BuildNumber.Length) + "*"; + } + + var refType = "DotNetCliTool".Equals(pkg.Id, StringComparison.OrdinalIgnoreCase) + ? "DotNetCliToolReference" + : "PackageReference"; + + items.Add(new XElement(refType, + new XAttribute("Update", pkg.Id), + new XAttribute("Version", version))); + } + + var settings = new XmlWriterSettings + { + OmitXmlDeclaration = true, + Indent = true, + }; + using (var writer = XmlWriter.Create(OutputPath, settings)) + { + doc.Save(writer); + } + return true; + } + } +} diff --git a/build/tasks/RepoTasks.tasks b/build/tasks/RepoTasks.tasks index 4026e9810b..d6c6ae3488 100644 --- a/build/tasks/RepoTasks.tasks +++ b/build/tasks/RepoTasks.tasks @@ -5,5 +5,6 @@ + diff --git a/build/tasks/Utilities/ArtifactInfo.cs b/build/tasks/Utilities/ArtifactInfo.cs new file mode 100644 index 0000000000..f3bfa91ced --- /dev/null +++ b/build/tasks/Utilities/ArtifactInfo.cs @@ -0,0 +1,61 @@ +// 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.IO; +using System.Linq; +using NuGet.Frameworks; +using Microsoft.Build.Framework; +using RepoTasks.ProjectModel; + +namespace RepoTasks.Utilities +{ + internal abstract class ArtifactInfo + { + public static ArtifactInfo Parse(ITaskItem item) + { + ArtifactInfo info; + switch (item.GetMetadata("ArtifactType").ToLowerInvariant()) + { + case "nugetpackage": + info = new Package { PackageInfo = GetPackageInfo(item) }; + break; + case "nugetsymbolspackage": + info = new Package { PackageInfo = GetPackageInfo(item), IsSymbolsArtifact = true }; + break; + default: + throw new InvalidDataException($"Unrecognized artifact type: {item.GetMetadata("ArtifactType")} for artifact {item.ItemSpec}"); + } + + info.RepositoryRoot = item.GetMetadata("RepositoryRoot")?.TrimEnd(new [] { '\\', '/' }); + + if (!string.IsNullOrEmpty(info.RepositoryRoot)) + { + info.RepoName = Path.GetFileName(info.RepositoryRoot); + } + + return info; + } + + public string RepositoryRoot { get; private set; } + public string RepoName { get; private set; } + + public class Package : ArtifactInfo + { + public PackageInfo PackageInfo { get; set; } + public bool IsSymbolsArtifact { get; set; } + } + + private static PackageInfo GetPackageInfo(ITaskItem item) + { + return new PackageInfo( + item.GetMetadata("PackageId"), + item.GetMetadata("Version"), + string.IsNullOrEmpty(item.GetMetadata("TargetFramework")) + ? MSBuildListSplitter.SplitItemList(item.GetMetadata("TargetFramework")).Select(s => NuGetFramework.Parse(s)).ToArray() + : new [] { NuGetFramework.Parse(item.GetMetadata("TargetFramework")) }, + Path.GetDirectoryName(item.ItemSpec), + item.GetMetadata("PackageType")); + } + } +} diff --git a/korebuild-lock.txt b/korebuild-lock.txt index 7b57925f8f..73a677fef7 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:2.0.0-rtm-15492 -commithash:9ea72bcf88063cee9afbe53835681702e2efd720 +version:2.0.2-alpha-15495 +commithash:60338bc298ac6f70287e89256470cccf24c9bd80