Browse Source

SharedFolders refactor for ComfyUI & Vlad:

- Now updates config files in the respective packages instead of using symlinks
- Other 3 packages still use symlinks for now
- Added dictionary indexer [] thing to packageFactory
- Installers now call the BasePackage SetupModelFolders method instead of SharedFolders
- Launch page now calls the BasePackage UpdateModelFolders instead of SharedFolders
pull/55/head
JT 1 year ago
parent
commit
dc342742ce
  1. 3
      StabilityMatrix.Avalonia/ViewModels/Dialogs/InstallerViewModel.cs
  2. 2
      StabilityMatrix.Avalonia/ViewModels/Dialogs/OneClickInstallViewModel.cs
  3. 2
      StabilityMatrix.Avalonia/ViewModels/LaunchPageViewModel.cs
  4. 4
      StabilityMatrix.Avalonia/ViewModels/ProgressManagerViewModel.cs
  5. 1
      StabilityMatrix.Core/Helper/Factory/IPackageFactory.cs
  6. 2
      StabilityMatrix.Core/Helper/Factory/PackageFactory.cs
  7. 1
      StabilityMatrix.Core/Helper/ISharedFolders.cs
  8. 21
      StabilityMatrix.Core/Helper/SharedFolders.cs
  9. 16
      StabilityMatrix.Core/Models/Packages/A3WebUI.cs
  10. 4
      StabilityMatrix.Core/Models/Packages/BasePackage.cs
  11. 73
      StabilityMatrix.Core/Models/Packages/ComfyUI.cs
  12. 11
      StabilityMatrix.Core/Models/Packages/DankDiffusion.cs
  13. 13
      StabilityMatrix.Core/Models/Packages/InvokeAI.cs
  14. 56
      StabilityMatrix.Core/Models/Packages/VladAutomatic.cs
  15. 14
      StabilityMatrix.Core/Models/Packages/VoltaML.cs
  16. 1
      StabilityMatrix.Core/StabilityMatrix.Core.csproj

3
StabilityMatrix.Avalonia/ViewModels/Dialogs/InstallerViewModel.cs

@ -215,7 +215,8 @@ public partial class InstallerViewModel : ContentDialogViewModelBase
await InstallPackage();
InstallProgress.Text = "Setting up shared folder links...";
sharedFolders.SetupLinksForPackage(SelectedPackage, SelectedPackage.InstallLocation);
await SelectedPackage.SetupModelFolders(SelectedPackage.InstallLocation);
//sharedFolders.SetupLinksForPackage(SelectedPackage, SelectedPackage.InstallLocation);
InstallProgress.Text = "Done";
InstallProgress.IsIndeterminate = false;

2
StabilityMatrix.Avalonia/ViewModels/Dialogs/OneClickInstallViewModel.cs

@ -113,7 +113,7 @@ public partial class OneClickInstallViewModel : ViewModelBase
await InstallPackage();
SubHeaderText = "Setting up shared folder links...";
sharedFolders.SetupLinksForPackage(SelectedPackage, SelectedPackage.InstallLocation);
await SelectedPackage.SetupModelFolders(SelectedPackage.InstallLocation);
var installedPackage = new InstalledPackage
{

2
StabilityMatrix.Avalonia/ViewModels/LaunchPageViewModel.cs

@ -231,7 +231,7 @@ public partial class LaunchPageViewModel : PageViewModelBase, IDisposable, IAsyn
Console.StartUpdates();
// Update shared folder links (in case library paths changed)
await sharedFolders.UpdateLinksForPackage(basePackage, packagePath);
await basePackage.UpdateModelFolders(packagePath);
// Load user launch args from settings and convert to string
var userArgs = settingsManager.GetLaunchArgs(activeInstall.Id);

4
StabilityMatrix.Avalonia/ViewModels/ProgressManagerViewModel.cs

@ -33,11 +33,11 @@ public partial class ProgressManagerViewModel : PageViewModelBase
public void ClearDownloads()
{
if (!ProgressItems.Any(p => Math.Abs(p.Progress.Percentage - 100) < 0.01f))
if (!ProgressItems.Any(p => Math.Abs(p.Progress.Percentage - 100) < 0.01f || p.Failed))
return;
var itemsInProgress = ProgressItems
.Where(p => p.Progress.Percentage < 100).ToList();
.Where(p => p.Progress.Percentage < 100 && !p.Failed).ToList();
ProgressItems = new ObservableCollection<ProgressItemViewModel>(itemsInProgress);
}

1
StabilityMatrix.Core/Helper/Factory/IPackageFactory.cs

@ -6,4 +6,5 @@ public interface IPackageFactory
{
IEnumerable<BasePackage> GetAllAvailablePackages();
BasePackage? FindPackageByName(string? packageName);
BasePackage? this[string packageName] { get; }
}

2
StabilityMatrix.Core/Helper/Factory/PackageFactory.cs

@ -24,4 +24,6 @@ public class PackageFactory : IPackageFactory
return packageName == null ? null :
basePackages.GetValueOrDefault(packageName);
}
public BasePackage? this[string packageName] => basePackages[packageName];
}

