tool/TeamCity.Docker/BuildGraphsFactory.cs (38 lines of code) (raw):

namespace TeamCity.Docker { using System; using System.Collections.Generic; using System.Linq; using Generic; using Model; // ReSharper disable once ClassNeverInstantiated.Global internal class BuildGraphsFactory : IFactory<IEnumerable<IGraph<IArtifact, Dependency>>, IGraph<IArtifact, Dependency>> { public Result<IEnumerable<IGraph<IArtifact, Dependency>>> Create(IGraph<IArtifact, Dependency> graph) { if (graph == null) throw new ArgumentNullException(nameof(graph)); return new Result<IEnumerable<IGraph<IArtifact, Dependency>>>(CreateInternal(graph)); } private IEnumerable<IGraph<IArtifact, Dependency>> CreateInternal(IGraph<IArtifact, Dependency> graph) { if (graph == null) throw new ArgumentNullException(nameof(graph)); var buildGraph = graph.Copy(i => i.Value is Image || i.Value is Reference); var cutNodes = new HashSet<INode<IArtifact>>(); while (true) { var bestCut = new HashSet<INode<IArtifact>>(buildGraph.FindMinimumCutByStoerWagner(links => links.Select(i => i.From.Value.Weight.Value).Concat(Enumerable.Repeat(0, 1)).Sum(), out var bestCost)); if (bestCost > 0) { yield return buildGraph.Copy(node => node.Value is Image || node.Value is Reference); break; } if (bestCut.Count > buildGraph.NodesCount >> 1) { bestCut = new HashSet<INode<IArtifact>>(graph.Nodes.Except(bestCut)); } cutNodes.UnionWith(bestCut); yield return buildGraph.Copy(node => (node.Value is Image || node.Value is Reference) && bestCut.Contains(node)); buildGraph = buildGraph.Copy(node => !cutNodes.Contains(node)); } } } }