소스 검색

Merge pull request #4247 from crobibero/update-plugin

Update all on-disk plugins
Claus Vium 4 년 전
부모
커밋
3900976be5

+ 30 - 54
Emby.Server.Implementations/ApplicationHost.cs

@@ -4,7 +4,6 @@ using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Net;
@@ -30,7 +29,6 @@ using Emby.Server.Implementations.Cryptography;
 using Emby.Server.Implementations.Data;
 using Emby.Server.Implementations.Devices;
 using Emby.Server.Implementations.Dto;
-using Emby.Server.Implementations.HttpServer;
 using Emby.Server.Implementations.HttpServer.Security;
 using Emby.Server.Implementations.IO;
 using Emby.Server.Implementations.Library;
@@ -993,62 +991,36 @@ namespace Emby.Server.Implementations
 
         protected abstract void RestartInternal();
 
-        /// <summary>
-        /// Comparison function used in <see cref="GetPlugins" />.
-        /// </summary>
-        /// <param name="a">Item to compare.</param>
-        /// <param name="b">Item to compare with.</param>
-        /// <returns>Boolean result of the operation.</returns>
-        private static int VersionCompare(
-            (Version PluginVersion, string Name, string Path) a,
-            (Version PluginVersion, string Name, string Path) b)
-        {
-            int compare = string.Compare(a.Name, b.Name, true, CultureInfo.InvariantCulture);
-
-            if (compare == 0)
-            {
-                return a.PluginVersion.CompareTo(b.PluginVersion);
-            }
-
-            return compare;
-        }
-
-        /// <summary>
-        /// Returns a list of plugins to install.
-        /// </summary>
-        /// <param name="path">Path to check.</param>
-        /// <param name="cleanup">True if an attempt should be made to delete old plugs.</param>
-        /// <returns>Enumerable list of dlls to load.</returns>
-        private IEnumerable<string> GetPlugins(string path, bool cleanup = true)
+        /// <inheritdoc/>
+        public IEnumerable<LocalPlugin> GetLocalPlugins(string path, bool cleanup = true)
         {
-            var dllList = new List<string>();
-            var versions = new List<(Version PluginVersion, string Name, string Path)>();
+            var minimumVersion = new Version(0, 0, 0, 1);
+            var versions = new List<LocalPlugin>();
             var directories = Directory.EnumerateDirectories(path, "*.*", SearchOption.TopDirectoryOnly);
-            string metafile;
 
             foreach (var dir in directories)
             {
                 try
                 {
-                    metafile = Path.Combine(dir, "meta.json");
+                    var metafile = Path.Combine(dir, "meta.json");
                     if (File.Exists(metafile))
                     {
                         var manifest = _jsonSerializer.DeserializeFromFile<PluginManifest>(metafile);
 
                         if (!Version.TryParse(manifest.TargetAbi, out var targetAbi))
                         {
-                            targetAbi = new Version(0, 0, 0, 1);
+                            targetAbi = minimumVersion;
                         }
 
                         if (!Version.TryParse(manifest.Version, out var version))
                         {
-                            version = new Version(0, 0, 0, 1);
+                            version = minimumVersion;
                         }
 
                         if (ApplicationVersion >= targetAbi)
                         {
                             // Only load Plugins if the plugin is built for this version or below.
-                            versions.Add((version, manifest.Name, dir));
+                            versions.Add(new LocalPlugin(manifest.Guid, manifest.Name, version, dir));
                         }
                     }
                     else
@@ -1057,15 +1029,15 @@ namespace Emby.Server.Implementations
                         metafile = dir.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries)[^1];
 
                         int versionIndex = dir.LastIndexOf('_');
-                        if (versionIndex != -1 && Version.TryParse(dir.Substring(versionIndex + 1), out Version ver))
+                        if (versionIndex != -1 && Version.TryParse(dir.Substring(versionIndex + 1), out Version parsedVersion))
                         {
                             // Versioned folder.
-                            versions.Add((ver, metafile, dir));
+                            versions.Add(new LocalPlugin(Guid.Empty, metafile, parsedVersion, dir));
                         }
                         else
                         {
                             // Un-versioned folder - Add it under the path name and version 0.0.0.1.
-                            versions.Add((new Version(0, 0, 0, 1), metafile, dir));
+                            versions.Add(new LocalPlugin(Guid.Empty, metafile, minimumVersion, dir));
                         }
                     }
                 }