1
StabilityMatrix.Core/Helper/ISharedFolders.cs

@ -6,7 +6,6 @@ namespace StabilityMatrix.Core.Helper;
public interface ISharedFolders
{
void SetupLinksForPackage(BasePackage basePackage, DirectoryPath installDirectory);
Task UpdateLinksForPackage(BasePackage basePackage, DirectoryPath installDirectory);
void RemoveLinksForAllPackages();
void SetupSharedModelFolders();
}

21
StabilityMatrix.Core/Helper/SharedFolders.cs

@ -1,5 +1,4 @@
using System.Globalization;
using NLog;
using NLog;
using StabilityMatrix.Core.Extensions;
using StabilityMatrix.Core.Helper.Factory;
using StabilityMatrix.Core.Models;
@ -90,7 +89,7 @@ public class SharedFolders : ISharedFolders
/// Deletes junction links and remakes them. Unlike SetupLinksForPackage,
/// this will not copy files from the destination to the source.
/// </summary>
public async Task UpdateLinksForPackage(BasePackage basePackage, DirectoryPath installDirectory)
public static async Task UpdateLinksForPackage(BasePackage basePackage, DirectoryPath modelsDirectory, DirectoryPath installDirectory)
{
var sharedFolders = basePackage.SharedFolders;
if (sharedFolders is null) return;
@ -99,9 +98,9 @@ public class SharedFolders : ISharedFolders
{
foreach (var relativePath in relativePaths)
{
var sourceDir = new DirectoryPath(settingsManager.ModelsDirectory, folderType.GetStringValue());
var sourceDir = new DirectoryPath(modelsDirectory, folderType.GetStringValue());
var destinationDir = installDirectory.JoinDir(relativePath);
// Create source folder if it doesn't exist
if (!sourceDir.Exists)
{
@ -117,9 +116,11 @@ public class SharedFolders : ISharedFolders
// If link is already the same, just skip
if (destinationDir.Info.LinkTarget == sourceDir)
{
Logger.Info($"Skipped updating matching folder link ({destinationDir} -> ({sourceDir})");
continue;
Logger.Info(
$"Skipped updating matching folder link ({destinationDir} -> ({sourceDir})");
return;
}
// Otherwise delete the link
Logger.Info($"Deleting existing junction at target {destinationDir}");
await destinationDir.DeleteAsync(false).ConfigureAwait(false);
@ -131,10 +132,10 @@ public class SharedFolders : ISharedFolders
{
Logger.Info($"Moving files from {destinationDir} to {sourceDir}");
await FileTransfers.MoveAllFilesAndDirectories(
destinationDir,sourceDir, overwriteIfHashMatches: true)
destinationDir, sourceDir, overwriteIfHashMatches: true)
.ConfigureAwait(false);
}
Logger.Info($"Deleting existing empty folder at target {destinationDir}");
await destinationDir.DeleteAsync(false).ConfigureAwait(false);
}
@ -175,7 +176,7 @@ public class SharedFolders : ISharedFolders
foreach (var package in packages)
{
if (package.PackageName == null) continue;
var basePackage = packageFactory.FindPackageByName(package.PackageName);
var basePackage = packageFactory[package.PackageName];
if (basePackage == null) continue;
if (package.LibraryPath == null) continue;

16
StabilityMatrix.Core/Models/Packages/A3WebUI.cs

@ -5,6 +5,7 @@ using System.Text.RegularExpressions;
using NLog;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Helper.Cache;
using StabilityMatrix.Core.Models.FileInterfaces;
using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Processes;
using StabilityMatrix.Core.Python;
@ -113,7 +114,7 @@ public class A3WebUI : BaseGitPackage
},
LaunchOptionDefinition.Extras
};
public override async Task<string> GetLatestVersion()
{
var release = await GetLatestRelease().ConfigureAwait(false);
@ -193,4 +194,17 @@ public class A3WebUI : BaseGitPackage
VenvRunner.RunDetached(args.TrimEnd(), HandleConsoleOutput, OnExit);
}
public override Task SetupModelFolders(DirectoryPath installDirectory)
{
StabilityMatrix.Core.Helper.SharedFolders
.SetupLinks(SharedFolders, SettingsManager.ModelsDirectory, installDirectory);
return Task.CompletedTask;
}
public override async Task UpdateModelFolders(DirectoryPath installDirectory)
{
await StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage(this,
SettingsManager.ModelsDirectory, installDirectory).ConfigureAwait(false);
}
}

