Browse Source

Merge pull request #406 from ionite34/shared-folder-fixes

pull/333/head
Ionite 11 months ago committed by GitHub
parent
commit
c8aa8bafbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      CHANGELOG.md
  2. 28
      StabilityMatrix.Core/Models/FileInterfaces/FileSystemPath.cs
  3. 25
      StabilityMatrix.Core/Models/Packages/A3WebUI.cs
  4. 116
      StabilityMatrix.Core/Models/Packages/ComfyUI.cs

6
CHANGELOG.md

@ -5,6 +5,12 @@ 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.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`.
### Fixed
- Fixed ControlNet / T2IAdapter shared folder links for Automatic1111 conflicting with each other
## v2.7.1
### Added
- Added Turkish UI language option, thanks to Progresor for the translation

28
StabilityMatrix.Core/Models/FileInterfaces/FileSystemPath.cs

@ -1,6 +1,6 @@
namespace StabilityMatrix.Core.Models.FileInterfaces;
public class FileSystemPath : IEquatable<FileSystemPath>, IEquatable<string>
public class FileSystemPath : IEquatable<FileSystemPath>, IEquatable<string>, IFormattable
{
public string FullPath { get; }
@ -9,23 +9,38 @@ public class FileSystemPath : IEquatable<FileSystemPath>, IEquatable<string>
FullPath = path;
}
protected FileSystemPath(FileSystemPath path) : this(path.FullPath)
protected FileSystemPath(FileSystemPath path)
: this(path.FullPath) { }
protected FileSystemPath(params string[] paths)
: this(Path.Combine(paths)) { }
public override string ToString()
{
return FullPath;
}
protected FileSystemPath(params string[] paths) : this(Path.Combine(paths))
/// <inheritdoc />
string IFormattable.ToString(string? format, IFormatProvider? formatProvider)
{
return ToString(format, formatProvider);
}
public override string ToString()
/// <summary>
/// Overridable IFormattable.ToString method.
/// By default, returns <see cref="FullPath"/>.
/// </summary>
protected virtual string ToString(string? format, IFormatProvider? formatProvider)
{
return FullPath;
}
public bool Equals(FileSystemPath? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return FullPath == other.FullPath;
}
@ -51,5 +66,6 @@ public class FileSystemPath : IEquatable<FileSystemPath>, IEquatable<string>
// Implicit conversions to and from string
public static implicit operator string(FileSystemPath path) => path.FullPath;
public static implicit operator FileSystemPath(string path) => new(path);
}

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

@ -56,12 +56,12 @@ public class A3WebUI(
[SharedFolderType.Karlo] = new[] { "models/karlo" },
[SharedFolderType.TextualInversion] = new[] { "embeddings" },
[SharedFolderType.Hypernetwork] = new[] { "models/hypernetworks" },
[SharedFolderType.ControlNet] = new[] { "models/ControlNet" },
[SharedFolderType.ControlNet] = new[] { "models/controlnet/ControlNet" },
[SharedFolderType.Codeformer] = new[] { "models/Codeformer" },
[SharedFolderType.LDSR] = new[] { "models/LDSR" },
[SharedFolderType.AfterDetailer] = new[] { "models/adetailer" },
[SharedFolderType.T2IAdapter] = new[] { "models/controlnet" },
[SharedFolderType.IpAdapter] = new[] { "models/ipadapter" }
[SharedFolderType.T2IAdapter] = new[] { "models/controlnet/T2IAdapter" },
[SharedFolderType.IpAdapter] = new[] { "models/controlnet/IpAdapter" }
};
public override Dictionary<SharedOutputType, IReadOnlyList<string>>? SharedOutputFolders =>
@ -278,4 +278,23 @@ public class A3WebUI(
)
.ConfigureAwait(false);
}
/// <inheritdoc />
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)
{
Logger.Info("Migration: Removing old controlnet link {Path}", controlnetOldLink);
await controlnetOldLink.DeleteAsync(false).ConfigureAwait(false);
}
// Resume base setup
await base.SetupModelFolders(installDirectory, sharedFolderMethod).ConfigureAwait(false);
}
/// <inheritdoc />
public override Task UpdateModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) =>
SetupModelFolders(installDirectory, sharedFolderMethod);
}

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

@ -10,6 +10,7 @@ using StabilityMatrix.Core.Models.Progress;
using StabilityMatrix.Core.Processes;
using StabilityMatrix.Core.Python;
using StabilityMatrix.Core.Services;
using YamlDotNet.Core;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
@ -53,12 +54,12 @@ public class ComfyUI(
[SharedFolderType.TextualInversion] = new[] { "models/embeddings" },
[SharedFolderType.VAE] = new[] { "models/vae" },
[SharedFolderType.ApproxVAE] = new[] { "models/vae_approx" },
[SharedFolderType.ControlNet] = new[] { "models/controlnet" },
[SharedFolderType.ControlNet] = new[] { "models/controlnet/ControlNet" },
[SharedFolderType.GLIGEN] = new[] { "models/gligen" },
[SharedFolderType.ESRGAN] = new[] { "models/upscale_models" },
[SharedFolderType.Hypernetwork] = new[] { "models/hypernetworks" },
[SharedFolderType.IpAdapter] = new[] { "models/ipadapter" },
[SharedFolderType.T2IAdapter] = new[] { "models/controlnet" },
[SharedFolderType.T2IAdapter] = new[] { "models/controlnet/T2IAdapter" },
};
public override Dictionary<SharedOutputType, IReadOnlyList<string>>? SharedOutputFolders =>
@ -267,26 +268,55 @@ public class ComfyUI(
}
}
public override Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod)
public override Task SetupModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) =>
sharedFolderMethod switch
{
SharedFolderMethod.Symlink => SetupModelFoldersSymlink(installDirectory),
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
{
SharedFolderMethod.Symlink => base.RemoveModelFolderLinks(installDirectory, sharedFolderMethod),
SharedFolderMethod.Configuration => RemoveConfigSection(installDirectory),
SharedFolderMethod.None => Task.CompletedTask,
_ => throw new ArgumentOutOfRangeException(nameof(sharedFolderMethod), sharedFolderMethod, null)
};
}
private async Task SetupModelFoldersSymlink(DirectoryPath installDirectory)
{
switch (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)
{
case SharedFolderMethod.None:
return Task.CompletedTask;
case SharedFolderMethod.Symlink:
return base.SetupModelFolders(installDirectory, sharedFolderMethod);
Logger.Info("Migration: Removing old controlnet link {Path}", controlnetOldLink);
await controlnetOldLink.DeleteAsync(false).ConfigureAwait(false);
}
var extraPathsYamlPath = installDirectory + "extra_model_paths.yaml";
// 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");
var modelsDir = SettingsManager.ModelsDirectory;
var exists = File.Exists(extraPathsYamlPath);
if (!exists)
if (!extraPathsYamlPath.Exists)
{
Logger.Info("Creating extra_model_paths.yaml");
File.WriteAllText(extraPathsYamlPath, string.Empty);
extraPathsYamlPath.Create();
}
var yaml = File.ReadAllText(extraPathsYamlPath);
var yaml = await extraPathsYamlPath.ReadAllTextAsync().ConfigureAwait(false);
using var sr = new StringReader(yaml);
var yamlStream = new YamlStream();
yamlStream.Load(sr);
@ -307,7 +337,7 @@ public class ComfyUI(
if (stabilityMatrixNode.Key != null)
{
if (stabilityMatrixNode.Value is not YamlMappingNode nodeValue)
return Task.CompletedTask;
return;
nodeValue.Children["checkpoints"] = Path.Combine(modelsDir, "StableDiffusion");
nodeValue.Children["vae"] = Path.Combine(modelsDir, "VAE");
@ -319,7 +349,11 @@ public class ComfyUI(
+ $"{Path.Combine(modelsDir, "SwinIR")}";
nodeValue.Children["embeddings"] = Path.Combine(modelsDir, "TextualInversion");
nodeValue.Children["hypernetworks"] = Path.Combine(modelsDir, "Hypernetwork");
nodeValue.Children["controlnet"] = Path.Combine(modelsDir, "ControlNet");
nodeValue.Children["controlnet"] = string.Join(
'\n',
Path.Combine(modelsDir, "ControlNet"),
Path.Combine(modelsDir, "T2IAdapter")
);
nodeValue.Children["clip"] = Path.Combine(modelsDir, "CLIP");
nodeValue.Children["diffusers"] = Path.Combine(modelsDir, "Diffusers");
nodeValue.Children["gligen"] = Path.Combine(modelsDir, "GLIGEN");
@ -340,7 +374,10 @@ public class ComfyUI(
},
{ "embeddings", Path.Combine(modelsDir, "TextualInversion") },
{ "hypernetworks", Path.Combine(modelsDir, "Hypernetwork") },
{ "controlnet", Path.Combine(modelsDir, "ControlNet") },
{
"controlnet",
string.Join('\n', Path.Combine(modelsDir, "ControlNet"), Path.Combine(modelsDir, "T2IAdapter"))
},
{ "clip", Path.Combine(modelsDir, "CLIP") },
{ "diffusers", Path.Combine(modelsDir, "Diffusers") },
{ "gligen", Path.Combine(modelsDir, "GLIGEN") },
@ -357,65 +394,46 @@ public class ComfyUI(
newRootNode.Children.Add(stabilityMatrixNode);
var serializer = new SerializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).Build();
var yamlData = serializer.Serialize(newRootNode);
File.WriteAllText(extraPathsYamlPath, yamlData);
var serializer = new SerializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.WithDefaultScalarStyle(ScalarStyle.Literal)
.Build();
return Task.CompletedTask;
var yamlData = serializer.Serialize(newRootNode);
await extraPathsYamlPath.WriteAllTextAsync(yamlData).ConfigureAwait(false);
}
public override Task UpdateModelFolders(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod) =>
sharedFolderMethod switch
{
SharedFolderMethod.Symlink => base.UpdateModelFolders(installDirectory, sharedFolderMethod),
SharedFolderMethod.Configuration => SetupModelFolders(installDirectory, sharedFolderMethod),
SharedFolderMethod.None => Task.CompletedTask,
_ => Task.CompletedTask
};
public override Task RemoveModelFolderLinks(DirectoryPath installDirectory, SharedFolderMethod sharedFolderMethod)
private static async Task RemoveConfigSection(DirectoryPath installDirectory)
{
return sharedFolderMethod switch
{
SharedFolderMethod.Configuration => RemoveConfigSection(installDirectory),
SharedFolderMethod.None => Task.CompletedTask,
SharedFolderMethod.Symlink => base.RemoveModelFolderLinks(installDirectory, sharedFolderMethod),
_ => Task.CompletedTask
};
}
var extraPathsYamlPath = installDirectory.JoinFile("extra_model_paths.yaml");
private Task RemoveConfigSection(string installDirectory)
{
var extraPathsYamlPath = Path.Combine(installDirectory, "extra_model_paths.yaml");
var exists = File.Exists(extraPathsYamlPath);
if (!exists)
if (!extraPathsYamlPath.Exists)
{
return Task.CompletedTask;
return;
}
var yaml = File.ReadAllText(extraPathsYamlPath);
var yaml = await extraPathsYamlPath.ReadAllTextAsync().ConfigureAwait(false);
using var sr = new StringReader(yaml);
var yamlStream = new YamlStream();
yamlStream.Load(sr);
if (!yamlStream.Documents.Any())
{
return Task.CompletedTask;
return;
}
var root = yamlStream.Documents[0].RootNode;
if (root is not YamlMappingNode mappingNode)
{
return Task.CompletedTask;
return;
}
mappingNode.Children.Remove("stability_matrix");
var serializer = new SerializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).Build();
var yamlData = serializer.Serialize(mappingNode);
File.WriteAllText(extraPathsYamlPath, yamlData);
return Task.CompletedTask;
await extraPathsYamlPath.WriteAllTextAsync(yamlData).ConfigureAwait(false);
}
private async Task InstallRocmTorch(

Loading…
Cancel
Save