mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-30 13:51:53 +08:00
refactor: save history filters into $GIT_DIR/sourcegit.filters to support different filters between worktrees (#1893)
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
@@ -60,6 +60,7 @@ namespace SourceGit
|
||||
]
|
||||
)]
|
||||
[JsonSerializable(typeof(Models.ExternalToolPaths))]
|
||||
[JsonSerializable(typeof(Models.HistoryFilterCollection))]
|
||||
[JsonSerializable(typeof(Models.InteractiveRebaseJobCollection))]
|
||||
[JsonSerializable(typeof(Models.JetBrainsState))]
|
||||
[JsonSerializable(typeof(Models.ThemeOverrides))]
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public enum FilterType
|
||||
{
|
||||
LocalBranch = 0,
|
||||
LocalBranchFolder,
|
||||
RemoteBranch,
|
||||
RemoteBranchFolder,
|
||||
Tag,
|
||||
}
|
||||
|
||||
public enum FilterMode
|
||||
{
|
||||
None = 0,
|
||||
Included,
|
||||
Excluded,
|
||||
}
|
||||
|
||||
public class Filter : ObservableObject
|
||||
{
|
||||
public string Pattern
|
||||
{
|
||||
get => _pattern;
|
||||
set => SetProperty(ref _pattern, value);
|
||||
}
|
||||
|
||||
public FilterType Type
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = FilterType.LocalBranch;
|
||||
|
||||
public FilterMode Mode
|
||||
{
|
||||
get => _mode;
|
||||
set => SetProperty(ref _mode, value);
|
||||
}
|
||||
|
||||
public bool IsBranch
|
||||
{
|
||||
get => Type != FilterType.Tag;
|
||||
}
|
||||
|
||||
public Filter()
|
||||
{
|
||||
}
|
||||
|
||||
public Filter(string pattern, FilterType type, FilterMode mode)
|
||||
{
|
||||
_pattern = pattern;
|
||||
_mode = mode;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
private string _pattern = string.Empty;
|
||||
private FilterMode _mode = FilterMode.None;
|
||||
}
|
||||
}
|
||||
246
src/Models/HistoryFilterCollection.cs
Normal file
246
src/Models/HistoryFilterCollection.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Avalonia.Collections;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.Models
|
||||
{
|
||||
public enum FilterType
|
||||
{
|
||||
LocalBranch = 0,
|
||||
LocalBranchFolder,
|
||||
RemoteBranch,
|
||||
RemoteBranchFolder,
|
||||
Tag,
|
||||
}
|
||||
|
||||
public enum FilterMode
|
||||
{
|
||||
None = 0,
|
||||
Included,
|
||||
Excluded,
|
||||
}
|
||||
|
||||
public class HistoryFilter : ObservableObject
|
||||
{
|
||||
public string Pattern
|
||||
{
|
||||
get => _pattern;
|
||||
set => SetProperty(ref _pattern, value);
|
||||
}
|
||||
|
||||
public FilterType Type
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = FilterType.LocalBranch;
|
||||
|
||||
public FilterMode Mode
|
||||
{
|
||||
get => _mode;
|
||||
set => SetProperty(ref _mode, value);
|
||||
}
|
||||
|
||||
public bool IsBranch
|
||||
{
|
||||
get => Type != FilterType.Tag;
|
||||
}
|
||||
|
||||
public HistoryFilter()
|
||||
{
|
||||
}
|
||||
|
||||
public HistoryFilter(string pattern, FilterType type, FilterMode mode)
|
||||
{
|
||||
_pattern = pattern;
|
||||
_mode = mode;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
private string _pattern = string.Empty;
|
||||
private FilterMode _mode = FilterMode.None;
|
||||
}
|
||||
|
||||
public class HistoryFilterCollection
|
||||
{
|
||||
public AvaloniaList<HistoryFilter> Filters
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = [];
|
||||
|
||||
public FilterMode Mode => Filters.Count > 0 ? Filters[0].Mode : FilterMode.None;
|
||||
|
||||
public Dictionary<string, FilterMode> ToMap()
|
||||
{
|
||||
var map = new Dictionary<string, FilterMode>();
|
||||
foreach (var filter in Filters)
|
||||
map.Add(filter.Pattern, filter.Mode);
|
||||
return map;
|
||||
}
|
||||
|
||||
public bool Update(string pattern, FilterType type, FilterMode mode)
|
||||
{
|
||||
// Clear all filters when there's a filter that has different mode.
|
||||
if (mode != FilterMode.None)
|
||||
{
|
||||
var clear = false;
|
||||
foreach (var filter in Filters)
|
||||
{
|
||||
if (filter.Mode != mode)
|
||||
{
|
||||
clear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (clear)
|
||||
{
|
||||
Filters.Clear();
|
||||
Filters.Add(new HistoryFilter(pattern, type, mode));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < Filters.Count; i++)
|
||||
{
|
||||
var filter = Filters[i];
|
||||
if (filter.Type == type && filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
||||
{
|
||||
Filters.RemoveAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var filter in Filters)
|
||||
{
|
||||
if (filter.Type != type)
|
||||
continue;
|
||||
|
||||
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
||||
return false;
|
||||
}
|
||||
|
||||
Filters.Add(new HistoryFilter(pattern, type, mode));
|
||||
return true;
|
||||
}
|
||||
|
||||
public FilterMode GetFilterMode(string pattern)
|
||||
{
|
||||
foreach (var filter in Filters)
|
||||
{
|
||||
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
||||
return filter.Mode;
|
||||
}
|
||||
|
||||
return FilterMode.None;
|
||||
}
|
||||
|
||||
public void RemoveBranchFiltersByPrefix(string pattern)
|
||||
{
|
||||
var dirty = new List<HistoryFilter>();
|
||||
var prefix = $"{pattern}/";
|
||||
|
||||
foreach (var filter in Filters)
|
||||
{
|
||||
if (filter.Type != FilterType.Tag)
|
||||
continue;
|
||||
|
||||
if (filter.Pattern.StartsWith(prefix, StringComparison.Ordinal))
|
||||
dirty.Add(filter);
|
||||
}
|
||||
|
||||
foreach (var filter in dirty)
|
||||
Filters.Remove(filter);
|
||||
}
|
||||
|
||||
public string Build()
|
||||
{
|
||||
var includedRefs = new List<string>();
|
||||
var excludedBranches = new List<string>();
|
||||
var excludedRemotes = new List<string>();
|
||||
var excludedTags = new List<string>();
|
||||
foreach (var filter in Filters)
|
||||
{
|
||||
if (filter.Type == FilterType.LocalBranch)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add(filter.Pattern);
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
|
||||
}
|
||||
else if (filter.Type == FilterType.LocalBranchFolder)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add($"--branches={filter.Pattern.AsSpan(11)}/*");
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
|
||||
}
|
||||
else if (filter.Type == FilterType.RemoteBranch)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add(filter.Pattern);
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
|
||||
}
|
||||
else if (filter.Type == FilterType.RemoteBranchFolder)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add($"--remotes={filter.Pattern.AsSpan(13)}/*");
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
|
||||
}
|
||||
else if (filter.Type == FilterType.Tag)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add($"refs/tags/{filter.Pattern}");
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedTags.Add($"--exclude=\"{filter.Pattern}\" --decorate-refs-exclude=\"refs/tags/{filter.Pattern}\"");
|
||||
}
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
if (includedRefs.Count > 0)
|
||||
{
|
||||
foreach (var r in includedRefs)
|
||||
{
|
||||
builder.Append(r);
|
||||
builder.Append(' ');
|
||||
}
|
||||
}
|
||||
else if (excludedBranches.Count + excludedRemotes.Count + excludedTags.Count > 0)
|
||||
{
|
||||
foreach (var b in excludedBranches)
|
||||
{
|
||||
builder.Append(b);
|
||||
builder.Append(' ');
|
||||
}
|
||||
|
||||
builder.Append("--exclude=HEAD --branches ");
|
||||
|
||||
foreach (var r in excludedRemotes)
|
||||
{
|
||||
builder.Append(r);
|
||||
builder.Append(' ');
|
||||
}
|
||||
|
||||
builder.Append("--exclude=origin/HEAD --remotes ");
|
||||
|
||||
foreach (var t in excludedTags)
|
||||
{
|
||||
builder.Append(t);
|
||||
builder.Append(' ');
|
||||
}
|
||||
|
||||
builder.Append("--tags ");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
using Avalonia.Collections;
|
||||
|
||||
namespace SourceGit.Models
|
||||
@@ -116,12 +113,6 @@ namespace SourceGit.Models
|
||||
set;
|
||||
} = true;
|
||||
|
||||
public AvaloniaList<Filter> HistoriesFilters
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = [];
|
||||
|
||||
public AvaloniaList<CommitTemplate> CommitTemplates
|
||||
{
|
||||
get;
|
||||
@@ -242,166 +233,6 @@ namespace SourceGit.Models
|
||||
set;
|
||||
} = string.Empty;
|
||||
|
||||
public Dictionary<string, FilterMode> CollectHistoriesFilters()
|
||||
{
|
||||
var map = new Dictionary<string, FilterMode>();
|
||||
foreach (var filter in HistoriesFilters)
|
||||
map.Add(filter.Pattern, filter.Mode);
|
||||
return map;
|
||||
}
|
||||
|
||||
public bool UpdateHistoriesFilter(string pattern, FilterType type, FilterMode mode)
|
||||
{
|
||||
// Clear all filters when there's a filter that has different mode.
|
||||
if (mode != FilterMode.None)
|
||||
{
|
||||
var clear = false;
|
||||
foreach (var filter in HistoriesFilters)
|
||||
{
|
||||
if (filter.Mode != mode)
|
||||
{
|
||||
clear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (clear)
|
||||
{
|
||||
HistoriesFilters.Clear();
|
||||
HistoriesFilters.Add(new Filter(pattern, type, mode));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < HistoriesFilters.Count; i++)
|
||||
{
|
||||
var filter = HistoriesFilters[i];
|
||||
if (filter.Type == type && filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
||||
{
|
||||
HistoriesFilters.RemoveAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var filter in HistoriesFilters)
|
||||
{
|
||||
if (filter.Type != type)
|
||||
continue;
|
||||
|
||||
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
||||
return false;
|
||||
}
|
||||
|
||||
HistoriesFilters.Add(new Filter(pattern, type, mode));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void RemoveChildrenBranchFilters(string pattern)
|
||||
{
|
||||
var dirty = new List<Filter>();
|
||||
var prefix = $"{pattern}/";
|
||||
|
||||
foreach (var filter in HistoriesFilters)
|
||||
{
|
||||
if (filter.Type == FilterType.Tag)
|
||||
continue;
|
||||
|
||||
if (filter.Pattern.StartsWith(prefix, StringComparison.Ordinal))
|
||||
dirty.Add(filter);
|
||||
}
|
||||
|
||||
foreach (var filter in dirty)
|
||||
HistoriesFilters.Remove(filter);
|
||||
}
|
||||
|
||||
public string BuildHistoriesFilter()
|
||||
{
|
||||
var includedRefs = new List<string>();
|
||||
var excludedBranches = new List<string>();
|
||||
var excludedRemotes = new List<string>();
|
||||
var excludedTags = new List<string>();
|
||||
foreach (var filter in HistoriesFilters)
|
||||
{
|
||||
if (filter.Type == FilterType.LocalBranch)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add(filter.Pattern);
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
|
||||
}
|
||||
else if (filter.Type == FilterType.LocalBranchFolder)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add($"--branches={filter.Pattern.AsSpan(11)}/*");
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
|
||||
}
|
||||
else if (filter.Type == FilterType.RemoteBranch)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add(filter.Pattern);
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
|
||||
}
|
||||
else if (filter.Type == FilterType.RemoteBranchFolder)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add($"--remotes={filter.Pattern.AsSpan(13)}/*");
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
|
||||
}
|
||||
else if (filter.Type == FilterType.Tag)
|
||||
{
|
||||
if (filter.Mode == FilterMode.Included)
|
||||
includedRefs.Add($"refs/tags/{filter.Pattern}");
|
||||
else if (filter.Mode == FilterMode.Excluded)
|
||||
excludedTags.Add($"--exclude=\"{filter.Pattern}\" --decorate-refs-exclude=\"refs/tags/{filter.Pattern}\"");
|
||||
}
|
||||
}
|
||||
|
||||
var builder = new StringBuilder();
|
||||
if (includedRefs.Count > 0)
|
||||
{
|
||||
foreach (var r in includedRefs)
|
||||
{
|
||||
builder.Append(r);
|
||||
builder.Append(' ');
|
||||
}
|
||||
}
|
||||
else if (excludedBranches.Count + excludedRemotes.Count + excludedTags.Count > 0)
|
||||
{
|
||||
foreach (var b in excludedBranches)
|
||||
{
|
||||
builder.Append(b);
|
||||
builder.Append(' ');
|
||||
}
|
||||
|
||||
builder.Append("--exclude=HEAD --branches ");
|
||||
|
||||
foreach (var r in excludedRemotes)
|
||||
{
|
||||
builder.Append(r);
|
||||
builder.Append(' ');
|
||||
}
|
||||
|
||||
builder.Append("--exclude=origin/HEAD --remotes ");
|
||||
|
||||
foreach (var t in excludedTags)
|
||||
{
|
||||
builder.Append(t);
|
||||
builder.Append(' ');
|
||||
}
|
||||
|
||||
builder.Append("--tags ");
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public void PushCommitMessage(string message)
|
||||
{
|
||||
message = message.Trim().ReplaceLineEndings("\n");
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace SourceGit.ViewModels
|
||||
log.Complete();
|
||||
|
||||
var b = _repo.Branches.Find(x => x.IsLocal && x.Name == Branch);
|
||||
if (b != null && _repo.HistoriesFilterMode == Models.FilterMode.Included)
|
||||
if (b != null && _repo.HistoryFilterMode == Models.FilterMode.Included)
|
||||
_repo.SetBranchFilterMode(b, Models.FilterMode.Included, false, false);
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
log.Complete();
|
||||
|
||||
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
|
||||
if (_repo.HistoryFilterMode == Models.FilterMode.Included)
|
||||
_repo.SetBranchFilterMode(LocalBranch, Models.FilterMode.Included, false, false);
|
||||
|
||||
_repo.MarkBranchesDirtyManually();
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace SourceGit.ViewModels
|
||||
if (folderEndIdx > 10)
|
||||
_repo.Settings.ExpandedBranchNodesInSideBar.Add(fake.FullName.Substring(0, folderEndIdx));
|
||||
|
||||
if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
|
||||
if (_repo.HistoryFilterMode == Models.FilterMode.Included)
|
||||
_repo.SetBranchFilterMode(fake, Models.FilterMode.Included, false, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
@@ -23,20 +22,9 @@ namespace SourceGit.ViewModels
|
||||
_target = target;
|
||||
|
||||
if (_target is Models.Branch b)
|
||||
_mode = GetFilterMode(b.FullName);
|
||||
_mode = _repo.HistoryFilterCollection.GetFilterMode(b.FullName);
|
||||
else if (_target is Models.Tag t)
|
||||
_mode = GetFilterMode(t.Name);
|
||||
}
|
||||
|
||||
private Models.FilterMode GetFilterMode(string pattern)
|
||||
{
|
||||
foreach (var filter in _repo.Settings.HistoriesFilters)
|
||||
{
|
||||
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
|
||||
return filter.Mode;
|
||||
}
|
||||
|
||||
return Models.FilterMode.None;
|
||||
_mode = _repo.HistoryFilterCollection.GetFilterMode(t.Name);
|
||||
}
|
||||
|
||||
private void SetFilterMode(Models.FilterMode mode)
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (succ)
|
||||
{
|
||||
foreach (var filter in _repo.Settings.HistoriesFilters)
|
||||
foreach (var filter in _repo.HistoryFilterCollection.Filters)
|
||||
{
|
||||
if (filter.Type == Models.FilterType.LocalBranch &&
|
||||
filter.Pattern.Equals(oldName, StringComparison.Ordinal))
|
||||
|
||||
@@ -41,10 +41,15 @@ namespace SourceGit.ViewModels
|
||||
set;
|
||||
} = new();
|
||||
|
||||
public Models.FilterMode HistoriesFilterMode
|
||||
public Models.HistoryFilterCollection HistoryFilterCollection
|
||||
{
|
||||
get => _historiesFilterMode;
|
||||
private set => SetProperty(ref _historiesFilterMode, value);
|
||||
get => _historyFilterCollection;
|
||||
}
|
||||
|
||||
public Models.FilterMode HistoryFilterMode
|
||||
{
|
||||
get => _historyFilterMode;
|
||||
private set => SetProperty(ref _historyFilterMode, value);
|
||||
}
|
||||
|
||||
public bool HasAllowedSignersFile
|
||||
@@ -526,6 +531,24 @@ namespace SourceGit.ViewModels
|
||||
_settings = new Models.RepositorySettings();
|
||||
}
|
||||
|
||||
var historyFilterFile = Path.Combine(GitDir, "sourcegit.filters");
|
||||
if (File.Exists(historyFilterFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
using var stream = File.OpenRead(historyFilterFile);
|
||||
_historyFilterCollection = JsonSerializer.Deserialize(stream, JsonCodeGen.Default.HistoryFilterCollection);
|
||||
}
|
||||
catch
|
||||
{
|
||||
_historyFilterCollection = new Models.HistoryFilterCollection();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_historyFilterCollection = new Models.HistoryFilterCollection();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_watcher = new Models.Watcher(this, FullPath, _gitCommonDir);
|
||||
@@ -535,11 +558,7 @@ namespace SourceGit.ViewModels
|
||||
App.RaiseException(string.Empty, $"Failed to start watcher for repository: '{FullPath}'. You may need to press 'F5' to refresh repository manually!\n\nReason: {ex.Message}");
|
||||
}
|
||||
|
||||
if (_settings.HistoriesFilters.Count > 0)
|
||||
_historiesFilterMode = _settings.HistoriesFilters[0].Mode;
|
||||
else
|
||||
_historiesFilterMode = Models.FilterMode.None;
|
||||
|
||||
_historyFilterMode = _historyFilterCollection.Mode;
|
||||
_histories = new Histories(this);
|
||||
_workingCopy = new WorkingCopy(this) { CommitMessage = _settings.LastCommitMessage };
|
||||
_stashesPage = new StashesPage(this);
|
||||
@@ -583,6 +602,16 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var stream = File.Create(Path.Combine(GitDir, "sourcegit.filters"));
|
||||
JsonSerializer.Serialize(stream, _historyFilterCollection, JsonCodeGen.Default.HistoryFilterCollection);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
|
||||
if (_cancellationRefreshBranches is { IsCancellationRequested: false })
|
||||
_cancellationRefreshBranches.Cancel();
|
||||
if (_cancellationRefreshTags is { IsCancellationRequested: false })
|
||||
@@ -598,7 +627,7 @@ namespace SourceGit.ViewModels
|
||||
_autoFetchTimer = null;
|
||||
|
||||
_settings = null;
|
||||
_historiesFilterMode = Models.FilterMode.None;
|
||||
_historyFilterMode = Models.FilterMode.None;
|
||||
|
||||
_watcher?.Dispose();
|
||||
_histories.Dispose();
|
||||
@@ -1014,10 +1043,10 @@ namespace SourceGit.ViewModels
|
||||
return (_histories?.DetailContext as CommitDetail)?.Commit;
|
||||
}
|
||||
|
||||
public void ClearHistoriesFilter()
|
||||
public void ClearHistoryFilters()
|
||||
{
|
||||
_settings.HistoriesFilters.Clear();
|
||||
HistoriesFilterMode = Models.FilterMode.None;
|
||||
_historyFilterCollection.Filters.Clear();
|
||||
HistoryFilterMode = Models.FilterMode.None;
|
||||
|
||||
ResetBranchTreeFilterMode(LocalBranchTrees);
|
||||
ResetBranchTreeFilterMode(RemoteBranchTrees);
|
||||
@@ -1025,12 +1054,12 @@ namespace SourceGit.ViewModels
|
||||
RefreshCommits();
|
||||
}
|
||||
|
||||
public void RemoveHistoriesFilter(Models.Filter filter)
|
||||
public void RemoveHistoryFilter(Models.HistoryFilter filter)
|
||||
{
|
||||
if (_settings.HistoriesFilters.Remove(filter))
|
||||
if (_historyFilterCollection.Filters.Remove(filter))
|
||||
{
|
||||
HistoriesFilterMode = _settings.HistoriesFilters.Count > 0 ? _settings.HistoriesFilters[0].Mode : Models.FilterMode.None;
|
||||
RefreshHistoriesFilters(true);
|
||||
HistoryFilterMode = _historyFilterCollection.Mode;
|
||||
RefreshHistoryFilters(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1052,9 +1081,9 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public void SetTagFilterMode(Models.Tag tag, Models.FilterMode mode)
|
||||
{
|
||||
var changed = _settings.UpdateHistoriesFilter(tag.Name, Models.FilterType.Tag, mode);
|
||||
var changed = _historyFilterCollection.Update(tag.Name, Models.FilterType.Tag, mode);
|
||||
if (changed)
|
||||
RefreshHistoriesFilters(true);
|
||||
RefreshHistoryFilters(true);
|
||||
}
|
||||
|
||||
public void SetBranchFilterMode(Models.Branch branch, Models.FilterMode mode, bool clearExists, bool refresh)
|
||||
@@ -1071,28 +1100,28 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (clearExists)
|
||||
{
|
||||
_settings.HistoriesFilters.Clear();
|
||||
HistoriesFilterMode = Models.FilterMode.None;
|
||||
_historyFilterCollection.Filters.Clear();
|
||||
HistoryFilterMode = Models.FilterMode.None;
|
||||
}
|
||||
|
||||
if (node.Backend is Models.Branch branch)
|
||||
{
|
||||
var type = isLocal ? Models.FilterType.LocalBranch : Models.FilterType.RemoteBranch;
|
||||
var changed = _settings.UpdateHistoriesFilter(node.Path, type, mode);
|
||||
var changed = _historyFilterCollection.Update(node.Path, type, mode);
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
if (isLocal && !string.IsNullOrEmpty(branch.Upstream) && !branch.IsUpstreamGone)
|
||||
_settings.UpdateHistoriesFilter(branch.Upstream, Models.FilterType.RemoteBranch, mode);
|
||||
_historyFilterCollection.Update(branch.Upstream, Models.FilterType.RemoteBranch, mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
var type = isLocal ? Models.FilterType.LocalBranchFolder : Models.FilterType.RemoteBranchFolder;
|
||||
var changed = _settings.UpdateHistoriesFilter(node.Path, type, mode);
|
||||
var changed = _historyFilterCollection.Update(node.Path, type, mode);
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
_settings.RemoveChildrenBranchFilters(node.Path);
|
||||
_historyFilterCollection.RemoveBranchFiltersByPrefix(node.Path);
|
||||
}
|
||||
|
||||
var parentType = isLocal ? Models.FilterType.LocalBranchFolder : Models.FilterType.RemoteBranchFolder;
|
||||
@@ -1108,11 +1137,11 @@ namespace SourceGit.ViewModels
|
||||
if (parent == null)
|
||||
break;
|
||||
|
||||
_settings.UpdateHistoriesFilter(parent.Path, parentType, Models.FilterMode.None);
|
||||
_historyFilterCollection.Update(parent.Path, parentType, Models.FilterMode.None);
|
||||
cur = parent;
|
||||
} while (true);
|
||||
|
||||
RefreshHistoriesFilters(refresh);
|
||||
RefreshHistoryFilters(refresh);
|
||||
}
|
||||
|
||||
public async Task StashAllAsync(bool autoStart)
|
||||
@@ -1304,7 +1333,7 @@ namespace SourceGit.ViewModels
|
||||
if (_settings.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.SimplifyByDecoration))
|
||||
builder.Append("--simplify-by-decoration ");
|
||||
|
||||
var filters = _settings.BuildHistoriesFilter();
|
||||
var filters = _historyFilterCollection.Build();
|
||||
if (string.IsNullOrEmpty(filters))
|
||||
builder.Append("--branches --remotes --tags HEAD");
|
||||
else
|
||||
@@ -1770,9 +1799,9 @@ namespace SourceGit.ViewModels
|
||||
builder.Run(visibles, remotes, true);
|
||||
}
|
||||
|
||||
var historiesFilters = _settings.CollectHistoriesFilters();
|
||||
UpdateBranchTreeFilterMode(builder.Locals, historiesFilters);
|
||||
UpdateBranchTreeFilterMode(builder.Remotes, historiesFilters);
|
||||
var filterMap = _historyFilterCollection.ToMap();
|
||||
UpdateBranchTreeFilterMode(builder.Locals, filterMap);
|
||||
UpdateBranchTreeFilterMode(builder.Remotes, filterMap);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -1802,21 +1831,21 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
var historiesFilters = _settings.CollectHistoriesFilters();
|
||||
UpdateTagFilterMode(historiesFilters);
|
||||
var filterMap = _historyFilterCollection.ToMap();
|
||||
UpdateTagFilterMode(filterMap);
|
||||
|
||||
if (Preferences.Instance.ShowTagsAsTree)
|
||||
{
|
||||
var tree = TagCollectionAsTree.Build(visible, _visibleTags as TagCollectionAsTree);
|
||||
foreach (var node in tree.Tree)
|
||||
node.UpdateFilterMode(historiesFilters);
|
||||
node.UpdateFilterMode(filterMap);
|
||||
return tree;
|
||||
}
|
||||
else
|
||||
{
|
||||
var list = new TagCollectionAsList(visible);
|
||||
foreach (var item in list.TagItems)
|
||||
item.FilterMode = historiesFilters.GetValueOrDefault(item.Tag.Name, Models.FilterMode.None);
|
||||
item.FilterMode = filterMap.GetValueOrDefault(item.Tag.Name, Models.FilterMode.None);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1843,45 +1872,41 @@ namespace SourceGit.ViewModels
|
||||
return new SubmoduleCollectionAsList() { Submodules = visible };
|
||||
}
|
||||
|
||||
private void RefreshHistoriesFilters(bool refresh)
|
||||
private void RefreshHistoryFilters(bool refresh)
|
||||
{
|
||||
if (_settings.HistoriesFilters.Count > 0)
|
||||
HistoriesFilterMode = _settings.HistoriesFilters[0].Mode;
|
||||
else
|
||||
HistoriesFilterMode = Models.FilterMode.None;
|
||||
|
||||
HistoryFilterMode = _historyFilterCollection.Mode;
|
||||
if (!refresh)
|
||||
return;
|
||||
|
||||
var filters = _settings.CollectHistoriesFilters();
|
||||
UpdateBranchTreeFilterMode(LocalBranchTrees, filters);
|
||||
UpdateBranchTreeFilterMode(RemoteBranchTrees, filters);
|
||||
UpdateTagFilterMode(filters);
|
||||
var map = _historyFilterCollection.ToMap();
|
||||
UpdateBranchTreeFilterMode(LocalBranchTrees, map);
|
||||
UpdateBranchTreeFilterMode(RemoteBranchTrees, map);
|
||||
UpdateTagFilterMode(map);
|
||||
RefreshCommits();
|
||||
}
|
||||
|
||||
private void UpdateBranchTreeFilterMode(List<BranchTreeNode> nodes, Dictionary<string, Models.FilterMode> filters)
|
||||
private void UpdateBranchTreeFilterMode(List<BranchTreeNode> nodes, Dictionary<string, Models.FilterMode> map)
|
||||
{
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
node.FilterMode = filters.GetValueOrDefault(node.Path, Models.FilterMode.None);
|
||||
node.FilterMode = map.GetValueOrDefault(node.Path, Models.FilterMode.None);
|
||||
|
||||
if (!node.IsBranch)
|
||||
UpdateBranchTreeFilterMode(node.Children, filters);
|
||||
UpdateBranchTreeFilterMode(node.Children, map);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTagFilterMode(Dictionary<string, Models.FilterMode> filters)
|
||||
private void UpdateTagFilterMode(Dictionary<string, Models.FilterMode> map)
|
||||
{
|
||||
if (VisibleTags is TagCollectionAsTree tree)
|
||||
{
|
||||
foreach (var node in tree.Tree)
|
||||
node.UpdateFilterMode(filters);
|
||||
node.UpdateFilterMode(map);
|
||||
}
|
||||
else if (VisibleTags is TagCollectionAsList list)
|
||||
{
|
||||
foreach (var item in list.TagItems)
|
||||
item.FilterMode = filters.GetValueOrDefault(item.Tag.Name, Models.FilterMode.None);
|
||||
item.FilterMode = map.GetValueOrDefault(item.Tag.Name, Models.FilterMode.None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2040,7 +2065,8 @@ namespace SourceGit.ViewModels
|
||||
private readonly bool _isWorktree = false;
|
||||
private readonly string _gitCommonDir = null;
|
||||
private Models.RepositorySettings _settings = null;
|
||||
private Models.FilterMode _historiesFilterMode = Models.FilterMode.None;
|
||||
private Models.HistoryFilterCollection _historyFilterCollection = null;
|
||||
private Models.FilterMode _historyFilterMode = Models.FilterMode.None;
|
||||
private bool _hasAllowedSignersFile = false;
|
||||
|
||||
private Models.Watcher _watcher = null;
|
||||
|
||||
@@ -785,7 +785,7 @@
|
||||
<Border.IsVisible>
|
||||
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
||||
<Binding Path="SelectedViewIndex" Converter="{x:Static c:IntConverters.IsZero}"/>
|
||||
<Binding Path="Settings.HistoriesFilters.Count" Converter="{x:Static c:IntConverters.IsGreaterThanZero}"/>
|
||||
<Binding Path="HistoryFilterCollection.Filters.Count" Converter="{x:Static c:IntConverters.IsGreaterThanZero}"/>
|
||||
</MultiBinding>
|
||||
</Border.IsVisible>
|
||||
|
||||
@@ -795,15 +795,15 @@
|
||||
Width="12" Height="12"
|
||||
Data="{StaticResource Icons.Filter}"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
IsVisible="{Binding HistoriesFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Included}}"/>
|
||||
IsVisible="{Binding HistoryFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Included}}"/>
|
||||
<Path Grid.Column="0"
|
||||
Margin="8,0,0,0"
|
||||
Width="12" Height="12"
|
||||
Data="{StaticResource Icons.EyeClose}"
|
||||
Fill="{DynamicResource Brush.FG2}"
|
||||
IsVisible="{Binding HistoriesFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Excluded}}"/>
|
||||
IsVisible="{Binding HistoryFilterMode, Converter={x:Static ObjectConverters.Equal}, ConverterParameter={x:Static m:FilterMode.Excluded}}"/>
|
||||
|
||||
<ItemsControl Grid.Column="1" Margin="8,4" ItemsSource="{Binding Settings.HistoriesFilters}">
|
||||
<ItemsControl Grid.Column="1" Margin="8,4" ItemsSource="{Binding HistoryFilterCollection.Filters}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Orientation="Horizontal" ItemHeight="22"/>
|
||||
@@ -811,7 +811,7 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="m:Filter">
|
||||
<DataTemplate DataType="m:HistoryFilter">
|
||||
<Border Height="20"
|
||||
Margin="0,0,6,0"
|
||||
CornerRadius="12"
|
||||
@@ -823,7 +823,7 @@
|
||||
<Path Width="10" Height="10" Data="{StaticResource Icons.Tag}" IsVisible="{Binding !IsBranch}"/>
|
||||
<TextBlock Text="{Binding Pattern, Converter={x:Static c:StringConverters.TrimRefsPrefix}}" Margin="4,0,8,0"/>
|
||||
|
||||
<Button Classes="icon_button" VerticalAlignment="Center" Margin="0" Padding="0" Click="OnRemoveSelectedHistoriesFilter">
|
||||
<Button Classes="icon_button" VerticalAlignment="Center" Margin="0" Padding="0" Click="OnRemoveSelectedHistoryFilter">
|
||||
<Path Width="8" Height="8" Data="{StaticResource Icons.Close}"/>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
@@ -832,7 +832,7 @@
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<Button Grid.Column="2" Classes="icon_button" Command="{Binding ClearHistoriesFilter}" ToolTip.Tip="{DynamicResource Text.Repository.ClearAllCommitsFilter}">
|
||||
<Button Grid.Column="2" Classes="icon_button" Command="{Binding ClearHistoryFilters}" ToolTip.Tip="{DynamicResource Text.Repository.ClearAllCommitsFilter}">
|
||||
<Path Width="14" Height="14" Margin="16,0,8,0" Data="{StaticResource Icons.RemoveAll}"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
||||
@@ -586,10 +586,10 @@ namespace SourceGit.Views
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnRemoveSelectedHistoriesFilter(object sender, RoutedEventArgs e)
|
||||
private void OnRemoveSelectedHistoryFilter(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter })
|
||||
repo.RemoveHistoriesFilter(filter);
|
||||
if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.HistoryFilter filter })
|
||||
repo.RemoveHistoryFilter(filter);
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user