Line data Source code
1 : /*!
2 : * \file esys/repo/manifest/syncrepo_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/syncrepo.h"
20 : #include "esys/repo/manifest/location.h"
21 : #include "esys/repo/git/clonerev.h"
22 :
23 : #include "esys/repo/filesystem.h"
24 :
25 : #include <esys/trace/call.h>
26 : #include <esys/trace/macros.h>
27 :
28 : #include <boost/filesystem.hpp>
29 :
30 : #include <sstream>
31 : #include <string>
32 :
33 : namespace esys::repo::manifest
34 : {
35 :
36 155 : SyncRepo::SyncRepo()
37 155 : : log::User()
38 : {
39 155 : }
40 :
41 310 : SyncRepo::~SyncRepo() = default;
42 :
43 152 : int SyncRepo::run()
44 : {
45 152 : int result = 0;
46 152 : ETRC_CALL_RET_NP(result);
47 :
48 152 : return ETRC_RET(process_repo());
49 152 : }
50 :
51 152 : int SyncRepo::process_repo()
52 : {
53 152 : int result = 0;
54 152 : ETRC_CALL_RET_NP(result);
55 :
56 152 : boost::filesystem::path path = get_config_folder()->get_workspace_path();
57 436 : if (get_repo()->get_path() != ".") path /= get_repo()->get_path();
58 :
59 152 : if (!GitBase::is_repo(path.string()))
60 139 : result = clone();
61 : else
62 13 : result = fetch_update();
63 152 : if (result != 0) return ETRC_RET(result);
64 152 : return ETRC_RET(maybe_update_submodules(path.string()));
65 152 : }
66 :
67 10 : bool SyncRepo::has_branch(GitHelper &git_helper, const std::string &branch)
68 : {
69 10 : bool result_bool = false;
70 10 : ETRC_CALL_RET(result_bool, branch);
71 :
72 : // Remote names are origin/<branch> after fetch; resolve_ref / find_ref accept the short name.
73 10 : Result_t<bool> found = git_helper.has_branch(branch, git::BranchType::REMOTE, log::Level::DEBUG);
74 10 : if (found.error() || !found)
75 4 : found = git_helper.has_branch(branch, git::BranchType::LOCAL, log::Level::DEBUG);
76 :
77 10 : if (found.error() || !found)
78 : {
79 2 : git_helper.debug(0, "Branch not found : " + branch);
80 2 : return ETRC_RET(false);
81 : }
82 8 : git_helper.debug(0, "Branch found : " + branch);
83 8 : return ETRC_RET(true);
84 10 : }
85 :
86 148 : std::string SyncRepo::get_manifest_repo_revision()
87 : {
88 444 : if (m_manifest != nullptr && get_repo() != nullptr) return m_manifest->get_repo_revision(get_repo());
89 0 : if (get_repo() != nullptr) return get_repo()->get_revision();
90 148 : return {};
91 : }
92 :
93 64 : bool SyncRepo::is_pinned()
94 : {
95 128 : if (m_manifest == nullptr || get_repo() == nullptr) return false;
96 128 : return m_manifest->has_revision_pin(get_repo()->get_path());
97 : }
98 :
99 49 : std::string SyncRepo::get_checkout_revision(GitHelper &git_helper)
100 : {
101 49 : std::string result;
102 49 : ETRC_CALL_RET_NP(result);
103 :
104 : // Workspace pins win over --prefer-branch (ADR-0021 / ADR-0037)
105 51 : if (is_pinned()) return ETRC_RET(get_manifest_repo_revision());
106 :
107 112 : if (get_branch().empty()) return ETRC_RET(get_manifest_repo_revision());
108 :
109 16 : Result_t<bool> branch_exists =
110 16 : git_helper.has_branch(get_branch(), git::BranchType::REMOTE, esys::log::Level::DEBUG);
111 :
112 16 : std::ostringstream oss;
113 16 : oss << "branch_exists = " << branch_exists;
114 16 : debug(0, oss.str());
115 :
116 16 : if (branch_exists) return ETRC_RET(get_branch());
117 39 : return ETRC_RET(get_manifest_repo_revision());
118 114 : }
119 :
120 152 : std::shared_ptr<GitHelper> SyncRepo::new_git_helper()
121 : {
122 456 : auto git_helper = std::make_shared<GitHelper>(get_git(), get_logger_if(), static_cast<int>(get_repo_idx()));
123 :
124 456 : get_git()->set_logger_if(git_helper);
125 152 : return git_helper;
126 0 : }
127 :
128 152 : SyncRepo::PhaseCapture::PhaseCapture(SyncRepo &self, GitHelper &helper)
129 152 : : m_self(self)
130 152 : , m_helper(helper)
131 : {
132 152 : }
133 :
134 152 : SyncRepo::PhaseCapture::~PhaseCapture()
135 : {
136 152 : m_self.m_phase_timings = m_helper.get_phase_timings();
137 152 : m_helper.log_phase_summary();
138 152 : }
139 :
140 0 : const GitPhaseTimings &SyncRepo::get_phase_timings() const
141 : {
142 0 : return m_phase_timings;
143 : }
144 :
145 139 : int SyncRepo::clone()
146 : {
147 139 : int result = 0;
148 139 : ETRC_CALL_RET_NP(result);
149 :
150 139 : std::shared_ptr<GitHelper> git_helper = new_git_helper();
151 139 : PhaseCapture phase_capture(*this, *git_helper);
152 139 : std::string url = get_repo_url();
153 139 : std::string branch_to_checkout;
154 :
155 139 : boost::filesystem::path path = get_config_folder()->get_workspace_path();
156 278 : ETRC_MSG("path : " + get_repo()->get_path());
157 :
158 278 : if (get_repo()->get_path() != ".")
159 : {
160 : // A simple clone can be made
161 121 : path /= get_repo()->get_path();
162 :
163 : // Prefer tip-at-clone when SyncRepos enabled checkout_rev (ADR-0030 default).
164 : // Raw commit SHAs and empty revs force the legacy path for this repo.
165 121 : git::CloneOptions clone_opts = get_clone_options();
166 242 : git::CloneRevPlan plan = git::plan_clone_rev(clone_opts.checkout_rev, get_branch(),
167 121 : get_branch().empty() ? get_manifest_repo_revision()
168 121 : : std::string());
169 121 : std::string clone_rev = plan.clone_rev;
170 121 : if (!plan.use_tip) clone_opts.checkout_rev = false;
171 :
172 121 : Result rresult =
173 121 : git_helper->clone_rev(url, clone_rev, path.string(), false, log::Level::INFO, 0, clone_opts);
174 121 : if (rresult.error() && clone_opts.checkout_rev && !clone_rev.empty())
175 : {
176 : // Branch/tag missing on this remote (e.g. sync -b), or odd rev: fall back.
177 20 : git_helper->debug(0, "clone with rev '" + clone_rev + "' failed; cloning default");
178 10 : clone_rev.clear();
179 10 : clone_opts = git::CloneOptions();
180 10 : rresult = git_helper->clone_rev(url, "", path.string(), false, log::Level::INFO, 0, clone_opts);
181 : }
182 121 : if (rresult.error())
183 : {
184 0 : git_helper->close_on_error(log::Level::DEBUG);
185 0 : return ETRC_RET(rresult.get_result_code_int());
186 : }
187 :
188 121 : if (clone_opts.checkout_rev && !clone_rev.empty())
189 : {
190 : // Already on the requested branch/tag tip from clone.
191 94 : rresult = git_helper->close(log::Level::DEBUG);
192 94 : return ETRC_RET(rresult.get_result_code_int());
193 : }
194 :
195 27 : if (!get_branch().empty())
196 : {
197 10 : Result result = git_helper->fetch(get_log_level());
198 10 : if (result.error())
199 : {
200 0 : git_helper->close_on_error(log::Level::DEBUG);
201 0 : return ETRC_RET(result.get_result_code_int());
202 : }
203 10 : }
204 :
205 27 : branch_to_checkout = get_checkout_revision(*git_helper.get());
206 27 : git_helper->debug(0, "branch_to_checkout = " + branch_to_checkout);
207 27 : if (branch_to_checkout.empty()) return ETRC_RET(0);
208 :
209 27 : rresult = git_helper->checkout(branch_to_checkout, false, log::Level::INFO);
210 27 : if (rresult.error())
211 : {
212 0 : git_helper->close_on_error(log::Level::DEBUG);
213 0 : return ETRC_RET(rresult.get_result_code_int());
214 : }
215 27 : rresult = git_helper->close(log::Level::DEBUG);
216 27 : return ETRC_RET(rresult.get_result_code_int());
217 121 : }
218 :
219 18 : if (get_workspace_root_clone_method() == WorkspaceRootCloneMethod::InitFetch)
220 1 : return ETRC_RET(clone_workspace_root_init_fetch(*git_helper.get(), url, path.string()));
221 :
222 17 : return ETRC_RET(clone_workspace_root_temp_move(*git_helper.get(), url, path.string()));
223 278 : }
224 :
225 17 : int SyncRepo::clone_workspace_root_temp_move(GitHelper &git_helper, const std::string &url, const std::string &path)
226 : {
227 17 : int result = 0;
228 17 : ETRC_CALL_RET(result, url, path);
229 :
230 : // Folder is not empty (.esysrepo): clone into temp, then move into the workspace
231 17 : boost::filesystem::path temp_path = get_config_folder()->get_temp_path();
232 17 : std::ostringstream oss;
233 17 : oss << "repo_temp" << get_repo_idx();
234 17 : temp_path /= oss.str();
235 :
236 17 : Result rresult = git_helper.clone(url, temp_path.string(), path, true, get_log_level());
237 17 : if (rresult.error())
238 : {
239 0 : git_helper.close_on_error(log::Level::DEBUG);
240 0 : return ETRC_RET(rresult.get_result_code_int());
241 : }
242 :
243 17 : rresult = git_helper.open(path, esys::log::INFO);
244 17 : if (rresult.error()) return ETRC_RET(rresult.get_result_code_int());
245 :
246 17 : if (!get_branch().empty())
247 : {
248 4 : rresult = git_helper.fetch(get_log_level());
249 4 : if (rresult.error())
250 : {
251 0 : git_helper.close_on_error(log::Level::DEBUG);
252 0 : return ETRC_RET(rresult.get_result_code_int());
253 : }
254 : }
255 :
256 17 : return ETRC_RET(finish_workspace_root_clone(git_helper));
257 17 : }
258 :
259 1 : int SyncRepo::clone_workspace_root_init_fetch(GitHelper &git_helper, const std::string &url, const std::string &path)
260 : {
261 1 : int result = 0;
262 1 : ETRC_CALL_RET(result, url, path);
263 :
264 2 : git_helper.info("Init+fetch workspace root ...\n path : " + path + "\n url : " + url);
265 :
266 1 : Result rresult = git_helper.get_git()->init(path);
267 1 : if (rresult.error())
268 : {
269 0 : git_helper.error("Failed to init workspace root", rresult.get_result_code_int());
270 0 : git_helper.close_on_error(log::Level::DEBUG);
271 0 : return ETRC_RET(rresult.get_result_code_int());
272 : }
273 :
274 1 : rresult = git_helper.get_git()->add_remote("origin", url);
275 1 : if (rresult.error())
276 : {
277 0 : git_helper.error("Failed to add remote origin", rresult.get_result_code_int());
278 0 : git_helper.close_on_error(log::Level::DEBUG);
279 0 : return ETRC_RET(rresult.get_result_code_int());
280 : }
281 :
282 1 : rresult = git_helper.fetch("origin", get_log_level());
283 1 : if (rresult.error())
284 : {
285 0 : git_helper.close_on_error(log::Level::DEBUG);
286 0 : return ETRC_RET(rresult.get_result_code_int());
287 : }
288 :
289 1 : return ETRC_RET(finish_workspace_root_clone(git_helper));
290 1 : }
291 :
292 18 : int SyncRepo::finish_workspace_root_clone(GitHelper &git_helper)
293 : {
294 18 : int result = 0;
295 18 : ETRC_CALL_RET_NP(result);
296 :
297 18 : std::string branch_to_checkout = resolve_checkout_revision(git_helper);
298 18 : git_helper.debug(0, "branch_to_checkout = " + branch_to_checkout);
299 18 : if (branch_to_checkout.empty())
300 : {
301 0 : git_helper.error("No revision to checkout after workspace-root clone");
302 0 : git_helper.close_on_error(log::Level::DEBUG);
303 0 : return ETRC_RET(-1);
304 : }
305 :
306 18 : Result rresult = git_helper.checkout(branch_to_checkout, get_force(), log::Level::INFO);
307 18 : if (rresult.error())
308 : {
309 0 : git_helper.close_on_error(log::Level::DEBUG);
310 0 : return ETRC_RET(rresult.get_result_code_int());
311 : }
312 18 : rresult = git_helper.close(log::Level::DEBUG);
313 18 : return ETRC_RET(rresult.get_result_code_int());
314 36 : }
315 :
316 18 : std::string SyncRepo::resolve_checkout_revision(GitHelper &git_helper)
317 : {
318 18 : std::string rev = get_checkout_revision(git_helper);
319 :
320 18 : const std::string heads = "refs/heads/";
321 18 : if (rev.compare(0, heads.size(), heads) == 0) rev = rev.substr(heads.size());
322 36 : if (!rev.empty()) return rev;
323 :
324 : // Init-fetch leaves no default checkout (unlike clone). Pick a remote branch.
325 0 : git::Branches branches;
326 0 : Result rresult = git_helper.get_branches(branches, git::BranchType::REMOTE, log::Level::DEBUG);
327 0 : if (rresult.error() || branches.size() == 0) return {};
328 :
329 0 : auto short_name = [](const std::string &full) -> std::string {
330 0 : auto pos = full.rfind('/');
331 0 : if (pos == std::string::npos) return full;
332 0 : return full.substr(pos + 1);
333 : };
334 :
335 0 : auto find_named = [&](const std::string &want) -> std::string {
336 0 : for (const auto &branch : branches.get())
337 : {
338 0 : if (short_name(branch->get_name()) == want) return want;
339 : }
340 0 : return {};
341 0 : };
342 :
343 0 : rev = find_named("master");
344 0 : if (rev.empty()) rev = find_named("main");
345 0 : if (rev.empty()) rev = short_name(branches.get()[0]->get_name());
346 0 : return rev;
347 18 : }
348 :
349 13 : int SyncRepo::fetch_update()
350 : {
351 13 : int result_int = 0;
352 13 : ETRC_CALL_RET_NP(result_int);
353 :
354 13 : std::shared_ptr<GitHelper> git_helper = new_git_helper();
355 13 : PhaseCapture phase_capture(*this, *git_helper);
356 13 : git_helper->set_display_repo_idx(get_display_repo_idx());
357 :
358 13 : boost::filesystem::path path = get_config_folder()->get_workspace_path();
359 37 : if (get_repo()->get_path() != ".") path /= get_repo()->get_path();
360 :
361 13 : Result rresult = git_helper->open(path.string(), log::Level::INFO);
362 13 : if (rresult.error()) return ETRC_RET(rresult.get_result_code_int());
363 :
364 13 : bool dirty = false;
365 13 : rresult = git_helper->is_dirty(dirty, log::Level::DEBUG);
366 13 : if (rresult.error()) return ETRC_RET(rresult.get_result_code_int());
367 :
368 13 : if (dirty)
369 : {
370 0 : git_helper->warn("Changes detected in repo, no sync.");
371 0 : return ETRC_RET(0);
372 : }
373 :
374 13 : if (is_pinned()) return ETRC_RET(pin_sync(*git_helper.get()));
375 :
376 12 : if (get_branch().empty())
377 7 : return ETRC_RET(normal_sync(*git_helper.get()));
378 : else
379 5 : return ETRC_RET(branch_sync(*git_helper.get()));
380 26 : }
381 :
382 1 : int SyncRepo::pin_sync(GitHelper &git_helper)
383 : {
384 1 : int result_int = 0;
385 1 : ETRC_CALL_RET_NP(result_int);
386 :
387 1 : const std::string pin_rev = get_manifest_repo_revision();
388 1 : if (pin_rev.empty())
389 : {
390 0 : git_helper.error("Pinned repository has an empty revision.");
391 0 : return ETRC_RET(-1);
392 : }
393 :
394 1 : Result result = git_helper.fetch(log::Level::DEBUG);
395 1 : if (result.error())
396 : {
397 0 : git_helper.error("Fetch failed on the pinned git repo");
398 0 : return ETRC_RET(result.get_result_code_int());
399 : }
400 :
401 2 : git_helper.info("Checking out pinned revision " + pin_rev + " ...");
402 1 : result = git_helper.checkout(pin_rev, get_force(), log::Level::INFO);
403 1 : if (result.error())
404 : {
405 0 : git_helper.error("Failed to checkout pinned revision " + pin_rev + ".");
406 0 : return ETRC_RET(result.get_result_code_int());
407 : }
408 1 : git_helper.info("Pinned revision checkout completed.");
409 1 : return ETRC_RET(0);
410 2 : }
411 :
412 7 : int SyncRepo::normal_sync(GitHelper &git_helper)
413 : {
414 7 : int result_int = 0;
415 7 : ETRC_CALL_RET_NP(result_int);
416 :
417 7 : bool detached = false;
418 7 : Result result = git_helper.is_detached(detached, log::Level::DEBUG);
419 7 : if (result.error())
420 : {
421 0 : git_helper.error("Couldn't detect if the git repo is detached or not.");
422 0 : return ETRC_RET(result.get_result_code_int());
423 : }
424 :
425 7 : if (detached)
426 : {
427 : // Soft skip (same as dirty): detached HEADs are left alone on a normal sync
428 2 : git_helper.warn("Sync repo aborted: the git repo is detached.");
429 2 : return ETRC_RET(0);
430 : }
431 :
432 5 : result = git_helper.fetch(log::Level::DEBUG);
433 5 : if (result.error())
434 : {
435 0 : git_helper.error("Fetch failed on the git repo");
436 0 : return ETRC_RET(result.get_result_code_int());
437 : }
438 :
439 5 : git::Branches branches;
440 5 : result = git_helper.get_branches(branches, git::BranchType::LOCAL, log::Level::DEBUG);
441 5 : if (result.error())
442 : {
443 0 : git_helper.error("Couldn't get the list of local branches");
444 0 : return ETRC_RET(result.get_result_code_int());
445 : }
446 :
447 5 : branches.sort();
448 :
449 10 : if (branches.get_head() == nullptr)
450 : {
451 0 : git_helper.error("Couldn't get the HEAD.");
452 0 : return ETRC_RET(-4);
453 : }
454 :
455 5 : std::vector<std::string> refs;
456 5 : git::MergeAnalysisResult merge_analysis_result;
457 5 : std::vector<git::CommitHash> commits;
458 :
459 5 : refs.push_back(branches.get_head()->get_remote_branch());
460 :
461 5 : result = git_helper.merge_analysis(refs, merge_analysis_result, commits, log::Level::DEBUG);
462 5 : if (result.error())
463 : {
464 0 : git_helper.error("Merge analysis failed.");
465 0 : return ETRC_RET(-5);
466 : }
467 :
468 5 : if (merge_analysis_result == git::MergeAnalysisResult::UP_TO_DATE)
469 : {
470 4 : git_helper.info("Git repo up to date.");
471 4 : return ETRC_RET(0);
472 : }
473 1 : if (merge_analysis_result != git::MergeAnalysisResult::FASTFORWARD)
474 : {
475 0 : git_helper.warn("Sync manifest aborted: can't be fastforwarded.");
476 0 : return ETRC_RET(-6);
477 : }
478 :
479 : // For a fastforward, there should be only one commit
480 1 : if (commits.size() != 1)
481 : {
482 0 : git_helper.error("Fast forward failed.");
483 0 : return ETRC_RET(-7);
484 : }
485 :
486 1 : git_helper.info("Fast forwarding git repo ...");
487 :
488 1 : result = git_helper.fastforward(commits[0], log::Level::DEBUG);
489 1 : if (result.error())
490 : {
491 0 : git_helper.error("Fast forward failed.");
492 0 : return ETRC_RET(-8);
493 : }
494 1 : git_helper.info("Fast forward completed.");
495 1 : return ETRC_RET(0);
496 7 : }
497 :
498 5 : int SyncRepo::branch_sync(GitHelper &git_helper)
499 : {
500 5 : int result_int = false;
501 5 : ETRC_CALL_RET_NP(result_int);
502 :
503 5 : Result result = git_helper.fetch(log::Level::DEBUG);
504 5 : if (result.error())
505 : {
506 0 : git_helper.error("Fetch failed on the git repo");
507 0 : return ETRC_RET(result.get_result_code_int());
508 : }
509 :
510 5 : if (!has_branch(git_helper, get_branch()))
511 : {
512 : // Single-branch clone (ADR-0030) only fetched the first tip. Ask for this branch.
513 4 : const std::string spec = "+refs/heads/" + get_branch() + ":refs/remotes/origin/" + get_branch();
514 2 : result = git_helper.fetch_refspec(spec, log::Level::DEBUG);
515 2 : if (result.error()) git_helper.debug(0, "Prefer-branch fetch of " + get_branch() + " failed");
516 2 : }
517 :
518 5 : if (!has_branch(git_helper, get_branch())) return ETRC_RET(normal_sync(git_helper));
519 :
520 5 : result = git_helper.checkout(get_branch(), get_force(), log::Level::DEBUG);
521 5 : if (result.ok())
522 10 : info("Checkout branch " + get_branch() + ".");
523 : else
524 0 : error("Failed to checkout branch " + get_branch() + ".");
525 5 : return ETRC_RET(result.get_result_code_int());
526 5 : }
527 :
528 0 : void SyncRepo::set_log_level(log::Level log_level)
529 : {
530 0 : m_log_level = log_level;
531 0 : }
532 :
533 32 : log::Level SyncRepo::get_log_level()
534 : {
535 32 : return m_log_level;
536 : }
537 :
538 152 : void SyncRepo::set_repo_idx(std::size_t repo_idx)
539 : {
540 152 : m_repo_idx = repo_idx;
541 152 : }
542 :
543 0 : std::size_t SyncRepo::get_repo_idx() const
544 : {
545 0 : return m_repo_idx;
546 : }
547 :
548 321 : std::size_t &SyncRepo::get_repo_idx()
549 : {
550 321 : return m_repo_idx;
551 : }
552 :
553 152 : void SyncRepo::set_display_repo_idx(bool display_repo_idx)
554 : {
555 152 : m_display_repo_idx = display_repo_idx;
556 152 : }
557 :
558 13 : bool SyncRepo::get_display_repo_idx() const
559 : {
560 13 : return m_display_repo_idx;
561 : }
562 :
563 139 : std::string SyncRepo::get_repo_url()
564 : {
565 139 : assert(get_repo() != nullptr);
566 139 : assert(get_repo()->get_location() != nullptr);
567 :
568 139 : std::string url;
569 139 : if (!get_alt_address())
570 417 : url = get_repo()->get_location()->get_address();
571 : else
572 0 : url = get_repo()->get_location()->get_alt_address();
573 :
574 278 : url += "/" + get_repo()->get_name();
575 :
576 139 : return url;
577 0 : }
578 :
579 34 : void SyncRepo::set_branch(const std::string &branch)
580 : {
581 34 : m_branch = branch;
582 34 : }
583 :
584 389 : const std::string &SyncRepo::get_branch() const
585 : {
586 389 : return m_branch;
587 : }
588 :
589 152 : void SyncRepo::set_alt_address(bool alt_address)
590 : {
591 152 : m_alt_address = alt_address;
592 152 : }
593 :
594 139 : bool SyncRepo::get_alt_address() const
595 : {
596 139 : return m_alt_address;
597 : }
598 :
599 155 : void SyncRepo::set_manifest(std::shared_ptr<Manifest> manifest)
600 : {
601 155 : m_manifest = manifest;
602 155 : }
603 :
604 0 : std::shared_ptr<Manifest> SyncRepo::get_manifest() const
605 : {
606 0 : return m_manifest;
607 : }
608 :
609 0 : void SyncRepo::set_force(bool force)
610 : {
611 0 : m_force = force;
612 0 : }
613 :
614 24 : bool SyncRepo::get_force() const
615 : {
616 24 : return m_force;
617 : }
618 :
619 152 : void SyncRepo::set_workspace_root_clone_method(WorkspaceRootCloneMethod method)
620 : {
621 152 : m_workspace_root_clone_method = method;
622 152 : }
623 :
624 18 : WorkspaceRootCloneMethod SyncRepo::get_workspace_root_clone_method() const
625 : {
626 18 : return m_workspace_root_clone_method;
627 : }
628 :
629 152 : void SyncRepo::set_clone_options(const git::CloneOptions &options)
630 : {
631 152 : m_clone_options = options;
632 152 : }
633 :
634 121 : const git::CloneOptions &SyncRepo::get_clone_options() const
635 : {
636 121 : return m_clone_options;
637 : }
638 :
639 152 : void SyncRepo::set_update_submodules(bool update)
640 : {
641 152 : m_update_submodules = update;
642 152 : }
643 :
644 152 : bool SyncRepo::get_update_submodules() const
645 : {
646 152 : return m_update_submodules;
647 : }
648 :
649 152 : int SyncRepo::maybe_update_submodules(const std::string &abs_path)
650 : {
651 152 : int result = 0;
652 152 : ETRC_CALL_RET(result, abs_path);
653 :
654 152 : if (!get_update_submodules()) return ETRC_RET(0);
655 :
656 0 : auto git = get_git();
657 0 : if (git == nullptr) return ETRC_RET(-1);
658 :
659 0 : Result rresult = git->update_submodules(abs_path, true);
660 0 : if (rresult.error())
661 : {
662 0 : error("Failed to update Git submodules for '" + abs_path + "'");
663 0 : return ETRC_RET(rresult.get_result_code_int());
664 : }
665 0 : return ETRC_RET(0);
666 152 : }
667 :
668 : } // namespace esys::repo::manifest
|