4
StabilityMatrix.Core/Models/Packages/BasePackage.cs

@ -1,5 +1,6 @@
using Octokit;
using StabilityMatrix.Core.Models.Database;
using StabilityMatrix.Core.Models.FileInterfaces;
using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Processes;
@ -35,7 +36,8 @@ public abstract class BasePackage
IProgress<ProgressReport>? progress = null);
public abstract Task InstallPackage(IProgress<ProgressReport>? progress = null);
public abstract Task RunPackage(string installedPackagePath, string command, string arguments);
public abstract Task SetupModelFolders(DirectoryPath installDirectory);
public abstract Task UpdateModelFolders(DirectoryPath installDirectory);
/// <summary>
/// Shuts down the subprocess, canceling any pending streams.

73
StabilityMatrix.Core/Models/Packages/ComfyUI.cs

@ -3,10 +3,13 @@ using System.Text.RegularExpressions;
using NLog;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Helper.Cache;
using StabilityMatrix.Core.Models.FileInterfaces;
using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Processes;
using StabilityMatrix.Core.Python;
using StabilityMatrix.Core.Services;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace StabilityMatrix.Core.Models.Packages;
@ -171,4 +174,74 @@ public class ComfyUI : BaseGitPackage
HandleConsoleOutput,
HandleExit);
}
public override Task SetupModelFolders(DirectoryPath installDirectory)
{
var extraPathsYamlPath = installDirectory + "extra_model_paths.yaml";
var modelsDir = SettingsManager.ModelsDirectory;
var deserializer = new DeserializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build();
var exists = File.Exists(extraPathsYamlPath);
if (!exists)
{
Logger.Info("Creating extra_model_paths.yaml");
File.WriteAllText(extraPathsYamlPath, string.Empty);
}
var yaml = File.ReadAllText(extraPathsYamlPath);
var comfyModelPaths = deserializer.Deserialize<ComfyModelPathsYaml>(yaml) ??
// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract
// cuz it can actually be null lol
new ComfyModelPathsYaml();
comfyModelPaths.StabilityMatrix ??= new ComfyModelPathsYaml.SmData();
comfyModelPaths.StabilityMatrix.Checkpoints = Path.Combine(modelsDir, "StableDiffusion");
comfyModelPaths.StabilityMatrix.Vae = Path.Combine(modelsDir, "VAE");
comfyModelPaths.StabilityMatrix.Loras = $"{Path.Combine(modelsDir, "Lora")}\n" +
$"{Path.Combine(modelsDir, "LyCORIS")}";
comfyModelPaths.StabilityMatrix.UpscaleModels = $"{Path.Combine(modelsDir, "ESRGAN")}\n" +
$"{Path.Combine(modelsDir, "RealESRGAN")}\n" +
$"{Path.Combine(modelsDir, "SwinIR")}";
comfyModelPaths.StabilityMatrix.Embeddings = Path.Combine(modelsDir, "TextualInversion");
comfyModelPaths.StabilityMatrix.Hypernetworks = Path.Combine(modelsDir, "Hypernetwork");
comfyModelPaths.StabilityMatrix.Controlnet = Path.Combine(modelsDir, "ControlNet");
comfyModelPaths.StabilityMatrix.Clip = Path.Combine(modelsDir, "CLIP");
comfyModelPaths.StabilityMatrix.Diffusers = Path.Combine(modelsDir, "Diffusers");
comfyModelPaths.StabilityMatrix.Gligen = Path.Combine(modelsDir, "GLIGEN");
comfyModelPaths.StabilityMatrix.VaeApprox = Path.Combine(modelsDir, "ApproxVAE");
var serializer = new SerializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.Build();
var yamlData = serializer.Serialize(comfyModelPaths);
File.WriteAllText(extraPathsYamlPath, yamlData);
return Task.CompletedTask;
}
public override Task UpdateModelFolders(DirectoryPath installDirectory) =>
SetupModelFolders(installDirectory);
public class ComfyModelPathsYaml
{
public class SmData
{
public string Checkpoints { get; set; }
public string Vae { get; set; }
public string Loras { get; set; }
public string UpscaleModels { get; set; }
public string Embeddings { get; set; }
public string Hypernetworks { get; set; }
public string Controlnet { get; set; }
public string Clip { get; set; }
public string Diffusers { get; set; }
public string Gligen { get; set; }
public string VaeApprox { get; set; }
}
public SmData? StabilityMatrix { get; set; }
}
}

11
StabilityMatrix.Core/Models/Packages/DankDiffusion.cs

