示例#1
0
        public void Render(
            ITree tree,
            IRemote usedRemote,
            IBranchesKnowledge branchesKnowledge,
            ITreeRenderingOptions options)
        {
            IRemoteWebUrlProvider remoteUrlProvider =
                _remoteWebUrlProviderFactory.CreateUrlProvider(usedRemote.Url, options.ForceTreatAsGitHub);

            WriteHeader();

            IBranch[] branchesWithNodes     = tree.Branches.Where(b => tree.EnumerateNodes(b).Any()).ToArray();
            IBranch[] currentBranchesSorted = OrderByFirstCommitDate(branchesWithNodes, tree).ToArray();

            IPairList <INode, INode> unwrittenMerges = new PairList <INode, INode>();
            IPairList <INode, INode> writtenMerges   = new PairList <INode, INode>();

            // Main branches.
            foreach (IBranch b in currentBranchesSorted)
            {
                _gvWriter.EmptyLine();
                _gvWriter.Comment($"Branch {b.Label}.");

                using (_gvWriter.StartSubGraph())
                {
                    _gvWriter.SetNodeAttributes(AttrSet.Empty.Group(b.Label));

                    Color drawColor = branchesKnowledge.GetSuggestedDrawingColorFor(b);
                    bool  isLesser  = branchesKnowledge.IsAWorkItemBranch(b);

                    IAttrSet nodeStyle = _style.GetBranchNodeStyle(drawColor, isLesser);
                    IAttrSet edgeStyle = _style.GetBranchEdgeStyle(drawColor, isLesser);

                    _gvWriter.SetNodeAttributes(nodeStyle);
                    _gvWriter.SetEdgeAttributes(edgeStyle);

                    INode[] nodes = tree.EnumerateNodes(b).ToArray();

                    for (int i = 0; i < nodes.Length; i++)
                    {
                        INode currentNode = nodes[i];

                        WriteNode(currentNode, remoteUrlProvider);

                        if (i == 0)
                        {
                            // Starting node.
                            INode parent    = currentNode.Parents.FirstOrDefault();
                            bool  hasParent = parent != null;
                            if (!hasParent)
                            {
                                _gvWriter.Comment("Starting line.");
                                string id = string.Format($"{currentNode.Commit.Treeish}_start");
                                // Write starting empty node.
                                using (_gvWriter.StartSubGraph())
                                {
                                    _gvWriter.RawAttributes(AttrSet.Empty.Rank(RankType.Source));

                                    _gvWriter.Node(id, AttrSet.Empty.Width(0).Height(0).PenWidth(0));
                                }

                                _gvWriter.Edge(id, currentNode.Commit, _style.EdgeBranchStartVirtual);
                                _gvWriter.EmptyLine();
                            }
                            else
                            {
                                // It is some other branch, and we draw that edge.
                                WriteEdge(parent, currentNode, remoteUrlProvider);
                                writtenMerges.Add(parent, currentNode);
                            }
                        }

                        bool  isLast   = i == nodes.Length - 1;
                        INode nextNode = isLast ? null : nodes[i + 1];

                        if (!isLast)
                        {
                            // Edge to the next node.
                            WriteEdge(currentNode, nextNode, remoteUrlProvider);
                        }
                        else
                        {
                            WriteBranchPointer(b, tree, isLesser, remoteUrlProvider);
                        }

                        INode[] otherChildren = currentNode.Children.Except(nextNode).ToArray();
                        foreach (INode child in otherChildren)
                        {
                            unwrittenMerges.Add(currentNode, child);
                        }
                    }
                }
            }

            IBranch[] branchesWithoutNodes = tree.Branches.Except(branchesWithNodes).ToArray();
            foreach (IBranch b in branchesWithoutNodes)
            {
                bool isLesser = branchesKnowledge.IsAWorkItemBranch(b);
                WriteBranchPointer(b, tree, isLesser, remoteUrlProvider);
            }

            // Tags.
            ITag[] tags = tree.Tags.ToArray();
            foreach (ITag t in tags)
            {
                _gvWriter.EmptyLine();

                INode  n  = tree.GetNode(t.Tip);
                string id = MakeNodeIdForPointerLabel(n, t);

                using (_gvWriter.StartSubGraph())
                {
                    _gvWriter.Comment($"Tag {t.Label}.");
                    _gvWriter.RawAttributes(AttrSet.Empty.Rank(RankType.Same));

                    string url = remoteUrlProvider?.GetTagLink(t);

                    _gvWriter.Node(id, _style.LabelTag.Label(t.Label).Url(url));

                    _gvWriter.Edge(n.Commit, id, _style.EdgeTagLabel);
                }
            }

            INode[] allLeftOvers = tree.Nodes.Where(n => tree.GetContainingBranch(n) == null).ToArray();
            if (allLeftOvers.Length > 0)
            {
                using (_gvWriter.StartSubGraph())
                {
                    _gvWriter.EmptyLine();
                    _gvWriter.Comment("Leftover nodes.");
                    _gvWriter.SetNodeAttributes(_style.NodeOrphaned);

                    foreach (INode currentNode in allLeftOvers)
                    {
                        WriteNode(currentNode, remoteUrlProvider);
                        // Remember children.
                        foreach (INode child in currentNode.Children)
                        {
                            unwrittenMerges.Add(currentNode, child);
                        }
                    }
                }
            }

            PairList <INode, INode> edgesToWrite = unwrittenMerges.Except(writtenMerges).ToPairList();

            if (edgesToWrite.Count > 0)
            {
                using (_gvWriter.StartSubGraph())
                {
                    _gvWriter.EmptyLine();
                    _gvWriter.Comment("Other edges.");
                    _gvWriter.SetEdgeAttributes(_style.EdgeOther);

                    foreach (Tuple <INode, INode> edge in edgesToWrite)
                    {
                        _gvWriter.Edge(edge.Item1.Commit, edge.Item2.Commit);
                    }
                }
            }

            WriteFooter();
        }