@@ -1076,14 +1048,14 @@ namespace Emby.Server.Implementations
             }
 
             string lastName = string.Empty;
-            versions.Sort(VersionCompare);
+            versions.Sort(LocalPlugin.Compare);
             // Traverse backwards through the list.
             // The first item will be the latest version.
             for (int x = versions.Count - 1; x >= 0; x--)
             {
                 if (!string.Equals(lastName, versions[x].Name, StringComparison.OrdinalIgnoreCase))
                 {
-                    dllList.AddRange(Directory.EnumerateFiles(versions[x].Path, "*.dll", SearchOption.AllDirectories));
+                    versions[x].DllFiles.AddRange(Directory.EnumerateFiles(versions[x].Path, "*.dll", SearchOption.AllDirectories));
                     lastName = versions[x].Name;
                     continue;
                 }
@@ -1091,6 +1063,7 @@ namespace Emby.Server.Implementations
                 if (!string.IsNullOrEmpty(lastName) && cleanup)
                 {
                     // Attempt a cleanup of old folders.
+                    versions.RemoveAt(x);
                     try
                     {
                         Logger.LogDebug("Deleting {Path}", versions[x].Path);
@@ -1103,7 +1076,7 @@ namespace Emby.Server.Implementations
                 }
             }
 
-            return dllList;
+            return versions;
         }
 
         /// <summary>
@@ -1114,21 +1087,24 @@ namespace Emby.Server.Implementations
         {
             if (Directory.Exists(ApplicationPaths.PluginsPath))
             {
-                foreach (var file in GetPlugins(ApplicationPaths.PluginsPath))
+                foreach (var plugin in GetLocalPlugins(ApplicationPaths.PluginsPath))
                 {
-                    Assembly plugAss;
-                    try
-                    {
-                        plugAss = Assembly.LoadFrom(file);
-                    }
-                    catch (FileLoadException ex)
+                    foreach (var file in plugin.DllFiles)
                     {
-                        Logger.LogError(ex, "Failed to load assembly {Path}", file);
-                        continue;
-                    }
+                        Assembly plugAss;
+                        try
+                        {
+                            plugAss = Assembly.LoadFrom(file);
+                        }
+                        catch (FileLoadException ex)
+                        {
+                            Logger.LogError(ex, "Failed to load assembly {Path}", file);
+                            continue;
+                        }
 
-                    Logger.LogInformation("Loaded assembly {Assembly} from {Path}", plugAss.FullName, file);
-                    yield return plugAss;
+                        Logger.LogInformation("Loaded assembly {Assembly} from {Path}", plugAss.FullName, file);
+                        yield return plugAss;
+                    }
                 }
             }
 

+ 5 - 5
Emby.Server.Implementations/Updates/InstallationManager.cs

@@ -16,7 +16,7 @@ using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Common.Updates;
-using MediaBrowser.Common.System;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Events;
 using MediaBrowser.Controller.Events.Updates;
@@ -25,7 +25,6 @@ using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Updates;
 using Microsoft.Extensions.Logging;
