LCOV - code coverage report
Current view: top level - src/esys/repo/manifest - sync_manifest.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 92 171 53.8 %
Date: 2026-08-01 10:43:40 Functions: 14 20 70.0 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/manifest/sync_manifest.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 2021-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/sync.h"
      20             : 
      21             : #include <esys/trace/call.h>
      22             : #include <esys/trace/macros.h>
      23             : 
      24             : namespace esys::repo::manifest
      25             : {
      26             : 
      27          20 : Sync::Sync()
      28          20 :     : log::User()
      29             : {
      30          20 : }
      31             : 
      32          60 : Sync::~Sync() = default;
      33             : 
      34           2 : void Sync::set_branch(const std::string &branch)
      35             : {
      36           2 :     m_branch = branch;
      37           2 : }
      38             : 
      39          25 : const std::string &Sync::get_branch() const
      40             : {
      41          25 :     return m_branch;
      42             : }
      43             : 
      44           0 : void Sync::set_force(bool force)
      45             : {
      46           0 :     m_force = force;
      47           0 : }
      48             : 
      49           1 : bool Sync::get_force() const
      50             : {
      51           1 :     return m_force;
      52             : }
      53             : 
      54           0 : int Sync::is_manifest_modified(bool &modified)
      55             : {
      56           0 :     int result_int = 0;
      57           0 :     ETRC_CALL_RET_NP(result_int);
      58             : 
      59           0 :     bool dirty = false;
      60           0 :     modified = false;
      61             : 
      62           0 :     if (get_git()->is_dirty(dirty).error()) return ETRC_RET(GIT_IS_DIRTY_FAILED);
      63             : 
      64           0 :     if (!dirty) return ETRC_RET(0);
      65             : 
      66           0 :     git::RepoStatus status;
      67             : 
      68           0 :     Result result = get_git()->get_status(status);
      69           0 :     if (result.error()) return ETRC_RET(GIT_GET_STATUS_FAILED);
      70             : 
      71           0 :     if (get_config_folder() == nullptr) return ETRC_RET(CONFIG_FOLDER_IS_NULL);
      72           0 :     auto config = get_config_folder()->get_config();
      73           0 :     if (config == nullptr) return ETRC_RET(CONFIG_IS_NULL);
      74             : 
      75           0 :     auto rel_file_name = get_config_folder()->get_manifest_rel_file_name();
      76             : 
      77           0 :     auto file_status_it = status.get_map_file_status().find(rel_file_name);
      78           0 :     if (file_status_it == status.get_map_file_status().end()) return ETRC_RET(0);
      79             : 
      80           0 :     auto file_status = file_status_it->second;
      81             : 
      82           0 :     warn("The manifest file has local changes!");
      83           0 :     return ETRC_RET(0);
      84           0 : }
      85             : 
      86          20 : std::shared_ptr<GitHelper> Sync::new_git_helper()
      87             : {
      88          40 :     auto git_helper = std::make_shared<GitHelper>(get_git(), get_logger_if());
      89          60 :     get_git()->set_logger_if(git_helper);
      90          20 :     return git_helper;
      91           0 : }
      92             : 
      93          20 : Result Sync::run()
      94             : {
      95          20 :     Result result;
      96          20 :     ETRC_CALL_RET_NP(result);
      97             : 
      98          40 :     if (get_git() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_GIT_IS_NULLPTR));
      99          40 :     if (get_git()->is_open()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_GIT_IS_NOT_OPENED));
     100             : 
     101          20 :     auto git_helper = new_git_helper();
     102             : 
     103          20 :     result = git_helper->open(get_config_folder()->get_manifest_repo_path(), get_log_level());
     104          20 :     if (result.error())
     105             :     {
     106           0 :         std::string err_str = "Couldn't open the manifest git repo";
     107           0 :         error(err_str);
     108           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_GIT_OPEN_FAILED, err_str));
     109           0 :     }
     110          20 :     bool dirty = false;
     111          20 :     if (git_helper->is_dirty(dirty, get_log_level()).error())
     112           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_GIT_IS_DIRTY_FAILED));
     113          20 :     if (dirty)
     114             :     {
     115           0 :         std::string err_str = "Sync manifest aborted: found changes in the git repo.";
     116           0 :         warn(err_str);
     117           0 :         git_helper->close_on_error(log::Level::DEBUG);
     118           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMDSYNC_ABORTED_FOUND_CHANGES, err_str));
     119           0 :     }
     120             : 
     121          20 :     result = git_helper->fetch(get_log_level());
     122          20 :     if (result.error())
     123             :     {
     124           0 :         std::string err_str = "Fetch failed on the manifest git repo";
     125           0 :         error(err_str);
     126           0 :         git_helper->close_on_error(log::Level::DEBUG);
     127           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_GIT_FETCH_FAILED, err_str));
     128           0 :     }
     129             : 
     130          38 :     if (get_branch().empty()) return ETRC_RET(ESYSREPO_RESULT(normal_sync(*git_helper)));
     131           4 :     return ETRC_RET(ESYSREPO_RESULT(branch_sync(*git_helper)));
     132          20 : }
     133             : 
     134          19 : Result Sync::normal_sync(GitHelper &git_helper)
     135             : {
     136          19 :     Result result;
     137          19 :     ETRC_CALL_RET_NP(result);
     138             : 
     139          19 :     bool detached = false;
     140          19 :     result = git_helper.is_detached(detached, get_log_level());
     141          19 :     if (result.error())
     142             :     {
     143           0 :         error("Couldn't detect if the git repo is detached or not.");
     144           0 :         git_helper.close_on_error(log::Level::DEBUG);
     145           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     146             :     }
     147             : 
     148          19 :     if (detached)
     149             :     {
     150           1 :         warn("Sync manifest aborted: the git repo is detached.");
     151           1 :         git_helper.close_on_error(log::Level::DEBUG);
     152           2 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     153             :     }
     154             : 
     155          18 :     git::Branches branches;
     156             : 
     157          18 :     result = git_helper.get_branches(branches, git::BranchType::LOCAL, get_log_level());
     158          18 :     if (result.error())
     159             :     {
     160           0 :         git_helper.close_on_error(log::Level::DEBUG);
     161           0 :         return ETRC_RET(ESYSREPO_RESULT(result));
     162             :     }
     163             : 
     164          36 :     if (branches.get_head() == nullptr)
     165             :     {
     166           0 :         std::string err_str = "Couldn't get the HEAD.";
     167           0 :         error(err_str);
     168           0 :         git_helper.close_on_error(log::Level::DEBUG);
     169           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_GIT_GET_HEAD_FAILED, err_str));
     170           0 :     }
     171             : 
     172          18 :     std::vector<std::string> refs;
     173          18 :     git::MergeAnalysisResult merge_analysis_result;
     174          18 :     std::vector<git::CommitHash> commits;
     175             : 
     176          18 :     refs.push_back(branches.get_head()->get_remote_branch());
     177             : 
     178          18 :     result = git_helper.merge_analysis(refs, merge_analysis_result, commits, get_log_level());
     179          18 :     if (result.error())
     180             :     {
     181           0 :         std::string err_str = "Merge analysis failed.";
     182           0 :         error(err_str);
     183           0 :         git_helper.close_on_error(log::Level::DEBUG);
     184           0 :         return ETRC_RET(ESYSREPO_RESULT(result, err_str));
     185           0 :     }
     186             : 
     187          18 :     if (merge_analysis_result == git::MergeAnalysisResult::UP_TO_DATE)
     188             :     {
     189          17 :         info("Manifest up to date.");
     190          17 :         git_helper.close_on_error(log::Level::DEBUG);
     191          34 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     192             :     }
     193           1 :     if (merge_analysis_result != git::MergeAnalysisResult::FASTFORWARD)
     194             :     {
     195           0 :         std::string err_str = "Sync manifest aborted: can't be fastforwarded.";
     196           0 :         warn(err_str);
     197           0 :         git_helper.close_on_error(log::Level::DEBUG);
     198           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMDSYNC_GIT_CAN_NOT_BE_FAST_FORWARDED, err_str));
     199           0 :     }
     200             : 
     201             :     // For a fastforward, there should be only one commit
     202           1 :     if (commits.size() != 1)
     203             :     {
     204           0 :         std::string err_str = "fastforward failed.";
     205           0 :         error(err_str);
     206           0 :         git_helper.close_on_error(log::Level::DEBUG);
     207           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_GIT_MORE_THAN_ONE_COMMIT, err_str));
     208           0 :     }
     209             : 
     210           1 :     info("Fastforward manifest ...");
     211             : 
     212           1 :     result = git_helper.fastforward(commits[0], get_log_level());
     213           1 :     if (result.error())
     214             :     {
     215           0 :         std::string err_str = "Fastforward failed.";
     216           0 :         error(err_str);
     217           0 :         git_helper.close_on_error(log::Level::DEBUG);
     218           0 :         return ETRC_RET(ESYSREPO_RESULT(result, err_str));
     219           0 :     }
     220           1 :     info("Fastforward manifest completed.");
     221           1 :     result = git_helper.close(log::Level::DEBUG);
     222           2 :     return ETRC_RET(ESYSREPO_RESULT(result));
     223          19 : }
     224             : 
     225           2 : Result Sync::branch_sync(GitHelper &git_helper)
     226             : {
     227           2 :     Result result;
     228           2 :     ETRC_CALL_RET_NP(result);
     229             : 
     230           2 :     result = git_helper.fetch(get_log_level());
     231           2 :     if (result.error())
     232             :     {
     233           0 :         git_helper.close_on_error(log::Level::DEBUG);
     234           0 :         return ETRC_RET(ESYSREPO_RESULT(result));
     235             :     }
     236             : 
     237           2 :     Result_t<bool> has_branch = git_helper.has_branch(get_branch(), git::BranchType::LOCAL, get_log_level());
     238             : 
     239           2 :     if (has_branch.error())
     240             :     {
     241           2 :         warn("Manifest: error when trying to know if the following branch exits : " + get_branch() + ".");
     242           2 :         return ETRC_RET(ESYSREPO_RESULT(normal_sync(git_helper)));
     243             :         // return ESYSREPO_RESULT(has_branch);
     244             :     }
     245             : 
     246           1 :     if (!has_branch) return ETRC_RET(ESYSREPO_RESULT(normal_sync(git_helper)));
     247             : 
     248           1 :     result = git_helper.checkout(get_branch(), get_force(), get_log_level());
     249           1 :     if (result.ok())
     250           2 :         info("Manifest: checkout branch " + get_branch() + ".");
     251             :     else
     252           0 :         error("Manifest: failed to checkout branch " + get_branch() + ".");
     253           1 :     result = git_helper.close(log::Level::DEBUG);
     254           2 :     return ETRC_RET(ESYSREPO_RESULT(result));
     255           2 : }
     256             : 
     257           0 : int Sync::process_repo()
     258             : {
     259           0 :     return NOT_IMPLEMENTED;
     260             : }
     261             : 
     262           0 : int Sync::fetch_update()
     263             : {
     264           0 :     return NOT_IMPLEMENTED;
     265             : }
     266             : 
     267          20 : void Sync::set_git(std::shared_ptr<GitBase> git)
     268             : {
     269          20 :     m_git = git;
     270          20 : }
     271             : 
     272          80 : std::shared_ptr<GitBase> Sync::get_git() const
     273             : {
     274          80 :     return m_git;
     275             : }
     276             : 
     277          20 : void Sync::set_config_folder(std::shared_ptr<ConfigFolder> config_folder)
     278             : {
     279          20 :     m_config_folder = config_folder;
     280          20 : }
     281             : 
     282          20 : std::shared_ptr<ConfigFolder> Sync::get_config_folder()
     283             : {
     284          20 :     return m_config_folder;
     285             : }
     286             : 
     287           0 : void Sync::set_log_level(log::Level log_level)
     288             : {
     289           0 :     m_log_level = log_level;
     290           0 : }
     291             : 
     292         121 : log::Level Sync::get_log_level()
     293             : {
     294         121 :     return m_log_level;
     295             : }
     296             : 
     297             : } // namespace esys::repo::manifest

Generated by: LCOV version 1.14