From 6d83bd1ae4d1a68c03816273b9fe6ea5f4087dc6 Mon Sep 17 00:00:00 2001 From: Michael Seibt Date: Mon, 10 Sep 2018 01:02:59 +0200 Subject: [PATCH] #5125 RevisionGrid Graph: Branches and tags in tooltip. --- .../Columns/CommitIdColumnProvider.cs | 21 ++- .../Columns/GraphColumnProvider.cs | 159 ++++++++++++------ 2 files changed, 129 insertions(+), 51 deletions(-) diff --git a/GitUI/UserControls/RevisionGrid/Columns/CommitIdColumnProvider.cs b/GitUI/UserControls/RevisionGrid/Columns/CommitIdColumnProvider.cs index fed8f27d4ed..f2df984f3a7 100644 --- a/GitUI/UserControls/RevisionGrid/Columns/CommitIdColumnProvider.cs +++ b/GitUI/UserControls/RevisionGrid/Columns/CommitIdColumnProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; +using System.Text; using System.Windows.Forms; using GitCommands; using GitExtUtils.GitUI; @@ -66,8 +67,26 @@ public override bool TryGetToolTip(DataGridViewCellMouseEventArgs e, GitRevision return false; } - toolTip = revision.Guid; + toolTip = Format(revision.Guid); return true; } + + public static string Format(string guid) + { + var text = new StringBuilder(); + for (int pos = 0, length = guid.Length; pos < length; pos += 4) + { + if (pos > 0) + { + text.Append(MinimumSpace); + } + + text.Append(guid.Substring(pos, 4)); + } + + return text.ToString(); + } + + private const char MinimumSpace = '\x200A'; } } \ No newline at end of file diff --git a/GitUI/UserControls/RevisionGrid/Columns/GraphColumnProvider.cs b/GitUI/UserControls/RevisionGrid/Columns/GraphColumnProvider.cs index 8082a2e86ec..7cf5c122901 100644 --- a/GitUI/UserControls/RevisionGrid/Columns/GraphColumnProvider.cs +++ b/GitUI/UserControls/RevisionGrid/Columns/GraphColumnProvider.cs @@ -554,7 +554,7 @@ string GetLaneInfo(int x, int rowIndex) { if (!node.Revision.IsArtificial) { - laneInfoText.AppendLine(node.Revision.Guid); + laneInfoText.AppendLine(CommitIdColumnProvider.Format(node.Revision.Guid)); var references = new References(node); @@ -567,6 +567,14 @@ string GetLaneInfo(int x, int rowIndex) } } + laneInfoText.Append(Format("\nContained in branches: {0}\n", references.Branches)); + laneInfoText.Append(Format("\nContained in tags: {0}\n", references.Tags)); + + string Format(string format, IEnumerable list) + { + return list.Any() ? string.Format(format, string.Join(", ", list)) : string.Empty; + } + // laneInfoText.Append(references.DebugInfo); laneInfoText.AppendLine().AppendLine(); @@ -592,9 +600,60 @@ string GetLaneInfo(int x, int rowIndex) } } + private class Reference + { + internal readonly string LocalName; + internal bool IsLocal { get; private set; } = false; + internal List Remotes { get; } = new List(); + + internal Reference(string localName) + { + LocalName = localName; + } + + internal void Add([NotNull] IGitRef gitReference) + { + if (gitReference.IsHead) + { + IsLocal = true; + } + else if (gitReference.IsRemote) + { + Remotes.Add(gitReference.Remote); + } + } + + public override string ToString() + { + var list = new StringBuilder(); + + if (Remotes.Any()) + { + if (IsLocal) + { + list.Append("["); + } + + list.Append(Remotes.Join("|")).Append("/"); + + if (IsLocal) + { + list.Append("]"); + } + } + + list.Append(LocalName); + + return list.ToString(); + } + } + private class References { private HashSet _visitedNodes = new HashSet(); + private Dictionary _referenceByName = new Dictionary(); + internal List Tags { get; } = new List(); + internal List Branches { get; } = new List(); internal string CommittedTo { get; private set; } internal string MergedWith { get; private set; } internal StringBuilder DebugInfo = new StringBuilder(); @@ -604,15 +663,12 @@ internal References([NotNull] Node node) AddReferencesOf(node, previousDescJunction: null); } - private bool AddReferencesOf([NotNull] Node node, [CanBeNull] Junction previousDescJunction) + private void AddReferencesOf([NotNull] Node node, [CanBeNull] Junction previousDescJunction) { if (_visitedNodes.Add(node)) { - if (CheckForMerge(node, previousDescJunction) || FindBranch(node, node, previousDescJunction)) - { - return true; - } - + CheckForMerge(node, previousDescJunction); + node.Revision.Refs.ForEach(reference => Add(reference, node, previousDescJunction)); foreach (var descJunction in node.Descendants) { // iterate the inner nodes (i.e. excluding the youngest) beginning with the oldest @@ -622,10 +678,7 @@ private bool AddReferencesOf([NotNull] Node node, [CanBeNull] Junction previousD Node innerNode = descJunction[nodeIndex]; if (nodeFound) { - if (FindBranch(innerNode, node, descJunction)) - { - return true; - } + innerNode.Revision.Refs.ForEach(reference => Add(reference, node, descJunction)); } else { @@ -634,38 +687,43 @@ private bool AddReferencesOf([NotNull] Node node, [CanBeNull] Junction previousD } // handle the youngest and its descendants - if (AddReferencesOf(descJunction.Youngest, descJunction)) - { - return true; - } + AddReferencesOf(descJunction.Youngest, descJunction); } } - - return false; } - private bool FindBranch([NotNull] Node descNode, [NotNull] Node node, [CanBeNull] Junction descJunction) + private void Add([NotNull] IGitRef gitReference, [NotNull] Node node, [CanBeNull] Junction descJunction) { - foreach (var gitReference in descNode.Revision.Refs) + Reference reference; + if (!_referenceByName.TryGetValue(gitReference.LocalName, out reference)) { - if (gitReference.IsHead || gitReference.IsRemote) + reference = new Reference(gitReference.LocalName); + _referenceByName.Add(gitReference.LocalName, reference); + if (gitReference.IsTag) { - CheckForMerge(node, descJunction); - CommittedTo = CommittedTo ?? gitReference.Name; - return true; + Tags.Add(reference); + } + else if (gitReference.IsHead || gitReference.IsRemote) + { + Branches.Add(reference); + if (CommittedTo == null) + { + CheckForMerge(node, descJunction); + CommittedTo = CommittedTo ?? gitReference.Name; + } } else if (gitReference.IsStash && CommittedTo == null) { CommittedTo = gitReference.Name; - return true; } } - return false; + reference.Add(gitReference); } /// /// Checks whether the commit message is a merge message + /// though only if CommittedTo has not been set yet /// and then if its a merge message, sets CommittedTo and MergedWith. /// /// MergedWith is set if it is the current node, i.e. on the first call. @@ -677,38 +735,39 @@ private bool FindBranch([NotNull] Node descNode, [NotNull] Node node, [CanBeNull /// the descending junction the node is part of /// (used for the decision whether the node belongs the first or second branch of the merge) /// - private bool CheckForMerge([NotNull] Node node, [CanBeNull] Junction descJunction) + private void CheckForMerge([NotNull] Node node, [CanBeNull] Junction descJunction) { - bool isTheFirstBranch = descJunction == null || node.Ancestors.Count == 0 || node.Ancestors.First() == descJunction; - string mergedInto; - string mergedWith; - (mergedInto, mergedWith) = ParseMergeMessage(node, appendPullRequest: isTheFirstBranch); - - if (mergedInto != null) + if (CommittedTo == null) { - CommittedTo = isTheFirstBranch ? mergedInto : mergedWith; - } + bool isTheFirstBranch = descJunction == null || node.Ancestors.Count == 0 || node.Ancestors.First() == descJunction; + string mergedInto; + string mergedWith; + (mergedInto, mergedWith) = ParseMergeMessage(node, appendPullRequest: isTheFirstBranch); - if (MergedWith == null) - { - MergedWith = mergedWith ?? string.Empty; - } + if (mergedInto != null) + { + CommittedTo = isTheFirstBranch ? mergedInto : mergedWith; + } - if (CommittedTo != null) - { - DebugInfo.AppendFormat(" node: {0}, branch: {1}, descJunction {2} isTheFirstBranch {3}\n", - node.Revision.Guid.Substring(0, 8), CommittedTo, descJunction?.ToString() ?? "(null)", isTheFirstBranch); - foreach (var ancJunction in node.Ancestors) + if (MergedWith == null) { - DebugInfo.AppendFormat(" {2}anc {0} -> {1} {3}\n", - ancJunction.Oldest.Revision.Guid.Substring(0, 8), - ancJunction.Youngest.Revision.Guid.Substring(0, 8), - ancJunction == descJunction ? ">\x200A" : " ", - ancJunction == descJunction ? CommittedTo + " " + MergedWith : ""); + MergedWith = mergedWith ?? string.Empty; } - } - return CommittedTo != null; + if (CommittedTo != null) + { + DebugInfo.AppendFormat(" node: {0}, branch: {1}, descJunction {2} isTheFirstBranch {3}\n", + node.Revision.Guid.Substring(0, 8), CommittedTo, descJunction?.ToString() ?? "(null)", isTheFirstBranch); + foreach (var ancJunction in node.Ancestors) + { + DebugInfo.AppendFormat(" {2}anc {0} -> {1} {3}\n", + ancJunction.Oldest.Revision.Guid.Substring(0, 8), + ancJunction.Youngest.Revision.Guid.Substring(0, 8), + ancJunction == descJunction ? ">\x200A" : " ", + ancJunction == descJunction ? CommittedTo + " " + MergedWith : ""); + } + } + } } private static readonly Regex _merge = new Regex("(?i)^merged? (pull request (.*) from )?(.*branch )?'?([^ ']+)'?( into (.*))?\\.?$");