Skip to content

Commit 6215a58

Browse files
committed
Merge pull request LykosAI#980 from ionite34/fix-model-overwrite
Fix models with same name overwriting each other on download & update… (cherry picked from commit 894c1ab) # Conflicts: # CHANGELOG.md # StabilityMatrix.Avalonia/Services/ModelImportService.cs
1 parent e7f2093 commit 6215a58

File tree

4 files changed

+228
-3
lines changed

4 files changed

+228
-3
lines changed

CHANGELOG.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,78 @@ All notable changes to Stability Matrix will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
77

8+
<<<<<<< HEAD
89
## v2.13.3
10+
=======
11+
## v2.14.0-dev.3
12+
### Changed
13+
- Upgraded ComfyUI CUDA torch to 12.6
14+
### Fixed
15+
- Fixed [#1128](https://github.com/LykosAI/StabilityMatrix/issues/1128) - overwriting models when downloading multiple with the same name
16+
- Fixed ROCm torch indexes for ComfyUI & Forge
17+
18+
## v2.14.0-dev.2
19+
>>>>>>> 894c1abe (Merge pull request #980 from ionite34/fix-model-overwrite)
920
### Added
1021
- Added Safetensor Metadata viewer to the Checkpoint Manager context menu - thanks to @genteure!
1122
### Changed
23+
<<<<<<< HEAD
24+
=======
25+
- Updated the Civitai Model Browser base model selector to match the new Checkpoint Manager filter UI
26+
- FaceDetailers in Inference will now inherit the primary sampler/scheduler/etc. by default. You can still manually set these by enabling the options via the ⚙️ button on the FaceDetailer card
27+
- Slightly rearranged the FaceDetailer card layout due to the above change
28+
- "Remove symbolic links on shutdown" option now also removes links from Output Sharing
29+
- Inference "Extra Networks" selector now filters extra networks based on the selected base model
30+
- Updated Japanese, Brazilian Portuguese, Chinese, and Russian translations
31+
### Fixed
32+
- Fixed crash when dragging & dropping images in Inference (hopefully)
33+
- Fixed HiresFix Inference addon not inheriting sampler/scheduler properly
34+
- Fixed some plus (+) buttons getting cut off in the Inference UI
35+
- Fixed CFG Rescale addon interfering with refiner model in Inference
36+
- Fixed [#1083](https://github.com/LykosAI/StabilityMatrix/issues/1083) - "Show Nested Models" incorrectly displaying models from some non-nested folders
37+
- Fixed issue with InvokeAI model sharing when the host address is set to 0.0.0.0
38+
- Fixed issue when parsing index URLs in Python Dependencies Override menu
39+
- Fixed ComfyUI-Zluda not respecting pip user overrides
40+
- Fixed issue with Checkpoint Manager not displaying any models
41+
- (dev.2 re-release) Fixed autocomplete not showing in certain cases when using wildcards
42+
- (dev.2 re-release) Fixed package restart button not working
43+
- (dev.2 re-release) Fixed [#1120](https://github.com/LykosAI/StabilityMatrix/issues/1120) - crash when right clicking in the console after restarting a package
44+
### Supporters
45+
#### Visionaries
46+
- A huge thank you to our incredible Visionary-tier Patreon supporters, **Waterclouds**, **TheTekknician**, and our newest Visionary, **Corey**! Your generous support is greatly appreciated!
47+
48+
## v2.14.0-dev.1
49+
### Added
50+
- Added Rescale CFG addon to Inference
51+
- Added Swap Dimensions button between the width/height input in Inference
52+
- Added Ctrl+Tab/Ctrl+Shift+Tab shortcuts for navigating between Inference tabs
53+
- Added OpenModelDB tab to the Model Browser
54+
### Changed
55+
- Improved the quality of Inference inpainting by upgrading the workflow behind the scenes. The workflow remains the same for you — just better results!
56+
- Redesigned the Checkpoint Manager Filter flyout to include more options and improve the layout
57+
- "Clear All" button will now remain at the top of the Downloads list regardless of scroll position - thanks to @Genteure!
58+
- Improved image metadata parsing - thanks to @Genteure!
59+
### Fixed
60+
- Fixed Inference image selector card buttons taking up the whole height of the card
61+
- Fixed Inference mask editor failing to paint to the right-most edge on large images
62+
- Fixed Inference mask editor not showing the entire image in certain circumstances
63+
- Fixed an issue where certain sampler/scheduler combos would not get saved in image metadata - thanks to @yansigit!
64+
- Fixed [#1078](https://github.com/LykosAI/StabilityMatrix/issues/1078) - "Call from invalid thread" error after one-click install finishes
65+
- Fixed [#1080](https://github.com/LykosAI/StabilityMatrix/issues/1080) - Some models not displayed in Checkpoint Manager
66+
### Supporters
67+
#### Visionaries
68+
- Many thanks to our incredible Visionary-tier Patreon supporters, **Waterclouds** and **TheTekknician**! Your support helps us continue to improve Stability Matrix!
69+
70+
## v2.13.4
71+
### Changed
72+
- Upgraded ComfyUI CUDA torch to 12.6
73+
### Fixed
74+
- Fixed [#1128](https://github.com/LykosAI/StabilityMatrix/issues/1128) - overwriting models when downloading multiple with the same name
75+
- Fixed ROCm torch indexes for ComfyUI & Forge
76+
77+
## v2.13.3
78+
### Changed
79+
>>>>>>> 894c1abe (Merge pull request #980 from ionite34/fix-model-overwrite)
1280
- "Remove symbolic links on shutdown" option now also removes links from Output Sharing
1381
### Fixed
1482
- Fixed [#1083](https://github.com/LykosAI/StabilityMatrix/issues/1083) - "Show Nested Models" incorrectly displaying models from some non-nested folders

StabilityMatrix.Avalonia/Services/ModelImportService.cs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@
55
using AsyncAwaitBestPractices;
66
using Avalonia.Controls.Notifications;
77
using Injectio.Attributes;
8+
<<<<<<< HEAD
9+
=======
10+
using Python.Runtime;
11+
using StabilityMatrix.Core.Extensions;
12+
>>>>>>> 894c1abe (Merge pull request #980 from ionite34/fix-model-overwrite)
813
using StabilityMatrix.Core.Models;
914
using StabilityMatrix.Core.Models.Api;
1015
using StabilityMatrix.Core.Models.FileInterfaces;
1116
using StabilityMatrix.Core.Models.Progress;
1217
using StabilityMatrix.Core.Services;
18+
using Dispatcher = Avalonia.Threading.Dispatcher;
1319

1420
namespace StabilityMatrix.Avalonia.Services;
1521

@@ -117,6 +123,23 @@ public async Task DoImport(
117123
modelFile.Name = Path.GetInvalidFileNameChars()
118124
.Aggregate(modelFile.Name, (current, c) => current.Replace(c, '_'));
119125

126+
// New code: Ensure unique file name
127+
var originalFileName = modelFile.Name;
128+
var uniqueFileName = GenerateUniqueFileName(downloadFolder.ToString(), originalFileName);
129+
if (!uniqueFileName.Equals(originalFileName, StringComparison.Ordinal))
130+
{
131+
Dispatcher.UIThread.Post(() =>
132+
{
133+
notificationService.Show(
134+
new Notification(
135+
"File renamed",
136+
$"A file with the name \"{originalFileName}\" already exists. The model will be saved as \"{uniqueFileName}\"."
137+
)
138+
);
139+
});
140+
modelFile.Name = uniqueFileName;
141+
}
142+
120143
var downloadPath = downloadFolder.JoinFile(modelFile.Name);
121144

122145
// Download model info and preview first
@@ -163,4 +186,138 @@ public async Task DoImport(
163186

164187
await trackedDownloadService.TryStartDownload(download);
165188
}
189+
<<<<<<< HEAD
190+
=======
191+
192+
public Task DoOpenModelDbImport(
193+
OpenModelDbKeyedModel model,
194+
OpenModelDbResource resource,
195+
DirectoryPath downloadFolder,
196+
Action<TrackedDownload>? configureDownload = null
197+
)
198+
{
199+
// todo: maybe can get actual filename from url?
200+
ArgumentException.ThrowIfNullOrEmpty(model.Id, nameof(model));
201+
ArgumentException.ThrowIfNullOrEmpty(resource.Type, nameof(resource));
202+
var modelFileName = $"{model.Id}.{resource.Type}";
203+
204+
var modelUris = resource.Urls?.Select(u => new Uri(u, UriKind.Absolute)).ToArray();
205+
if (modelUris is null || modelUris.Length == 0)
206+
{
207+
notificationService.Show(
208+
new Notification(
209+
"Model has no download links",
210+
"This model has no download links available",
211+
NotificationType.Warning
212+
)
213+
);
214+
return Task.CompletedTask;
215+
}
216+
217+
return DoCustomImport(
218+
modelUris,
219+
modelFileName,
220+
downloadFolder,
221+
model.Images?.SelectImageAbsoluteUris().FirstOrDefault(),
222+
configureDownload: configureDownload,
223+
connectedModelInfo: new ConnectedModelInfo(model, resource, DateTimeOffset.Now)
224+
);
225+
}
226+
227+
public async Task DoCustomImport(
228+
IEnumerable<Uri> modelUris,
229+
string modelFileName,
230+
DirectoryPath downloadFolder,
231+
Uri? previewImageUri = null,
232+
string? previewImageFileExtension = null,
233+
ConnectedModelInfo? connectedModelInfo = null,
234+
Action<TrackedDownload>? configureDownload = null
235+
)
236+
{
237+
// Folders might be missing if user didn't install any packages yet
238+
downloadFolder.Create();
239+
240+
// Fix invalid chars in FileName
241+
var modelBaseFileName = Path.GetFileNameWithoutExtension(modelFileName);
242+
modelBaseFileName = Path.GetInvalidFileNameChars()
243+
.Aggregate(modelBaseFileName, (current, c) => current.Replace(c, '_'));
244+
var modelFileExtension = Path.GetExtension(modelFileName);
245+
246+
var downloadPath = downloadFolder.JoinFile(modelBaseFileName + modelFileExtension);
247+
248+
// Save model info and preview image first if available
249+
var cleanupFilePaths = new List<string>();
250+
if (connectedModelInfo is not null)
251+
{
252+
await connectedModelInfo.SaveJsonToDirectory(downloadFolder, modelBaseFileName);
253+
cleanupFilePaths.Add(
254+
downloadFolder.JoinFile(modelBaseFileName + ConnectedModelInfo.FileExtension)
255+
);
256+
}
257+
if (previewImageUri is not null)
258+
{
259+
if (previewImageFileExtension is null)
260+
{
261+
previewImageFileExtension = Path.GetExtension(previewImageUri.LocalPath);
262+
if (string.IsNullOrEmpty(previewImageFileExtension))
263+
{
264+
throw new InvalidOperationException(
265+
"Unable to get preview image file extension from from Uri, and no file extension provided"
266+
);
267+
}
268+
}
269+
270+
var previewImageDownloadPath = downloadFolder.JoinFile(
271+
modelBaseFileName + ".preview" + previewImageFileExtension
272+
);
273+
274+
await notificationService.TryAsync(
275+
downloadService.DownloadToFileAsync(previewImageUri.ToString(), previewImageDownloadPath),
276+
"Could not download preview image"
277+
);
278+
279+
cleanupFilePaths.Add(previewImageDownloadPath);
280+
}
281+
282+
// Create tracked download
283+
// todo: support multiple uris
284+
var modelUri = modelUris.First();
285+
var download = trackedDownloadService.NewDownload(modelUri, downloadPath);
286+
287+
// Add hash info
288+
// download.ExpectedHashSha256 = modelFile.Hashes.SHA256;
289+
290+
// Add files to cleanup list
291+
download.ExtraCleanupFileNames.AddRange(cleanupFilePaths);
292+
293+
// Configure
294+
configureDownload?.Invoke(download);
295+
296+
// Add hash context action
297+
// download.ContextAction = CivitPostDownloadContextAction.FromCivitFile(modelFile);
298+
299+
await trackedDownloadService.TryStartDownload(download);
300+
}
301+
302+
private string GenerateUniqueFileName(string folder, string fileName)
303+
{
304+
var fullPath = Path.Combine(folder, fileName);
305+
if (!File.Exists(fullPath))
306+
return fileName;
307+
308+
var name = Path.GetFileNameWithoutExtension(fileName);
309+
var extension = Path.GetExtension(fileName);
310+
var count = 1;
311+
string newFileName;
312+
313+
do
314+
{
315+
newFileName = $"{name} ({count}){extension}";
316+
fullPath = Path.Combine(folder, newFileName);
317+
count++;
318+
} while (File.Exists(fullPath));
319+
320+
return newFileName;
321+
}
322+
>>>>>>> 894c1abe (Merge pull request #980 from ionite34/fix-model-overwrite)
166323
}

StabilityMatrix.Core/Models/Packages/ComfyUI.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ public override async Task InstallPackage(
219219
torchVersion switch
220220
{
221221
TorchIndex.Cpu => "cpu",
222-
TorchIndex.Cuda => "cu124",
223-
TorchIndex.Rocm => "rocm6.2",
222+
TorchIndex.Cuda => "cu126",
223+
TorchIndex.Rocm => "rocm6.2.4",
224224
TorchIndex.Mps => "cpu",
225225
_
226226
=> throw new ArgumentOutOfRangeException(

StabilityMatrix.Core/Models/Packages/SDWebForge.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public override async Task InstallPackage(
161161
{
162162
TorchIndex.Cpu => "cpu",
163163
TorchIndex.Cuda => "cu121",
164-
TorchIndex.Rocm => "rocm5.6",
164+
TorchIndex.Rocm => "rocm5.7",
165165
TorchIndex.Mps => "cpu",
166166
_ => throw new ArgumentOutOfRangeException(nameof(torchVersion), torchVersion, null)
167167
}

0 commit comments

Comments
 (0)