@ -1,5 +1,6 @@
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Helper.Cache;
using StabilityMatrix.Core.Models.FileInterfaces;
using StabilityMatrix.Core.Services;
namespace StabilityMatrix.Core.Models.Packages;
@ -33,6 +34,16 @@ public class DankDiffusion : BaseGitPackage
throw new NotImplementedException();
}
public override Task SetupModelFolders(DirectoryPath installDirectory)
{
throw new NotImplementedException();
}
public override Task UpdateModelFolders(DirectoryPath installDirectory)
{
throw new NotImplementedException();
}
public override List<LaunchOptionDefinition> LaunchOptions { get; }
public override Task<string> GetLatestVersion()
{

13
StabilityMatrix.Core/Models/Packages/InvokeAI.cs

@ -248,6 +248,19 @@ public class InvokeAI : BaseGitPackage
VenvRunner.RunDetached($"-c \"{code}\"".TrimEnd(), OnConsoleOutput, OnExit);
}
public override Task SetupModelFolders(DirectoryPath installDirectory)
{
StabilityMatrix.Core.Helper.SharedFolders.SetupLinks(SharedFolders,
SettingsManager.ModelsDirectory, installDirectory);
return Task.CompletedTask;
}
public override async Task UpdateModelFolders(DirectoryPath installDirectory)
{
await StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage(this,
SettingsManager.ModelsDirectory, installDirectory).ConfigureAwait(false);
}
private Dictionary<string, string> GetEnvVars(DirectoryPath installPath)
{
// Set additional required environment variables

56
StabilityMatrix.Core/Models/Packages/VladAutomatic.cs

@ -1,5 +1,7 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using NLog;
using StabilityMatrix.Core.Helper;
@ -235,6 +237,60 @@ public class VladAutomatic : BaseGitPackage
VenvRunner.RunDetached(args.TrimEnd(), HandleConsoleOutput, HandleExit);
}
public override Task SetupModelFolders(DirectoryPath installDirectory)
{
var configJsonPath = installDirectory + "config.json";
var exists = File.Exists(configJsonPath);
JsonObject? configRoot;
if (exists)
{
var configJson = File.ReadAllText(configJsonPath);
try
{
configRoot = JsonSerializer.Deserialize<JsonObject>(configJson) ?? new JsonObject();
}
catch (JsonException)
{
configRoot = new JsonObject();
}
}
else
{
configRoot = new JsonObject();
}
configRoot["ckpt_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "StableDiffusion");
configRoot["diffusers_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "Diffusers");
configRoot["vae_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "VAE");
configRoot["lora_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "Lora");
configRoot["lyco_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "LyCORIS");
configRoot["embeddings_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "TextualInversion");
configRoot["hypernetwork_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "Hypernetwork");
configRoot["codeformer_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "Codeformer");
configRoot["gfpgan_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "GFPGAN");
configRoot["bsrgan_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "BSRGAN");
configRoot["esrgan_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "ESRGAN");
configRoot["realesrgan_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "RealESRGAN");
configRoot["scunet_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "ScuNET");
configRoot["swinir_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "SwinIR");
configRoot["ldsr_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "LDSR");
configRoot["clip_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "CLIP");
configRoot["control_net_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "ControlNet");
var configJsonStr = JsonSerializer.Serialize(configRoot, new JsonSerializerOptions
{
WriteIndented = true
});
File.WriteAllText(configJsonPath, configJsonStr);
return Task.CompletedTask;
}
public override Task UpdateModelFolders(DirectoryPath installDirectory)
{
return SetupModelFolders(installDirectory);
}
public override async Task<string> Update(InstalledPackage installedPackage,
IProgress<ProgressReport>? progress = null, bool includePrerelease = false)
{

14
StabilityMatrix.Core/Models/Packages/VoltaML.cs

@ -1,5 +1,6 @@
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Helper.Cache;
using StabilityMatrix.Core.Models.FileInterfaces;
using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Python;
using StabilityMatrix.Core.Services;
@ -149,4 +150,17 @@ public class VoltaML : BaseGitPackage
VenvRunner.RunDetached(args.TrimEnd(), OnConsoleOutput, OnExit);
}
public override Task SetupModelFolders(DirectoryPath installDirectory)
{
StabilityMatrix.Core.Helper.SharedFolders.SetupLinks(SharedFolders,
SettingsManager.ModelsDirectory, installDirectory);
return Task.CompletedTask;
}
public override async Task UpdateModelFolders(DirectoryPath installDirectory)
{
await StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage(this,
SettingsManager.ModelsDirectory, installDirectory).ConfigureAwait(false);
}
}

1
StabilityMatrix.Core/StabilityMatrix.Core.csproj

@ -37,6 +37,7 @@
<PackageReference Include="Semver" Version="3.0.0-beta.0" />
<PackageReference Include="Sentry.NLog" Version="3.33.1" />
<PackageReference Include="SharpCompress" Version="0.33.0" />
<PackageReference Include="YamlDotNet" Version="13.1.1" />
</ItemGroup>
</Project>

Loading…
Cancel
Save