Skip to content

Commit 95ddedd

Browse files
committed
refactor: save history filters into $GIT_DIR/sourcegit.filters to support different filters between worktrees (#1893)
Signed-off-by: leo <longshuang@msn.cn>
1 parent 36aeb3f commit 95ddedd

File tree

12 files changed

+341
-309
lines changed

12 files changed

+341
-309
lines changed

src/App.JsonCodeGen.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public override void Write(Utf8JsonWriter writer, DataGridLength value, JsonSeri
6060
]
6161
)]
6262
[JsonSerializable(typeof(Models.ExternalToolPaths))]
63+
[JsonSerializable(typeof(Models.HistoryFilterCollection))]
6364
[JsonSerializable(typeof(Models.InteractiveRebaseJobCollection))]
6465
[JsonSerializable(typeof(Models.JetBrainsState))]
6566
[JsonSerializable(typeof(Models.ThemeOverrides))]

src/Models/Filter.cs

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Avalonia.Collections;
5+
using CommunityToolkit.Mvvm.ComponentModel;
6+
7+
namespace SourceGit.Models
8+
{
9+
public enum FilterType
10+
{
11+
LocalBranch = 0,
12+
LocalBranchFolder,
13+
RemoteBranch,
14+
RemoteBranchFolder,
15+
Tag,
16+
}
17+
18+
public enum FilterMode
19+
{
20+
None = 0,
21+
Included,
22+
Excluded,
23+
}
24+
25+
public class HistoryFilter : ObservableObject
26+
{
27+
public string Pattern
28+
{
29+
get => _pattern;
30+
set => SetProperty(ref _pattern, value);
31+
}
32+
33+
public FilterType Type
34+
{
35+
get;
36+
set;
37+
} = FilterType.LocalBranch;
38+
39+
public FilterMode Mode
40+
{
41+
get => _mode;
42+
set => SetProperty(ref _mode, value);
43+
}
44+
45+
public bool IsBranch
46+
{
47+
get => Type != FilterType.Tag;
48+
}
49+
50+
public HistoryFilter()
51+
{
52+
}
53+
54+
public HistoryFilter(string pattern, FilterType type, FilterMode mode)
55+
{
56+
_pattern = pattern;
57+
_mode = mode;
58+
Type = type;
59+
}
60+
61+
private string _pattern = string.Empty;
62+
private FilterMode _mode = FilterMode.None;
63+
}
64+
65+
public class HistoryFilterCollection
66+
{
67+
public AvaloniaList<HistoryFilter> Filters
68+
{
69+
get;
70+
set;
71+
} = [];
72+
73+
public FilterMode Mode => Filters.Count > 0 ? Filters[0].Mode : FilterMode.None;
74+
75+
public Dictionary<string, FilterMode> ToMap()
76+
{
77+
var map = new Dictionary<string, FilterMode>();
78+
foreach (var filter in Filters)
79+
map.Add(filter.Pattern, filter.Mode);
80+
return map;
81+
}
82+
83+
public bool Update(string pattern, FilterType type, FilterMode mode)
84+
{
85+
// Clear all filters when there's a filter that has different mode.
86+
if (mode != FilterMode.None)
87+
{
88+
var clear = false;
89+
foreach (var filter in Filters)
90+
{
91+
if (filter.Mode != mode)
92+
{
93+
clear = true;
94+
break;
95+
}
96+
}
97+
98+
if (clear)
99+
{
100+
Filters.Clear();
101+
Filters.Add(new HistoryFilter(pattern, type, mode));
102+
return true;
103+
}
104+
}
105+
else
106+
{
107+
for (int i = 0; i < Filters.Count; i++)
108+
{
109+
var filter = Filters[i];
110+
if (filter.Type == type && filter.Pattern.Equals(pattern, StringComparison.Ordinal))
111+
{
112+
Filters.RemoveAt(i);
113+
return true;
114+
}
115+
}
116+
117+
return false;
118+
}
119+
120+
foreach (var filter in Filters)
121+
{
122+
if (filter.Type != type)
123+
continue;
124+
125+
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
126+
return false;
127+
}
128+
129+
Filters.Add(new HistoryFilter(pattern, type, mode));
130+
return true;
131+
}
132+
133+
public FilterMode GetFilterMode(string pattern)
134+
{
135+
foreach (var filter in Filters)
136+
{
137+
if (filter.Pattern.Equals(pattern, StringComparison.Ordinal))
138+
return filter.Mode;
139+
}
140+
141+
return FilterMode.None;
142+
}
143+
144+
public void RemoveBranchFiltersByPrefix(string pattern)
145+
{
146+
var dirty = new List<HistoryFilter>();
147+
var prefix = $"{pattern}/";
148+
149+
foreach (var filter in Filters)
150+
{
151+
if (filter.Type != FilterType.Tag)
152+
continue;
153+
154+
if (filter.Pattern.StartsWith(prefix, StringComparison.Ordinal))
155+
dirty.Add(filter);
156+
}
157+
158+
foreach (var filter in dirty)
159+
Filters.Remove(filter);
160+
}
161+
162+
public string Build()
163+
{
164+
var includedRefs = new List<string>();
165+
var excludedBranches = new List<string>();
166+
var excludedRemotes = new List<string>();
167+
var excludedTags = new List<string>();
168+
foreach (var filter in Filters)
169+
{
170+
if (filter.Type == FilterType.LocalBranch)
171+
{
172+
if (filter.Mode == FilterMode.Included)
173+
includedRefs.Add(filter.Pattern);
174+
else if (filter.Mode == FilterMode.Excluded)
175+
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
176+
}
177+
else if (filter.Type == FilterType.LocalBranchFolder)
178+
{
179+
if (filter.Mode == FilterMode.Included)
180+
includedRefs.Add($"--branches={filter.Pattern.AsSpan(11)}/*");
181+
else if (filter.Mode == FilterMode.Excluded)
182+
excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
183+
}
184+
else if (filter.Type == FilterType.RemoteBranch)
185+
{
186+
if (filter.Mode == FilterMode.Included)
187+
includedRefs.Add(filter.Pattern);
188+
else if (filter.Mode == FilterMode.Excluded)
189+
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
190+
}
191+
else if (filter.Type == FilterType.RemoteBranchFolder)
192+
{
193+
if (filter.Mode == FilterMode.Included)
194+
includedRefs.Add($"--remotes={filter.Pattern.AsSpan(13)}/*");
195+
else if (filter.Mode == FilterMode.Excluded)
196+
excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
197+
}
198+
else if (filter.Type == FilterType.Tag)
199+
{
200+
if (filter.Mode == FilterMode.Included)
201+
includedRefs.Add($"refs/tags/{filter.Pattern}");
202+
else if (filter.Mode == FilterMode.Excluded)
203+
excludedTags.Add($"--exclude=\"{filter.Pattern}\" --decorate-refs-exclude=\"refs/tags/{filter.Pattern}\"");
204+
}
205+
}
206+
207+
var builder = new StringBuilder();
208+
if (includedRefs.Count > 0)
209+
{
210+
foreach (var r in includedRefs)
211+
{
212+
builder.Append(r);
213+
builder.Append(' ');
214+
}
215+
}
216+
else if (excludedBranches.Count + excludedRemotes.Count + excludedTags.Count > 0)
217+
{
218+
foreach (var b in excludedBranches)
219+
{
220+
builder.Append(b);
221+
builder.Append(' ');
222+
}
223+
224+
builder.Append("--exclude=HEAD --branches ");
225+
226+
foreach (var r in excludedRemotes)
227+
{
228+
builder.Append(r);
229+
builder.Append(' ');
230+
}
231+
232+
builder.Append("--exclude=origin/HEAD --remotes ");
233+
234+
foreach (var t in excludedTags)
235+
{
236+
builder.Append(t);
237+
builder.Append(' ');
238+
}
239+
240+
builder.Append("--tags ");
241+
}
242+
243+
return builder.ToString();
244+
}
245+
}
246+
}

0 commit comments

Comments
 (0)