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