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