LCOV - code coverage report
Current view: top level - src/esys/repo/manifest - xmlfileimpl_manifest.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 182 200 91.0 %
Date: 2026-08-01 10:43:40 Functions: 20 21 95.2 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/manifest/xmlfileimpl_manifest.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 2020 Michel Gillet
       9             :  * Distributed under the MIT License.
      10             :  * (See accompanying file LICENSE.txt or
      11             :  * copy at https://opensource.org/licenses/MIT)
      12             :  *
      13             :  * __legal_e__
      14             :  * \endcond
      15             :  *
      16             :  */
      17             : 
      18             : #include "esys/repo/esysrepo_prec.h"
      19             : #include "esys/repo/manifest/xmlfileimpl.h"
      20             : #include "esys/repo/manifest/xmlfile.h"
      21             : 
      22             : #include <esysfile/xml/writer.h>
      23             : #include <esysfile/xml/file.h>
      24             : #include <esysfile/xml/attr.h>
      25             : 
      26             : namespace esys::repo::manifest
      27             : {
      28             : 
      29          28 : XMLFileImpl::XMLFileImpl(XMLFile *self)
      30          28 :     : m_self(self)
      31             : {
      32          28 : }
      33             : 
      34          56 : XMLFileImpl::~XMLFileImpl() = default;
      35             : 
      36          25 : Result XMLFileImpl::read(const std::string &path)
      37             : {
      38          25 :     esysfile::xml::File xml_file;
      39             : 
      40          25 :     xml_file.set_root_node_name("esysrepo_manifest");
      41          25 :     int result = xml_file.read(path);
      42          25 :     if (result < 0)
      43             :     {
      44           0 :         self()->add_error(result, "XML parsing failed.");
      45           0 :         return ESYSREPO_RESULT(ResultCode::MANIFEST_ERROR_PARSING_FILE, path);
      46             :     }
      47             : 
      48          50 :     if (self()->get_data() == nullptr) self()->set_data(std::make_shared<Manifest>());
      49             : 
      50          25 :     self()->get_data()->set_type(Type::ESYSREPO_MANIFEST);
      51             : 
      52          50 :     return read(xml_file.get_data());
      53          25 : }
      54             : 
      55          25 : Result XMLFileImpl::read(std::shared_ptr<esysfile::xml::Data> data)
      56             : {
      57          25 :     if (data->get_attrs().size() != 0)
      58             :     {
      59           8 :         Result result = read_root_attributes(data);
      60           4 :         if (result.error())
      61             :         {
      62           0 :             self()->add_error(result.get_result_code_int(), "read_root_attributes failed.");
      63           0 :             return ESYSREPO_RESULT(result);
      64             :         }
      65           4 :     }
      66             :     else
      67          42 :         self()->get_data()->set_kind(manifest::Kind::ISOLATED);
      68             : 
      69          25 :     Result result;
      70             : 
      71         102 :     for (auto el : data->get_elements())
      72             :     {
      73          77 :         if (el->get_name() == "location")
      74         150 :             result = read_location(el);
      75          27 :         else if ((el->get_name() == "default"))
      76          75 :             result = read_default(el);
      77           2 :         else if ((el->get_name() == "group"))
      78           6 :             result = read_group(el);
      79             :         else
      80           0 :             result = ESYSREPO_RESULT(ResultCode::MANIFEST_ELEMENT_UNKNOWN, el->get_name());
      81          77 :         if (result.error())
      82             :         {
      83           0 :             self()->add_error(result.get_result_code_int(), "Reading XML element failed : " + el->get_name());
      84           0 :             return result;
      85             :         }
      86          77 :     }
      87          25 :     return ESYSREPO_RESULT(ResultCode::OK);
      88          25 : }
      89             : 
      90           4 : Result XMLFileImpl::read_root_attributes(std::shared_ptr<esysfile::xml::Element> root_el)
      91             : {
      92           8 :     for (auto attr : root_el->get_attrs())
      93             :     {
      94           8 :         Result result = read_root_attribute(attr);
      95           4 :         if (result.error()) return ESYSREPO_RESULT(result);
      96           8 :     }
      97           4 :     return ESYSREPO_RESULT(ResultCode::OK);
      98             : }
      99             : 
     100           4 : Result XMLFileImpl::read_root_attribute(std::shared_ptr<esysfile::xml::Attr> attr)
     101             : {
     102           4 :     if (attr->get_name() != "kind") return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     103             : 
     104           4 :     manifest::Kind kind;
     105           4 :     Result result = convert(attr->get_value(), kind);
     106           4 :     if (result.error()) return ESYSREPO_RESULT(result, ResultCode::MANIFEST_KIND_UNKNOWN, attr->get_value());
     107             : 
     108           4 :     self()->get_data()->set_kind(kind);
     109           4 :     return ESYSREPO_RESULT(ResultCode::OK);
     110           4 : }
     111             : 
     112          50 : Result XMLFileImpl::read_location(std::shared_ptr<esysfile::xml::Element> el)
     113             : {
     114          50 :     if (el->get_name() != "location") return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     115             : 
     116          50 :     std::shared_ptr<Location> location = std::make_shared<Location>();
     117             : 
     118          50 :     auto attr = el->get_attr("name");
     119          50 :     if (attr != nullptr)
     120          50 :         location->set_name(attr->get_value());
     121             :     else
     122           0 :         return ESYSREPO_RESULT(ResultCode::MANIFEST_LOCATION_WITHOUT_NAME);
     123             : 
     124         100 :     attr = el->get_attr("addr");
     125          50 :     if (attr != nullptr)
     126          50 :         location->set_address(attr->get_value());
     127             :     else
     128           0 :         return ESYSREPO_RESULT(ResultCode::MANIFEST_LOCATION_WITHOUT_ADDRESS);
     129             : 
     130         100 :     attr = el->get_attr("alt_addr");
     131          50 :     if (attr != nullptr) location->set_alt_address(attr->get_value());
     132             : 
     133          50 :     Result result;
     134             : 
     135         329 :     for (auto child_el : el->get_elements())
     136             :     {
     137         279 :         if (child_el->get_name() == "repository")
     138        1395 :             result = read_repository(child_el, location);
     139             :         else
     140           0 :             result = ESYSREPO_RESULT(ResultCode::MANIFEST_ELEMENT_UNKNOWN, child_el->get_name());
     141         279 :         if (result.error()) return result;
     142         279 :     }
     143             : 
     144         150 :     self()->get_data()->add_location(location);
     145          50 :     return ESYSREPO_RESULT(ResultCode::OK);
     146         150 : }
     147             : 
     148         279 : Result XMLFileImpl::read_repository(std::shared_ptr<esysfile::xml::Element> el, std::shared_ptr<Location> location)
     149             : {
     150         279 :     if (el->get_name() != "repository") return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     151             : 
     152         279 :     auto repository = std::make_shared<Repository>();
     153         279 :     repository->set_location(location.get());
     154             : 
     155         279 :     auto attr = el->get_attr("name");
     156         279 :     if (attr == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_REPOSITORY_WITHOUT_NAME);
     157         279 :     repository->set_name(attr->get_value());
     158             : 
     159         558 :     attr = el->get_attr("path");
     160         279 :     if (attr == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_REPOSITORY_WITHOUT_PATH);
     161         279 :     repository->set_path(attr->get_value());
     162             : 
     163         558 :     attr = el->get_attr("revision");
     164         279 :     if (attr != nullptr) repository->set_revision(attr->get_value());
     165             : 
     166         558 :     location->add_repo(repository);
     167             : 
     168         279 :     return ESYSREPO_RESULT(ResultCode::OK);
     169         558 : }
     170             : 
     171          25 : Result XMLFileImpl::read_default(std::shared_ptr<esysfile::xml::Element> el)
     172             : {
     173          25 :     if (el->get_name() != "default") return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     174             : 
     175          75 :     for (auto attr : el->get_attrs())
     176             :     {
     177         100 :         Result result = read_default_attr(attr);
     178          50 :         if (result.error()) return result;
     179         100 :     }
     180          25 :     return ESYSREPO_RESULT(ResultCode::OK);
     181             : }
     182             : 
     183          50 : Result XMLFileImpl::read_default_attr(std::shared_ptr<esysfile::xml::Attr> attr)
     184             : {
     185          50 :     if (attr->get_name() == "revision")
     186          50 :         self()->get_data()->set_default_revision(attr->get_value());
     187          25 :     else if (attr->get_name() == "sync-j")
     188          50 :         self()->get_data()->set_default_job_count(atoi(attr->get_value().c_str()));
     189             :     else
     190           0 :         return ESYSREPO_RESULT(ResultCode::MANIFEST_ATTRIBUTE_UNKNOWN, attr->get_name());
     191          50 :     return ESYSREPO_RESULT(ResultCode::OK);
     192             : }
     193             : 
     194           2 : Result XMLFileImpl::read_group(std::shared_ptr<esysfile::xml::Element> el)
     195             : {
     196           2 :     auto attr = el->get_attr("name");
     197           2 :     if (attr == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_GROUP_WITHOUT_NAME);
     198             : 
     199           2 :     std::shared_ptr<Group> group = std::make_shared<Group>();
     200           2 :     group->set_name(attr->get_value());
     201             : 
     202           6 :     for (auto child : el->get_elements())
     203             :     {
     204          16 :         Result result = read_group_repo(child, group);
     205           4 :         if (result.error()) return ESYSREPO_RESULT(result);
     206           8 :     }
     207             : 
     208           6 :     self()->get_data()->get_groups().add_group(group);
     209             : 
     210           2 :     return ESYSREPO_RESULT(ResultCode::OK);
     211           4 : }
     212             : 
     213           4 : Result XMLFileImpl::read_group_repo(std::shared_ptr<esysfile::xml::Element> el, std::shared_ptr<Group> group)
     214             : {
     215           4 :     if (el->get_name() != "repo") return ESYSREPO_RESULT(ResultCode::MANIFEST_GROUP_REPO_WITHOUT_NAME);
     216             : 
     217           4 :     auto attr = el->get_attr("path");
     218           4 :     if (attr == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_GROUP_REPO_WITHOUT_PATH);
     219             : 
     220           4 :     auto repo = self()->get_data()->find_repo_by_path(attr->get_value());
     221           4 :     if (repo == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_REPO_UNKNOWN, "path = " + attr->get_value());
     222             : 
     223           8 :     group->add_repo(repo);
     224           4 :     return ESYSREPO_RESULT(ResultCode::OK);
     225           8 : }
     226             : 
     227           3 : Result XMLFileImpl::write_xml()
     228             : {
     229           6 :     if (self()->get_data() == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_XML_DATA_NULLPTR);
     230             : 
     231           3 :     m_xml_data = std::make_shared<esysfile::xml::Data>();
     232           3 :     m_xml_data->set_root_node_name("esysrepo_manifest");
     233             : 
     234           6 :     if (self()->get_data()->get_kind() != manifest::Kind::ISOLATED)
     235             :     {
     236           0 :         std::string kind;
     237           0 :         Result result = convert(self()->get_data()->get_kind(), kind);
     238           0 :         if (result.error()) return ESYSREPO_RESULT(result);
     239           0 :         m_xml_data->add_attr("kind", kind);
     240           0 :     }
     241             : 
     242          13 :     for (auto location : self()->get_data()->get_locations())
     243             :     {
     244          28 :         Result result = write(m_xml_data, location);
     245           7 :         if (result.error()) return ESYSREPO_RESULT(result);
     246          14 :     }
     247             : 
     248           8 :     for (auto group : self()->get_data()->get_groups().get_groups())
     249             :     {
     250           8 :         Result result = write(m_xml_data, group);
     251           2 :         if (result.error()) return ESYSREPO_RESULT(result);
     252           4 :     }
     253           3 :     return ESYSREPO_RESULT(ResultCode::OK);
     254             : }
     255             : 
     256           1 : Result XMLFileImpl::write(const std::string &path)
     257             : {
     258           1 :     Result result = write_xml();
     259           1 :     if (result.error()) return ESYSREPO_RESULT(result);
     260             : 
     261           1 :     esysfile::xml::Writer writer;
     262             : 
     263           1 :     writer.set_indent(4);
     264           2 :     int result_int = writer.write(path, m_xml_data);
     265           1 :     if (result_int < 0) return ESYSREPO_RESULT(ResultCode::RAW_INT_ERROR, result_int);
     266           1 :     return ESYSREPO_RESULT(ResultCode::OK);
     267           1 : }
     268             : 
     269           2 : Result XMLFileImpl::write(std::ostream &os)
     270             : {
     271           2 :     Result result = write_xml();
     272           2 :     if (result.error()) return ESYSREPO_RESULT(result);
     273             : 
     274           2 :     esysfile::xml::Writer writer;
     275             : 
     276           2 :     writer.set_indent(4);
     277           4 :     int result_int = writer.write(os, m_xml_data);
     278           2 :     if (result_int < 0) return ESYSREPO_RESULT(ResultCode::RAW_INT_ERROR, result_int);
     279           2 :     return ESYSREPO_RESULT(ResultCode::OK);
     280           2 : }
     281             : 
     282           7 : Result XMLFileImpl::write(std::shared_ptr<esysfile::xml::Element> parent_el, std::shared_ptr<Location> location)
     283             : {
     284           7 :     std::shared_ptr<esysfile::xml::Element> location_el = std::make_shared<esysfile::xml::Element>();
     285             : 
     286           7 :     location_el->set_name("location");
     287           7 :     location_el->add_attr("name", location->get_name());
     288           7 :     location_el->add_attr("addr", location->get_address());
     289             : 
     290          77 :     for (auto repo : location->get_repos())
     291             :     {
     292         280 :         Result result = write(location_el, repo);
     293          70 :         if (result.error()) return ESYSREPO_RESULT(result);
     294         140 :     }
     295             : 
     296          14 :     parent_el->add_element(location_el);
     297           7 :     return ESYSREPO_RESULT(ResultCode::OK);
     298           7 : }
     299             : 
     300          70 : Result XMLFileImpl::write(std::shared_ptr<esysfile::xml::Element> parent_el, std::shared_ptr<Repository> repository)
     301             : {
     302          70 :     std::shared_ptr<esysfile::xml::Element> repo_el = std::make_shared<esysfile::xml::Element>();
     303             : 
     304          70 :     repo_el->set_name("repository");
     305          70 :     repo_el->add_attr("path", repository->get_path());
     306          70 :     repo_el->add_attr("name", repository->get_name());
     307          90 :     if (!repository->get_revision().empty()) repo_el->add_attr("revision", repository->get_revision());
     308             : 
     309         140 :     parent_el->add_element(repo_el);
     310          70 :     return ESYSREPO_RESULT(ResultCode::OK);
     311          70 : }
     312             : 
     313           2 : Result XMLFileImpl::write(std::shared_ptr<esysfile::xml::Element> parent_el, std::shared_ptr<Group> group)
     314             : {
     315           2 :     std::shared_ptr<esysfile::xml::Element> grp_el = std::make_shared<esysfile::xml::Element>();
     316             : 
     317           2 :     grp_el->set_name("group");
     318           2 :     grp_el->add_attr("name", group->get_name());
     319             : 
     320           8 :     for (auto repo : group->get_repos())
     321             :     {
     322           6 :         std::shared_ptr<esysfile::xml::Element> repo_el = std::make_shared<esysfile::xml::Element>();
     323             : 
     324           6 :         repo_el->set_name("repo");
     325           6 :         repo_el->add_attr("path", repo->get_path());
     326          18 :         grp_el->add_element(repo_el);
     327          12 :     }
     328             : 
     329           4 :     parent_el->add_element(grp_el);
     330           2 :     return ESYSREPO_RESULT(ResultCode::OK);
     331           2 : }
     332             : 
     333         194 : XMLFile *XMLFileImpl::self()
     334             : {
     335         194 :     return m_self;
     336             : }
     337             : 
     338           0 : const XMLFile *XMLFileImpl::self() const
     339             : {
     340           0 :     return m_self;
     341             : }
     342             : 
     343             : } // namespace esys::repo::manifest

Generated by: LCOV version 1.14