LCOV - code coverage report
Current view: top level - src/esys/repo/exe - cmdinit.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 423 634 66.7 %
Date: 2026-11-07 22:18:26 Functions: 45 51 88.2 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/exe/cmdinit.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 2020-2023 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/exe/cmdinit.h"
      20             : #include "esys/repo/exe/nested.h"
      21             : #include "esys/repo/filesystem.h"
      22             : #include "esys/repo/git/url.h"
      23             : #include "esys/repo/manifest/base.h"
      24             : #include "esys/repo/manifest/file.h"
      25             : #include "esys/repo/manifest/xmlfile.h"
      26             : #include "esys/repo/grepo/manifest.h"
      27             : #include "esys/repo/manifest/directorymngr.h"
      28             : 
      29             : #include <esys/trace/call.h>
      30             : #include <esys/trace/macros.h>
      31             : 
      32             : #include <boost/filesystem.hpp>
      33             : #include <boost/system/error_code.hpp>
      34             : 
      35             : #include <cassert>
      36             : #include <iostream>
      37             : #include <sstream>
      38             : 
      39             : namespace esys::repo::exe
      40             : {
      41             : 
      42          52 : CmdInit::CmdInit()
      43         104 :     : Cmd("Init")
      44             : {
      45          52 : }
      46             : 
      47          53 : CmdInit::~CmdInit() = default;
      48             : 
      49          52 : void CmdInit::set_url(const std::string &url)
      50             : {
      51          52 :     m_url = url;
      52          52 : }
      53             : 
      54         110 : const std::string &CmdInit::get_url() const
      55             : {
      56         110 :     return m_url;
      57             : }
      58             : 
      59          18 : void CmdInit::set_branch(const std::string &branch)
      60             : {
      61          18 :     m_branch = branch;
      62          18 : }
      63             : 
      64          36 : const std::string &CmdInit::get_branch() const
      65             : {
      66          36 :     return m_branch;
      67             : }
      68             : 
      69          16 : void CmdInit::set_rev_set(const std::string &rev_set)
      70             : {
      71          16 :     m_rev_set = rev_set;
      72          16 : }
      73             : 
      74          15 : const std::string &CmdInit::get_rev_set() const
      75             : {
      76          15 :     return m_rev_set;
      77             : }
      78             : 
      79          18 : void CmdInit::set_prefer_branch(const std::string &prefer_branch)
      80             : {
      81          18 :     m_prefer_branch = prefer_branch;
      82          18 : }
      83             : 
      84          47 : const std::string &CmdInit::get_prefer_branch() const
      85             : {
      86          47 :     return m_prefer_branch;
      87             : }
      88             : 
      89          15 : void CmdInit::set_manifest_name(const std::string &manifest_name)
      90             : {
      91          15 :     m_manifest_name = manifest_name;
      92          15 : }
      93             : 
      94          37 : const std::string &CmdInit::get_manifest_name() const
      95             : {
      96          37 :     return m_manifest_name;
      97             : }
      98             : 
      99          16 : void CmdInit::set_project_name(const std::string &project_name)
     100             : {
     101          16 :     m_project_name = project_name;
     102          16 : }
     103             : 
     104           3 : const std::string &CmdInit::get_project_name() const
     105             : {
     106           3 :     return m_project_name;
     107             : }
     108             : 
     109          22 : void CmdInit::set_manifest_local(const std::string &manifest_local)
     110             : {
     111          22 :     m_manifest_local = manifest_local;
     112          22 : }
     113             : 
     114          44 : const std::string &CmdInit::get_manifest_local() const
     115             : {
     116          44 :     return m_manifest_local;
     117             : }
     118             : 
     119          17 : void CmdInit::set_google_manifest(bool google_manifest)
     120             : {
     121          17 :     m_google_manifest = google_manifest;
     122          17 :     m_manifest_type = manifest::Type::GOOGLE_MANIFEST;
     123          17 : }
     124             : 
     125          37 : bool CmdInit::get_google_manifest() const
     126             : {
     127          37 :     return m_google_manifest;
     128             : }
     129             : 
     130          15 : void CmdInit::set_git_super_project(bool git_super_project)
     131             : {
     132          15 :     m_git_super_project = git_super_project;
     133          15 :     m_manifest_type = manifest::Type::GOOGLE_MANIFEST;
     134          15 : }
     135             : 
     136          58 : bool CmdInit::get_git_super_project() const
     137             : {
     138          58 :     return m_git_super_project;
     139             : }
     140             : 
     141          16 : void CmdInit::set_parse_mode(manifest::ParseMode mode)
     142             : {
     143          16 :     m_parse_mode = mode;
     144          16 : }
     145             : 
     146          46 : manifest::ParseMode CmdInit::get_parse_mode() const
     147             : {
     148          46 :     return m_parse_mode;
     149             : }
     150             : 
     151           0 : std::string CmdInit::get_extra_start_msg()
     152             : {
     153           0 :     if (!get_manifest_local().empty()) return "\n    local : " + get_manifest_local();
     154           0 :     return "\n    url : " + get_url();
     155             : }
     156             : 
     157           1 : void CmdInit::set_bootstrap_nested(bool bootstrap_nested)
     158             : {
     159           1 :     m_bootstrap_nested = bootstrap_nested;
     160           1 : }
     161             : 
     162          31 : bool CmdInit::get_bootstrap_nested() const
     163             : {
     164          31 :     return m_bootstrap_nested;
     165             : }
     166             : 
     167          32 : Result CmdInit::impl_run()
     168             : {
     169          32 :     Result result;
     170          32 :     ETRC_CALL_RET_NP(result);
     171             : 
     172          32 :     if (get_git_super_project()) warn("The option --git-super is not implemented yet");
     173             : 
     174          32 :     result = only_one_folder_or_workspace();
     175          32 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     176             : 
     177          32 :     result = load_esysrepo_folder();
     178          32 :     if (result.ok())
     179             :     {
     180           1 :         if (get_url().empty() && !get_project_name().empty())
     181             :         {
     182           0 :             info("Finding URL for project " + get_project_name() + " ...");
     183           0 :             result = find_url_from_project_name();
     184           0 :             if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     185           0 :             if (!get_url().empty()) info("Found URL : '" + get_url() + "'.");
     186             :         }
     187           1 :         result = load_esysrepo_folder_succeeded();
     188             :     }
     189             :     else
     190             :     {
     191          31 :         result = load_esysrepo_folder_failed();
     192             :     }
     193          33 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     194             : 
     195          31 :     if (get_bootstrap_nested())
     196             :     {
     197          30 :         NestedContext nested_ctx;
     198          30 :         NestedContext *ctx = get_nested_context() != nullptr ? get_nested_context() : &nested_ctx;
     199          30 :         set_nested_context(ctx);
     200          30 :         result = bootstrap_nested_workspaces(*this, *ctx);
     201          30 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     202          30 :     }
     203             : 
     204          62 :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     205          32 : }
     206             : 
     207           1 : Result CmdInit::load_esysrepo_folder_succeeded()
     208             : {
     209           1 :     Result result;
     210           1 :     ETRC_CALL_RET_NP(result);
     211             : 
     212           1 :     assert(get_config_folder() != nullptr);
     213           2 :     if (get_config_folder() == nullptr)
     214             :     {
     215           0 :         error("Internal error [CmdInit::load_esysrepo_folder_succeeded] get_config_folder() == nullptr");
     216           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR));
     217             :     }
     218             : 
     219           1 :     auto config = get_config_folder()->get_config();
     220           1 :     assert(config != nullptr);
     221           1 :     if (config == nullptr)
     222             :     {
     223           0 :         error("Internal error [CmdInit::load_esysrepo_folder_succeeded] config == nullptr");
     224           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR));
     225             :     }
     226             : 
     227           1 :     if (!get_manifest_local().empty())
     228             :     {
     229           0 :         boost::filesystem::path local_abs = boost::filesystem::absolute(get_manifest_local()).lexically_normal();
     230           0 :         boost::filesystem::path ws = boost::filesystem::absolute(get_workspace_path()).lexically_normal();
     231           0 :         std::string want = boost::filesystem::relative(local_abs, ws).generic_string();
     232           0 :         if (want.empty()) want = ".";
     233           0 :         if (want != config->get_manifest_local())
     234             :         {
     235           0 :             std::stringstream oss;
     236           0 :             oss << "Current manifest local is:" << std::endl;
     237           0 :             oss << "    '" << config->get_manifest_local() << "'" << std::endl;
     238           0 :             oss << "But --manifest-local given is different:" << std::endl;
     239           0 :             oss << "    '" << want << "'" << std::endl;
     240           0 :             oss << "Use --force if this is really wanted.";
     241           0 :             error(oss.str());
     242           0 :             return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_INCORRECT_PARAMETERS_IN_CONTEXT, oss.str()));
     243           0 :         }
     244           0 :         warn("Nothing to do: workspace already initialized from this local manifest.");
     245           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     246           0 :     }
     247             : 
     248           1 :     git::URL url(get_url());
     249           1 :     if (url != config->get_manifest_url())
     250             :     {
     251           0 :         std::stringstream oss;
     252             : 
     253           0 :         oss << "Current manifest url is:" << std::endl;
     254           0 :         oss << "    '" << config->get_manifest_url() << "'" << std::endl;
     255           0 :         oss << "But manifest url given is different:" << std::endl;
     256           0 :         oss << "    '" << get_url() << "'" << std::endl;
     257           0 :         oss << "Use --force if this is really wanted.";
     258           0 :         error(oss.str());
     259           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_INCORRECT_PARAMETERS_IN_CONTEXT, oss.str()));
     260           0 :     }
     261             : 
     262           1 :     if (get_branch().empty())
     263             :     {
     264           1 :         warn("Nothing to do as a branch is not provided");
     265           2 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     266             :     }
     267             : 
     268           0 :     boost::filesystem::path manifest_git_path = get_config_folder()->get_manifest_repo_path();
     269             : 
     270           0 :     auto git_helper = new_git_helper();
     271             : 
     272           0 :     debug(1, "Test debug, before git_helper");
     273           0 :     git_helper->debug(1, "Test debug with git_helper");
     274             : 
     275           0 :     result = git_helper->open(manifest_git_path.lexically_normal().make_preferred().string(), log::DEBUG);
     276           0 :     if (result.error())
     277             :     {
     278           0 :         std::string err_str = "Opening git repo holding the manifest failed.";
     279           0 :         error(err_str);
     280           0 :         return ETRC_RET(ESYSREPO_RESULT(result, err_str));
     281           0 :     }
     282             : 
     283           0 :     result = get_git()->checkout(get_branch() /*, get_force()*/);
     284           0 :     if (result.error())
     285             :     {
     286           0 :         std::string err_str = "Checkout branch failed.";
     287           0 :         error(err_str);
     288           0 :         return ETRC_RET(ESYSREPO_RESULT(result, err_str));
     289           0 :     }
     290             : 
     291           0 :     result = get_git()->close();
     292             : 
     293           0 :     return ETRC_RET(ESYSREPO_RESULT(result));
     294           2 : }
     295             : 
     296          31 : Result CmdInit::load_esysrepo_folder_failed()
     297             : {
     298          31 :     Result result;
     299          31 :     ETRC_CALL_RET_NP(result);
     300             : 
     301             :     // Since it failed, either there is no .esysrepo folder or the xml config
     302             :     // file is corrupted
     303          31 :     result = create_esysrepo_folder();
     304          31 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     305             : 
     306             :     // Now there are 2 cases, we couldn't load be the ESysRepo config folder because
     307             :     // it got corrupted, or it's not there at all.
     308          31 :     result = fetch_manifest();
     309          32 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     310             : 
     311          30 :     return ETRC_RET(Result::OK);
     312          31 : }
     313             : 
     314          31 : Result CmdInit::fetch_manifest()
     315             : {
     316          31 :     Result result;
     317          31 :     ETRC_CALL_RET_NP(result);
     318             : 
     319          37 :     if (!get_manifest_local().empty()) return ETRC_RET(fetch_local_manifest());
     320             : 
     321          25 :     if (get_google_manifest())
     322           4 :         return ETRC_RET(fetch_google_manifest());
     323          23 :     else if (get_git_super_project())
     324           0 :         return ETRC_RET(fetch_git_super_project());
     325             : 
     326             :     // Here we can't be sure, either it's a google manifest, a esysrepo manifest or a git super project
     327          46 :     return ETRC_RET(fetch_unknown_manifest());
     328          31 : }
     329             : 
     330          32 : std::string CmdInit::get_google_manifest_filename() const
     331             : {
     332          32 :     if (!get_manifest_name().empty()) return get_manifest_name();
     333          32 :     return "default.xml";
     334             : }
     335             : 
     336          25 : Result CmdInit::clone_manifest_repo(GitHelper &git_helper, std::string &git_repo_path)
     337             : {
     338          25 :     Result result;
     339          25 :     ETRC_CALL_RET_NP(result);
     340             : 
     341          50 :     if (get_git() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR));
     342             : 
     343          25 :     if (get_url().empty() && !get_project_name().empty())
     344             :     {
     345           2 :         info("Finding URL for project " + get_project_name() + " ...");
     346           1 :         result = find_url_from_project_name();
     347           1 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     348           2 :         if (!get_url().empty()) info("Found URL : '" + get_url() + "'.");
     349             :     }
     350             : 
     351          25 :     if (get_url().empty())
     352             :     {
     353           0 :         error("URL is empty");
     354           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMDINIT_NO_URL));
     355             :     }
     356             : 
     357          25 :     boost::filesystem::path path = get_config_folder()->get_temp_path();
     358          25 :     path /= "unknown_manifest";
     359          50 :     git_repo_path = path.lexically_normal().make_preferred().string();
     360             : 
     361          25 :     debug(1, "Test debug, before git_helper");
     362          25 :     git_helper.debug(1, "Test debug with git_helper");
     363             : 
     364          25 :     result = git_helper.clone(get_url(), git_repo_path, false, log::DEBUG);
     365          25 :     if (result.error())
     366             :     {
     367           0 :         error("Cloning failed.");
     368           0 :         return ETRC_RET(ESYSREPO_RESULT(result));
     369             :     }
     370             : 
     371          25 :     if (!get_branch().empty())
     372             :     {
     373           2 :         result = get_git()->checkout(get_branch() /*, get_force()*/);
     374           2 :         if (result.error())
     375             :         {
     376           0 :             std::string err_str = "Cloning failed : checkout branch failed.";
     377           0 :             error(err_str);
     378           0 :             return ETRC_RET(ESYSREPO_RESULT(result, err_str));
     379           0 :         }
     380             :     }
     381             : 
     382          25 :     result = git_helper.close(log::DEBUG);
     383          25 :     if (result.error())
     384             :     {
     385           0 :         std::string err_str = "Cloning failed : can't clod the git repo.";
     386           0 :         error(err_str);
     387           0 :         return ETRC_RET(ESYSREPO_RESULT(result, err_str));
     388           0 :     }
     389             : 
     390          50 :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     391          25 : }
     392             : 
     393          16 : Result CmdInit::install_google_manifest(GitHelper &git_helper, const std::string &git_repo_path)
     394             : {
     395          16 :     Result result;
     396          16 :     ETRC_CALL_RET(result, git_repo_path);
     397             : 
     398          16 :     auto config = get_config_folder()->get_or_new_config();
     399          16 :     config->set_manifest_type(manifest::Type::GOOGLE_MANIFEST);
     400          16 :     config->set_manifest_format(manifest::Format::XML);
     401          16 :     config->set_manifest_url(get_url());
     402          16 :     config->set_parse_mode(get_parse_mode());
     403          16 :     if (!get_prefer_branch().empty()) config->set_prefer_branch(get_prefer_branch());
     404             : 
     405          16 :     boost::filesystem::path source = git_repo_path;
     406          32 :     boost::filesystem::path rel_source = boost::filesystem::relative(source);
     407          16 :     boost::filesystem::path target = get_config_folder()->get_path();
     408          32 :     boost::filesystem::path rel_target = boost::filesystem::relative(target);
     409          16 :     target /= grepo::Manifest::get_folder_name();
     410          32 :     rel_target = boost::filesystem::relative(target);
     411             : 
     412          16 :     bool result_bool = boost::filesystem::create_directory(target);
     413          16 :     if (!result_bool)
     414             :     {
     415           0 :         std::string err_str = "Couldn't create the folder : " + rel_target.string();
     416           0 :         error(err_str);
     417           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::FOLDER_CREATION_ERROR, err_str));
     418           0 :     }
     419          16 :     debug(0, "Created folder : " + rel_target.string());
     420             : 
     421          16 :     result = git_helper.move(source.string(), target.string(), true, log::Level::DEBUG);
     422          16 :     if (result == ResultCode::FAILED_TO_COPY) return ETRC_RET(ESYSREPO_RESULT(result));
     423          16 :     if (result == ResultCode::FAILED_TO_REMOVE_ALL)
     424           0 :         warn("While moving folder " + rel_source.string() + " some files were left behind.");
     425             : 
     426          16 :     std::string manifest_path = "grepo/" + get_google_manifest_filename();
     427          32 :     get_config_folder()->get_config()->set_manifest_path(manifest_path);
     428          48 :     return ETRC_RET(get_config_folder()->write_config_file());
     429          32 : }
     430             : 
     431           2 : Result CmdInit::fetch_google_manifest()
     432             : {
     433           2 :     Result result;
     434           2 :     ETRC_CALL_RET_NP(result);
     435             : 
     436           2 :     info("Using Google repo tool manifest (--google).");
     437             : 
     438           2 :     auto git_helper = new_git_helper();
     439           2 :     std::string git_repo_path;
     440             : 
     441           2 :     result = clone_manifest_repo(*git_helper, git_repo_path);
     442           2 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     443             : 
     444           2 :     boost::filesystem::path file_path = git_repo_path;
     445           4 :     file_path /= get_google_manifest_filename();
     446             : 
     447           2 :     if (!boost::filesystem::exists(file_path))
     448             :     {
     449           0 :         std::string err_str = "Google repo manifest file not found: " + get_google_manifest_filename();
     450           0 :         error(err_str);
     451           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::FILE_NOT_EXISTING, err_str));
     452           0 :     }
     453             : 
     454           2 :     result = install_google_manifest(*git_helper, git_repo_path);
     455           4 :     return ETRC_RET(ESYSREPO_RESULT(result));
     456           4 : }
     457             : 
     458           0 : Result CmdInit::read_esysrepo_manifest(std::shared_ptr<Manifest> manifest, const std::string &filename)
     459             : {
     460           0 :     Result result;
     461           0 :     ETRC_CALL_RET_NP(result);
     462             : 
     463           0 :     manifest::File manifest_file;
     464             : 
     465           0 :     manifest_file.set_data(manifest);
     466           0 :     manifest_file.set_parse_mode(get_parse_mode());
     467           0 :     result = manifest_file.read(filename);
     468           0 :     if (result.error()) log_manifest_read_error(manifest_file, result);
     469           0 :     return ETRC_RET(ESYSREPO_RESULT(result));
     470           0 : }
     471             : 
     472          14 : Result CmdInit::read_esysrepo_manifest_xml(std::shared_ptr<Manifest> manifest, const std::string &filename)
     473             : {
     474          14 :     Result result;
     475          14 :     ETRC_CALL_RET_NP(result);
     476             : 
     477          14 :     manifest::XMLFile manifest_file;
     478             : 
     479          28 :     manifest_file.set_data(manifest);
     480          14 :     manifest_file.set_parse_mode(get_parse_mode());
     481          14 :     result = manifest_file.read(filename);
     482          14 :     if (result.error()) log_manifest_read_error(manifest_file, result);
     483          42 :     return ETRC_RET(ESYSREPO_RESULT(result));
     484          14 : }
     485             : 
     486           0 : void CmdInit::log_manifest_read_error(manifest::FileBase &file, const Result &result)
     487             : {
     488           0 :     bool printed = false;
     489           0 :     for (auto &err : file.get_errors())
     490             :     {
     491           0 :         if (err == nullptr) continue;
     492           0 :         if (err->get_msg().empty()) continue;
     493           0 :         error(err->get_msg());
     494             :         printed = true;
     495             :     }
     496           0 :     if (printed) return;
     497           0 :     if (result.get_error_info() == nullptr) return;
     498           0 :     if (result.get_error_info()->get_text().empty()) return;
     499           0 :     error(result.get_error_info()->get_text());
     500             : }
     501             : 
     502           0 : Result CmdInit::read_esysrepo_manifest_json(std::shared_ptr<Manifest> manifest, const std::string &filename)
     503             : {
     504             :     //! \TODO
     505           0 :     return ESYSREPO_RESULT(ResultCode::NOT_IMPLEMENTED);
     506             : }
     507             : 
     508           9 : Result CmdInit::fetch_esysrepo_manifest(GitHelper &git_helper, const std::string &git_repo_path,
     509             :                                         const std::string &manifest_filename)
     510             : {
     511           9 :     Result result;
     512           9 :     ETRC_CALL_RET(result, git_repo_path, manifest_filename);
     513             : 
     514           9 :     std::string manifest_path;
     515           9 :     boost::filesystem::path manifest_filename_path = manifest_filename;
     516           9 :     std::string manifest_filename_ext = manifest_filename_path.extension().string();
     517             : 
     518           9 :     info("ESysRepo manifest detected.");
     519           9 :     debug(0, "Manifest filename : " + manifest_filename);
     520             : 
     521           9 :     auto config_file = get_config_folder()->get_or_new_config();
     522             : 
     523           9 :     config_file->set_manifest_type(manifest::Type::ESYSREPO_MANIFEST);
     524           9 :     config_file->set_manifest_url(get_url());
     525           9 :     config_file->set_parse_mode(get_parse_mode());
     526           9 :     if (!get_prefer_branch().empty()) config_file->set_prefer_branch(get_prefer_branch());
     527             : 
     528           9 :     boost::filesystem::path source = git_repo_path;
     529          18 :     boost::filesystem::path rel_source = boost::filesystem::relative(source);
     530           9 :     boost::filesystem::path target;
     531           9 :     boost::filesystem::path file_path = git_repo_path;
     532           9 :     file_path /= manifest_filename;
     533             : 
     534           9 :     std::shared_ptr<Manifest> manifest = std::make_shared<Manifest>();
     535             : 
     536           9 :     if (manifest_filename_ext == ".manifest")
     537             :     {
     538           0 :         result = read_esysrepo_manifest(manifest, file_path.string());
     539           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     540             :     }
     541           9 :     else if (manifest_filename_ext == ".xml")
     542             :     {
     543          18 :         result = read_esysrepo_manifest_xml(manifest, file_path.string());
     544           9 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     545           9 :         manifest->set_format(manifest::Format::XML);
     546           9 :         config_file->set_manifest_format(manifest::Format::XML);
     547             :     }
     548           0 :     else if (manifest_filename_ext == ".json")
     549             :     {
     550           0 :         result = read_esysrepo_manifest_json(manifest, file_path.string());
     551           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     552           0 :         manifest->set_format(manifest::Format::JSON);
     553           0 :         config_file->set_manifest_format(manifest::Format::JSON);
     554             :     }
     555             :     else
     556             :     {
     557           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::MANIFEST_FILE_EXT_UNKNOWN, manifest_filename_ext));
     558             :     }
     559             : 
     560           9 :     config_file->set_manifest_format(manifest->get_format());
     561             : 
     562           9 :     if (manifest->get_kind() == manifest::Kind::NOT_SET) manifest->set_kind(manifest::Kind::ISOLATED);
     563             : 
     564           9 :     if (manifest->get_kind() == manifest::Kind::EMBEDDED)
     565             :     {
     566           1 :         info("Embedded kind.");
     567           1 :         config_file->set_manifest_kind(manifest::Kind::EMBEDDED);
     568           2 :         target = get_config_folder()->get_workspace_path();
     569           1 :         result = git_helper.move(source.string(), target.string(), true, log::Level::DEBUG);
     570           1 :         if (result == ResultCode::FAILED_TO_COPY) return ETRC_RET(ESYSREPO_RESULT(result));
     571           1 :         if (result == ResultCode::FAILED_TO_REMOVE_ALL)
     572           0 :             warn("While moving folder " + rel_source.string() + " some files were left behind.");
     573           1 :         target = "..";
     574           1 :         target /= manifest_filename;
     575           1 :         manifest_path = target.string();
     576             :     }
     577           8 :     else if (manifest->get_kind() == manifest::Kind::ISOLATED)
     578             :     {
     579           8 :         info("Isolated kind.");
     580           8 :         config_file->set_manifest_kind(manifest::Kind::ISOLATED);
     581          16 :         target = get_config_folder()->get_path();
     582             : 
     583           8 :         target /= manifest::Base::get_folder_name();
     584           8 :         boost::filesystem::path rel_target;
     585          16 :         rel_target = boost::filesystem::relative(target);
     586             : 
     587           8 :         bool result_bool = boost::filesystem::create_directory(target);
     588           8 :         if (!result_bool)
     589             :         {
     590           0 :             error("Couldn't create the folder : " + rel_target.string());
     591           0 :             return ETRC_RET(ESYSREPO_RESULT(ResultCode::FOLDER_CREATION_ERROR, target.string()));
     592             :         }
     593             :         else
     594           8 :             debug(0, "Created folder : " + rel_target.string());
     595             : 
     596           8 :         result = git_helper.move(source.string(), target.string(), true, log::Level::DEBUG);
     597           8 :         if (result == ResultCode::FAILED_TO_COPY) return ETRC_RET(ESYSREPO_RESULT(result));
     598           8 :         if (result == ResultCode::FAILED_TO_REMOVE_ALL)
     599           0 :             warn("While moving folder " + rel_source.string() + " some files were left behind.");
     600           8 :         target = manifest::Base::get_folder_name();
     601           8 :         target /= manifest_filename;
     602          24 :         manifest_path = target.generic_path().string();
     603           8 :     }
     604             :     else
     605           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::MANIFEST_KIND_UNKNOWN));
     606             : 
     607           9 :     config_file->set_manifest_path(manifest_path);
     608             : 
     609           9 :     if (!get_rev_set().empty())
     610             :     {
     611           0 :         result = manifest->select_revision_set(get_rev_set());
     612           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     613           0 :         config_file->set_revision_set(get_rev_set());
     614             :     }
     615           9 :     if (!get_prefer_branch().empty()) config_file->set_prefer_branch(get_prefer_branch());
     616             : 
     617           9 :     result = get_config_folder()->write_config_file();
     618          18 :     return ETRC_RET(ESYSREPO_RESULT(result));
     619          18 : }
     620             : 
     621           0 : Result CmdInit::fetch_git_super_project()
     622             : {
     623           0 :     return ESYSREPO_RESULT(ResultCode::NOT_IMPLEMENTED);
     624             : }
     625             : 
     626             : namespace
     627             : {
     628             : 
     629          21 : boost::filesystem::path abs_norm(const boost::filesystem::path &path)
     630             : {
     631          21 :     return boost::filesystem::absolute(path).lexically_normal();
     632             : }
     633             : 
     634           5 : bool paths_same(const boost::filesystem::path &left, const boost::filesystem::path &right)
     635             : {
     636           5 :     boost::system::error_code ec;
     637           5 :     if (boost::filesystem::exists(left) && boost::filesystem::exists(right))
     638             :     {
     639           5 :         bool same = boost::filesystem::equivalent(left, right, ec);
     640           5 :         if (!ec) return same;
     641             :     }
     642           0 :     return abs_norm(left) == abs_norm(right);
     643             : }
     644             : 
     645           5 : std::string rel_generic(const boost::filesystem::path &from_dir, const boost::filesystem::path &target,
     646             :                         const std::string &fallback)
     647             : {
     648           5 :     boost::system::error_code ec;
     649          10 :     auto rel = boost::filesystem::relative(abs_norm(target), abs_norm(from_dir), ec);
     650           5 :     if (ec) return fallback.empty() ? "." : fallback;
     651           5 :     std::string text = rel.generic_string();
     652           5 :     if (text.empty()) return ".";
     653          10 :     return text;
     654           5 : }
     655             : 
     656           2 : bool is_native_manifest_filename(const boost::filesystem::path &file)
     657             : {
     658           2 :     const std::string name = file.filename().string();
     659           4 :     return name == ".esysrepo.manifest" || name == ".esysrepo.manifest.xml" || name == ".esysrepo.manifest.json";
     660           2 : }
     661             : 
     662             : } // namespace
     663             : 
     664           6 : Result CmdInit::fetch_local_manifest()
     665             : {
     666           6 :     Result result;
     667           6 :     ETRC_CALL_RET_NP(result);
     668             : 
     669           6 :     if (!get_branch().empty())
     670             :     {
     671           0 :         std::string err_str = "--manifest-branch / -b cannot be combined with --manifest-local / -l";
     672           0 :         error(err_str);
     673           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_INCORRECT_PARAMETERS_COMBINATION, err_str));
     674           0 :     }
     675             : 
     676           6 :     boost::filesystem::path local_path = abs_norm(get_manifest_local());
     677           6 :     if (!boost::filesystem::exists(local_path))
     678             :     {
     679           1 :         std::string err_str = "Local manifest path does not exist: " + local_path.string();
     680           1 :         error(err_str);
     681           2 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::PATH_NOT_EXISTING, err_str));
     682           1 :     }
     683             : 
     684           5 :     const bool is_file = boost::filesystem::is_regular_file(local_path);
     685           5 :     const bool is_dir = boost::filesystem::is_directory(local_path);
     686           5 :     if (!is_file && !is_dir)
     687             :     {
     688           0 :         std::string err_str = "Local manifest path is not a file or directory: " + local_path.string();
     689           0 :         error(err_str);
     690           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::PATH_NOT_EXISTING, err_str));
     691           0 :     }
     692             : 
     693           5 :     if (is_file && !get_manifest_name().empty())
     694             :     {
     695           0 :         std::string err_str = "--manifest-name / -m cannot be combined with --manifest-local pointing at a file";
     696           0 :         error(err_str);
     697           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_INCORRECT_PARAMETERS_COMBINATION, err_str));
     698           0 :     }
     699             : 
     700           5 :     boost::filesystem::path source_file;
     701           5 :     bool google_manifest = get_google_manifest();
     702           5 :     bool git_super = false;
     703             : 
     704           5 :     if (is_file)
     705             :     {
     706           2 :         source_file = local_path;
     707           2 :         if (!google_manifest) google_manifest = !is_native_manifest_filename(source_file) && source_file.extension() == ".xml";
     708             :     }
     709             :     else
     710             :     {
     711           3 :         if (get_google_manifest() || !get_manifest_name().empty())
     712             :         {
     713           0 :             source_file = local_path / (get_manifest_name().empty() ? get_google_manifest_filename() : get_manifest_name());
     714           0 :             if (!boost::filesystem::exists(source_file))
     715             :             {
     716           0 :                 std::string err_str = "Manifest file not found in folder: " + source_file.string();
     717           0 :                 error(err_str);
     718           0 :                 return ETRC_RET(ESYSREPO_RESULT(ResultCode::FILE_NOT_EXISTING, err_str));
     719           0 :             }
     720           0 :             google_manifest = get_google_manifest() || !is_native_manifest_filename(source_file);
     721             :         }
     722             :         else
     723             :         {
     724           3 :             const char *native_names[] = {".esysrepo.manifest", ".esysrepo.manifest.xml", ".esysrepo.manifest.json"};
     725           6 :             for (const char *name : native_names)
     726             :             {
     727          12 :                 boost::filesystem::path candidate = local_path / name;
     728           6 :                 if (boost::filesystem::exists(candidate))
     729             :                 {
     730           3 :                     source_file = candidate;
     731           3 :                     google_manifest = false;
     732           3 :                     break;
     733             :                 }
     734           6 :             }
     735           3 :             if (source_file.empty())
     736             :             {
     737           0 :                 boost::filesystem::path candidate = local_path / get_google_manifest_filename();
     738           0 :                 if (boost::filesystem::exists(candidate))
     739             :                 {
     740           0 :                     source_file = candidate;
     741             :                     google_manifest = true;
     742             :                 }
     743           0 :             }
     744           3 :             if (source_file.empty())
     745             :             {
     746           0 :                 boost::filesystem::path candidate = local_path / ".gitmodules";
     747           0 :                 if (boost::filesystem::exists(candidate))
     748             :                 {
     749           0 :                     source_file = candidate;
     750             :                     git_super = true;
     751             :                 }
     752           0 :             }
     753           3 :             if (source_file.empty())
     754             :             {
     755           0 :                 std::string err_str = "No manifest found in folder: " + local_path.string();
     756           0 :                 error(err_str);
     757           0 :                 return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMDINIT_NO_LOCAL_MANIFEST, err_str));
     758           0 :             }
     759             :         }
     760             :     }
     761             : 
     762           5 :     info("Using local manifest (no clone).");
     763           5 :     debug(0, "Local source : " + local_path.string());
     764           5 :     debug(0, "Manifest file : " + source_file.string());
     765             : 
     766           5 :     auto config = get_config_folder()->get_or_new_config();
     767           5 :     config->set_parse_mode(get_parse_mode());
     768           5 :     if (!get_prefer_branch().empty()) config->set_prefer_branch(get_prefer_branch());
     769          10 :     config->set_manifest_local(rel_generic(get_workspace_path(), local_path, get_manifest_local()));
     770             :     // No git remote for -l
     771           5 :     config->set_manifest_url("");
     772             : 
     773           5 :     boost::filesystem::path workspace = abs_norm(get_workspace_path());
     774           5 :     boost::filesystem::path source_dir = is_file ? local_path.parent_path() : local_path;
     775           5 :     const bool source_is_workspace = paths_same(source_dir, workspace);
     776             : 
     777           5 :     if (git_super)
     778             :     {
     779           0 :         info("Git submodule detected.");
     780           0 :         config->set_manifest_type(manifest::Type::GIT_SUPER_PROJECT);
     781           0 :         result = get_config_folder()->write_config_file();
     782           0 :         return ETRC_RET(ESYSREPO_RESULT(result));
     783             :     }
     784             : 
     785           5 :     if (google_manifest)
     786             :     {
     787           0 :         info("Google repo tool manifest detected.");
     788           0 :         config->set_manifest_type(manifest::Type::GOOGLE_MANIFEST);
     789           0 :         config->set_manifest_format(manifest::Format::XML);
     790           0 :         config->set_manifest_kind(manifest::Kind::ISOLATED);
     791             : 
     792           0 :         boost::filesystem::path dest_dir = get_config_folder()->get_path();
     793           0 :         dest_dir /= grepo::Manifest::get_folder_name();
     794           0 :         boost::system::error_code ec;
     795           0 :         boost::filesystem::create_directories(dest_dir, ec);
     796           0 :         if (ec)
     797             :         {
     798           0 :             error("Couldn't create the folder : " + dest_dir.string());
     799           0 :             return ETRC_RET(ESYSREPO_RESULT(ResultCode::FOLDER_CREATION_ERROR, dest_dir.string()));
     800             :         }
     801           0 :         boost::filesystem::path dest_file = dest_dir / source_file.filename();
     802           0 :         boost::filesystem::copy_file(source_file, dest_file, boost::filesystem::copy_options::overwrite_existing, ec);
     803           0 :         if (ec)
     804             :         {
     805           0 :             error("Couldn't copy the manifest file : " + source_file.string());
     806           0 :             return ETRC_RET(ESYSREPO_RESULT(ResultCode::FAILED_TO_COPY, source_file.string()));
     807             :         }
     808           0 :         config->set_manifest_path((boost::filesystem::path(grepo::Manifest::get_folder_name()) / source_file.filename())
     809             :                                       .generic_string());
     810           0 :         result = get_config_folder()->write_config_file();
     811           0 :         return ETRC_RET(ESYSREPO_RESULT(result));
     812           0 :     }
     813             : 
     814           5 :     info("ESysRepo manifest detected.");
     815           5 :     config->set_manifest_type(manifest::Type::ESYSREPO_MANIFEST);
     816             : 
     817           5 :     auto manifest = std::make_shared<Manifest>();
     818           5 :     std::string ext = source_file.extension().string();
     819          20 :     if (ext == ".manifest" || source_file.filename() == ".esysrepo.manifest")
     820             :     {
     821           0 :         result = read_esysrepo_manifest(manifest, source_file.string());
     822           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     823             :     }
     824           5 :     else if (ext == ".xml")
     825             :     {
     826          10 :         result = read_esysrepo_manifest_xml(manifest, source_file.string());
     827           5 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     828           5 :         manifest->set_format(manifest::Format::XML);
     829             :     }
     830           0 :     else if (ext == ".json")
     831             :     {
     832           0 :         result = read_esysrepo_manifest_json(manifest, source_file.string());
     833           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     834           0 :         manifest->set_format(manifest::Format::JSON);
     835             :     }
     836             :     else
     837             :     {
     838           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::MANIFEST_FILE_EXT_UNKNOWN, ext));
     839             :     }
     840             : 
     841           5 :     if (manifest->get_kind() == manifest::Kind::NOT_SET) manifest->set_kind(manifest::Kind::ISOLATED);
     842           5 :     config->set_manifest_format(manifest->get_format());
     843             : 
     844           5 :     const bool leave_in_place = (manifest->get_kind() == manifest::Kind::EMBEDDED) && source_is_workspace;
     845           5 :     if (leave_in_place)
     846             :     {
     847           3 :         info("Embedded kind.");
     848           3 :         config->set_manifest_kind(manifest::Kind::EMBEDDED);
     849           3 :         boost::filesystem::path stored = "..";
     850           6 :         stored /= source_file.filename();
     851           3 :         config->set_manifest_path(stored.generic_string());
     852           3 :     }
     853             :     else
     854             :     {
     855           4 :         info(manifest->get_kind() == manifest::Kind::EMBEDDED ? "Embedded kind (source outside workspace, copying)."
     856             :                                                              : "Isolated kind.");
     857           2 :         config->set_manifest_kind(manifest::Kind::ISOLATED);
     858           2 :         boost::filesystem::path dest_dir = get_config_folder()->get_path();
     859           2 :         dest_dir /= manifest::Base::get_folder_name();
     860           2 :         boost::system::error_code ec;
     861           2 :         boost::filesystem::create_directories(dest_dir, ec);
     862           2 :         if (ec)
     863             :         {
     864           0 :             error("Couldn't create the folder : " + dest_dir.string());
     865           0 :             return ETRC_RET(ESYSREPO_RESULT(ResultCode::FOLDER_CREATION_ERROR, dest_dir.string()));
     866             :         }
     867           4 :         boost::filesystem::path dest_file = dest_dir / source_file.filename();
     868           2 :         boost::filesystem::copy_file(source_file, dest_file, boost::filesystem::copy_options::overwrite_existing, ec);
     869           2 :         if (ec)
     870             :         {
     871           0 :             error("Couldn't copy the manifest file : " + source_file.string());
     872           0 :             return ETRC_RET(ESYSREPO_RESULT(ResultCode::FAILED_TO_COPY, source_file.string()));
     873             :         }
     874           4 :         config->set_manifest_path(
     875           6 :             (boost::filesystem::path(manifest::Base::get_folder_name()) / source_file.filename()).generic_string());
     876           2 :     }
     877             : 
     878           5 :     if (!get_rev_set().empty())
     879             :     {
     880           0 :         result = manifest->select_revision_set(get_rev_set());
     881           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     882           0 :         config->set_revision_set(get_rev_set());
     883             :     }
     884           5 :     if (!get_prefer_branch().empty()) config->set_prefer_branch(get_prefer_branch());
     885             : 
     886           5 :     result = get_config_folder()->write_config_file();
     887          10 :     return ETRC_RET(ESYSREPO_RESULT(result));
     888          27 : }
     889             : 
     890          23 : Result CmdInit::fetch_unknown_manifest()
     891             : {
     892          23 :     Result result;
     893          23 :     ETRC_CALL_RET_NP(result);
     894             : 
     895          23 :     info("Detecting the manifest type ...");
     896             : 
     897          23 :     auto git_helper = new_git_helper();
     898          23 :     std::string git_repo_path;
     899             : 
     900          23 :     result = clone_manifest_repo(*git_helper, git_repo_path);
     901          23 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     902             : 
     903          23 :     boost::filesystem::path path = git_repo_path;
     904          23 :     boost::filesystem::path file_path = path;
     905          23 :     file_path /= ".esysrepo.manifest";
     906             : 
     907          23 :     if (boost::filesystem::exists(file_path))
     908             :     {
     909           0 :         result = fetch_esysrepo_manifest(*git_helper.get(), path.string(), ".esysrepo.manifest");
     910           0 :         return ETRC_RET(ESYSREPO_RESULT(result));
     911             :     }
     912             : 
     913          23 :     file_path = path;
     914          23 :     file_path /= ".esysrepo.manifest.xml";
     915             : 
     916          23 :     if (boost::filesystem::exists(file_path))
     917             :     {
     918           9 :         result = fetch_esysrepo_manifest(*git_helper.get(), path.string(), ".esysrepo.manifest.xml");
     919          18 :         return ETRC_RET(ESYSREPO_RESULT(result));
     920             :     }
     921             : 
     922          14 :     file_path = path;
     923          14 :     file_path /= ".esysrepo.manifest.json";
     924             : 
     925          14 :     if (boost::filesystem::exists(file_path))
     926             :     {
     927           0 :         result = fetch_esysrepo_manifest(*git_helper.get(), path.string(), ".esysrepo.manifest.json");
     928           0 :         return ETRC_RET(ESYSREPO_RESULT(result));
     929             :     }
     930             : 
     931          14 :     file_path = path;
     932          28 :     file_path /= get_google_manifest_filename();
     933             : 
     934          14 :     if (boost::filesystem::exists(file_path))
     935             :     {
     936          14 :         info("Google repo tool manifest detected.");
     937          14 :         result = install_google_manifest(*git_helper, git_repo_path);
     938          28 :         return ETRC_RET(ESYSREPO_RESULT(result));
     939             :     }
     940             : 
     941           0 :     file_path = path;
     942           0 :     file_path /= ".gitmodules";
     943             : 
     944           0 :     if (boost::filesystem::exists(file_path))
     945             :     {
     946           0 :         info("Git submodule detected.");
     947           0 :         auto config = get_config_folder()->get_or_new_config();
     948             : 
     949           0 :         config->set_manifest_type(manifest::Type::GIT_SUPER_PROJECT);
     950           0 :         config->set_manifest_url(get_url());
     951           0 :         if (!get_prefer_branch().empty()) config->set_prefer_branch(get_prefer_branch());
     952           0 :         boost::filesystem::path source = path.string();
     953           0 :         boost::filesystem::path target = get_config_folder()->get_workspace_path();
     954             : 
     955           0 :         result = git_helper->move(source.string(), target.string(), true, log::Level::DEBUG);
     956           0 :         if (result == ResultCode::FAILED_TO_COPY) return ETRC_RET(ESYSREPO_RESULT(result));
     957           0 :         if (result == ResultCode::FAILED_TO_REMOVE_ALL)
     958           0 :             warn("While moving folder " + source.string() + " some files were left behind.");
     959           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     960           0 :     }
     961             : 
     962           0 :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMDINIT_FAILED_FETCH_UNKNOWN_MANIFEST));
     963          69 : }
     964             : 
     965          32 : Result CmdInit::load_esysrepo_folder()
     966             : {
     967          32 :     Result result;
     968          32 :     ETRC_CALL_RET_NP(result);
     969             : 
     970          32 :     auto config_folder = std::make_shared<ConfigFolder>();
     971          32 :     config_folder->set_logger_if(get_logger_if());
     972             : 
     973          64 :     set_config_folder(config_folder);
     974             : 
     975          32 :     ETRC_MSG("parent_path = " + get_workspace_path());
     976             : 
     977          32 :     result = config_folder->open(get_workspace_path(), false);
     978          96 :     return ETRC_RET(ESYSREPO_RESULT(result));
     979          32 : }
     980             : 
     981          31 : Result CmdInit::create_esysrepo_folder()
     982             : {
     983          31 :     Result result;
     984          31 :     ETRC_CALL_RET_NP(result);
     985             : 
     986          31 :     auto config_folder = get_config_folder();
     987          31 :     if (config_folder == nullptr)
     988             :     {
     989           0 :         config_folder = std::make_shared<ConfigFolder>();
     990           0 :         config_folder->set_logger_if(get_logger_if());
     991             : 
     992           0 :         set_config_folder(config_folder);
     993             :     }
     994             : 
     995          31 :     ETRC_MSG("parent_path = " + get_workspace_path());
     996             : 
     997          31 :     result = config_folder->create(get_workspace_path(), true);
     998          93 :     return ESYSREPO_RESULT(result);
     999          31 : }
    1000             : 
    1001           1 : Result CmdInit::find_url_from_project_name()
    1002             : {
    1003           1 :     Result result;
    1004           1 :     ETRC_CALL_RET_NP(result);
    1005             : 
    1006           1 :     manifest::DirectoryMngr mngr;
    1007             : 
    1008           1 :     boost::filesystem::path path = get_config_folder()->get_temp_path();
    1009           1 :     path /= "manifest_directories";
    1010           1 :     mngr.set_folder_path(path.string());
    1011             : 
    1012           1 :     if (get_directories() == nullptr)
    1013             :     {
    1014           1 :         auto directories = std::make_shared<manifest::Directories>();
    1015           1 :         directories->add_default_libesys();
    1016             : 
    1017           2 :         mngr.set_directories(directories);
    1018           3 :         set_directories(directories);
    1019           1 :     }
    1020             : 
    1021           1 :     result = mngr.load();
    1022           1 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
    1023             : 
    1024           1 :     auto project = get_directories()->find_project(get_project_name());
    1025           1 :     if (project == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::GENERIC_ERROR));
    1026             : 
    1027           1 :     set_url(project->get_url_ssh());
    1028           2 :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
    1029           1 : }
    1030             : 
    1031           1 : void CmdInit::set_directories(std::shared_ptr<manifest::Directories> directories)
    1032             : {
    1033           1 :     m_directories = directories;
    1034           1 : }
    1035             : 
    1036           2 : std::shared_ptr<manifest::Directories> CmdInit::get_directories() const
    1037             : {
    1038           2 :     return m_directories;
    1039             : }
    1040             : 
    1041             : } // namespace esys::repo::exe

Generated by: LCOV version 1.14