Skip to content

Commit b467edd

Browse files
committed
feature: supports to share issuetracker rules in .issuetracker file (#1567)
Signed-off-by: leo <longshuang@msn.cn>
1 parent 69d6e5e commit b467edd

File tree

9 files changed

+142
-1
lines changed

9 files changed

+142
-1
lines changed

src/Commands/SharedIssueTracker.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Threading.Tasks;
5+
6+
namespace SourceGit.Commands
7+
{
8+
public class SharedIssueTracker : Command
9+
{
10+
public SharedIssueTracker(string repo)
11+
{
12+
WorkingDirectory = repo;
13+
Context = repo;
14+
_file = $"{repo}/.issuetracker";
15+
}
16+
17+
public async Task<List<Models.IssueTrackerRule>> ReadAllAsync()
18+
{
19+
if (!File.Exists(_file))
20+
return [];
21+
22+
Args = $"config -f {_file.Quoted()} -l";
23+
24+
var output = await ReadToEndAsync().ConfigureAwait(false);
25+
var rs = new List<Models.IssueTrackerRule>();
26+
if (output.IsSuccess)
27+
{
28+
var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
29+
foreach (var line in lines)
30+
{
31+
var parts = line.Split('=', 2);
32+
if (parts.Length < 2)
33+
continue;
34+
35+
var key = parts[0];
36+
var value = parts[1];
37+
38+
if (!key.StartsWith("issuetracker.", StringComparison.Ordinal))
39+
continue;
40+
41+
if (key.EndsWith(".regex", StringComparison.Ordinal))
42+
{
43+
var prefixLen = "issuetracker.".Length;
44+
var suffixLen = ".regex".Length;
45+
var ruleName = key.Substring(prefixLen, key.Length - prefixLen - suffixLen);
46+
FindOrAdd(rs, ruleName).RegexString = value;
47+
}
48+
else if (key.EndsWith(".url", StringComparison.Ordinal))
49+
{
50+
var prefixLen = "issuetracker.".Length;
51+
var suffixLen = ".url".Length;
52+
var ruleName = key.Substring(prefixLen, key.Length - prefixLen - suffixLen);
53+
FindOrAdd(rs, ruleName).URLTemplate = value;
54+
}
55+
}
56+
}
57+
58+
return rs;
59+
}
60+
61+
public async Task<bool> AddAsync(Models.IssueTrackerRule rule)
62+
{
63+
Args = $"config -f {_file.Quoted()} issuetracker.{rule.Name.Quoted()}.regex {rule.RegexString.Quoted()}";
64+
65+
var succ = await ExecAsync().ConfigureAwait(false);
66+
if (succ)
67+
{
68+
Args = $"config -f {_file.Quoted()} issuetracker.{rule.Name.Quoted()}.url {rule.URLTemplate.Quoted()}";
69+
return await ExecAsync().ConfigureAwait(false);
70+
}
71+
72+
return false;
73+
}
74+
75+
public async Task<bool> RemoveAsync(Models.IssueTrackerRule rule)
76+
{
77+
Args = $"config -f {_file.Quoted()} --remove-section issuetracker.{rule.Name.Quoted()}";
78+
return await ExecAsync().ConfigureAwait(false);
79+
}
80+
81+
private Models.IssueTrackerRule FindOrAdd(List<Models.IssueTrackerRule> rules, string ruleName)
82+
{
83+
var rule = rules.Find(x => x.Name.Equals(ruleName, StringComparison.Ordinal));
84+
if (rule != null)
85+
return rule;
86+
87+
rule = new Models.IssueTrackerRule() { IsShared = true, Name = ruleName };
88+
rules.Add(rule);
89+
return rule;
90+
}
91+
92+
private readonly string _file;
93+
}
94+
}

src/Models/IssueTrackerRule.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ namespace SourceGit.Models
66
{
77
public class IssueTrackerRule : ObservableObject
88
{
9+
public bool IsShared
10+
{
11+
get => _isShared;
12+
set => SetProperty(ref _isShared, value);
13+
}
14+
915
public string Name
1016
{
1117
get => _name;
@@ -70,6 +76,7 @@ public void Matches(InlineElementCollector outs, string message)
7076
}
7177
}
7278

79+
private bool _isShared;
7380
private string _name;
7481
private string _regexString;
7582
private string _urlTemplate;

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@
204204
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">New Rule</x:String>
205205
<x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">Issue Regex Expression:</x:String>
206206
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">Rule Name:</x:String>
207+
<x:String x:Key="Text.Configure.IssueTracker.Share" xml:space="preserve">Share this rule in .issuetracker file</x:String>
207208
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">Result URL:</x:String>
208209
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">Please use $1, $2 to access regex groups values.</x:String>
209210
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">新增自定义规则</x:String>
209209
<x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">匹配ISSUE的正则表达式 :</x:String>
210210
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">规则名 :</x:String>
211+
<x:String x:Key="Text.Configure.IssueTracker.Share" xml:space="preserve">写入 .issuetracker 文件共享此规则</x:String>
211212
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">为ISSUE生成的URL链接 :</x:String>
212213
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">可在URL中使用$1,$2等变量填入正则表达式匹配的内容</x:String>
213214
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
<x:String x:Key="Text.Configure.IssueTracker.NewRule" xml:space="preserve">新增自訂規則</x:String>
209209
<x:String x:Key="Text.Configure.IssueTracker.Regex" xml:space="preserve">符合 Issue 的正規表達式:</x:String>
210210
<x:String x:Key="Text.Configure.IssueTracker.RuleName" xml:space="preserve">規則名稱:</x:String>
211+
<x:String x:Key="Text.Configure.IssueTracker.Share" xml:space="preserve">寫入 .issuetracker 檔案以分享此規則</x:String>
211212
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate" xml:space="preserve">為 Issue 產生的網址連結:</x:String>
212213
<x:String x:Key="Text.Configure.IssueTracker.URLTemplate.Tip" xml:space="preserve">可在網址中使用 $1、$2 等變數填入正規表達式相符的內容</x:String>
213214
<x:String x:Key="Text.Configure.OpenAI" xml:space="preserve">AI</x:String>

src/ViewModels/Repository.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,13 @@ public void Close()
546546

547547
_settings.LastCommitMessage = _workingCopy.CommitMessage;
548548

549+
var sharedIssueTrackers = new List<Models.IssueTrackerRule>();
550+
foreach (var rule in _settings.IssueTrackerRules)
551+
if (rule.IsShared)
552+
sharedIssueTrackers.Add(rule);
553+
554+
_settings.IssueTrackerRules.RemoveAll(sharedIssueTrackers);
555+
549556
try
550557
{
551558
using var stream = File.Create(Path.Combine(_gitDir, "sourcegit.settings"));
@@ -704,6 +711,10 @@ public void RefreshAll()
704711

705712
Task.Run(async () =>
706713
{
714+
var sharedIssueTrackers = await new Commands.SharedIssueTracker(_fullpath).ReadAllAsync().ConfigureAwait(false);
715+
if (sharedIssueTrackers.Count > 0)
716+
Dispatcher.UIThread.Post(() => _settings.IssueTrackerRules.InsertRange(0, sharedIssueTrackers));
717+
707718
var config = await new Commands.Config(_fullpath).ReadAllAsync().ConfigureAwait(false);
708719
_hasAllowedSignersFile = config.TryGetValue("gpg.ssh.allowedSignersFile", out var allowedSignersFile) && !string.IsNullOrEmpty(allowedSignersFile);
709720

src/ViewModels/RepositoryConfigure.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,17 @@ public void RemoveSelectedIssueTracker()
295295
SelectedIssueTrackerRule = null;
296296
}
297297

298+
public async Task ChangeIssueTrackerShareModeAsync()
299+
{
300+
if (_selectedIssueTrackerRule is not { } rule)
301+
return;
302+
303+
if (rule.IsShared)
304+
await new Commands.SharedIssueTracker(_repo.FullPath).AddAsync(rule);
305+
else
306+
await new Commands.SharedIssueTracker(_repo.FullPath).RemoveAsync(rule);
307+
}
308+
298309
public void AddNewCustomAction()
299310
{
300311
SelectedCustomAction = _repo.Settings.AddNewCustomAction();

src/Views/RepositoryConfigure.axaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@
355355

356356
<ContentControl.DataTemplates>
357357
<DataTemplate DataType="m:IssueTrackerRule">
358-
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
358+
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,32">
359359
<TextBlock Grid.Row="0" Text="{DynamicResource Text.Configure.IssueTracker.RuleName}"/>
360360
<TextBox Grid.Row="1" Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Name, Mode=TwoWay}"/>
361361

@@ -369,6 +369,12 @@
369369
<TextBlock Grid.Row="4" Margin="0,12,0,0" Text="{DynamicResource Text.Configure.IssueTracker.URLTemplate}"/>
370370
<TextBox Grid.Row="5" Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding URLTemplate, Mode=TwoWay}"/>
371371
<TextBlock Grid.Row="6" Margin="0,2,0,0" Text="{DynamicResource Text.Configure.IssueTracker.URLTemplate.Tip}" Foreground="{DynamicResource Brush.FG2}"/>
372+
373+
<CheckBox Grid.Row="7" Grid.Column="1"
374+
Margin="0,4,0,0"
375+
Content="{DynamicResource Text.Configure.IssueTracker.Share}"
376+
IsChecked="{Binding IsShared, Mode=TwoWay}"
377+
Click="OnIssueTrackerIsSharedChanged"/>
372378
</Grid>
373379
</DataTemplate>
374380
</ContentControl.DataTemplates>

src/Views/RepositoryConfigure.axaml.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,14 @@ private async void EditCustomActionControls(object sender, RoutedEventArgs e)
4848
await dialog.ShowDialog(this);
4949
e.Handled = true;
5050
}
51+
52+
private async void OnIssueTrackerIsSharedChanged(object sender, RoutedEventArgs e)
53+
{
54+
if (DataContext is ViewModels.RepositoryConfigure configure)
55+
{
56+
await configure.ChangeIssueTrackerShareModeAsync();
57+
e.Handled = true;
58+
}
59+
}
5160
}
5261
}

0 commit comments

Comments
 (0)