LCOV - code coverage report
Current view: top level - src/esys/repo/exe - cmdmanifest.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 71 195 36.4 %
Date: 2026-08-01 10:43:40 Functions: 12 29 41.4 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/exe/cmdmanifest.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 2020-2021 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/cmdmanifest.h"
      20             : #include "esys/repo/manifest/file.h"
      21             : #include "esys/repo/grepo/manifest.h"
      22             : #include "esys/repo/manifest/directorymngr.h"
      23             : #include "esys/repo/manifest/repository.h"
      24             : #include "esys/repo/manifest/xmlfile.h"
      25             : #include "esys/repo/githelper.h"
      26             : #include "esys/repo/userfolder.h"
      27             : 
      28             : #include <esys/trace/call.h>
      29             : #include <esys/trace/macros.h>
      30             : 
      31             : #include <boost/filesystem.hpp>
      32             : 
      33             : #include <iostream>
      34             : #include <fstream>
      35             : #include <sstream>
      36             : 
      37             : namespace esys::repo::exe
      38             : {
      39             : 
      40          56 : CmdManifest::TaskDelDir::TaskDelDir() = default;
      41             : 
      42           0 : void CmdManifest::TaskDelDir::set_name(const std::string &name)
      43             : {
      44           0 :     m_name = name;
      45           0 : }
      46             : 
      47           0 : const std::string &CmdManifest::TaskDelDir::get_name() const
      48             : {
      49           0 :     return m_name;
      50             : }
      51             : 
      52          28 : CmdManifest::TaskAddDir::TaskAddDir() = default;
      53             : 
      54           0 : void CmdManifest::TaskAddDir::set_url_ssh(const std::string &url_ssh)
      55             : {
      56           0 :     m_url_ssh = url_ssh;
      57           0 : }
      58             : 
      59           0 : const std::string &CmdManifest::TaskAddDir::get_url_ssh() const
      60             : {
      61           0 :     return m_url_ssh;
      62             : }
      63             : 
      64           0 : void CmdManifest::TaskAddDir::set_url_https(const std::string &url_https)
      65             : {
      66           0 :     m_url_https = url_https;
      67           0 : }
      68             : 
      69           0 : const std::string &CmdManifest::TaskAddDir::get_url_https() const
      70             : {
      71           0 :     return m_url_https;
      72             : }
      73             : 
      74          28 : CmdManifest::CmdManifest()
      75          56 :     : Cmd("Manifest")
      76             : {
      77          28 : }
      78             : 
      79          28 : CmdManifest::~CmdManifest() = default;
      80             : 
      81           1 : void CmdManifest::set_task(Task task)
      82             : {
      83           1 :     m_task = task;
      84           1 : }
      85             : 
      86           3 : CmdManifest::Task CmdManifest::get_task() const
      87             : {
      88           3 :     return m_task;
      89             : }
      90             : 
      91           0 : void CmdManifest::set_task_add_dir(const TaskAddDir &task_add_dir)
      92             : {
      93           0 :     m_task_add_dir = task_add_dir;
      94           0 :     set_task(Task::ADD_DIR);
      95           0 : }
      96             : 
      97           0 : const CmdManifest::TaskAddDir &CmdManifest::get_task_add_dir() const
      98             : {
      99           0 :     return m_task_add_dir;
     100             : }
     101             : 
     102           0 : void CmdManifest::set_task_del_dir(const TaskDelDir &task_del_dir)
     103             : {
     104           0 :     m_task_del_dir = task_del_dir;
     105           0 :     set_task(Task::DEL_DIR);
     106           0 : }
     107             : 
     108           0 : const CmdManifest::TaskDelDir &CmdManifest::get_task_del_dir() const
     109             : {
     110           0 :     return m_task_del_dir;
     111             : }
     112             : 
     113           0 : void CmdManifest::set_dirs(const std::string &dirs)
     114             : {
     115           0 :     m_dirs = dirs;
     116           0 : }
     117             : 
     118           0 : const std::string &CmdManifest::get_dirs() const
     119             : {
     120           0 :     return m_dirs;
     121             : }
     122             : 
     123           1 : void CmdManifest::set_output_file(const std::string &output_file)
     124             : {
     125           1 :     m_output_file = output_file;
     126           1 : }
     127             : 
     128           4 : const std::string &CmdManifest::get_output_file() const
     129             : {
     130           4 :     return m_output_file;
     131             : }
     132             : 
     133           3 : Result CmdManifest::update_revision_as_head()
     134             : {
     135          11 :     for (auto location : get_manifest()->get_locations())
     136             :     {
     137          31 :         for (auto repo : location->get_repos())
     138             :         {
     139          52 :             Result result = update_revision_as_head(repo);
     140          26 :             if (result.error()) return ESYSREPO_RESULT(result);
     141          52 :         }
     142           5 :     }
     143           3 :     return ESYSREPO_RESULT(ResultCode::OK);
     144             : }
     145             : 
     146          26 : Result CmdManifest::update_revision_as_head(std::shared_ptr<manifest::Repository> repo)
     147             : {
     148          26 :     auto git_helper = new_git_helper();
     149             : 
     150          26 :     boost::filesystem::path repo_path = get_config_folder()->get_workspace_path();
     151          26 :     repo_path /= repo->get_path();
     152          78 :     repo_path = boost::filesystem::absolute(repo_path).lexically_normal().make_preferred();
     153             : 
     154          26 :     std::string revision = repo->get_revision();
     155          64 :     if (revision.empty()) revision = get_manifest()->get_default_revision();
     156             : 
     157          26 :     Result rresult = git_helper->open(repo_path.string(), log::Level::DEBUG);
     158          26 :     if (rresult.error()) return ESYSREPO_RESULT(rresult);
     159             : 
     160          26 :     rresult = git_helper->fetch(log::Level::DEBUG);
     161          26 :     if (rresult.error()) return ESYSREPO_RESULT(rresult);
     162             : 
     163          26 :     std::string hash;
     164          26 :     rresult = git_helper->get_hash(revision, hash, log::Level::DEBUG);
     165          26 :     if (rresult.error())
     166             :     {
     167           0 :         git_helper->close_on_error(log::Level::DEBUG);
     168           0 :         return ESYSREPO_RESULT(rresult);
     169             :     }
     170          26 :     repo->set_revision(hash);
     171             : 
     172          26 :     return git_helper->close(log::Level::DEBUG);
     173          52 : }
     174             : 
     175           3 : Result CmdManifest::do_revision_as_head()
     176             : {
     177           3 :     Result result = only_one_folder_or_workspace();
     178           3 :     if (result.error()) return ESYSREPO_RESULT(result);
     179             : 
     180           3 :     result = open_esysrepo_folder();
     181           3 :     if (result.error()) return ESYSREPO_RESULT(result);
     182             : 
     183           3 :     result = load_manifest();
     184           3 :     if (result.error()) return ESYSREPO_RESULT(result);
     185             : 
     186           3 :     result = update_revision_as_head();
     187           3 :     if (result.error())
     188             :     {
     189           0 :         std::string err_str = "Failed to get the revision as HEAD";
     190           0 :         error(err_str);
     191           0 :         return ESYSREPO_RESULT(result, err_str);
     192           0 :     }
     193             : 
     194           3 :     std::shared_ptr<std::ofstream> fos;
     195           3 :     std::ostream *os = nullptr;
     196             : 
     197           3 :     if (get_output_file().empty())
     198             :         os = &std::cout;
     199             :     else
     200             :     {
     201           1 :         fos = std::make_shared<std::ofstream>(get_output_file());
     202           1 :         os = fos.get();
     203             :     }
     204             : 
     205           3 :     std::shared_ptr<manifest::FileBase> file;
     206             : 
     207           6 :     switch (get_manifest()->get_type())
     208             :     {
     209           2 :         case manifest::Type::GOOGLE_MANIFEST: file = std::make_shared<grepo::Manifest>(); break;
     210           4 :         case manifest::Type::ESYSREPO_MANIFEST: file = std::make_shared<manifest::XMLFile>(); break;
     211           0 :         default: error("Manifest format not supported."); return generic_error(-1);
     212             :     }
     213             : 
     214           3 :     file->set_data(get_manifest());
     215           3 :     result = file->write(*os);
     216             : 
     217           3 :     if (fos != nullptr) fos->close();
     218           6 :     return ESYSREPO_RESULT(result);
     219           6 : }
     220             : 
     221           0 : Result CmdManifest::do_list_dirs()
     222             : {
     223           0 :     UserFolder user_folder;
     224             : 
     225           0 :     auto result = user_folder.read();
     226           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     227             : 
     228           0 :     if (user_folder.get_user_config() == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     229             : 
     230           0 :     auto mds = user_folder.get_user_config()->get_manifest_directories();
     231           0 :     if (mds == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     232             : 
     233           0 :     std::ostringstream oss;
     234             : 
     235           0 :     for (auto idx = 0; idx < mds->get_items().size(); ++idx)
     236             :     {
     237           0 :         auto md = mds->get_items()[idx];
     238           0 :         oss.str("");
     239             : 
     240           0 :         oss << "[" << idx << "] " << md->get_name() << std::endl;
     241           0 :         oss << "    " << md->get_url_ssh() << std::endl;
     242           0 :         oss << "    " << md->get_url_https();
     243             : 
     244           0 :         info(oss.str());
     245           0 :     }
     246           0 :     return ESYSREPO_RESULT(ResultCode::OK);
     247           0 : }
     248             : 
     249           0 : Result CmdManifest::do_list_projects()
     250             : {
     251           0 :     UserFolder user_folder;
     252             : 
     253           0 :     auto result = user_folder.read();
     254           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     255             : 
     256           0 :     if (user_folder.get_user_config() == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     257             : 
     258           0 :     auto mds = user_folder.get_user_config()->get_manifest_directories();
     259           0 :     if (mds == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     260             : 
     261           0 :     manifest::DirectoryMngr mngr;
     262             : 
     263           0 :     mngr.set_folder_path(user_folder.get_user_config()->get_manifest_directories_path());
     264           0 :     mngr.set_directories(mds);
     265             : 
     266           0 :     result = mngr.load();
     267           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     268             : 
     269           0 :     std::ostringstream oss;
     270             : 
     271           0 :     for (auto idx = 0; idx < mds->get_items().size(); ++idx)
     272             :     {
     273           0 :         auto md = mds->get_items()[idx];
     274           0 :         oss.str("");
     275             : 
     276           0 :         oss << "[" << idx << "] " << md->get_name() << std::endl;
     277           0 :         oss << "    urls:" << std::endl;
     278           0 :         oss << "        " << md->get_url_ssh() << std::endl;
     279           0 :         oss << "        " << md->get_url_https();
     280             : 
     281           0 :         if (md->get_directory() == nullptr)
     282             :         {
     283           0 :             warn("Manifest directory has no projects.");
     284           0 :             continue;
     285             :         }
     286           0 :         oss << std::endl << "    projects:";
     287           0 :         for (auto dir : md->get_directory()->get_items())
     288             :         {
     289           0 :             oss << std::endl << "        " << dir->get_name();
     290             :             // oss << "            " << dir
     291           0 :         }
     292             : 
     293           0 :         info(oss.str());
     294           0 :     }
     295           0 :     return ESYSREPO_RESULT(ResultCode::OK);
     296           0 : }
     297             : 
     298           0 : Result CmdManifest::do_add_dir()
     299             : {
     300           0 :     UserFolder user_folder;
     301             : 
     302           0 :     auto result = user_folder.read();
     303           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     304             : 
     305           0 :     if (user_folder.get_user_config() == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     306             : 
     307           0 :     auto mds = user_folder.get_user_config()->get_manifest_directories();
     308           0 :     if (mds == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     309             : 
     310           0 :     auto item = std::make_shared<manifest::Directories::Item>();
     311           0 :     item->set_name(get_task_add_dir().get_name());
     312           0 :     item->set_url_ssh(get_task_add_dir().get_url_ssh());
     313           0 :     item->set_url_https(get_task_add_dir().get_url_https());
     314             : 
     315           0 :     mds->add_item(item->get_name(), item);
     316             : 
     317           0 :     result = user_folder.write();
     318           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     319             : 
     320           0 :     info("Added manifest directory '" + get_task_del_dir().get_name() + "'.");
     321           0 :     return ESYSREPO_RESULT(ResultCode::OK);
     322           0 : }
     323             : 
     324           0 : Result CmdManifest::do_del_dir()
     325             : {
     326           0 :     UserFolder user_folder;
     327             : 
     328           0 :     auto result = user_folder.read();
     329           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     330             : 
     331           0 :     if (user_folder.get_user_config() == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     332             : 
     333           0 :     auto mds = user_folder.get_user_config()->get_manifest_directories();
     334           0 :     if (mds == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     335             : 
     336           0 :     result = mds->del_item(get_task_del_dir().get_name());
     337           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     338             : 
     339           0 :     result = user_folder.write();
     340           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     341             : 
     342           0 :     info("Deleted manifest directory '" + get_task_del_dir().get_name() + "'.");
     343           0 :     return ESYSREPO_RESULT(ResultCode::OK);
     344           0 : }
     345             : 
     346           3 : Result CmdManifest::impl_run()
     347             : {
     348           3 :     Result result;
     349           3 :     ETRC_CALL_RET_NP(result);
     350             : 
     351           3 :     switch (get_task())
     352             :     {
     353           3 :         case Task::REVISION_AS_HEAD:
     354           6 :         case Task::NOT_SET: return ETRC_RET(do_revision_as_head());
     355           0 :         case Task::LIST_DIRS: return ETRC_RET(do_list_dirs());
     356           0 :         case Task::LIST_PROJECTS: return ETRC_RET(do_list_projects());
     357           0 :         case Task::ADD_DIR: return ETRC_RET(do_add_dir());
     358           0 :         case Task::DEL_DIR: return ETRC_RET(do_del_dir());
     359           0 :         default: return ETRC_RET(ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR));
     360             :     }
     361             :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     362           3 : }
     363             : 
     364             : } // namespace esys::repo::exe

Generated by: LCOV version 1.14