diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index 066d5b666..751cd05ce 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -229,6 +229,19 @@ protected ProcessStartInfo CreateGitStartInfo(bool redirect) return start; } + protected CancellationTokenRegistration TerminateOnCancellation(Process proc) + { + if (!CancellationToken.CanBeCanceled) + return default; + + // Disposing the returned registration waits for a running callback, so `proc` is always valid inside it. + return CancellationToken.Register(() => + { + if (!proc.HasExited) + Native.OS.TerminateProcess(proc); + }); + } + protected void RaiseException(string error) { Models.Notification.Send(Context, error, true); diff --git a/src/Commands/QueryCommits.cs b/src/Commands/QueryCommits.cs index 1a5073988..fc5e33ae2 100644 --- a/src/Commands/QueryCommits.cs +++ b/src/Commands/QueryCommits.cs @@ -59,6 +59,8 @@ public QueryCommits(string repo, string filter, Models.CommitSearchMethod method proc.StartInfo = CreateGitStartInfo(true); proc.Start(); + using var cancellation = TerminateOnCancellation(proc); + var findHead = false; while (await proc.StandardOutput.ReadLineAsync().ConfigureAwait(false) is { } line) { @@ -82,9 +84,13 @@ public QueryCommits(string repo, string filter, Models.CommitSearchMethod method await proc.WaitForExitAsync().ConfigureAwait(false); + if (CancellationToken.IsCancellationRequested) + return commits; + if (_markMerged && !findHead && commits.Count > 0) { var set = await new QueryCurrentBranchCommitHashes(WorkingDirectory, commits[^1].CommitterTime) + .WithCancellation(CancellationToken) .GetResultAsync() .ConfigureAwait(false); @@ -100,7 +106,8 @@ public QueryCommits(string repo, string filter, Models.CommitSearchMethod method } catch (Exception e) { - RaiseException($"Failed to query commits. Reason: {e.Message}"); + if (!CancellationToken.IsCancellationRequested) + RaiseException($"Failed to query commits. Reason: {e.Message}"); } return commits; diff --git a/src/Commands/QueryCurrentBranchCommitHashes.cs b/src/Commands/QueryCurrentBranchCommitHashes.cs index 393160602..43cec7391 100644 --- a/src/Commands/QueryCurrentBranchCommitHashes.cs +++ b/src/Commands/QueryCurrentBranchCommitHashes.cs @@ -23,6 +23,8 @@ public async Task> GetResultAsync() proc.StartInfo = CreateGitStartInfo(true); proc.Start(); + using var cancellation = TerminateOnCancellation(proc); + while (await proc.StandardOutput.ReadLineAsync().ConfigureAwait(false) is { Length: > 8 } line) outs.Add(line); diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 4d3b5541c..2c73060cc 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1276,6 +1276,7 @@ public void RefreshCommits() } var commits = await new Commands.QueryCommits(FullPath, builder.ToString()) + .WithCancellation(token) .GetResultAsync() .ConfigureAwait(false);