mirror of https://github.com/jellyfin/jellyfin.git
Changes as requested
This commit is contained in:
parent
d98f42a6aa
commit
62702fa3eb
|
@ -462,7 +462,7 @@ namespace Emby.Server.Implementations
|
||||||
{
|
{
|
||||||
// Convert to list so this isn't executed for each iteration
|
// Convert to list so this isn't executed for each iteration
|
||||||
var parts = GetExportTypes<T>()
|
var parts = GetExportTypes<T>()
|
||||||
.Select(defaultFunc)
|
.Select(i => defaultFunc(i))
|
||||||
.Where(i => i != null)
|
.Where(i => i != null)
|
||||||
.Cast<T>()
|
.Cast<T>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Json;
|
using MediaBrowser.Common.Json;
|
||||||
|
@ -86,7 +87,8 @@ namespace Emby.Server.Implementations.Plugins
|
||||||
var plugin = _plugins[i];
|
var plugin = _plugins[i];
|
||||||
if (plugin.Manifest.Status == PluginStatus.Deleted && DeletePlugin(plugin))
|
if (plugin.Manifest.Status == PluginStatus.Deleted && DeletePlugin(plugin))
|
||||||
{
|
{
|
||||||
UpdateSuccessors(plugin);
|
// See if there is another version, and if so make that active.
|
||||||
|
ProcessAlternative(plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,12 +210,19 @@ namespace Emby.Server.Implementations.Plugins
|
||||||
|
|
||||||
if (DeletePlugin(plugin))
|
if (DeletePlugin(plugin))
|
||||||
{
|
{
|
||||||
|
ProcessAlternative(plugin);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogWarning("Unable to delete {Path}, so marking as deleteOnStartup.", plugin.Path);
|
_logger.LogWarning("Unable to delete {Path}, so marking as deleteOnStartup.", plugin.Path);
|
||||||
// Unable to delete, so disable.
|
// Unable to delete, so disable.
|
||||||
return ChangePluginState(plugin, PluginStatus.Deleted);
|
if (ChangePluginState(plugin, PluginStatus.Deleted))
|
||||||
|
{
|
||||||
|
ProcessAlternative(plugin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -232,9 +241,9 @@ namespace Emby.Server.Implementations.Plugins
|
||||||
var plugins = _plugins.Where(p => p.Id.Equals(id)).ToList();
|
var plugins = _plugins.Where(p => p.Id.Equals(id)).ToList();
|
||||||
|
|
||||||
plugin = plugins.FirstOrDefault(p => p.Instance != null);
|
plugin = plugins.FirstOrDefault(p => p.Instance != null);
|
||||||
if (plugin == null && plugins.Length > 0)
|
if (plugin == null)
|
||||||
{
|
{
|
||||||
plugin = plugins.OrderByDescending(p => p.Version)[0];
|
plugin = plugins.OrderByDescending(p => p.Version).FirstOrDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -259,7 +268,8 @@ namespace Emby.Server.Implementations.Plugins
|
||||||
|
|
||||||
if (ChangePluginState(plugin, PluginStatus.Active))
|
if (ChangePluginState(plugin, PluginStatus.Active))
|
||||||
{
|
{
|
||||||
UpdateSuccessors(plugin);
|
// See if there is another version, and if so, supercede it.
|
||||||
|
ProcessAlternative(plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +287,8 @@ namespace Emby.Server.Implementations.Plugins
|
||||||
// Update the manifest on disk
|
// Update the manifest on disk
|
||||||
if (ChangePluginState(plugin, PluginStatus.Disabled))
|
if (ChangePluginState(plugin, PluginStatus.Disabled))
|
||||||
{
|
{
|
||||||
UpdateSuccessors(plugin);
|
// If there is another version, activate it.
|
||||||
|
ProcessAlternative(plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,27 +650,33 @@ namespace Emby.Server.Implementations.Plugins
|
||||||
/// Changes the status of the other versions of the plugin to "Superceded".
|
/// Changes the status of the other versions of the plugin to "Superceded".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="plugin">The <see cref="LocalPlugin"/> that's master.</param>
|
/// <param name="plugin">The <see cref="LocalPlugin"/> that's master.</param>
|
||||||
private void UpdateSuccessors(LocalPlugin plugin)
|
private void ProcessAlternative(LocalPlugin plugin)
|
||||||
{
|
{
|
||||||
// This value is memory only - so that the web will show restart required.
|
|
||||||
plugin.Manifest.Status = PluginStatus.Restart;
|
|
||||||
|
|
||||||
// Detect whether there is another version of this plugin that needs disabling.
|
// Detect whether there is another version of this plugin that needs disabling.
|
||||||
var predecessor = _plugins.OrderByDescending(p => p.Version)
|
var previousVersion = _plugins.OrderByDescending(p => p.Version)
|
||||||
.FirstOrDefault(
|
.FirstOrDefault(
|
||||||
p => p.Id.Equals(plugin.Id)
|
p => p.Id.Equals(plugin.Id)
|
||||||
&& p.IsEnabledAndSupported
|
&& p.IsEnabledAndSupported
|
||||||
&& p.Version != plugin.Version);
|
&& p.Version != plugin.Version);
|
||||||
|
|
||||||
if (predecessor == null)
|
if (previousVersion == null)
|
||||||
{
|
{
|
||||||
|
// This value is memory only - so that the web will show restart required.
|
||||||
|
plugin.Manifest.Status = PluginStatus.Restart;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (predecessor.Manifest.Status == PluginStatus.Active && !ChangePluginState(predecessor, PluginStatus.Superceded))
|
if (plugin.Manifest.Status == PluginStatus.Active && !ChangePluginState(previousVersion, PluginStatus.Superceded))
|
||||||
{
|
{
|
||||||
_logger.LogError("Unable to disable version {Version} of {Name}", predecessor.Version, predecessor.Name);
|
_logger.LogError("Unable to enable version {Version} of {Name}", previousVersion.Version, previousVersion.Name);
|
||||||
}
|
}
|
||||||
|
else if (plugin.Manifest.Status == PluginStatus.Superceded && !ChangePluginState(previousVersion, PluginStatus.Active))
|
||||||
|
{
|
||||||
|
_logger.LogError("Unable to supercede version {Version} of {Name}", previousVersion.Version, previousVersion.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This value is memory only - so that the web will show restart required.
|
||||||
|
plugin.Manifest.Status = PluginStatus.Restart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <param name="pluginId">Plugin id.</param>
|
/// <param name="pluginId">Plugin id.</param>
|
||||||
/// <response code="204">Plugin uninstalled.</response>
|
/// <response code="204">Plugin uninstalled.</response>
|
||||||
/// <response code="404">Plugin not found.</response>
|
/// <response code="404">Plugin not found.</response>
|
||||||
/// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns>
|
/// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the plugin could not be found.</returns>
|
||||||
[HttpDelete("{pluginId}")]
|
[HttpDelete("{pluginId}")]
|
||||||
[Authorize(Policy = Policies.RequiresElevation)]
|
[Authorize(Policy = Policies.RequiresElevation)]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
|
@ -210,7 +210,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId));
|
var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId));
|
||||||
|
|
||||||
// Select the un-instanced one first.
|
// Select the un-instanced one first.
|
||||||
var plugin = plugins.FirstOrDefault(p => p.Instance != null);
|
var plugin = plugins.FirstOrDefault(p => p.Instance == null);
|
||||||
if (plugin == null)
|
if (plugin == null)
|
||||||
{
|
{
|
||||||
// Then by the status.
|
// Then by the status.
|
||||||
|
@ -256,11 +256,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <param name="pluginId">Plugin id.</param>
|
/// <param name="pluginId">Plugin id.</param>
|
||||||
/// <response code="204">Plugin configuration updated.</response>
|
/// <response code="204">Plugin configuration updated.</response>
|
||||||
/// <response code="404">Plugin not found or plugin does not have configuration.</response>
|
/// <response code="404">Plugin not found or plugin does not have configuration.</response>
|
||||||
/// <returns>
|
/// <returns>An <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the plugin could not be found.</returns>
|
||||||
/// A <see cref="Task" /> that represents the asynchronous operation to update plugin configuration.
|
|
||||||
/// The task result contains an <see cref="NoContentResult"/> indicating success, or <see cref="NotFoundResult"/>
|
|
||||||
/// when plugin not found or plugin doesn't have configuration.
|
|
||||||
/// </returns>
|
|
||||||
[HttpPost("{pluginId}/Configuration")]
|
[HttpPost("{pluginId}/Configuration")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
@ -321,11 +317,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
/// <param name="pluginId">Plugin id.</param>
|
/// <param name="pluginId">Plugin id.</param>
|
||||||
/// <response code="204">Plugin manifest returned.</response>
|
/// <response code="204">Plugin manifest returned.</response>
|
||||||
/// <response code="404">Plugin not found.</response>
|
/// <response code="404">Plugin not found.</response>
|
||||||
/// <returns>
|
/// <returns>A <see cref="PluginManifest"/> on success, or a <see cref="NotFoundResult"/> if the plugin could not be found.</returns>
|
||||||
/// A <see cref="Task" /> that represents the asynchronous operation to get the plugin's manifest.
|
|
||||||
/// The task result contains an <see cref="NoContentResult"/> indicating success, or <see cref="NotFoundResult"/>
|
|
||||||
/// when plugin not found.
|
|
||||||
/// </returns>
|
|
||||||
[HttpPost("{pluginId}/Manifest")]
|
[HttpPost("{pluginId}/Manifest")]
|
||||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
|
|
|
@ -23,7 +23,6 @@ namespace Jellyfin.Api.Models
|
||||||
if (page.Plugin != null)
|
if (page.Plugin != null)
|
||||||
{
|
{
|
||||||
DisplayName = page.Plugin.Name;
|
DisplayName = page.Plugin.Name;
|
||||||
// Don't use "N" because it needs to match Plugin.Id
|
|
||||||
PluginId = page.Plugin.Id;
|
PluginId = page.Plugin.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,6 @@ namespace MediaBrowser.Common.Plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly object _configurationSaveLock = new object();
|
private readonly object _configurationSaveLock = new object();
|
||||||
|
|
||||||
private Action<string> _directoryCreateFn;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The configuration.
|
/// The configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -65,11 +63,6 @@ namespace MediaBrowser.Common.Plugins
|
||||||
assemblyPlugin.SetId(assemblyId);
|
assemblyPlugin.SetId(assemblyId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this is IHasPluginConfiguration hasPluginConfiguration)
|
|
||||||
{
|
|
||||||
hasPluginConfiguration.SetStartupInfo(s => Directory.CreateDirectory(s));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -145,13 +138,6 @@ namespace MediaBrowser.Common.Plugins
|
||||||
/// <value>The configuration.</value>
|
/// <value>The configuration.</value>
|
||||||
BasePluginConfiguration IHasPluginConfiguration.Configuration => Configuration;
|
BasePluginConfiguration IHasPluginConfiguration.Configuration => Configuration;
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void SetStartupInfo(Action<string> directoryCreateFn)
|
|
||||||
{
|
|
||||||
// hack alert, until the .net core transition is complete
|
|
||||||
_directoryCreateFn = directoryCreateFn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the current configuration to the file system.
|
/// Saves the current configuration to the file system.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -160,7 +146,11 @@ namespace MediaBrowser.Common.Plugins
|
||||||
{
|
{
|
||||||
lock (_configurationSaveLock)
|
lock (_configurationSaveLock)
|
||||||
{
|
{
|
||||||
_directoryCreateFn(Path.GetDirectoryName(ConfigurationFilePath));
|
var folder = Path.GetDirectoryName(ConfigurationFilePath);
|
||||||
|
if (!Directory.Exists(folder))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(folder);
|
||||||
|
}
|
||||||
|
|
||||||
XmlSerializer.SerializeToFile(config, ConfigurationFilePath);
|
XmlSerializer.SerializeToFile(config, ConfigurationFilePath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,5 @@ namespace MediaBrowser.Common.Plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="configuration">The configuration.</param>
|
/// <param name="configuration">The configuration.</param>
|
||||||
void UpdateConfiguration(BasePluginConfiguration configuration);
|
void UpdateConfiguration(BasePluginConfiguration configuration);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the startup directory creation function.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="directoryCreateFn">The directory function used to create the configuration folder.</param>
|
|
||||||
void SetStartupInfo(Action<string> directoryCreateFn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Plugins
|
namespace MediaBrowser.Common.Plugins
|
||||||
|
|
|
@ -19,14 +19,12 @@ namespace MediaBrowser.Common.Plugins
|
||||||
Category = string.Empty;
|
Category = string.Empty;
|
||||||
Changelog = string.Empty;
|
Changelog = string.Empty;
|
||||||
Description = string.Empty;
|
Description = string.Empty;
|
||||||
Status = PluginStatus.Active;
|
|
||||||
Id = Guid.Empty;
|
Id = Guid.Empty;
|
||||||
Name = string.Empty;
|
Name = string.Empty;
|
||||||
Owner = string.Empty;
|
Owner = string.Empty;
|
||||||
Overview = string.Empty;
|
Overview = string.Empty;
|
||||||
TargetAbi = string.Empty;
|
TargetAbi = string.Empty;
|
||||||
Version = string.Empty;
|
Version = string.Empty;
|
||||||
AutoUpdate = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -99,7 +97,7 @@ namespace MediaBrowser.Common.Plugins
|
||||||
/// Gets or sets a value indicating whether this plugin should automatically update.
|
/// Gets or sets a value indicating whether this plugin should automatically update.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonPropertyName("autoUpdate")]
|
[JsonPropertyName("autoUpdate")]
|
||||||
public bool AutoUpdate { get; set; }
|
public bool AutoUpdate { get; set; } = true; // DO NOT MOVE THIS INTO THE CONSTRUCTOR.
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ImagePath
|
/// Gets or sets the ImagePath
|
||||||
|
|
Loading…
Reference in New Issue