Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for windows plug-in upgrades issue: #1623 #3401

Merged
merged 35 commits into from
Sep 16, 2020
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a041fe8
Add versioning to plugin folders
BaronGreenback Jun 21, 2020
99410f3
fixes
BaronGreenback Jun 21, 2020
d89c46f
fixes
BaronGreenback Jun 21, 2020
2255bc9
Changed padding in version numbers based up how they are stored in th…
BaronGreenback Jun 21, 2020
bf1bbbd
Changed sorting to case insensitive
BaronGreenback Jun 21, 2020
a25a233
Using Version class.
BaronGreenback Jun 22, 2020
ba3a9f7
removing stray < character from description.
BaronGreenback Jun 22, 2020
e33824d
Changed to named tuples
BaronGreenback Sep 5, 2020
8439860
Merge branch 'master' into Plugins
BaronGreenback Sep 5, 2020
0f6ea12
Update ApplicationHost.cs
BaronGreenback Sep 5, 2020
2eff0db
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 8, 2020
a9d8b53
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 8, 2020
f4eb34a
Update Emby.Server.Implementations/Updates/InstallationManager.cs
BaronGreenback Sep 8, 2020
ddfb13f
Update Emby.Server.Implementations/Updates/InstallationManager.cs
BaronGreenback Sep 8, 2020
60e8f47
Update ApplicationHost.cs
BaronGreenback Sep 8, 2020
81f6558
Modified to work with manifests.
BaronGreenback Sep 13, 2020
5f58d2c
With method comments.
BaronGreenback Sep 13, 2020
b4edb7c
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 13, 2020
008aa51
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 13, 2020
12fb827
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 13, 2020
ea0eb9a
Update PlugInManifest.cs
BaronGreenback Sep 13, 2020
6c2c2cb
Update ApplicationHost.cs
BaronGreenback Sep 13, 2020
107d606
Update ApplicationHost.cs
BaronGreenback Sep 13, 2020
7b4b101
Update ApplicationHost.cs
BaronGreenback Sep 13, 2020
68d08e9
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 14, 2020
f73e744
Update Emby.Server.Implementations/Plugins/PlugInManifest.cs
BaronGreenback Sep 14, 2020
d27d2a8
Renamed file.
BaronGreenback Sep 14, 2020
f80e181
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 14, 2020
e88d3ba
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 14, 2020
51c416c
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 14, 2020
69c4b44
Update ApplicationHost.cs
BaronGreenback Sep 14, 2020
02951bb
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 14, 2020
5baf876
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 14, 2020
a2c50e8
Update Emby.Server.Implementations/ApplicationHost.cs
BaronGreenback Sep 14, 2020
ad00b93
Rename PlugInManifest.cs to PluginManifest.cs
BaronGreenback Sep 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
109 changes: 108 additions & 1 deletion Emby.Server.Implementations/ApplicationHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
Expand Down Expand Up @@ -37,6 +38,7 @@
using Emby.Server.Implementations.Localization;
using Emby.Server.Implementations.Net;
using Emby.Server.Implementations.Playlists;
using Emby.Server.Implementations.Plugins;
using Emby.Server.Implementations.QuickConnect;
using Emby.Server.Implementations.ScheduledTasks;
using Emby.Server.Implementations.Security;
Expand Down Expand Up @@ -119,6 +121,7 @@ public abstract class ApplicationHost : IServerApplicationHost, IDisposable
private readonly IFileSystem _fileSystemManager;
private readonly INetworkManager _networkManager;
private readonly IXmlSerializer _xmlSerializer;
private readonly IJsonSerializer _jsonSerializer;
private readonly IStartupOptions _startupOptions;

private IMediaEncoder _mediaEncoder;
Expand Down Expand Up @@ -249,6 +252,8 @@ public virtual bool CanLaunchWebBrowser
IServiceCollection serviceCollection)
{
_xmlSerializer = new MyXmlSerializer();
_jsonSerializer = new JsonSerializer();

ServiceCollection = serviceCollection;

_networkManager = networkManager;
Expand Down Expand Up @@ -1015,6 +1020,108 @@ public void Restart()

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)
{
var dllList = new List<string>();
var versions = new List<(Version PluginVersion, string Name, string Path)>();
var directories = Directory.EnumerateDirectories(path, "*.*", SearchOption.TopDirectoryOnly);
string metafile;

foreach (var dir in directories)
BaronGreenback marked this conversation as resolved.
Show resolved Hide resolved
{
try
{
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);
}

if (!Version.TryParse(manifest.Version, out var version))
{
version = new Version(0, 0, 0, 1);
}

if (ApplicationVersion >= targetAbi)
{
// Only load Plugins if the plugin is built for this version or below.
versions.Add((version, manifest.Name, dir));
}
}
else
{
metafile = dir.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries)[^1];
// Add it under the path name and version 0.0.0.1.
versions.Add(new Version(0, 0, 0, 1), metafile, dir);
BaronGreenback marked this conversation as resolved.
Show resolved Hide resolved
}
}
catch
{
continue;
}
}

