diff options
| -rw-r--r-- | Emby.Server.Implementations/Plugins/PluginManager.cs | 13 | ||||
| -rw-r--r-- | src/Jellyfin.Extensions/TypeExtensions.cs | 45 | ||||
| -rw-r--r-- | tests/Jellyfin.Extensions.Tests/TypeExtensionsTests.cs | 68 |
3 files changed, 7 insertions, 119 deletions
diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 10d5ea906..48584ae0c 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -432,7 +432,7 @@ namespace Emby.Server.Implementations.Plugins ImagePath = imagePath }; - if (!ReconcileManifest(manifest, path)) + if (!await ReconcileManifest(manifest, path)) { // An error occurred during reconciliation and saving could be undesirable. return false; @@ -448,7 +448,7 @@ namespace Emby.Server.Implementations.Plugins /// <param name="manifest">The <see cref="PluginManifest"/> to reconcile against.</param> /// <param name="path">The plugin path.</param> /// <returns>The reconciled <see cref="PluginManifest"/>.</returns> - private bool ReconcileManifest(PluginManifest manifest, string path) + private async Task<bool> ReconcileManifest(PluginManifest manifest, string path) { try { @@ -459,8 +459,9 @@ namespace Emby.Server.Implementations.Plugins return true; } - var data = File.ReadAllBytes(metafile); - var localManifest = JsonSerializer.Deserialize<PluginManifest>(data, _jsonOptions) ?? new PluginManifest(); + using var metaStream = File.OpenRead(metafile); + var localManifest = await JsonSerializer.DeserializeAsync<PluginManifest>(metaStream, _jsonOptions); + localManifest ??= new PluginManifest(); if (!Equals(localManifest.Id, manifest.Id)) { @@ -483,7 +484,7 @@ namespace Emby.Server.Implementations.Plugins manifest.Overview = string.IsNullOrEmpty(localManifest.Overview) ? manifest.Overview : localManifest.Overview; manifest.Owner = string.IsNullOrEmpty(localManifest.Owner) ? manifest.Owner : localManifest.Owner; manifest.TargetAbi = string.IsNullOrEmpty(localManifest.TargetAbi) ? manifest.TargetAbi : localManifest.TargetAbi; - manifest.Timestamp = localManifest.Timestamp.IsNullOrDefault() ? manifest.Timestamp : localManifest.Timestamp; + manifest.Timestamp = localManifest.Timestamp.Equals(default) ? manifest.Timestamp : localManifest.Timestamp; manifest.ImagePath = string.IsNullOrEmpty(localManifest.ImagePath) ? manifest.ImagePath : localManifest.ImagePath; manifest.Assemblies = localManifest.Assemblies; @@ -842,7 +843,7 @@ namespace Emby.Server.Implementations.Plugins var canonicalized = Path.Combine(plugin.Path, path).Canonicalize(); // Ensure we stay in the plugin directory. - if (!canonicalized.StartsWith(plugin.Path.NormalizePath()!, StringComparison.Ordinal)) + if (!canonicalized.StartsWith(plugin.Path.NormalizePath(), StringComparison.Ordinal)) { _logger.LogError("Assembly path {Path} is not inside the plugin directory.", path); return false; diff --git a/src/Jellyfin.Extensions/TypeExtensions.cs b/src/Jellyfin.Extensions/TypeExtensions.cs deleted file mode 100644 index 5b1111d59..000000000 --- a/src/Jellyfin.Extensions/TypeExtensions.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Globalization; - -namespace Jellyfin.Extensions; - -/// <summary> -/// Provides extensions methods for <see cref="Type" />. -/// </summary> -public static class TypeExtensions -{ - /// <summary> - /// Checks if the supplied value is the default or null value for that type. - /// </summary> - /// <typeparam name="T">The type of the value to compare.</typeparam> - /// <param name="type">The type.</param> - /// <param name="value">The value to check.</param> - /// <returns><see langword="true"/> if the value is the default for the type. Otherwise, <see langword="false"/>.</returns> - public static bool IsNullOrDefault<T>(this Type type, T value) - { - if (value is null) - { - return true; - } - - object? tmp = value; - object? defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null; - if (type.IsAssignableTo(typeof(IConvertible))) - { - tmp = Convert.ChangeType(value, type, CultureInfo.InvariantCulture); - } - - return Equals(tmp, defaultValue); - } - - /// <summary> - /// Checks if the object is currently a default or null value. Boxed types will be unboxed prior to comparison. - /// </summary> - /// <param name="obj">The object to check.</param> - /// <returns><see langword="true"/> if the value is the default for the type. Otherwise, <see langword="false"/>.</returns> - public static bool IsNullOrDefault(this object? obj) - { - // Unbox the type and check. - return obj?.GetType().IsNullOrDefault(obj) ?? true; - } -} diff --git a/tests/Jellyfin.Extensions.Tests/TypeExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/TypeExtensionsTests.cs deleted file mode 100644 index 747913fa1..000000000 --- a/tests/Jellyfin.Extensions.Tests/TypeExtensionsTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using Xunit; - -namespace Jellyfin.Extensions.Tests -{ - public class TypeExtensionsTests - { - [Theory] - [InlineData(typeof(byte), byte.MaxValue, false)] - [InlineData(typeof(short), short.MinValue, false)] - [InlineData(typeof(ushort), ushort.MaxValue, false)] - [InlineData(typeof(int), int.MinValue, false)] - [InlineData(typeof(uint), uint.MaxValue, false)] - [InlineData(typeof(long), long.MinValue, false)] - [InlineData(typeof(ulong), ulong.MaxValue, false)] - [InlineData(typeof(decimal), -1.0, false)] - [InlineData(typeof(bool), true, false)] - [InlineData(typeof(char), 'a', false)] - [InlineData(typeof(string), "", false)] - [InlineData(typeof(object), 1, false)] - [InlineData(typeof(byte), 0, true)] - [InlineData(typeof(short), 0, true)] - [InlineData(typeof(ushort), 0, true)] - [InlineData(typeof(int), 0, true)] - [InlineData(typeof(uint), 0, true)] - [InlineData(typeof(long), 0, true)] - [InlineData(typeof(ulong), 0, true)] - [InlineData(typeof(decimal), 0, true)] - [InlineData(typeof(bool), false, true)] - [InlineData(typeof(char), '\x0000', true)] - [InlineData(typeof(string), null, true)] - [InlineData(typeof(object), null, true)] - [InlineData(typeof(PhonyClass), null, true)] - [InlineData(typeof(DateTime), null, true)] // Special case handled within the test. - [InlineData(typeof(DateTime), null, false)] // Special case handled within the test. - [InlineData(typeof(byte?), null, true)] - [InlineData(typeof(short?), null, true)] - [InlineData(typeof(ushort?), null, true)] - [InlineData(typeof(int?), null, true)] - [InlineData(typeof(uint?), null, true)] - [InlineData(typeof(long?), null, true)] - [InlineData(typeof(ulong?), null, true)] - [InlineData(typeof(decimal?), null, true)] - [InlineData(typeof(bool?), null, true)] - [InlineData(typeof(char?), null, true)] - public void IsNullOrDefault_Matches_Expected(Type type, object? value, bool expectedResult) - { - if (type == typeof(DateTime)) - { - if (expectedResult) - { - value = default(DateTime); - } - else - { - value = DateTime.Now; - } - } - - Assert.Equal(expectedResult, type.IsNullOrDefault(value)); - Assert.Equal(expectedResult, value.IsNullOrDefault()); - } - - private class PhonyClass - { - } - } -} |
