diff --git a/Applications/CLI/CMakeLists.txt b/Applications/CLI/CMakeLists.txt index 3206d3eb380cd8a0b4e027999aaaf487c7916ddc..cfd5b09be80480d394bc2f9c2ead789cfa9cebcb 100644 --- a/Applications/CLI/CMakeLists.txt +++ b/Applications/CLI/CMakeLists.txt @@ -62,7 +62,6 @@ target_link_libraries( $<$<TARGET_EXISTS:MPI::MPI_CXX>:MPI::MPI_CXX> $<$<TARGET_EXISTS:InSituLib>:InSituLib> tclap - xmlpatch ) target_compile_definitions( diff --git a/Applications/CLI/ogs.cpp b/Applications/CLI/ogs.cpp index 3a0aef505fe2c3bb3c70132ec802b96d72561f1d..24275613453bcd61de8517ab360b0582ebdc599c 100644 --- a/Applications/CLI/ogs.cpp +++ b/Applications/CLI/ogs.cpp @@ -10,11 +10,8 @@ * */ -#include <libxml/parser.h> -#include <libxml/tree.h> #include <spdlog/spdlog.h> #include <tclap/CmdLine.h> -#include <xml_patch.h> #include <chrono> #include <sstream> @@ -192,107 +189,10 @@ int main(int argc, char* argv[]) run_time.start(); - std::string prj_file = project_arg.getValue(); - auto patch_files = xml_patch_files.getValue(); - std::string includepath = ""; - if (BaseLib::getFileExtension(prj_file) == ".xml") - { - if (!patch_files.empty()) - { - OGS_FATAL( - "It is not allowed to specify additional patch files " - "if a patch file was already specified as the " - "prj-file."); - } - auto patch = xmlParseFile(prj_file.c_str()); - auto node = xmlDocGetRootElement(patch); - auto base_file = xmlGetProp(node, (const xmlChar*)"base_file"); - if (base_file == nullptr) - { - OGS_FATAL( - "Error reading base prj file in given patch file {:s}.", - prj_file); - } - patch_files = {prj_file}; - std::stringstream ss; - ss << base_file; - prj_file = BaseLib::joinPaths(BaseLib::extractPath(prj_file), - ss.str()); - } - - if (!patch_files.empty()) - { - includepath = - fs::canonical(fs::path(prj_file)).parent_path().string(); - std::string current_prj_file = prj_file; - std::string current_prj_file_base = - BaseLib::extractBaseNameWithoutExtension(current_prj_file); - for (const auto& patch_file : patch_files) - { - auto patch = xmlParseFile(patch_file.c_str()); - if (patch == NULL) - { - OGS_FATAL("Error reading XML diff file {:s}.", - patch_file); - } - - auto doc = xmlParseFile(current_prj_file.c_str()); - if (doc == NULL) - { - OGS_FATAL("Error reading project file {:s}.", - current_prj_file); - } - - auto node = xmlDocGetRootElement(patch); - int rc = 0; - for (node = node ? node->children : NULL; node; - node = node->next) - { - if (node->type != XML_ELEMENT_NODE) - continue; - - if (!strcmp((char*)node->name, "add")) - rc = xml_patch_add(doc, node); - else if (!strcmp((char*)node->name, "replace")) - rc = xml_patch_replace(doc, node); - else if (!strcmp((char*)node->name, "remove")) - rc = xml_patch_remove(doc, node); - else - continue; - - if (rc) - { - OGS_FATAL( - "Error while patching prj file {:s} with patch " - "file " - "{:}.", - project_arg.getValue(), patch_file); - } - } - - current_prj_file_base = - current_prj_file_base + "_" + - BaseLib::extractBaseNameWithoutExtension(patch_file); - current_prj_file = BaseLib::joinPaths( - outdir_arg.getValue(), current_prj_file_base + ".prj"); - - // TODO: make name unique - xmlSaveFile(current_prj_file.c_str(), doc); - - xmlFreeDoc(doc); - xmlFreeDoc(patch); - } - xmlCleanupParser(); - prj_file = current_prj_file; - } - else - { - prj_file = project_arg.getValue(); - } - - auto project_config = - BaseLib::makeConfigTree(prj_file, !nonfatal_arg.getValue(), - "OpenGeoSysProject", includepath); + auto project_config = BaseLib::makeConfigTree( + project_arg.getValue(), !nonfatal_arg.getValue(), + "OpenGeoSysProject", xml_patch_files.getValue(), + outdir_arg.getValue()); BaseLib::setProjectDirectory( BaseLib::extractPath(project_arg.getValue())); diff --git a/BaseLib/CMakeLists.txt b/BaseLib/CMakeLists.txt index 6eb7030eebe3020e43cc5513c42ac07f91c9a534..77d904ff5ebc578db6db12a629734959e947622b 100644 --- a/BaseLib/CMakeLists.txt +++ b/BaseLib/CMakeLists.txt @@ -16,6 +16,7 @@ target_link_libraries( $<$<BOOL:${MSVC}>:WinMM> # needed for timeGetTime $<$<BOOL:${OGS_BUILD_GUI}>:Qt5::Xml> $<$<BOOL:${OGS_BUILD_GUI}>:Qt5::XmlPatterns> + PRIVATE xmlpatch ) target_compile_definitions( diff --git a/BaseLib/ConfigTreeUtil.cpp b/BaseLib/ConfigTreeUtil.cpp index b4596d03868b3c05544d4226d9d43d3a31a6bb0a..cf0ff1de0438a74015cfc86775b21627b3fc70e5 100644 --- a/BaseLib/ConfigTreeUtil.cpp +++ b/BaseLib/ConfigTreeUtil.cpp @@ -10,9 +10,15 @@ #include "ConfigTreeUtil.h" +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <spdlog/spdlog.h> +#include <xml_patch.h> + #include <boost/property_tree/xml_parser.hpp> #include <regex> +#include "BaseLib/FileTools.h" #include "Error.h" #include "Logging.h" #include "filesystem.h" @@ -112,15 +118,108 @@ void replace_includes( ConfigTreeTopLevel makeConfigTree(const std::string& filepath, const bool be_ruthless, const std::string& toplevel_tag, - std::string includepath) + std::vector<std::string> + patch_files, + std::string outdir) { + std::string prj_file = filepath; + std::string includepath = ""; + if (BaseLib::getFileExtension(prj_file) == ".xml") + { + if (!patch_files.empty()) + { + OGS_FATAL( + "It is not allowed to specify additional patch files " + "if a patch file was already specified as the " + "prj-file."); + } + auto patch = xmlParseFile(prj_file.c_str()); + auto node = xmlDocGetRootElement(patch); + auto base_file = xmlGetProp(node, (const xmlChar*)"base_file"); + if (base_file == nullptr) + { + OGS_FATAL("Error reading base prj file in given patch file {:s}.", + prj_file); + } + patch_files = {prj_file}; + std::stringstream ss; + ss << base_file; + prj_file = BaseLib::joinPaths(BaseLib::extractPath(prj_file), ss.str()); + } + + if (!patch_files.empty()) + { + includepath = fs::canonical(fs::path(prj_file)).parent_path().string(); + std::string current_prj_file = prj_file; + std::string current_prj_file_base = + BaseLib::extractBaseNameWithoutExtension(current_prj_file); + for (const auto& patch_file : patch_files) + { + auto patch = xmlParseFile(patch_file.c_str()); + if (patch == NULL) + { + OGS_FATAL("Error reading XML diff file {:s}.", patch_file); + } + + auto doc = xmlParseFile(current_prj_file.c_str()); + if (doc == NULL) + { + OGS_FATAL("Error reading project file {:s}.", current_prj_file); + } + + auto node = xmlDocGetRootElement(patch); + int rc = 0; + for (node = node ? node->children : NULL; node; node = node->next) + { + if (node->type != XML_ELEMENT_NODE) + continue; + + if (!strcmp((char*)node->name, "add")) + rc = xml_patch_add(doc, node); + else if (!strcmp((char*)node->name, "replace")) + rc = xml_patch_replace(doc, node); + else if (!strcmp((char*)node->name, "remove")) + rc = xml_patch_remove(doc, node); + else + continue; + + if (rc) + { + OGS_FATAL( + "Error while patching prj file {:s} with patch " + "file " + "{:}.", + filepath, patch_file); + } + } + + current_prj_file_base = + current_prj_file_base + "_" + + BaseLib::extractBaseNameWithoutExtension(patch_file); + current_prj_file = + BaseLib::joinPaths(outdir, current_prj_file_base + ".prj"); + + // TODO: make name unique + xmlSaveFile(current_prj_file.c_str(), doc); + + xmlFreeDoc(doc); + xmlFreeDoc(patch); + } + xmlCleanupParser(); + prj_file = current_prj_file; + } + else + { + prj_file = filepath; + } + ConfigTree::PTree ptree; // note: Trimming whitespace and ignoring comments is crucial in order // for our configuration tree implementation to work! try { - read_xml(filepath, ptree, + read_xml(prj_file, ptree, boost::property_tree::xml_parser::no_comments | boost::property_tree::xml_parser::trim_whitespace); diff --git a/BaseLib/ConfigTreeUtil.h b/BaseLib/ConfigTreeUtil.h index 1a9d13c8c6f697c59ef64e71b4dd4eaa3b4cc9ad..484e6038b87df2cab29dd0d338fe3e8c85af0afa 100644 --- a/BaseLib/ConfigTreeUtil.h +++ b/BaseLib/ConfigTreeUtil.h @@ -95,6 +95,7 @@ private: ConfigTreeTopLevel makeConfigTree(std::string const& filepath, bool const be_ruthless, std::string const& toplevel_tag, - std::string includepath = ""); + std::vector<std::string> patch_files = {}, + std::string outdir = ""); } // namespace BaseLib