65 std::filesystem::path
const& prj_dir)
67 xmlNode* cur_node =
nullptr;
68 for (cur_node = node; cur_node; cur_node = cur_node->next)
70 if (cur_node->type != XML_ELEMENT_NODE)
74 if (xmlStrEqual(cur_node->name, xmlCharStrdup(
"include")))
76 auto include_file_char_pointer =
77 xmlGetProp(cur_node, xmlCharStrdup(
"file"));
78 if (include_file_char_pointer ==
nullptr)
81 "Error while processing includes in prj file. Error in "
82 "element '{:s}' on line {:d}: no file attribute given!",
83 reinterpret_cast<const char*
>(cur_node->name),
86 auto filename_length = xmlStrlen(include_file_char_pointer);
88 reinterpret_cast<char*
>(include_file_char_pointer),
90 if (
auto const filepath = std::filesystem::path(filename);
91 filepath.is_relative())
93 filename = (prj_dir / filepath).
string();
96 if (!std::filesystem::exists(filename))
99 "Error while processing includes in prj file. Error in "
100 "element '{:s}' on line {:d}: Include file is not "
103 reinterpret_cast<const char*
>(cur_node->name),
105 reinterpret_cast<const char*
>(include_file_char_pointer));
107 INFO(
"Including {:s} into project file.", filename);
109 const std::ifstream input_stream(filename, std::ios_base::binary);
110 if (input_stream.fail())
112 OGS_FATAL(
"Failed to open file {}!", filename);
114 std::stringstream buffer;
115 buffer << input_stream.rdbuf();
116 const std::string xml = buffer.str();
119 std::regex xmlDeclaration(
"<\\?xml.*?>");
120 const std::string xml_filtered =
121 std::regex_replace(xml, xmlDeclaration,
"");
123 xmlNodePtr pNewNode =
nullptr;
124 xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(),
125 (
int)xml_filtered.length(), 0, &pNewNode);
126 if (pNewNode !=
nullptr)
129 xmlNode* pChild = pNewNode;
130 while (pChild !=
nullptr)
132 xmlAddChild(cur_node->parent, xmlCopyNode(pChild, 1));
133 pChild = pChild->next;
135 xmlFreeNode(pNewNode);
139 auto next_node = cur_node->next;
140 xmlUnlinkNode(cur_node);
141 xmlFreeNode(cur_node);
142 cur_node = next_node;
146 xmlFreeNode(cur_node);
150 std::filesystem::path
const& prj_dir)
158 auto doc = xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
159 nullptr,
nullptr, 0);
162 OGS_FATAL(
"Error reading project file from memory.");
165 auto root_node = xmlDocGetRootElement(doc);
170 xmlDocDumpMemory(doc, &xmlbuff, &buffersize);
172 prj_stream << xmlbuff;
179void patchStream(std::string
const& patch_file, std::stringstream& prj_stream,
180 bool after_includes =
false)
184 auto patch = xmlParseFile(patch_file.c_str());
185 if (patch ==
nullptr)
187 OGS_FATAL(
"Error reading XML diff file {:s}.", patch_file);
190 auto doc = xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
191 nullptr,
nullptr, 0);
194 OGS_FATAL(
"Error reading project file from memory.");
197 auto node = xmlDocGetRootElement(patch);
199 for (node = node ? node->children :
nullptr; node; node = node->next)
201 if (node->type != XML_ELEMENT_NODE)
205 bool node_after_includes =
false;
206 xmlAttr* attribute = node->properties;
211 xmlNodeListGetString(node->doc, attribute->children, 1);
212 if (xmlStrEqual(attribute->name, xmlCharStrdup(
"after_includes")) &&
213 xmlStrEqual(value, xmlCharStrdup(
"true")))
215 node_after_includes =
true;
219 attribute = attribute->next;
222 if (after_includes != node_after_includes)
227 if (xmlStrEqual(node->name, xmlCharStrdup(
"add")))
229 rc = xml_patch_add(doc, node);
231 else if (xmlStrEqual(node->name, xmlCharStrdup(
"replace")))
233 rc = xml_patch_replace(doc, node);
235 else if (xmlStrEqual(node->name, xmlCharStrdup(
"remove")))
237 rc = xml_patch_remove(doc, node);
242 "Error while patching prj file with patch file {:}. Only "
243 "'add', 'replace' and 'remove' elements are allowed! Got an "
244 "element '{:s}' on line {:d}.",
245 patch_file,
reinterpret_cast<const char*
>(node->name),
252 "Error while patching prj file with patch file {:}. Error in "
253 "element '{:s}' on line {:d}.",
254 patch_file,
reinterpret_cast<const char*
>(node->name),
261 xmlDocDumpMemory(doc, &xmlbuff, &buffersize);
263 prj_stream << xmlbuff;
273 std::vector<std::string>& patch_files)
279 if (!patch_files.empty())
282 "It is not allowed to specify additional patch files "
283 "if a patch file was already specified as the "
286 auto patch = xmlReadFile(prj_file.c_str(),
nullptr, 0);
287 auto node = xmlDocGetRootElement(patch);
288 xmlChar
const base_file_string[] =
"base_file";
289 auto base_file = xmlGetProp(node, base_file_string);
290 if (base_file ==
nullptr)
293 "Error reading base prj file (base_file attribute) in given "
297 patch_files = {prj_file};
298 std::stringstream ss;
304 if (std::ifstream file(prj_file); file)
306 prj_stream << file.rdbuf();
312 ERR(
"File {:s} does not exist.", prj_file);
314 DBUG(
"Stream state flags: {:s}.", iostateToString(file.rdstate()));
315 OGS_FATAL(
"Could not open project file '{:s}' for reading.", prj_file);
319 for (
const auto& patch_file : patch_files)
326 const std::string& filepath,
327 const std::vector<std::string>& patch_files,
328 bool write_prj,
const std::string& out_directory)
330 std::string prj_file = filepath;
332 std::vector<std::string> patch_files_copy = patch_files;
335 std::filesystem::absolute(std::filesystem::path(prj_file))
338 for (
const auto& patch_file : patch_files_copy)
352 xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
353 nullptr,
nullptr, XML_PARSE_NOBLANKS);
354 auto prj_out = (std::filesystem::path(out_directory) /
355 std::filesystem::path(filepath).stem())
358 xmlSaveFormatFileEnc(prj_out.c_str(), doc,
"utf-8", 1);
359 INFO(
"Processed project file written to {:s}.", prj_out);
void prepareProjectFile(std::stringstream &prj_stream, const std::string &filepath, const std::vector< std::string > &patch_files, bool write_prj, const std::string &out_directory)
Applies includes and patch files to project file.