Переглянути джерело

Merge pull request #994 from PixiEditor/fixes/extension-updating

Fixed extension updating
Krzysztof Krysiński 1 місяць тому
батько
коміт
47aee2d41a

+ 23 - 14
src/PixiEditor.Extensions.Runtime/ExtensionLoader.cs

@@ -34,23 +34,32 @@ public class ExtensionLoader
     {
         foreach (var packagesPath in PackagesPath)
         {
-            LoadExtensionsFromPath(packagesPath);
-        }
-    }
-
-    private void LoadExtensionsFromPath(string path)
-    {
-        if (!Directory.Exists(path))
-        {
-            return;
-        }
+            foreach (var updateFile in Directory.GetFiles(packagesPath, "*.update"))
+            {
+                try
+                {
+                    string newExtension = Path.ChangeExtension(updateFile, ".pixiext");
+                    if (File.Exists(newExtension))
+                    {
+                        File.Delete(newExtension);
+                    }
 
-        foreach (var file in Directory.GetFiles(path))
-        {
-            if (file.EndsWith(".pixiext"))
+                    File.Move(updateFile, newExtension);
+                }
+                catch (IOException)
+                {
+                    // File is in use, ignore
+                }
+                catch (UnauthorizedAccessException)
+                {
+                    // File is in use, ignore
+                } 
+            }
+            
+            foreach (var file in Directory.GetFiles(packagesPath, "*.pixiext"))
             {
                 LoadExtension(file);
-            }
+            } 
         }
     }
 

+ 23 - 14
src/PixiEditor.Platform.Standalone/StandaloneAdditionalContentProvider.cs

