From 1ee7d1184ea2fc8559a3903ad487a2fc0f0d6a64 Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 22 May 2025 11:02:54 +0800 Subject: [PATCH] enhance: only refresh submodules when it is needed (#1344) Signed-off-by: leo --- src/Models/IRepository.cs | 2 ++ src/Models/Remote.cs | 2 +- src/Models/Watcher.cs | 22 ++++++++------- src/ViewModels/Repository.cs | 52 ++++++++++++++++++++++++++++++++++-- 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/Models/IRepository.cs b/src/Models/IRepository.cs index 0224d81f..2fc7c612 100644 --- a/src/Models/IRepository.cs +++ b/src/Models/IRepository.cs @@ -2,6 +2,8 @@ { public interface IRepository { + bool MayHaveSubmodules(); + void RefreshBranches(); void RefreshWorktrees(); void RefreshTags(); diff --git a/src/Models/Remote.cs b/src/Models/Remote.cs index 2f6c7dc1..6e36cfb9 100644 --- a/src/Models/Remote.cs +++ b/src/Models/Remote.cs @@ -50,7 +50,7 @@ namespace SourceGit.Models return true; } - return url.StartsWith("file://", StringComparison.Ordinal) || + return url.StartsWith("file://", StringComparison.Ordinal) || url.StartsWith("./", StringComparison.Ordinal) || url.StartsWith("../", StringComparison.Ordinal) || Directory.Exists(url); diff --git a/src/Models/Watcher.cs b/src/Models/Watcher.cs index 81b4605b..928951ca 100644 --- a/src/Models/Watcher.cs +++ b/src/Models/Watcher.cs @@ -107,7 +107,6 @@ namespace SourceGit.Models { _updateBranch = 0; _updateWC = 0; - _updateSubmodules = 0; if (_updateTags > 0) { @@ -115,10 +114,15 @@ namespace SourceGit.Models Task.Run(_repo.RefreshTags); } + if (_updateSubmodules > 0 || _repo.MayHaveSubmodules()) + { + _updateSubmodules = 0; + Task.Run(_repo.RefreshSubmodules); + } + Task.Run(_repo.RefreshBranches); Task.Run(_repo.RefreshCommits); Task.Run(_repo.RefreshWorkingCopyChanges); - Task.Run(_repo.RefreshSubmodules); Task.Run(_repo.RefreshWorktrees); } @@ -150,12 +154,13 @@ namespace SourceGit.Models private void OnRepositoryChanged(object o, FileSystemEventArgs e) { - if (string.IsNullOrEmpty(e.Name) || e.Name.EndsWith(".lock", StringComparison.Ordinal)) + if (string.IsNullOrEmpty(e.Name)) return; var name = e.Name.Replace("\\", "/"); - - if (name.Contains("fsmonitor--daemon/", StringComparison.Ordinal)) + if (name.Contains("fsmonitor--daemon/", StringComparison.Ordinal) || + name.EndsWith(".lock", StringComparison.Ordinal) || + name.StartsWith("lfs/", StringComparison.Ordinal)) return; if (name.StartsWith("modules", StringComparison.Ordinal)) @@ -170,8 +175,8 @@ namespace SourceGit.Models else if (name.Equals("MERGE_HEAD", StringComparison.Ordinal) || name.Equals("AUTO_MERGE", StringComparison.Ordinal)) { - _updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime(); - _updateWC = DateTime.Now.AddSeconds(1).ToFileTime(); + if (_repo.MayHaveSubmodules()) + _updateSubmodules = DateTime.Now.AddSeconds(1).ToFileTime(); } else if (name.StartsWith("refs/tags", StringComparison.Ordinal)) { @@ -201,13 +206,12 @@ namespace SourceGit.Models return; var name = e.Name.Replace("\\", "/"); - if (name.Equals(".git", StringComparison.Ordinal) || name.StartsWith(".git/", StringComparison.Ordinal) || name.EndsWith("/.git", StringComparison.Ordinal)) return; - if (name.StartsWith(".vs/", StringComparison.Ordinal) && name.EndsWith("/.suo", StringComparison.Ordinal)) + if (name.StartsWith(".vs/", StringComparison.Ordinal)) return; if (name.Equals(".gitmodules", StringComparison.Ordinal)) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 5c2986fa..14162eba 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1093,6 +1093,13 @@ namespace SourceGit.ViewModels }); } + public bool MayHaveSubmodules() + { + var modulesFile = Path.Combine(_fullpath, ".gitmodules"); + var info = new FileInfo(modulesFile); + return info.Exists && info.Length > 20; + } + public void RefreshBranches() { var branches = new Commands.QueryBranches(_fullpath).Result(out var localBranchesCount); @@ -1196,13 +1203,54 @@ namespace SourceGit.ViewModels public void RefreshSubmodules() { + if (!MayHaveSubmodules()) + { + if (_submodules.Count > 0) + { + Dispatcher.UIThread.Invoke(() => + { + Submodules = []; + VisibleSubmodules = BuildVisibleSubmodules(); + }); + } + + return; + } + var submodules = new Commands.QuerySubmodules(_fullpath).Result(); _watcher?.SetSubmodules(submodules); Dispatcher.UIThread.Invoke(() => { - Submodules = submodules; - VisibleSubmodules = BuildVisibleSubmodules(); + bool hasChanged = _submodules.Count != submodules.Count; + if (!hasChanged) + { + var old = new Dictionary(); + foreach (var module in _submodules) + old.Add(module.Path, module); + + foreach (var module in submodules) + { + if (!old.TryGetValue(module.Path, out var exist)) + { + hasChanged = true; + break; + } + + hasChanged = !exist.SHA.Equals(module.SHA, StringComparison.Ordinal) || + !exist.URL.Equals(module.URL, StringComparison.Ordinal) || + exist.Status != module.Status; + + if (hasChanged) + break; + } + } + + if (hasChanged) + { + Submodules = submodules; + VisibleSubmodules = BuildVisibleSubmodules(); + } }); }