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