diff --git a/GitUI/CommandsDialogs/FormBrowse.cs b/GitUI/CommandsDialogs/FormBrowse.cs index c32fd846f12..90523e8fac7 100644 --- a/GitUI/CommandsDialogs/FormBrowse.cs +++ b/GitUI/CommandsDialogs/FormBrowse.cs @@ -163,16 +163,11 @@ public FormBrowse([NotNull] GitUICommands commands, string filter, ObjectId sele ThreadHelper.JoinableTaskFactory.RunAsync(async () => { await TaskScheduler.Default; - - try - { - PluginRegistry.Initialize(); - } - finally + await PluginRegistry.InitializeAsync(async () => { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); RegisterPlugins(); - } + }); }).FileAndForget(); _filterRevisionsHelper = new FilterRevisionsHelper(toolStripRevisionFilterTextBox, toolStripRevisionFilterDropDownButton, RevisionGrid, toolStripRevisionFilterLabel, ShowFirstParent, form: this); @@ -690,7 +685,6 @@ private void RegisterPlugins() } UpdatePluginMenu(Module.IsValidGitWorkingDir()); - PluginRegistry.ArePluginsRegistered = true; } private void UnregisterPlugins() @@ -699,8 +693,6 @@ private void UnregisterPlugins() { plugin.Unregister(UICommands); } - - PluginRegistry.ArePluginsRegistered = false; } /// diff --git a/GitUI/GitUICommands.cs b/GitUI/GitUICommands.cs index c97093fe020..ed18387bc9c 100644 --- a/GitUI/GitUICommands.cs +++ b/GitUI/GitUICommands.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using System.Windows.Forms; using GitCommands; using GitCommands.Settings; @@ -303,57 +304,6 @@ public bool DoActionOnRepo(Func action) return DoActionOnRepo(null, false, true, null, null, action); } - #region Plugins - - private IDisposable RegisterPlugins(IWin32Window owner) - { - if (PluginRegistry.ArePluginsRegistered) - { - return EmptyDiposable.Instance; - } - - return new RegisterDisposable(owner, this); - } - - private class RegisterDisposable : IDisposable - { - private readonly GitUICommands _commands; - - public RegisterDisposable(IWin32Window owner, GitUICommands commands) - { - _commands = commands; - - foreach (IGitPlugin plugin in PluginRegistry.Plugins) - { - plugin.Register(_commands); - } - - PluginRegistry.ArePluginsRegistered = true; - commands.RaisePostRegisterPlugin(owner); - } - - public void Dispose() - { - foreach (IGitPlugin plugin in PluginRegistry.Plugins) - { - plugin.Unregister(_commands); - } - - PluginRegistry.ArePluginsRegistered = false; - } - } - - private class EmptyDiposable : IDisposable - { - public static readonly EmptyDiposable Instance = new EmptyDiposable(); - - public void Dispose() - { - } - } - - #endregion - #region Checkout public bool StartCheckoutBranch([CanBeNull] IWin32Window owner, string branch = "", bool remote = false, IReadOnlyList containRevisions = null) @@ -491,16 +441,43 @@ public bool StartCommitDialog(IWin32Window owner, bool showOnlyWhenChanges = fal bool Action() { - using (var form = new FormCommit(this)) - using (RegisterPlugins(owner)) + // Commit dialog can be opened on its own without the main form + // If it is opened by itself, we need to ensure plugins are loaded because some of them + // may have hooks into the commit flow + bool pluginsRegistered = PluginRegistry.PluginsRegistered; + + try { - if (showOnlyWhenChanges) + // Load plugins synchronously + // if the commit dialog is opened from the main form, all plugins are already loaded and we return instantly, + // if the dialog is loaded on its own, plugins need to be loaded before we load the form + ThreadHelper.JoinableTaskFactory.Run(async () => { - form.ShowDialogWhenChanges(owner); + await PluginRegistry.InitializeAsync(() => + { + // this will only execute, if start without the main form + PluginRegistry.Plugins.ForEach(p => p.Register(this)); + return Task.CompletedTask; + }); + }); + + using (var form = new FormCommit(this)) + { + if (showOnlyWhenChanges) + { + form.ShowDialogWhenChanges(owner); + } + else + { + form.ShowDialog(owner); + } } - else + } + finally + { + if (!pluginsRegistered) { - form.ShowDialog(owner); + PluginRegistry.Plugins.ForEach(p => p.Unregister(this)); } } diff --git a/GitUI/Plugin/PluginRegistry.cs b/GitUI/Plugin/PluginRegistry.cs index 64718b44af7..f0069b4064d 100644 --- a/GitUI/Plugin/PluginRegistry.cs +++ b/GitUI/Plugin/PluginRegistry.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using GitCommands; using GitUIPluginInterfaces; using GitUIPluginInterfaces.RepositoryHosts; @@ -13,30 +15,44 @@ public static class PluginRegistry public static List GitHosters { get; } = new List(); - public static bool ArePluginsRegistered { get; set; } + public static bool PluginsRegistered { get; private set; } - public static void Initialize() + /// + /// Initialises all available plugins on the background thread. + /// + /// A function to execute once plugins are loaded. + public static Task InitializeAsync(Func postInitialiseAsync) { lock (Plugins) { if (Plugins.Count > 0) { - return; + return Task.CompletedTask; } - ManagedExtensibility.SetApplicationDataFolder(AppSettings.ApplicationDataPath.Value); - - foreach (var plugin in ManagedExtensibility.GetExports().Select(lazy => lazy.Value)) + try { - plugin.SettingsContainer = new GitPluginSettingsContainer(plugin.Name); - - if (plugin is IRepositoryHostPlugin repositoryHostPlugin) + foreach (var plugin in ManagedExtensibility.GetExports().Select(lazy => lazy.Value)) { - GitHosters.Add(repositoryHostPlugin); - } + plugin.SettingsContainer = new GitPluginSettingsContainer(plugin.Name); + + if (plugin is IRepositoryHostPlugin repositoryHostPlugin) + { + GitHosters.Add(repositoryHostPlugin); + } - Plugins.Add(plugin); + Plugins.Add(plugin); + } + } + catch + { + // no-op } + +#pragma warning disable VSTHRD105 // Avoid method overloads that assume TaskScheduler.Current + return postInitialiseAsync() + .ContinueWith(t => PluginsRegistered = true); +#pragma warning restore VSTHRD105 // Avoid method overloads that assume TaskScheduler.Current } } diff --git a/TranslationApp/Program.cs b/TranslationApp/Program.cs index 2994a79055e..306368dde86 100644 --- a/TranslationApp/Program.cs +++ b/TranslationApp/Program.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Threading.Tasks; using System.Windows.Forms; using GitCommands.Utils; using GitUI; @@ -49,7 +50,8 @@ private static void Main() } // required for translation - PluginRegistry.Initialize(); + ThreadHelper.JoinableTaskFactory.Run(() => PluginRegistry.InitializeAsync(() => Task.CompletedTask)); + string[] args = Environment.GetCommandLineArgs(); if (args.Length == 1) {