57 std::filesystem::path
const& prj_dir)
59 xmlNode* cur_node =
nullptr;
60 for (cur_node = node; cur_node; cur_node = cur_node->next)
62 if (cur_node->type != XML_ELEMENT_NODE)
66 if (xmlStrEqual(cur_node->name, xmlCharStrdup(
"include")))
68 auto include_file_char_pointer =
69 xmlGetProp(cur_node, xmlCharStrdup(
"file"));
70 if (include_file_char_pointer ==
nullptr)
73 "Error while processing includes in prj file. Error in "
74 "element '{:s}' on line {:d}: no file attribute given!",
75 reinterpret_cast<const char*
>(cur_node->name),
78 auto filename_length = xmlStrlen(include_file_char_pointer);
80 reinterpret_cast<char*
>(include_file_char_pointer),
82 if (
auto const filepath = std::filesystem::path(filename);
83 filepath.is_relative())
85 filename = (prj_dir / filepath).
string();
88 if (!std::filesystem::exists(filename))
91 "Error while processing includes in prj file. Error in "
92 "element '{:s}' on line {:d}: Include file is not "
95 reinterpret_cast<const char*
>(cur_node->name),
97 reinterpret_cast<const char*
>(include_file_char_pointer));
99 INFO(
"Including {:s} into project file.", filename);
101 const std::ifstream input_stream(filename, std::ios_base::binary);
102 if (input_stream.fail())
104 OGS_FATAL(
"Failed to open file {}!", filename);
106 std::stringstream buffer;
107 buffer << input_stream.rdbuf();
108 const std::string xml = buffer.str();
111 std::regex xmlDeclaration(
"<\\?xml.*?>");
112 const std::string xml_filtered =
113 std::regex_replace(xml, xmlDeclaration,
"");
115 xmlNodePtr pNewNode =
nullptr;
116 xmlParseInNodeContext(cur_node->parent, xml_filtered.c_str(),
117 (
int)xml_filtered.length(), 0, &pNewNode);
118 if (pNewNode !=
nullptr)
121 xmlNode* pChild = pNewNode;
122 while (pChild !=
nullptr)
124 xmlAddChild(cur_node->parent, xmlCopyNode(pChild, 1));
125 pChild = pChild->next;
127 xmlFreeNode(pNewNode);
131 auto next_node = cur_node->next;
132 xmlUnlinkNode(cur_node);
133 xmlFreeNode(cur_node);
134 cur_node = next_node;
138 xmlFreeNode(cur_node);
142 std::filesystem::path
const& prj_dir)
150 auto doc = xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
151 nullptr,
nullptr, 0);
154 OGS_FATAL(
"Error reading project file from memory.");
157 auto root_node = xmlDocGetRootElement(doc);
162 xmlDocDumpMemory(doc, &xmlbuff, &buffersize);
164 prj_stream << xmlbuff;
171void patchStream(std::string
const& patch_file, std::stringstream& prj_stream,
172 bool after_includes =
false)
176 auto patch = xmlParseFile(patch_file.c_str());
177 if (patch ==
nullptr)
179 OGS_FATAL(
"Error reading XML diff file {:s}.", patch_file);
182 auto doc = xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
183 nullptr,
nullptr, 0);
186 OGS_FATAL(
"Error reading project file from memory.");
189 auto node = xmlDocGetRootElement(patch);
191 for (node = node ? node->children :
nullptr; node; node = node->next)
193 if (node->type != XML_ELEMENT_NODE)
197 bool node_after_includes =
false;
198 xmlAttr* attribute = node->properties;
203 xmlNodeListGetString(node->doc, attribute->children, 1);
204 if (xmlStrEqual(attribute->name, xmlCharStrdup(
"after_includes")) &&
205 xmlStrEqual(value, xmlCharStrdup(
"true")))
207 node_after_includes =
true;
211 attribute = attribute->next;
214 if (after_includes != node_after_includes)
219 if (xmlStrEqual(node->name, xmlCharStrdup(
"add")))
221 rc = xml_patch_add(doc, node);
223 else if (xmlStrEqual(node->name, xmlCharStrdup(
"replace")))
225 rc = xml_patch_replace(doc, node);
227 else if (xmlStrEqual(node->name, xmlCharStrdup(
"remove")))
229 rc = xml_patch_remove(doc, node);
234 "Error while patching prj file with patch file {:}. Only "
235 "'add', 'replace' and 'remove' elements are allowed! Got an "
236 "element '{:s}' on line {:d}.",
237 patch_file,
reinterpret_cast<const char*
>(node->name),
244 "Error while patching prj file with patch file {:}. Error in "
245 "element '{:s}' on line {:d}.",
246 patch_file,
reinterpret_cast<const char*
>(node->name),
253 xmlDocDumpMemory(doc, &xmlbuff, &buffersize);
255 prj_stream << xmlbuff;
265 std::vector<std::string>& patch_files)
271 if (!patch_files.empty())
274 "It is not allowed to specify additional patch files "
275 "if a patch file was already specified as the "
278 auto patch = xmlReadFile(prj_file.c_str(),
nullptr, 0);
279 auto node = xmlDocGetRootElement(patch);
280 xmlChar
const base_file_string[] =
"base_file";
281 auto base_file = xmlGetProp(node, base_file_string);
282 if (base_file ==
nullptr)
285 "Error reading base prj file (base_file attribute) in given "
289 patch_files = {prj_file};
290 std::stringstream ss;
296 if (std::ifstream file(prj_file); file)
298 prj_stream << file.rdbuf();
304 ERR(
"File {:s} does not exist.", prj_file);
306 DBUG(
"Stream state flags: {:s}.", iostateToString(file.rdstate()));
307 OGS_FATAL(
"Could not open project file '{:s}' for reading.", prj_file);
311 for (
const auto& patch_file : patch_files)
318 const std::string& filepath,
319 const std::vector<std::string>& patch_files,
320 bool write_prj,
const std::string& out_directory)
322 std::string prj_file = filepath;
324 std::vector<std::string> patch_files_copy = patch_files;
327 std::filesystem::absolute(std::filesystem::path(prj_file))
330 for (
const auto& patch_file : patch_files_copy)
344 xmlReadMemory(prj_stream.str().c_str(), prj_stream.str().size(),
345 nullptr,
nullptr, XML_PARSE_NOBLANKS);
346 auto prj_out = (std::filesystem::path(out_directory) /
347 std::filesystem::path(filepath).stem())
350 xmlSaveFormatFileEnc(prj_out.c_str(), doc,
"utf-8", 1);
351 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.