mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-30 22:01:10 +08:00
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 <longshuang@msn.cn>
This commit is contained in:
@@ -7,20 +7,21 @@ namespace SourceGit.Commands
|
||||
{
|
||||
public class IssueTracker : Command
|
||||
{
|
||||
public IssueTracker(string repo, string storage)
|
||||
public IssueTracker(string repo, bool isShared)
|
||||
{
|
||||
WorkingDirectory = repo;
|
||||
Context = repo;
|
||||
|
||||
if (string.IsNullOrEmpty(storage))
|
||||
if (isShared)
|
||||
{
|
||||
_isStorageFileExists = true;
|
||||
_baseArg = "config --local";
|
||||
var storage = $"{repo}/.issuetracker";
|
||||
_isStorageFileExists = File.Exists(storage);
|
||||
_baseArg = $"config -f {storage.Quoted()}";
|
||||
}
|
||||
else
|
||||
{
|
||||
_isStorageFileExists = File.Exists(storage);
|
||||
_baseArg = $"config -f {storage.Quoted()}";
|
||||
_isStorageFileExists = true;
|
||||
_baseArg = "config --local";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,12 +80,24 @@ namespace SourceGit.Commands
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> RemoveAsync(Models.IssueTracker rule)
|
||||
public async Task<bool> UpdateRegexAsync(Models.IssueTracker rule)
|
||||
{
|
||||
Args = $"{_baseArg} issuetracker.{rule.Name.Quoted()}.regex {rule.RegexString.Quoted()}";
|
||||
return await ExecAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateURLTemplateAsync(Models.IssueTracker rule)
|
||||
{
|
||||
Args = $"{_baseArg} issuetracker.{rule.Name.Quoted()}.url {rule.URLTemplate.Quoted()}";
|
||||
return await ExecAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> RemoveAsync(string name)
|
||||
{
|
||||
if (!_isStorageFileExists)
|
||||
return true;
|
||||
|
||||
Args = $"{_baseArg} --remove-section issuetracker.{rule.Name.Quoted()}";
|
||||
Args = $"{_baseArg} --remove-section issuetracker.{name.Quoted()}";
|
||||
return await ExecAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,11 @@ namespace SourceGit.Models
|
||||
{
|
||||
try
|
||||
{
|
||||
_regex = null;
|
||||
_regex = new Regex(_regexString, RegexOptions.Multiline);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore errors.
|
||||
_regex = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -740,39 +740,6 @@ namespace SourceGit.ViewModels
|
||||
return log;
|
||||
}
|
||||
|
||||
public async Task<Models.IssueTracker> AddIssueTrackerAsync(string name, string regex, string url)
|
||||
{
|
||||
var rule = new Models.IssueTracker()
|
||||
{
|
||||
IsShared = false,
|
||||
Name = name,
|
||||
RegexString = regex,
|
||||
URLTemplate = url,
|
||||
};
|
||||
|
||||
var succ = await CreateIssueTrackerCommand(false).AddAsync(rule);
|
||||
if (succ)
|
||||
{
|
||||
IssueTrackers.Add(rule);
|
||||
return rule;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task RemoveIssueTrackerAsync(Models.IssueTracker rule)
|
||||
{
|
||||
var succ = await CreateIssueTrackerCommand(rule.IsShared).RemoveAsync(rule);
|
||||
if (succ)
|
||||
IssueTrackers.Remove(rule);
|
||||
}
|
||||
|
||||
public async Task ChangeIssueTrackerShareModeAsync(Models.IssueTracker rule)
|
||||
{
|
||||
await CreateIssueTrackerCommand(!rule.IsShared).RemoveAsync(rule);
|
||||
await CreateIssueTrackerCommand(rule.IsShared).AddAsync(rule);
|
||||
}
|
||||
|
||||
public void RefreshAll()
|
||||
{
|
||||
RefreshCommits();
|
||||
@@ -786,8 +753,8 @@ namespace SourceGit.ViewModels
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var issuetrackers = new List<Models.IssueTracker>();
|
||||
await CreateIssueTrackerCommand(true).ReadAllAsync(issuetrackers, true).ConfigureAwait(false);
|
||||
await CreateIssueTrackerCommand(false).ReadAllAsync(issuetrackers, false).ConfigureAwait(false);
|
||||
await new Commands.IssueTracker(FullPath, true).ReadAllAsync(issuetrackers, true).ConfigureAwait(false);
|
||||
await new Commands.IssueTracker(FullPath, false).ReadAllAsync(issuetrackers, false).ConfigureAwait(false);
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
IssueTrackers.Clear();
|
||||
@@ -1743,11 +1710,6 @@ namespace SourceGit.ViewModels
|
||||
return null;
|
||||
}
|
||||
|
||||
private Commands.IssueTracker CreateIssueTrackerCommand(bool shared)
|
||||
{
|
||||
return new Commands.IssueTracker(FullPath, shared ? $"{FullPath}/.issuetracker" : null);
|
||||
}
|
||||
|
||||
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
|
||||
{
|
||||
var builder = new BranchTreeNode.Builder(_settings.LocalBranchSortMode, _settings.RemoteBranchSortMode);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Collections;
|
||||
@@ -114,8 +115,8 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public AvaloniaList<Models.IssueTracker> IssueTrackers
|
||||
{
|
||||
get => _repo.IssueTrackers;
|
||||
}
|
||||
get;
|
||||
} = [];
|
||||
|
||||
public Models.IssueTracker SelectedIssueTracker
|
||||
{
|
||||
@@ -176,6 +177,17 @@ namespace SourceGit.ViewModels
|
||||
HttpProxy = proxy;
|
||||
if (_cached.TryGetValue("fetch.prune", out var prune))
|
||||
EnablePruneOnFetch = (prune == "true");
|
||||
|
||||
foreach (var rule in _repo.IssueTrackers)
|
||||
{
|
||||
IssueTrackers.Add(new()
|
||||
{
|
||||
IsShared = rule.IsShared,
|
||||
Name = rule.Name,
|
||||
RegexString = rule.RegexString,
|
||||
URLTemplate = rule.URLTemplate,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearHttpProxy()
|
||||
@@ -208,25 +220,28 @@ namespace SourceGit.ViewModels
|
||||
return outs;
|
||||
}
|
||||
|
||||
public async Task AddIssueTrackerAsync(string name, string regex, string url)
|
||||
public void AddIssueTracker(string name, string regex, string url)
|
||||
{
|
||||
SelectedIssueTracker = await _repo.AddIssueTrackerAsync(name, regex, url);
|
||||
var rule = new Models.IssueTracker()
|
||||
{
|
||||
IsShared = false,
|
||||
Name = name,
|
||||
RegexString = regex,
|
||||
URLTemplate = url,
|
||||
};
|
||||
|
||||
IssueTrackers.Add(rule);
|
||||
SelectedIssueTracker = rule;
|
||||
}
|
||||
|
||||
public async Task RemoveIssueTrackerAsync()
|
||||
public void RemoveIssueTracker()
|
||||
{
|
||||
if (_selectedIssueTracker is { } rule)
|
||||
await _repo.RemoveIssueTrackerAsync(rule);
|
||||
IssueTrackers.Remove(rule);
|
||||
|
||||
SelectedIssueTracker = null;
|
||||
}
|
||||
|
||||
public async Task ChangeIssueTrackerShareModeAsync()
|
||||
{
|
||||
if (_selectedIssueTracker is { } rule)
|
||||
await _repo.ChangeIssueTrackerShareModeAsync(rule);
|
||||
}
|
||||
|
||||
public void AddNewCustomAction()
|
||||
{
|
||||
SelectedCustomAction = _repo.Settings.AddNewCustomAction();
|
||||
@@ -259,6 +274,8 @@ namespace SourceGit.ViewModels
|
||||
await SetIfChangedAsync("user.signingkey", GPGUserSigningKey, "");
|
||||
await SetIfChangedAsync("http.proxy", HttpProxy, "");
|
||||
await SetIfChangedAsync("fetch.prune", EnablePruneOnFetch ? "true" : "false", "false");
|
||||
|
||||
await ApplyIssueTrackerChangesAsync();
|
||||
}
|
||||
|
||||
private async Task SetIfChangedAsync(string key, string value, string defValue)
|
||||
@@ -267,6 +284,62 @@ namespace SourceGit.ViewModels
|
||||
await new Commands.Config(_repo.FullPath).SetAsync(key, value);
|
||||
}
|
||||
|
||||
private async Task ApplyIssueTrackerChangesAsync()
|
||||
{
|
||||
var changed = false;
|
||||
var oldRules = new Dictionary<string, Models.IssueTracker>();
|
||||
foreach (var rule in _repo.IssueTrackers)
|
||||
oldRules.Add(rule.Name, rule);
|
||||
|
||||
foreach (var rule in IssueTrackers)
|
||||
{
|
||||
if (oldRules.TryGetValue(rule.Name, out var old))
|
||||
{
|
||||
if (old.IsShared != rule.IsShared)
|
||||
{
|
||||
changed = true;
|
||||
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).RemoveAsync(old.Name);
|
||||
await new Commands.IssueTracker(_repo.FullPath, rule.IsShared).AddAsync(rule);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!old.RegexString.Equals(rule.RegexString, StringComparison.Ordinal))
|
||||
{
|
||||
changed = true;
|
||||
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).UpdateRegexAsync(rule);
|
||||
}
|
||||
|
||||
if (!old.URLTemplate.Equals(rule.URLTemplate, StringComparison.Ordinal))
|
||||
{
|
||||
changed = true;
|
||||
await new Commands.IssueTracker(_repo.FullPath, old.IsShared).UpdateURLTemplateAsync(rule);
|
||||
}
|
||||
}
|
||||
|
||||
oldRules.Remove(rule.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
changed = true;
|
||||
await new Commands.IssueTracker(_repo.FullPath, rule.IsShared).AddAsync(rule);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldRules.Count > 0)
|
||||
{
|
||||
changed = true;
|
||||
|
||||
foreach (var kv in oldRules)
|
||||
await new Commands.IssueTracker(_repo.FullPath, kv.Value.IsShared).RemoveAsync(kv.Key);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
_repo.IssueTrackers.Clear();
|
||||
_repo.IssueTrackers.AddRange(IssueTrackers);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Repository _repo = null;
|
||||
private readonly Dictionary<string, string> _cached = null;
|
||||
private string _httpProxy;
|
||||
|
||||
@@ -374,8 +374,7 @@
|
||||
<CheckBox Grid.Row="7" Grid.Column="1"
|
||||
Margin="0,4,0,0"
|
||||
Content="{DynamicResource Text.Configure.IssueTracker.Share}"
|
||||
IsChecked="{Binding IsShared, Mode=TwoWay}"
|
||||
Click="OnIssueTrackerIsSharedChanged"/>
|
||||
IsChecked="{Binding IsShared, Mode=TwoWay}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ContentControl.DataTemplates>
|
||||
|
||||
@@ -50,15 +50,15 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnNewCustomIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnNewCustomIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
await vm.AddIssueTrackerAsync("New Issue Tracker", @"#(\d+)", "https://xxx/$1");
|
||||
vm.AddIssueTracker("New Issue Tracker", @"#(\d+)", "https://xxx/$1");
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGitHubIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGitHubIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -73,17 +73,17 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("GitHub Issue", @"#(\d+)", link);
|
||||
vm.AddIssueTracker("GitHub Issue", @"#(\d+)", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddJiraIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddJiraIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
await vm.AddIssueTrackerAsync(
|
||||
vm.AddIssueTracker(
|
||||
"Jira Tracker",
|
||||
@"PROJ-(\d+)",
|
||||
"https://jira.yourcompany.com/browse/PROJ-$1");
|
||||
@@ -92,11 +92,11 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddAzureWorkItemTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddAzureWorkItemTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
await vm.AddIssueTrackerAsync(
|
||||
vm.AddIssueTracker(
|
||||
"Azure DevOps Tracker",
|
||||
@"#(\d+)",
|
||||
"https://dev.azure.com/yourcompany/workspace/_workitems/edit/$1");
|
||||
@@ -105,7 +105,7 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGitLabIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGitLabIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -117,13 +117,13 @@ namespace SourceGit.Views
|
||||
break;
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("GitLab Issue", @"#(\d+)", link);
|
||||
vm.AddIssueTracker("GitLab Issue", @"#(\d+)", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGitLabMergeRequestTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGitLabMergeRequestTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -135,13 +135,13 @@ namespace SourceGit.Views
|
||||
break;
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("GitLab MR", @"!(\d+)", link);
|
||||
vm.AddIssueTracker("GitLab MR", @"!(\d+)", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGiteeIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGiteeIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -156,13 +156,13 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("Gitee Issue", @"#([0-9A-Z]{6,10})", link);
|
||||
vm.AddIssueTracker("Gitee Issue", @"#([0-9A-Z]{6,10})", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGiteePullRequestTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGiteePullRequestTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
@@ -177,17 +177,17 @@ namespace SourceGit.Views
|
||||
}
|
||||
}
|
||||
|
||||
await vm.AddIssueTrackerAsync("Gitee Pull Request", @"!(\d+)", link);
|
||||
vm.AddIssueTracker("Gitee Pull Request", @"!(\d+)", link);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnAddGerritChangeIdTracker(object sender, RoutedEventArgs e)
|
||||
private void OnAddGerritChangeIdTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
{
|
||||
await vm.AddIssueTrackerAsync(
|
||||
vm.AddIssueTracker(
|
||||
"Gerrit Change-Id",
|
||||
@"(I[A-Za-z0-9]{40})",
|
||||
"https://gerrit.yourcompany.com/q/$1");
|
||||
@@ -196,18 +196,10 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnRemoveIssueTracker(object sender, RoutedEventArgs e)
|
||||
private void OnRemoveIssueTracker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
await vm.RemoveIssueTrackerAsync();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnIssueTrackerIsSharedChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.RepositoryConfigure vm)
|
||||
await vm.ChangeIssueTrackerShareModeAsync();
|
||||
vm.RemoveIssueTracker();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user