Line data Source code
1 : /*!
2 : * \file esys/repo/manifest/syncrepos_manifest.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/manifest/syncrepos.h"
20 : #include "esys/repo/manifest/location.h"
21 : #include "esys/repo/gitmngr.h"
22 : #include "esys/repo/githelper.h"
23 : #include "esys/repo/gitphasetimings.h"
24 : #include "esys/repo/tui/is_tty.h"
25 : #include "esys/repo/tui/run_compact_sync_tui.h"
26 :
27 : #include "esys/repo/filesystem.h"
28 :
29 : #include <esys/repo/git/sshenv.h>
30 :
31 : #include <esys/trace/call.h>
32 : #include <esys/trace/macros.h>
33 :
34 : #include <boost/filesystem.hpp>
35 :
36 : #include <algorithm>
37 : #include <cstdlib>
38 : #include <iostream>
39 : #include <sstream>
40 :
41 : namespace esys::repo::manifest
42 : {
43 :
44 23 : SyncRepos::SyncRepos()
45 23 : : log::User()
46 : {
47 : // ADR-0030: tip-at-clone is the SyncRepos product default.
48 23 : m_clone_options.checkout_rev = true;
49 23 : m_clone_options.single_branch = true;
50 23 : }
51 :
52 83 : SyncRepos::~SyncRepos() = default;
53 :
54 20 : void SyncRepos::set_manifest(std::shared_ptr<Manifest> manifest)
55 : {
56 20 : m_manifest = manifest;
57 20 : }
58 :
59 300 : std::shared_ptr<Manifest> SyncRepos::get_manifest() const
60 : {
61 300 : return m_manifest;
62 : }
63 :
64 20 : void SyncRepos::set_config_folder(std::shared_ptr<ConfigFolder> config_folder)
65 : {
66 20 : m_config_folder = config_folder;
67 20 : }
68 :
69 140 : std::shared_ptr<ConfigFolder> SyncRepos::get_config_folder()
70 : {
71 140 : return m_config_folder;
72 : }
73 :
74 20 : void SyncRepos::set_git(std::shared_ptr<GitBase> git)
75 : {
76 20 : m_git = git;
77 20 : }
78 :
79 40 : std::shared_ptr<GitBase> SyncRepos::get_git() const
80 : {
81 40 : return m_git;
82 : }
83 :
84 0 : std::shared_ptr<GitBase> SyncRepos::get_git_or_new()
85 : {
86 0 : if (get_git() != nullptr) return get_git();
87 :
88 0 : return new_git();
89 : }
90 :
91 0 : void SyncRepos::set_git_generator(GitBase::GeneratorType git_generator)
92 : {
93 0 : m_git_generator = git_generator;
94 0 : }
95 :
96 120 : GitBase::GeneratorType SyncRepos::get_git_generator()
97 : {
98 120 : return m_git_generator;
99 : }
100 :
101 120 : std::shared_ptr<GitBase> SyncRepos::new_git()
102 : {
103 120 : if (get_git_generator() != nullptr) return get_git_generator()();
104 :
105 120 : return GitMngr::new_ptr();
106 : }
107 :
108 20 : bool SyncRepos::check_if_ssh_auth_needed_and_ok()
109 : {
110 20 : bool result = false;
111 20 : ETRC_CALL_RET_NP(result);
112 :
113 40 : for (auto location : get_manifest()->get_locations())
114 : {
115 28 : for (auto repo : location->get_repos())
116 : {
117 84 : if (!is_repo_to_be_synced(repo)) continue;
118 :
119 20 : if (location->is_address_ssh())
120 : {
121 20 : if (!get_alt_address()) return ETRC_RET(false);
122 0 : if (location->is_alt_address_ssh()) return ETRC_RET(false);
123 : }
124 28 : }
125 20 : }
126 0 : return ETRC_RET(true);
127 20 : }
128 :
129 20 : Result SyncRepos::run()
130 : {
131 20 : Result result;
132 20 : ETRC_CALL_RET_NP(result);
133 :
134 40 : if (get_manifest() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::MANIFEST_IS_NULLPTR));
135 40 : if (get_config_folder() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::CONFIG_FOLDER_IS_NULLPTR));
136 40 : if (get_git() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::GIT_IS_NULLPTR));
137 :
138 20 : apply_workspace_root_env();
139 :
140 80 : if (!check_if_ssh_auth_needed_and_ok() && !get_git()->is_ssh_agent_running()
141 40 : && git::explicit_ssh_private_key_from_env().empty())
142 0 : warn("SSH authentication needs an SSH agent, SSH_PRIVATE_KEY (file), or "
143 : "GIT_SSH_COMMAND -i. Git repos with SSH access may not sync.");
144 20 : bool display_repo_idx = true;
145 :
146 20 : if (get_run_tasks().get_job_count() == 1) display_repo_idx = false;
147 :
148 20 : std::vector<std::shared_ptr<SyncRepo>> root_tasks;
149 20 : std::vector<std::shared_ptr<SyncRepo>> other_tasks;
150 :
151 20 : set_repo_idx(0);
152 66 : for (auto location : get_manifest()->get_locations())
153 : {
154 169 : for (auto repo : location->get_repos())
155 : {
156 429 : if (!is_repo_to_be_synced(repo)) continue;
157 :
158 240 : std::shared_ptr<SyncRepo> sync_repo = make_sync_repo(repo, display_repo_idx);
159 120 : if (repo->get_path() == ".")
160 15 : root_tasks.push_back(sync_repo);
161 : else
162 105 : other_tasks.push_back(sync_repo);
163 :
164 120 : ++get_repo_idx();
165 263 : }
166 26 : }
167 :
168 20 : const std::size_t parallel_jobs = get_job_count();
169 :
170 20 : if (get_tui())
171 0 : return ETRC_RET(ESYSREPO_RESULT(run_sync_with_tui(root_tasks, other_tasks, parallel_jobs)));
172 :
173 40 : auto run_root = [this, &root_tasks]() { return run_sync_tasks(root_tasks, 1); };
174 20 : auto run_others = [this, &other_tasks, parallel_jobs]() { return run_sync_tasks(other_tasks, parallel_jobs); };
175 :
176 20 : if (get_workspace_root_order() == WorkspaceRootOrder::Last)
177 : {
178 0 : result = run_others();
179 0 : if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
180 0 : result = run_root();
181 : }
182 : else
183 : {
184 20 : result = run_root();
185 20 : if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
186 20 : result = run_others();
187 : }
188 :
189 40 : return ETRC_RET(ESYSREPO_RESULT(result));
190 20 : }
191 :
192 22 : void SyncRepos::apply_workspace_root_env()
193 : {
194 22 : if (const char *order_env = std::getenv("ESYSREPO_WORKSPACE_ROOT_ORDER"))
195 : {
196 0 : WorkspaceRootOrder order = m_workspace_root_order;
197 0 : if (parse_workspace_root_order(order_env, order))
198 : {
199 0 : m_workspace_root_order = order;
200 0 : std::ostringstream oss;
201 0 : oss << "Workspace root order: " << order << " (ESYSREPO_WORKSPACE_ROOT_ORDER)";
202 0 : info(oss.str());
203 0 : }
204 : else
205 0 : warn(std::string("Unknown ESYSREPO_WORKSPACE_ROOT_ORDER='") + order_env + "' (use first|last)");
206 : }
207 :
208 22 : if (const char *clone_env = std::getenv("ESYSREPO_WORKSPACE_ROOT_CLONE"))
209 : {
210 2 : WorkspaceRootCloneMethod method = m_workspace_root_clone_method;
211 2 : if (parse_workspace_root_clone_method(clone_env, method))
212 : {
213 2 : m_workspace_root_clone_method = method;
214 2 : std::ostringstream oss;
215 2 : oss << "Workspace root clone: " << method << " (ESYSREPO_WORKSPACE_ROOT_CLONE)";
216 2 : info(oss.str());
217 2 : }
218 : else
219 0 : warn(std::string("Unknown ESYSREPO_WORKSPACE_ROOT_CLONE='") + clone_env
220 0 : + "' (use temp-move|init-fetch)");
221 : }
222 :
223 22 : if (const char *checkout_env = std::getenv("ESYSREPO_CLONE_CHECKOUT_REV"))
224 : {
225 2 : if (checkout_env[0] == '\0')
226 : {
227 : // Unset / empty: keep SyncRepos product default (tip).
228 : }
229 : else
230 : {
231 2 : std::string text = checkout_env;
232 12 : for (char &c : text)
233 : {
234 10 : if (c >= 'A' && c <= 'Z') c = static_cast<char>(c - 'A' + 'a');
235 : }
236 8 : if (text == "1" || text == "true" || text == "yes" || text == "tip")
237 : {
238 1 : m_clone_options.checkout_rev = true;
239 1 : m_clone_options.single_branch = true;
240 2 : info("Clone checkout_rev=true single_branch=true (ESYSREPO_CLONE_CHECKOUT_REV)");
241 : }
242 4 : else if (text == "0" || text == "false" || text == "no" || text == "default")
243 : {
244 1 : m_clone_options.checkout_rev = false;
245 1 : m_clone_options.single_branch = false;
246 2 : info("Clone checkout_rev=false (ESYSREPO_CLONE_CHECKOUT_REV) — legacy path");
247 : }
248 : else
249 0 : warn(std::string("Unknown ESYSREPO_CLONE_CHECKOUT_REV='") + checkout_env
250 0 : + "' (use tip|default or 1|0)");
251 2 : }
252 : }
253 22 : }
254 :
255 120 : std::shared_ptr<SyncRepo> SyncRepos::make_sync_repo(std::shared_ptr<manifest::Repository> repo, bool display_repo_idx)
256 : {
257 120 : std::shared_ptr<SyncRepo> sync_repo = std::make_shared<SyncRepo>();
258 :
259 240 : sync_repo->set_repo(repo);
260 120 : sync_repo->set_manifest(get_manifest());
261 120 : sync_repo->set_repo_idx(get_repo_idx());
262 120 : sync_repo->set_display_repo_idx(display_repo_idx);
263 120 : sync_repo->set_config_folder(get_config_folder());
264 120 : sync_repo->set_git(new_git());
265 240 : sync_repo->get_git()->set_logger_if(get_logger_if());
266 120 : sync_repo->set_logger_if(get_logger_if());
267 120 : sync_repo->set_workspace_root_clone_method(get_workspace_root_clone_method());
268 120 : sync_repo->set_clone_options(get_clone_options());
269 :
270 120 : if (!get_branch().empty()) sync_repo->set_branch(get_branch());
271 :
272 120 : sync_repo->set_alt_address(get_alt_address());
273 :
274 120 : const auto *manifest = get_manifest().get();
275 120 : const bool update_subs =
276 : (manifest != nullptr)
277 120 : ? should_update_submodules(get_recurse_submodules(), *manifest, repo.get())
278 0 : : (get_recurse_submodules() == RecurseSubmodules::Yes);
279 120 : sync_repo->set_update_submodules(update_subs);
280 :
281 120 : return sync_repo;
282 0 : }
283 :
284 40 : Result SyncRepos::run_sync_tasks(const std::vector<std::shared_ptr<SyncRepo>> &tasks, std::size_t job_count)
285 : {
286 40 : Result result;
287 40 : ETRC_CALL_RET_NP(result);
288 :
289 46 : if (tasks.empty()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
290 :
291 34 : RunTasks run_tasks;
292 34 : run_tasks.set_logger_if(get_logger_if());
293 34 : run_tasks.set_job_count(job_count);
294 274 : for (const auto &task : tasks) run_tasks.add(task, task->get_repo_idx());
295 :
296 34 : result = run_tasks.run();
297 34 : log_phase_totals(tasks);
298 :
299 68 : return ETRC_RET(ESYSREPO_RESULT(result));
300 40 : }
301 :
302 34 : void SyncRepos::log_phase_totals(const std::vector<std::shared_ptr<SyncRepo>> &tasks)
303 : {
304 34 : if (!GitHelper::phase_timing_enabled()) return;
305 :
306 0 : GitPhaseTimings totals;
307 0 : for (const auto &task : tasks) totals.add(task->get_phase_timings());
308 0 : if (totals.total_ms() != 0 || totals.refresh_ms != 0) info(totals.format("sync phase totals (ms):"));
309 : }
310 :
311 0 : Result SyncRepos::run_with_session(progress::ProgressSession &session, tui::SyncTuiControl *control)
312 : {
313 0 : Result result;
314 0 : ETRC_CALL_RET_NP(result);
315 :
316 0 : if (get_manifest() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::MANIFEST_IS_NULLPTR));
317 0 : if (get_config_folder() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::CONFIG_FOLDER_IS_NULLPTR));
318 0 : if (get_git() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::GIT_IS_NULLPTR));
319 :
320 0 : apply_workspace_root_env();
321 :
322 0 : if (!check_if_ssh_auth_needed_and_ok() && !get_git()->is_ssh_agent_running()
323 0 : && git::explicit_ssh_private_key_from_env().empty())
324 0 : warn("SSH authentication needs an SSH agent, SSH_PRIVATE_KEY (file), or "
325 : "GIT_SSH_COMMAND -i. Git repos with SSH access may not sync.");
326 :
327 0 : bool display_repo_idx = true;
328 0 : if (get_run_tasks().get_job_count() == 1) display_repo_idx = false;
329 :
330 0 : std::vector<std::shared_ptr<SyncRepo>> root_tasks;
331 0 : std::vector<std::shared_ptr<SyncRepo>> other_tasks;
332 :
333 0 : set_repo_idx(0);
334 0 : for (auto location : get_manifest()->get_locations())
335 : {
336 0 : for (auto repo : location->get_repos())
337 : {
338 0 : if (!is_repo_to_be_synced(repo)) continue;
339 :
340 0 : std::shared_ptr<SyncRepo> sync_repo = make_sync_repo(repo, display_repo_idx);
341 0 : if (repo->get_path() == ".")
342 0 : root_tasks.push_back(sync_repo);
343 : else
344 0 : other_tasks.push_back(sync_repo);
345 :
346 0 : ++get_repo_idx();
347 0 : }
348 0 : }
349 :
350 0 : const std::size_t parallel_jobs = get_job_count();
351 :
352 0 : auto task_name = [](const std::shared_ptr<SyncRepo> &task) -> std::string {
353 0 : std::string name;
354 0 : if (task->get_repo() != nullptr)
355 : {
356 0 : name = task->get_repo()->get_path();
357 0 : if (name.empty()) name = task->get_repo()->get_name();
358 : }
359 0 : if (name.empty()) name = "repo";
360 0 : return name;
361 0 : };
362 :
363 0 : std::vector<std::string> names;
364 0 : auto note_task = [&](const std::shared_ptr<SyncRepo> &task) {
365 0 : const std::size_t idx = task->get_repo_idx();
366 0 : if (names.size() <= idx) names.resize(idx + 1, "repo");
367 0 : names[idx] = task_name(task);
368 0 : };
369 0 : for (const auto &task : root_tasks) note_task(task);
370 0 : for (const auto &task : other_tasks) note_task(task);
371 :
372 0 : const std::size_t ui_workers =
373 0 : other_tasks.empty() ? 1 : (std::min)(parallel_jobs == 0 ? std::size_t{1} : parallel_jobs, other_tasks.size());
374 :
375 0 : if (control != nullptr)
376 : {
377 0 : if (control->reset_repos) control->reset_repos(names, ui_workers);
378 0 : if (control->set_phase) control->set_phase("Sync in progress…");
379 : }
380 :
381 0 : if (names.empty()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
382 :
383 0 : auto run_batch = [this](const std::vector<std::shared_ptr<SyncRepo>> &tasks, std::size_t job_count,
384 0 : progress::ProgressSession &sess) -> Result {
385 0 : if (tasks.empty()) return ESYSREPO_RESULT(ResultCode::OK);
386 :
387 0 : RunTasks run_tasks;
388 0 : run_tasks.set_logger_if(get_logger_if());
389 0 : run_tasks.set_job_count(job_count);
390 0 : run_tasks.set_progress_session(&sess);
391 0 : run_tasks.set_console_progress(false);
392 0 : for (const auto &task : tasks) run_tasks.add(task, task->get_repo_idx());
393 0 : auto batch_result = run_tasks.run();
394 0 : log_phase_totals(tasks);
395 0 : return batch_result;
396 0 : };
397 :
398 0 : if (get_workspace_root_order() == WorkspaceRootOrder::Last)
399 : {
400 0 : result = run_batch(other_tasks, parallel_jobs, session);
401 0 : if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
402 0 : result = run_batch(root_tasks, 1, session);
403 : }
404 : else
405 : {
406 0 : result = run_batch(root_tasks, 1, session);
407 0 : if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
408 0 : result = run_batch(other_tasks, parallel_jobs, session);
409 : }
410 :
411 0 : return ETRC_RET(ESYSREPO_RESULT(result));
412 0 : }
413 :
414 0 : Result SyncRepos::run_sync_with_tui(const std::vector<std::shared_ptr<SyncRepo>> &root_tasks,
415 : const std::vector<std::shared_ptr<SyncRepo>> &other_tasks,
416 : std::size_t parallel_jobs)
417 : {
418 0 : Result result;
419 0 : ETRC_CALL_RET_NP(result);
420 :
421 : #ifndef ESYSREPO_HAVE_TUI
422 : error("--tui requested but esysrepo was built without FTXUI (Conan with_tui / ESYSREPO_WITH_TUI)");
423 : return ETRC_RET(ESYSREPO_RESULT(ResultCode::NOT_IMPLEMENTED));
424 : #else
425 0 : if (!tui::is_tty())
426 : {
427 0 : const char *msg =
428 : "--tui requires a real Win32 console (cmd.exe, PowerShell, or Windows "
429 : "Terminal). Git Bash/mintty and redirected stdout are not supported.";
430 0 : error(msg);
431 0 : std::cerr << "ERROR: " << msg << std::endl;
432 0 : return ETRC_RET(ESYSREPO_RESULT(ResultCode::GENERIC_ERROR));
433 : }
434 :
435 0 : auto task_name = [](const std::shared_ptr<SyncRepo> &task) -> std::string {
436 0 : std::string name;
437 0 : if (task->get_repo() != nullptr)
438 : {
439 0 : name = task->get_repo()->get_path();
440 0 : if (name.empty()) name = task->get_repo()->get_name();
441 : }
442 0 : if (name.empty()) name = "repo";
443 0 : return name;
444 0 : };
445 :
446 0 : std::vector<std::string> names;
447 0 : auto note_task = [&](const std::shared_ptr<SyncRepo> &task) {
448 0 : const std::size_t idx = task->get_repo_idx();
449 0 : if (names.size() <= idx) names.resize(idx + 1, "repo");
450 0 : names[idx] = task_name(task);
451 0 : };
452 0 : for (const auto &task : root_tasks) note_task(task);
453 0 : for (const auto &task : other_tasks) note_task(task);
454 :
455 0 : if (names.empty()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
456 :
457 0 : const std::size_t ui_workers =
458 0 : other_tasks.empty() ? 1 : (std::min)(parallel_jobs == 0 ? std::size_t{1} : parallel_jobs, other_tasks.size());
459 :
460 0 : auto run_batch = [this](const std::vector<std::shared_ptr<SyncRepo>> &tasks, std::size_t job_count,
461 0 : progress::ProgressSession &session) -> Result {
462 0 : if (tasks.empty()) return ESYSREPO_RESULT(ResultCode::OK);
463 :
464 0 : RunTasks run_tasks;
465 0 : run_tasks.set_logger_if(get_logger_if());
466 0 : run_tasks.set_job_count(job_count);
467 0 : run_tasks.set_progress_session(&session);
468 0 : run_tasks.set_console_progress(false);
469 0 : for (const auto &task : tasks) run_tasks.add(task, task->get_repo_idx());
470 0 : auto batch_result = run_tasks.run();
471 0 : log_phase_totals(tasks);
472 0 : return batch_result;
473 0 : };
474 :
475 0 : auto work = [this, &root_tasks, &other_tasks, parallel_jobs, &run_batch](
476 0 : progress::ProgressSession &session, tui::SyncTuiControl &control) -> Result {
477 0 : if (control.logger) set_logger_if(control.logger);
478 0 : if (control.set_phase) control.set_phase("Sync in progress…");
479 :
480 0 : Result phase;
481 0 : if (get_workspace_root_order() == WorkspaceRootOrder::Last)
482 : {
483 0 : phase = run_batch(other_tasks, parallel_jobs, session);
484 0 : if (phase.error()) return phase;
485 0 : return run_batch(root_tasks, 1, session);
486 : }
487 0 : phase = run_batch(root_tasks, 1, session);
488 0 : if (phase.error()) return phase;
489 0 : return run_batch(other_tasks, parallel_jobs, session);
490 0 : };
491 :
492 0 : result = tui::run_compact_sync_tui(work, names, ui_workers, get_logger_if());
493 0 : return ETRC_RET(ESYSREPO_RESULT(result));
494 : #endif
495 0 : }
496 :
497 16 : void SyncRepos::set_log_level(log::Level log_level)
498 : {
499 16 : m_log_level = log_level;
500 16 : }
501 :
502 0 : log::Level SyncRepos::get_log_level()
503 : {
504 0 : return m_log_level;
505 : }
506 :
507 20 : void SyncRepos::set_repo_idx(std::size_t repo_idx)
508 : {
509 20 : m_repo_idx = repo_idx;
510 20 : }
511 :
512 0 : std::size_t SyncRepos::get_repo_idx() const
513 : {
514 0 : return m_repo_idx;
515 : }
516 :
517 240 : std::size_t &SyncRepos::get_repo_idx()
518 : {
519 240 : return m_repo_idx;
520 : }
521 :
522 62 : bool SyncRepos::globly_match(const std::string &text, const std::string &glob)
523 : {
524 62 : const char *text_backup = nullptr;
525 62 : const char *glob_backup = nullptr;
526 62 : const char *text_ = text.c_str();
527 62 : const char *glob_ = glob.c_str();
528 :
529 312 : while (*text_ != '\0')
530 : {
531 302 : if (*glob_ == '*')
532 : {
533 : // new star-loop: backup positions in pattern and text
534 8 : text_backup = text_;
535 8 : glob_backup = ++glob_;
536 : }
537 294 : else if ((*glob_ == '?' && *text_ != '/') || *glob_ == *text_)
538 : {
539 : // ? matched any character except /, or we matched the current non-NUL character
540 226 : text_++;
541 226 : glob_++;
542 : }
543 : else
544 : {
545 68 : if (glob_backup == nullptr || *text_backup == '/') return false;
546 : // star-loop: backtrack to the last * but do not jump over /
547 16 : text_ = ++text_backup;
548 16 : glob_ = glob_backup;
549 : }
550 : }
551 : // ignore trailing stars
552 10 : while (*glob_ == '*') glob_++;
553 : // at end of text means success if nothing else is left to match
554 10 : return *glob_ == '\0' ? true : false;
555 : }
556 :
557 171 : bool SyncRepos::is_repo_to_be_synced(std::shared_ptr<manifest::Repository> repo) const
558 : {
559 171 : bool result = false;
560 171 : ETRC_CALL_RET(result, repo);
561 :
562 171 : if (m_map_folders_to_sync.size() == 0) return ETRC_RET(true);
563 :
564 50 : auto it = m_map_folders_to_sync.find(repo->get_path());
565 :
566 50 : if (it != m_map_folders_to_sync.end()) return ETRC_RET(true);
567 :
568 35 : result = false;
569 : // Now let's see if glob filter were used in the sync command
570 88 : for (auto &str : get_folders_to_sync())
571 : {
572 57 : result = globly_match(repo->get_path(), str);
573 57 : if (result) return ETRC_RET(true);
574 : }
575 31 : return ETRC_RET(false);
576 171 : }
577 :
578 6 : void SyncRepos::set_folders_to_sync(std::vector<std::string> folders_to_sync)
579 : {
580 6 : m_folders_to_sync = folders_to_sync;
581 6 : m_map_folders_to_sync.clear();
582 :
583 17 : for (auto &folder : folders_to_sync) m_map_folders_to_sync[folder] = true;
584 6 : }
585 :
586 35 : const std::vector<std::string> &SyncRepos::get_folders_to_sync() const
587 : {
588 35 : return m_folders_to_sync;
589 : }
590 :
591 20 : void SyncRepos::set_job_count(std::size_t job_count)
592 : {
593 20 : m_run_tasks.set_job_count(job_count);
594 20 : }
595 :
596 20 : std::size_t SyncRepos::get_job_count() const
597 : {
598 20 : return m_run_tasks.get_job_count();
599 : }
600 :
601 2 : void SyncRepos::set_branch(const std::string &branch)
602 : {
603 2 : m_branch = branch;
604 2 : }
605 :
606 133 : const std::string &SyncRepos::get_branch() const
607 : {
608 133 : return m_branch;
609 : }
610 :
611 0 : void SyncRepos::set_alt_address(bool alt_address)
612 : {
613 0 : m_alt_address = alt_address;
614 0 : }
615 :
616 140 : bool SyncRepos::get_alt_address() const
617 : {
618 140 : return m_alt_address;
619 : }
620 :
621 20 : RunTasks &SyncRepos::get_run_tasks()
622 : {
623 20 : return m_run_tasks;
624 : }
625 :
626 0 : const RunTasks &SyncRepos::get_run_tasks() const
627 : {
628 0 : return m_run_tasks;
629 : }
630 :
631 0 : void SyncRepos::set_workspace_root_order(WorkspaceRootOrder order)
632 : {
633 0 : m_workspace_root_order = order;
634 0 : }
635 :
636 20 : WorkspaceRootOrder SyncRepos::get_workspace_root_order() const
637 : {
638 20 : return m_workspace_root_order;
639 : }
640 :
641 0 : void SyncRepos::set_workspace_root_clone_method(WorkspaceRootCloneMethod method)
642 : {
643 0 : m_workspace_root_clone_method = method;
644 0 : }
645 :
646 120 : WorkspaceRootCloneMethod SyncRepos::get_workspace_root_clone_method() const
647 : {
648 120 : return m_workspace_root_clone_method;
649 : }
650 :
651 1 : void SyncRepos::set_clone_options(const git::CloneOptions &options)
652 : {
653 1 : m_clone_options = options;
654 1 : }
655 :
656 127 : const git::CloneOptions &SyncRepos::get_clone_options() const
657 : {
658 127 : return m_clone_options;
659 : }
660 :
661 20 : void SyncRepos::set_recurse_submodules(RecurseSubmodules recurse)
662 : {
663 20 : m_recurse_submodules = recurse;
664 20 : }
665 :
666 120 : RecurseSubmodules SyncRepos::get_recurse_submodules() const
667 : {
668 120 : return m_recurse_submodules;
669 : }
670 :
671 20 : void SyncRepos::set_tui(bool tui)
672 : {
673 20 : m_tui = tui;
674 20 : }
675 :
676 20 : bool SyncRepos::get_tui() const
677 : {
678 20 : return m_tui;
679 : }
680 :
681 : } // namespace esys::repo::manifest
|