From bdd979eb58af0782f76fdb8668fe32a58aed5dba Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 17 Dec 2020 13:12:52 +0800 Subject: [PATCH] optimize: use binary search to find first ancestor of current HEAD when HEAD is filtered out --- src/Git/Commit.cs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/Git/Commit.cs b/src/Git/Commit.cs index 6646791b..ae3a326a 100644 --- a/src/Git/Commit.cs +++ b/src/Git/Commit.cs @@ -153,6 +153,17 @@ namespace SourceGit.Git { commits.Add(current); } + if (!findHead && commits.Count > 0) { + if (commits[commits.Count - 1].IsAncestorOfHead(repo)) { + if (commits.Count == 1) { + commits[0].IsMerged = true; + } else { + var head = FindFirstMerged(repo, commits, 0, commits.Count - 1); + if (head != null) head.IsMerged = true; + } + } + } + return commits; } @@ -277,6 +288,41 @@ namespace SourceGit.Git { File.Delete(bat); } + private bool IsAncestorOfHead(Repository repo) { + var startInfo = new ProcessStartInfo(); + startInfo.FileName = App.Setting.Tools.GitExecutable; + startInfo.Arguments = $"merge-base --is-ancestor {SHA} HEAD"; + startInfo.WorkingDirectory = repo.Path; + startInfo.UseShellExecute = false; + startInfo.CreateNoWindow = true; + startInfo.RedirectStandardOutput = false; + startInfo.RedirectStandardError = false; + + var proc = new Process() { StartInfo = startInfo }; + proc.Start(); + proc.WaitForExit(); + + var ret = proc.ExitCode; + proc.Close(); + return ret == 0; + } + + private static Commit FindFirstMerged(Repository repo, List commits, int start, int end) { + var isStartAncestor = commits[start].IsAncestorOfHead(repo); + if (isStartAncestor) return commits[start]; + + if (end - start <= 1) { + return commits[end]; + } else { + var mid = (int)Math.Floor((end + start) * 0.5f); + if (commits[mid].IsAncestorOfHead(repo)) { + return FindFirstMerged(repo, commits, start + 1, mid); + } else { + return FindFirstMerged(repo, commits, mid + 1, end); + } + } + } + private static void ParseSHA(Commit commit, string data) { var decoratorStart = data.IndexOf('('); if (decoratorStart < 0) {