Skip to content

Commit ecfe914

Browse files
committed
fix: modified/renamed issue tracker rule can not be saved (#1768)
This commit also change the way to save modified issue tracker - It will be saved when closing the `Repository Configuration` dialog. Signed-off-by: leo <[email protected]>
1 parent aa26885 commit ecfe914

File tree

6 files changed

+131
-93
lines changed

6 files changed

+131
-93
lines changed

src/Commands/IssueTracker.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@ namespace SourceGit.Commands
77
{
88
public class IssueTracker : Command
99
{
10-
public IssueTracker(string repo, string storage)
10+
public IssueTracker(string repo, bool isShared)
1111
{
1212
WorkingDirectory = repo;
1313
Context = repo;
1414

15-
if (string.IsNullOrEmpty(storage))
15+
if (isShared)
1616
{
17-
_isStorageFileExists = true;
18-
_baseArg = "config --local";
17+
var storage = $"{repo}/.issuetracker";
18+
_isStorageFileExists = File.Exists(storage);
19+
_baseArg = $"config -f {storage.Quoted()}";
1920
}
2021
else
2122
{
22-
_isStorageFileExists = File.Exists(storage);
23-
_baseArg = $"config -f {storage.Quoted()}";
23+
_isStorageFileExists = true;
24+
_baseArg = "config --local";
2425
}
2526
}
2627

@@ -79,12 +80,24 @@ public async Task<bool> AddAsync(Models.IssueTracker rule)
7980
return false;
8081
}
8182

82-
public async Task<bool> RemoveAsync(Models.IssueTracker rule)
83+
public async Task<bool> UpdateRegexAsync(Models.IssueTracker rule)
84+
{
85+
Args = $"{_baseArg} issuetracker.{rule.Name.Quoted()}.regex {rule.RegexString.Quoted()}";
86+
return await ExecAsync().ConfigureAwait(false);
87+
}
88+
89+
public async Task<bool> UpdateURLTemplateAsync(Models.IssueTracker rule)
90+
{
91+
Args = $"{_baseArg} issuetracker.{rule.Name.Quoted()}.url {rule.URLTemplate.Quoted()}";
92+
return await ExecAsync().ConfigureAwait(false);
93+
}
94+
95+
public async Task<bool> RemoveAsync(string name)
8396
{
8497
if (!_isStorageFileExists)
8598
return true;
8699

87-
Args = $"{_baseArg} --remove-section issuetracker.{rule.Name.Quoted()}";
100+
Args = $"{_baseArg} --remove-section issuetracker.{name.Quoted()}";
88101
return await ExecAsync().ConfigureAwait(false);
89102
}
90103

src/Models/IssueTracker.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,11 @@ public string RegexString
2626
{
2727
try
2828
{
29-
_regex = null;
3029
_regex = new Regex(_regexString, RegexOptions.Multiline);
3130
}
3231
catch
3332
{
34-
// Ignore errors.
33+
_regex = null;
3534
}
3635
}
3736

src/ViewModels/Repository.cs

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -740,39 +740,6 @@ public CommandLog CreateLog(string name)
740740
return log;
741741
}
742742

743-
public async Task<Models.IssueTracker> AddIssueTrackerAsync(string name, string regex, string url)
744-
{
745-
var rule = new Models.IssueTracker()
746-
{
747-
IsShared = false,
748-
Name = name,
749-
RegexString = regex,
750-
URLTemplate = url,
751-
};
752-
753-
var succ = await CreateIssueTrackerCommand(false).AddAsync(rule);
754-
if (succ)
755-
{
756-
IssueTrackers.Add(rule);
757-
return rule;
758-
}
759-
760-
return null;
761-
}
762-
763-
public async Task RemoveIssueTrackerAsync(Models.IssueTracker rule)
764-
{
765-
var succ = await CreateIssueTrackerCommand(rule.IsShared).RemoveAsync(rule);
766-
if (succ)
767-
IssueTrackers.Remove(rule);
768-
}
769-
770-
public async Task ChangeIssueTrackerShareModeAsync(Models.IssueTracker rule)
771-
{
772-
await CreateIssueTrackerCommand(!rule.IsShared).RemoveAsync(rule);
773-
await CreateIssueTrackerCommand(rule.IsShared).AddAsync(rule);
774-
}
775-
776743
public void RefreshAll()
777744
{
778745
RefreshCommits();
@@ -786,8 +753,8 @@ public void RefreshAll()
786753
Task.Run(async () =>
787754
{
788755
var issuetrackers = new List<Models.IssueTracker>();
789-
await CreateIssueTrackerCommand(true).ReadAllAsync(issuetrackers, true).ConfigureAwait(false);
790-
await CreateIssueTrackerCommand(false).ReadAllAsync(issuetrackers, false).ConfigureAwait(false);
756+
await new Commands.IssueTracker(FullPath, true).ReadAllAsync(issuetrackers, true).ConfigureAwait(false);
757+
await new Commands.IssueTracker(FullPath, false).ReadAllAsync(issuetrackers, false).ConfigureAwait(false);
791758
Dispatcher.UIThread.Post(() =>
792759
{
793760
IssueTrackers.Clear();
@@ -1743,11 +1710,6 @@ private LauncherPage GetOwnerPage()
17431710
return null;
17441711
}
17451712

1746-
private Commands.IssueTracker CreateIssueTrackerCommand(bool shared)
1747-
{
1748-
return new Commands.IssueTracker(FullPath, shared ? $"{FullPath}/.issuetracker" : null);
1749-
}
1750-
17511713
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
17521714
{
17531715
var builder = new BranchTreeNode.Builder(_settings.LocalBranchSortMode, _settings.RemoteBranchSortMode);

src/ViewModels/RepositoryConfigure.cs

Lines changed: 86 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Threading.Tasks;
34

45
using Avalonia.Collections;
@@ -114,8 +115,8 @@ public Models.CommitTemplate SelectedCommitTemplate
114115

115116
public AvaloniaList<Models.IssueTracker> IssueTrackers
116117
{
117-
get => _repo.IssueTrackers;
118-
}
118+
get;
119+
} = [];
119120

120121
public Models.IssueTracker SelectedIssueTracker
121122
{
@@ -176,6 +177,17 @@ public RepositoryConfigure(Repository repo)
176177
HttpProxy = proxy;
177178
if (_cached.TryGetValue("fetch.prune", out var prune))
178179
EnablePruneOnFetch = (prune == "true");
180+
181+
foreach (var rule in _repo.IssueTrackers)
182+
{
183+
IssueTrackers.Add(new()
184+
{
185+
IsShared = rule.IsShared,
186+
Name = rule.Name,
187+
RegexString = rule.RegexString,
188+
URLTemplate = rule.URLTemplate,
189+
});
190+
}
179191
}
180192

181193
public void ClearHttpProxy()
@@ -208,25 +220,28 @@ public List<string> GetRemoteVisitUrls()
208220
return outs;
209221
}
210222

211-
public async Task AddIssueTrackerAsync(string name, string regex, string url)
223+
public void AddIssueTracker(string name, string regex, string url)
212224
{
213-
SelectedIssueTracker = await _repo.AddIssueTrackerAsync(name, regex, url);
225+
var rule = new Models.IssueTracker()
226+
{
227+
IsShared = false,
228+
Name = name,
229+
RegexString = regex,
230+
URLTemplate = url,
231+
};
232+
233+
IssueTrackers.Add(rule);
234+
SelectedIssueTracker = rule;
214235
}
215236

216-
public async Task RemoveIssueTrackerAsync()
237+
public void RemoveIssueTracker()
217238
{
218239
if (_selectedIssueTracker is { } rule)
219-
await _repo.RemoveIssueTrackerAsync(rule);
240+
IssueTrackers.Remove(rule);
220241

221242
SelectedIssueTracker = null;
222243
}
223244

224-
public async Task ChangeIssueTrackerShareModeAsync()
225-
{
226-
if (_selectedIssueTracker is { } rule)
227-
await _repo.ChangeIssueTrackerShareModeAsync(rule);
228-
}
229-
230245
public void AddNewCustomAction()
231246
{
232247
SelectedCustomAction = _repo.Settings.AddNewCustomAction();
@@ -259,6 +274,8 @@ public async Task SaveAsync()
259274
await SetIfChangedAsync("user.signingkey", GPGUserSigningKey, "");
260275
await SetIfChangedAsync("http.proxy", HttpProxy, "");
261276
await SetIfChangedAsync("fetch.prune", EnablePruneOnFetch ? "true" : "false", "false");
277+
278+
await ApplyIssueTrackerChangesAsync();
262279
}
263280

264281
private async Task SetIfChangedAsync(string key, string value, string defValue)
@@ -267,6 +284,62 @@ private async Task SetIfChangedAsync(string key, string value, string defValue)
267284
await new Commands.Config(_repo.FullPath).SetAsync(key, value);
268285
}
269286

287+
private async Task ApplyIssueTrackerChangesAsync()
288+
{
289+
var changed = false;
290+
var oldRules = new Dictionary<string, Models.IssueTracker>();
291+
foreach (var rule in _repo.IssueTrackers)
292+
oldRules.Add(rule.Name, rule);
293+
294+
foreach (var rule in IssueTrackers)
295+
{
296+
if (oldRules.TryGetValue(rule.Name, out var old))
297+
{
298+
if (old.IsShared != rule.IsShared)
299+
{
300+
changed = true;
301+
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).RemoveAsync(old.Name);
302+
await new Commands.IssueTracker(_repo.FullPath, rule.IsShared).AddAsync(rule);
303+
}
304+
else
305+
{
306+
if (!old.RegexString.Equals(rule.RegexString, StringComparison.Ordinal))
307+
{
308+
changed = true;
309+
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).UpdateRegexAsync(rule);
310+
}
311+
312+
if (!old.URLTemplate.Equals(rule.URLTemplate, StringComparison.Ordinal))
313+
{
314+
changed = true;
315+
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).UpdateURLTemplateAsync(rule);
316+
}
317+
}
318+
319+
oldRules.Remove(rule.Name);
320+
}
321+
else
322+
{
323+
changed = true;
324+
await new Commands.IssueTracker(_repo.FullPath, rule.IsShared).AddAsync(rule);
325+
}
326+
}
327+
328+
if (oldRules.Count > 0)
329+
{
330+
changed = true;
331+
332+
foreach (var kv in oldRules)
333+
await new Commands.IssueTracker(_repo.FullPath, kv.Value.IsShared).RemoveAsync(kv.Key);
334+
}
335+
336+
if (changed)
337+
{
338+
_repo.IssueTrackers.Clear();
339+
_repo.IssueTrackers.AddRange(IssueTrackers);
340+
}
341+
}
342+
270343
private readonly Repository _repo = null;
271344
private readonly Dictionary<string, string> _cached = null;
272345
private string _httpProxy;

src/Views/RepositoryConfigure.axaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,7 @@
374374
<CheckBox Grid.Row="7" Grid.Column="1"
375375
Margin="0,4,0,0"
376376
Content="{DynamicResource Text.Configure.IssueTracker.Share}"
377-
IsChecked="{Binding IsShared, Mode=TwoWay}"
378-
Click="OnIssueTrackerIsSharedChanged"/>
377+
IsChecked="{Binding IsShared, Mode=TwoWay}"/>
379378
</Grid>
380379
</DataTemplate>
381380
</ContentControl.DataTemplates>

0 commit comments

Comments
 (0)