LCOV - code coverage report
Current view: top level - src/esys/repo/cli - cmdmanifest_cli.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 59 90 65.6 %
Date: 2026-11-07 22:18:26 Functions: 4 6 66.7 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/cli/cmdmanifest_cli.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/cli/cmdmanifest.h"
      20             : #include "esys/repo/manifest/merge.h"
      21             : #include "esys/repo/manifest/parsemode.h"
      22             : 
      23             : #include <esys/md/rend/styled_string.h>
      24             : 
      25             : #include <termcolor/termcolor.hpp>
      26             : 
      27             : #include <boost/filesystem.hpp>
      28             : 
      29             : #include <vector>
      30             : 
      31             : namespace esys::repo::cli
      32             : {
      33             : 
      34             : #include "esys/repo/cli/cmdmanifest_doc.cpp"
      35             : 
      36          17 : CmdManifest::CmdManifest(AppBase *app)
      37          34 :     : BaseType(app, "manifest", "Manifest tools")
      38             : {
      39          17 : }
      40             : 
      41          17 : CmdManifest::~CmdManifest() = default;
      42             : 
      43           3 : std::shared_ptr<po::options_description> CmdManifest::get_desc()
      44             : {
      45           3 :     auto desc = Cmd::get_desc();
      46           3 :     if (desc != nullptr) return desc;
      47             : 
      48           3 :     desc = std::make_shared<po::options_description>("Manifest options");
      49             :     // clang-format off
      50           3 :     desc->add_options()
      51           3 :         ("help,h", "produce help message")
      52           3 :         ("revision-as-HEAD,r", "Save revisions as current HEAD")
      53           3 :         ("output-file,o", po::value<std::string>(), "File to save the manifest to")
      54           3 :         ("list-dirs,l", "List all manifest directories")
      55           3 :         ("list-projects,p", po::value<std::string>()->implicit_value(""),
      56             :             "List all projects from one or all manifest directories")
      57           3 :         ("add-dir,a", po::value<std::string>(), "Add a manifest directory <name> <ssh> <https>")
      58           3 :         ("del-dir,d", po::value<std::string>(), "Delete a manifest directory <name>")
      59           3 :         ("format", po::value<std::string>(), "merge output format: native (default) or google")
      60           3 :         ("on-conflict", po::value<std::string>(), "merge collision policy: fail (default), prefer-first, prefer-last")
      61           3 :         ("strict", po::value<bool>()->default_value(false)->implicit_value(true),
      62             :          "fail on unknown manifest XML when merging")
      63             :         ;
      64             :     // clang-format on
      65           6 :     Cmd::set_desc(desc);
      66           3 :     return desc;
      67           0 : }
      68             : 
      69           8 : int CmdManifest::configure_cmd(CmdType &cmd)
      70             : {
      71           8 :     const auto sub = get_sub_args();
      72           8 :     const bool is_merge = !sub.empty() && sub[0] == "merge";
      73          24 :     const bool other_task = get_vm().count("revision-as-HEAD") || get_vm().count("list-dirs")
      74          37 :         || get_vm().count("list-projects") || get_vm().count("add-dir") || get_vm().count("del-dir");
      75             : 
      76           8 :     if (is_merge && other_task)
      77             :     {
      78           1 :         error("manifest merge cannot be combined with -r, --list-dirs, --list-projects, --add-dir, or --del-dir");
      79           1 :         return -1;
      80             :     }
      81             : 
      82           7 :     if (is_merge)
      83             :     {
      84           2 :         if (sub.size() < 3)
      85             :         {
      86           1 :             error("manifest merge requires at least two input files");
      87           1 :             return -1;
      88             :         }
      89           1 :         cmd.set_task(CmdType::Task::MERGE);
      90           1 :         std::vector<std::string> inputs(sub.begin() + 1, sub.end());
      91           1 :         cmd.set_merge_inputs(inputs);
      92           2 :         if (get_vm().count("format"))
      93             :         {
      94           2 :             const auto fmt = get_vm()["format"].as<std::string>();
      95           1 :             if (fmt == "native")
      96           1 :                 cmd.set_merge_format(esys::repo::manifest::Merge::OutputFormat::Native);
      97           0 :             else if (fmt == "google")
      98           0 :                 cmd.set_merge_format(esys::repo::manifest::Merge::OutputFormat::Google);
      99             :             else
     100             :             {
     101           0 :                 error("--format must be native or google");
     102           0 :                 return -1;
     103             :             }
     104           1 :         }
     105           2 :         if (get_vm().count("on-conflict"))
     106             :         {
     107           2 :             const auto pol = get_vm()["on-conflict"].as<std::string>();
     108           1 :             if (pol == "fail")
     109           0 :                 cmd.set_on_conflict(esys::repo::manifest::Merge::OnConflict::Fail);
     110           1 :             else if (pol == "prefer-first")
     111           0 :                 cmd.set_on_conflict(esys::repo::manifest::Merge::OnConflict::PreferFirst);
     112           1 :             else if (pol == "prefer-last")
     113           1 :                 cmd.set_on_conflict(esys::repo::manifest::Merge::OnConflict::PreferLast);
     114             :             else
     115             :             {
     116           0 :                 error("--on-conflict must be fail, prefer-first, or prefer-last");
     117           0 :                 return -1;
     118             :             }
     119           1 :         }
     120           2 :         if (get_vm()["strict"].as<bool>()) cmd.set_merge_parse_mode(esys::repo::manifest::ParseMode::Strict);
     121           4 :         if (get_vm().count("output-file")) cmd.set_output_file(get_vm()["output-file"].as<std::string>());
     122           1 :         return 0;
     123           1 :     }
     124             : 
     125          10 :     if (get_vm().count("revision-as-HEAD"))
     126           0 :         cmd.set_task(CmdType::Task::REVISION_AS_HEAD);
     127          10 :     else if (get_vm().count("list-dirs"))
     128           0 :         cmd.set_task(CmdType::Task::LIST_DIRS);
     129          10 :     else if (get_vm().count("list-projects"))
     130             :     {
     131           0 :         cmd.set_task(CmdType::Task::LIST_PROJECTS);
     132           0 :         cmd.set_dirs(get_vm()["list-projects"].as<std::string>());
     133             :     }
     134          10 :     else if (get_vm().count("add-dir"))
     135             :     {
     136           0 :         CmdType::TaskAddDir add_dir;
     137             : 
     138           0 :         add_dir.set_name(get_vm()["add-dir"].as<std::string>());
     139             : 
     140           0 :         for (auto const &url : get_sub_args())
     141             :         {
     142           0 :             if (url.find("ssh://") != std::string::npos)
     143           0 :                 add_dir.set_url_ssh(url);
     144           0 :             else if (url.find("https://") != std::string::npos)
     145           0 :                 add_dir.set_url_https(url);
     146             :             else
     147           0 :                 error("url not known protocol for '" + url + "'");
     148           0 :         }
     149             : 
     150           0 :         cmd.set_task_add_dir(add_dir);
     151           0 :     }
     152          10 :     else if (get_vm().count("del-dir"))
     153             :     {
     154           0 :         CmdType::TaskDelDir del_dir;
     155             : 
     156           0 :         del_dir.set_name(get_vm()["del-dir"].as<std::string>());
     157             : 
     158           0 :         cmd.set_task_del_dir(del_dir);
     159           0 :     }
     160          10 :     if (get_vm().count("output-file")) cmd.set_output_file(get_vm()["output-file"].as<std::string>());
     161             : 
     162             :     return 0;
     163           8 : }
     164             : 
     165           0 : int CmdManifest::print_doc(std::ostream &os)
     166             : {
     167           0 :     os << cmdmanifest_doc_strings;
     168           0 :     return 0;
     169             : }
     170             : 
     171             : } // namespace esys::repo::cli

Generated by: LCOV version 1.14