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);
                }
            }
        }
Beispiel #3
0
        /// <summary>
        ///     Diff two commits in a repository and return information about them.
        /// </summary>
        /// <param name="repoUri">Repository uri</param>
        /// <param name="baseVersion">Base version</param>
        /// <param name="targetVersion">Target version</param>
        /// <returns>Diff information</returns>
        public async Task <GitDiff> GitDiffAsync(string repoUri, string baseVersion, string targetVersion)
        {
            CheckForValidGitClient();

            // If base and target are the same, return no diff
            if (baseVersion.Equals(targetVersion, StringComparison.OrdinalIgnoreCase))
            {
                return(GitDiff.NoDiff(baseVersion));
            }

            return(await _gitClient.GitDiffAsync(repoUri, baseVersion, targetVersion));
        }