From 918eb486636513cc7a0d0b1b31a98c13f551b726 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 12 Oct 2023 12:02:41 +0800 Subject: [PATCH] optimize<*>: reduce repository loading time --- src/Commands/Branches.cs | 18 ++++++++---------- src/Commands/Command.cs | 8 ++++++-- src/Commands/Commits.cs | 4 ++-- src/Commands/Stashes.cs | 2 +- src/Commands/Tags.cs | 24 ++++++++---------------- src/Models/Branch.cs | 1 - src/Models/Commit.cs | 11 +++++------ src/Models/User.cs | 13 ++++++++----- 8 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/Commands/Branches.cs b/src/Commands/Branches.cs index 88e767b3..8dfdfae1 100644 --- a/src/Commands/Branches.cs +++ b/src/Commands/Branches.cs @@ -9,8 +9,7 @@ namespace SourceGit.Commands { public class Branches : Command { private static readonly string PREFIX_LOCAL = "refs/heads/"; private static readonly string PREFIX_REMOTE = "refs/remotes/"; - private static readonly string CMD = "branch -l --all -v --format=\"$%(refname)$%(objectname)$%(HEAD)$%(upstream)$%(upstream:track)$%(contents:subject)\""; - private static readonly Regex REG_FORMAT = new Regex(@"\$(.*)\$(.*)\$([\* ])\$(.*)\$(.*?)\$(.*)"); + private static readonly string CMD = "branch -l --all -v --format=\"%(refname)$%(objectname)$%(HEAD)$%(upstream)$%(upstream:track)\""; private static readonly Regex REG_AHEAD = new Regex(@"ahead (\d+)"); private static readonly Regex REG_BEHIND = new Regex(@"behind (\d+)"); @@ -27,11 +26,11 @@ namespace SourceGit.Commands { } public override void OnReadline(string line) { - var match = REG_FORMAT.Match(line); - if (!match.Success) return; + var parts = line.Split('$'); + if (parts.Length != 5) return; var branch = new Models.Branch(); - var refName = match.Groups[1].Value; + var refName = parts[0]; if (refName.EndsWith("/HEAD")) return; if (refName.StartsWith(PREFIX_LOCAL, StringComparison.Ordinal)) { @@ -51,11 +50,10 @@ namespace SourceGit.Commands { } branch.FullName = refName; - branch.Head = match.Groups[2].Value; - branch.IsCurrent = match.Groups[3].Value == "*"; - branch.Upstream = match.Groups[4].Value; - branch.UpstreamTrackStatus = ParseTrackStatus(match.Groups[5].Value); - branch.HeadSubject = match.Groups[6].Value; + branch.Head = parts[1]; + branch.IsCurrent = parts[2] == "*"; + branch.Upstream = parts[3]; + branch.UpstreamTrackStatus = ParseTrackStatus(parts[4]); loaded.Add(branch); } diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index 3c22903b..96f18c3f 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -17,6 +17,7 @@ namespace SourceGit.Commands { /// 命令接口 /// public class Command { + private static readonly Regex PROGRESS_REG = new Regex(@"\d+%"); /// /// 读取全部输出时的结果 @@ -68,7 +69,6 @@ namespace SourceGit.Commands { if (!string.IsNullOrEmpty(Cwd)) start.WorkingDirectory = Cwd; - var progressFilter = new Regex(@"\s\d+%\s"); var errs = new List(); var proc = new Process() { StartInfo = start }; var isCancelled = false; @@ -97,8 +97,12 @@ namespace SourceGit.Commands { if (string.IsNullOrEmpty(e.Data)) return; if (TraitErrorAsOutput) OnReadline(e.Data); - if (progressFilter.IsMatch(e.Data)) return; + // 错误信息中忽略进度相关的输出 + if (e.Data.StartsWith("remote: Enumerating objects:", StringComparison.Ordinal)) return; if (e.Data.StartsWith("remote: Counting objects:", StringComparison.Ordinal)) return; + if (e.Data.StartsWith("remote: Compressing objects:", StringComparison.Ordinal)) return; + if (e.Data.StartsWith("Filtering content:", StringComparison.Ordinal)) return; + if (PROGRESS_REG.IsMatch(e.Data)) return; errs.Add(e.Data); }; diff --git a/src/Commands/Commits.cs b/src/Commands/Commits.cs index b1b4c28f..f70528db 100644 --- a/src/Commands/Commits.cs +++ b/src/Commands/Commits.cs @@ -77,13 +77,13 @@ namespace SourceGit.Commands { } else if (line.StartsWith("author ", StringComparison.Ordinal)) { Models.User user = Models.User.Invalid; ulong time = 0; - Models.Commit.ParseUserAndTime(line, ref user, ref time); + Models.Commit.ParseUserAndTime(line.Substring(7), ref user, ref time); current.Author = user; current.AuthorTime = time; } else if (line.StartsWith("committer ", StringComparison.Ordinal)) { Models.User user = Models.User.Invalid; ulong time = 0; - Models.Commit.ParseUserAndTime(line, ref user, ref time); + Models.Commit.ParseUserAndTime(line.Substring(10), ref user, ref time); current.Committer = user; current.CommitterTime = time; } else if (string.IsNullOrEmpty(current.Subject)) { diff --git a/src/Commands/Stashes.cs b/src/Commands/Stashes.cs index 3e7d9713..5668ff64 100644 --- a/src/Commands/Stashes.cs +++ b/src/Commands/Stashes.cs @@ -39,7 +39,7 @@ namespace SourceGit.Commands { } else if (line.StartsWith("author ", StringComparison.Ordinal)) { Models.User user = Models.User.Invalid; ulong time = 0; - Models.Commit.ParseUserAndTime(line, ref user, ref time); + Models.Commit.ParseUserAndTime(line.Substring(7), ref user, ref time); current.Author = user; current.Time = time; } diff --git a/src/Commands/Tags.cs b/src/Commands/Tags.cs index f534c7b2..738c86db 100644 --- a/src/Commands/Tags.cs +++ b/src/Commands/Tags.cs @@ -1,5 +1,5 @@ +using System; using System.Collections.Generic; -using System.Text.RegularExpressions; namespace SourceGit.Commands { /// @@ -7,8 +7,6 @@ namespace SourceGit.Commands { /// public class Tags : Command { public static readonly string CMD = "for-each-ref --sort=-creatordate --format=\"$%(refname:short)$%(objectname)$%(*objectname)\" refs/tags"; - public static readonly Regex REG_FORMAT = new Regex(@"\$(.*)\$(.*)\$(.*)"); - private List loaded = new List(); public Tags(string path) { @@ -22,22 +20,16 @@ namespace SourceGit.Commands { } public override void OnReadline(string line) { - var match = REG_FORMAT.Match(line); - if (!match.Success) return; - - var name = match.Groups[1].Value; - var commit = match.Groups[2].Value; - var dereference = match.Groups[3].Value; - - if (string.IsNullOrEmpty(dereference)) { + var subs = line.Split(new char[] { '$' }, StringSplitOptions.RemoveEmptyEntries); + if (subs.Length == 2) { loaded.Add(new Models.Tag() { - Name = name, - SHA = commit, + Name = subs[0], + SHA = subs[1], }); - } else { + } else if (subs.Length == 3) { loaded.Add(new Models.Tag() { - Name = name, - SHA = dereference, + Name = subs[0], + SHA = subs[2], }); } } diff --git a/src/Models/Branch.cs b/src/Models/Branch.cs index f6d63b50..9f88c4c8 100644 --- a/src/Models/Branch.cs +++ b/src/Models/Branch.cs @@ -6,7 +6,6 @@ namespace SourceGit.Models { public string Name { get; set; } public string FullName { get; set; } public string Head { get; set; } - public string HeadSubject { get; set; } public bool IsLocal { get; set; } public bool IsCurrent { get; set; } public string Upstream { get; set; } diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index ed60faae..141f6b9e 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text.RegularExpressions; using System.Windows; namespace SourceGit.Models { @@ -8,7 +7,6 @@ namespace SourceGit.Models { /// 提交记录 /// public class Commit { - private static readonly Regex REG_USER_FORMAT = new Regex(@"\w+ (.*) <(.*)> (\d{10}) [\+\-]\d+"); private static readonly DateTime UTC_START = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).ToLocalTime(); public string SHA { get; set; } = string.Empty; @@ -31,11 +29,12 @@ namespace SourceGit.Models { public string CommitterTimeShortStr => UTC_START.AddSeconds(CommitterTime).ToString("yyyy/MM/dd"); public static void ParseUserAndTime(string data, ref User user, ref ulong time) { - var match = REG_USER_FORMAT.Match(data); - if (!match.Success) return; + var userEndIdx = data.IndexOf('>'); + if (userEndIdx < 0) return; - user = User.FindOrAdd(match.Groups[1].Value, match.Groups[2].Value); - time = ulong.Parse(match.Groups[3].Value); + var timeEndIdx = data.IndexOf(' ', userEndIdx + 2); + user = User.FindOrAdd(data.Substring(0, userEndIdx)); + time = timeEndIdx < 0 ? 0 : ulong.Parse(data.Substring(userEndIdx + 2, timeEndIdx - userEndIdx - 2)); } } } diff --git a/src/Models/User.cs b/src/Models/User.cs index bc3aeb3d..9af6bdcf 100644 --- a/src/Models/User.cs +++ b/src/Models/User.cs @@ -22,13 +22,16 @@ namespace SourceGit.Models { return base.GetHashCode(); } - public static User FindOrAdd(string name, string email) { - string key = $"{name}#&#{email}"; - if (Caches.ContainsKey(key)) { - return Caches[key]; + public static User FindOrAdd(string data) { + if (Caches.ContainsKey(data)) { + return Caches[data]; } else { + var nameEndIdx = data.IndexOf('<'); + var name = nameEndIdx >= 2 ? data.Substring(0, nameEndIdx - 1) : string.Empty; + var email = data.Substring(nameEndIdx + 1); + User user = new User() { Name = name, Email = email }; - Caches.Add(key, user); + Caches.Add(data, user); return user; } }