diff --git a/build/tasks/AnalyzeBuildGraph.cs b/build/tasks/AnalyzeBuildGraph.cs
index a135e66568..1c94093ac0 100644
--- a/build/tasks/AnalyzeBuildGraph.cs
+++ b/build/tasks/AnalyzeBuildGraph.cs
@@ -5,9 +5,11 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using System.IO;
using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
+using RepoTools.BuildGraph;
using RepoTasks.ProjectModel;
using RepoTasks.Utilities;
@@ -26,6 +28,8 @@ namespace RepoTasks
[Required]
public string Properties { get; set; }
+ public string StartGraphAt { get; set; }
+
///
/// New packages we are compiling. Used in the pin tool.
///
@@ -58,7 +62,21 @@ namespace RepoTasks
return false;
}
- PackagesProduced = solutions
+ EnsureConsistentGraph(solutions);
+ PackagesProduced = GetPackagesProduced(solutions);
+ RepositoryBuildOrder = GetRepositoryBuildOrder(solutions.Where(s => s.ShouldBuild));
+
+ return !Log.HasLoggedErrors;
+ }
+
+ private void EnsureConsistentGraph(IEnumerable solutions)
+ {
+ // TODO
+ }
+
+ private ITaskItem[] GetPackagesProduced(IEnumerable solutions)
+ {
+ return solutions
.Where(s => s.ShouldBuild)
.SelectMany(p => p.Projects)
.Where(p => p.IsPackable)
@@ -67,8 +85,63 @@ namespace RepoTasks
["Version"] = p.PackageVersion
}))
.ToArray();
+ }
- return !Log.HasLoggedErrors;
+ private ITaskItem[] GetRepositoryBuildOrder(IEnumerable solutions)
+ {
+ var repositories = solutions.Select(s =>
+ {
+ var repoName = Path.GetFileName(Path.GetDirectoryName(s.FullPath));
+ var repo = new Repository(repoName);
+ repo.Projects = s.Projects
+ .Where(p => p.IsPackable)
+ .Select(p =>
+ new Project(p.PackageId)
+ {
+ Repository = repo,
+ PackageReferences = new HashSet(p.Frameworks.SelectMany(f => f.Dependencies.Keys), StringComparer.OrdinalIgnoreCase),
+ })
+ .ToList();
+ repo.SupportProjects = s.Projects
+ .Where(p => !p.IsPackable)
+ .Select(p =>
+ new Project(p.PackageId)
+ {
+ Repository = repo,
+ PackageReferences = new HashSet(p.Frameworks.SelectMany(f => f.Dependencies.Keys), StringComparer.OrdinalIgnoreCase),
+ })
+ .ToList();
+ return repo;
+ }).ToList();
+
+ var graph = GraphBuilder.Generate(repositories, StartGraphAt, Log);
+ var repositoriesWithOrder = new List<(ITaskItem repository, int order)>();
+ foreach (var repository in repositories)
+ {
+ var graphNodeRepository = graph.FirstOrDefault(g => g.Repository.Name == repository.Name);
+ if (graphNodeRepository == null)
+ {
+ // StartGraphAt was specified so the graph is incomplete.
+ continue;
+ }
+
+ var order = TopologicalSort.GetOrder(graphNodeRepository);
+ var repositoryTaskItem = new TaskItem(repository.Name);
+ repositoryTaskItem.SetMetadata("Order", order.ToString());
+ repositoriesWithOrder.Add((repositoryTaskItem, order));
+ }
+
+ Log.LogMessage(MessageImportance.High, "Repository build order:");
+ foreach (var buildGroup in repositoriesWithOrder.GroupBy(r => r.order).OrderBy(g => g.Key))
+ {
+ var buildGroupRepos = buildGroup.Select(b => b.repository.ItemSpec);
+ Log.LogMessage(MessageImportance.High, $"{buildGroup.Key.ToString().PadLeft(2, ' ')}: {string.Join(", ", buildGroupRepos)}");
+ }
+
+ return repositoriesWithOrder
+ .OrderBy(r => r.order)
+ .Select(r => r.repository)
+ .ToArray();
}
}
}
diff --git a/build/tasks/BuildGraph/Project.cs b/build/tasks/BuildGraph/Project.cs
index 72b5eee254..ad03468a61 100644
--- a/build/tasks/BuildGraph/Project.cs
+++ b/build/tasks/BuildGraph/Project.cs
@@ -23,6 +23,6 @@ namespace RepoTools.BuildGraph
public Repository Repository { get; set; }
- public ISet PackageReferences { get; } = new HashSet(StringComparer.OrdinalIgnoreCase);
+ public ISet PackageReferences { get; set; } = new HashSet(StringComparer.OrdinalIgnoreCase);
}
}
diff --git a/build/tasks/BuildGraph/Repository.cs b/build/tasks/BuildGraph/Repository.cs
index c1e3e5c619..ed7135491c 100644
--- a/build/tasks/BuildGraph/Repository.cs
+++ b/build/tasks/BuildGraph/Repository.cs
@@ -22,9 +22,9 @@ namespace RepoTools.BuildGraph
public string Name { get; private set; }
- public IList Projects { get; } = new List();
+ public IList Projects { get; set; } = new List();
- public IList SupportProjects { get; } = new List();
+ public IList SupportProjects { get; set; } = new List();
public IEnumerable AllProjects => Projects.Concat(SupportProjects);