From 32b3d9f39fe91d1b097cca16535b289234c001d7 Mon Sep 17 00:00:00 2001 From: heartacker Date: Thu, 7 Aug 2025 18:21:12 +0800 Subject: [PATCH 1/7] feat: Add solo commits filter and enhance history filtering - Add new filter type for solo commits to the filter options. - Enhance history filtering to support solo commits by including or excluding their associated refs. - Add new localization string for solo commits option in context menu. - Add methods to filter and query commits by solo commit mode and refs containing a specific commit. - Add a menu option to filter commits by focusing on a specific commit. --- src/Models/Filter.cs | 1 + src/Models/RepositorySettings.cs | 30 +++++++++++++++++++++++++++++- src/Resources/Locales/en_US.axaml | 1 + src/ViewModels/Repository.cs | 20 +++++++++++++++++++- src/Views/Histories.axaml.cs | 11 +++++++++++ 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/Models/Filter.cs b/src/Models/Filter.cs index af4569fad..7a3923e77 100644 --- a/src/Models/Filter.cs +++ b/src/Models/Filter.cs @@ -9,6 +9,7 @@ public enum FilterType RemoteBranch, RemoteBranchFolder, Tag, + SoloCommits, } public enum FilterMode diff --git a/src/Models/RepositorySettings.cs b/src/Models/RepositorySettings.cs index 1dd194857..8767d84bf 100644 --- a/src/Models/RepositorySettings.cs +++ b/src/Models/RepositorySettings.cs @@ -306,7 +306,7 @@ public void RemoveChildrenBranchFilters(string pattern) HistoriesFilters.Remove(filter); } - public string BuildHistoriesFilter() + public string BuildHistoriesFilter(SourceGit.ViewModels.Repository repo) { var includedRefs = new List(); var excludedBranches = new List(); @@ -349,6 +349,34 @@ public string BuildHistoriesFilter() else if (filter.Mode == FilterMode.Excluded) excludedTags.Add($"--exclude=\"{filter.Pattern}\" --decorate-refs-exclude=\"refs/tags/{filter.Pattern}\""); } + else if (filter.Type == FilterType.SoloCommits) + { + var allRefs = repo.GetRefsContainsThisCommit(filter.Pattern); + if (filter.Mode == FilterMode.Included) + { + foreach (var refItem in allRefs) + { + if (refItem.Type == Models.DecoratorType.LocalBranchHead) + includedRefs.Add($"{refItem.Name}"); + else if (refItem.Type == Models.DecoratorType.RemoteBranchHead) + includedRefs.Add($"{refItem.Name}"); + else if (refItem.Type == Models.DecoratorType.Tag) + includedRefs.Add($"refs/tags/{refItem.Name}"); + } + } + else if (filter.Mode == FilterMode.Excluded) + { + foreach (var refItem in allRefs) + { + if (refItem.Type == Models.DecoratorType.LocalBranchHead) + excludedBranches.Add($"--exclude=\"{refItem.Name}\" --decorate-refs-exclude=\"refs/heads/{refItem.Name}\""); + else if (refItem.Type == Models.DecoratorType.RemoteBranchHead) + excludedRemotes.Add($"--exclude=\"{refItem.Name}\" --decorate-refs-exclude=\"refs/remotes/{refItem.Name}\""); + else if (refItem.Type == Models.DecoratorType.Tag) + excludedTags.Add($"--exclude=\"refs/tags/{refItem.Name}\" --decorate-refs-exclude=\"refs/tags/{refItem.Name}\""); + } + } + } } var builder = new StringBuilder(); diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index a11e9edd1..59eb78b51 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -126,6 +126,7 @@ SHA Subject Custom Action + Solo on Current Commit Interactive Rebase Drop... Edit... diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 9adbb1a8e..4c7f42b20 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1062,6 +1062,17 @@ public void SetTagFilterMode(Models.Tag tag, Models.FilterMode mode) if (changed) RefreshHistoriesFilters(true); } + public void SetSoloCommitFilterMode(Models.Commit commit, Models.FilterMode mode) + { + SetSoloCommitFilterMode(commit.SHA[..10], mode); + } + + public void SetSoloCommitFilterMode(string sha, Models.FilterMode mode) + { + var changed = _settings.UpdateHistoriesFilter(sha, Models.FilterType.SoloCommits, mode); + if (changed) + RefreshHistoriesFilters(true); + } public void SetBranchFilterMode(Models.Branch branch, Models.FilterMode mode, bool clearExists, bool refresh) { @@ -1257,6 +1268,13 @@ public void RefreshTags() }); } + public List GetRefsContainsThisCommit(string hash = null) + { + var a = new Commands.QueryRefsContainsCommit(FullPath, hash ?? "HEAD") + .GetResultAsync(); + return a.Result; + } + public void RefreshCommits() { Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true); @@ -1278,7 +1296,7 @@ public void RefreshCommits() if (_settings.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.SimplifyByDecoration)) builder.Append("--simplify-by-decoration "); - var filters = _settings.BuildHistoriesFilter(); + var filters = _settings.BuildHistoriesFilter(this); if (string.IsNullOrEmpty(filters)) builder.Append("--branches --remotes --tags HEAD"); else diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 83ce5ee0c..d0fe5382d 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -824,6 +824,17 @@ private ContextMenu CreateContextMenuForSingleCommit(ViewModels.Repository repo, menu.Items.Add(new MenuItem() { Header = "-" }); } + var SoloCommits = new MenuItem(); + SoloCommits.Header = App.Text("CommitCM.SoloCommits"); + SoloCommits.Icon = App.CreateMenuIcon("Icons.LightOn"); + SoloCommits.Click += (_, e) => + { + repo.SetSoloCommitFilterMode(commit, Models.FilterMode.Included); + e.Handled = true; + }; + + menu.Items.Add(SoloCommits); + var copySHA = new MenuItem(); copySHA.Header = App.Text("CommitCM.CopySHA"); copySHA.Icon = App.CreateMenuIcon("Icons.Hash"); From bcc04645552c73861f1f08d273ff5f6429def896 Mon Sep 17 00:00:00 2001 From: heartacker Date: Thu, 7 Aug 2025 18:22:21 +0800 Subject: [PATCH 2/7] feat: Add solo mode functionality to repository toolbar - Add a new localization string for solo mode functionality on HEAD. - Add a solo mode button to the repository toolbar for toggling the current head view. - Add solo commit filter mode for the current HEAD branch. - Add `HEAD` and `HEAD_SHA` both is usefull and comparable while HEAD is Changed --- src/Resources/Locales/en_US.axaml | 1 + src/ViewModels/Repository.cs | 20 +++++++++++++++++--- src/Views/RepositoryToolbar.axaml | 3 +++ src/Views/RepositoryToolbar.axaml.cs | 9 +++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 59eb78b51..927f4c208 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -655,6 +655,7 @@ LOCAL BRANCHES More options... Navigate to HEAD + Solo On HEAD Create Branch CLEAR NOTIFICATIONS Only highlight current branch diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 4c7f42b20..055938295 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using System.Text.Json; using System.Threading; @@ -1062,10 +1063,13 @@ public void SetTagFilterMode(Models.Tag tag, Models.FilterMode mode) if (changed) RefreshHistoriesFilters(true); } + public void SetSoloCommitFilterMode(Models.Commit commit, Models.FilterMode mode) - { - SetSoloCommitFilterMode(commit.SHA[..10], mode); - } + => SetSoloCommitFilterMode(commit.SHA[..10], mode); + + + public void SetSoloCommitFilterMode(IEnumerable commits, Models.FilterMode mode) + => SetSoloCommitFilterMode(commits.Select(x => x.SHA[..10]).ToList(), mode); public void SetSoloCommitFilterMode(string sha, Models.FilterMode mode) { @@ -1074,6 +1078,16 @@ public void SetSoloCommitFilterMode(string sha, Models.FilterMode mode) RefreshHistoriesFilters(true); } + public void SetSoloCommitFilterMode(IEnumerable shas, Models.FilterMode mode) + { + bool changed = false; + foreach (var sha in shas) + changed |= _settings.UpdateHistoriesFilter(sha, Models.FilterType.SoloCommits, mode); + + if (changed) + RefreshHistoriesFilters(true); + } + public void SetBranchFilterMode(Models.Branch branch, Models.FilterMode mode, bool clearExists, bool refresh) { var node = FindBranchNode(branch.IsLocal ? _localBranchTrees : _remoteBranchTrees, branch.FullName); diff --git a/src/Views/RepositoryToolbar.axaml b/src/Views/RepositoryToolbar.axaml index 2e62e55ef..277276a47 100644 --- a/src/Views/RepositoryToolbar.axaml +++ b/src/Views/RepositoryToolbar.axaml @@ -132,6 +132,9 @@ + diff --git a/src/Views/RepositoryToolbar.axaml.cs b/src/Views/RepositoryToolbar.axaml.cs index 027e64584..7def7c7f1 100644 --- a/src/Views/RepositoryToolbar.axaml.cs +++ b/src/Views/RepositoryToolbar.axaml.cs @@ -462,5 +462,14 @@ private void NavigateToHead(object sender, RoutedEventArgs e) e.Handled = true; } } + + private void SoloModeOnCurrentHead(object sender, RoutedEventArgs e) + { + if (DataContext is ViewModels.Repository { CurrentBranch: not null } repo) + { + repo.SetSoloCommitFilterMode(["HEAD", repo.CurrentBranch.Head[..10]], Models.FilterMode.Included); + e.Handled = true; + } + } } } From 14f6e9ed91ae662b9f9e4304b42fd1ff5332a134 Mon Sep 17 00:00:00 2001 From: heartacker Date: Thu, 7 Aug 2025 22:56:12 +0800 Subject: [PATCH 3/7] feat: Add solo multi commits filter - Add solo commits filter option to the context menu for commit selection. - it will be useful for compare those branchs/tags/commits --- src/Views/Histories.axaml.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index d0fe5382d..1ac8551de 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -412,6 +412,17 @@ private ContextMenu CreateContextMenuForMultipleCommits(ViewModels.Repository re menu.Items.Add(saveToPatch); menu.Items.Add(new MenuItem() { Header = "-" }); + var soloCommits = new MenuItem(); + soloCommits.Header = App.Text("CommitCM.SoloCommits"); + soloCommits.Icon = App.CreateMenuIcon("Icons.LightOn"); + soloCommits.Click += (_, e) => + { + repo.SetSoloCommitFilterMode(selected, Models.FilterMode.Included); + e.Handled = true; + }; + menu.Items.Add(soloCommits); + menu.Items.Add(new MenuItem() { Header = "-" }); + var copyShas = new MenuItem(); copyShas.Header = App.Text("CommitCM.CopySHA"); copyShas.Icon = App.CreateMenuIcon("Icons.Hash"); From 28d90fafb918ca8f2980271552d4e7c64ed0aa79 Mon Sep 17 00:00:00 2001 From: heartacker Date: Fri, 8 Aug 2025 10:18:51 +0800 Subject: [PATCH 4/7] feat: support navigat filter to repository view - Add branch and tag navigation support to the repository view model. - Increase filter item height and replace text block with clickable button for navigation. - Add navigation functionality for different filter types in the repository view. --- src/ViewModels/Repository.cs | 16 ++++++++++++++++ src/Views/Repository.axaml | 12 +++++++++--- src/Views/Repository.axaml.cs | 29 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 055938295..b52f63a2a 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1006,10 +1006,26 @@ public void NavigateToCommit(string sha, bool isDelayMode = false) else if (_histories != null) { SelectedViewIndex = 0; + if (sha == "HEAD") + sha = _currentBranch.Head; _histories.NavigateTo(sha); } } + public void NavigateToBranch(string branch, bool isDelayMode = false) + { + var b = _branches.Find(b => b.FullName.Equals(branch, StringComparison.Ordinal)); + if (b != null) + NavigateToCommit(b.Head); + } + + public void NavigateToTag(string tag, bool isDelayMode = false) + { + var t = _tags.Find(t => t.Name.Equals(tag, StringComparison.Ordinal)); + if (t != null) + NavigateToCommit(t.SHA); + } + public void ClearCommitMessage() { if (_workingCopy is not null) diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 71a1f322a..29476cbae 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -800,7 +800,7 @@ - - - + diff --git a/src/Views/Repository.axaml.cs b/src/Views/Repository.axaml.cs index ed6901fe1..0719599e0 100644 --- a/src/Views/Repository.axaml.cs +++ b/src/Views/Repository.axaml.cs @@ -659,6 +659,35 @@ private async void OnAbortInProgress(object sender, RoutedEventArgs e) e.Handled = true; } + private void OnNavigateToFilter(object sender, RoutedEventArgs e) + { + if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter }) + { + if (filter.Mode == Models.FilterMode.Excluded) + return; + + switch (filter.Type) + { + default: + case Models.FilterType.LocalBranchFolder: + case Models.FilterType.RemoteBranchFolder: + break; + case Models.FilterType.LocalBranch: + case Models.FilterType.RemoteBranch: + repo.NavigateToBranch(filter.Pattern); + break; + case Models.FilterType.Tag: + repo.NavigateToTag(filter.Pattern); + break; + case Models.FilterType.SoloCommits: + repo.NavigateToCommit(filter.Pattern); + break; + } + e.Handled = true; + } + } + + private void OnRemoveSelectedHistoriesFilter(object sender, RoutedEventArgs e) { if (DataContext is ViewModels.Repository repo && sender is Button { DataContext: Models.Filter filter }) From 443e13903514ab75824b2df7b82c77a7e3f3eb56 Mon Sep 17 00:00:00 2001 From: heartacker Date: Fri, 8 Aug 2025 15:38:37 +0800 Subject: [PATCH 5/7] feat: remember the multi selected commit if avalible - it is usefull for multi selection. - like two revision compare, it will keep those selection for compare while filter changed --- src/ViewModels/Histories.cs | 15 +++++++++++++++ src/ViewModels/Repository.cs | 11 +++++++++++ src/Views/Histories.axaml.cs | 21 +++++++++++++++++++++ src/Views/Repository.axaml | 1 + 4 files changed, 48 insertions(+) diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index 86424f6d8..688cde70f 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using Avalonia.Controls; @@ -44,6 +45,12 @@ public Models.Commit AutoSelectedCommit set => SetProperty(ref _autoSelectedCommit, value); } + public List LastSelectedCommits + { + get => _lastSelectedCommits; + private set => SetProperty(ref _lastSelectedCommits, value); + } + public long NavigationId { get => _navigationId; @@ -191,6 +198,13 @@ public void Select(IList commits) _repo.SelectedSearchedCommit = null; DetailContext = new Models.Count(commits.Count); } + + _repo.SelectedCommits = commits.Cast().ToList(); + } + + public void MarkCommitsAsSelected(IList commits) + { + LastSelectedCommits = _commits.Where(x => commits.Any(y => y.SHA == x.SHA)).ToList(); } public bool CheckoutBranchByDecorator(Models.Decorator decorator) @@ -402,6 +416,7 @@ private void NavigateTo(Models.Commit commit) private Repository _repo = null; private bool _isLoading = true; private List _commits = new List(); + private List _lastSelectedCommits = []; private Models.CommitGraph _graph = null; private Models.Commit _autoSelectedCommit = null; private Models.Bisect _bisect = null; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index b52f63a2a..77621238a 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -349,6 +349,12 @@ public List SearchedCommits set => SetProperty(ref _searchedCommits, value); } + public List SelectedCommits + { + get => _selectCommits; + set => SetProperty(ref _selectCommits, value); + } + public Models.Commit SelectedSearchedCommit { get => _selectedSearchedCommit; @@ -1307,6 +1313,8 @@ public void RefreshTags() public void RefreshCommits() { + var oldSelectedCommits = _selectCommits.ToList(); + Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true); var builder = new StringBuilder(); @@ -1345,6 +1353,8 @@ public void RefreshCommits() BisectState = _histories.UpdateBisectInfo(); + _histories.MarkCommitsAsSelected(oldSelectedCommits); + if (!string.IsNullOrEmpty(_navigateToCommitDelayed)) NavigateToCommit(_navigateToCommitDelayed); } @@ -2031,6 +2041,7 @@ private async void AutoFetchImpl(object sender) private bool _onlySearchCommitsInCurrentBranch = false; private string _searchCommitFilter = string.Empty; private List _searchedCommits = new List(); + private List _selectCommits = new List(); private Models.Commit _selectedSearchedCommit = null; private bool _requestingWorktreeFiles = false; private List _worktreeFiles = null; diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index 1ac8551de..edc2fc178 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -122,6 +122,15 @@ public long NavigationId set => SetValue(NavigationIdProperty, value); } + public static readonly StyledProperty> LastSelectedCommitsProperty = + AvaloniaProperty.Register>(nameof(LastSelectedCommits)); + + public List LastSelectedCommits + { + get => GetValue(LastSelectedCommitsProperty); + set => SetValue(LastSelectedCommitsProperty, value); + } + public static readonly StyledProperty IsScrollToTopVisibleProperty = AvaloniaProperty.Register(nameof(IsScrollToTopVisible)); @@ -145,6 +154,18 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang if (CommitListContainer is { SelectedItems.Count: 1, IsLoaded: true } dataGrid) dataGrid.ScrollIntoView(dataGrid.SelectedItem, null); } + if (change.Property == LastSelectedCommitsProperty) + { + if (LastSelectedCommits?.Count > 1 && + (CommitListContainer is DataGrid { IsLoaded: true } dataGrid)) + { + foreach (var c in LastSelectedCommits) + { + dataGrid.SelectedItems.Add(c); + } + } + } + } private void OnCommitListLoaded(object sender, RoutedEventArgs e) diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index 29476cbae..b0f58f83e 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -838,6 +838,7 @@ Bisect="{Binding Bisect}" IssueTrackers="{Binding $parent[v:Repository].((vm:Repository)DataContext).IssueTrackers}" OnlyHighlightCurrentBranch="{Binding $parent[v:Repository].((vm:Repository)DataContext).OnlyHighlightCurrentBranchInHistories}" + LastSelectedCommits="{Binding LastSelectedCommits}" NavigationId="{Binding NavigationId}"/> From 0db270b8aeb806fa017fd19bb6af4ba8091f45d5 Mon Sep 17 00:00:00 2001 From: heartacker Date: Fri, 8 Aug 2025 16:38:09 +0800 Subject: [PATCH 6/7] improvement: do not clear the commit filter while change the branch - do not clear the commit filter while changing the branch - do not change the filter if thereis `HEAD` filter while changing branch --- src/ViewModels/Checkout.cs | 6 ++++-- src/ViewModels/Repository.cs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ViewModels/Checkout.cs b/src/ViewModels/Checkout.cs index ce6195b8d..8f14813e0 100644 --- a/src/ViewModels/Checkout.cs +++ b/src/ViewModels/Checkout.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; namespace SourceGit.ViewModels { @@ -102,7 +103,8 @@ public override async Task Sure() 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.HistoriesFilterMode == Models.FilterMode.Included + && !_repo.Settings.HistoriesFilters.Any(f => f.Pattern == "HEAD")) _repo.SetBranchFilterMode(b, Models.FilterMode.Included, true, false); _repo.MarkBranchesDirtyManually(); diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 77621238a..c5692e9a8 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1124,8 +1124,10 @@ public void SetBranchFilterMode(BranchTreeNode node, Models.FilterMode mode, boo if (clearExists) { - _settings.HistoriesFilters.Clear(); - HistoriesFilterMode = Models.FilterMode.None; + _settings.HistoriesFilters.RemoveAll(_settings.HistoriesFilters + .Where(f => f.Type != Models.FilterType.SoloCommits).ToArray()); + if (_settings.HistoriesFilters.Count <= 0) + HistoriesFilterMode = Models.FilterMode.None; } if (node.Backend is Models.Branch branch) From febb6ee3de3089b2205b45dbbd57c9e310a0b8a8 Mon Sep 17 00:00:00 2001 From: heartacker Date: Sat, 9 Aug 2025 16:33:12 +0800 Subject: [PATCH 7/7] feat: Mark "filter commit" in the view to Make the UI experience better - Add commit filtering by SHA patterns and track filtered head commits. - Add property to track if commit is a filter head in commit model. - Add filter support to commit graph by introducing a new DotType and handling filter head commits. - Enhance commit querying by adding support for solo commit filters in the history view. - Add new filter dot type visualization to the commit graph. --- src/Commands/QueryCommits.cs | 6 +++++- src/Models/Commit.cs | 1 + src/Models/CommitGraph.cs | 5 ++++- src/ViewModels/Repository.cs | 4 +++- src/Views/CommitGraph.cs | 6 ++++++ 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index 311406bdc..92f132560 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -7,12 +8,13 @@ namespace SourceGit.Commands { public class QueryCommits : Command { - public QueryCommits(string repo, string limits, bool needFindHead = true) + public QueryCommits(string repo, string limits, bool needFindHead = true, List patterns = null) { WorkingDirectory = repo; Context = repo; Args = $"log --no-show-signature --decorate=full --format=%H%n%P%n%D%n%aN±%aE%n%at%n%cN±%cE%n%ct%n%s {limits}"; _findFirstMerged = needFindHead; + _patterns = patterns ?? new List(); } public QueryCommits(string repo, string filter, Models.CommitSearchMethod method, bool onlyCurrentBranch) @@ -70,6 +72,7 @@ public QueryCommits(string repo, string filter, Models.CommitSearchMethod method { case 0: _current = new Models.Commit() { SHA = line }; + _current.IsCommitFilterHead = _patterns.Count > 0 && _patterns.Any(f => line.StartsWith(f)); _commits.Add(_current); break; case 1: @@ -143,6 +146,7 @@ private async Task MarkFirstMergedAsync() } private List _commits = new List(); + private List _patterns = new List(); private Models.Commit _current = null; private bool _findFirstMerged = false; private bool _isHeadFound = false; diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs index 61438424a..78f12d41c 100644 --- a/src/Models/Commit.cs +++ b/src/Models/Commit.cs @@ -42,6 +42,7 @@ public static double OpacityForNotMerged public string AuthorTimeShortStr => DateTime.UnixEpoch.AddSeconds(AuthorTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly); public string CommitterTimeShortStr => DateTime.UnixEpoch.AddSeconds(CommitterTime).ToLocalTime().ToString(DateTimeFormat.Active.DateOnly); + public bool IsCommitFilterHead { get; set; } = false; public bool IsMerged { get; set; } = false; public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime; public bool IsCurrentHead => Decorators.Find(x => x.Type is DecoratorType.CurrentBranchHead or DecoratorType.CurrentCommitHead) != null; diff --git a/src/Models/CommitGraph.cs b/src/Models/CommitGraph.cs index cb5696101..b122a72eb 100644 --- a/src/Models/CommitGraph.cs +++ b/src/Models/CommitGraph.cs @@ -53,6 +53,7 @@ public enum DotType Default, Head, Merge, + Filter, } public class Dot @@ -157,7 +158,9 @@ public static CommitGraph Parse(List commits, bool firstParentOnlyEnable var position = new Point(major?.LastX ?? offsetX, offsetY); var dotColor = major?.Path.Color ?? 0; var anchor = new Dot() { Center = position, Color = dotColor, IsMerged = isMerged }; - if (commit.IsCurrentHead) + if (commit.IsCommitFilterHead) + anchor.Type = DotType.Filter; + else if (commit.IsCurrentHead) anchor.Type = DotType.Head; else if (commit.Parents.Count > 1) anchor.Type = DotType.Merge; diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index c5692e9a8..f4550e344 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1342,7 +1342,9 @@ public void RefreshCommits() else builder.Append(filters); - var commits = new Commands.QueryCommits(_fullpath, builder.ToString()).GetResultAsync().Result; + var patterns = _settings.HistoriesFilters.Where(f => f.Type == Models.FilterType.SoloCommits).Select(f => f.Pattern).ToList(); + + var commits = new Commands.QueryCommits(_fullpath, builder.ToString(), true, patterns).GetResultAsync().Result; var graph = Models.CommitGraph.Parse(commits, _settings.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.FirstParentOnly)); Dispatcher.UIThread.Invoke(() => diff --git a/src/Views/CommitGraph.cs b/src/Views/CommitGraph.cs index 858ff3a07..750109a8b 100644 --- a/src/Views/CommitGraph.cs +++ b/src/Views/CommitGraph.cs @@ -230,6 +230,12 @@ private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, doubl context.DrawLine(dotFillPen, new Point(center.X, center.Y - 3), new Point(center.X, center.Y + 3)); context.DrawLine(dotFillPen, new Point(center.X - 3, center.Y), new Point(center.X + 3, center.Y)); break; + case Models.CommitGraph.DotType.Filter: + context.DrawEllipse(pen.Brush, null, center, 7, 7); + context.DrawLine(dotFillPen, new Point(center.X, center.Y - 5), new Point(center.X, center.Y + 5)); + context.DrawLine(dotFillPen, new Point(center.X - 4, center.Y - 3), new Point(center.X + 4, center.Y + 3)); + context.DrawLine(dotFillPen, new Point(center.X + 4, center.Y - 3), new Point(center.X - 4, center.Y + 3)); + break; default: context.DrawEllipse(dotFill, pen, center, 3, 3); break;