@@ -9,20 +9,20 @@ namespace PixiEditor.Platform.Standalone;
 
 public sealed class StandaloneAdditionalContentProvider : IAdditionalContentProvider
 {
-    public string ExtensionsPath { get; }
+    public string[] ExtensionsPaths { get; }
     public PixiAuthIdentityProvider IdentityProvider { get; }
 
     public event Action<string, object>? OnError;
 
-    public StandaloneAdditionalContentProvider(string extensionsPath, PixiAuthIdentityProvider identityProvider)
+    public StandaloneAdditionalContentProvider(string[] extensionsPaths, PixiAuthIdentityProvider identityProvider)
     {
         IdentityProvider = identityProvider;
-        ExtensionsPath = extensionsPath;
+        ExtensionsPaths = extensionsPaths;
     }
 
     public async Task<string?> InstallContent(string productId)
     {
-        if (!IdentityProvider.IsValid) return null;
+        if (!IdentityProvider.IsValid || ExtensionsPaths == null || ExtensionsPaths.Length == 0) return null;
 
         if (IdentityProvider.User is not { IsLoggedIn: true })
         {
@@ -35,7 +35,21 @@ public sealed class StandaloneAdditionalContentProvider : IAdditionalContentProv
                 await IdentityProvider.PixiAuthClient.DownloadProduct(IdentityProvider.User.SessionToken, productId);
             if (stream != null)
             {
-                var filePath = Path.Combine(ExtensionsPath, $"{productId}.pixiext");
+                var firstExistingPath =
+                    ExtensionsPaths.FirstOrDefault(path => File.Exists(Path.Combine(path, $"{productId}.pixiext")));
+                if (firstExistingPath != null)
+                {
+                    var updatePath = Path.Combine(firstExistingPath, $"{productId}.update");
+                    await using (var fileStream = File.Create(updatePath))
+                    {
+                        await stream.CopyToAsync(fileStream);
+                    }
+
+                    await stream.DisposeAsync();
+                    return updatePath;
+                }
+
+                var filePath = Path.Combine(ExtensionsPaths[0], $"{productId}.pixiext");
                 try
                 {
                     await using (var fileStream = File.Create(filePath))
@@ -47,7 +61,7 @@ public sealed class StandaloneAdditionalContentProvider : IAdditionalContentProv
                 }
                 catch (IOException e)
                 {
-                    filePath = Path.Combine(ExtensionsPath, $"{productId}.update");
+                    filePath = Path.Combine(ExtensionsPaths[0], $"{productId}.update");
                     await using (var fileStream = File.Create(filePath))
                     {
                         await stream.CopyToAsync(fileStream);
@@ -80,14 +94,9 @@ public sealed class StandaloneAdditionalContentProvider : IAdditionalContentProv
     {
         if (string.IsNullOrEmpty(productId)) return false;
 
-        string filePath = Path.Combine(ExtensionsPath, $"{productId}.pixiext");
-        bool exists = File.Exists(filePath);
-        if (exists) return true;
-        
-        filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Extensions", $"{productId}.pixiext");
-        exists = File.Exists(filePath);
-
-        return exists;
+        var firstExistingPath =
+            ExtensionsPaths.FirstOrDefault(path => File.Exists(Path.Combine(path, $"{productId}.pixiext")));
+        return firstExistingPath != null;
     }
 
     public bool IsContentOwned(string product)

+ 2 - 2
src/PixiEditor.Platform.Standalone/StandalonePlatform.cs

@@ -12,11 +12,11 @@ public sealed class StandalonePlatform : IPlatform
     public IIdentityProvider? IdentityProvider { get; }
     public IAdditionalContentProvider? AdditionalContentProvider { get; }
 
-    public StandalonePlatform(string extensionsPath, string apiUrl, string? apiKey)
+    public StandalonePlatform(string[] extensionsPaths, string apiUrl, string? apiKey)
     {
         PixiAuthIdentityProvider authProvider = new PixiAuthIdentityProvider(apiUrl, apiKey);
         IdentityProvider = authProvider;
-        AdditionalContentProvider = new StandaloneAdditionalContentProvider(extensionsPath, authProvider);
+        AdditionalContentProvider = new StandaloneAdditionalContentProvider(extensionsPaths, authProvider);
     }
 
     public bool PerformHandshake()

+ 3 - 5
src/PixiEditor/Initialization/ClassicDesktopEntry.cs

@@ -10,14 +10,12 @@ using PixiEditor.Extensions;
 using PixiEditor.Extensions.Runtime;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers.Behaviours;
-using PixiEditor.IdentityProvider;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.ExceptionHandling;
 using PixiEditor.Models.IO;
 using PixiEditor.OperatingSystem;
 using PixiEditor.Platform;
 using PixiEditor.UI.Common.Controls;
-using PixiEditor.ViewModels.SubViewModels;
 using PixiEditor.Views;
 using PixiEditor.Views.Auth;
 using PixiEditor.Views.Dialogs;
@@ -149,7 +147,7 @@ internal class ClassicDesktopEntry
         }
 
         ExtensionLoader extensionLoader = new ExtensionLoader(
-            [Paths.InstallDirExtensionPackagesPath, Paths.LocalExtensionPackagesPath], Paths.UserExtensionsPath);
+            [Paths.InstallDirExtensionPackagesPath, Paths.LocalExtensionPackagesPath], Paths.UnpackedExtensionsPath);
         if (!safeMode)
         {
             extensionLoader.LoadExtensions();
@@ -174,8 +172,8 @@ internal class ClassicDesktopEntry
         return new PixiEditor.Platform.MSStore.MicrosoftStorePlatform(Paths.LocalExtensionPackagesPath, GetApiUrl(),
             GetApiKey());
 #else
-        return new PixiEditor.Platform.Standalone.StandalonePlatform(Paths.LocalExtensionPackagesPath, GetApiUrl(),
-            GetApiKey());
+        return new PixiEditor.Platform.Standalone.StandalonePlatform([Paths.LocalExtensionPackagesPath, Paths.InstallDirExtensionPackagesPath], GetApiUrl(),
+            GetApiKey()); // The first in the extensionsPath array should be local, because it's the default where extensions are installed. Otherwise, OS access rights may cause issues.
 #endif
     }
 

+ 1 - 1
src/PixiEditor/Models/IO/Paths.cs

@@ -21,7 +21,7 @@ public static class Paths
         Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
         "PixiEditor", "Configs");
 
-    public static string UserExtensionsPath { get; } = Path.Combine(
+    public static string UnpackedExtensionsPath { get; } = Path.Combine(
         Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
         "PixiEditor", "Extensions", "Unpacked");