LCOV - code coverage report
Current view: top level - src/esys/repo/exe - cmdpin.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 34 173 19.7 %
Date: 2026-08-12 14:26:50 Functions: 14 23 60.9 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/exe/cmdpin.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 2026 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/cmdpin.h"
      20             : #include "esys/repo/cienv.h"
      21             : #include "esys/repo/revisionpins.h"
      22             : 
      23             : #include <iostream>
      24             : #include <sstream>
      25             : 
      26             : namespace esys::repo::exe
      27             : {
      28             : 
      29          20 : CmdPin::CmdPin()
      30          40 :     : Cmd("Pin")
      31             : {
      32          20 : }
      33             : 
      34          20 : CmdPin::~CmdPin() = default;
      35             : 
      36           1 : void CmdPin::set_name(const std::string &name)
      37             : {
      38           1 :     m_name = name;
      39           1 : }
      40             : 
      41           1 : const std::string &CmdPin::get_name() const
      42             : {
      43           1 :     return m_name;
      44             : }
      45             : 
      46           1 : void CmdPin::set_project(const std::string &project)
      47             : {
      48           1 :     m_project = project;
      49           1 : }
      50             : 
      51           1 : const std::string &CmdPin::get_project() const
      52             : {
      53           1 :     return m_project;
      54             : }
      55             : 
      56           0 : void CmdPin::set_url(const std::string &url)
      57             : {
      58           0 :     m_url = url;
      59           0 : }
      60             : 
      61           0 : const std::string &CmdPin::get_url() const
      62             : {
      63           0 :     return m_url;
      64             : }
      65             : 
      66           1 : void CmdPin::set_rev(const std::string &rev)
      67             : {
      68           1 :     m_rev = rev;
      69           1 : }
      70             : 
      71           1 : const std::string &CmdPin::get_rev() const
      72             : {
      73           1 :     return m_rev;
      74             : }
      75             : 
      76           1 : void CmdPin::set_ci(bool ci)
      77             : {
      78           1 :     m_ci = ci;
      79           1 : }
      80             : 
      81           1 : bool CmdPin::get_ci() const
      82             : {
      83           1 :     return m_ci;
      84             : }
      85             : 
      86           1 : void CmdPin::set_list(bool list)
      87             : {
      88           1 :     m_list = list;
      89           1 : }
      90             : 
      91           1 : bool CmdPin::get_list() const
      92             : {
      93           1 :     return m_list;
      94             : }
      95             : 
      96           1 : void CmdPin::set_clear(bool clear)
      97             : {
      98           1 :     m_clear = clear;
      99           1 : }
     100             : 
     101           1 : bool CmdPin::get_clear() const
     102             : {
     103           1 :     return m_clear;
     104             : }
     105             : 
     106           0 : void CmdPin::set_rev_set(const std::string &rev_set)
     107             : {
     108           0 :     m_rev_set = rev_set;
     109           0 : }
     110             : 
     111           0 : const std::string &CmdPin::get_rev_set() const
     112             : {
     113           0 :     return m_rev_set;
     114             : }
     115             : 
     116           0 : Result CmdPin::apply_revision_set_selection()
     117             : {
     118           0 :     if (get_manifest() == nullptr) return ESYSREPO_RESULT(ResultCode::MANIFEST_IS_NULLPTR);
     119             : 
     120           0 :     std::string preferred = get_rev_set();
     121           0 :     if (preferred.empty() && get_config_folder() != nullptr && get_config_folder()->get_config() != nullptr)
     122           0 :         preferred = get_config_folder()->get_config()->get_revision_set();
     123             : 
     124           0 :     return get_manifest()->select_revision_set(preferred);
     125           0 : }
     126             : 
     127           0 : void CmdPin::print_pin(const RevisionPin &pin, const char *action)
     128             : {
     129           0 :     std::ostringstream oss;
     130           0 :     oss << "pin";
     131           0 :     if (action != nullptr && action[0] != '\0') oss << " " << action;
     132           0 :     oss << ": " << to_string(pin.get_selector()) << "=" << pin.get_value() << " rev=" << pin.get_rev()
     133           0 :         << " path=" << pin.get_path();
     134           0 :     info(oss.str());
     135           0 :     if (get_console_os() != nullptr) *get_console_os() << oss.str() << std::endl;
     136           0 : }
     137             : 
     138           0 : Result CmdPin::resolve_repo(std::shared_ptr<manifest::Repository> &repo, PinSelector &selector, std::string &value)
     139             : {
     140           0 :     repo = nullptr;
     141           0 :     selector = PinSelector::NOT_SET;
     142           0 :     value.clear();
     143             : 
     144           0 :     int selectors = 0;
     145           0 :     if (!get_name().empty()) ++selectors;
     146           0 :     if (!get_project().empty()) ++selectors;
     147           0 :     if (!get_url().empty()) ++selectors;
     148           0 :     if (get_ci()) ++selectors;
     149             : 
     150           0 :     if (selectors != 1) return ESYSREPO_RESULT(ResultCode::CMD_INCORRECT_PARAMETERS_COMBINATION);
     151             : 
     152           0 :     if (get_ci())
     153             :     {
     154           0 :         CIEnv ci;
     155           0 :         Result result = CIEnv::detect(ci);
     156           0 :         if (result.error()) return result;
     157             : 
     158           0 :         std::string rev = get_rev().empty() ? ci.get_rev() : get_rev();
     159           0 :         if (rev.empty()) return ESYSREPO_RESULT(ResultCode::CMD_MISSING_PARAMETERS);
     160             : 
     161             :         // Prefer project path, then URL
     162           0 :         if (!ci.get_project().empty())
     163             :         {
     164           0 :             auto matches = get_manifest()->find_repos_by_project(ci.get_project());
     165           0 :             if (matches.size() > 1) return ESYSREPO_RESULT(ResultCode::CMDPIN_AMBIGUOUS_MATCH, ci.get_project());
     166           0 :             if (matches.size() == 1)
     167             :             {
     168           0 :                 repo = matches[0];
     169           0 :                 selector = PinSelector::PROJECT;
     170           0 :                 value = ci.get_project();
     171           0 :                 m_rev = rev;
     172           0 :                 return ESYSREPO_RESULT(ResultCode::OK);
     173             :             }
     174           0 :         }
     175           0 :         if (!ci.get_url().empty())
     176             :         {
     177           0 :             repo = get_manifest()->find_repo_by_url(ci.get_url());
     178           0 :             if (repo != nullptr)
     179             :             {
     180           0 :                 selector = PinSelector::URL;
     181           0 :                 value = ci.get_url();
     182           0 :                 m_rev = rev;
     183           0 :                 return ESYSREPO_RESULT(ResultCode::OK);
     184             :             }
     185             :         }
     186           0 :         return ESYSREPO_RESULT(ResultCode::CMDPIN_NO_MATCH);
     187           0 :     }
     188             : 
     189           0 :     if (!get_name().empty())
     190             :     {
     191           0 :         auto matches = get_manifest()->find_repos_by_name(get_name());
     192           0 :         if (matches.empty()) return ESYSREPO_RESULT(ResultCode::CMDPIN_NO_MATCH, get_name());
     193           0 :         if (matches.size() > 1) return ESYSREPO_RESULT(ResultCode::CMDPIN_AMBIGUOUS_MATCH, get_name());
     194           0 :         repo = matches[0];
     195           0 :         selector = PinSelector::NAME;
     196           0 :         value = get_name();
     197           0 :         return ESYSREPO_RESULT(ResultCode::OK);
     198           0 :     }
     199             : 
     200           0 :     if (!get_project().empty())
     201             :     {
     202           0 :         auto matches = get_manifest()->find_repos_by_project(get_project());
     203           0 :         if (matches.empty()) return ESYSREPO_RESULT(ResultCode::CMDPIN_NO_MATCH, get_project());
     204           0 :         if (matches.size() > 1) return ESYSREPO_RESULT(ResultCode::CMDPIN_AMBIGUOUS_MATCH, get_project());
     205           0 :         repo = matches[0];
     206           0 :         selector = PinSelector::PROJECT;
     207           0 :         value = get_project();
     208           0 :         return ESYSREPO_RESULT(ResultCode::OK);
     209           0 :     }
     210             : 
     211           0 :     if (!get_url().empty())
     212             :     {
     213           0 :         repo = get_manifest()->find_repo_by_url(get_url());
     214           0 :         if (repo == nullptr) return ESYSREPO_RESULT(ResultCode::CMDPIN_NO_MATCH, get_url());
     215           0 :         selector = PinSelector::URL;
     216           0 :         value = get_url();
     217           0 :         return ESYSREPO_RESULT(ResultCode::OK);
     218             :     }
     219             : 
     220           0 :     return ESYSREPO_RESULT(ResultCode::CMD_MISSING_PARAMETERS);
     221             : }
     222             : 
     223           0 : Result CmdPin::impl_run()
     224             : {
     225           0 :     Result result = default_handling_folder_workspace();
     226           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     227             : 
     228           0 :     result = open_esysrepo_folder();
     229           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     230             : 
     231           0 :     result = load_manifest();
     232           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     233             : 
     234           0 :     result = apply_revision_set_selection();
     235           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     236             : 
     237           0 :     auto pins = get_config_folder()->get_or_new_revision_pins();
     238           0 :     get_manifest()->set_revision_pins(pins);
     239             : 
     240           0 :     if (get_list())
     241             :     {
     242           0 :         for (auto &pin : pins->get_pins())
     243             :         {
     244           0 :             if (pin == nullptr) continue;
     245           0 :             print_pin(*pin, "");
     246             :         }
     247           0 :         return ESYSREPO_RESULT(ResultCode::OK);
     248             :     }
     249             : 
     250             :     // Show one pin by selector (no --rev, no --clear)
     251           0 :     const bool show_only = !get_clear() && get_rev().empty() && !get_ci() &&
     252           0 :                            (!get_name().empty() || !get_project().empty() || !get_url().empty());
     253             : 
     254           0 :     std::shared_ptr<manifest::Repository> repo;
     255           0 :     PinSelector selector = PinSelector::NOT_SET;
     256           0 :     std::string value;
     257           0 :     result = resolve_repo(repo, selector, value);
     258           0 :     if (result.error()) return result;
     259             : 
     260           0 :     if (show_only)
     261             :     {
     262           0 :         auto pin = pins->find_by_path(repo->get_path());
     263           0 :         if (pin == nullptr) pin = pins->find_by_selector(selector, value);
     264           0 :         if (pin == nullptr) return ESYSREPO_RESULT(ResultCode::CMDPIN_NO_MATCH, value);
     265           0 :         print_pin(*pin, "");
     266           0 :         return ESYSREPO_RESULT(ResultCode::OK);
     267           0 :     }
     268             : 
     269           0 :     if (get_clear())
     270             :     {
     271           0 :         auto pin = pins->find_by_path(repo->get_path());
     272           0 :         if (pin == nullptr) pin = pins->find_by_selector(selector, value);
     273           0 :         if (pin == nullptr) return ESYSREPO_RESULT(ResultCode::CMDPIN_NO_MATCH, value);
     274           0 :         RevisionPin cleared = *pin;
     275           0 :         pins->remove_by_path(pin->get_path());
     276           0 :         result = get_config_folder()->write_pins_file();
     277           0 :         if (result.error()) return result;
     278           0 :         print_pin(cleared, "cleared");
     279           0 :         return ESYSREPO_RESULT(ResultCode::OK);
     280           0 :     }
     281             : 
     282             :     // Set pin
     283           0 :     if (get_rev().empty()) return ESYSREPO_RESULT(ResultCode::CMD_MISSING_PARAMETERS);
     284             : 
     285           0 :     auto pin = std::make_shared<RevisionPin>();
     286           0 :     pin->set_selector(selector);
     287           0 :     pin->set_value(value);
     288           0 :     pin->set_rev(get_rev());
     289           0 :     pin->set_path(repo->get_path());
     290           0 :     pins->add(pin);
     291             : 
     292           0 :     result = get_config_folder()->write_pins_file();
     293           0 :     if (result.error()) return result;
     294             : 
     295           0 :     print_pin(*pin, "set");
     296           0 :     return ESYSREPO_RESULT(ResultCode::OK);
     297           0 : }
     298             : 
     299             : } // namespace esys::repo::exe

Generated by: LCOV version 1.14