Skip to content

Solo commits filter #1691

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Commands/QueryCommits.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

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<string> 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<string>();
}

public QueryCommits(string repo, string filter, Models.CommitSearchMethod method, bool onlyCurrentBranch)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -143,6 +146,7 @@ private async Task MarkFirstMergedAsync()
}

private List<Models.Commit> _commits = new List<Models.Commit>();
private List<string> _patterns = new List<string>();
private Models.Commit _current = null;
private bool _findFirstMerged = false;
private bool _isHeadFound = false;
Expand Down
1 change: 1 addition & 0 deletions src/Models/Commit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion src/Models/CommitGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public enum DotType
Default,
Head,
Merge,
Filter,
}

public class Dot
Expand Down Expand Up @@ -157,7 +158,9 @@ public static CommitGraph Parse(List<Commit> 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;
Expand Down
1 change: 1 addition & 0 deletions src/Models/Filter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public enum FilterType
RemoteBranch,
RemoteBranchFolder,
Tag,
SoloCommits,
}

public enum FilterMode
Expand Down
30 changes: 29 additions & 1 deletion src/Models/RepositorySettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>();
var excludedBranches = new List<string>();
Expand Down Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions src/Resources/Locales/en_US.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.CommitCM.CopySubject" xml:space="preserve">Subject</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Custom Action</x:String>
<x:String x:Key="Text.CommitCM.SoloCommits" xml:space="preserve">Solo on Current Commit</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactive Rebase</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase.Drop" xml:space="preserve">Drop...</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase.Edit" xml:space="preserve">Edit...</x:String>
Expand Down Expand Up @@ -654,6 +655,7 @@
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOCAL BRANCHES</x:String>
<x:String x:Key="Text.Repository.MoreOptions" xml:space="preserve">More options...</x:String>
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate to HEAD</x:String>
<x:String x:Key="Text.Repository.SoloModeOnCurrentHead" xml:space="preserve">Solo On HEAD</x:String>
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
<x:String x:Key="Text.Repository.Notifications.Clear" xml:space="preserve">CLEAR NOTIFICATIONS</x:String>
<x:String x:Key="Text.Repository.OnlyHighlightCurrentBranchInGraph" xml:space="preserve">Only highlight current branch</x:String>
Expand Down
6 changes: 4 additions & 2 deletions src/ViewModels/Checkout.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Linq;
using System.Threading.Tasks;

namespace SourceGit.ViewModels
{
Expand Down Expand Up @@ -102,7 +103,8 @@ public override async Task<bool> 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();
Expand Down
15 changes: 15 additions & 0 deletions src/ViewModels/Histories.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Avalonia.Controls;
Expand Down Expand Up @@ -44,6 +45,12 @@ public Models.Commit AutoSelectedCommit
set => SetProperty(ref _autoSelectedCommit, value);
}

public List<Models.Commit> LastSelectedCommits
{
get => _lastSelectedCommits;
private set => SetProperty(ref _lastSelectedCommits, value);
}

public long NavigationId
{
get => _navigationId;
Expand Down Expand Up @@ -191,6 +198,13 @@ public void Select(IList commits)
_repo.SelectedSearchedCommit = null;
DetailContext = new Models.Count(commits.Count);
}

_repo.SelectedCommits = commits.Cast<Models.Commit>().ToList();
}

public void MarkCommitsAsSelected(IList<Models.Commit> commits)
{
LastSelectedCommits = _commits.Where(x => commits.Any(y => y.SHA == x.SHA)).ToList();
}

public bool CheckoutBranchByDecorator(Models.Decorator decorator)
Expand Down Expand Up @@ -402,6 +416,7 @@ private void NavigateTo(Models.Commit commit)
private Repository _repo = null;
private bool _isLoading = true;
private List<Models.Commit> _commits = new List<Models.Commit>();
private List<Models.Commit> _lastSelectedCommits = [];
private Models.CommitGraph _graph = null;
private Models.Commit _autoSelectedCommit = null;
private Models.Bisect _bisect = null;
Expand Down
71 changes: 67 additions & 4 deletions src/ViewModels/Repository.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -348,6 +349,12 @@ public List<Models.Commit> SearchedCommits
set => SetProperty(ref _searchedCommits, value);
}

public List<Models.Commit> SelectedCommits
{
get => _selectCommits;
set => SetProperty(ref _selectCommits, value);
}

public Models.Commit SelectedSearchedCommit
{
get => _selectedSearchedCommit;
Expand Down Expand Up @@ -1005,10 +1012,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)
Expand Down Expand Up @@ -1063,6 +1086,30 @@ public void SetTagFilterMode(Models.Tag tag, Models.FilterMode mode)
RefreshHistoriesFilters(true);
}

public void SetSoloCommitFilterMode(Models.Commit commit, Models.FilterMode mode)
=> SetSoloCommitFilterMode(commit.SHA[..10], mode);


public void SetSoloCommitFilterMode(IEnumerable<Models.Commit> commits, Models.FilterMode mode)
=> SetSoloCommitFilterMode(commits.Select(x => x.SHA[..10]).ToList(), mode);

public void SetSoloCommitFilterMode(string sha, Models.FilterMode mode)
{
var changed = _settings.UpdateHistoriesFilter(sha, Models.FilterType.SoloCommits, mode);
if (changed)
RefreshHistoriesFilters(true);
}

public void SetSoloCommitFilterMode(IEnumerable<string> 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);
Expand All @@ -1077,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)
Expand Down Expand Up @@ -1257,8 +1306,17 @@ public void RefreshTags()
});
}

public List<Models.Decorator> GetRefsContainsThisCommit(string hash = null)
{
var a = new Commands.QueryRefsContainsCommit(FullPath, hash ?? "HEAD")
.GetResultAsync();
return a.Result;
}

public void RefreshCommits()
{
var oldSelectedCommits = _selectCommits.ToList();

Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true);

var builder = new StringBuilder();
Expand All @@ -1278,13 +1336,15 @@ 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
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(() =>
Expand All @@ -1297,6 +1357,8 @@ public void RefreshCommits()

BisectState = _histories.UpdateBisectInfo();

_histories.MarkCommitsAsSelected(oldSelectedCommits);

if (!string.IsNullOrEmpty(_navigateToCommitDelayed))
NavigateToCommit(_navigateToCommitDelayed);
}
Expand Down Expand Up @@ -1983,6 +2045,7 @@ private async void AutoFetchImpl(object sender)
private bool _onlySearchCommitsInCurrentBranch = false;
private string _searchCommitFilter = string.Empty;
private List<Models.Commit> _searchedCommits = new List<Models.Commit>();
private List<Models.Commit> _selectCommits = new List<Models.Commit>();
private Models.Commit _selectedSearchedCommit = null;
private bool _requestingWorktreeFiles = false;
private List<string> _worktreeFiles = null;
Expand Down
6 changes: 6 additions & 0 deletions src/Views/CommitGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading