Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono-addins.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLluis Sanchez <llsan@microsoft.com>2019-09-13 16:52:19 +0300
committerLluis Sanchez <llsan@microsoft.com>2019-09-13 16:59:21 +0300
commitd749da6e35a86455de33539103cfeb1a6191ea07 (patch)
tree112680ddc0b777b5eb5f7e3e470165740d8fd026
parent5a5607d9969c25a472bcca422a8cc669d332058c (diff)
Fix add-in status consistency issue
When initializing an add-in dabatase ensure that all add-ins have all their dependencies enabled. The database takes care to keep the enabled status consistent at run-time (so if an add-in is disabled, all dependent add-ins will also be disabled). However, that status may already be inconsistent when loading the database, and that may cause add-in loading issues. This may happen for example if add-in A is disabled, and then an add-in B that depends on A is installed externally, outside of the control of the db. With the changes of this commit, when the db is initialized it will detect that B depends on a disabled add-in and it will be disabled too. Fixes VSTS #952473
-rw-r--r--Mono.Addins/Mono.Addins.Database/AddinDatabase.cs52
-rw-r--r--Mono.Addins/Mono.Addins.Database/DatabaseConfiguration.cs27
-rw-r--r--Mono.Addins/Mono.Addins/AddinRegistry.cs2
3 files changed, 66 insertions, 15 deletions
diff --git a/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs b/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs
index 4dabf61..7d5a1d2 100644
--- a/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs
+++ b/Mono.Addins/Mono.Addins.Database/AddinDatabase.cs
@@ -497,7 +497,7 @@ namespace Mono.Addins.Database
addinEngine.ActivateAddin (id);
}
- public void DisableAddin (string domain, string id, bool exactVersionMatch = false)
+ public void DisableAddin (string domain, string id, bool exactVersionMatch = false, bool onlyForCurrentSession = false)
{
Addin ai = GetInstalledAddin (domain, id, true);
if (ai == null)
@@ -505,8 +505,8 @@ namespace Mono.Addins.Database
if (!IsAddinEnabled (domain, id, exactVersionMatch))
return;
-
- Configuration.SetEnabled (id, false, ai.AddinInfo.EnabledByDefault, exactVersionMatch);
+
+ Configuration.SetEnabled (id, false, ai.AddinInfo.EnabledByDefault, exactVersionMatch, onlyForCurrentSession);
SaveConfiguration ();
// Disable all add-ins which depend on it
@@ -531,7 +531,7 @@ namespace Mono.Addins.Database
Addin adepinfo = GetInstalledAddin (domain, adepid, false, true);
if (adepinfo == null) {
- DisableAddin (domain, ainfo.Id);
+ DisableAddin (domain, ainfo.Id, onlyForCurrentSession: onlyForCurrentSession);
break;
}
}
@@ -539,7 +539,7 @@ namespace Mono.Addins.Database
}
catch {
// If something goes wrong, enable the add-in again
- Configuration.SetEnabled (id, true, ai.AddinInfo.EnabledByDefault, false);
+ Configuration.SetEnabled (id, true, ai.AddinInfo.EnabledByDefault, false, onlyForCurrentSession);
SaveConfiguration ();
throw;
}
@@ -547,7 +547,46 @@ namespace Mono.Addins.Database
if (addinEngine != null && addinEngine.IsInitialized)
addinEngine.UnloadAddin (id);
}
-
+
+ public void UpdateEnabledStatus (string domain)
+ {
+ // Ensure that all enabled addins that have dependencies also have their dependencies enabled.
+ HashSet<Addin> updatedAddins = new HashSet<Addin> ();
+ var allAddins = GetInstalledAddins (domain, AddinSearchFlagsInternal.IncludeAddins | AddinSearchFlagsInternal.LatestVersionsOnly).ToList ();
+ foreach (Addin addin in allAddins)
+ UpdateEnabledStatus (domain, addin, allAddins, updatedAddins);
+ }
+
+ void UpdateEnabledStatus (string domain, Addin addin, List<Addin> allAddins, HashSet<Addin> updatedAddins)
+ {
+ if (!updatedAddins.Add (addin))
+ return;
+
+ if (!addin.Enabled)
+ return;
+
+ // Make sure all dependencies of this add-in have an up to date enabled status
+
+ foreach (Dependency dep in addin.AddinInfo.Dependencies) {
+ var adep = dep as AddinDependency;
+ if (adep == null)
+ continue;
+
+ string adepid = Addin.GetFullId (addin.AddinInfo.Namespace, adep.AddinId, null);
+ var dependency = allAddins.FirstOrDefault (a => Addin.GetFullId (a.Namespace, a.LocalId, null) == adepid);
+ if (dependency != null) {
+ UpdateEnabledStatus (domain, dependency, allAddins, updatedAddins);
+ if (!dependency.Enabled) {
+ // One of the dependencies is disabled, so this add-in also needs to be disabled.
+ // However, we disabled only for the current configuration, we don't want to change
+ // what the user configured.
+ DisableAddin (domain, addin.Id, onlyForCurrentSession: true);
+ return;
+ }
+ }
+ }
+ }
+
public void RegisterForUninstall (string domain, string id, IEnumerable<string> files)
{
DisableAddin (domain, id, true);
@@ -1955,6 +1994,7 @@ namespace Mono.Addins.Database
}
// Keep in sync with AddinSearchFlags
+ [Flags]
enum AddinSearchFlagsInternal
{
IncludeAddins = 1,
diff --git a/Mono.Addins/Mono.Addins.Database/DatabaseConfiguration.cs b/Mono.Addins/Mono.Addins.Database/DatabaseConfiguration.cs
index 37779ec..14d8840 100644
--- a/Mono.Addins/Mono.Addins.Database/DatabaseConfiguration.cs
+++ b/Mono.Addins/Mono.Addins.Database/DatabaseConfiguration.cs
@@ -39,7 +39,7 @@ namespace Mono.Addins.Database
internal class DatabaseConfiguration
{
Dictionary<string,AddinStatus> addinStatus = new Dictionary<string,AddinStatus> ();
-
+
internal class AddinStatus
{
public AddinStatus (string addinId)
@@ -48,11 +48,15 @@ namespace Mono.Addins.Database
}
public string AddinId;
- public bool Enabled;
+ public bool ConfigEnabled;
+ public bool? SessionEnabled;
public bool Uninstalled;
public List<string> Files;
+ public bool Enabled {
+ get { return SessionEnabled ?? ConfigEnabled; }
+ }
}
-
+
public bool IsEnabled (string addinId, bool defaultValue)
{
var addinName = Addin.GetIdName (addinId);
@@ -71,7 +75,7 @@ namespace Mono.Addins.Database
return defaultValue;
}
- public void SetEnabled (string addinId, bool enabled, bool defaultValue, bool exactVersionMatch)
+ public void SetEnabled (string addinId, bool enabled, bool defaultValue, bool exactVersionMatch, bool onlyForTheSession = false)
{
if (IsRegisteredForUninstall (addinId))
return;
@@ -83,11 +87,16 @@ namespace Mono.Addins.Database
if (s == null)
s = addinStatus [addinName] = new AddinStatus (addinName);
- s.Enabled = enabled;
+ if (onlyForTheSession)
+ s.SessionEnabled = enabled;
+ else {
+ s.ConfigEnabled = enabled;
+ s.SessionEnabled = null;
+ }
// If enabling a specific version of an add-in, make sure the add-in is enabled as a whole
if (enabled && exactVersionMatch)
- SetEnabled (addinId, true, defaultValue, false);
+ SetEnabled (addinId, true, defaultValue, false, onlyForTheSession);
}
public void RegisterForUninstall (string addinId, IEnumerable<string> files)
@@ -96,7 +105,7 @@ namespace Mono.Addins.Database
if (!addinStatus.TryGetValue (addinId, out s))
s = addinStatus [addinId] = new AddinStatus (addinId);
- s.Enabled = false;
+ s.ConfigEnabled = false;
s.Uninstalled = true;
s.Files = new List<string> (files);
}
@@ -171,7 +180,7 @@ namespace Mono.Addins.Database
foreach (XmlElement elem in statusElem.SelectNodes ("Addin")) {
AddinStatus status = new AddinStatus (elem.GetAttribute ("id"));
string senabled = elem.GetAttribute ("enabled");
- status.Enabled = senabled.Length == 0 || senabled == "True";
+ status.ConfigEnabled = senabled.Length == 0 || senabled == "True";
status.Uninstalled = elem.GetAttribute ("uninstalled") == "True";
config.addinStatus [status.AddinId] = status;
foreach (XmlElement fileElem in elem.SelectNodes ("File")) {
@@ -196,7 +205,7 @@ namespace Mono.Addins.Database
foreach (AddinStatus e in addinStatus.Values) {
tw.WriteStartElement ("Addin");
tw.WriteAttributeString ("id", e.AddinId);
- tw.WriteAttributeString ("enabled", e.Enabled.ToString ());
+ tw.WriteAttributeString ("enabled", e.ConfigEnabled.ToString ());
if (e.Uninstalled)
tw.WriteAttributeString ("uninstalled", "True");
if (e.Files != null && e.Files.Count > 0) {
diff --git a/Mono.Addins/Mono.Addins/AddinRegistry.cs b/Mono.Addins/Mono.Addins/AddinRegistry.cs
index f51b4db..1efeb1c 100644
--- a/Mono.Addins/Mono.Addins/AddinRegistry.cs
+++ b/Mono.Addins/Mono.Addins/AddinRegistry.cs
@@ -220,6 +220,8 @@ namespace Mono.Addins
currentDomain = database.GetFolderDomain (null, this.startupDirectory);
} else
currentDomain = AddinDatabase.GlobalDomain;
+
+ database.UpdateEnabledStatus (currentDomain);
}
/// <summary>