diff --git a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs
index d653da77..5a8062cf 100644
--- a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs
+++ b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs
@@ -56,11 +56,11 @@ 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.T2IAdapter] = new[] { "models/controlnet/T2IAdapter" },
[SharedFolderType.IpAdapter] = new[] { "models/ipadapter" }
};
@@ -278,4 +278,23 @@ public class A3WebUI(
)
.ConfigureAwait(false);
}
+
+ ///
+ 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(true).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/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
index ac58db1f..8901d191 100644
--- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
+++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
@@ -54,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>? SharedOutputFolders =>
@@ -268,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)
{
- switch (sharedFolderMethod)
+ return sharedFolderMethod switch
{
- case SharedFolderMethod.None:
- return Task.CompletedTask;
- case SharedFolderMethod.Symlink:
- return base.SetupModelFolders(installDirectory, sharedFolderMethod);
+ 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)
+ {
+ // 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(true).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);
@@ -308,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");
@@ -371,63 +400,40 @@ public class ComfyUI(
.Build();
var yamlData = serializer.Serialize(newRootNode);
- File.WriteAllText(extraPathsYamlPath, yamlData);
-
- return Task.CompletedTask;
+ 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(