diff --git a/Torch.API/Plugins/PluginAttribute.cs b/Torch.API/Plugins/PluginAttribute.cs
index 4142ce3..d8c1297 100644
--- a/Torch.API/Plugins/PluginAttribute.cs
+++ b/Torch.API/Plugins/PluginAttribute.cs
@@ -10,7 +10,7 @@ namespace Torch.API.Plugins
///
/// Indicates that the given type should be loaded by the plugin manager as a plugin.
///
- [Obsolete]
+ [Obsolete("All plugin meta-information is now defined in the manifest.xml.")]
[AttributeUsage(AttributeTargets.Class)]
public class PluginAttribute : Attribute
{
diff --git a/Torch.Server/Views/PluginsControl.xaml b/Torch.Server/Views/PluginsControl.xaml
index a9f343e..f0bc7a4 100644
--- a/Torch.Server/Views/PluginsControl.xaml
+++ b/Torch.Server/Views/PluginsControl.xaml
@@ -12,7 +12,7 @@
-
+
@@ -27,7 +27,7 @@
-
+
diff --git a/Torch.Server/Views/PluginsControl.xaml.cs b/Torch.Server/Views/PluginsControl.xaml.cs
index 2f53d43..6b54f26 100644
--- a/Torch.Server/Views/PluginsControl.xaml.cs
+++ b/Torch.Server/Views/PluginsControl.xaml.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -15,6 +16,8 @@ using System.Windows.Navigation;
using System.Windows.Shapes;
using NLog;
using Torch.API;
+using Torch.API.Managers;
+using Torch.Managers;
using Torch.Server.ViewModels;
namespace Torch.Server.Views
@@ -24,6 +27,9 @@ namespace Torch.Server.Views
///
public partial class PluginsControl : UserControl
{
+ private ITorchServer _server;
+ private PluginManager _plugins;
+
public PluginsControl()
{
InitializeComponent();
@@ -31,8 +37,15 @@ namespace Torch.Server.Views
public void BindServer(ITorchServer server)
{
- var pluginManager = new PluginManagerViewModel(server.Plugins);
+ _server = server;
+ _plugins = _server.Managers.GetManager();
+ var pluginManager = new PluginManagerViewModel(_plugins);
DataContext = pluginManager;
}
+
+ private void OpenFolder_OnClick(object sender, RoutedEventArgs e)
+ {
+ Process.Start("explorer.exe", _plugins.PluginDir);
+ }
}
}
diff --git a/Torch/Managers/PluginManager.cs b/Torch/Plugins/PluginManager.cs
similarity index 84%
rename from Torch/Managers/PluginManager.cs
rename to Torch/Plugins/PluginManager.cs
index 4f699a0..d480b46 100644
--- a/Torch/Managers/PluginManager.cs
+++ b/Torch/Plugins/PluginManager.cs
@@ -99,30 +99,42 @@ namespace Torch.Managers
var pluginItems = Directory.EnumerateFiles(PluginDir, "*.zip").Union(Directory.EnumerateDirectories(PluginDir));
Parallel.ForEach(pluginItems, async item =>
{
- var path = Path.Combine(PluginDir, item);
- var isZip = item.EndsWith(".zip", StringComparison.CurrentCultureIgnoreCase);
- var manifest = isZip ? GetManifestFromZip(path) : GetManifestFromDirectory(path);
- if (manifest == null)
+ PluginManifest manifest = null;
+ try
{
- _log.Warn($"Item '{item}' is missing a manifest, skipping update check.");
- return;
+ var path = Path.Combine(PluginDir, item);
+ var isZip = item.EndsWith(".zip", StringComparison.CurrentCultureIgnoreCase);
+ manifest = isZip ? GetManifestFromZip(path) : GetManifestFromDirectory(path);
+ if (manifest == null)
+ {
+ _log.Warn($"Item '{item}' is missing a manifest, skipping update check.");
+ return;
+ }
+
+ manifest.Version.TryExtractVersion(out Version currentVersion);
+ var latest = await GetLatestArchiveAsync(manifest.Repository).ConfigureAwait(false);
+
+ if (currentVersion == null || latest.Item1 == null)
+ {
+ _log.Error($"Error parsing version from manifest or GitHub for plugin '{manifest.Name}.'");
+ return;
+ }
+
+ if (latest.Item1 <= currentVersion)
+ {
+ _log.Debug($"{manifest.Name} {manifest.Version} is up to date.");
+ return;
+ }
+
+ _log.Info($"Updating plugin '{manifest.Name}' from {currentVersion} to {latest.Item1}.");
+ await UpdatePluginAsync(path, latest.Item2).ConfigureAwait(false);
+ count++;
}
-
- manifest.Version.TryExtractVersion(out Version currentVersion);
- var latest = await GetLatestArchiveAsync(manifest.Repository).ConfigureAwait(false);
-
- if (currentVersion == null || latest.Item1 == null)
+ catch (Exception e)
{
- _log.Error($"Error parsing version from manifest or GitHub for plugin '{manifest.Name}.'");
- return;
+ _log.Error($"An error occurred updating the plugin {manifest.Name}.");
+ _log.Error(e);
}
-
- if (latest.Item1 <= currentVersion)
- return;
-
- _log.Info($"Updating plugin '{manifest.Name}' from {currentVersion} to {latest.Item1}.");
- await UpdatePlugin(path, latest.Item2).ConfigureAwait(false);
- count++;
});
_log.Info($"Updated {count} plugins.");
@@ -155,7 +167,7 @@ namespace Torch.Managers
}
}
- private Task UpdatePlugin(string localPath, string downloadUrl)
+ private Task UpdatePluginAsync(string localPath, string downloadUrl)
{
if (File.Exists(localPath))
File.Delete(localPath);
@@ -238,9 +250,7 @@ namespace Torch.Managers
using (var stream = new StreamReader(entry.Open()))
{
- var ser = new XmlSerializer(typeof(PluginManifest));
- var manifest = (PluginManifest)ser.Deserialize(stream);
- return manifest;
+ return PluginManifest.Load(stream);
}
}
}
@@ -266,7 +276,7 @@ namespace Torch.Managers
if (pluginType != null)
{
- _log.Error($"The plugin '{manifest.Name}' has multiple implementations of {nameof(ITorchPlugin)}.");
+ _log.Error($"The plugin '{manifest.Name}' has multiple implementations of {nameof(ITorchPlugin)}, not loading.");
return;
}
@@ -276,7 +286,7 @@ namespace Torch.Managers
if (pluginType == null)
{
- _log.Error($"The plugin '{manifest.Name}' does not have an implementation of {nameof(ITorchPlugin)}.");
+ _log.Error($"The plugin '{manifest.Name}' does not have an implementation of {nameof(ITorchPlugin)}, not loading.");
return;
}
@@ -301,6 +311,7 @@ namespace Torch.Managers
_commandManager.RegisterPluginCommands(plugin);
}
+ ///
public IEnumerator GetEnumerator()
{
return Plugins.Values.GetEnumerator();
diff --git a/Torch/PluginManifest.cs b/Torch/Plugins/PluginManifest.cs
similarity index 63%
rename from Torch/PluginManifest.cs
rename to Torch/Plugins/PluginManifest.cs
index 8329cfc..13618a9 100644
--- a/Torch/PluginManifest.cs
+++ b/Torch/Plugins/PluginManifest.cs
@@ -10,11 +10,30 @@ namespace Torch
{
public class PluginManifest
{
+ ///
+ /// The display name of the plugin.
+ ///
public string Name { get; set; }
+
+ ///
+ /// A unique identifier for the plugin.
+ ///
public Guid Guid { get; set; }
+
+ ///
+ /// A GitHub repository in the format of Author/Repository to retrieve plugin updates.
+ ///
public string Repository { get; set; }
+
+ ///
+ /// The plugin version. This must include a string in the format of #[.#[.#]] for update checking purposes.
+ ///
public string Version { get; set; }
- public List Dependencies { get; } = new List();
+
+ ///
+ /// A list of dependent plugin repositories. This may be updated to include GUIDs in the future.
+ ///
+ public List Dependencies { get; } = new List();
public void Save(string path)
{
diff --git a/Torch/Torch.csproj b/Torch/Torch.csproj
index 751c5fc..6c31db6 100644
--- a/Torch/Torch.csproj
+++ b/Torch/Torch.csproj
@@ -181,7 +181,7 @@
-
+
@@ -198,7 +198,7 @@
-
+
CollectionEditor.xaml