-using MediaBrowser.Model.System;
 
 namespace Emby.Server.Implementations.Updates
 {
@@ -49,7 +48,7 @@ namespace Emby.Server.Implementations.Updates
         /// Gets the application host.
         /// </summary>
         /// <value>The application host.</value>
-        private readonly IApplicationHost _applicationHost;
+        private readonly IServerApplicationHost _applicationHost;
 
         private readonly IZipClient _zipClient;
 
@@ -67,7 +66,7 @@ namespace Emby.Server.Implementations.Updates
 
         public InstallationManager(
             ILogger<InstallationManager> logger,
-            IApplicationHost appHost,
+            IServerApplicationHost appHost,
             IApplicationPaths appPaths,
             IEventManager eventManager,
             IHttpClientFactory httpClientFactory,
@@ -217,7 +216,8 @@ namespace Emby.Server.Implementations.Updates
 
         private IEnumerable<InstallationInfo> GetAvailablePluginUpdates(IReadOnlyList<PackageInfo> pluginCatalog)
         {
-            foreach (var plugin in _applicationHost.Plugins)
+            var plugins = _applicationHost.GetLocalPlugins(_appPaths.PluginsPath);
+            foreach (var plugin in plugins)
             {
                 var compatibleVersions = GetCompatibleVersions(pluginCatalog, plugin.Name, plugin.Id, minVersion: plugin.Version);
                 var version = compatibleVersions.FirstOrDefault(y => y.Version > plugin.Version);

+ 113 - 0
MediaBrowser.Common/Plugins/LocalPlugin.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace MediaBrowser.Common.Plugins
+{
+    /// <summary>
+    /// Local plugin struct.
+    /// </summary>
+    public class LocalPlugin : IEquatable<LocalPlugin>
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="LocalPlugin"/> class.
+        /// </summary>
+        /// <param name="id">The plugin id.</param>
+        /// <param name="name">The plugin name.</param>
+        /// <param name="version">The plugin version.</param>
+        /// <param name="path">The plugin path.</param>
+        public LocalPlugin(Guid id, string name, Version version, string path)
+        {
+            Id = id;
+            Name = name;
+            Version = version;
+            Path = path;
+            DllFiles = new List<string>();
+        }
+
+        /// <summary>
+        /// Gets the plugin id.
+        /// </summary>
+        public Guid Id { get; }
+
+        /// <summary>
+        /// Gets the plugin name.
+        /// </summary>
+        public string Name { get; }
+
+        /// <summary>
+        /// Gets the plugin version.
+        /// </summary>
+        public Version Version { get; }
+
+        /// <summary>
+        /// Gets the plugin path.
+        /// </summary>
+        public string Path { get; }
+
+        /// <summary>
+        /// Gets the list of dll files for this plugin.
+        /// </summary>
+        public List<string> DllFiles { get; }
+
+        /// <summary>
+        /// == operator.
+        /// </summary>
+        /// <param name="left">Left item.</param>
+        /// <param name="right">Right item.</param>
+        /// <returns>Comparison result.</returns>
+        public static bool operator ==(LocalPlugin left, LocalPlugin right)
+        {
+            return left.Equals(right);
+        }
+
+        /// <summary>
+        /// != operator.
+        /// </summary>
+        /// <param name="left">Left item.</param>
+        /// <param name="right">Right item.</param>
+        /// <returns>Comparison result.</returns>
+        public static bool operator !=(LocalPlugin left, LocalPlugin right)
+        {
+            return !left.Equals(right);
+        }
+
+        /// <summary>
+        /// Compare two <see cref="LocalPlugin"/>.
+        /// </summary>
+        /// <param name="a">The first item.</param>
+        /// <param name="b">The second item.</param>
+        /// <returns>Comparison result.</returns>
+        public static int Compare(LocalPlugin a, LocalPlugin b)
+        {
+            var compare = string.Compare(a.Name, b.Name, true, CultureInfo.InvariantCulture);
+
+            // Id is not equal but name is.
+            if (a.Id != b.Id && compare == 0)
+            {
+                compare = a.Id.CompareTo(b.Id);
+            }
+
+            return compare == 0 ? a.Version.CompareTo(b.Version) : compare;
+        }
+
+        /// <inheritdoc />
+        public override bool Equals(object obj)
+        {
+            return obj is LocalPlugin other && this.Equals(other);
+        }
+
+        /// <inheritdoc />
+        public override int GetHashCode()
+        {
+            return Name.GetHashCode(StringComparison.OrdinalIgnoreCase);
+        }
+
+        /// <inheritdoc />
+        public bool Equals(LocalPlugin other)
+        {
+            return Name.Equals(other.Name, StringComparison.OrdinalIgnoreCase)
+                   && Id.Equals(other.Id);
+        }
+    }
+}

+ 9 - 1
MediaBrowser.Controller/IServerApplicationHost.cs

@@ -6,8 +6,8 @@ using System.Net;
 using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Common;
+using MediaBrowser.Common.Plugins;
 using MediaBrowser.Model.System;
-using Microsoft.AspNetCore.Http;
 
 namespace MediaBrowser.Controller
 {
@@ -120,5 +120,13 @@ namespace MediaBrowser.Controller
         string ExpandVirtualPath(string path);
 
         string ReverseVirtualPath(string path);
+
+        /// <summary>
+        /// Gets the list of local plugins.
+        /// </summary>
+        /// <param name="path">Plugin base directory.</param>
+        /// <param name="cleanup">Cleanup old plugins.</param>
+        /// <returns>Enumerable of local plugins.</returns>
+        IEnumerable<LocalPlugin> GetLocalPlugins(string path, bool cleanup = true);
     }
 }