Skip to content

Commit 3b3fac6

Browse files
committed
refactor: saving time about repo's shared settings (#2108)
- Save repo's settings only when user changed it from `Repository Configuration` dialog and is closing this dialog - Never unload repo's settings (it is very small in memory)
1 parent ef17743 commit 3b3fac6

File tree

3 files changed

+36
-26
lines changed

3 files changed

+36
-26
lines changed

src/Models/RepositorySettings.cs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.IO;
4+
using System.Security.Cryptography;
5+
using System.Text;
36
using System.Text.Json;
7+
using System.Threading.Tasks;
48

59
using Avalonia.Collections;
610

@@ -68,15 +72,12 @@ public AvaloniaList<CustomAction> CustomActions
6872
set;
6973
} = [];
7074

71-
public static RepositorySettings Get(string repo, string gitCommonDir)
75+
public static RepositorySettings Get(string gitCommonDir)
7276
{
7377
var fileInfo = new FileInfo(Path.Combine(gitCommonDir, "sourcegit.settings"));
7478
var fullpath = fileInfo.FullName;
7579
if (_cache.TryGetValue(fullpath, out var setting))
76-
{
77-
setting._usedBy.Add(repo);
7880
return setting;
79-
}
8081

8182
if (!File.Exists(fullpath))
8283
{
@@ -96,28 +97,26 @@ public static RepositorySettings Get(string repo, string gitCommonDir)
9697
}
9798

9899
setting._file = fullpath;
99-
setting._usedBy.Add(repo);
100+
setting._orgHash = HashContent(JsonSerializer.Serialize(setting, JsonCodeGen.Default.RepositorySettings));
100101
_cache.Add(fullpath, setting);
101102
return setting;
102103
}
103104

104-
public void TryUnload(string repo)
105+
public async Task SaveAsync()
105106
{
106-
_usedBy.Remove(repo);
107-
108-
if (_usedBy.Count == 0)
107+
try
109108
{
110-
try
111-
{
112-
using var stream = File.Create(_file);
113-
JsonSerializer.Serialize(stream, this, JsonCodeGen.Default.RepositorySettings);
114-
}
115-
catch
109+
string content = JsonSerializer.Serialize(this, JsonCodeGen.Default.RepositorySettings);
110+
string hash = HashContent(content);
111+
if (!hash.Equals(_orgHash, StringComparison.Ordinal))
116112
{
117-
// Ignore save errors
113+
await File.WriteAllTextAsync(_file, content);
114+
_orgHash = hash;
118115
}
119-
120-
_cache.Remove(_file);
116+
}
117+
catch
118+
{
119+
// Ignore save errors
121120
}
122121
}
123122

@@ -167,8 +166,17 @@ public void MoveCustomActionDown(CustomAction act)
167166
CustomActions.Move(idx + 1, idx);
168167
}
169168

169+
private static string HashContent(string source)
170+
{
171+
var hash = MD5.HashData(Encoding.Default.GetBytes(source));
172+
var builder = new StringBuilder(hash.Length * 2);
173+
foreach (var c in hash)
174+
builder.Append(c.ToString("x2"));
175+
return builder.ToString();
176+
}
177+
170178
private static Dictionary<string, RepositorySettings> _cache = new();
171179
private string _file = string.Empty;
172-
private HashSet<string> _usedBy = new();
180+
private string _orgHash = string.Empty;
173181
}
174182
}

src/ViewModels/Repository.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,10 @@ public Repository(bool isBare, string path, string gitDir)
426426
GitDir = gitDir.Replace('\\', '/').TrimEnd('/');
427427

428428
var commonDirFile = Path.Combine(GitDir, "commondir");
429-
_isWorktree = GitDir.IndexOf("/worktrees/", StringComparison.Ordinal) > 0 &&
429+
var isWorktree = GitDir.IndexOf("/worktrees/", StringComparison.Ordinal) > 0 &&
430430
File.Exists(commonDirFile);
431431

432-
if (_isWorktree)
432+
if (isWorktree)
433433
{
434434
var commonDir = File.ReadAllText(commonDirFile).Trim();
435435
if (!Path.IsPathRooted(commonDir))
@@ -445,7 +445,7 @@ public Repository(bool isBare, string path, string gitDir)
445445

446446
public void Open()
447447
{
448-
_settings = Models.RepositorySettings.Get(FullPath, _gitCommonDir);
448+
_settings = Models.RepositorySettings.Get(_gitCommonDir);
449449
_uiStates = Models.RepositoryUIStates.Load(GitDir);
450450

451451
try
@@ -484,7 +484,6 @@ public void Close()
484484
SelectedView = null; // Do NOT modify. Used to remove exists widgets for GC.Collect
485485
Logs.Clear();
486486

487-
_settings.TryUnload(FullPath);
488487
_uiStates.Unload(_workingCopy.CommitMessage);
489488

490489
if (_cancellationRefreshBranches is { IsCancellationRequested: false })
@@ -1775,6 +1774,9 @@ private void AutoFetchByTimer(object sender)
17751774

17761775
private async Task AutoFetchOnUIThread()
17771776
{
1777+
if (_uiStates == null)
1778+
return;
1779+
17781780
CommandLog log = null;
17791781

17801782
try
@@ -1829,7 +1831,6 @@ private async Task AutoFetchOnUIThread()
18291831
log?.Complete();
18301832
}
18311833

1832-
private readonly bool _isWorktree = false;
18331834
private readonly string _gitCommonDir = null;
18341835
private Models.RepositorySettings _settings = null;
18351836
private Models.RepositoryUIStates _uiStates = null;

src/ViewModels/RepositoryConfigure.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ public async Task SaveAsync()
295295
await SetIfChangedAsync("fetch.prune", EnablePruneOnFetch ? "true" : "false", "false");
296296

297297
await ApplyIssueTrackerChangesAsync();
298+
await _repo.Settings.SaveAsync();
298299
}
299300

300301
private async Task SetIfChangedAsync(string key, string value, string defValue)
@@ -359,8 +360,8 @@ private async Task ApplyIssueTrackerChangesAsync()
359360
}
360361
}
361362

362-
private readonly Repository _repo = null;
363-
private readonly Dictionary<string, string> _cached = null;
363+
private readonly Repository _repo;
364+
private readonly Dictionary<string, string> _cached;
364365
private string _httpProxy;
365366
private Models.CommitTemplate _selectedCommitTemplate = null;
366367
private Models.IssueTracker _selectedIssueTracker = null;

0 commit comments

Comments
 (0)