private static async Task DoLatestInChannelGraphNodeDiffAsync( IRemoteFactory remoteFactory, ILogger logger, Dictionary <string, DependencyGraphNode> nodeCache, Dictionary <string, DependencyGraphNode> visitedRepoUriNodes) { logger.LogInformation("Running latest in channel node diff."); IRemote barOnlyRemote = await remoteFactory.GetBarOnlyRemoteAsync(logger); // Walk each node in the graph and diff against the latest build in the channel // that was also applied to the node. Dictionary <string, string> latestCommitCache = new Dictionary <string, string>(); foreach (DependencyGraphNode node in nodeCache.Values) { // Start with an unknown diff. node.DiffFrom = GitDiff.UnknownDiff(); if (node.ContributingBuilds.Any()) { // Choose latest build of node that has a channel. Build newestBuildWithChannel = node.ContributingBuilds.OrderByDescending(b => b.DateProduced).FirstOrDefault( b => b.Channels != null && b.Channels.Any()); // If no build was found (e.g. build was flowed without a channel or channel was removed from // a build, then no diff from latest. if (newestBuildWithChannel != null) { int channelId = newestBuildWithChannel.Channels.First().Id; // Just choose the first channel. This algorithm is mostly just heuristic. string latestCommitKey = $"{node.Repository}@{channelId}"; string latestCommit = null; if (!latestCommitCache.TryGetValue(latestCommitKey, out latestCommit)) { // Look up latest build in the channel var latestBuild = await barOnlyRemote.GetLatestBuildAsync(node.Repository, channelId); // Could be null, if the only build was removed from the channel if (latestBuild != null) { latestCommit = latestBuild.Commit; } // Add to cache latestCommitCache.Add(latestCommitKey, latestCommit); } // Perform diff if there is a latest commit. if (!string.IsNullOrEmpty(latestCommit)) { IRemote repoRemote = await remoteFactory.GetRemoteAsync(node.Repository, logger); // This will return a no-diff if latestCommit == node.Commit node.DiffFrom = await repoRemote.GitDiffAsync(node.Repository, latestCommit, node.Commit); } } } } }
/// <summary> /// Diff each node in the graph against the latest build in /// the graph. /// </summary> /// <param name="remoteFactory"></param> /// <param name="logger"></param> /// <param name="nodeCache"></param> /// <param name="visitedRepoUriNodes"></param> /// <returns></returns> private static async Task DoLatestInGraphNodeDiffAsync( IRemoteFactory remoteFactory, ILogger logger, Dictionary <string, DependencyGraphNode> nodeCache, Dictionary <string, DependencyGraphNode> visitedRepoUriNodes) { logger.LogInformation("Running latest in graph node diff."); // Find the build of each repo in the graph, then // get the diff info from the latest foreach (string repo in visitedRepoUriNodes.Keys) { // Get all nodes with this value List <DependencyGraphNode> nodes = nodeCache.Values.Where(n => n.Repository == repo).ToList(); // If only one, determine latest if (nodes.Count > 1) { // Find latest DependencyGraphNode newestNode = null; Build newestBuild = null; foreach (DependencyGraphNode node in nodes) { if (newestNode == null) { newestNode = node; if (newestNode.ContributingBuilds.Any()) { newestBuild = newestNode.ContributingBuilds.OrderByDescending(b => b.DateProduced).First(); } } else if (node.ContributingBuilds.Any(b => b.DateProduced > newestBuild?.DateProduced)) { newestNode = node; newestBuild = newestNode.ContributingBuilds.OrderByDescending(b => b.DateProduced).First(); } } // Compare all other nodes to the latest foreach (DependencyGraphNode node in nodes) { IRemote repoRemote = await remoteFactory.GetRemoteAsync(node.Repository, logger); // If node == newestNode, returns no diff. node.DiffFrom = await repoRemote.GitDiffAsync(node.Repository, newestNode.Commit, node.Commit); } } else { DependencyGraphNode singleNode = nodes.Single(); singleNode.DiffFrom = GitDiff.NoDiff(singleNode.Commit); } } }