Skip to content

Commit

Permalink
Cancellation support for CustomDiffMergeTools (#9522)
Browse files Browse the repository at this point in the history
When forms starting list of custom diff/merge tools are closed,
cancel the handling including the Git process.

CustomMergeTools: Decrease delay before listing
  • Loading branch information
gerhardol committed Aug 31, 2021
1 parent fdadf89 commit e71339c
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 29 deletions.
11 changes: 7 additions & 4 deletions GitCommands/CustomDiffMergeToolCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task ClearAsync()
/// </summary>
/// <param name="module">The Git module</param>
/// <param name="delay">The delay before starting the operation</param>
public async Task<IEnumerable<string>> GetToolsAsync(GitModule module, int delay)
public async Task<IEnumerable<string>> GetToolsAsync(GitModule module, int delay, CancellationToken cancellationToken)
{
if (_tools is not null)
{
Expand All @@ -56,17 +56,20 @@ public async Task<IEnumerable<string>> GetToolsAsync(GitModule module, int delay

// The command will compete with other resources, avoid delaying startup
// Do not bother with cancel tokens
await Task.Delay(delay);
await Task.Delay(delay, cancellationToken);

await _mutex.WaitAsync(cancellationToken).ConfigureAwait(false);

await _mutex.WaitAsync().ConfigureAwait(false);
try
{
if (_tools is null)
{
await TaskScheduler.Default;
cancellationToken.ThrowIfCancellationRequested();

var toolKey = _isDiff ? SettingKeyString.DiffToolKey : SettingKeyString.MergeToolKey;
var defaultTool = module.GetEffectiveSetting(toolKey);
string output = module.GetCustomDiffMergeTools(_isDiff);
string output = module.GetCustomDiffMergeTools(_isDiff, cancellationToken);
_tools = ParseCustomDiffMergeTool(output, defaultTool);
}
}
Expand Down
5 changes: 3 additions & 2 deletions GitCommands/Git/GitModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3568,11 +3568,12 @@ public string GetFileText(ObjectId id, Encoding encoding)
/// </summary>
/// <param name="isDiff">diff or merge.</param>
/// <returns>the Git output.</returns>
public string GetCustomDiffMergeTools(bool isDiff)
public string GetCustomDiffMergeTools(bool isDiff, CancellationToken cancellationToken)
{
// Note that --gui has no effect here
GitArgumentBuilder args = new(isDiff ? "difftool" : "mergetool") { "--tool-help" };
return _gitExecutable.GetOutput(args);
ExecutionResult result = _gitExecutable.Execute(args, cancellationToken: cancellationToken);
return result.StandardOutput;
}

public string OpenWithDifftoolDirDiff(string? firstRevision, string? secondRevision, string? customTool = null)
Expand Down
4 changes: 3 additions & 1 deletion GitUI/CommandsDialogs/FormCommit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public sealed partial class FormCommit : GitModuleForm
private readonly ToolStripMenuItem _addSelectionToCommitMessageToolStripMenuItem;
private readonly AsyncLoader _unstagedLoader = new();
private readonly bool _useFormCommitMessage = AppSettings.UseFormCommitMessage;
private readonly CancellationTokenSequence _customDiffToolsSequence = new();
private readonly CancellationTokenSequence _interactiveAddSequence = new();
private readonly CancellationTokenSequence _viewChangesSequence = new();
private readonly SplitterManager _splitterManager = new(new AppSettingsPath("CommitDialog"));
Expand Down Expand Up @@ -411,6 +412,7 @@ protected override void Dispose(bool disposing)
if (disposing)
{
_unstagedLoader.Dispose();
_customDiffToolsSequence.Dispose();
_interactiveAddSequence.Dispose();
_viewChangesSequence.Dispose();
components?.Dispose();
Expand Down Expand Up @@ -629,7 +631,7 @@ public void LoadCustomDifftools()
new(stagedOpenDifftoolToolStripMenuItem9, stagedOpenDifftoolToolStripMenuItem9_Click),
};

new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: true);
new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: true, cancellationToken: _customDiffToolsSequence.Next());
}

private void FileViewer_TopScrollReached(object sender, EventArgs e)
Expand Down
4 changes: 3 additions & 1 deletion GitUI/CommandsDialogs/FormFileHistory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public sealed partial class FormFileHistory : GitModuleForm
private readonly FormBrowseMenus _formBrowseMenus;
private readonly IFullPathResolver _fullPathResolver;
private readonly FormFileHistoryController _controller = new();
private readonly CancellationTokenSequence _customDiffToolsSequence = new();
private readonly CancellationTokenSequence _viewChangesSequence = new();

private BuildReportTabPageExtension? _buildReportTabPageExtension;
Expand Down Expand Up @@ -177,6 +178,7 @@ protected override void Dispose(bool disposing)
if (disposing)
{
_asyncLoader.Dispose();
_customDiffToolsSequence.Dispose();
_viewChangesSequence.Dispose();

// if the form was instantiated by the translation app, all of the following would be null
Expand Down Expand Up @@ -215,7 +217,7 @@ public void LoadCustomDifftools()
};

const int ToolDelay = 10000;
new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: true, ToolDelay);
new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: true, ToolDelay, cancellationToken: _customDiffToolsSequence.Next());
}

