Skip to content

Commit f582d82

Browse files
committed
Fix unicode issues when scanning through models, and improve error handling
1 parent 5a1acc1 commit f582d82

1 file changed

Lines changed: 75 additions & 14 deletions

File tree

src/model_manager.cpp

Lines changed: 75 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -117,32 +117,90 @@ void ModelManager::scanDirectoryInternal(const std::string& directory, ModelType
117117
}
118118

119119
std::vector<ModelInfo> found_models;
120+
int processed_count = 0;
120121

121122
try {
122-
for (const auto& entry : fs::recursive_directory_iterator(directory)) {
123-
if (!entry.is_regular_file()) {
123+
// Use error_code overload to prevent exceptions from blocking iteration
124+
std::error_code ec;
125+
fs::recursive_directory_iterator it(directory, fs::directory_options::skip_permission_denied, ec);
126+
127+
if (ec) {
128+
LOG_ERROR("Cannot create directory iterator for %s: %s", directory.c_str(), ec.message().c_str());
129+
return;
130+
}
131+
132+
for (const auto& entry : it) {
133+
processed_count++;
134+
135+
// Log progress every 50 files for user feedback
136+
if (processed_count % 50 == 0) {
137+
LOG_INFO("Scanning %s directory: processed %d files...", getModelTypeString(type).c_str(),
138+
processed_count);
139+
}
140+
141+
// Skip non-regular files with error handling
142+
std::error_code file_ec;
143+
bool is_regular = entry.is_regular_file(file_ec);
144+
if (file_ec || !is_regular) {
145+
if (file_ec) {
146+
LOG_VERBOSE("Skipping entry (cannot determine file type): %s", entry.path().string().c_str());
147+
}
124148
continue;
125149
}
126150

127-
std::string filename = entry.path().filename().string();
151+
// Try to get the path strings - use generic_string() for better Unicode support
152+
std::string filename;
153+
std::string full_path;
154+
try {
155+
// generic_string() handles Unicode better than string() on Windows
156+
filename = entry.path().filename().generic_string();
157+
full_path = entry.path().generic_string();
158+
} catch (const std::exception& e) {
159+
// Fallback to regular string() if generic_string() fails
160+
try {
161+
filename = entry.path().filename().string();
162+
full_path = entry.path().string();
163+
LOG_VERBOSE("Using string() for path: %s", filename.c_str());
164+
} catch (...) {
165+
LOG_WARNING("Cannot convert path to string, skipping file: %s", e.what());
166+
continue;
167+
}
168+
}
169+
128170
if (!isValidModelFile(filename)) {
129171
continue;
130172
}
131173

132-
std::string full_path = entry.path().string();
133-
size_t file_size = fs::file_size(entry.path());
174+
// Get file size with error handling - don't let this block the scan
175+
size_t file_size = 0;
176+
try {
177+
file_size = fs::file_size(entry.path(), file_ec);
178+
if (file_ec) {
179+
LOG_VERBOSE("Cannot get file size for %s: %s, using 0", filename.c_str(),
180+
file_ec.message().c_str());
181+
file_size = 0;
182+
}
183+
} catch (const std::exception& e) {
184+
LOG_VERBOSE("Cannot get file size for %s: %s, using 0", filename.c_str(), e.what());
185+
file_size = 0;
186+
}
134187

135188
// Determine the lookup name based on model type
136189
std::string lookup_name;
137-
if (type == ModelType::CHECKPOINT) {
138-
// For stable-diffusion models: use relative path from directory with extension
139-
fs::path relative = fs::relative(entry.path(), directory);
140-
lookup_name = relative.string();
141-
} else if (type == ModelType::CONTROLNET || type == ModelType::EMBEDDINGS || type == ModelType::LORA) {
142-
// For controlnet, embeddings, lora: use filename without extension
143-
lookup_name = entry.path().stem().string();
144-
} else {
145-
// For other model types: use filename as-is
190+
try {
191+
if (type == ModelType::CHECKPOINT) {
192+
// For stable-diffusion models: use relative path from directory with extension
193+
fs::path relative = fs::relative(entry.path(), directory);
194+
lookup_name = relative.string();
195+
} else if (type == ModelType::CONTROLNET || type == ModelType::EMBEDDINGS || type == ModelType::LORA) {
196+
// For controlnet, embeddings, lora: use filename without extension
197+
lookup_name = entry.path().stem().string();
198+
} else {
199+
// For other model types: use filename as-is
200+
lookup_name = filename;
201+
}
202+
} catch (const std::exception& e) {
203+
LOG_WARNING("Cannot process path for %s: %s, using filename", filename.c_str(), e.what());
146204
lookup_name = filename;
147205
}
148206

@@ -155,6 +213,9 @@ void ModelManager::scanDirectoryInternal(const std::string& directory, ModelType
155213
} catch (const fs::filesystem_error& e) {
156214
LOG_ERROR("Error scanning directory %s: %s", directory.c_str(), e.what());
157215
return;
216+
} catch (const std::exception& e) {
217+
LOG_ERROR("Unexpected error scanning directory %s: %s", directory.c_str(), e.what());
218+
return;
158219
}
159220

160221
// Update the models_ map (already locked by caller)

0 commit comments

Comments
 (0)