From 3a48086f5d7800f2536a1acc1071c9ad2853fb1d Mon Sep 17 00:00:00 2001 From: Ian Chua Date: Mon, 20 Jul 2026 12:47:18 +0800 Subject: [PATCH] fix: plugin descriptor should not reply on changelog for latest version --- src/slic3r/plugin/PluginDescriptor.hpp | 6 +---- .../test_plugin_cloud_metadata.cpp | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/slic3r/plugin/PluginDescriptor.hpp b/src/slic3r/plugin/PluginDescriptor.hpp index 28c411b176..687b14d7c6 100644 --- a/src/slic3r/plugin/PluginDescriptor.hpp +++ b/src/slic3r/plugin/PluginDescriptor.hpp @@ -54,7 +54,7 @@ struct PluginDescriptor std::string description; // Plugin description std::string author; // Plugin author from manifest, if available std::string version; // Selected plugin version - std::string latest_version; // Latest available cloud version fallback when changelog is unavailable. + std::string latest_version; // Authoritative latest available cloud version. std::string installed_version; // Locally installed package version. Preserved across cloud merges, which overwrite `version` with the latest cloud version. Empty when not installed. std::vector display_types; // Display-only "compatibility" labels (cloud: raw service labels; local: from real capabilities). Never used for dispatch. std::string plugin_root; // Installed plugin directory, even when entry_path is invalid or ambiguous. @@ -113,10 +113,6 @@ struct PluginDescriptor bool is_unauthorized() const { return get_update_status() == PluginUpdateStatus::Unauthorized; } std::string latest_available_version() const { - for (const PluginChangelog& entry : changelog) { - if (!entry.version.empty()) - return entry.version; - } if (!latest_version.empty()) return latest_version; return version; diff --git a/tests/slic3rutils/test_plugin_cloud_metadata.cpp b/tests/slic3rutils/test_plugin_cloud_metadata.cpp index 6f438541ff..ec8b61dea9 100644 --- a/tests/slic3rutils/test_plugin_cloud_metadata.cpp +++ b/tests/slic3rutils/test_plugin_cloud_metadata.cpp @@ -52,6 +52,29 @@ print('ok') } // namespace +TEST_CASE("plugin latest version uses the authoritative catalog field", "[PluginDescriptor]") +{ + PluginDescriptor descriptor; + descriptor.version = "1.3.0"; + descriptor.latest_version = "1.3.0"; + PluginChangelog changelog; + changelog.version = "1.2.0"; + descriptor.changelog.push_back(changelog); + + CHECK(descriptor.latest_available_version() == "1.3.0"); +} + +TEST_CASE("plugin latest version falls back to the descriptor version", "[PluginDescriptor]") +{ + PluginDescriptor descriptor; + descriptor.version = "1.1.0"; + PluginChangelog changelog; + changelog.version = "1.0.0"; + descriptor.changelog.push_back(changelog); + + CHECK(descriptor.latest_available_version() == "1.1.0"); +} + // Regression: update_cloud_metadata() replaces a matched entry's descriptor wholesale with the // cloud catalog record (`entry = cloud_entry`). Configuration used to ride on the descriptor, so // that overwrite silently wiped it and plugins fell back to their built-in defaults (found via