string lastName = string.Empty;
versions.Sort(VersionCompare);
// 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));
lastName = versions[x].Name;
continue;
}

if (!string.IsNullOrEmpty(lastName) && cleanup)
{
// Attempt a cleanup of old folders.
try
{
Logger.LogDebug("Deleting {Path}", versions[x].Path);
Directory.Delete(versions[x].Path, true);
}
catch (Exception e)
{
Logger.LogWarning(e, "Unable to delete {Path}", versions[x].Path);
}
}
}

return dllList;
}

/// <summary>
/// Gets the composable part assemblies.
/// </summary>
Expand All @@ -1023,7 +1130,7 @@ protected IEnumerable<Assembly> GetComposablePartAssemblies()
{
if (Directory.Exists(ApplicationPaths.PluginsPath))
{
foreach (var file in Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.AllDirectories))
foreach (var file in GetPlugins(ApplicationPaths.PluginsPath))
{
Assembly plugAss;
try
Expand Down
60 changes: 60 additions & 0 deletions Emby.Server.Implementations/Plugins/PlugInManifest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;

namespace Emby.Server.Implementations.Plugins
{
/// <summary>
/// Defines a Plugin manifest file.
/// </summary>
public class PluginManifest
BaronGreenback marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// Gets or sets the category of the plugin.
/// </summary>
public string Category { get; set; }

/// <summary>
/// Gets or sets the changelog information.
/// </summary>
public string Changelog { get; set; }

/// <summary>
/// Gets or sets the description of the plugin.
/// </summary>
public string Description { get; set; }

/// <summary>
/// Gets or sets the Global Unique Identifier for the plugin.
/// </summary>
public Guid Guid { get; set; }

/// <summary>
/// Gets or sets the Name of the plugin.
/// </summary>
public string Name { get; set; }

/// <summary>
/// Gets or sets an overview of the plugin.
/// </summary>
public string Overview { get; set; }

/// <summary>
/// Gets or sets the owner of the plugin.
/// </summary>
public string Owner { get; set; }

/// <summary>
/// Gets or sets the compatibility version for the plugin.
/// </summary>
public string TargetAbi { get; set; }

/// <summary>
/// Gets or sets the timestamp of the plugin.
/// </summary>
public DateTime Timestamp { get; set; }

/// <summary>
/// Gets or sets the Version number of the plugin.
/// </summary>
public string Version { get; set; }
}
}
34 changes: 26 additions & 8 deletions Emby.Server.Implementations/Updates/InstallationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates;
using MediaBrowser.Common.System;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.IO;
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
{
Expand Down Expand Up @@ -372,11 +374,20 @@ private async Task PerformPackageInstallation(InstallationInfo package, Cancella
throw new InvalidDataException("The checksum of the received data doesn't match.");
}

// Version folder as they cannot be overwritten in Windows.
targetDir += "_" + package.Version;

if (Directory.Exists(targetDir))
{
Directory.Delete(targetDir, true);
try
{
Directory.Delete(targetDir, true);
}
catch
{
// Ignore any exceptions.
}
}

stream.Position = 0;
_zipClient.ExtractAllFromZip(stream, targetDir, true);

Expand Down Expand Up @@ -418,15 +429,22 @@ public void UninstallPlugin(IPlugin plugin)
path = file;
}

if (isDirectory)
try
{
_logger.LogInformation("Deleting plugin directory {0}", path);
Directory.Delete(path, true);
if (isDirectory)
{
_logger.LogInformation("Deleting plugin directory {0}", path);
Directory.Delete(path, true);
}
else
{
_logger.LogInformation("Deleting plugin file {0}", path);
_fileSystem.DeleteFile(path);
}
}
else
catch
{
_logger.LogInformation("Deleting plugin file {0}", path);
_fileSystem.DeleteFile(path);
// Ignore file errors.
}

var list = _config.Configuration.UninstalledPlugins.ToList();
Expand Down