Skip to content
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
1 change: 0 additions & 1 deletion src/Models/CommitGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ public static CommitGraph Generate(List<Commit> commits, bool firstParentOnlyEna
break;
}
}
commit.IsHighlightedInGraph = isHighlighted;

// If no path found, create new curve for branch head
// Otherwise, create new curve for new merged commit
Expand Down
86 changes: 69 additions & 17 deletions src/ViewModels/Histories.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.Threading;
using System.Threading.Tasks;

using Avalonia.Collections;
Expand Down Expand Up @@ -110,12 +111,6 @@ public bool IsCommitTimeColumnVisible
public List<Models.Commit> Commits
{
get => _commits;
set
{
GenerateGraph(value);
if (SetProperty(ref _commits, value))
PostCommitsChanged();
}
}

public Models.CommitGraph Graph
Expand All @@ -132,7 +127,7 @@ public Models.CommitGraphHighlighting GraphHighlighting
if (_repo.UIStates.GraphHighlighting != value)
{
_repo.UIStates.GraphHighlighting = value;
GenerateGraph(_commits);
RefreshGraph();
}
}
}
Expand Down Expand Up @@ -254,6 +249,46 @@ public void ToggleShowFlag(Models.HistoryShowFlags flag)
_repo.RefreshCommits();
}

public void SetCommits(List<Models.Commit> commits, Models.CommitGraph graph, HashSet<string> graphExtraHeads)
{
if (_cancellationRefreshGraph is { IsCancellationRequested: false })
_cancellationRefreshGraph.Cancel();

ApplyGraph(commits, graph);

if (SetProperty(ref _commits, commits, nameof(Commits)))
PostCommitsChanged();

// The selection may have changed while the graph was generated in background.
if (!graphExtraHeads.SetEquals(CollectGraphExtraHeads()))
RefreshGraph();
}

/// <summary>
/// Must be called on the UI thread: `_selectedCommits` is only modified there.
/// </summary>
public HashSet<string> CollectGraphExtraHeads()
{
var extraHeads = new HashSet<string>();
if (_repo.UIStates.GraphHighlighting >= Models.CommitGraphHighlighting.SelectedCommitsOnly)
{
foreach (var c in _selectedCommits)
extraHeads.Add(c.SHA);
}

return extraHeads;
}

/// <summary>
/// Thread-safe as long as `extraHeads` is not shared with the UI thread.
/// </summary>
public Models.CommitGraph GenerateGraph(List<Models.Commit> commits, HashSet<string> extraHeads)
{
var firstParentOnly = _repo.UIStates.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.FirstParentOnly);
var highlighting = _repo.UIStates.GraphHighlighting;
return Models.CommitGraph.Generate(commits, firstParentOnly, highlighting, extraHeads);
}

public Models.BisectState UpdateBisectInfo()
{
var test = Path.Combine(_repo.GitDir, "BISECT_START");
Expand Down Expand Up @@ -564,22 +599,38 @@ private void PostSelectedCommitsChanged()
}

if (_repo.UIStates.GraphHighlighting >= Models.CommitGraphHighlighting.SelectedCommitsOnly)
GenerateGraph(_commits);
RefreshGraph();
}

private void GenerateGraph(List<Models.Commit> commits)
private void RefreshGraph()
{
var firstParentOnly = _repo.UIStates.HistoryShowFlags.HasFlag(Models.HistoryShowFlags.FirstParentOnly);
var highlighting = _repo.UIStates.GraphHighlighting;
var extraHeads = new HashSet<string>();
if (_cancellationRefreshGraph is { IsCancellationRequested: false })
_cancellationRefreshGraph.Cancel();

_cancellationRefreshGraph = new CancellationTokenSource();
var token = _cancellationRefreshGraph.Token;
var commits = _commits;
var extraHeads = CollectGraphExtraHeads();

if (highlighting >= Models.CommitGraphHighlighting.SelectedCommitsOnly)
Task.Run(() =>
{
foreach (var c in _selectedCommits)
extraHeads.Add(c.SHA);
}
var graph = GenerateGraph(commits, extraHeads);
Dispatcher.UIThread.Post(() =>
{
if (!token.IsCancellationRequested)
ApplyGraph(commits, graph);
});
}, token);
}

private void ApplyGraph(List<Models.Commit> commits, Models.CommitGraph graph)
{
// There is exactly one dot for each commit (in the same order). Update `IsHighlightedInGraph` here
// so that the property-changed notifications of displayed commits are raised on the UI thread.
for (var i = 0; i < commits.Count; i++)
commits[i].IsHighlightedInGraph = graph.Dots[i].IsHighlighted;

Graph = Models.CommitGraph.Generate(commits, firstParentOnly, highlighting, extraHeads);
Graph = graph;
}

private Repository _repo = null;
Expand All @@ -589,6 +640,7 @@ private void GenerateGraph(List<Models.Commit> commits)
private bool _isLoading = true;
private List<Models.Commit> _commits = [];
private Models.CommitGraph _graph = null;
private CancellationTokenSource _cancellationRefreshGraph = null;
private List<Models.Commit> _selectedCommits = [];
private Models.Bisect _bisect = null;
private object _detailContext = Models.Null.Instance;
Expand Down
18 changes: 16 additions & 2 deletions src/ViewModels/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,15 @@ public void RefreshCommits()

Task.Run(async () =>
{
await Dispatcher.UIThread.InvokeAsync(() => _histories.IsLoading = true);
var graphExtraHeads = new HashSet<string>();
await Dispatcher.UIThread.InvokeAsync(() =>
{
if (_histories == null)
return;

_histories.IsLoading = true;
graphExtraHeads = _histories.CollectGraphExtraHeads();
});

var builder = new StringBuilder();
builder
Expand Down Expand Up @@ -1292,6 +1300,12 @@ public void RefreshCommits()
}
}

var histories = _histories;
if (token.IsCancellationRequested || histories == null)
return;

var graph = histories.GenerateGraph(commits, graphExtraHeads);

Dispatcher.UIThread.Invoke(() =>
{
if (token.IsCancellationRequested)
Expand All @@ -1300,7 +1314,7 @@ public void RefreshCommits()
if (_histories != null)
{
_histories.IsLoading = false;
_histories.Commits = commits;
_histories.SetCommits(commits, graph, graphExtraHeads);
BisectState = _histories.UpdateBisectInfo();

if (!string.IsNullOrEmpty(_navigateToCommitDelayed))
Expand Down