From 9d2e50fa56e643043a6748cef0ce177e69f66887 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 3 May 2020 12:23:54 +0100 Subject: [PATCH] =?UTF-8?q?Addon-config:=20don=E2=80=99t=20overwrite=20aut?= =?UTF-8?q?osaved=20props?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix for: https://sourceforge.net/p/flightgear/codetickets/2059/ When copying addon-config into the main property tree, skip props which already exist and which are marked ARCHIVE, on the assumption they came from autosave.xml. --- src/Add-ons/AddonManager.cxx | 22 +++++++++++++- test_suite/simgear_tests/props/test_props.cxx | 29 +++++++++++++++++++ test_suite/simgear_tests/props/test_props.hxx | 3 +- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/Add-ons/AddonManager.cxx b/src/Add-ons/AddonManager.cxx index 9faae1ca2..667b5561d 100644 --- a/src/Add-ons/AddonManager.cxx +++ b/src/Add-ons/AddonManager.cxx @@ -96,13 +96,33 @@ AddonManager::loadConfigFileIfExists(const SGPath& configFile) return; } + SGPropertyNode_ptr configProps(new SGPropertyNode); try { - readProperties(configFile, globals->get_props()); + readProperties(configFile, configProps); } catch (const sg_exception &e) { throw errors::error_loading_config_file( "unable to load add-on config file '" + configFile.utf8Str() + "': " + e.getFormattedMessage()); } + + // bug https://sourceforge.net/p/flightgear/codetickets/2059/ + // since we're loading this after autosave.xml is loaded, the defaults + // always take precedence. To fix this, only copy a value from the + // addon-config if it's not makred as ARCHIVE. (We assume ARCHIVE props + // came from autosave.xml) + copyPropertiesIf(configProps, globals->get_props(), [](const SGPropertyNode* src) { + if (src->nChildren() > 0) + return true; + + // find the correspnding destination node + auto dstNode = globals->get_props()->getNode(src->getPath()); + if (!dstNode) + return true; // easy, just copy it + + // copy if it's NOT marked archive. In other words, we can replace + // values from defaults, but not autosave + return dstNode->getAttribute(SGPropertyNode::ARCHIVE) == false; + }); SG_LOG(SG_GENERAL, SG_INFO, "Loaded add-on config file: '" << configFile.utf8Str() + "'"); diff --git a/test_suite/simgear_tests/props/test_props.cxx b/test_suite/simgear_tests/props/test_props.cxx index c4e419eb7..82487b31b 100644 --- a/test_suite/simgear_tests/props/test_props.cxx +++ b/test_suite/simgear_tests/props/test_props.cxx @@ -20,6 +20,7 @@ #include "test_props.hxx" +#include // Set up function for each test. void SimgearPropsTests::setUp() @@ -50,3 +51,31 @@ void SimgearPropsTests::testAliasLeak() alias = tree->getNode("test-alias", true); alias->alias("test-node"); } + +void SimgearPropsTests::testPropsCopyIf() +{ +// dummy property tree structure + tree->setIntValue("a/a/a", 42); + tree->setStringValue("a/a/b", "foo"); + tree->setIntValue("a/a/c[2]", 99); + tree->setIntValue("a/a/d", 1); + tree->setIntValue("a/b/a[0]", 50); + tree->setIntValue("a/b/a[1]", 100); + tree->setStringValue("a/b/b", "foo"); + + SGPropertyNode_ptr destA(new SGPropertyNode); + + copyPropertiesIf(tree, destA, [](const SGPropertyNode* src) { + // always copy non-leaf nodes + if (src->nChildren() > 0) + return true; + + return (src->getType() == simgear::props::INT) && + src->getIntValue() > 50; + }); + + CPPUNIT_ASSERT_EQUAL(1, destA->getNode("a/a")->nChildren()); // only 99 + CPPUNIT_ASSERT_EQUAL(99, destA->getIntValue("a/a/c[2]")); + CPPUNIT_ASSERT_EQUAL(1, destA->getNode("a/b")->nChildren()); // only 100 + CPPUNIT_ASSERT_EQUAL(100, destA->getIntValue("a/b/a[1]")); +} diff --git a/test_suite/simgear_tests/props/test_props.hxx b/test_suite/simgear_tests/props/test_props.hxx index e73f61190..861906057 100644 --- a/test_suite/simgear_tests/props/test_props.hxx +++ b/test_suite/simgear_tests/props/test_props.hxx @@ -34,6 +34,7 @@ class SimgearPropsTests : public CppUnit::TestFixture // Set up the test suite. CPPUNIT_TEST_SUITE(SimgearPropsTests); CPPUNIT_TEST(testAliasLeak); + CPPUNIT_TEST(testPropsCopyIf); CPPUNIT_TEST_SUITE_END(); public: @@ -45,7 +46,7 @@ public: // The tests. void testAliasLeak(); - + void testPropsCopyIf(); private: // A property tree. SGPropertyNode *tree;