From 536c5449d9eace34255091e4949edffdb765978f Mon Sep 17 00:00:00 2001 From: Ionite Date: Thu, 14 Dec 2023 05:13:45 -0500 Subject: [PATCH 01/28] Fix name --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ce75e9e5..48096ad61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 ## v2.7.1 ### Added -- Added Turkish UI language option, thanks to Progresor for the translation +- Added Turkish UI language option, thanks to Progesor for the translation ### Fixed - Fixed Inference Image to Image projects missing denoise strength setting From 2576571b1bd7a786193d30cecb1bb5234257d495 Mon Sep 17 00:00:00 2001 From: Ionite Date: Thu, 14 Dec 2023 05:14:00 -0500 Subject: [PATCH 02/28] Fix name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index daadd8f5c..a5f348dd1 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ Stability Matrix is now available in the following languages, thanks to our comm - 🇷🇺 Русский - aolko - 🇹🇷 Türkçe - - Progresor + - Progesor If you would like to contribute a translation, please create an issue or contact us on Discord. Include an email where we'll send an invite to our [POEditor](https://poeditor.com/) project. From 9bf950125865947b167a228e6a2da86a6be1d81d Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 16 Dec 2023 21:28:01 -0800 Subject: [PATCH 03/28] Fix UTF8 encoding including the BOM --- CHANGELOG.md | 4 +++ .../Models/FileInterfaces/FilePath.cs | 25 ++++++------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef2412c85..97b974e5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to Stability Matrix will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## v2.7.3 +### Fixed +- Fixed UnicodeDecodeError when using extra_model_paths.yaml in ComfyUI on certain locales + ## v2.7.2 ### Changed - Changed Symlink shared folder link targets for Automatic1111 and ComfyUI. From `ControlNet -> models/controlnet` to `ControlNet -> models/controlnet/ControlNet` and `T2IAdapter -> models/controlnet/T2IAdapter`. diff --git a/StabilityMatrix.Core/Models/FileInterfaces/FilePath.cs b/StabilityMatrix.Core/Models/FileInterfaces/FilePath.cs index a083fba68..494e3aa5e 100644 --- a/StabilityMatrix.Core/Models/FileInterfaces/FilePath.cs +++ b/StabilityMatrix.Core/Models/FileInterfaces/FilePath.cs @@ -113,12 +113,13 @@ public Task ReadAllTextAsync(CancellationToken ct = default) } /// Write text - public void WriteAllText(string text) => File.WriteAllText(FullPath, text, Encoding.UTF8); + public void WriteAllText(string text, Encoding? encoding = null) => + File.WriteAllText(FullPath, text, encoding ?? new UTF8Encoding(false)); /// Write text asynchronously - public Task WriteAllTextAsync(string text, CancellationToken ct = default) + public Task WriteAllTextAsync(string text, CancellationToken ct = default, Encoding? encoding = null) { - return File.WriteAllTextAsync(FullPath, text, Encoding.UTF8, ct); + return File.WriteAllTextAsync(FullPath, text, encoding ?? new UTF8Encoding(false), ct); } /// Read bytes @@ -144,19 +145,14 @@ public Task WriteAllBytesAsync(byte[] bytes, CancellationToken ct = default) /// public FilePath Rename(string fileName) { - if ( - Path.GetDirectoryName(FullPath) is { } directory - && !string.IsNullOrWhiteSpace(directory) - ) + if (Path.GetDirectoryName(FullPath) is { } directory && !string.IsNullOrWhiteSpace(directory)) { var target = Path.Combine(directory, fileName); Info.MoveTo(target, true); return new FilePath(target); } - throw new InvalidOperationException( - "Cannot rename a file path that is empty or has no directory" - ); + throw new InvalidOperationException("Cannot rename a file path that is empty or has no directory"); } /// @@ -193,10 +189,7 @@ public async Task MoveToAsync(FilePath destinationFile) /// Move the file to a target path with auto increment if the file already exists. /// /// The new path, possibly with incremented file name - public async Task MoveToWithIncrementAsync( - FilePath destinationFile, - int maxTries = 100 - ) + public async Task MoveToWithIncrementAsync(FilePath destinationFile, int maxTries = 100) { await Task.Yield(); @@ -214,9 +207,7 @@ public async Task MoveToWithIncrementAsync( ); } - throw new IOException( - $"Could not move file to {destinationFile} because it already exists." - ); + throw new IOException($"Could not move file to {destinationFile} because it already exists."); } /// From b5dc9639aaa6f76fd8e26e6d35b5db0e9d5518b5 Mon Sep 17 00:00:00 2001 From: Ionite Date: Sun, 17 Dec 2023 16:07:45 -0500 Subject: [PATCH 04/28] Handle exceptions in fetching memory info --- CHANGELOG.md | 1 + .../Settings/MainSettingsViewModel.cs | 6 +++-- .../Helper/HardwareInfo/HardwareHelper.cs | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97b974e5c..d7e7a250d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 ## v2.7.3 ### Fixed - Fixed UnicodeDecodeError when using extra_model_paths.yaml in ComfyUI on certain locales +- Fixed [#334](https://github.com/LykosAI/StabilityMatrix/issues/334) - Win32Exception if Settings are opened ## v2.7.2 ### Changed diff --git a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs index 837604b19..2b79de91d 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Settings/MainSettingsViewModel.cs @@ -212,7 +212,6 @@ public override void OnLoaded() base.OnLoaded(); hardwareInfoUpdateTimer.Start(); - OnHardwareInfoUpdateTimerTick(null, null!); } /// @@ -236,7 +235,10 @@ public override async Task OnLoadedAsync() private void OnHardwareInfoUpdateTimerTick(object? sender, EventArgs e) { - MemoryInfo = HardwareHelper.GetMemoryInfo(); + if (HardwareHelper.IsMemoryInfoAvailable && HardwareHelper.TryGetMemoryInfo(out var newMemoryInfo)) + { + MemoryInfo = newMemoryInfo; + } } partial void OnSelectedThemeChanged(string? value) diff --git a/StabilityMatrix.Core/Helper/HardwareInfo/HardwareHelper.cs b/StabilityMatrix.Core/Helper/HardwareInfo/HardwareHelper.cs index 5a8cec803..f356d59af 100644 --- a/StabilityMatrix.Core/Helper/HardwareInfo/HardwareHelper.cs +++ b/StabilityMatrix.Core/Helper/HardwareInfo/HardwareHelper.cs @@ -5,11 +5,14 @@ using System.Text.RegularExpressions; using Hardware.Info; using Microsoft.Win32; +using NLog; namespace StabilityMatrix.Core.Helper.HardwareInfo; public static partial class HardwareHelper { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static IReadOnlyList? cachedGpuInfos; private static readonly Lazy HardwareInfoLazy = new(() => new Hardware.Info.HardwareInfo()); @@ -149,6 +152,25 @@ public static bool HasAmdGpu() // Set DirectML for default if AMD and Windows public static bool PreferDirectML() => !HasNvidiaGpu() && HasAmdGpu() && Compat.IsWindows; + private static readonly Lazy IsMemoryInfoAvailableLazy = new(() => TryGetMemoryInfo(out _)); + public static bool IsMemoryInfoAvailable => IsMemoryInfoAvailableLazy.Value; + + public static bool TryGetMemoryInfo(out MemoryInfo memoryInfo) + { + try + { + memoryInfo = GetMemoryInfo(); + return true; + } + catch (Exception ex) + { + Logger.Warn(ex, "Failed to get memory info"); + + memoryInfo = default; + return false; + } + } + /// /// Gets the total and available physical memory in bytes. /// From fc555415642ea3b86c1136608d642c5329589b5f Mon Sep 17 00:00:00 2001 From: JT Date: Sun, 17 Dec 2023 21:00:06 -0800 Subject: [PATCH 05/28] fix SDXL clip vision download having same folder name as SD1.5 clip vision & add links to ipadapters/clip vision in comfy --- .../Assets/hf-packages.json | 2 +- .../Models/Packages/ComfyUI.cs | 33 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/StabilityMatrix.Avalonia/Assets/hf-packages.json b/StabilityMatrix.Avalonia/Assets/hf-packages.json index e103d80eb..498e9c38a 100644 --- a/StabilityMatrix.Avalonia/Assets/hf-packages.json +++ b/StabilityMatrix.Avalonia/Assets/hf-packages.json @@ -351,7 +351,7 @@ "config.json", "model.safetensors" ], - "Subfolder": "ip_adapter_sd_image_encoder", + "Subfolder": "ip_adapter_sdxl_image_encoder", "LicenseType": "Apache 2.0" }, { diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs index 1b221a62c..4815dc37f 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs @@ -51,6 +51,7 @@ IPrerequisiteHelper prerequisiteHelper [SharedFolderType.Diffusers] = new[] { "models/diffusers" }, [SharedFolderType.Lora] = new[] { "models/loras" }, [SharedFolderType.CLIP] = new[] { "models/clip" }, + [SharedFolderType.InvokeClipVision] = new[] { "models/clip_vision" }, [SharedFolderType.TextualInversion] = new[] { "models/embeddings" }, [SharedFolderType.VAE] = new[] { "models/vae" }, [SharedFolderType.ApproxVAE] = new[] { "models/vae_approx" }, @@ -58,7 +59,9 @@ IPrerequisiteHelper prerequisiteHelper [SharedFolderType.GLIGEN] = new[] { "models/gligen" }, [SharedFolderType.ESRGAN] = new[] { "models/upscale_models" }, [SharedFolderType.Hypernetwork] = new[] { "models/hypernetworks" }, - [SharedFolderType.IpAdapter] = new[] { "models/ipadapter" }, + [SharedFolderType.IpAdapter] = new[] { "models/ipadapter/base" }, + [SharedFolderType.InvokeIpAdapters15] = new[] { "models/ipadapter/sd15" }, + [SharedFolderType.InvokeIpAdaptersXl] = new[] { "models/ipadapter/sdxl" }, [SharedFolderType.T2IAdapter] = new[] { "models/controlnet/T2IAdapter" }, }; @@ -323,9 +326,16 @@ private async Task SetupModelFoldersConfig(DirectoryPath installDirectory) Path.Combine(modelsDir, "T2IAdapter") ); nodeValue.Children["clip"] = Path.Combine(modelsDir, "CLIP"); + nodeValue.Children["clip_vision"] = Path.Combine(modelsDir, "InvokeClipVision"); nodeValue.Children["diffusers"] = Path.Combine(modelsDir, "Diffusers"); nodeValue.Children["gligen"] = Path.Combine(modelsDir, "GLIGEN"); nodeValue.Children["vae_approx"] = Path.Combine(modelsDir, "ApproxVAE"); + nodeValue.Children["ipadapter"] = string.Join( + '\n', + Path.Combine(modelsDir, "IpAdapter"), + Path.Combine(modelsDir, "InvokeIpAdapters15"), + Path.Combine(modelsDir, "InvokeIpAdaptersXl") + ); } else { @@ -344,12 +354,29 @@ private async Task SetupModelFoldersConfig(DirectoryPath installDirectory) { "hypernetworks", Path.Combine(modelsDir, "Hypernetwork") }, { "controlnet", - string.Join('\n', Path.Combine(modelsDir, "ControlNet"), Path.Combine(modelsDir, "T2IAdapter")) + string.Join( + '\n', + Path.Combine(modelsDir, "ControlNet"), + Path.Combine(modelsDir, "T2IAdapter"), + Path.Combine(modelsDir, "IpAdapter"), + Path.Combine(modelsDir, "InvokeIpAdapters15"), + Path.Combine(modelsDir, "InvokeIpAdaptersXl") + ) }, { "clip", Path.Combine(modelsDir, "CLIP") }, + { "clip_vision", Path.Combine(modelsDir, "InvokeClipVision") }, { "diffusers", Path.Combine(modelsDir, "Diffusers") }, { "gligen", Path.Combine(modelsDir, "GLIGEN") }, - { "vae_approx", Path.Combine(modelsDir, "ApproxVAE") } + { "vae_approx", Path.Combine(modelsDir, "ApproxVAE") }, + { + "ipadapter", + string.Join( + '\n', + Path.Combine(modelsDir, "IpAdapter"), + Path.Combine(modelsDir, "InvokeIpAdapters15"), + Path.Combine(modelsDir, "InvokeIpAdaptersXl") + ) + } } ); } From 44223abe2187553499aed603a3a51b222dcc241f Mon Sep 17 00:00:00 2001 From: JT Date: Sun, 17 Dec 2023 21:02:14 -0800 Subject: [PATCH 06/28] chagenlog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97b974e5c..6f9d34038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). ## v2.7.3 +### Added +- Added missing IPAdapter and CLIP Vision folder links for ComfyUI ### Fixed - Fixed UnicodeDecodeError when using extra_model_paths.yaml in ComfyUI on certain locales +- Fixed SDXL CLIP Vision model directory name conflict ## v2.7.2 ### Changed From b2ea2e938f274fc9c137c3aca9e5912d7e8b479a Mon Sep 17 00:00:00 2001 From: JT Date: Sun, 17 Dec 2023 21:04:05 -0800 Subject: [PATCH 07/28] migration --- StabilityMatrix.Core/Models/Packages/ComfyUI.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs index 4815dc37f..f48aef0dc 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs @@ -272,6 +272,14 @@ private async Task SetupModelFoldersSymlink(DirectoryPath installDirectory) await controlnetOldLink.DeleteAsync(false).ConfigureAwait(false); } + // Migration for `IPAdapters` -> `ipadapter/base` and SD version folders + // If the original link exists, delete it first + if (installDirectory.JoinDir("models/ipadapter") is { IsSymbolicLink: true } ipAdapterOldLink) + { + Logger.Info("Migration: Removing old IPAdapter link {Path}", ipAdapterOldLink); + await ipAdapterOldLink.DeleteAsync(false).ConfigureAwait(false); + } + // Resume base setup await base.SetupModelFolders(installDirectory, SharedFolderMethod.Symlink).ConfigureAwait(false); } From efa4e1243d3320b6e01834e6b48aa8e9f5e8f981 Mon Sep 17 00:00:00 2001 From: JT Date: Sun, 17 Dec 2023 21:09:18 -0800 Subject: [PATCH 08/28] dont migrate actually --- StabilityMatrix.Core/Models/Packages/ComfyUI.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs index f48aef0dc..4815dc37f 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs @@ -272,14 +272,6 @@ private async Task SetupModelFoldersSymlink(DirectoryPath installDirectory) await controlnetOldLink.DeleteAsync(false).ConfigureAwait(false); } - // Migration for `IPAdapters` -> `ipadapter/base` and SD version folders - // If the original link exists, delete it first - if (installDirectory.JoinDir("models/ipadapter") is { IsSymbolicLink: true } ipAdapterOldLink) - { - Logger.Info("Migration: Removing old IPAdapter link {Path}", ipAdapterOldLink); - await ipAdapterOldLink.DeleteAsync(false).ConfigureAwait(false); - } - // Resume base setup await base.SetupModelFolders(installDirectory, SharedFolderMethod.Symlink).ConfigureAwait(false); } From a907914b297486a51d7c99b2eeb1d0255ecd03cf Mon Sep 17 00:00:00 2001 From: JT Date: Sun, 17 Dec 2023 21:10:50 -0800 Subject: [PATCH 09/28] remove ipadapter from controlnet section --- StabilityMatrix.Core/Models/Packages/ComfyUI.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs index 4815dc37f..0f425da36 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs @@ -354,14 +354,7 @@ private async Task SetupModelFoldersConfig(DirectoryPath installDirectory) { "hypernetworks", Path.Combine(modelsDir, "Hypernetwork") }, { "controlnet", - string.Join( - '\n', - Path.Combine(modelsDir, "ControlNet"), - Path.Combine(modelsDir, "T2IAdapter"), - Path.Combine(modelsDir, "IpAdapter"), - Path.Combine(modelsDir, "InvokeIpAdapters15"), - Path.Combine(modelsDir, "InvokeIpAdaptersXl") - ) + string.Join('\n', Path.Combine(modelsDir, "ControlNet"), Path.Combine(modelsDir, "T2IAdapter")) }, { "clip", Path.Combine(modelsDir, "CLIP") }, { "clip_vision", Path.Combine(modelsDir, "InvokeClipVision") }, From 81351d3a0fd5787e1580ea948f28b2341703e8c0 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 10:45:47 -0800 Subject: [PATCH 10/28] Fix denoise strength not being 1.0 for txt2img --- CHANGELOG.md | 4 ++ .../InferenceTextToImageViewModel.cs | 46 +++++++------------ 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 337cb2be0..0680559e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to Stability Matrix will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## v2.7.4 +### Fixed +- Fixed denoise strength in Inference Text to Image + ## v2.7.3 ### Added - Added missing IPAdapter and CLIP Vision folder links for ComfyUI diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs index 31ce98432..ccfb36677 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs @@ -26,9 +26,7 @@ namespace StabilityMatrix.Avalonia.ViewModels.Inference; [View(typeof(InferenceTextToImageView), IsPersistent = true)] [ManagedService] [Transient] -public class InferenceTextToImageViewModel - : InferenceGenerationViewModelBase, - IParametersLoadableState +public class InferenceTextToImageViewModel : InferenceGenerationViewModelBase, IParametersLoadableState { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); @@ -81,6 +79,7 @@ IModelIndexService modelIndexService samplerCard.IsCfgScaleEnabled = true; samplerCard.IsSamplerSelectionEnabled = true; samplerCard.IsSchedulerSelectionEnabled = true; + samplerCard.DenoiseStrength = 1.0d; }); PromptCardViewModel = vmFactory.Get(); @@ -162,22 +161,19 @@ protected override void BuildPrompt(BuildPromptEventArgs args) /// protected override IEnumerable GetInputImages() { - var samplerImages = SamplerCardViewModel.ModulesCardViewModel.Cards + var samplerImages = SamplerCardViewModel + .ModulesCardViewModel + .Cards .OfType() .SelectMany(m => m.GetInputImages()); - var moduleImages = ModulesCardViewModel.Cards - .OfType() - .SelectMany(m => m.GetInputImages()); + var moduleImages = ModulesCardViewModel.Cards.OfType().SelectMany(m => m.GetInputImages()); return samplerImages.Concat(moduleImages); } /// - protected override async Task GenerateImageImpl( - GenerateOverrides overrides, - CancellationToken cancellationToken - ) + protected override async Task GenerateImageImpl(GenerateOverrides overrides, CancellationToken cancellationToken) { // Validate the prompts if (!await PromptCardViewModel.ValidatePrompts()) @@ -205,11 +201,7 @@ CancellationToken cancellationToken { var seed = seedCard.Seed + i; - var buildPromptArgs = new BuildPromptEventArgs - { - Overrides = overrides, - SeedOverride = seed - }; + var buildPromptArgs = new BuildPromptEventArgs { Overrides = overrides, SeedOverride = seed }; BuildPrompt(buildPromptArgs); var generationArgs = new ImageGenerationEventArgs @@ -270,16 +262,12 @@ public override void LoadStateFromJsonObject(JsonObject state, int version) if (state.TryGetPropertyValue("HiresSampler", out var hiresSamplerState)) { - module - .GetCard() - .LoadStateFromJsonObject(hiresSamplerState!.AsObject()); + module.GetCard().LoadStateFromJsonObject(hiresSamplerState!.AsObject()); } if (state.TryGetPropertyValue("HiresUpscaler", out var hiresUpscalerState)) { - module - .GetCard() - .LoadStateFromJsonObject(hiresUpscalerState!.AsObject()); + module.GetCard().LoadStateFromJsonObject(hiresUpscalerState!.AsObject()); } }); @@ -289,17 +277,17 @@ public override void LoadStateFromJsonObject(JsonObject state, int version) if (state.TryGetPropertyValue("Upscaler", out var upscalerState)) { - module - .GetCard() - .LoadStateFromJsonObject(upscalerState!.AsObject()); + module.GetCard().LoadStateFromJsonObject(upscalerState!.AsObject()); } }); // Add FreeU to sampler - SamplerCardViewModel.ModulesCardViewModel.AddModule(module => - { - module.IsEnabled = state.GetPropertyValueOrDefault("IsFreeUEnabled"); - }); + SamplerCardViewModel + .ModulesCardViewModel + .AddModule(module => + { + module.IsEnabled = state.GetPropertyValueOrDefault("IsFreeUEnabled"); + }); } base.LoadStateFromJsonObject(state); From bd22ac51b324c9c384d705307b7a5df3d8d9bea0 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 10:54:22 -0800 Subject: [PATCH 11/28] watever --- .../Inference/InferenceTextToImageViewModel.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs index ccfb36677..7a3afdf0b 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs @@ -130,6 +130,11 @@ protected override void BuildPrompt(BuildPromptEventArgs args) _ => Convert.ToUInt64(SeedCardViewModel.Seed) }; + if (!SamplerCardViewModel.IsDenoiseStrengthEnabled) + { + SamplerCardViewModel.DenoiseStrength = 1.0d; + } + BatchSizeCardViewModel.ApplyStep(args); // Load models @@ -233,6 +238,11 @@ public void LoadStateFromParameters(GenerationParameters parameters) ModelCardViewModel.LoadStateFromParameters(parameters); SeedCardViewModel.Seed = Convert.ToInt64(parameters.Seed); + + if (Math.Abs(SamplerCardViewModel.DenoiseStrength - 1.0d) > 0.01d) + { + SamplerCardViewModel.DenoiseStrength = 1.0d; + } } /// From d646db150ccae70389f7792f25d5a5e0a4ad1c4d Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 11:17:35 -0800 Subject: [PATCH 12/28] Throw exceptions when out of free space instead of whatever the fk it does now --- .../InferenceTextToImageViewModel.cs | 5 - .../Inference/SamplerCardViewModel.cs | 2 + StabilityMatrix.Core/Helper/SystemInfo.cs | 40 ++++- .../Models/Packages/BaseGitPackage.cs | 138 ++++++------------ .../Services/DownloadService.cs | 108 ++++---------- .../Services/SettingsManager.cs | 6 + 6 files changed, 127 insertions(+), 172 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs index 7a3afdf0b..c51e540cd 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs @@ -130,11 +130,6 @@ protected override void BuildPrompt(BuildPromptEventArgs args) _ => Convert.ToUInt64(SeedCardViewModel.Seed) }; - if (!SamplerCardViewModel.IsDenoiseStrengthEnabled) - { - SamplerCardViewModel.DenoiseStrength = 1.0d; - } - BatchSizeCardViewModel.ApplyStep(args); // Load models diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs index 32640d8e1..5670bb940 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs @@ -115,6 +115,8 @@ public void ApplyStep(ModuleApplyStepEventArgs e) e.Builder.Connections.PrimarySize = new Size(Width, Height); } + DenoiseStrength = IsDenoiseStrengthEnabled ? DenoiseStrength : 1.0d; + // Provide temp values e.Temp.Conditioning = ( e.Builder.Connections.BaseConditioning!, diff --git a/StabilityMatrix.Core/Helper/SystemInfo.cs b/StabilityMatrix.Core/Helper/SystemInfo.cs index e8a006d0b..dd5fec1a6 100644 --- a/StabilityMatrix.Core/Helper/SystemInfo.cs +++ b/StabilityMatrix.Core/Helper/SystemInfo.cs @@ -1,9 +1,47 @@ using System.Runtime.InteropServices; +using NLog; namespace StabilityMatrix.Core.Helper; public static class SystemInfo { - [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")] + public const long Gigabyte = 1024 * 1024 * 1024; + public const long Megabyte = 1024 * 1024; + + [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")] public static extern bool ShouldUseDarkMode(); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool GetDiskFreeSpaceEx( + string lpDirectoryName, + out long lpFreeBytesAvailable, + out long lpTotalNumberOfBytes, + out long lpTotalNumberOfFreeBytes + ); + + public static long? GetDiskFreeSpaceBytes(string path) + { + long? freeBytes = null; + try + { + if (Compat.IsWindows) + { + if (GetDiskFreeSpaceEx(path, out var freeBytesOut, out var _, out var _)) + freeBytes = freeBytesOut; + } + + if (freeBytes == null) + { + var drive = new DriveInfo(path); + freeBytes = drive.AvailableFreeSpace; + } + } + catch (Exception e) + { + LogManager.GetCurrentClassLogger().Error(e); + } + + return freeBytes; + } } diff --git a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs index cb2a742c8..f0306a8d5 100644 --- a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs +++ b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs @@ -36,8 +36,7 @@ public abstract class BaseGitPackage : BasePackage public override string GithubUrl => $"https://github.com/{Author}/{Name}"; - public string DownloadLocation => - Path.Combine(SettingsManager.LibraryDir, "Packages", $"{Name}.zip"); + public string DownloadLocation => Path.Combine(SettingsManager.LibraryDir, "Packages", $"{Name}.zip"); protected string GetDownloadUrl(DownloadPackageVersionOptions versionOptions) { @@ -72,9 +71,7 @@ IPrerequisiteHelper prerequisiteHelper PrerequisiteHelper = prerequisiteHelper; } - public override async Task GetLatestVersion( - bool includePrerelease = false - ) + public override async Task GetLatestVersion(bool includePrerelease = false) { if (ShouldIgnoreReleases) { @@ -87,9 +84,7 @@ public override async Task GetLatestVersion( } var releases = await GithubApi.GetAllReleases(Author, Name).ConfigureAwait(false); - var latestRelease = includePrerelease - ? releases.First() - : releases.First(x => !x.Prerelease); + var latestRelease = includePrerelease ? releases.First() : releases.First(x => !x.Prerelease); return new DownloadPackageVersionOptions { @@ -99,11 +94,7 @@ public override async Task GetLatestVersion( }; } - public override Task?> GetAllCommits( - string branch, - int page = 1, - int perPage = 10 - ) + public override Task?> GetAllCommits(string branch, int page = 1, int perPage = 10) { return GithubApi.GetAllCommits(Author, Name, branch, page, perPage); } @@ -181,6 +172,14 @@ public override async Task DownloadPackage( IProgress? progress = null ) { + const long fiveGigs = 5 * SystemInfo.Gigabyte; + if (SystemInfo.GetDiskFreeSpaceBytes(installLocation) < fiveGigs) + { + throw new ApplicationException( + $"Not enough space to download {Name} to {installLocation}, need at least 5GB" + ); + } + await PrerequisiteHelper .RunGit( new[] @@ -223,10 +222,7 @@ protected Task UnzipPackage(string installLocation, IProgress? p zipDirName = entry.FullName; } - var folderPath = Path.Combine( - installLocation, - entry.FullName.Replace(zipDirName, string.Empty) - ); + var folderPath = Path.Combine(installLocation, entry.FullName.Replace(zipDirName, string.Empty)); Directory.CreateDirectory(folderPath); continue; } @@ -237,10 +233,7 @@ protected Task UnzipPackage(string installLocation, IProgress? p entry.ExtractToFile(destinationPath, true); progress?.Report( - new ProgressReport( - current: Convert.ToUInt64(currentEntry), - total: Convert.ToUInt64(totalEntries) - ) + new ProgressReport(current: Convert.ToUInt64(currentEntry), total: Convert.ToUInt64(totalEntries)) ); } @@ -264,16 +257,12 @@ public override async Task CheckForUpdates(InstalledPackage package) { if (currentVersion.IsReleaseMode) { - var latestVersion = await GetLatestVersion(currentVersion.IsPrerelease) - .ConfigureAwait(false); - UpdateAvailable = - latestVersion.VersionTag != currentVersion.InstalledReleaseVersion; + var latestVersion = await GetLatestVersion(currentVersion.IsPrerelease).ConfigureAwait(false); + UpdateAvailable = latestVersion.VersionTag != currentVersion.InstalledReleaseVersion; return UpdateAvailable; } - var allCommits = ( - await GetAllCommits(currentVersion.InstalledBranch!).ConfigureAwait(false) - )?.ToList(); + var allCommits = (await GetAllCommits(currentVersion.InstalledBranch!).ConfigureAwait(false))?.ToList(); if (allCommits == null || !allCommits.Any()) { @@ -305,18 +294,10 @@ public override async Task Update( if (!Directory.Exists(Path.Combine(installedPackage.FullPath!, ".git"))) { Logger.Info("not a git repo, initializing..."); - progress?.Report( - new ProgressReport(-1f, "Initializing git repo", isIndeterminate: true) - ); - await PrerequisiteHelper - .RunGit("init", onConsoleOutput, installedPackage.FullPath) - .ConfigureAwait(false); + progress?.Report(new ProgressReport(-1f, "Initializing git repo", isIndeterminate: true)); + await PrerequisiteHelper.RunGit("init", onConsoleOutput, installedPackage.FullPath).ConfigureAwait(false); await PrerequisiteHelper - .RunGit( - new[] { "remote", "add", "origin", GithubUrl }, - onConsoleOutput, - installedPackage.FullPath - ) + .RunGit(new[] { "remote", "add", "origin", GithubUrl }, onConsoleOutput, installedPackage.FullPath) .ConfigureAwait(false); } @@ -328,11 +309,7 @@ await PrerequisiteHelper .ConfigureAwait(false); progress?.Report( - new ProgressReport( - -1f, - $"Checking out {versionOptions.VersionTag}", - isIndeterminate: true - ) + new ProgressReport(-1f, $"Checking out {versionOptions.VersionTag}", isIndeterminate: true) ); await PrerequisiteHelper .RunGit( @@ -361,9 +338,7 @@ await InstallPackage( // fetch progress?.Report(new ProgressReport(-1f, "Fetching data...", isIndeterminate: true)); - await PrerequisiteHelper - .RunGit("fetch", onConsoleOutput, installedPackage.FullPath) - .ConfigureAwait(false); + await PrerequisiteHelper.RunGit("fetch", onConsoleOutput, installedPackage.FullPath).ConfigureAwait(false); if (versionOptions.IsLatest) { @@ -387,13 +362,7 @@ await PrerequisiteHelper progress?.Report(new ProgressReport(-1f, "Pulling changes...", isIndeterminate: true)); await PrerequisiteHelper .RunGit( - new[] - { - "pull", - "--autostash", - "origin", - installedPackage.Version.InstalledBranch! - }, + new[] { "pull", "--autostash", "origin", installedPackage.Version.InstalledBranch! }, onConsoleOutput, installedPackage.FullPath! ) @@ -436,51 +405,39 @@ await InstallPackage( }; } - public override Task SetupModelFolders( - DirectoryPath installDirectory, - SharedFolderMethod sharedFolderMethod - ) + public override Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) { if (sharedFolderMethod == SharedFolderMethod.Symlink && SharedFolders is { } folders) { - return StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage( - folders, - SettingsManager.ModelsDirectory, - installDirectory - ); + return StabilityMatrix + .Core + .Helper + .SharedFolders + .UpdateLinksForPackage(folders, SettingsManager.ModelsDirectory, installDirectory); } return Task.CompletedTask; } - public override Task UpdateModelFolders( - DirectoryPath installDirectory, - SharedFolderMethod sharedFolderMethod - ) + public override Task UpdateModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) { if (sharedFolderMethod == SharedFolderMethod.Symlink && SharedFolders is { } sharedFolders) { - return StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage( - sharedFolders, - SettingsManager.ModelsDirectory, - installDirectory - ); + return StabilityMatrix + .Core + .Helper + .SharedFolders + .UpdateLinksForPackage(sharedFolders, SettingsManager.ModelsDirectory, installDirectory); } return Task.CompletedTask; } - public override Task RemoveModelFolderLinks( - DirectoryPath installDirectory, - SharedFolderMethod sharedFolderMethod - ) + public override Task RemoveModelFolderLinks(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) { if (SharedFolders is not null && sharedFolderMethod == SharedFolderMethod.Symlink) { - StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage( - SharedFolders, - installDirectory - ); + StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage(SharedFolders, installDirectory); } return Task.CompletedTask; } @@ -489,12 +446,16 @@ public override Task SetupOutputFolderLinks(DirectoryPath installDirectory) { if (SharedOutputFolders is { } sharedOutputFolders) { - return StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage( - sharedOutputFolders, - SettingsManager.ImagesDirectory, - installDirectory, - recursiveDelete: true - ); + return StabilityMatrix + .Core + .Helper + .SharedFolders + .UpdateLinksForPackage( + sharedOutputFolders, + SettingsManager.ImagesDirectory, + installDirectory, + recursiveDelete: true + ); } return Task.CompletedTask; @@ -504,10 +465,7 @@ public override Task RemoveOutputFolderLinks(DirectoryPath installDirectory) { if (SharedOutputFolders is { } sharedOutputFolders) { - StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage( - sharedOutputFolders, - installDirectory - ); + StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage(sharedOutputFolders, installDirectory); } return Task.CompletedTask; } diff --git a/StabilityMatrix.Core/Services/DownloadService.cs b/StabilityMatrix.Core/Services/DownloadService.cs index ee6b03a42..8dc767143 100644 --- a/StabilityMatrix.Core/Services/DownloadService.cs +++ b/StabilityMatrix.Core/Services/DownloadService.cs @@ -39,18 +39,11 @@ public async Task DownloadToFileAsync( : httpClientFactory.CreateClient(httpClientName); client.Timeout = TimeSpan.FromMinutes(10); - client.DefaultRequestHeaders.UserAgent.Add( - new ProductInfoHeaderValue("StabilityMatrix", "2.0") - ); + client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("StabilityMatrix", "2.0")); await AddConditionalHeaders(client, new Uri(downloadUrl)).ConfigureAwait(false); - await using var file = new FileStream( - downloadPath, - FileMode.Create, - FileAccess.Write, - FileShare.None - ); + await using var file = new FileStream(downloadPath, FileMode.Create, FileAccess.Write, FileShare.None); long contentLength = 0; @@ -59,10 +52,7 @@ public async Task DownloadToFileAsync( .ConfigureAwait(false); contentLength = response.Content.Headers.ContentLength ?? 0; - var delays = Backoff.DecorrelatedJitterBackoffV2( - TimeSpan.FromMilliseconds(50), - retryCount: 3 - ); + var delays = Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(50), retryCount: 3); foreach (var delay in delays) { @@ -77,9 +67,19 @@ public async Task DownloadToFileAsync( } var isIndeterminate = contentLength == 0; - await using var stream = await response.Content - .ReadAsStreamAsync(cancellationToken) - .ConfigureAwait(false); + if (contentLength > 0) + { + // check free space + var freeSpace = SystemInfo.GetDiskFreeSpaceBytes(Path.GetDirectoryName(downloadPath)); + if (freeSpace < contentLength) + { + throw new ApplicationException( + $"Not enough free space to download file. Free: {freeSpace} bytes, Required: {contentLength} bytes" + ); + } + } + + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var totalBytesRead = 0L; var buffer = new byte[BufferSize]; while (true) @@ -87,8 +87,7 @@ public async Task DownloadToFileAsync( var bytesRead = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); if (bytesRead == 0) break; - await file.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken) - .ConfigureAwait(false); + await file.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); totalBytesRead += bytesRead; @@ -130,9 +129,7 @@ public async Task ResumeDownloadToFileAsync( using var noRedirectClient = httpClientFactory.CreateClient("DontFollowRedirects"); client.Timeout = TimeSpan.FromMinutes(10); - client.DefaultRequestHeaders.UserAgent.Add( - new ProductInfoHeaderValue("StabilityMatrix", "2.0") - ); + client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("StabilityMatrix", "2.0")); await AddConditionalHeaders(client, new Uri(downloadUrl)).ConfigureAwait(false); await AddConditionalHeaders(noRedirectClient, new Uri(downloadUrl)).ConfigureAwait(false); @@ -140,19 +137,11 @@ public async Task ResumeDownloadToFileAsync( // Create file if it doesn't exist if (!File.Exists(downloadPath)) { - logger.LogInformation( - "Resume file doesn't exist, creating file {DownloadPath}", - downloadPath - ); + logger.LogInformation("Resume file doesn't exist, creating file {DownloadPath}", downloadPath); File.Create(downloadPath).Close(); } - await using var file = new FileStream( - downloadPath, - FileMode.Append, - FileAccess.Write, - FileShare.None - ); + await using var file = new FileStream(downloadPath, FileMode.Append, FileAccess.Write, FileShare.None); // Remaining content length long remainingContentLength = 0; @@ -165,24 +154,13 @@ public async Task ResumeDownloadToFileAsync( noRedirectRequest.Headers.Range = new RangeHeaderValue(existingFileSize, null); HttpResponseMessage? response = null; - foreach ( - var delay in Backoff.DecorrelatedJitterBackoffV2( - TimeSpan.FromMilliseconds(50), - retryCount: 4 - ) - ) + foreach (var delay in Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(50), retryCount: 4)) { var noRedirectResponse = await noRedirectClient - .SendAsync( - noRedirectRequest, - HttpCompletionOption.ResponseHeadersRead, - cancellationToken - ) + .SendAsync(noRedirectRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); - if ( - (int)noRedirectResponse.StatusCode > 299 && (int)noRedirectResponse.StatusCode < 400 - ) + if ((int)noRedirectResponse.StatusCode > 299 && (int)noRedirectResponse.StatusCode < 400) { var redirectUrl = noRedirectResponse.Headers.Location?.ToString(); if (redirectUrl != null && redirectUrl.Contains("reason=download-auth")) @@ -197,16 +175,11 @@ var delay in Backoff.DecorrelatedJitterBackoffV2( redirectRequest.Headers.Range = new RangeHeaderValue(existingFileSize, null); response = await client - .SendAsync( - redirectRequest, - HttpCompletionOption.ResponseHeadersRead, - cancellationToken - ) + .SendAsync(redirectRequest, HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); remainingContentLength = response.Content.Headers.ContentLength ?? 0; - originalContentLength = - response.Content.Headers.ContentRange?.Length.GetValueOrDefault() ?? 0; + originalContentLength = response.Content.Headers.ContentRange?.Length.GetValueOrDefault() ?? 0; if (remainingContentLength > 0) break; @@ -222,9 +195,7 @@ var delay in Backoff.DecorrelatedJitterBackoffV2( var isIndeterminate = remainingContentLength == 0; - await using var stream = await response.Content - .ReadAsStreamAsync(cancellationToken) - .ConfigureAwait(false); + await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var totalBytesRead = 0L; var buffer = new byte[BufferSize]; while (true) @@ -234,8 +205,7 @@ var delay in Backoff.DecorrelatedJitterBackoffV2( var bytesRead = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); if (bytesRead == 0) break; - await file.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken) - .ConfigureAwait(false); + await file.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); totalBytesRead += bytesRead; @@ -274,20 +244,13 @@ public async Task GetFileSizeAsync( : httpClientFactory.CreateClient(httpClientName); client.Timeout = TimeSpan.FromMinutes(10); - client.DefaultRequestHeaders.UserAgent.Add( - new ProductInfoHeaderValue("StabilityMatrix", "2.0") - ); + client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("StabilityMatrix", "2.0")); await AddConditionalHeaders(client, new Uri(downloadUrl)).ConfigureAwait(false); var contentLength = 0L; - foreach ( - var delay in Backoff.DecorrelatedJitterBackoffV2( - TimeSpan.FromMilliseconds(50), - retryCount: 3 - ) - ) + foreach (var delay in Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromMilliseconds(50), retryCount: 3)) { var response = await client .GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken) @@ -308,9 +271,7 @@ var delay in Backoff.DecorrelatedJitterBackoffV2( { using var client = httpClientFactory.CreateClient(); client.Timeout = TimeSpan.FromSeconds(10); - client.DefaultRequestHeaders.UserAgent.Add( - new ProductInfoHeaderValue("StabilityMatrix", "2.0") - ); + client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("StabilityMatrix", "2.0")); await AddConditionalHeaders(client, new Uri(url)).ConfigureAwait(false); try { @@ -333,19 +294,14 @@ private async Task AddConditionalHeaders(HttpClient client, Uri url) if (url.Host.Equals("civitai.com", StringComparison.OrdinalIgnoreCase)) { // Add auth if we have it - if ( - await secretsManager.LoadAsync().ConfigureAwait(false) is { CivitApi: { } civitApi } - ) + if (await secretsManager.LoadAsync().ConfigureAwait(false) is { CivitApi: { } civitApi }) { logger.LogTrace( "Adding Civit auth header {Signature} for download {Url}", ObjectHash.GetStringSignature(civitApi.ApiToken), url ); - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( - "Bearer", - civitApi.ApiToken - ); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", civitApi.ApiToken); } } } diff --git a/StabilityMatrix.Core/Services/SettingsManager.cs b/StabilityMatrix.Core/Services/SettingsManager.cs index b70dc13d9..6498f3d17 100644 --- a/StabilityMatrix.Core/Services/SettingsManager.cs +++ b/StabilityMatrix.Core/Services/SettingsManager.cs @@ -650,6 +650,12 @@ protected virtual void SaveSettings() if (!isLoaded) return; + if (SystemInfo.GetDiskFreeSpaceBytes(SettingsPath) < 1024 * 1024) + { + Logger.Warn("Not enough disk space to save settings"); + return; + } + var jsonBytes = JsonSerializer.SerializeToUtf8Bytes(Settings, SettingsSerializerContext.Default.Settings); File.WriteAllBytes(SettingsPath, jsonBytes); From 346542f95380a9a6fd4495e63e50204a57a2848c Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 11:36:51 -0800 Subject: [PATCH 13/28] we pay per line of code or something idk --- StabilityMatrix.Core/Helper/SystemInfo.cs | 25 +++---------------- .../Models/Packages/BaseGitPackage.cs | 2 +- .../Services/DownloadService.cs | 6 +++-- .../Services/SettingsManager.cs | 2 +- 4 files changed, 9 insertions(+), 26 deletions(-) diff --git a/StabilityMatrix.Core/Helper/SystemInfo.cs b/StabilityMatrix.Core/Helper/SystemInfo.cs index dd5fec1a6..3e8a7d1ab 100644 --- a/StabilityMatrix.Core/Helper/SystemInfo.cs +++ b/StabilityMatrix.Core/Helper/SystemInfo.cs @@ -11,37 +11,18 @@ public static class SystemInfo [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")] public static extern bool ShouldUseDarkMode(); - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetDiskFreeSpaceEx( - string lpDirectoryName, - out long lpFreeBytesAvailable, - out long lpTotalNumberOfBytes, - out long lpTotalNumberOfFreeBytes - ); - public static long? GetDiskFreeSpaceBytes(string path) { - long? freeBytes = null; try { - if (Compat.IsWindows) - { - if (GetDiskFreeSpaceEx(path, out var freeBytesOut, out var _, out var _)) - freeBytes = freeBytesOut; - } - - if (freeBytes == null) - { - var drive = new DriveInfo(path); - freeBytes = drive.AvailableFreeSpace; - } + var drive = new DriveInfo(path); + return drive.AvailableFreeSpace; } catch (Exception e) { LogManager.GetCurrentClassLogger().Error(e); } - return freeBytes; + return null; } } diff --git a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs index f0306a8d5..89293dea6 100644 --- a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs +++ b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs @@ -173,7 +173,7 @@ public override async Task DownloadPackage( ) { const long fiveGigs = 5 * SystemInfo.Gigabyte; - if (SystemInfo.GetDiskFreeSpaceBytes(installLocation) < fiveGigs) + if (SystemInfo.GetDiskFreeSpaceBytes(installLocation) is < fiveGigs) { throw new ApplicationException( $"Not enough space to download {Name} to {installLocation}, need at least 5GB" diff --git a/StabilityMatrix.Core/Services/DownloadService.cs b/StabilityMatrix.Core/Services/DownloadService.cs index 8dc767143..ed4a5763f 100644 --- a/StabilityMatrix.Core/Services/DownloadService.cs +++ b/StabilityMatrix.Core/Services/DownloadService.cs @@ -70,8 +70,10 @@ public async Task DownloadToFileAsync( if (contentLength > 0) { // check free space - var freeSpace = SystemInfo.GetDiskFreeSpaceBytes(Path.GetDirectoryName(downloadPath)); - if (freeSpace < contentLength) + if ( + SystemInfo.GetDiskFreeSpaceBytes(Path.GetDirectoryName(downloadPath)) is { } freeSpace + && freeSpace < contentLength + ) { throw new ApplicationException( $"Not enough free space to download file. Free: {freeSpace} bytes, Required: {contentLength} bytes" diff --git a/StabilityMatrix.Core/Services/SettingsManager.cs b/StabilityMatrix.Core/Services/SettingsManager.cs index 6498f3d17..1ff8ba51a 100644 --- a/StabilityMatrix.Core/Services/SettingsManager.cs +++ b/StabilityMatrix.Core/Services/SettingsManager.cs @@ -650,7 +650,7 @@ protected virtual void SaveSettings() if (!isLoaded) return; - if (SystemInfo.GetDiskFreeSpaceBytes(SettingsPath) < 1024 * 1024) + if (SystemInfo.GetDiskFreeSpaceBytes(SettingsPath) is < 1 * SystemInfo.Megabyte) { Logger.Warn("Not enough disk space to save settings"); return; From 5494868af219555606bb1015f35e07cb7061c123 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 14:07:41 -0800 Subject: [PATCH 14/28] Show tooltip explaining why you cant import cuz your hard drive is full --- .../Dialogs/SelectModelVersionViewModel.cs | 51 ++++++++++++++----- .../Dialogs/SelectModelVersionDialog.axaml | 3 ++ StabilityMatrix.Core/Helper/SystemInfo.cs | 4 +- .../Models/Packages/BaseGitPackage.cs | 2 +- .../Services/SettingsManager.cs | 2 +- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs index c3f109317..61221efab 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/SelectModelVersionViewModel.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; +using System.IO; using System.Linq; using Avalonia.Media.Imaging; using Avalonia.Threading; @@ -8,6 +10,8 @@ using StabilityMatrix.Avalonia.Models; using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Core.Attributes; +using StabilityMatrix.Core.Helper; +using StabilityMatrix.Core.Models.FileInterfaces; using StabilityMatrix.Core.Services; namespace StabilityMatrix.Avalonia.ViewModels.Dialogs; @@ -49,12 +53,12 @@ public partial class SelectModelVersionViewModel : ContentDialogViewModelBase [NotifyPropertyChangedFor(nameof(DisplayedPageNumber))] private int selectedImageIndex; + [ObservableProperty] + private string importTooltip = string.Empty; + public int DisplayedPageNumber => SelectedImageIndex + 1; - public SelectModelVersionViewModel( - ISettingsManager settingsManager, - IDownloadService downloadService - ) + public SelectModelVersionViewModel(ISettingsManager settingsManager, IDownloadService downloadService) { this.settingsManager = settingsManager; this.downloadService = downloadService; @@ -70,7 +74,9 @@ partial void OnSelectedVersionViewModelChanged(ModelVersionViewModel? value) { var nsfwEnabled = settingsManager.Settings.ModelBrowserNsfwEnabled; var allImages = value - ?.ModelVersion?.Images?.Where(img => nsfwEnabled || img.Nsfw == "None") + ?.ModelVersion + ?.Images + ?.Where(img => nsfwEnabled || img.Nsfw == "None") ?.Select(x => new ImageSource(x.Url)) .ToList(); @@ -84,18 +90,35 @@ partial void OnSelectedVersionViewModelChanged(ModelVersionViewModel? value) CanGoToNextImage = allImages.Count > 1; } - Dispatcher.UIThread.Post(() => - { - CanGoToPreviousImage = false; - SelectedFile = SelectedVersionViewModel?.CivitFileViewModels.FirstOrDefault(); - ImageUrls = new ObservableCollection(allImages); - SelectedImageIndex = 0; - }); + Dispatcher + .UIThread + .Post(() => + { + CanGoToPreviousImage = false; + SelectedFile = SelectedVersionViewModel?.CivitFileViewModels.FirstOrDefault(); + ImageUrls = new ObservableCollection(allImages); + SelectedImageIndex = 0; + }); } partial void OnSelectedFileChanged(CivitFileViewModel? value) { - IsImportEnabled = value?.CivitFile != null; + var canImport = true; + if (settingsManager.IsLibraryDirSet) + { + var fileSizeBytes = value?.CivitFile.SizeKb * 1024; + var freeSizeBytes = SystemInfo.GetDiskFreeSpaceBytes(settingsManager.ModelsDirectory); + canImport = fileSizeBytes < freeSizeBytes; + ImportTooltip = canImport + ? $"Free space after download: {Size.FormatBytes(Convert.ToUInt64(freeSizeBytes - fileSizeBytes))}" + : $"Not enough space on disk. Need {Size.FormatBytes(Convert.ToUInt64(fileSizeBytes))} but only have {Size.FormatBytes(Convert.ToUInt64(freeSizeBytes))}"; + } + else + { + ImportTooltip = "Please set the library directory in settings"; + } + + IsImportEnabled = value?.CivitFile != null && canImport; } public void Cancel() diff --git a/StabilityMatrix.Avalonia/Views/Dialogs/SelectModelVersionDialog.axaml b/StabilityMatrix.Avalonia/Views/Dialogs/SelectModelVersionDialog.axaml index 4fb5151d9..632c8fd45 100644 --- a/StabilityMatrix.Avalonia/Views/Dialogs/SelectModelVersionDialog.axaml +++ b/StabilityMatrix.Avalonia/Views/Dialogs/SelectModelVersionDialog.axaml @@ -11,6 +11,7 @@ xmlns:models="clr-namespace:StabilityMatrix.Avalonia.Models" xmlns:avalonia="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia" xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages" + xmlns:markupExtensions="clr-namespace:StabilityMatrix.Avalonia.MarkupExtensions" d:DataContext="{x:Static designData:DesignData.SelectModelVersionViewModel}" x:Class="StabilityMatrix.Avalonia.Views.Dialogs.SelectModelVersionDialog"> @@ -190,6 +191,8 @@ Content="{x:Static lang:Resources.Action_Import}" Command="{Binding Import}" IsEnabled="{Binding IsImportEnabled}" + ToolTip.Tip="{Binding ImportTooltip}" + markupExtensions:ShowDisabledTooltipExtension.ShowOnDisabled="True" Classes="accent" /> diff --git a/StabilityMatrix.Core/Helper/SystemInfo.cs b/StabilityMatrix.Core/Helper/SystemInfo.cs index 3e8a7d1ab..935a087bf 100644 --- a/StabilityMatrix.Core/Helper/SystemInfo.cs +++ b/StabilityMatrix.Core/Helper/SystemInfo.cs @@ -5,8 +5,8 @@ namespace StabilityMatrix.Core.Helper; public static class SystemInfo { - public const long Gigabyte = 1024 * 1024 * 1024; - public const long Megabyte = 1024 * 1024; + public const long Gibibyte = 1024 * 1024 * 1024; + public const long Mebibyte = 1024 * 1024; [DllImport("UXTheme.dll", SetLastError = true, EntryPoint = "#138")] public static extern bool ShouldUseDarkMode(); diff --git a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs index 89293dea6..bd09057c7 100644 --- a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs +++ b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs @@ -172,7 +172,7 @@ public override async Task DownloadPackage( IProgress? progress = null ) { - const long fiveGigs = 5 * SystemInfo.Gigabyte; + const long fiveGigs = 5 * SystemInfo.Gibibyte; if (SystemInfo.GetDiskFreeSpaceBytes(installLocation) is < fiveGigs) { throw new ApplicationException( diff --git a/StabilityMatrix.Core/Services/SettingsManager.cs b/StabilityMatrix.Core/Services/SettingsManager.cs index 1ff8ba51a..d36314cc0 100644 --- a/StabilityMatrix.Core/Services/SettingsManager.cs +++ b/StabilityMatrix.Core/Services/SettingsManager.cs @@ -650,7 +650,7 @@ protected virtual void SaveSettings() if (!isLoaded) return; - if (SystemInfo.GetDiskFreeSpaceBytes(SettingsPath) is < 1 * SystemInfo.Megabyte) + if (SystemInfo.GetDiskFreeSpaceBytes(SettingsPath) is < 1 * SystemInfo.Mebibyte) { Logger.Warn("Not enough disk space to save settings"); return; From 1998ca2bd064a2428f352806bc46e6b5a2639a32 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 14:08:58 -0800 Subject: [PATCH 15/28] chagenlog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0680559e0..7b3be855c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). ## v2.7.4 +### Changed +- Improved low disk space handling ### Fixed -- Fixed denoise strength in Inference Text to Image +- Fixed denoise strength in Inference Text to Image ## v2.7.3 ### Added From a0a26f63d84a69fedd511f3e28fd3f00daff4db6 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 14:15:01 -0800 Subject: [PATCH 16/28] idk --- .../ViewModels/Inference/SamplerCardViewModel.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs index 5670bb940..32640d8e1 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/SamplerCardViewModel.cs @@ -115,8 +115,6 @@ public void ApplyStep(ModuleApplyStepEventArgs e) e.Builder.Connections.PrimarySize = new Size(Width, Height); } - DenoiseStrength = IsDenoiseStrengthEnabled ? DenoiseStrength : 1.0d; - // Provide temp values e.Temp.Conditioning = ( e.Builder.Connections.BaseConditioning!, From d0be16beb0328fd6683616b730b1b04d675fa499 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 15:54:17 -0800 Subject: [PATCH 17/28] Fix IPAdapters link recursion & actually clean up configs/symlinks when switching to the other --- CHANGELOG.md | 2 + .../PackageManager/PackageCardViewModel.cs | 93 +++++-------------- .../Models/Packages/ComfyUI.cs | 20 ++++ 3 files changed, 46 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b3be855c..a94c57388 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 - Improved low disk space handling ### Fixed - Fixed denoise strength in Inference Text to Image +- Fixed PathTooLongException for IPAdapter folders when using ComfyUI in Symlink mode +- Fixed configs and symlinks not being cleaned up when switched to the opposite mode ## v2.7.3 ### Added diff --git a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs index 182280de1..e6d1c6a8c 100644 --- a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs @@ -97,10 +97,7 @@ partial void OnPackageChanged(InstalledPackage? value) if (string.IsNullOrWhiteSpace(value?.PackageName)) return; - if ( - value.PackageName == UnknownPackage.Key - || packageFactory.FindPackageByName(value.PackageName) is null - ) + if (value.PackageName == UnknownPackage.Key || packageFactory.FindPackageByName(value.PackageName) is null) { IsUnknownPackage = true; CardImageSource = ""; @@ -114,11 +111,9 @@ partial void OnPackageChanged(InstalledPackage? value) CardImageSource = basePackage?.PreviewImageUri.ToString() ?? Assets.NoImage.ToString(); InstalledVersion = value.Version?.DisplayVersion ?? "Unknown"; CanUseConfigMethod = - basePackage?.AvailableSharedFolderMethods.Contains(SharedFolderMethod.Configuration) - ?? false; + basePackage?.AvailableSharedFolderMethods.Contains(SharedFolderMethod.Configuration) ?? false; CanUseSymlinkMethod = - basePackage?.AvailableSharedFolderMethods.Contains(SharedFolderMethod.Symlink) - ?? false; + basePackage?.AvailableSharedFolderMethods.Contains(SharedFolderMethod.Symlink) ?? false; UseSharedOutput = Package?.UseSharedOutputFolder ?? false; CanUseSharedOutput = basePackage?.SharedOutputFolders != null; } @@ -126,22 +121,13 @@ partial void OnPackageChanged(InstalledPackage? value) public override async Task OnLoadedAsync() { - if ( - Design.IsDesignMode - || !settingsManager.IsLibraryDirSet - || Package is not { } currentPackage - ) + if (Design.IsDesignMode || !settingsManager.IsLibraryDirSet || Package is not { } currentPackage) return; - if ( - packageFactory.FindPackageByName(currentPackage.PackageName) - is { } basePackage - and not UnknownPackage - ) + if (packageFactory.FindPackageByName(currentPackage.PackageName) is { } basePackage and not UnknownPackage) { // Migrate old packages with null preferred shared folder method - currentPackage.PreferredSharedFolderMethod ??= - basePackage.RecommendedSharedFolderMethod; + currentPackage.PreferredSharedFolderMethod ??= basePackage.RecommendedSharedFolderMethod; switch (currentPackage.PreferredSharedFolderMethod) { @@ -199,18 +185,11 @@ public async Task Uninstall() var packagePath = new DirectoryPath(settingsManager.LibraryDir, Package.LibraryPath); var deleteTask = packagePath.DeleteVerboseAsync(logger); - var taskResult = await notificationService.TryAsync( - deleteTask, - Resources.Text_SomeFilesCouldNotBeDeleted - ); + var taskResult = await notificationService.TryAsync(deleteTask, Resources.Text_SomeFilesCouldNotBeDeleted); if (taskResult.IsSuccessful) { notificationService.Show( - new Notification( - Resources.Label_PackageUninstalled, - Package.DisplayName, - NotificationType.Success - ) + new Notification(Resources.Label_PackageUninstalled, Package.DisplayName, NotificationType.Success) ); if (!IsUnknownPackage) @@ -238,10 +217,7 @@ public async Task Update() var basePackage = packageFactory[Package.PackageName!]; if (basePackage == null) { - logger.LogWarning( - "Could not find package {SelectedPackagePackageName}", - Package.PackageName - ); + logger.LogWarning("Could not find package {SelectedPackagePackageName}", Package.PackageName); notificationService.Show( Resources.Label_InvalidPackageType, Package.PackageName.ToRepr(), @@ -278,12 +254,7 @@ public async Task Update() versionOptions.CommitHash = latest.Sha; } - var updatePackageStep = new UpdatePackageStep( - settingsManager, - Package, - versionOptions, - basePackage - ); + var updatePackageStep = new UpdatePackageStep(settingsManager, Package, versionOptions, basePackage); var steps = new List { updatePackageStep }; EventManager.Instance.OnPackageInstallProgressAdded(runner); @@ -321,9 +292,7 @@ public async Task Import() var viewModel = vmFactory.Get(vm => { - vm.PackagePath = new DirectoryPath( - Package?.FullPath ?? throw new InvalidOperationException() - ); + vm.PackagePath = new DirectoryPath(Package?.FullPath ?? throw new InvalidOperationException()); }); var dialog = new TaskDialog @@ -349,9 +318,7 @@ public async Task Import() await using (new MinimumDelay(200, 300)) { - var result = await notificationService.TryAsync( - viewModel.AddPackageWithCurrentInputs() - ); + var result = await notificationService.TryAsync(viewModel.AddPackageWithCurrentInputs()); if (result.IsSuccessful) { EventManager.Instance.OnInstalledPackagesChanged(); @@ -398,10 +365,7 @@ private void OpenOnGitHub() var basePackage = packageFactory[Package.PackageName!]; if (basePackage == null) { - logger.LogWarning( - "Could not find package {SelectedPackagePackageName}", - Package.PackageName - ); + logger.LogWarning("Could not find package {SelectedPackagePackageName}", Package.PackageName); return; } @@ -417,9 +381,7 @@ private async Task HasUpdate() if (basePackage == null) return false; - var canCheckUpdate = - Package.LastUpdateCheck == null - || Package.LastUpdateCheck < DateTime.Now.AddMinutes(-15); + var canCheckUpdate = Package.LastUpdateCheck == null || Package.LastUpdateCheck < DateTime.Now.AddMinutes(-15); if (!canCheckUpdate) { @@ -482,13 +444,6 @@ partial void OnIsSharedModelSymlinkChanged(bool oldValue, bool newValue) if (newValue != Package!.PreferredSharedFolderMethod is SharedFolderMethod.Symlink) { - if (!newValue) - { - var basePackage = packageFactory[Package!.PackageName!]; - basePackage!.RemoveModelFolderLinks(Package.FullPath!, SharedFolderMethod.Symlink); - return; - } - using var st = settingsManager.BeginTransaction(); Package.PreferredSharedFolderMethod = SharedFolderMethod.Symlink; } @@ -498,6 +453,11 @@ partial void OnIsSharedModelSymlinkChanged(bool oldValue, bool newValue) IsSharedModelConfig = false; IsSharedModelDisabled = false; } + else + { + var basePackage = packageFactory[Package!.PackageName!]; + basePackage!.RemoveModelFolderLinks(Package.FullPath!, SharedFolderMethod.Symlink); + } } partial void OnIsSharedModelConfigChanged(bool oldValue, bool newValue) @@ -507,16 +467,6 @@ partial void OnIsSharedModelConfigChanged(bool oldValue, bool newValue) if (newValue != Package!.PreferredSharedFolderMethod is SharedFolderMethod.Configuration) { - if (!newValue) - { - var basePackage = packageFactory[Package!.PackageName!]; - basePackage!.RemoveModelFolderLinks( - Package.FullPath!, - SharedFolderMethod.Configuration - ); - return; - } - using var st = settingsManager.BeginTransaction(); Package.PreferredSharedFolderMethod = SharedFolderMethod.Configuration; } @@ -526,6 +476,11 @@ partial void OnIsSharedModelConfigChanged(bool oldValue, bool newValue) IsSharedModelSymlink = false; IsSharedModelDisabled = false; } + else + { + var basePackage = packageFactory[Package!.PackageName!]; + basePackage!.RemoveModelFolderLinks(Package.FullPath!, SharedFolderMethod.Configuration); + } } partial void OnIsSharedModelDisabledChanged(bool value) diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs index 0f425da36..5341da8b5 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs @@ -272,6 +272,26 @@ private async Task SetupModelFoldersSymlink(DirectoryPath installDirectory) await controlnetOldLink.DeleteAsync(false).ConfigureAwait(false); } + // and also ipadapter links + if (installDirectory.JoinDir("models/ipadapter") is { IsSymbolicLink: true } oldIpAdapterLink) + { + Logger.Info("Migration: Removing old ipadapter link {Path}", oldIpAdapterLink); + await oldIpAdapterLink.DeleteAsync(false).ConfigureAwait(false); + } + + // also fix broken links in models dir + var modelsDir = new DirectoryPath(settingsManager.ModelsDirectory); + string[] links = ["base", "sd15", "sdxl"]; + foreach (var link in links) + { + var oldLink = modelsDir.JoinDir($"IpAdapter{Path.DirectorySeparatorChar}{link}"); + if (!oldLink.IsSymbolicLink) + continue; + + Logger.Info("Fixing broken IPadapter links {Path}", oldLink); + await oldLink.DeleteAsync(false).ConfigureAwait(false); + } + // Resume base setup await base.SetupModelFolders(installDirectory, SharedFolderMethod.Symlink).ConfigureAwait(false); } From db929e12d5f298ab8d910adbe4ca94bae487b037 Mon Sep 17 00:00:00 2001 From: Ionite Date: Mon, 18 Dec 2023 20:58:55 -0500 Subject: [PATCH 18/28] Move parent link remove to SharedFolders --- StabilityMatrix.Core/Helper/SharedFolders.cs | 37 ++++++++++--------- .../Models/Packages/A3WebUI.cs | 15 +++++--- .../Models/Packages/ComfyUI.cs | 21 ++--------- 3 files changed, 32 insertions(+), 41 deletions(-) diff --git a/StabilityMatrix.Core/Helper/SharedFolders.cs b/StabilityMatrix.Core/Helper/SharedFolders.cs index 2e2f2115b..33fbc9141 100644 --- a/StabilityMatrix.Core/Helper/SharedFolders.cs +++ b/StabilityMatrix.Core/Helper/SharedFolders.cs @@ -35,7 +35,9 @@ private static void CreateLinkOrJunction(string junctionDir, string targetDir, b else { // Create parent directory if it doesn't exist, since CreateSymbolicLink doesn't seem to - new DirectoryPath(junctionDir).Parent?.Create(); + new DirectoryPath(junctionDir) + .Parent + ?.Create(); Directory.CreateSymbolicLink(junctionDir, targetDir); } } @@ -70,9 +72,7 @@ public static async Task CreateOrUpdateLink( // If link is already the same, just skip if (destinationDir.Info.LinkTarget == sourceDir) { - Logger.Info( - $"Skipped updating matching folder link ({destinationDir} -> ({sourceDir})" - ); + Logger.Info($"Skipped updating matching folder link ({destinationDir} -> ({sourceDir})"); return; } @@ -113,9 +113,7 @@ public void SetupLinksForPackage(BasePackage basePackage, DirectoryPath installD var sharedFolders = basePackage.SharedFolders; if (sharedFolders == null) return; - UpdateLinksForPackage(sharedFolders, modelsDirectory, installDirectory) - .GetAwaiter() - .GetResult(); + UpdateLinksForPackage(sharedFolders, modelsDirectory, installDirectory).GetAwaiter().GetResult(); } /// @@ -137,11 +135,18 @@ public static async Task UpdateLinksForPackage( var sourceDir = new DirectoryPath(modelsDirectory, folderType.GetStringValue()); var destinationDir = installDirectory.JoinDir(relativePath); - await CreateOrUpdateLink( - sourceDir, - destinationDir, - recursiveDelete: recursiveDelete - ) + // Check and remove destinationDir parent if it's a link + if (destinationDir.Parent is { IsSymbolicLink: true } parentLink) + { + Logger.Info("Deleting parent junction at target {Path}", parentLink.ToString()); + + await parentLink.DeleteAsync(false).ConfigureAwait(false); + + // Recreate + parentLink.Create(); + } + + await CreateOrUpdateLink(sourceDir, destinationDir, recursiveDelete: recursiveDelete) .ConfigureAwait(false); } } @@ -189,12 +194,8 @@ public void RemoveLinksForAllPackages() } var sharedFolderMethod = - package.PreferredSharedFolderMethod - ?? basePackage.RecommendedSharedFolderMethod; - basePackage - .RemoveModelFolderLinks(package.FullPath, sharedFolderMethod) - .GetAwaiter() - .GetResult(); + package.PreferredSharedFolderMethod ?? basePackage.RecommendedSharedFolderMethod; + basePackage.RemoveModelFolderLinks(package.FullPath, sharedFolderMethod).GetAwaiter().GetResult(); } catch (Exception e) { diff --git a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs index 6f3efd8d2..4ed7d07de 100644 --- a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs +++ b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs @@ -271,12 +271,17 @@ void HandleConsoleOutput(ProcessOutput s) /// public override async Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) { - // Migration for `controlnet` -> `controlnet/ControlNet` and `controlnet/T2IAdapter` - // If the original link exists, delete it first - if (installDirectory.JoinDir("models/controlnet") is { IsSymbolicLink: true } controlnetOldLink) + // fix duplicate links in models dir + var modelsDir = new DirectoryPath(settingsManager.ModelsDirectory); + string[] links = ["ControlNet"]; + foreach (var link in links) { - Logger.Info("Migration: Removing old controlnet link {Path}", controlnetOldLink); - await controlnetOldLink.DeleteAsync(false).ConfigureAwait(false); + var oldLink = modelsDir.JoinDir("controlnet", link); + if (!oldLink.IsSymbolicLink) + continue; + + Logger.Info("Removing duplicate junctions in {Path}", oldLink.ToString()); + await oldLink.DeleteAsync(false).ConfigureAwait(false); } // Resume base setup diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs index 5341da8b5..b606ad038 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs @@ -264,31 +264,16 @@ public override Task RemoveModelFolderLinks(DirectoryPath installDirectory, Shar private async Task SetupModelFoldersSymlink(DirectoryPath installDirectory) { - // Migration for `controlnet` -> `controlnet/ControlNet` and `controlnet/T2IAdapter` - // If the original link exists, delete it first - if (installDirectory.JoinDir("models/controlnet") is { IsSymbolicLink: true } controlnetOldLink) - { - Logger.Info("Migration: Removing old controlnet link {Path}", controlnetOldLink); - await controlnetOldLink.DeleteAsync(false).ConfigureAwait(false); - } - - // and also ipadapter links - if (installDirectory.JoinDir("models/ipadapter") is { IsSymbolicLink: true } oldIpAdapterLink) - { - Logger.Info("Migration: Removing old ipadapter link {Path}", oldIpAdapterLink); - await oldIpAdapterLink.DeleteAsync(false).ConfigureAwait(false); - } - - // also fix broken links in models dir + // fix duplicate links in models dir var modelsDir = new DirectoryPath(settingsManager.ModelsDirectory); string[] links = ["base", "sd15", "sdxl"]; foreach (var link in links) { - var oldLink = modelsDir.JoinDir($"IpAdapter{Path.DirectorySeparatorChar}{link}"); + var oldLink = modelsDir.JoinDir("ipadapter", link); if (!oldLink.IsSymbolicLink) continue; - Logger.Info("Fixing broken IPadapter links {Path}", oldLink); + Logger.Info("Removing duplicate junctions in {Path}", oldLink.ToString()); await oldLink.DeleteAsync(false).ConfigureAwait(false); } From feb1bf3bcbc66cc2255a8748012b8580a2ae9819 Mon Sep 17 00:00:00 2001 From: Ionite Date: Mon, 18 Dec 2023 21:21:00 -0500 Subject: [PATCH 19/28] Move duplicate path fixes to BaseGitPackage --- .../Models/Packages/A3WebUI.cs | 24 --------- .../Models/Packages/BaseGitPackage.cs | 49 ++++++++++++------- .../Models/Packages/ComfyUI.cs | 24 +-------- 3 files changed, 32 insertions(+), 65 deletions(-) diff --git a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs index 4ed7d07de..c26f52b5e 100644 --- a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs +++ b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs @@ -267,28 +267,4 @@ void HandleConsoleOutput(ProcessOutput s) VenvRunner.RunDetached(args.TrimEnd(), HandleConsoleOutput, OnExit); } - - /// - public override async Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) - { - // fix duplicate links in models dir - var modelsDir = new DirectoryPath(settingsManager.ModelsDirectory); - string[] links = ["ControlNet"]; - foreach (var link in links) - { - var oldLink = modelsDir.JoinDir("controlnet", link); - if (!oldLink.IsSymbolicLink) - continue; - - Logger.Info("Removing duplicate junctions in {Path}", oldLink.ToString()); - await oldLink.DeleteAsync(false).ConfigureAwait(false); - } - - // Resume base setup - await base.SetupModelFolders(installDirectory, sharedFolderMethod).ConfigureAwait(false); - } - - /// - public override Task UpdateModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) => - SetupModelFolders(installDirectory, sharedFolderMethod); } diff --git a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs index bd09057c7..a84f93c78 100644 --- a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs +++ b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs @@ -405,34 +405,47 @@ await InstallPackage( }; } - public override Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) + public override async Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) { - if (sharedFolderMethod == SharedFolderMethod.Symlink && SharedFolders is { } folders) + if (sharedFolderMethod != SharedFolderMethod.Symlink || SharedFolders is not { } sharedFolders) { - return StabilityMatrix - .Core - .Helper - .SharedFolders - .UpdateLinksForPackage(folders, SettingsManager.ModelsDirectory, installDirectory); + return; } - return Task.CompletedTask; - } + // fix duplicate links in models dir + // see https://github.com/LykosAI/StabilityMatrix/issues/338 + var modelsDir = new DirectoryPath(SettingsManager.ModelsDirectory); - public override Task UpdateModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) - { - if (sharedFolderMethod == SharedFolderMethod.Symlink && SharedFolders is { } sharedFolders) + string[] duplicatePaths = + [ + Path.Combine("ControlNet", "ControlNet"), + Path.Combine("IPAdapter", "base"), + Path.Combine("IPAdapter", "sd15"), + Path.Combine("IPAdapter", "sdxl") + ]; + + foreach (var duplicatePath in duplicatePaths) { - return StabilityMatrix - .Core - .Helper - .SharedFolders - .UpdateLinksForPackage(sharedFolders, SettingsManager.ModelsDirectory, installDirectory); + var linkDir = modelsDir.JoinDir(duplicatePath); + if (!linkDir.IsSymbolicLink) + continue; + + Logger.Info("Removing duplicate junction at {Path}", linkDir.ToString()); + + await linkDir.DeleteAsync(false).ConfigureAwait(false); } - return Task.CompletedTask; + await StabilityMatrix + .Core + .Helper + .SharedFolders + .UpdateLinksForPackage(sharedFolders, SettingsManager.ModelsDirectory, installDirectory) + .ConfigureAwait(false); } + public override Task UpdateModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) => + SetupModelFolders(installDirectory, sharedFolderMethod); + public override Task RemoveModelFolderLinks(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) { if (SharedFolders is not null && sharedFolderMethod == SharedFolderMethod.Symlink) diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs index b606ad038..81a415c4a 100644 --- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs +++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs @@ -242,15 +242,12 @@ void HandleConsoleOutput(ProcessOutput s) public override Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) => sharedFolderMethod switch { - SharedFolderMethod.Symlink => SetupModelFoldersSymlink(installDirectory), + SharedFolderMethod.Symlink => base.SetupModelFolders(installDirectory, SharedFolderMethod.Symlink), SharedFolderMethod.Configuration => SetupModelFoldersConfig(installDirectory), SharedFolderMethod.None => Task.CompletedTask, _ => throw new ArgumentOutOfRangeException(nameof(sharedFolderMethod), sharedFolderMethod, null) }; - public override Task UpdateModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) => - SetupModelFolders(installDirectory, sharedFolderMethod); - public override Task RemoveModelFolderLinks(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) { return sharedFolderMethod switch @@ -262,25 +259,6 @@ public override Task RemoveModelFolderLinks(DirectoryPath installDirectory, Shar }; } - private async Task SetupModelFoldersSymlink(DirectoryPath installDirectory) - { - // fix duplicate links in models dir - var modelsDir = new DirectoryPath(settingsManager.ModelsDirectory); - string[] links = ["base", "sd15", "sdxl"]; - foreach (var link in links) - { - var oldLink = modelsDir.JoinDir("ipadapter", link); - if (!oldLink.IsSymbolicLink) - continue; - - Logger.Info("Removing duplicate junctions in {Path}", oldLink.ToString()); - await oldLink.DeleteAsync(false).ConfigureAwait(false); - } - - // Resume base setup - await base.SetupModelFolders(installDirectory, SharedFolderMethod.Symlink).ConfigureAwait(false); - } - private async Task SetupModelFoldersConfig(DirectoryPath installDirectory) { var extraPathsYamlPath = installDirectory.JoinFile("extra_model_paths.yaml"); From 4bb95b70fe1dd779f279cf891cd41346c4b64290 Mon Sep 17 00:00:00 2001 From: JT Date: Mon, 18 Dec 2023 20:23:37 -0800 Subject: [PATCH 20/28] review pls --- StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs index a84f93c78..3848697b3 100644 --- a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs +++ b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs @@ -431,7 +431,6 @@ public override async Task SetupModelFolders(DirectoryPath installDirectory, Sha continue; Logger.Info("Removing duplicate junction at {Path}", linkDir.ToString()); - await linkDir.DeleteAsync(false).ConfigureAwait(false); } From ae13c871c89b4c8669539af2d1e4c21c908fe1cb Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 19 Dec 2023 00:48:08 -0500 Subject: [PATCH 21/28] Add model index key length check and skip --- CHANGELOG.md | 1 + .../Services/ModelIndexService.cs | 42 ++++++++++--------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a94c57388..4d546cf4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 - Fixed denoise strength in Inference Text to Image - Fixed PathTooLongException for IPAdapter folders when using ComfyUI in Symlink mode - Fixed configs and symlinks not being cleaned up when switched to the opposite mode +- Fixed model indexing stopping when encountering paths longer than 1021 bytes in length ## v2.7.3 ### Added diff --git a/StabilityMatrix.Core/Services/ModelIndexService.cs b/StabilityMatrix.Core/Services/ModelIndexService.cs index dec7eeb9b..9733f126d 100644 --- a/StabilityMatrix.Core/Services/ModelIndexService.cs +++ b/StabilityMatrix.Core/Services/ModelIndexService.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Text; using AsyncAwaitBestPractices; using Microsoft.Extensions.Logging; using StabilityMatrix.Core.Attributes; @@ -18,8 +19,7 @@ public class ModelIndexService : IModelIndexService private readonly ILiteDbContext liteDbContext; private readonly ISettingsManager settingsManager; - public Dictionary> ModelIndex { get; private set; } = - new(); + public Dictionary> ModelIndex { get; private set; } = new(); public ModelIndexService( ILogger logger, @@ -48,7 +48,8 @@ public IEnumerable GetFromModelIndex(SharedFolderType types) /// public async Task> GetModelsOfType(SharedFolderType type) { - return await liteDbContext.LocalModelFiles + return await liteDbContext + .LocalModelFiles .Query() .Where(m => m.SharedFolderType == type) .ToArrayAsync() @@ -87,7 +88,8 @@ public async Task RefreshIndex() var newIndex = new Dictionary>(); foreach ( - var file in modelsDir.Info + var file in modelsDir + .Info .EnumerateFiles("*.*", SearchOption.AllDirectories) .Select(info => new FilePath(info)) ) @@ -111,16 +113,22 @@ var file in modelsDir.Info continue; } - var localModel = new LocalModelFile + // Since RelativePath is the database key, for LiteDB this is limited to 1021 bytes + if (Encoding.Unicode.GetByteCount(relativePath) is var byteCount and > 1021) { - RelativePath = relativePath, - SharedFolderType = sharedFolderType, - }; + logger.LogWarning( + "Skipping model {Path} because it's path is too long ({Length} bytes)", + relativePath, + byteCount + ); + + continue; + } + + var localModel = new LocalModelFile { RelativePath = relativePath, SharedFolderType = sharedFolderType, }; // Try to find a connected model info - var jsonPath = file.Directory!.JoinFile( - new FilePath($"{file.NameWithoutExtension}.cm-info.json") - ); + var jsonPath = file.Directory!.JoinFile(new FilePath($"{file.NameWithoutExtension}.cm-info.json")); if (jsonPath.Exists) { @@ -132,18 +140,14 @@ await jsonPath.ReadAllTextAsync().ConfigureAwait(false) } // Try to find a preview image - var previewImagePath = LocalModelFile.SupportedImageExtensions - .Select( - ext => file.Directory!.JoinFile($"{file.NameWithoutExtension}.preview{ext}") - ) + var previewImagePath = LocalModelFile + .SupportedImageExtensions + .Select(ext => file.Directory!.JoinFile($"{file.NameWithoutExtension}.preview{ext}")) .FirstOrDefault(path => path.Exists); if (previewImagePath != null) { - localModel.PreviewImageRelativePath = Path.GetRelativePath( - modelsDir, - previewImagePath - ); + localModel.PreviewImageRelativePath = Path.GetRelativePath(modelsDir, previewImagePath); } // Insert into database From b0d5a4be75b25e244e54ef6feccce70a14dba80f Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 19 Dec 2023 01:03:48 -0500 Subject: [PATCH 22/28] Fix UTF8 encoding for byte count --- StabilityMatrix.Core/Services/ModelIndexService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StabilityMatrix.Core/Services/ModelIndexService.cs b/StabilityMatrix.Core/Services/ModelIndexService.cs index 9733f126d..56dd15346 100644 --- a/StabilityMatrix.Core/Services/ModelIndexService.cs +++ b/StabilityMatrix.Core/Services/ModelIndexService.cs @@ -114,7 +114,7 @@ var file in modelsDir } // Since RelativePath is the database key, for LiteDB this is limited to 1021 bytes - if (Encoding.Unicode.GetByteCount(relativePath) is var byteCount and > 1021) + if (Encoding.UTF8.GetByteCount(relativePath) is var byteCount and > 1021) { logger.LogWarning( "Skipping model {Path} because it's path is too long ({Length} bytes)", From 6be1f479d8ff99d8d7f36e4bba5784e2b6d4fa08 Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 19 Dec 2023 01:03:57 -0500 Subject: [PATCH 23/28] Add some BsonIgnores --- StabilityMatrix.Core/Models/Database/LocalModelFile.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/StabilityMatrix.Core/Models/Database/LocalModelFile.cs b/StabilityMatrix.Core/Models/Database/LocalModelFile.cs index 3fae7841c..e5f92cef3 100644 --- a/StabilityMatrix.Core/Models/Database/LocalModelFile.cs +++ b/StabilityMatrix.Core/Models/Database/LocalModelFile.cs @@ -32,16 +32,19 @@ public class LocalModelFile /// /// File name of the relative path. /// + [BsonIgnore] public string FileName => Path.GetFileName(RelativePath); /// /// File name of the relative path without extension. /// + [BsonIgnore] public string FileNameWithoutExtension => Path.GetFileNameWithoutExtension(RelativePath); /// /// Relative file path from the shared folder type model directory. /// + [BsonIgnore] public string RelativePathFromSharedFolder => Path.GetRelativePath(SharedFolderType.GetStringValue(), RelativePath); public string GetFullPath(string rootModelDirectory) @@ -54,8 +57,10 @@ public string GetFullPath(string rootModelDirectory) return PreviewImageRelativePath == null ? null : Path.Combine(rootModelDirectory, PreviewImageRelativePath); } + [BsonIgnore] public string FullPathGlobal => GetFullPath(GlobalConfig.LibraryDir.JoinDir("Models")); + [BsonIgnore] public string? PreviewImageFullPathGlobal => GetPreviewImageFullPath(GlobalConfig.LibraryDir.JoinDir("Models")); protected bool Equals(LocalModelFile other) From dc961f394e65f8f278c8fff6dfcdc0de28561856 Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 19 Dec 2023 01:09:04 -0500 Subject: [PATCH 24/28] Bump csharpier version --- .config/.csharpierrc.json | 2 +- .config/dotnet-tools.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/.csharpierrc.json b/.config/.csharpierrc.json index c821bbeb8..ce1241317 100644 --- a/.config/.csharpierrc.json +++ b/.config/.csharpierrc.json @@ -1,4 +1,4 @@ { - "printWidth": 120, + "printWidth": 100, "preprocessorSymbolSets": ["", "DEBUG", "DEBUG,CODE_STYLE"] } diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 55da51a77..126b4f0bc 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,10 +15,10 @@ ] }, "csharpier": { - "version": "0.26.4", + "version": "0.26.7", "commands": [ "dotnet-csharpier" ] } } -} \ No newline at end of file +} From 7ebec1c99dab3a6100135f5594f6b3d046ac8e09 Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 19 Dec 2023 01:18:06 -0500 Subject: [PATCH 25/28] Fix config --- .config/.csharpierrc.json | 2 +- .csharpierrc.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .csharpierrc.yaml diff --git a/.config/.csharpierrc.json b/.config/.csharpierrc.json index ce1241317..822be0a5b 100644 --- a/.config/.csharpierrc.json +++ b/.config/.csharpierrc.json @@ -1,4 +1,4 @@ { - "printWidth": 100, + "printWidth": 110, "preprocessorSymbolSets": ["", "DEBUG", "DEBUG,CODE_STYLE"] } diff --git a/.csharpierrc.yaml b/.csharpierrc.yaml new file mode 100644 index 000000000..568c45f6e --- /dev/null +++ b/.csharpierrc.yaml @@ -0,0 +1 @@ +printWidth: 110 From 8375038a81fef46bf8495ba0a055132930ec213e Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 19 Dec 2023 01:20:34 -0500 Subject: [PATCH 26/28] Reformat --- .../Services/ModelIndexService.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/StabilityMatrix.Core/Services/ModelIndexService.cs b/StabilityMatrix.Core/Services/ModelIndexService.cs index 56dd15346..67a676697 100644 --- a/StabilityMatrix.Core/Services/ModelIndexService.cs +++ b/StabilityMatrix.Core/Services/ModelIndexService.cs @@ -49,8 +49,7 @@ public IEnumerable GetFromModelIndex(SharedFolderType types) public async Task> GetModelsOfType(SharedFolderType type) { return await liteDbContext - .LocalModelFiles - .Query() + .LocalModelFiles.Query() .Where(m => m.SharedFolderType == type) .ToArrayAsync() .ConfigureAwait(false); @@ -89,8 +88,7 @@ public async Task RefreshIndex() var newIndex = new Dictionary>(); foreach ( var file in modelsDir - .Info - .EnumerateFiles("*.*", SearchOption.AllDirectories) + .Info.EnumerateFiles("*.*", SearchOption.AllDirectories) .Select(info => new FilePath(info)) ) { @@ -125,10 +123,16 @@ var file in modelsDir continue; } - var localModel = new LocalModelFile { RelativePath = relativePath, SharedFolderType = sharedFolderType, }; + var localModel = new LocalModelFile + { + RelativePath = relativePath, + SharedFolderType = sharedFolderType + }; // Try to find a connected model info - var jsonPath = file.Directory!.JoinFile(new FilePath($"{file.NameWithoutExtension}.cm-info.json")); + var jsonPath = file.Directory!.JoinFile( + new FilePath($"{file.NameWithoutExtension}.cm-info.json") + ); if (jsonPath.Exists) { @@ -141,8 +145,9 @@ await jsonPath.ReadAllTextAsync().ConfigureAwait(false) // Try to find a preview image var previewImagePath = LocalModelFile - .SupportedImageExtensions - .Select(ext => file.Directory!.JoinFile($"{file.NameWithoutExtension}.preview{ext}")) + .SupportedImageExtensions.Select( + ext => file.Directory!.JoinFile($"{file.NameWithoutExtension}.preview{ext}") + ) .FirstOrDefault(path => path.Exists); if (previewImagePath != null) From 2fac330523d1185d0e802c98e237c556d68f1f90 Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 19 Dec 2023 02:25:40 -0500 Subject: [PATCH 27/28] Fix infinity --- .../Models/Packages/BaseGitPackage.cs | 118 ++++++++++++++---- 1 file changed, 91 insertions(+), 27 deletions(-) diff --git a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs index 3848697b3..a0aed491a 100644 --- a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs +++ b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs @@ -222,7 +222,10 @@ protected Task UnzipPackage(string installLocation, IProgress? p zipDirName = entry.FullName; } - var folderPath = Path.Combine(installLocation, entry.FullName.Replace(zipDirName, string.Empty)); + var folderPath = Path.Combine( + installLocation, + entry.FullName.Replace(zipDirName, string.Empty) + ); Directory.CreateDirectory(folderPath); continue; } @@ -233,7 +236,10 @@ protected Task UnzipPackage(string installLocation, IProgress? p entry.ExtractToFile(destinationPath, true); progress?.Report( - new ProgressReport(current: Convert.ToUInt64(currentEntry), total: Convert.ToUInt64(totalEntries)) + new ProgressReport( + current: Convert.ToUInt64(currentEntry), + total: Convert.ToUInt64(totalEntries) + ) ); } @@ -262,7 +268,9 @@ public override async Task CheckForUpdates(InstalledPackage package) return UpdateAvailable; } - var allCommits = (await GetAllCommits(currentVersion.InstalledBranch!).ConfigureAwait(false))?.ToList(); + var allCommits = ( + await GetAllCommits(currentVersion.InstalledBranch!).ConfigureAwait(false) + )?.ToList(); if (allCommits == null || !allCommits.Any()) { @@ -295,9 +303,15 @@ public override async Task Update( { Logger.Info("not a git repo, initializing..."); progress?.Report(new ProgressReport(-1f, "Initializing git repo", isIndeterminate: true)); - await PrerequisiteHelper.RunGit("init", onConsoleOutput, installedPackage.FullPath).ConfigureAwait(false); await PrerequisiteHelper - .RunGit(new[] { "remote", "add", "origin", GithubUrl }, onConsoleOutput, installedPackage.FullPath) + .RunGit("init", onConsoleOutput, installedPackage.FullPath) + .ConfigureAwait(false); + await PrerequisiteHelper + .RunGit( + new[] { "remote", "add", "origin", GithubUrl }, + onConsoleOutput, + installedPackage.FullPath + ) .ConfigureAwait(false); } @@ -338,7 +352,9 @@ await InstallPackage( // fetch progress?.Report(new ProgressReport(-1f, "Fetching data...", isIndeterminate: true)); - await PrerequisiteHelper.RunGit("fetch", onConsoleOutput, installedPackage.FullPath).ConfigureAwait(false); + await PrerequisiteHelper + .RunGit("fetch", onConsoleOutput, installedPackage.FullPath) + .ConfigureAwait(false); if (versionOptions.IsLatest) { @@ -405,17 +421,60 @@ await InstallPackage( }; } - public override async Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) + private async Task FixInfinityFolders(DirectoryPath rootDirectory, string infinityFolderName) + { + // Skip if first infinity not found + if ( + rootDirectory.JoinDir(infinityFolderName) + is not { Exists: true, IsSymbolicLink: false } firstInfinity + ) + { + return; + } + + var depth = 0; + var currentDir = rootDirectory; + + while (currentDir.JoinDir(infinityFolderName) is { Exists: true, IsSymbolicLink: false } newInfinity) + { + depth++; + currentDir = newInfinity; + } + + Logger.Info("Found {Depth} infinity folders from {FirstPath}", depth, firstInfinity.ToString()); + + // Move all items in infinity folder to root + Logger.Info("Moving infinity folders content to root: {Path}", currentDir.ToString()); + await FileTransfers.MoveAllFilesAndDirectories(currentDir, rootDirectory).ConfigureAwait(false); + + // Move any files from first infinity by enumeration just in case + foreach (var file in firstInfinity.EnumerateFiles()) + { + await file.MoveToDirectoryAsync(rootDirectory).ConfigureAwait(false); + } + + // Delete infinity folders chain from first + Logger.Info("Deleting infinity folders: {Path}", currentDir.ToString()); + await firstInfinity.DeleteAsync(true).ConfigureAwait(false); + } + + public override async Task SetupModelFolders( + DirectoryPath installDirectory, + SharedFolderMethod sharedFolderMethod + ) { if (sharedFolderMethod != SharedFolderMethod.Symlink || SharedFolders is not { } sharedFolders) { return; } - // fix duplicate links in models dir - // see https://github.com/LykosAI/StabilityMatrix/issues/338 var modelsDir = new DirectoryPath(SettingsManager.ModelsDirectory); + // fix infinity controlnet folders + await FixInfinityFolders(modelsDir.JoinDir("ControlNet"), "ControlNet").ConfigureAwait(false); + + // fix duplicate links in models dir + // see https://github.com/LykosAI/StabilityMatrix/issues/338 string[] duplicatePaths = [ Path.Combine("ControlNet", "ControlNet"), @@ -435,17 +494,23 @@ public override async Task SetupModelFolders(DirectoryPath installDirectory, Sha } await StabilityMatrix - .Core - .Helper - .SharedFolders - .UpdateLinksForPackage(sharedFolders, SettingsManager.ModelsDirectory, installDirectory) + .Core.Helper.SharedFolders.UpdateLinksForPackage( + sharedFolders, + SettingsManager.ModelsDirectory, + installDirectory + ) .ConfigureAwait(false); } - public override Task UpdateModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) => - SetupModelFolders(installDirectory, sharedFolderMethod); + public override Task UpdateModelFolders( + DirectoryPath installDirectory, + SharedFolderMethod sharedFolderMethod + ) => SetupModelFolders(installDirectory, sharedFolderMethod); - public override Task RemoveModelFolderLinks(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) + public override Task RemoveModelFolderLinks( + DirectoryPath installDirectory, + SharedFolderMethod sharedFolderMethod + ) { if (SharedFolders is not null && sharedFolderMethod == SharedFolderMethod.Symlink) { @@ -458,16 +523,12 @@ public override Task SetupOutputFolderLinks(DirectoryPath installDirectory) { if (SharedOutputFolders is { } sharedOutputFolders) { - return StabilityMatrix - .Core - .Helper - .SharedFolders - .UpdateLinksForPackage( - sharedOutputFolders, - SettingsManager.ImagesDirectory, - installDirectory, - recursiveDelete: true - ); + return StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage( + sharedOutputFolders, + SettingsManager.ImagesDirectory, + installDirectory, + recursiveDelete: true + ); } return Task.CompletedTask; @@ -477,7 +538,10 @@ public override Task RemoveOutputFolderLinks(DirectoryPath installDirectory) { if (SharedOutputFolders is { } sharedOutputFolders) { - StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage(sharedOutputFolders, installDirectory); + StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage( + sharedOutputFolders, + installDirectory + ); } return Task.CompletedTask; } From 24d52580135ea6ff05fd000ee466a4d43b4d61cc Mon Sep 17 00:00:00 2001 From: Ionite Date: Tue, 19 Dec 2023 02:42:43 -0500 Subject: [PATCH 28/28] Changelog for infinity fix --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d546cf4f..1843f51b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 - Fixed PathTooLongException for IPAdapter folders when using ComfyUI in Symlink mode - Fixed configs and symlinks not being cleaned up when switched to the opposite mode - Fixed model indexing stopping when encountering paths longer than 1021 bytes in length +- Fixed repeated nested folders being created in `Models/ControlNet` when using ComfyUI in Symlink mode. Existing folders will be repaired to their original structure on launch. ## v2.7.3 ### Added