private void LoadFileHistory()
Expand Down
13 changes: 0 additions & 13 deletions GitUI/CommandsDialogs/FormResolveConflicts.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions GitUI/CommandsDialogs/FormResolveConflicts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ private enum ConflictResolutionPreference
private int _filesDeletedLocallyAndModifiedRemotelySolved;
private int _filesModifiedLocallyAndDeletedRemotelySolved;
private int _conflictItemsCount;
private readonly CancellationTokenSequence _customDiffToolsSequence = new();

[Obsolete("For VS designer and translation test only. Do not remove.")]
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
Expand Down Expand Up @@ -149,6 +150,17 @@ protected override void OnRuntimeLoad(EventArgs e)
Hotkeys = HotkeySettingsManager.LoadHotkeys(HotkeySettingsName);
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
_customDiffToolsSequence.Dispose();
components?.Dispose();
}

base.Dispose(disposing);
}

private void Mergetool_Click(object sender, EventArgs e)
{
using (WaitCursorScope.Enter())
Expand Down Expand Up @@ -302,8 +314,8 @@ private void LoadCustomMergetools()
new(customMergetool, customMergetool_Click),
};

const int ToolDelay = 5000;
new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: false, ToolDelay);
const int ToolDelay = 500;
new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: false, ToolDelay, cancellationToken: _customDiffToolsSequence.Next());
}

private readonly Dictionary<string, string> _mergeScripts = new()
Expand Down
4 changes: 3 additions & 1 deletion GitUI/CommandsDialogs/RevisionDiffControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public partial class RevisionDiffControl : GitModuleControl
private readonly IFullPathResolver _fullPathResolver;
private readonly IFindFilePredicateProvider _findFilePredicateProvider;
private readonly IGitRevisionTester _gitRevisionTester;
private readonly CancellationTokenSequence _customDiffToolsSequence = new();
private readonly CancellationTokenSequence _viewChangesSequence = new();
private readonly RememberFileContextMenuController _rememberFileContextMenuController
= RememberFileContextMenuController.Default;
Expand Down Expand Up @@ -187,7 +188,7 @@ public void LoadCustomDifftools()
new(diffTwoSelectedDifftoolToolStripMenuItem, diffTwoSelectedDiffToolToolStripMenuItem_Click)
};

new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: true);
new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: true, cancellationToken: _customDiffToolsSequence.Next());
}

public void CancelLoadCustomDifftools()
Expand Down Expand Up @@ -257,6 +258,7 @@ protected override void Dispose(bool disposing)
{
if (disposing)
{
_customDiffToolsSequence.Dispose();
_viewChangesSequence.Dispose();
components?.Dispose();
}
Expand Down
10 changes: 6 additions & 4 deletions GitUI/CustomDiffMergeToolProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using GitCommands;
Expand Down Expand Up @@ -40,7 +41,7 @@ public async Task ClearAsync(bool isDiff)
/// <param name="components">The calling Form components, to dispose correctly.</param>
/// <param name="isDiff">True if diff, false if merge.</param>
/// <param name="delay">The delay before starting the operation.</param>
public void LoadCustomDiffMergeTools(GitModule module, IList<CustomDiffMergeTool> menus, IContainer components, bool isDiff, int delay = FormBrowseToolDelay)
public void LoadCustomDiffMergeTools(GitModule module, IList<CustomDiffMergeTool> menus, IContainer components, bool isDiff, int delay = FormBrowseToolDelay, CancellationToken cancellationToken = default)
{
InitMenus(menus);

Expand All @@ -54,16 +55,17 @@ public void LoadCustomDiffMergeTools(GitModule module, IList<CustomDiffMergeTool
// get the tools, possibly with a delay as requesting requires considerable time
// cache is shared
List<string> tools = (await (isDiff ? CustomDiffMergeToolCache.DiffToolCache : CustomDiffMergeToolCache.MergeToolCache)
.GetToolsAsync(module, delay))
.GetToolsAsync(module, delay, cancellationToken))
.ToList();
if (tools.Count() <= 1)
if (tools.Count <= 1)
{
// No need to show the menu
return;
}
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
foreach (var menu in menus)
{
menu.MenuItem.DropDown = new ContextMenuStrip(components);
Expand Down
4 changes: 3 additions & 1 deletion GitUI/UserControls/RevisionGrid/RevisionGridControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public sealed partial class RevisionGridControl : GitModuleControl, IScriptHostC
private DataGridViewColumn? _lastVisibleResizableColumn;
private readonly ArtificialCommitChangeCount _workTreeChangeCount = new();
private readonly ArtificialCommitChangeCount _indexChangeCount = new();
private readonly CancellationTokenSequence _customDiffToolsSequence = new();

private RefFilterOptions _DONT_USE_ME_DIRECTLY_refFilterOptions = RefFilterOptions.All | RefFilterOptions.Boundary;

Expand Down Expand Up @@ -299,6 +300,7 @@ protected override void Dispose(bool disposing)
//// _revisionGraphColumnProvider not disposable
//// _selectionTimer handled by this.components
_buildServerWatcher?.Dispose();
_customDiffToolsSequence.Dispose();

if (_indexWatcher.IsValueCreated)
{
Expand Down Expand Up @@ -661,7 +663,7 @@ public void LoadCustomDifftools()
new(openCommitsWithDiffToolMenuItem, diffSelectedCommitsMenuItem_Click)
};

new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: true);
new CustomDiffMergeToolProvider().LoadCustomDiffMergeTools(Module, menus, components, isDiff: true, cancellationToken: _customDiffToolsSequence.Next());
}

public void CancelLoadCustomDifftools()
Expand Down

0 comments on commit e71339c

Please sign in to comment.