64 std::filesystem::path
const& prj_dir)
66 xmlNode* cur_node =
nullptr;
67 for (cur_node = node; cur_node; cur_node = cur_node->next)
69 if (cur_node->type != XML_ELEMENT_NODE)
73 if (xmlStrEqual(cur_node->name, xmlCharStrdup(
"include")))
75 auto include_file_char_pointer =
76 xmlGetProp(cur_node, xmlCharStrdup(
"file"));
77 if (include_file_char_pointer ==
nullptr)
80 "Error while processing includes in prj file. Error in "
81 "element '{:s}' on line {:d}: no file attribute given!",
82 reinterpret_cast<const char*
>(cur_node->name),
85 auto filename_length = xmlStrlen(include_file_char_pointer);
87 reinterpret_cast<char*
>(include_file_char_pointer),
89 if (
auto const filepath = std::filesystem::path(filename);
90 filepath.is_relative())
92 filename = (prj_dir / filepath).
string();
95 if (!std::filesystem::exists(filename))
98 "Error while processing includes in prj file. Error in "
99 "element '{:s}' on line {:d}: Include file is not "
102 reinterpret_cast<const char*
>(cur_node->name),
104 reinterpret_cast<const char*
>(include_file_char_pointer));
106 INFO(
"Including {:s} into project file.", filename);
108 const std::ifstream input_stream(filename, std::ios_base::binary);
109 if (input_stream.fail())
111 OGS_FATAL(
"Failed to open file {}!", filename);
113 std::stringstream buffer;
114 buffer << input_stream.rdbuf();
115 const std::string xml = buffer.str();
118 std::regex xmlDeclaration(
"<\\?xml.*?>");
119 const std::string xml_filtered =
120 std::regex_replace(xml, xmlDeclaration,
"");
122 xmlNodePtr pNewNode =
nullptr;
123 xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(),
124 (
int)xml_filtered.length(), 0, &pNewNode);
125 if (pNewNode !=
nullptr)
128 xmlNode* pChild = pNewNode;
129 while (pChild !=
nullptr)
131 xmlAddChild(cur_node->parent, xmlCopyNode(pChild, 1));
132 pChild = pChild->next;
134 xmlFreeNode(pNewNode);
138 auto next_node = cur_node->next;
139 xmlUnlinkNode(cur_node);
140 xmlFreeNode(cur_node);
141 cur_node = next_node;
145 xmlFreeNode(cur_node);
149 std::filesystem::path
const& prj_dir)
157 auto doc = xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
158 nullptr,
nullptr, 0);
161 OGS_FATAL(
"Error reading project file from memory.");
164 auto root_node = xmlDocGetRootElement(doc);
169 xmlDocDumpMemory(doc, &xmlbuff, &buffersize);
171 prj_stream << xmlbuff;
178void patchStream(std::string
const& patch_file, std::stringstream& prj_stream,
179 bool after_includes =
false)
183 auto patch = xmlParseFile(patch_file.c_str());
184 if (patch ==
nullptr)
186 OGS_FATAL(
"Error reading XML diff file {:s}.", patch_file);
189 auto doc = xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
190 nullptr,
nullptr, 0);
193 OGS_FATAL(
"Error reading project file from memory.");
196 auto node = xmlDocGetRootElement(patch);
198 for (node = node ? node->children :
nullptr; node; node = node->next)
200 if (node->type != XML_ELEMENT_NODE)
204 bool node_after_includes =
false;
205 xmlAttr* attribute = node->properties;
210 xmlNodeListGetString(node->doc, attribute->children, 1);
211 if (xmlStrEqual(attribute->name, xmlCharStrdup(
"after_includes")) &&
212 xmlStrEqual(value, xmlCharStrdup(
"true")))
214 node_after_includes =
true;
218 attribute = attribute->next;
221 if (after_includes != node_after_includes)
226 if (xmlStrEqual(node->name, xmlCharStrdup(
"add")))
228 rc = xml_patch_add(doc, node);
230 else if (xmlStrEqual(node->name, xmlCharStrdup(
"replace")))
232 rc = xml_patch_replace(doc, node);
234 else if (xmlStrEqual(node->name, xmlCharStrdup(
"remove")))
236 rc = xml_patch_remove(doc, node);
241 "Error while patching prj file with patch file {:}. Only "
242 "'add', 'replace' and 'remove' elements are allowed! Got an "
243 "element '{:s}' on line {:d}.",
244 patch_file,
reinterpret_cast<const char*
>(node->name),
251 "Error while patching prj file with patch file {:}. Error in "
252 "element '{:s}' on line {:d}.",
253 patch_file,
reinterpret_cast<const char*
>(node->name),
260 xmlDocDumpMemory(doc, &xmlbuff, &buffersize);
262 prj_stream << xmlbuff;
272 std::vector<std::string>& patch_files)
278 if (!patch_files.empty())
281 "It is not allowed to specify additional patch files "
282 "if a patch file was already specified as the "
285 auto patch = xmlReadFile(prj_file.c_str(),
nullptr, 0);
286 auto node = xmlDocGetRootElement(patch);
287 xmlChar
const base_file_string[] =
"base_file";
288 auto base_file = xmlGetProp(node, base_file_string);
289 if (base_file ==
nullptr)
292 "Error reading base prj file (base_file attribute) in given "
296 patch_files = {prj_file};
297 std::stringstream ss;
303 if (std::ifstream file(prj_file); file)
305 prj_stream << file.rdbuf();
311 ERR(
"File {:s} does not exist.", prj_file);
313 DBUG(
"Stream state flags: {:s}.", iostateToString(file.rdstate()));
314 OGS_FATAL(
"Could not open project file '{:s}' for reading.", prj_file);
318 for (
const auto& patch_file : patch_files)
325 const std::string& filepath,
326 const std::vector<std::string>& patch_files,
327 bool write_prj,
const std::string& out_directory)
329 std::string prj_file = filepath;
331 std::vector<std::string> patch_files_copy = patch_files;
334 std::filesystem::absolute(std::filesystem::path(prj_file))
337 for (
const auto& patch_file : patch_files_copy)
351 xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
352 nullptr,
nullptr, XML_PARSE_NOBLANKS);
353 auto prj_out = (std::filesystem::path(out_directory) /
354 std::filesystem::path(filepath).stem())
357 xmlSaveFormatFileEnc(prj_out.c_str(), doc,
"utf-8", 1);
358 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.