diff --git a/.idea/.idea.StabilityMatrix/.idea/.gitignore b/.idea/.idea.StabilityMatrix/.idea/.gitignore new file mode 100644 index 000000000..b01cc5074 --- /dev/null +++ b/.idea/.idea.StabilityMatrix/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/.idea.StabilityMatrix.iml +/contentModel.xml +/modules.xml +/projectSettingsUpdater.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.StabilityMatrix/.idea/encodings.xml b/.idea/.idea.StabilityMatrix/.idea/encodings.xml new file mode 100644 index 000000000..df87cf951 --- /dev/null +++ b/.idea/.idea.StabilityMatrix/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.StabilityMatrix/.idea/indexLayout.xml b/.idea/.idea.StabilityMatrix/.idea/indexLayout.xml new file mode 100644 index 000000000..7b08163ce --- /dev/null +++ b/.idea/.idea.StabilityMatrix/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.StabilityMatrix/.idea/vcs.xml b/.idea/.idea.StabilityMatrix/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/.idea.StabilityMatrix/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/StabilityMatrix.Tests/Helper/PackageFactoryTests.cs b/StabilityMatrix.Tests/Helper/PackageFactoryTests.cs index b7b6145f4..8d6e02184 100644 --- a/StabilityMatrix.Tests/Helper/PackageFactoryTests.cs +++ b/StabilityMatrix.Tests/Helper/PackageFactoryTests.cs @@ -16,7 +16,7 @@ public void Setup() fakeBasePackages = new List { // TODO: inject mocks - new DankDiffusion(null, null, null, null) + new DankDiffusion(null, null, null, null, null) }; packageFactory = new PackageFactory(fakeBasePackages); } diff --git a/StabilityMatrix/App.xaml.cs b/StabilityMatrix/App.xaml.cs index d9168a046..c7303cacb 100644 --- a/StabilityMatrix/App.xaml.cs +++ b/StabilityMatrix/App.xaml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; @@ -231,6 +231,8 @@ private void App_OnStartup(object sender, StartupEventArgs e) serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddTransient(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/StabilityMatrix/Models/Packages/A3WebUI.cs b/StabilityMatrix/Models/Packages/A3WebUI.cs index 0e5b05b53..07b0735f8 100644 --- a/StabilityMatrix/Models/Packages/A3WebUI.cs +++ b/StabilityMatrix/Models/Packages/A3WebUI.cs @@ -24,10 +24,14 @@ public class A3WebUI : BaseGitPackage public string RelativeArgsDefinitionScriptPath => "modules.cmd_args"; - public A3WebUI(IGithubApiCache githubApi, ISettingsManager settingsManager, IDownloadService downloadService, - IPrerequisiteHelper prerequisiteHelper) : + public A3WebUI(IGithubApiCache githubApi, + ISettingsManager settingsManager, + IDownloadService downloadService, + IPrerequisiteHelper prerequisiteHelper, + LinkedFolderSharedFolderStrategy sharedFolderStrategy) : base(githubApi, settingsManager, downloadService, prerequisiteHelper) { + SharedFolderStrategy = sharedFolderStrategy; } // From https://github.com/AUTOMATIC1111/stable-diffusion-webui/tree/master/models @@ -48,6 +52,8 @@ public A3WebUI(IGithubApiCache githubApi, ISettingsManager settingsManager, IDow [SharedFolderType.ControlNet] = "models/ControlNet" }; + public override ISharedFolderStrategy SharedFolderStrategy { get; protected set; } + [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")] public override List LaunchOptions => new() { diff --git a/StabilityMatrix/Models/Packages/BaseGitPackage.cs b/StabilityMatrix/Models/Packages/BaseGitPackage.cs index a64f9a569..0431cf03b 100644 --- a/StabilityMatrix/Models/Packages/BaseGitPackage.cs +++ b/StabilityMatrix/Models/Packages/BaseGitPackage.cs @@ -28,7 +28,11 @@ public abstract class BaseGitPackage : BasePackage protected readonly IDownloadService DownloadService; protected readonly IPrerequisiteHelper PrerequisiteHelper; protected PyVenvRunner? VenvRunner; - + + public BaseGitPackage() + { + + } /// /// URL of the hosted web page on launch /// diff --git a/StabilityMatrix/Models/Packages/BasePackage.cs b/StabilityMatrix/Models/Packages/BasePackage.cs index cedd5c873..6b9b9e4a4 100644 --- a/StabilityMatrix/Models/Packages/BasePackage.cs +++ b/StabilityMatrix/Models/Packages/BasePackage.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -31,13 +31,15 @@ public abstract class BasePackage public abstract List LaunchOptions { get; } public virtual string? ExtraLaunchArguments { get; set; } = null; - + /// /// The shared folders that this package supports. /// Mapping of to the relative path from the package root. /// public virtual Dictionary? SharedFolders { get; } - + + public abstract ISharedFolderStrategy SharedFolderStrategy { get; protected set; } + public abstract Task GetLatestVersion(); public abstract Task> GetAllVersions(bool isReleaseMode = true); public abstract Task?> GetAllCommits(string branch, int page = 1, int perPage = 10); diff --git a/StabilityMatrix/Models/Packages/ComfyUI.cs b/StabilityMatrix/Models/Packages/ComfyUI.cs index 34256e692..74b029f1d 100644 --- a/StabilityMatrix/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix/Models/Packages/ComfyUI.cs @@ -26,9 +26,10 @@ public class ComfyUI : BaseGitPackage public override bool ShouldIgnoreReleases => true; public ComfyUI(IGithubApiCache githubApi, ISettingsManager settingsManager, IDownloadService downloadService, - IPrerequisiteHelper prerequisiteHelper) : + IPrerequisiteHelper prerequisiteHelper, LinkedFolderSharedFolderStrategy sharedFolderStrategy) : base(githubApi, settingsManager, downloadService, prerequisiteHelper) { + SharedFolderStrategy = sharedFolderStrategy; } // https://github.com/comfyanonymous/ComfyUI/blob/master/folder_paths.py#L11 @@ -46,7 +47,9 @@ public ComfyUI(IGithubApiCache githubApi, ISettingsManager settingsManager, IDow [SharedFolderType.ESRGAN] = "models/upscale_models", [SharedFolderType.Hypernetwork] = "models/hypernetworks", }; - + + public override ISharedFolderStrategy SharedFolderStrategy { get; protected set; } + public override List LaunchOptions => new() { new() diff --git a/StabilityMatrix/Models/Packages/DankDiffusion.cs b/StabilityMatrix/Models/Packages/DankDiffusion.cs index 24263df52..b9f955f73 100644 --- a/StabilityMatrix/Models/Packages/DankDiffusion.cs +++ b/StabilityMatrix/Models/Packages/DankDiffusion.cs @@ -10,9 +10,10 @@ namespace StabilityMatrix.Models.Packages; public class DankDiffusion : BaseGitPackage { public DankDiffusion(IGithubApiCache githubApi, ISettingsManager settingsManager, IDownloadService downloadService, - IPrerequisiteHelper prerequisiteHelper) : + IPrerequisiteHelper prerequisiteHelper, LinkedFolderSharedFolderStrategy sharedFolderStrategy) : base(githubApi, settingsManager, downloadService, prerequisiteHelper) { + SharedFolderStrategy = sharedFolderStrategy; } public override string Name => "dank-diffusion"; @@ -27,6 +28,8 @@ public override Task RunPackage(string installedPackagePath, string arguments) } public override List LaunchOptions { get; } + public override ISharedFolderStrategy SharedFolderStrategy { get; protected set; } + public override Task GetLatestVersion() { throw new System.NotImplementedException(); diff --git a/StabilityMatrix/Models/Packages/ISharedFolderStrategy.cs b/StabilityMatrix/Models/Packages/ISharedFolderStrategy.cs new file mode 100644 index 000000000..476036d6a --- /dev/null +++ b/StabilityMatrix/Models/Packages/ISharedFolderStrategy.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace StabilityMatrix.Models.Packages; + +public interface ISharedFolderStrategy +{ + Task ExecuteAsync(BasePackage package); +} \ No newline at end of file diff --git a/StabilityMatrix/Models/Packages/LinkedFolderSharedFolderStrategy.cs b/StabilityMatrix/Models/Packages/LinkedFolderSharedFolderStrategy.cs new file mode 100644 index 000000000..6eaa6100e --- /dev/null +++ b/StabilityMatrix/Models/Packages/LinkedFolderSharedFolderStrategy.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; + +namespace StabilityMatrix.Models.Packages; + +public class LinkedFolderSharedFolderStrategy : ISharedFolderStrategy +{ + private readonly IServiceProvider serviceProvider; + + public LinkedFolderSharedFolderStrategy(IServiceProvider serviceProvider) + { + this.serviceProvider = serviceProvider; + } + + public Task ExecuteAsync(BasePackage package) + { + // TODO: Move SharedFolders logic here + // NOTE: We're using this awkward solution because a circular dependency is generated in the graph otherwise + var sharedFolders = serviceProvider.GetRequiredService(); + sharedFolders.SetupLinksForPackage(package, package.InstallLocation); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/StabilityMatrix/Models/Packages/VladAutomatic.cs b/StabilityMatrix/Models/Packages/VladAutomatic.cs index 65401a986..218531bdd 100644 --- a/StabilityMatrix/Models/Packages/VladAutomatic.cs +++ b/StabilityMatrix/Models/Packages/VladAutomatic.cs @@ -27,9 +27,10 @@ public class VladAutomatic : BaseGitPackage public override bool ShouldIgnoreReleases => true; public VladAutomatic(IGithubApiCache githubApi, ISettingsManager settingsManager, IDownloadService downloadService, - IPrerequisiteHelper prerequisiteHelper) : + IPrerequisiteHelper prerequisiteHelper, VladAutomaticSharedFolderStrategy sharedFolderStrategy) : base(githubApi, settingsManager, downloadService, prerequisiteHelper) { + SharedFolderStrategy = sharedFolderStrategy; } // https://github.com/vladmandic/automatic/blob/master/modules/shared.py#L324 @@ -53,6 +54,8 @@ public VladAutomatic(IGithubApiCache githubApi, ISettingsManager settingsManager [SharedFolderType.LyCORIS] = "models/LyCORIS", }; + public override ISharedFolderStrategy SharedFolderStrategy { get; protected set; } + [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")] public override List LaunchOptions => new() { diff --git a/StabilityMatrix/Models/Packages/VladAutomaticSharedFolderStrategy.cs b/StabilityMatrix/Models/Packages/VladAutomaticSharedFolderStrategy.cs new file mode 100644 index 000000000..90171aa09 --- /dev/null +++ b/StabilityMatrix/Models/Packages/VladAutomaticSharedFolderStrategy.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using StabilityMatrix.Extensions; +using StabilityMatrix.Helper; +using StabilityMatrix.Models.FileInterfaces; + +namespace StabilityMatrix.Models.Packages; + +public class VladAutomaticSharedFolderStrategy : ISharedFolderStrategy +{ + private readonly ISettingsManager settingsManager; + + public VladAutomaticSharedFolderStrategy(ISettingsManager settingsManager) + { + this.settingsManager = settingsManager; + } + + public async Task ExecuteAsync(BasePackage package) + { + var installedPackage = settingsManager + .Settings + .InstalledPackages + .Single(p => p.PackageName == package.Name); + var configFilePath = Path.Combine(settingsManager.LibraryDir, installedPackage.LibraryPath!, "config.json"); + + // Load the configuration file + var json = await File.ReadAllTextAsync(configFilePath); + var job = JsonConvert.DeserializeObject(json)!; + + // Update the configuration values + var modelsDirectory = new DirectoryPath(settingsManager.ModelsDirectory); + foreach (var (sharedFolderType, configKey) in map) + { + var value = Path.Combine(modelsDirectory.FullPath, sharedFolderType.GetStringValue()); + job[configKey] = value; + } + + // Write the configuration file + await File.WriteAllTextAsync(configFilePath, JsonConvert.SerializeObject(job, Formatting.Indented)); + } + + private Dictionary map = new() + { + { SharedFolderType.StableDiffusion, "ckpt_dir" }, + { SharedFolderType.Diffusers, "diffusers_dir" }, + { SharedFolderType.VAE, "vae_dir" }, + { SharedFolderType.Lora, "lora_dir" }, + { SharedFolderType.LyCORIS, "lyco_dir" }, + // { SharedFolderType.Styles, "styles_dir"}, + { SharedFolderType.TextualInversion, "embeddings_dir" }, + { SharedFolderType.Hypernetwork, "hypernetwork_dir" }, + { SharedFolderType.Codeformer, "codeformer_models_path" }, + { SharedFolderType.GFPGAN, "gfpgan_models_path" }, + { SharedFolderType.ESRGAN, "esrgan_models_path" }, + { SharedFolderType.BSRGAN , "bsrgan_models_path"}, + { SharedFolderType.RealESRGAN, "realesrgan_models_path" }, + { SharedFolderType.ScuNET, "scunet_models_path" }, + { SharedFolderType.SwinIR, "swinir_models_path" }, + { SharedFolderType.LDSR, "ldsr_models_path" }, + { SharedFolderType.CLIP, "clip_models_path" } + }; +} + diff --git a/StabilityMatrix/StabilityMatrix.csproj b/StabilityMatrix/StabilityMatrix.csproj index 976b151f5..22b75d7d2 100644 --- a/StabilityMatrix/StabilityMatrix.csproj +++ b/StabilityMatrix/StabilityMatrix.csproj @@ -30,6 +30,7 @@ + diff --git a/StabilityMatrix/ViewModels/InstallerViewModel.cs b/StabilityMatrix/ViewModels/InstallerViewModel.cs index fe14b650f..8df3f6bd9 100644 --- a/StabilityMatrix/ViewModels/InstallerViewModel.cs +++ b/StabilityMatrix/ViewModels/InstallerViewModel.cs @@ -318,8 +318,9 @@ private async Task ActuallyInstall() await InstallPackage(); ProgressText = "Setting up shared folder links..."; - sharedFolders.SetupLinksForPackage(SelectedPackage, SelectedPackage.InstallLocation); - + + await SelectedPackage.SharedFolderStrategy.ExecuteAsync(SelectedPackage); + ProgressText = "Done"; IsIndeterminate = false; ProgressValue = 100; diff --git a/StabilityMatrix/ViewModels/LaunchViewModel.cs b/StabilityMatrix/ViewModels/LaunchViewModel.cs index 227bb51d8..75d807752 100644 --- a/StabilityMatrix/ViewModels/LaunchViewModel.cs +++ b/StabilityMatrix/ViewModels/LaunchViewModel.cs @@ -157,7 +157,10 @@ private void ToastNotificationManagerCompatOnOnActivated( basePackage.StartupComplete += RunningPackageOnStartupComplete; // Update shared folder links (in case library paths changed) - sharedFolders.UpdateLinksForPackage(basePackage, packagePath); + if (basePackage.SharedFolderStrategy is LinkedFolderSharedFolderStrategy) + sharedFolders.UpdateLinksForPackage(basePackage, packagePath); + else + await basePackage.SharedFolderStrategy.ExecuteAsync(basePackage); // Load user launch args from settings and convert to string var userArgs = settingsManager.GetLaunchArgs(activeInstall.Id);