Generate a file that contains all of the dependencies and their versions

This commit is contained in:
Nate McMaster 2017-09-15 16:10:24 -07:00
parent 4220c516bc
commit a0547c7b9f
6 changed files with 169 additions and 32 deletions

View File

@ -146,9 +146,17 @@
Properties="Configuration=$(Configuration);BuildNumber=$(BuildNumber)">
<Output TaskParameter="RepositoryBuildOrder" ItemName="RepositoryBuildOrder" />
</RepoTasks.AnalyzeBuildGraph>
</Target>
<Target Name="GenerateLineup" DependsOnTargets="ResolveRepoInfo">
<Message Text="Packages that will be produced:" Importance="High" />
<Message Text=" - %(ArtifactInfo.PackageId)/%(Version)" Importance="High" Condition="'%(ArtifactType)' == 'NuGetPackage'" />
<RepoTasks.GenerateLineup
Artifacts="@(ArtifactInfo)"
OutputPath="$(ArtifactsDir)dependencies.targets"
UseFloatingVersions="true"
BuildNumber="$(BuildNumber)" />
</Target>
<Target Name="_UpdateNuGetConfig">

View File

@ -49,7 +49,9 @@ namespace RepoTasks
public override bool Execute()
{
var packageArtifacts = GetPackageInfo(Artifacts);
var packageArtifacts = Artifacts.Select(ArtifactInfo.Parse)
.OfType<ArtifactInfo.Package>()
.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<PackageInfo> packages, IEnumerable<SolutionInfo> solutions)
private void EnsureConsistentGraph(IEnumerable<ArtifactInfo.Package> packages, IEnumerable<SolutionInfo> 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<VersionMismatch>();
@ -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<ITaskItem> 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<SolutionInfo> solutions)
private ITaskItem[] GetRepositoryBuildOrder(IEnumerable<ArtifactInfo.Package> artifacts, IEnumerable<SolutionInfo> 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;

View File

@ -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<PackageInfo>();
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;
}
}
}

View File

@ -5,5 +5,6 @@
<UsingTask TaskName="RepoTasks.CalculateBuildGraph" AssemblyFile="$(_RepoTaskAssembly)" />
<UsingTask TaskName="RepoTasks.AnalyzeBuildGraph" AssemblyFile="$(_RepoTaskAssembly)" />
<UsingTask TaskName="RepoTasks.GenerateLineup" AssemblyFile="$(_RepoTaskAssembly)" />
<UsingTask TaskName="RepoTasks.PinVersions" AssemblyFile="$(_RepoTaskAssembly)" />
</Project>

View File

@ -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"));
}
}
}

View File

@ -1,2 +1,2 @@
version:2.0.0-rtm-15492
commithash:9ea72bcf88063cee9afbe53835681702e2efd720
version:2.0.2-alpha-15495
commithash:60338bc298ac6f70287e89256470cccf24c9bd80