fix(cli): resolve inherited presets through vendor manifests (#15438)

* fix(cli): resolve inherited presets through vendor manifests

* fix(cli): resolve typeless inherited presets

Probe the configured preset collections when a preset JSON omits its type. Reject missing, cross-type, and duplicate identities instead of silently selecting a candidate.

* fix(cli): allow missing app config during preset resolution

* fix(cli): tolerate malformed app config during preset resolution
This commit is contained in:
Maximilian Ghazanfar
2026-09-08 12:12:55 +08:00
committed by GitHub
parent c61d2fe5d1
commit bcb4f17d9a
8 changed files with 718 additions and 44 deletions
+12 -10
View File
@@ -1653,7 +1653,7 @@ std::string PresetCollection::canonical_preset_name(const std::string &name, con
void PresetCollection::load_presets(
const std::string &dir_path, const std::string &subdir,
PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule substitution_rule,
std::function<void(Preset&)> preset_loaded_fn, const PresetOrigin &load_origin)
std::function<void(Preset&)> preset_loaded_fn, const PresetOrigin &load_origin, bool read_only)
{
// Don't use boost::filesystem::canonical() on Windows, it is broken in regard to reparse points,
// see https://github.com/prusa3d/PrusaSlicer/issues/732
@@ -1662,7 +1662,7 @@ void PresetCollection::load_presets(
// Load custom roots first
if (fs::exists(dir / "base")) {
load_presets(dir.string(), "base", substitutions, substitution_rule, nullptr, resolved_origin);
load_presets(dir.string(), "base", substitutions, substitution_rule, nullptr, resolved_origin, read_only);
}
//BBS: add config related logs
@@ -1670,7 +1670,8 @@ void PresetCollection::load_presets(
//BBS do not parse folder if not exists
m_dir_path = dir.string();
if (!fs::exists(dir)) {
fs::create_directory(dir);
if (!read_only)
fs::create_directory(dir);
return;
}
@@ -1720,10 +1721,10 @@ void PresetCollection::load_presets(
substitutions.push_back({ preset.name, m_type, PresetConfigSubstitutions::Source::UserFile, preset.file, std::move(config_substitutions) });
if (!reason.empty()) {
fs::path file_path(preset.file);
if (fs::exists(file_path))
if (!read_only && fs::exists(file_path))
fs::remove(file_path);
file_path.replace_extension(".info");
if (fs::exists(file_path))
if (!read_only && fs::exists(file_path))
fs::remove(file_path);
BOOST_LOG_TRIVIAL(error) << boost::format("parse config %1% failed")%preset.file;
++m_errors;
@@ -1794,7 +1795,8 @@ void PresetCollection::load_presets(
size_t at_pos = name.find('@');
if (at_pos != std::string::npos && at_pos + 1 < name.length()) {
compatible_printers->values.push_back(name.substr(at_pos + 1));
preset.save(nullptr);
if (!read_only)
preset.save(nullptr);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " added compatible_printers for preset: " << name;
}
}
@@ -1812,10 +1814,10 @@ void PresetCollection::load_presets(
++m_errors;
BOOST_LOG_TRIVIAL(error) << boost::format("The user-config cannot be loaded: %1%. Reason: %2%")%preset.file %err.what();
fs::path file_path(preset.file);
if (fs::exists(file_path))
if (!read_only && fs::exists(file_path))
fs::remove(file_path);
file_path.replace_extension(".info");
if (fs::exists(file_path))
if (!read_only && fs::exists(file_path))
fs::remove(file_path);
//throw Slic3r::RuntimeError(std::string("The selected preset cannot be loaded: ") + preset.file + "\n\tReason: " + err.what());
} catch (const std::runtime_error &err) {
@@ -1823,10 +1825,10 @@ void PresetCollection::load_presets(
BOOST_LOG_TRIVIAL(error) << boost::format("Failed loading the user-config file: %1%. Reason: %2%")%preset.file %err.what();
//throw Slic3r::RuntimeError(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what());
fs::path file_path(preset.file);
if (fs::exists(file_path))
if (!read_only && fs::exists(file_path))
fs::remove(file_path);
file_path.replace_extension(".info");
if (fs::exists(file_path))
if (!read_only && fs::exists(file_path))
fs::remove(file_path);
}