Compare commits

..

1 Commits

Author SHA1 Message Date
Ian Chua
d9fa43f1d7 fix: add opc support for ota workflow 2026-08-28 19:40:31 +08:00

View File

@@ -29,6 +29,7 @@
#include "libslic3r/format.hpp" #include "libslic3r/format.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "libslic3r/PresetBundle.hpp" #include "libslic3r/PresetBundle.hpp"
#include "libslic3r/PresetCacheFormat.hpp"
#include "libslic3r_version.h" #include "libslic3r_version.h"
#include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
@@ -96,6 +97,8 @@ struct Update
bool forced_update; bool forced_update;
//BBS: add directory support //BBS: add directory support
bool is_directory {false}; bool is_directory {false};
// Orca: a vendor update may be the cache-only form.
bool is_opc {false};
Update() {} Update() {}
//BBS: add directory support //BBS: add directory support
@@ -131,6 +134,18 @@ struct Update
} }
else { else {
copy_file_fix(source, target); copy_file_fix(source, target);
// A vendor must be installed in exactly one form. Remove the
// representation that would otherwise be stale or shadow this one.
boost::system::error_code ec;
if (is_opc) {
fs::remove(target.parent_path() / (vendor + ".json"), ec);
ec.clear();
fs::remove_all(target.parent_path() / vendor, ec);
}
else {
fs::remove(target.parent_path() / (vendor + ".opc"), ec);
}
} }
} }
@@ -708,6 +723,7 @@ void PresetUpdater::priv::sync_vendor_config(const std::string& vendor_id)
fs::remove_all(cache_profile_path / vendor_id, ec); fs::remove_all(cache_profile_path / vendor_id, ec);
fs::remove(cache_profile_path / (vendor_id + ".json"), ec); fs::remove(cache_profile_path / (vendor_id + ".json"), ec);
fs::remove(cache_profile_path / (vendor_id + ".changelog"), ec); fs::remove(cache_profile_path / (vendor_id + ".changelog"), ec);
fs::remove(cache_profile_path / (vendor_id + ".opc"), ec);
// Download the zip // Download the zip
BOOST_LOG_TRIVIAL(info) << "[Orca Updater] downloading update for " << vendor_id BOOST_LOG_TRIVIAL(info) << "[Orca Updater] downloading update for " << vendor_id
@@ -735,7 +751,7 @@ void PresetUpdater::priv::sync_vendor_config(const std::string& vendor_id)
if (!download_ok || cancel || vendor_check_cancel) return; if (!download_ok || cancel || vendor_check_cancel) return;
// Extract vendor profile bundles under ota/profiles. The downloaded zip contains // Extract vendor profile bundles under ota/profiles. The downloaded zip contains
// the vendor json/folder at its root. // either the vendor json/folder or the vendor cache at its root.
BOOST_LOG_TRIVIAL(info) << "[Orca Updater] extracting update for " << vendor_id; BOOST_LOG_TRIVIAL(info) << "[Orca Updater] extracting update for " << vendor_id;
if (!extract_file(download_file, cache_profile_path)) { if (!extract_file(download_file, cache_profile_path)) {
BOOST_LOG_TRIVIAL(warning) << "[Orca Updater] extraction failed for " << vendor_id; BOOST_LOG_TRIVIAL(warning) << "[Orca Updater] extraction failed for " << vendor_id;
@@ -1147,68 +1163,93 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
if (!fs::exists(cache_profile_path)) if (!fs::exists(cache_profile_path))
return updates; return updates;
for (auto &dir_entry : boost::filesystem::directory_iterator(cache_profile_path)) { for (auto &dir_entry : boost::filesystem::directory_iterator(cache_profile_path)) {
const auto &path = dir_entry.path(); const auto &path = dir_entry.path();
std::string file_path = path.string(); std::string file_path = path.string();
if (is_json_file(file_path)) { const bool is_opc_file = boost::iequals(path.extension().string(), ".opc");
const auto path_in_vendor = vendor_path / path.filename(); if (!is_json_file(file_path) && !is_opc_file)
std::string vendor_name = path.filename().string(); continue;
// Remove the .json suffix.
vendor_name.erase(vendor_name.size() - 5);
auto print_in_cache = (cache_profile_path / vendor_name / PRESET_PRINT_NAME);
auto filament_in_cache = (cache_profile_path / vendor_name / PRESET_FILAMENT_NAME);
auto machine_in_cache = (cache_profile_path / vendor_name / PRESET_PRINTER_NAME);
if (is_vendor_installed(vendor_name) const std::string vendor_name = path.stem().string();
|| fs::exists(print_in_cache) auto print_in_cache = (cache_profile_path / vendor_name / PRESET_PRINT_NAME);
|| fs::exists(filament_in_cache) auto filament_in_cache = (cache_profile_path / vendor_name / PRESET_FILAMENT_NAME);
|| fs::exists(machine_in_cache)) { auto machine_in_cache = (cache_profile_path / vendor_name / PRESET_PRINTER_NAME);
// Orca: a vendor installed as a preset cache carries its version there.
Semver vendor_ver = installed_vendor_version(vendor_name);
std::map<std::string, std::string> key_values; if (is_vendor_installed(vendor_name)
std::vector<std::string> keys(3); || is_opc_file
Semver cache_ver; || fs::exists(print_in_cache)
keys[0] = BBL_JSON_KEY_VERSION; || fs::exists(filament_in_cache)
keys[1] = BBL_JSON_KEY_DESCRIPTION; || fs::exists(machine_in_cache)) {
keys[2] = BBL_JSON_KEY_FORCE_UPDATE; // Orca: a vendor installed as a preset cache carries its version there.
get_values_from_json(file_path, keys, key_values); Semver vendor_ver = installed_vendor_version(vendor_name);
std::string description = key_values[BBL_JSON_KEY_DESCRIPTION];
bool force_update = false;
if (key_values.find(BBL_JSON_KEY_FORCE_UPDATE) != key_values.end())
force_update = (key_values[BBL_JSON_KEY_FORCE_UPDATE] == "1")?true:false;
auto config_version = Semver::parse(key_values[BBL_JSON_KEY_VERSION]);
if (config_version)
cache_ver = *config_version;
std::string changelog; Semver cache_ver;
std::string changelog_file = (cache_profile_path / (vendor_name + ".changelog")).string(); std::string description;
boost::nowide::ifstream ifs(changelog_file); bool force_update = false;
if (ifs) { if (is_opc_file) {
std::ostringstream oss; cache_ver = VendorCacheFile::usable_version(file_path, vendor_name);
oss<< ifs.rdbuf(); if (!cache_ver.valid()) {
changelog = oss.str(); BOOST_LOG_TRIVIAL(warning) << "[Orca Updater]:ignoring unreadable vendor cache " << file_path;
ifs.close(); continue;
} }
}
else {
std::map<std::string, std::string> key_values;
std::vector<std::string> keys(3);
keys[0] = BBL_JSON_KEY_VERSION;
keys[1] = BBL_JSON_KEY_DESCRIPTION;
keys[2] = BBL_JSON_KEY_FORCE_UPDATE;
get_values_from_json(file_path, keys, key_values);
description = key_values[BBL_JSON_KEY_DESCRIPTION];
if (key_values.find(BBL_JSON_KEY_FORCE_UPDATE) != key_values.end())
force_update = (key_values[BBL_JSON_KEY_FORCE_UPDATE] == "1")?true:false;
auto config_version = Semver::parse(key_values[BBL_JSON_KEY_VERSION]);
if (config_version)
cache_ver = *config_version;
}
if (vendor_ver < cache_ver) { std::string changelog;
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:need to update settings from " << vendor_ver.to_string() std::string changelog_file = (cache_profile_path / (vendor_name + ".changelog")).string();
<< " to newer version " << cache_ver.to_string() << ", app version " << SLIC3R_VERSION; boost::nowide::ifstream ifs(changelog_file);
Version version; if (ifs) {
version.config_version = cache_ver; std::ostringstream oss;
version.comment = description; oss<< ifs.rdbuf();
// Orca: update vendor.json changelog = oss.str();
updates.updates.emplace_back(std::move(file_path), path_in_vendor.string(), std::move(version), vendor_name, changelog, "", force_update, false); ifs.close();
//Orca: update vendor folder }
updates.updates.emplace_back(cache_profile_path / vendor_name, vendor_path / vendor_name, Version(), vendor_name, "", "", force_update, true);
} else { if (vendor_ver < cache_ver) {
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:cached settings for " << vendor_name BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:need to update settings from " << vendor_ver.to_string()
<< " are not newer than installed version, installed " << vendor_ver.to_string() << " to newer version " << cache_ver.to_string() << ", app version " << SLIC3R_VERSION;
<< ", cached " << cache_ver.to_string(); Version version;
} version.config_version = cache_ver;
} version.comment = description;
} if (is_opc_file) {
} // A cache contains the vendor profile and all presets.
// Install it directly; Update::install removes any
// superseded JSON representation.
auto &update = updates.updates.emplace_back(
std::move(file_path), vendor_path / (vendor_name + ".opc"),
std::move(version), vendor_name, changelog, "", force_update, false);
update.is_opc = true;
}
else {
// JSON profile and its preset directory are installed
// separately, as before.
updates.updates.emplace_back(std::move(file_path),
vendor_path / (vendor_name + ".json"), std::move(version),
vendor_name, changelog, "", force_update, false);
updates.updates.emplace_back(cache_profile_path / vendor_name,
vendor_path / vendor_name, Version(), vendor_name,
"", "", force_update, true);
}
} else {
BOOST_LOG_TRIVIAL(info) << "[Orca Updater]:cached settings for " << vendor_name
<< " are not newer than installed version, installed " << vendor_ver.to_string()
<< ", cached " << cache_ver.to_string();
}
}
}
return updates; return updates;
} }