mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-14 04:27:36 +00:00
Cut redundant work and duplication from the preset cache paths
The schema fingerprint, filament library version and cache blob are no longer recomputed, re-read or copied once per vendor on the startup path, and the setup wizard's completeness check now sees vendors shipped as caches alone. Duplicated reset/join/slurp blocks are folded into helpers.
This commit is contained in:
@@ -6,7 +6,6 @@
|
|||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
|
|||||||
@@ -27,6 +27,9 @@
|
|||||||
|
|
||||||
#include <cereal/access.hpp>
|
#include <cereal/access.hpp>
|
||||||
#include <cereal/types/base_class.hpp>
|
#include <cereal/types/base_class.hpp>
|
||||||
|
// The serialize() members below archive ConfigOption hierarchies through
|
||||||
|
// cereal::base_class, whose registration machinery lives in polymorphic.hpp.
|
||||||
|
#include <cereal/types/polymorphic.hpp>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
struct FloatOrPercent
|
struct FloatOrPercent
|
||||||
|
|||||||
@@ -16,13 +16,7 @@
|
|||||||
#include "Semver.hpp"
|
#include "Semver.hpp"
|
||||||
#include "ProjectTask.hpp"
|
#include "ProjectTask.hpp"
|
||||||
|
|
||||||
#include <cereal/archives/binary.hpp>
|
#include <cereal/access.hpp>
|
||||||
#include <cereal/cereal.hpp>
|
|
||||||
#include <cereal/types/map.hpp>
|
|
||||||
#include <cereal/types/polymorphic.hpp>
|
|
||||||
#include <cereal/types/set.hpp>
|
|
||||||
#include <cereal/types/string.hpp>
|
|
||||||
#include <cereal/types/vector.hpp>
|
|
||||||
|
|
||||||
//BBS: change system directories
|
//BBS: change system directories
|
||||||
#define PRESET_SYSTEM_DIR "system"
|
#define PRESET_SYSTEM_DIR "system"
|
||||||
|
|||||||
@@ -6,8 +6,11 @@
|
|||||||
#include "PresetBundle.hpp"
|
#include "PresetBundle.hpp"
|
||||||
|
|
||||||
#include <boost/crc.hpp>
|
#include <boost/crc.hpp>
|
||||||
|
#include <boost/iostreams/device/array.hpp>
|
||||||
|
#include <boost/iostreams/stream.hpp>
|
||||||
#include <cereal/archives/binary.hpp>
|
#include <cereal/archives/binary.hpp>
|
||||||
#include <cereal/types/map.hpp>
|
#include <cereal/types/map.hpp>
|
||||||
|
#include <cereal/types/set.hpp>
|
||||||
#include <cereal/types/string.hpp>
|
#include <cereal/types/string.hpp>
|
||||||
#include <cereal/types/vector.hpp>
|
#include <cereal/types/vector.hpp>
|
||||||
#include "PrintConfig.hpp"
|
#include "PrintConfig.hpp"
|
||||||
@@ -2281,6 +2284,15 @@ Semver installed_vendor_version(const std::string& vendor)
|
|||||||
return ver ? *ver : Semver();
|
return ver ? *ver : Semver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove_installed_vendor(const std::string& vendor)
|
||||||
|
{
|
||||||
|
const boost::filesystem::path dir = boost::filesystem::path(data_dir()) / PRESET_SYSTEM_DIR;
|
||||||
|
boost::filesystem::remove(dir / (vendor + ".json"));
|
||||||
|
boost::filesystem::remove(dir / (vendor + ".opc"));
|
||||||
|
if (boost::filesystem::exists(dir / vendor))
|
||||||
|
boost::filesystem::remove_all(dir / vendor);
|
||||||
|
}
|
||||||
|
|
||||||
std::set<std::string> vendor_names_in(const boost::filesystem::path& dir)
|
std::set<std::string> vendor_names_in(const boost::filesystem::path& dir)
|
||||||
{
|
{
|
||||||
std::set<std::string> names;
|
std::set<std::string> names;
|
||||||
@@ -2298,21 +2310,21 @@ std::set<std::string> vendor_names_in(const boost::filesystem::path& dir)
|
|||||||
// generated before that profile was bumped is out of date, and a cache that cannot
|
// generated before that profile was bumped is out of date, and a cache that cannot
|
||||||
// be read is no installation at all — and the vendor is installed the way it was
|
// be read is no installation at all — and the vendor is installed the way it was
|
||||||
// before caches existed, as its profile and the preset JSONs it points at. Returns
|
// before caches existed, as its profile and the preset JSONs it points at. Returns
|
||||||
// the version the cache is stamped with, or nothing when it is not the form to install.
|
// the version the cache is stamped with, invalid when it is not the form to install.
|
||||||
static std::string installable_cache_version(const boost::filesystem::path& dir, const std::string& vendor)
|
static Semver installable_cache_version(const boost::filesystem::path& dir, const std::string& vendor)
|
||||||
{
|
{
|
||||||
const auto cache_ver = Semver::parse(PresetBundle::peek_vendor_cache_version((dir / (vendor + ".opc")).string(), vendor));
|
const auto cache_ver = Semver::parse(PresetBundle::peek_vendor_cache_version((dir / (vendor + ".opc")).string(), vendor));
|
||||||
if (! cache_ver)
|
if (! cache_ver)
|
||||||
return {};
|
return Semver::invalid();
|
||||||
const Semver profile_ver = get_version_from_json((dir / (vendor + ".json")).string());
|
const Semver profile_ver = get_version_from_json((dir / (vendor + ".json")).string());
|
||||||
return profile_ver.valid() && *cache_ver < profile_ver ? std::string() : cache_ver->to_string();
|
return profile_ver.valid() && *cache_ver < profile_ver ? Semver::invalid() : *cache_ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
Semver resource_vendor_version(const std::string& vendor)
|
Semver resource_vendor_version(const std::string& vendor)
|
||||||
{
|
{
|
||||||
const boost::filesystem::path dir = boost::filesystem::path(resources_dir()) / "profiles";
|
const boost::filesystem::path dir = boost::filesystem::path(resources_dir()) / "profiles";
|
||||||
const auto ver = Semver::parse(installable_cache_version(dir, vendor));
|
const Semver ver = installable_cache_version(dir, vendor);
|
||||||
return ver ? *ver : get_version_from_json((dir / (vendor + ".json")).string());
|
return ver.valid() ? ver : get_version_from_json((dir / (vendor + ".json")).string());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool install_vendor_bundles_from_resources(
|
bool install_vendor_bundles_from_resources(
|
||||||
@@ -2347,7 +2359,7 @@ bool install_vendor_bundles_from_resources(
|
|||||||
|
|
||||||
std::string error_message;
|
std::string error_message;
|
||||||
bool installed_cache = false;
|
bool installed_cache = false;
|
||||||
if (! installable_cache_version(rsrc_path, bundle).empty()) {
|
if (installable_cache_version(rsrc_path, bundle).valid()) {
|
||||||
installed_cache = copy_file(cache_in_rsrc.string(), cache_in_vendors.string(), error_message, false) == CopyFileResult::SUCCESS;
|
installed_cache = copy_file(cache_in_rsrc.string(), cache_in_vendors.string(), error_message, false) == CopyFileResult::SUCCESS;
|
||||||
if (! installed_cache)
|
if (! installed_cache)
|
||||||
BOOST_LOG_TRIVIAL(warning) << "Failed to copy " << bundle << ".opc: " << error_message;
|
BOOST_LOG_TRIVIAL(warning) << "Failed to copy " << bundle << ".opc: " << error_message;
|
||||||
@@ -2405,6 +2417,17 @@ bool install_vendor_bundles_from_resources(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// m_printer_hold_alias survives reset() (and a cache body that failed partway
|
||||||
|
// in), so every full-bundle rebuild clears all five collections' maps by hand.
|
||||||
|
void PresetBundle::clear_printer_hold_aliases()
|
||||||
|
{
|
||||||
|
this->prints.m_printer_hold_alias.clear();
|
||||||
|
this->sla_prints.m_printer_hold_alias.clear();
|
||||||
|
this->filaments.m_printer_hold_alias.clear();
|
||||||
|
this->sla_materials.m_printer_hold_alias.clear();
|
||||||
|
this->printers.m_printer_hold_alias.clear();
|
||||||
|
}
|
||||||
|
|
||||||
//BBS: add json related logic, load system presets from json
|
//BBS: add json related logic, load system presets from json
|
||||||
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_presets_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule)
|
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_presets_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule)
|
||||||
{
|
{
|
||||||
@@ -2456,11 +2479,7 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
|||||||
// Match a fresh launch before parsing: hold aliases and the error
|
// Match a fresh launch before parsing: hold aliases and the error
|
||||||
// counter survive reset(), and would otherwise leak prior-cycle
|
// counter survive reset(), and would otherwise leak prior-cycle
|
||||||
// state into the library cache the load below writes.
|
// state into the library cache the load below writes.
|
||||||
this->prints.m_printer_hold_alias.clear();
|
this->clear_printer_hold_aliases();
|
||||||
this->sla_prints.m_printer_hold_alias.clear();
|
|
||||||
this->filaments.m_printer_hold_alias.clear();
|
|
||||||
this->sla_materials.m_printer_hold_alias.clear();
|
|
||||||
this->printers.m_printer_hold_alias.clear();
|
|
||||||
this->m_errors = 0;
|
this->m_errors = 0;
|
||||||
append(substitutions, this->load_vendor_configs_from_json(dir.string(), orca_lib_vendor, PresetBundle::LoadSystem, compatibility_rule).first);
|
append(substitutions, this->load_vendor_configs_from_json(dir.string(), orca_lib_vendor, PresetBundle::LoadSystem, compatibility_rule).first);
|
||||||
first = false;
|
first = false;
|
||||||
@@ -2479,6 +2498,11 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
|||||||
std::vector<PresetsConfigSubstitutions> parallel_substitutions(other_vendors.size());
|
std::vector<PresetsConfigSubstitutions> parallel_substitutions(other_vendors.size());
|
||||||
std::vector<std::string> parallel_errors(other_vendors.size());
|
std::vector<std::string> parallel_errors(other_vendors.size());
|
||||||
|
|
||||||
|
// The filament library version every vendor below is judged against. Fixed
|
||||||
|
// from here on — step 1 was the last thing that could touch the library on
|
||||||
|
// disk — so resolve it once instead of once per vendor.
|
||||||
|
const std::string lib_version = effective_lib_version(dir);
|
||||||
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, other_vendors.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, other_vendors.size()),
|
||||||
[&](const tbb::blocked_range<size_t>& range) {
|
[&](const tbb::blocked_range<size_t>& range) {
|
||||||
for (size_t i = range.begin(); i < range.end(); ++i) {
|
for (size_t i = range.begin(); i < range.end(); ++i) {
|
||||||
@@ -2487,7 +2511,7 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
|||||||
bundle->set_generate_vendor_caches(m_generate_vendor_caches);
|
bundle->set_generate_vendor_caches(m_generate_vendor_caches);
|
||||||
try {
|
try {
|
||||||
auto result = bundle->load_vendor_configs_from_json(
|
auto result = bundle->load_vendor_configs_from_json(
|
||||||
dir.string(), other_vendors[i], PresetBundle::LoadSystem, compatibility_rule, this);
|
dir.string(), other_vendors[i], PresetBundle::LoadSystem, compatibility_rule, this, lib_version);
|
||||||
parallel_substitutions[i] = std::move(result.first);
|
parallel_substitutions[i] = std::move(result.first);
|
||||||
parallel_bundles[i] = std::move(bundle);
|
parallel_bundles[i] = std::move(bundle);
|
||||||
} catch (const std::runtime_error &err) {
|
} catch (const std::runtime_error &err) {
|
||||||
@@ -4953,7 +4977,8 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||||||
|
|
||||||
//BBS: Load a config bundle file from json
|
//BBS: Load a config bundle file from json
|
||||||
std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_from_json(
|
std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_from_json(
|
||||||
const std::string &dir, const std::string &vendor_name, LoadConfigBundleAttributes flags, ForwardCompatibilitySubstitutionRule compatibility_rule, const PresetBundle* base_bundle)
|
const std::string &dir, const std::string &vendor_name, LoadConfigBundleAttributes flags, ForwardCompatibilitySubstitutionRule compatibility_rule, const PresetBundle* base_bundle,
|
||||||
|
const std::string &lib_version_hint)
|
||||||
{
|
{
|
||||||
// Enable substitutions for user config bundle, throw an exception when loading a system profile.
|
// Enable substitutions for user config bundle, throw an exception when loading a system profile.
|
||||||
ConfigSubstitutionContext substitution_context { compatibility_rule };
|
ConfigSubstitutionContext substitution_context { compatibility_rule };
|
||||||
@@ -4969,7 +4994,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||||||
// scans want a slice of one. Validation reads the JSONs whatever is cached.
|
// scans want a slice of one. Validation reads the JSONs whatever is cached.
|
||||||
const boost::filesystem::path dir_path(dir);
|
const boost::filesystem::path dir_path(dir);
|
||||||
const bool cacheable = flags.has(LoadConfigBundleAttribute::LoadSystem) && ! flags.has(LoadConfigBundleAttribute::LoadFilamentOnly);
|
const bool cacheable = flags.has(LoadConfigBundleAttribute::LoadSystem) && ! flags.has(LoadConfigBundleAttribute::LoadFilamentOnly);
|
||||||
if (cacheable && ! validation_mode && this->load_vendor_cache(dir_path, vendor_name)) {
|
if (cacheable && ! validation_mode && this->load_vendor_cache(dir_path, vendor_name, lib_version_hint)) {
|
||||||
size_t presets_loaded = 0;
|
size_t presets_loaded = 0;
|
||||||
for (const PresetCollection* coll : std::initializer_list<const PresetCollection*>{
|
for (const PresetCollection* coll : std::initializer_list<const PresetCollection*>{
|
||||||
&this->prints, &this->sla_prints, &this->filaments, &this->sla_materials, &this->printers })
|
&this->prints, &this->sla_prints, &this->filaments, &this->sla_materials, &this->printers })
|
||||||
@@ -5550,7 +5575,8 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||||||
const std::string version = vendor_profile.config_version.to_string();
|
const std::string version = vendor_profile.config_version.to_string();
|
||||||
// The library is its own reference point; every other vendor's cache holds
|
// The library is its own reference point; every other vendor's cache holds
|
||||||
// filaments resolved against it, and is stamped with the version in effect.
|
// filaments resolved against it, and is stamped with the version in effect.
|
||||||
const std::string lib_version = vendor_name == ORCA_FILAMENT_LIBRARY ? version : effective_lib_version(dir_path);
|
const std::string lib_version = vendor_name == ORCA_FILAMENT_LIBRARY ? version
|
||||||
|
: ! lib_version_hint.empty() ? lib_version_hint : effective_lib_version(dir_path);
|
||||||
if (! lib_version.empty() &&
|
if (! lib_version.empty() &&
|
||||||
! this->save_vendor_cache((dir_path / (vendor_name + ".opc")).string(), vendor_name, version, lib_version))
|
! this->save_vendor_cache((dir_path / (vendor_name + ".opc")).string(), vendor_name, version, lib_version))
|
||||||
BOOST_LOG_TRIVIAL(warning) << "PresetBundle: failed to save vendor cache for " << vendor_name;
|
BOOST_LOG_TRIVIAL(warning) << "PresetBundle: failed to save vendor cache for " << vendor_name;
|
||||||
@@ -6218,8 +6244,11 @@ static bool cache_covers_version(const std::string& cached, const std::string& o
|
|||||||
// values — serialization_key_ordinal IS the config wire format). Any mismatch
|
// values — serialization_key_ordinal IS the config wire format). Any mismatch
|
||||||
// means bytes written by another build could deserialize into the wrong
|
// means bytes written by another build could deserialize into the wrong
|
||||||
// fields, so the cache is rejected wholesale before its body is read.
|
// fields, so the cache is rejected wholesale before its body is read.
|
||||||
std::string compute_cache_schema_fingerprint()
|
const std::string& compute_cache_schema_fingerprint()
|
||||||
{
|
{
|
||||||
|
// Constant for the lifetime of the process (print_config_def is immutable
|
||||||
|
// after static initialization), and asked for once per cache load and save.
|
||||||
|
static const std::string fingerprint = [] {
|
||||||
std::string schema;
|
std::string schema;
|
||||||
schema += SLIC3R_VERSION;
|
schema += SLIC3R_VERSION;
|
||||||
schema += ';';
|
schema += ';';
|
||||||
@@ -6233,6 +6262,8 @@ std::string compute_cache_schema_fingerprint()
|
|||||||
boost::crc_32_type crc;
|
boost::crc_32_type crc;
|
||||||
crc.process_bytes(schema.data(), schema.size());
|
crc.process_bytes(schema.data(), schema.size());
|
||||||
return std::to_string(crc.checksum());
|
return std::to_string(crc.checksum());
|
||||||
|
}();
|
||||||
|
return fingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
@@ -6268,7 +6299,7 @@ bool PresetBundle::read_cache_blob(const std::string& path, std::string& out_blo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void PresetBundle::write_cache_blob(const std::string& path, const std::string& blob)
|
bool PresetBundle::write_cache_blob(const std::string& path, const std::string& blob)
|
||||||
{
|
{
|
||||||
boost::crc_32_type crc;
|
boost::crc_32_type crc;
|
||||||
crc.process_bytes(blob.data(), blob.size());
|
crc.process_bytes(blob.data(), blob.size());
|
||||||
@@ -6277,7 +6308,7 @@ void PresetBundle::write_cache_blob(const std::string& path, const std::string&
|
|||||||
boost::nowide::ofstream ofs(path, std::ios::binary | std::ios::trunc);
|
boost::nowide::ofstream ofs(path, std::ios::binary | std::ios::trunc);
|
||||||
if (!ofs.is_open()) {
|
if (!ofs.is_open()) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << "SystemPresetsCache: cannot open for writing: " << path;
|
BOOST_LOG_TRIVIAL(warning) << "SystemPresetsCache: cannot open for writing: " << path;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
CacheFileHeader fhdr;
|
CacheFileHeader fhdr;
|
||||||
fhdr.magic = CACHE_MAGIC;
|
fhdr.magic = CACHE_MAGIC;
|
||||||
@@ -6286,8 +6317,13 @@ void PresetBundle::write_cache_blob(const std::string& path, const std::string&
|
|||||||
fhdr.crc32 = crc.checksum();
|
fhdr.crc32 = crc.checksum();
|
||||||
ofs.write(reinterpret_cast<const char*>(&fhdr), sizeof(fhdr));
|
ofs.write(reinterpret_cast<const char*>(&fhdr), sizeof(fhdr));
|
||||||
ofs.write(blob.data(), static_cast<std::streamsize>(blob.size()));
|
ofs.write(blob.data(), static_cast<std::streamsize>(blob.size()));
|
||||||
|
ofs.close(); // flush; close() raises failbit on error
|
||||||
|
if (! ofs.good())
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "SystemPresetsCache: write failed (" << path << ")";
|
||||||
|
return ofs.good();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << "SystemPresetsCache: write failed (" << path << "): " << e.what();
|
BOOST_LOG_TRIVIAL(warning) << "SystemPresetsCache: write failed (" << path << "): " << e.what();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6373,9 +6409,7 @@ bool PresetBundle::save_vendor_cache(const std::string& cache_path, const std::s
|
|||||||
this->obsolete_presets.printers);
|
this->obsolete_presets.printers);
|
||||||
ar(this->m_errors);
|
ar(this->m_errors);
|
||||||
}
|
}
|
||||||
write_cache_blob(cache_path, body.str());
|
return write_cache_blob(cache_path, body.str());
|
||||||
std::string verify;
|
|
||||||
return read_cache_blob(cache_path, verify); // magic + size + CRC
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << "PresetBundle: failed to save vendor cache " << cache_path << ": " << e.what();
|
BOOST_LOG_TRIVIAL(warning) << "PresetBundle: failed to save vendor cache " << cache_path << ": " << e.what();
|
||||||
return false;
|
return false;
|
||||||
@@ -6415,7 +6449,7 @@ std::string PresetBundle::peek_vendor_cache_version(const std::string& cache_pat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PresetBundle::load_vendor_cache(const boost::filesystem::path& dir, const std::string& vendor_name)
|
bool PresetBundle::load_vendor_cache(const boost::filesystem::path& dir, const std::string& vendor_name, const std::string& lib_version_hint)
|
||||||
{
|
{
|
||||||
// Whichever cache answers is judged against the vendor as installed in `dir`:
|
// Whichever cache answers is judged against the vendor as installed in `dir`:
|
||||||
// the profile there, or — with none, as when the cache is the whole of the
|
// the profile there, or — with none, as when the cache is the whole of the
|
||||||
@@ -6425,7 +6459,7 @@ bool PresetBundle::load_vendor_cache(const boost::filesystem::path& dir, const s
|
|||||||
const boost::filesystem::path profile = dir / (vendor_name + ".json");
|
const boost::filesystem::path profile = dir / (vendor_name + ".json");
|
||||||
const std::string version = boost::filesystem::exists(profile) ? get_vendor_cache_version(profile.string())
|
const std::string version = boost::filesystem::exists(profile) ? get_vendor_cache_version(profile.string())
|
||||||
: std::string(CACHE_ANY_VERSION);
|
: std::string(CACHE_ANY_VERSION);
|
||||||
const std::string lib_version = effective_lib_version(dir);
|
const std::string lib_version = ! lib_version_hint.empty() ? lib_version_hint : effective_lib_version(dir);
|
||||||
const boost::filesystem::path rsrc = boost::filesystem::path(resources_dir()) / "profiles";
|
const boost::filesystem::path rsrc = boost::filesystem::path(resources_dir()) / "profiles";
|
||||||
return this->load_vendor_cache((dir / (vendor_name + ".opc")).string(), vendor_name, version, lib_version)
|
return this->load_vendor_cache((dir / (vendor_name + ".opc")).string(), vendor_name, version, lib_version)
|
||||||
|| (dir != rsrc && this->load_vendor_cache((rsrc / (vendor_name + ".opc")).string(), vendor_name, version, lib_version));
|
|| (dir != rsrc && this->load_vendor_cache((rsrc / (vendor_name + ".opc")).string(), vendor_name, version, lib_version));
|
||||||
@@ -6438,7 +6472,9 @@ bool PresetBundle::load_vendor_cache(const std::string& cache_path, const std::s
|
|||||||
if (! read_cache_blob(cache_path, blob))
|
if (! read_cache_blob(cache_path, blob))
|
||||||
return false;
|
return false;
|
||||||
try {
|
try {
|
||||||
std::istringstream body(blob, std::ios::binary);
|
// Read in place: an istringstream would copy the blob (tens of MB for
|
||||||
|
// the largest vendors) once more just to stream over it.
|
||||||
|
boost::iostreams::stream<boost::iostreams::array_source> body(blob.data(), blob.size());
|
||||||
cereal::BinaryInputArchive ar(body);
|
cereal::BinaryInputArchive ar(body);
|
||||||
uint32_t cache_version = 0;
|
uint32_t cache_version = 0;
|
||||||
ar(cache_version);
|
ar(cache_version);
|
||||||
@@ -6474,14 +6510,10 @@ bool PresetBundle::load_vendor_cache(const std::string& cache_path, const std::s
|
|||||||
this->m_config_maps.clear();
|
this->m_config_maps.clear();
|
||||||
this->m_filament_id_maps.clear();
|
this->m_filament_id_maps.clear();
|
||||||
this->m_errors = 0;
|
this->m_errors = 0;
|
||||||
// reset() does not clear m_printer_hold_alias, and a mid-body failure may
|
// A mid-body failure may have left collections the deserialization never
|
||||||
// have left collections it never reached (each load_collection clears its
|
// reached (each load_collection clears its own collection's map only when
|
||||||
// own collection's map only when it runs) with stale aliases.
|
// it runs) with stale aliases.
|
||||||
this->prints.m_printer_hold_alias.clear();
|
this->clear_printer_hold_aliases();
|
||||||
this->sla_prints.m_printer_hold_alias.clear();
|
|
||||||
this->filaments.m_printer_hold_alias.clear();
|
|
||||||
this->sla_materials.m_printer_hold_alias.clear();
|
|
||||||
this->printers.m_printer_hold_alias.clear();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,10 @@
|
|||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace cereal {
|
||||||
|
class BinaryInputArchive;
|
||||||
|
class BinaryOutputArchive;
|
||||||
|
}
|
||||||
|
|
||||||
#define DEFAULT_USER_FOLDER_NAME "default"
|
#define DEFAULT_USER_FOLDER_NAME "default"
|
||||||
#define BUNDLE_STRUCTURE_JSON_NAME "bundle_structure.json"
|
#define BUNDLE_STRUCTURE_JSON_NAME "bundle_structure.json"
|
||||||
@@ -488,8 +492,11 @@ public:
|
|||||||
// not the profile JSONs are still there. A whole-vendor load comes from the
|
// not the profile JSONs are still there. A whole-vendor load comes from the
|
||||||
// vendor's preset cache whenever one covers the profile on disk, and is parsed
|
// vendor's preset cache whenever one covers the profile on disk, and is parsed
|
||||||
// from the JSONs (falling back to the ones in resources) only when none does.
|
// from the JSONs (falling back to the ones in resources) only when none does.
|
||||||
|
// `lib_version_hint` is the filament library version in effect, when the caller
|
||||||
|
// loads many vendors and has already resolved it once; empty resolves it here.
|
||||||
std::pair<PresetsConfigSubstitutions, size_t> load_vendor_configs_from_json(
|
std::pair<PresetsConfigSubstitutions, size_t> load_vendor_configs_from_json(
|
||||||
const std::string &dir, const std::string &vendor_name, LoadConfigBundleAttributes flags, ForwardCompatibilitySubstitutionRule compatibility_rule, const PresetBundle* base_bundle = nullptr);
|
const std::string &dir, const std::string &vendor_name, LoadConfigBundleAttributes flags, ForwardCompatibilitySubstitutionRule compatibility_rule, const PresetBundle* base_bundle = nullptr,
|
||||||
|
const std::string &lib_version_hint = {});
|
||||||
|
|
||||||
// Export a config bundle file containing all the presets and the names of the active presets.
|
// Export a config bundle file containing all the presets and the names of the active presets.
|
||||||
//void export_configbundle(const std::string &path, bool export_system_settings = false, bool export_physical_printers = false);
|
//void export_configbundle(const std::string &path, bool export_system_settings = false, bool export_physical_printers = false);
|
||||||
@@ -573,15 +580,17 @@ public:
|
|||||||
private:
|
private:
|
||||||
// Load one vendor from its preset cache: the one in `dir`, or — when that is
|
// Load one vendor from its preset cache: the one in `dir`, or — when that is
|
||||||
// missing or stale — the one shipped in resources/profiles, both judged against
|
// missing or stale — the one shipped in resources/profiles, both judged against
|
||||||
// the vendor as installed in `dir` and against the filament library in effect.
|
// the vendor as installed in `dir` and against the filament library in effect
|
||||||
|
// (resolved here unless the caller passes the already-resolved version).
|
||||||
// False, with this bundle left clean, when neither is usable and the vendor has
|
// False, with this bundle left clean, when neither is usable and the vendor has
|
||||||
// to be parsed. This is how load_vendor_configs_from_json reads a cache.
|
// to be parsed. This is how load_vendor_configs_from_json reads a cache.
|
||||||
bool load_vendor_cache(const boost::filesystem::path& dir, const std::string& vendor_name);
|
bool load_vendor_cache(const boost::filesystem::path& dir, const std::string& vendor_name, const std::string& lib_version_hint = {});
|
||||||
|
|
||||||
// Read raw cache blob: verify magic, size, CRC.
|
// Read raw cache blob: verify magic, size, CRC.
|
||||||
static bool read_cache_blob(const std::string& path, std::string& out_blob);
|
static bool read_cache_blob(const std::string& path, std::string& out_blob);
|
||||||
// Write a cache blob with the standard 20-byte file header.
|
// Write a cache blob with the standard 20-byte file header. False when the
|
||||||
static void write_cache_blob(const std::string& path, const std::string& blob);
|
// file could not be opened or written whole.
|
||||||
|
static bool write_cache_blob(const std::string& path, const std::string& blob);
|
||||||
|
|
||||||
// (De)serialization of one collection's slice for the per-vendor cache:
|
// (De)serialization of one collection's slice for the per-vendor cache:
|
||||||
// every non-default, non-external preset (system or user) plus
|
// every non-default, non-external preset (system or user) plus
|
||||||
@@ -589,6 +598,9 @@ private:
|
|||||||
static void save_collection(cereal::BinaryOutputArchive& ar, const PresetCollection& coll);
|
static void save_collection(cereal::BinaryOutputArchive& ar, const PresetCollection& coll);
|
||||||
static void load_collection(cereal::BinaryInputArchive& ar, PresetCollection& coll, const VendorMap& vendors);
|
static void load_collection(cereal::BinaryInputArchive& ar, PresetCollection& coll, const VendorMap& vendors);
|
||||||
|
|
||||||
|
// Clear every collection's m_printer_hold_alias, which reset() leaves alone.
|
||||||
|
void clear_printer_hold_aliases();
|
||||||
|
|
||||||
// Whether to (re)write a per-vendor cache after a JSON parse.
|
// Whether to (re)write a per-vendor cache after a JSON parse.
|
||||||
bool m_generate_vendor_caches { false };
|
bool m_generate_vendor_caches { false };
|
||||||
|
|
||||||
@@ -642,6 +654,10 @@ extern bool is_vendor_installed(const std::string& vendor);
|
|||||||
// was stamped with where only the cache is installed. Invalid Semver if neither is.
|
// was stamped with where only the cache is installed. Invalid Semver if neither is.
|
||||||
extern Semver installed_vendor_version(const std::string& vendor);
|
extern Semver installed_vendor_version(const std::string& vendor);
|
||||||
|
|
||||||
|
// Remove every form `vendor` can be installed as from data_dir()/system: its
|
||||||
|
// profile, its preset cache, and its preset directory.
|
||||||
|
extern void remove_installed_vendor(const std::string& vendor);
|
||||||
|
|
||||||
// The vendors `dir` holds, sorted: one is named by its profile or, in a build that
|
// The vendors `dir` holds, sorted: one is named by its profile or, in a build that
|
||||||
// ships preset caches instead of the raw profile JSONs, by its cache alone.
|
// ships preset caches instead of the raw profile JSONs, by its cache alone.
|
||||||
extern std::set<std::string> vendor_names_in(const boost::filesystem::path& dir);
|
extern std::set<std::string> vendor_names_in(const boost::filesystem::path& dir);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "WebGuideDialog.hpp"
|
#include "WebGuideDialog.hpp"
|
||||||
#include "ConfigWizard.hpp"
|
#include "ConfigWizard.hpp"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/join.hpp>
|
||||||
#include <boost/filesystem/operations.hpp>
|
#include <boost/filesystem/operations.hpp>
|
||||||
#include <boost/nowide/fstream.hpp>
|
#include <boost/nowide/fstream.hpp>
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
@@ -190,8 +191,7 @@ GuideFrame::GuideFrame(GUI_App *pGUI, long style)
|
|||||||
|
|
||||||
GuideFrame::~GuideFrame()
|
GuideFrame::~GuideFrame()
|
||||||
{
|
{
|
||||||
m_destroy = true;
|
*m_cancel_token = true; // stop the loading thread and any queued CallAfter lambdas before join
|
||||||
*m_cancel_token = true; // signal any queued CallAfter lambdas before join
|
|
||||||
if (m_load_task && m_load_task->joinable())
|
if (m_load_task && m_load_task->joinable())
|
||||||
m_load_task->join();
|
m_load_task->join();
|
||||||
m_load_task.reset();
|
m_load_task.reset();
|
||||||
@@ -300,13 +300,19 @@ void GuideFrame::OnNavigationRequest(wxWebViewEvent &evt)
|
|||||||
/**
|
/**
|
||||||
* Callback invoked when a navigation request was accepted
|
* Callback invoked when a navigation request was accepted
|
||||||
*/
|
*/
|
||||||
void GuideFrame::init_guide_paths()
|
// The empty shape every profile-loading path starts from or falls back to.
|
||||||
|
void GuideFrame::reset_profile_json()
|
||||||
{
|
{
|
||||||
m_ProfileJson = json::parse("{}");
|
|
||||||
m_ProfileJson["model"] = json::array();
|
m_ProfileJson["model"] = json::array();
|
||||||
m_ProfileJson["machine"] = json::object();
|
m_ProfileJson["machine"] = json::object();
|
||||||
m_ProfileJson["filament"] = json::object();
|
m_ProfileJson["filament"] = json::object();
|
||||||
m_ProfileJson["process"] = json::array();
|
m_ProfileJson["process"] = json::array();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuideFrame::init_guide_paths()
|
||||||
|
{
|
||||||
|
m_ProfileJson = json::parse("{}");
|
||||||
|
reset_profile_json();
|
||||||
|
|
||||||
vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / PRESET_SYSTEM_DIR).make_preferred();
|
vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / PRESET_SYSTEM_DIR).make_preferred();
|
||||||
rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
||||||
@@ -349,7 +355,7 @@ void GuideFrame::OnNavigationComplete(wxWebViewEvent &evt)
|
|||||||
try {
|
try {
|
||||||
init_guide_paths();
|
init_guide_paths();
|
||||||
if (BuildProfileDataFromPresetBundle()) {
|
if (BuildProfileDataFromPresetBundle()) {
|
||||||
if (!m_destroy)
|
if (!*m_cancel_token)
|
||||||
on_profile_loaded();
|
on_profile_loaded();
|
||||||
} else {
|
} else {
|
||||||
// Presets not yet in memory — delegate to background thread.
|
// Presets not yet in memory — delegate to background thread.
|
||||||
@@ -1184,11 +1190,7 @@ bool GuideFrame::BuildProfileJson(const PresetBundle& bundle, bool require_all_r
|
|||||||
if (!nozzle_str.empty()) nozzle_str += ";";
|
if (!nozzle_str.empty()) nozzle_str += ";";
|
||||||
nozzle_str += v.name;
|
nozzle_str += v.name;
|
||||||
}
|
}
|
||||||
std::string materials_str;
|
const std::string materials_str = boost::algorithm::join(model.default_materials, ";");
|
||||||
for (const auto& m : model.default_materials) {
|
|
||||||
if (!materials_str.empty()) materials_str += ";";
|
|
||||||
materials_str += m;
|
|
||||||
}
|
|
||||||
boost::filesystem::path cover_path =
|
boost::filesystem::path cover_path =
|
||||||
(boost::filesystem::path(resources_dir()) / "profiles" / vp.id / (model.id + "_cover.png"))
|
(boost::filesystem::path(resources_dir()) / "profiles" / vp.id / (model.id + "_cover.png"))
|
||||||
.make_preferred();
|
.make_preferred();
|
||||||
@@ -1224,6 +1226,7 @@ bool GuideFrame::BuildProfileJson(const PresetBundle& bundle, bool require_all_r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filament map from system filament presets (vendor/type already resolved in config)
|
// Filament map from system filament presets (vendor/type already resolved in config)
|
||||||
|
const json& machines = m_ProfileJson["machine"];
|
||||||
for (const Preset& p : bundle.filaments()) {
|
for (const Preset& p : bundle.filaments()) {
|
||||||
if (!p.is_system || !p.vendor) continue;
|
if (!p.is_system || !p.vendor) continue;
|
||||||
const auto* fila_vendor = p.config.option<ConfigOptionStrings>("filament_vendor");
|
const auto* fila_vendor = p.config.option<ConfigOptionStrings>("filament_vendor");
|
||||||
@@ -1236,9 +1239,10 @@ bool GuideFrame::BuildProfileJson(const PresetBundle& bundle, bool require_all_r
|
|||||||
std::string model_list;
|
std::string model_list;
|
||||||
if (compat_printers) {
|
if (compat_printers) {
|
||||||
for (const std::string& pname : compat_printers->values) {
|
for (const std::string& pname : compat_printers->values) {
|
||||||
if (m_ProfileJson["machine"].contains(pname)) {
|
auto it = machines.find(pname);
|
||||||
std::string m = m_ProfileJson["machine"][pname]["model"];
|
if (it != machines.end()) {
|
||||||
std::string n = m_ProfileJson["machine"][pname]["nozzle"];
|
const std::string m = (*it)["model"];
|
||||||
|
const std::string n = (*it)["nozzle"];
|
||||||
model_list += "[" + m + "++" + n + "]";
|
model_list += "[" + m + "++" + n + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1264,20 +1268,16 @@ bool GuideFrame::BuildProfileJson(const PresetBundle& bundle, bool require_all_r
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (require_all_resource_vendors) {
|
if (require_all_resource_vendors) {
|
||||||
// If rsrc_vendor_dir has vendor JSONs not covered by the current bundle, the
|
// If rsrc_vendor_dir has vendors (profile JSONs, or the preset caches a
|
||||||
|
// packaged build ships instead) not covered by the current bundle, the
|
||||||
// bundle is incomplete (e.g. dev env where data_dir/system only has
|
// bundle is incomplete (e.g. dev env where data_dir/system only has
|
||||||
// OrcaFilamentLibrary+Custom). Fall back so LoadProfileFamily reads both dirs.
|
// OrcaFilamentLibrary+Custom). Fall back so the slow path reads both dirs.
|
||||||
try {
|
try {
|
||||||
for (const auto& e : boost::filesystem::directory_iterator(rsrc_vendor_dir)) {
|
for (const std::string& name : vendor_names_in(rsrc_vendor_dir)) {
|
||||||
if (e.path().extension().string() != ".json") continue;
|
if (bundle.vendors.find(name) == bundle.vendors.end()) {
|
||||||
const std::string stem = e.path().stem().string();
|
BOOST_LOG_TRIVIAL(info) << "GuideFrame: vendor '" << name
|
||||||
if (bundle.vendors.find(stem) == bundle.vendors.end()) {
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "GuideFrame: vendor '" << stem
|
|
||||||
<< "' in resources but not in preset_bundle — falling back to JSON loading";
|
<< "' in resources but not in preset_bundle — falling back to JSON loading";
|
||||||
m_ProfileJson["model"] = json::array();
|
reset_profile_json();
|
||||||
m_ProfileJson["machine"] = json::object();
|
|
||||||
m_ProfileJson["filament"] = json::object();
|
|
||||||
m_ProfileJson["process"] = json::array();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1292,10 +1292,7 @@ bool GuideFrame::BuildProfileJson(const PresetBundle& bundle, bool require_all_r
|
|||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << "GuideFrame::BuildProfileJson failed: " << e.what()
|
BOOST_LOG_TRIVIAL(warning) << "GuideFrame::BuildProfileJson failed: " << e.what()
|
||||||
<< " — falling back to JSON loading";
|
<< " — falling back to JSON loading";
|
||||||
m_ProfileJson["model"] = json::array();
|
reset_profile_json();
|
||||||
m_ProfileJson["machine"] = json::object();
|
|
||||||
m_ProfileJson["filament"] = json::object();
|
|
||||||
m_ProfileJson["process"] = json::array();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1340,7 +1337,7 @@ bool GuideFrame::BuildProfileDataFromVendors()
|
|||||||
if (vendor_files.count(filament_library))
|
if (vendor_files.count(filament_library))
|
||||||
load_vendor(bundle, filament_library, nullptr);
|
load_vendor(bundle, filament_library, nullptr);
|
||||||
for (const auto& entry : vendor_files) {
|
for (const auto& entry : vendor_files) {
|
||||||
if (m_destroy)
|
if (*m_cancel_token)
|
||||||
return false; // as in the scan below: a vendor without a cache is parsed, and that takes time
|
return false; // as in the scan below: a vendor without a cache is parsed, and that takes time
|
||||||
const std::string& vendor = entry.first;
|
const std::string& vendor = entry.first;
|
||||||
// A cache is only ever written for a versioned vendor; a JSON has to be
|
// A cache is only ever written for a versioned vendor; a JSON has to be
|
||||||
@@ -1358,10 +1355,7 @@ bool GuideFrame::BuildProfileDataFromVendors()
|
|||||||
return BuildProfileJson(bundle, /*require_all_resource_vendors=*/false);
|
return BuildProfileJson(bundle, /*require_all_resource_vendors=*/false);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed: " << e.what();
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " failed: " << e.what();
|
||||||
m_ProfileJson["model"] = json::array();
|
reset_profile_json();
|
||||||
m_ProfileJson["machine"] = json::object();
|
|
||||||
m_ProfileJson["filament"] = json::object();
|
|
||||||
m_ProfileJson["process"] = json::array();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1395,7 +1389,7 @@ int GuideFrame::LoadProfileData()
|
|||||||
LoadProfileFamily(w2s(strVendor), iter->path().string());
|
LoadProfileFamily(w2s(strVendor), iter->path().string());
|
||||||
loaded_vendors.insert(w2s(strVendor));
|
loaded_vendors.insert(w2s(strVendor));
|
||||||
}
|
}
|
||||||
if (m_destroy) return 0;
|
if (*m_cancel_token) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::filesystem::directory_iterator others_endIter;
|
boost::filesystem::directory_iterator others_endIter;
|
||||||
@@ -1410,7 +1404,7 @@ int GuideFrame::LoadProfileData()
|
|||||||
LoadProfileFamily(w2s(strVendor), iter->path().string());
|
LoadProfileFamily(w2s(strVendor), iter->path().string());
|
||||||
loaded_vendors.insert(w2s(strVendor));
|
loaded_vendors.insert(w2s(strVendor));
|
||||||
}
|
}
|
||||||
if (m_destroy) return 0;
|
if (*m_cancel_token) return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ public:
|
|||||||
bool BuildProfileJson(const PresetBundle& bundle, bool require_all_resource_vendors);
|
bool BuildProfileJson(const PresetBundle& bundle, bool require_all_resource_vendors);
|
||||||
bool BuildProfileDataFromPresetBundle();
|
bool BuildProfileDataFromPresetBundle();
|
||||||
bool BuildProfileDataFromVendors();
|
bool BuildProfileDataFromVendors();
|
||||||
|
void reset_profile_json();
|
||||||
int SaveProfile();
|
int SaveProfile();
|
||||||
int GetFilamentInfo( std::string VendorDirectory,json & pFilaList, std::string filepath, std::string &sVendor, std::string &sType);
|
int GetFilamentInfo( std::string VendorDirectory,json & pFilaList, std::string filepath, std::string &sVendor, std::string &sType);
|
||||||
|
|
||||||
@@ -121,9 +122,9 @@ private:
|
|||||||
|
|
||||||
//First Load
|
//First Load
|
||||||
bool bFirstComplete{false};
|
bool bFirstComplete{false};
|
||||||
std::atomic<bool> m_destroy{false};
|
// Set once in the destructor. Read through `this` by the loading thread
|
||||||
// Shared cancel token captured by CallAfter lambdas so they don't touch
|
// (joined before `this` dies) and captured as the shared_ptr by CallAfter
|
||||||
// `this` after the destructor has run and the object is freed.
|
// lambdas so they don't touch `this` after the object is freed.
|
||||||
std::shared_ptr<std::atomic<bool>> m_cancel_token{std::make_shared<std::atomic<bool>>(false)};
|
std::shared_ptr<std::atomic<bool>> m_cancel_token{std::make_shared<std::atomic<bool>>(false)};
|
||||||
std::unique_ptr<boost::thread> m_load_task;
|
std::unique_ptr<boost::thread> m_load_task;
|
||||||
|
|
||||||
|
|||||||
@@ -1069,12 +1069,7 @@ void PresetUpdater::priv::check_installed_vendor_profiles() const
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//need to be removed because not installed
|
//need to be removed because not installed
|
||||||
const auto path_in_vendor = vendor_path / (vendor_name + ".json");
|
remove_installed_vendor(vendor_name);
|
||||||
fs::remove(path_in_vendor);
|
|
||||||
fs::remove(vendor_path / (vendor_name + ".opc"));
|
|
||||||
const auto path_of_vendor = vendor_path / vendor_name;
|
|
||||||
if (fs::exists(path_of_vendor))
|
|
||||||
fs::remove_all(path_of_vendor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (is_vendor_enabled) {
|
else if (is_vendor_enabled) {
|
||||||
|
|||||||
@@ -54,6 +54,14 @@ std::string write_versionless_vendor_json(const fs::path& dir, const std::string
|
|||||||
return p.string();
|
return p.string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whole file as bytes, for the byte-identity comparisons below.
|
||||||
|
std::string slurp(const fs::path& p)
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
load_string_file(p, s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void corrupt_blob_byte(const std::string& path)
|
void corrupt_blob_byte(const std::string& path)
|
||||||
{
|
{
|
||||||
std::fstream f(path, std::ios::in | std::ios::out | std::ios::binary);
|
std::fstream f(path, std::ios::in | std::ios::out | std::ios::binary);
|
||||||
@@ -907,10 +915,6 @@ TEST_CASE("printer hold aliases survive a cache round-trip", "[VendorCache]")
|
|||||||
REQUIRE(loaded.load_vendor_cache(cache1.string(), vid, "1.0.0","1.0.0"));
|
REQUIRE(loaded.load_vendor_cache(cache1.string(), vid, "1.0.0","1.0.0"));
|
||||||
REQUIRE(save_one_vendor(loaded, cache2.string(), vid, "1.0.0"));
|
REQUIRE(save_one_vendor(loaded, cache2.string(), vid, "1.0.0"));
|
||||||
|
|
||||||
auto slurp = [](const fs::path& p) {
|
|
||||||
std::ifstream ifs(p.string(), std::ios::binary);
|
|
||||||
return std::string(std::istreambuf_iterator<char>(ifs), {});
|
|
||||||
};
|
|
||||||
REQUIRE(slurp(cache1) == slurp(cache2));
|
REQUIRE(slurp(cache1) == slurp(cache2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -964,10 +968,6 @@ TEST_CASE("a loaded cache re-serializes to byte-identical output", "[VendorCache
|
|||||||
PresetBundle loaded;
|
PresetBundle loaded;
|
||||||
REQUIRE(loaded.load_vendor_cache(cache1.string(), "Acme", "1.0.0", "1.0.0"));
|
REQUIRE(loaded.load_vendor_cache(cache1.string(), "Acme", "1.0.0", "1.0.0"));
|
||||||
REQUIRE(loaded.save_vendor_cache(cache2.string(), "Acme", "1.0.0", "1.0.0"));
|
REQUIRE(loaded.save_vendor_cache(cache2.string(), "Acme", "1.0.0", "1.0.0"));
|
||||||
auto slurp = [](const fs::path& p) {
|
|
||||||
std::ifstream ifs(p.string(), std::ios::binary);
|
|
||||||
return std::string(std::istreambuf_iterator<char>(ifs), {});
|
|
||||||
};
|
|
||||||
REQUIRE(slurp(cache1) == slurp(cache2));
|
REQUIRE(slurp(cache1) == slurp(cache2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1023,11 +1023,7 @@ TEST_CASE("a cache that fails mid-body deserialization is rejected and leaves th
|
|||||||
PresetBundle clean;
|
PresetBundle clean;
|
||||||
REQUIRE(out.save_vendor_cache(out_after.string(), vid, "1.0.0","1.0.0"));
|
REQUIRE(out.save_vendor_cache(out_after.string(), vid, "1.0.0","1.0.0"));
|
||||||
REQUIRE(clean.save_vendor_cache(clean_ref.string(), vid, "1.0.0","1.0.0"));
|
REQUIRE(clean.save_vendor_cache(clean_ref.string(), vid, "1.0.0","1.0.0"));
|
||||||
auto slurp2 = [](const fs::path& p) {
|
CHECK(slurp(out_after) == slurp(clean_ref));
|
||||||
std::ifstream ifs(p.string(), std::ios::binary);
|
|
||||||
return std::string(std::istreambuf_iterator<char>(ifs), {});
|
|
||||||
};
|
|
||||||
CHECK(slurp2(out_after) == slurp2(clean_ref));
|
|
||||||
|
|
||||||
// The recovery must leave a bundle a caller can still load a good cache into.
|
// The recovery must leave a bundle a caller can still load a good cache into.
|
||||||
REQUIRE(out.load_vendor_cache(valid_cache.string(), vid, "1.0.0","1.0.0"));
|
REQUIRE(out.load_vendor_cache(valid_cache.string(), vid, "1.0.0","1.0.0"));
|
||||||
|
|||||||
Reference in New Issue
Block a user