diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 5f0cfe6fd..b190fa0a4 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -113,6 +113,7 @@ + diff --git a/src/Artemis.Core/Extensions/DirectoryInfoExtensions.cs b/src/Artemis.Core/Extensions/DirectoryInfoExtensions.cs new file mode 100644 index 000000000..6b3a62785 --- /dev/null +++ b/src/Artemis.Core/Extensions/DirectoryInfoExtensions.cs @@ -0,0 +1,15 @@ +using System.IO; + +namespace Artemis.Core.Extensions +{ + public static class DirectoryInfoExtensions + { + public static void CopyFilesRecursively(this DirectoryInfo source, DirectoryInfo target) + { + foreach (var dir in source.GetDirectories()) + CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name)); + foreach (var file in source.GetFiles()) + file.CopyTo(Path.Combine(target.FullName, file.Name)); + } + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index 19915612e..c56789132 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -39,6 +39,7 @@ namespace Artemis.Core.Services throw new ArtemisCoreException("Cannot initialize the core as it is already initialized."); // Initialize the services + await Task.Run(() => _pluginService.CopyBuiltInPlugins()); await Task.Run(() => _pluginService.LoadPlugins()); OnInitialized(); diff --git a/src/Artemis.Core/Services/Interfaces/IPluginService.cs b/src/Artemis.Core/Services/Interfaces/IPluginService.cs index c51cd70db..50b904711 100644 --- a/src/Artemis.Core/Services/Interfaces/IPluginService.cs +++ b/src/Artemis.Core/Services/Interfaces/IPluginService.cs @@ -13,6 +13,12 @@ namespace Artemis.Core.Services.Interfaces /// bool LoadingPlugins { get; } + /// + /// Copy built-in plugins from the executable directory to the plugins directory if the version is higher + /// (higher or equal if compiled as debug) + /// + void CopyBuiltInPlugins(); + /// /// Loads all installed plugins. If plugins already loaded this will reload them all /// diff --git a/src/Artemis.Core/Services/PluginService.cs b/src/Artemis.Core/Services/PluginService.cs index c7e8c15bb..77407c8ac 100644 --- a/src/Artemis.Core/Services/PluginService.cs +++ b/src/Artemis.Core/Services/PluginService.cs @@ -5,6 +5,7 @@ using System.Linq; using AppDomainToolkit; using Artemis.Core.Events; using Artemis.Core.Exceptions; +using Artemis.Core.Extensions; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Exceptions; using Artemis.Core.Plugins.Models; @@ -30,6 +31,7 @@ namespace Artemis.Core.Services _kernel = kernel; _plugins = new List(); + // Ensure the plugins directory exists if (!Directory.Exists(Constants.DataFolder + "plugins")) Directory.CreateDirectory(Constants.DataFolder + "plugins"); } @@ -37,6 +39,54 @@ namespace Artemis.Core.Services /// public bool LoadingPlugins { get; private set; } + /// + public void CopyBuiltInPlugins() + { + var pluginDirectory = new DirectoryInfo(Path.Combine(Constants.DataFolder, "plugins")); + + // Iterate built-in plugins + var varBuiltInPluginDirectory = new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "Plugins")); + foreach (var subDirectory in varBuiltInPluginDirectory.EnumerateDirectories()) + { + // Load the metadata + var builtInMetadataFile = Path.Combine(subDirectory.FullName, "plugin.json"); + if (!File.Exists(builtInMetadataFile)) + throw new ArtemisPluginException("Couldn't find the built-in plugins metadata file at " + builtInMetadataFile); + + var builtInPluginInfo = JsonConvert.DeserializeObject(File.ReadAllText(builtInMetadataFile)); + + // Find the matching plugin in the plugin folder + var match = pluginDirectory.EnumerateDirectories().FirstOrDefault(d => d.Name == subDirectory.Name); + if (match == null) + CopyBuiltInPlugin(subDirectory); + else + { + var metadataFile = Path.Combine(match.FullName, "plugin.json"); + if (!File.Exists(metadataFile)) + CopyBuiltInPlugin(subDirectory); + else + { + try + { + // Compare versions, copy if the same when debugging + var pluginInfo = JsonConvert.DeserializeObject(File.ReadAllText(builtInMetadataFile)); + #if DEBUG + if (builtInPluginInfo.Version >= pluginInfo.Version) + CopyBuiltInPlugin(subDirectory); + #else + if (builtInPluginInfo.Version > pluginInfo.Version) + CopyBuiltInPlugin(subDirectory); + #endif + } + catch (Exception e) + { + throw new ArtemisPluginException("Failed read plugin metadata needed to install built-in plugin", e); + } + } + } + } + } + /// public void LoadPlugins() { @@ -54,8 +104,8 @@ namespace Artemis.Core.Services _childKernel = new ChildKernel(_kernel); // Load the plugin assemblies into the plugin context - var directory = new DirectoryInfo(Path.Combine(Constants.DataFolder, "plugins")); - foreach (var subDirectory in directory.EnumerateDirectories()) + var pluginDirectory = new DirectoryInfo(Path.Combine(Constants.DataFolder, "plugins")); + foreach (var subDirectory in pluginDirectory.EnumerateDirectories()) { try { @@ -236,6 +286,17 @@ namespace Artemis.Core.Services UnloadPlugins(); } + private static void CopyBuiltInPlugin(DirectoryInfo builtInPluginDirectory) + { + var pluginDirectory = new DirectoryInfo(Path.Combine(Constants.DataFolder, "plugins", builtInPluginDirectory.Name)); + + // Remove the old directory if it exists + if (Directory.Exists(pluginDirectory.FullName)) + Directory.Delete(pluginDirectory.FullName, true); + Directory.CreateDirectory(pluginDirectory.FullName); + + builtInPluginDirectory.CopyFilesRecursively(pluginDirectory); + } #region Events diff --git a/src/Artemis.Plugins.Devices.Corsair/Artemis.Plugins.Devices.Corsair.csproj b/src/Artemis.Plugins.Devices.Corsair/Artemis.Plugins.Devices.Corsair.csproj index 1f0cb4ff4..73e493530 100644 --- a/src/Artemis.Plugins.Devices.Corsair/Artemis.Plugins.Devices.Corsair.csproj +++ b/src/Artemis.Plugins.Devices.Corsair/Artemis.Plugins.Devices.Corsair.csproj @@ -73,7 +73,7 @@ - (robocopy $(TargetDir) %25ProgramData%25\Artemis\plugins\$(ProjectName) /E /NFL /NDL /NJH /NJS /nc /ns /np) ^& IF %25ERRORLEVEL%25 LEQ 4 exit /B 0 + (robocopy $(TargetDir) $(SolutionDir)\Artemis.UI\$(OutDir)\Plugins\$(ProjectName) /E /NFL /NDL /NJH /NJS /nc /ns /np) ^& IF %25ERRORLEVEL%25 LEQ 4 exit /B 0 diff --git a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerTypes.Brush.csproj b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerTypes.Brush.csproj index 8445ba521..f59eb32e7 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerTypes.Brush.csproj +++ b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerTypes.Brush.csproj @@ -86,6 +86,6 @@ - (robocopy $(TargetDir) %25ProgramData%25\Artemis\plugins\$(ProjectName) /E /NFL /NDL /NJH /NJS /nc /ns /np) ^& IF %25ERRORLEVEL%25 LEQ 4 exit /B 0 + (robocopy $(TargetDir) $(SolutionDir)\Artemis.UI\$(OutDir)\Plugins\$(ProjectName) /E /NFL /NDL /NJH /NJS /nc /ns /np) ^& IF %25ERRORLEVEL%25 LEQ 4 exit /B 0 \ No newline at end of file diff --git a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj index 9e4e5cd89..4978e43f1 100644 --- a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj +++ b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj @@ -95,6 +95,6 @@ - (robocopy $(TargetDir) %25ProgramData%25\Artemis\plugins\$(ProjectName) /E /NFL /NDL /NJH /NJS /nc /ns /np) ^& IF %25ERRORLEVEL%25 LEQ 4 exit /B 0 + (robocopy $(TargetDir) $(SolutionDir)\Artemis.UI\$(OutDir)\Plugins\$(ProjectName) /E /NFL /NDL /NJH /NJS /nc /ns /np) ^& IF %25ERRORLEVEL%25 LEQ 4 exit /B 0 \ No newline at end of file diff --git a/src/Artemis.Storage/StorageContext.cs b/src/Artemis.Storage/StorageContext.cs index 8af00a422..eae7928be 100644 --- a/src/Artemis.Storage/StorageContext.cs +++ b/src/Artemis.Storage/StorageContext.cs @@ -1,5 +1,5 @@ -using System.IO; -using System.Reflection; +using System; +using System.IO; using Artemis.Storage.Entities; using Microsoft.EntityFrameworkCore; using SQLitePCL; @@ -14,12 +14,12 @@ namespace Artemis.Storage protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { -// var dbLocation = @"C:\Repos\Artemis\src\Artemis.Storage\Storage.db"; + // ReSharper disable once RedundantAssignment - Used if not debugging + var dbLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Artemis\\Storage.db"); #if DEBUG - var dbLocation = Path.GetFullPath(Path.Combine(Assembly.GetEntryAssembly().Location, @"..\..\..\..\Artemis.Storage\Storage.db")); - #else - var dbLocation = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Artemis\\Storage.db"; + dbLocation = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), @"..\..\..\..\Artemis.Storage\Storage.db")); #endif + optionsBuilder.UseSqlite("Data Source=" + dbLocation); // Requires Microsoft.Data.Sqlite in the startup project