LCOV - code coverage report
Current view: top level - src/esys/repo/exe - cmdsync.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 135 314 43.0 %
Date: 2026-09-26 15:38:18 Functions: 20 32 62.5 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/exe/cmdsync.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 2020-2022 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/exe/cmdsync.h"
      20             : #include "esys/repo/manifest/capture.h"
      21             : #include "esys/repo/manifest/sync.h"
      22             : #include "esys/repo/manifest/syncrepos.h"
      23             : #include "esys/repo/resultcode.h"
      24             : #include "esys/repo/tui/is_tty.h"
      25             : #include "esys/repo/tui/run_compact_sync_tui.h"
      26             : 
      27             : #include <esys/trace/call.h>
      28             : #include <esys/trace/macros.h>
      29             : 
      30             : #include <boost/filesystem.hpp>
      31             : 
      32             : #include <cstdlib>
      33             : #include <cstring>
      34             : #include <iostream>
      35             : #include <sstream>
      36             : 
      37             : namespace esys::repo::exe
      38             : {
      39             : 
      40             : namespace
      41             : {
      42             : 
      43          26 : bool env_flag_enabled(const char *name)
      44             : {
      45          26 :     const char *value = std::getenv(name);
      46          26 :     if (value == nullptr || value[0] == '\0') return false;
      47           0 :     if (std::strcmp(value, "1") == 0) return true;
      48           0 :     if (std::strcmp(value, "true") == 0) return true;
      49           0 :     if (std::strcmp(value, "TRUE") == 0) return true;
      50           0 :     if (std::strcmp(value, "yes") == 0) return true;
      51           0 :     if (std::strcmp(value, "YES") == 0) return true;
      52           0 :     if (std::strcmp(value, "on") == 0) return true;
      53           0 :     if (std::strcmp(value, "ON") == 0) return true;
      54             :     return false;
      55             : }
      56             : 
      57             : } // namespace
      58             : 
      59          39 : CmdSync::CmdSync()
      60          78 :     : Cmd("Sync")
      61             : {
      62          39 : }
      63             : 
      64          39 : CmdSync::~CmdSync() = default;
      65             : 
      66           1 : void CmdSync::set_force(bool force)
      67             : {
      68           1 :     m_force = force;
      69           1 : }
      70             : 
      71          27 : bool CmdSync::get_force() const
      72             : {
      73          27 :     return m_force;
      74             : }
      75             : 
      76          28 : void CmdSync::set_branch(const std::string &branch)
      77             : {
      78          28 :     m_branch = branch;
      79          28 : }
      80             : 
      81          93 : const std::string &CmdSync::get_branch() const
      82             : {
      83          93 :     return m_branch;
      84             : }
      85             : 
      86           2 : void CmdSync::set_rev_set(const std::string &rev_set)
      87             : {
      88           2 :     m_rev_set = rev_set;
      89           2 : }
      90             : 
      91          54 : const std::string &CmdSync::get_rev_set() const
      92             : {
      93          54 :     return m_rev_set;
      94             : }
      95             : 
      96          26 : Result CmdSync::apply_revision_set_selection()
      97             : {
      98          26 :     Result result;
      99          26 :     ETRC_CALL_RET_NP(result);
     100             : 
     101          52 :     if (get_manifest() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::MANIFEST_IS_NULLPTR));
     102             : 
     103          26 :     std::string preferred = get_rev_set();
     104         104 :     if (preferred.empty() && get_config_folder() != nullptr && get_config_folder()->get_config() != nullptr)
     105         104 :         preferred = get_config_folder()->get_config()->get_revision_set();
     106             : 
     107          26 :     result = get_manifest()->select_revision_set(preferred);
     108          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     109             : 
     110          26 :     if (!get_rev_set().empty() && get_config_folder() != nullptr)
     111             :     {
     112           0 :         auto cfg = get_config_folder()->get_or_new_config();
     113           0 :         cfg->set_revision_set(get_rev_set());
     114           0 :         result = get_config_folder()->write_config_file();
     115           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     116           0 :     }
     117             : 
     118          52 :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     119          26 : }
     120             : 
     121          26 : Result CmdSync::apply_prefer_branch()
     122             : {
     123          26 :     Result result;
     124          26 :     ETRC_CALL_RET_NP(result);
     125             : 
     126          52 :     if (get_config_folder() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     127             : 
     128          26 :     if (get_branch().empty())
     129             :     {
     130          66 :         if (get_config_folder()->get_config() != nullptr)
     131          66 :             set_branch(get_config_folder()->get_config()->get_prefer_branch());
     132          44 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     133             :     }
     134             : 
     135           4 :     auto cfg = get_config_folder()->get_or_new_config();
     136           4 :     cfg->set_prefer_branch(get_branch());
     137           4 :     result = get_config_folder()->write_config_file();
     138           4 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     139           8 :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     140          26 : }
     141             : 
     142          26 : Result CmdSync::apply_revision_pins()
     143             : {
     144          26 :     Result result;
     145          26 :     ETRC_CALL_RET_NP(result);
     146             : 
     147          52 :     if (get_manifest() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::MANIFEST_IS_NULLPTR));
     148          52 :     if (get_config_folder() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::CONFIG_FOLDER_IS_NULLPTR));
     149             : 
     150             :     // open() already loaded pins; refresh in case they changed mid-session
     151          26 :     result = get_config_folder()->load_pins_file();
     152          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     153             : 
     154          78 :     get_manifest()->set_revision_pins(get_config_folder()->get_or_new_revision_pins());
     155          52 :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     156          26 : }
     157             : 
     158           1 : void CmdSync::set_alt_address(bool alt_address)
     159             : {
     160           1 :     m_alt_address = alt_address;
     161           1 : }
     162           1 : bool CmdSync::get_alt_address() const
     163             : {
     164           1 :     return m_alt_address;
     165             : }
     166             : 
     167           0 : void CmdSync::set_multi(bool multi)
     168             : {
     169           0 :     m_multi = multi;
     170           0 : }
     171             : 
     172          26 : bool CmdSync::get_multi() const
     173             : {
     174          26 :     return m_multi;
     175             : }
     176             : 
     177           0 : void CmdSync::set_tui(bool tui)
     178             : {
     179           0 :     m_tui = tui;
     180           0 : }
     181             : 
     182          26 : bool CmdSync::get_tui() const
     183             : {
     184          26 :     return m_tui;
     185             : }
     186             : 
     187           0 : void CmdSync::set_tui_demo(bool tui_demo)
     188             : {
     189           0 :     m_tui_demo = tui_demo;
     190           0 :     if (tui_demo) m_tui = true;
     191           0 : }
     192             : 
     193           0 : bool CmdSync::get_tui_demo() const
     194             : {
     195           0 :     return m_tui_demo;
     196             : }
     197             : 
     198           3 : void CmdSync::set_recurse_submodules(manifest::RecurseSubmodules recurse)
     199             : {
     200           3 :     m_recurse_submodules = recurse;
     201           3 : }
     202             : 
     203          29 : manifest::RecurseSubmodules CmdSync::get_recurse_submodules() const
     204             : {
     205          29 :     return m_recurse_submodules;
     206             : }
     207             : 
     208          26 : Result CmdSync::sync_manifest()
     209             : {
     210          26 :     Result result;
     211          26 :     ETRC_CALL_RET_NP(result);
     212             : 
     213          26 :     manifest::Sync sync;
     214             : 
     215          52 :     if (get_config_folder() == nullptr) return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_CONFIG_FOLDER_NULLPTR));
     216             : 
     217          26 :     auto config = get_config_folder()->get_config();
     218          26 :     if (config != nullptr && !config->get_manifest_local().empty())
     219             :     {
     220           1 :         info("Local manifest: skip git update of the manifest.");
     221           2 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     222             :     }
     223             : 
     224          25 :     sync.set_config_folder(get_config_folder());
     225          25 :     sync.set_git(get_git());
     226          25 :     sync.set_logger_if(get_logger_if());
     227          25 :     if (!get_branch().empty()) sync.set_branch(get_branch());
     228             : 
     229          50 :     return ETRC_RET(ESYSREPO_RESULT(sync.run()));
     230          26 : }
     231             : 
     232           0 : Result CmdSync::handle_capture_item(std::shared_ptr<manifest::Capture::Item> item)
     233             : {
     234           0 :     Result result;
     235           0 :     ETRC_CALL_RET(result, item);
     236             : 
     237           0 :     if (get_workspace_path().empty()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::CMD_WORKSPACE_PATH_IS_EMPTY));
     238             : 
     239           0 :     boost::filesystem::path git_path_folder = get_workspace_path();
     240           0 :     git_path_folder /= item->get_path();
     241           0 :     git_path_folder = git_path_folder.lexically_normal().make_preferred();
     242             : 
     243           0 :     auto git_helper = new_git_helper();
     244           0 :     result = git_helper->open(git_path_folder.string(), log::Level::DEBUG);
     245           0 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     246             : 
     247           0 :     GitHelper::AutoClose auto_close(git_helper.get());
     248             : 
     249           0 :     bool dirty = false;
     250           0 :     result = git_helper->is_dirty(dirty, log::Level::DEBUG);
     251           0 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     252             : 
     253             :     // If there is a remote defined, create it and fetch it
     254           0 :     if (!item->get_remote_name().empty())
     255             :     {
     256           0 :         result = git_helper->get_git()->add_remote(item->get_remote_name(), item->get_remote_url());
     257           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     258             : 
     259           0 :         result = git_helper->get_git()->fetch(item->get_remote_name());
     260           0 :         if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     261             :     }
     262             : 
     263             :     // Checkout the new revision
     264           0 :     result = git_helper->checkout(item->get_revision(), false, log::Level::DEBUG);
     265           0 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     266             : 
     267           0 :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     268           0 : }
     269             : 
     270           0 : Result CmdSync::do_multi()
     271             : {
     272           0 :     Result result;
     273           0 :     ETRC_CALL_RET_NP(result);
     274             : 
     275             :     // First we need to get the working folder
     276           0 :     std::string folder_path;
     277             : 
     278           0 :     if (!get_folder().empty())
     279           0 :         folder_path = get_folder();
     280           0 :     else if (!get_workspace_path().empty())
     281           0 :         folder_path = get_workspace_path();
     282             :     else
     283           0 :         folder_path = boost::filesystem::current_path().string();
     284           0 :     if (folder_path.empty()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR));
     285             : 
     286           0 :     auto git_folder_path = find_git_root_path(folder_path);
     287           0 :     auto git_helper = new_git_helper();
     288             : 
     289           0 :     set_git_folder_path(git_folder_path);
     290           0 :     result = git_helper->open(git_folder_path, log::Level::DEBUG);
     291           0 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     292             : 
     293           0 :     GitHelper::AutoClose auto_close(git_helper.get());
     294             : 
     295           0 :     int result_int = git_helper->get_git()->add_notes_ref("esysrepo");
     296           0 :     if (result_int < 0) return ETRC_RET(ESYSREPO_RESULT(ResultCode::GIT_RAW_INT_ERROR, result_int));
     297             : 
     298           0 :     result = git_helper->get_git()->fetch_all_notes();
     299           0 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     300             : 
     301           0 :     git::Commit last_commit;
     302             : 
     303           0 :     result = git_helper->get_git()->get_last_commit(last_commit, true);
     304           0 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     305             : 
     306           0 :     std::vector<std::shared_ptr<git::Note>> notes;
     307           0 :     result_int = last_commit.get_notes("esysrepo", notes);
     308           0 :     if (result_int < 0) return ETRC_RET(ESYSREPO_RESULT(ResultCode::GIT_RAW_INT_ERROR, result_int));
     309             : 
     310           0 :     std::ostringstream oss;
     311             : 
     312           0 :     oss << "Found " << notes.size() << " esysrepo multi note.";
     313             : 
     314           0 :     info(oss.str());
     315             : 
     316           0 :     if (notes.empty()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     317           0 :     if (notes.size() != 1) return ETRC_RET(ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR));
     318             : 
     319           0 :     std::string note_text = notes[0]->get_message();
     320           0 :     auto capture = std::make_shared<manifest::Capture>();
     321           0 :     result = load_capture(capture, note_text);
     322           0 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     323             : 
     324           0 :     oss.str("");
     325           0 :     print_capture(oss, capture);
     326           0 :     info(oss.str());
     327             : 
     328           0 :     Result rresult;
     329           0 :     for (auto repo : capture->get_items())
     330             :     {
     331           0 :         result = handle_capture_item(repo);
     332           0 :         if (result.error())
     333             :         {
     334           0 :             std::ostringstream e_oss;
     335             : 
     336           0 :             e_oss << "repo '" << repo->get_path() << "' could set revivions '" << repo->get_revision() << "'";
     337           0 :             error(e_oss.str());
     338           0 :             rresult.add(result);
     339           0 :         }
     340           0 :     }
     341             : 
     342           0 :     return ETRC_RET(ESYSREPO_RESULT(rresult));
     343           0 : }
     344             : 
     345           0 : void CmdSync::set_git_folder_path(const std::string &git_folder_path)
     346             : {
     347           0 :     m_git_folder_path = git_folder_path;
     348           0 : }
     349             : 
     350           0 : const std::string &CmdSync::get_git_folder_path() const
     351             : {
     352           0 :     return m_git_folder_path;
     353             : }
     354             : 
     355          26 : Result CmdSync::impl_run()
     356             : {
     357          26 :     Result result;
     358          26 :     ETRC_CALL_RET_NP(result);
     359             : 
     360          26 :     if (env_flag_enabled("ESYSREPO_TUI_DEMO")) set_tui_demo(true);
     361             : 
     362          26 :     if (get_tui()) return ETRC_RET(ESYSREPO_RESULT(impl_run_tui()));
     363             : 
     364          26 :     if (get_force()) warn("Option --force-sync is not implemented yet");
     365             : 
     366          26 :     result = default_handling_folder_workspace();
     367          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     368             : 
     369          26 :     result = open_esysrepo_folder();
     370          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     371             : 
     372          26 :     result = apply_prefer_branch();
     373          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     374             : 
     375          26 :     result = sync_manifest();
     376          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     377             : 
     378          26 :     result = load_manifest();
     379          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     380             : 
     381          26 :     result = apply_revision_set_selection();
     382          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     383             : 
     384          26 :     result = apply_revision_pins();
     385          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     386             : 
     387          26 :     manifest::SyncRepos sync_repos;
     388             : 
     389          26 :     if (!get_branch().empty()) sync_repos.set_branch(get_branch());
     390             : 
     391          26 :     if (get_sub_args().size() != 0)
     392           4 :         sync_repos.set_folders_to_sync(get_sub_args());
     393          22 :     else if (get_groups().size() != 0)
     394             :     {
     395           2 :         std::vector<std::string> repos;
     396             : 
     397           4 :         for (auto &group : get_groups())
     398             :         {
     399           2 :             auto group_ptr = get_manifest()->get_groups().find_group_by_name(group);
     400           2 :             if (group_ptr == nullptr)
     401             :             {
     402             :                 //! \TODO
     403           0 :                 continue;
     404             :             }
     405           8 :             for (auto repo : group_ptr->get_repos())
     406             :             {
     407           6 :                 repos.push_back(repo->get_path());
     408           6 :             }
     409           2 :         }
     410             : 
     411           2 :         sync_repos.set_folders_to_sync(repos);
     412           2 :     }
     413             : 
     414          26 :     if (get_debug()) sync_repos.set_log_level(log::Level::DEBUG);
     415             : 
     416          26 :     sync_repos.set_job_count(get_job_count());
     417          26 :     sync_repos.set_logger_if(get_logger_if());
     418          26 :     sync_repos.set_config_folder(get_config_folder());
     419          26 :     sync_repos.set_git(get_git());
     420          26 :     sync_repos.set_manifest(get_manifest());
     421          26 :     sync_repos.set_tui(false);
     422          26 :     sync_repos.set_recurse_submodules(get_recurse_submodules());
     423             : 
     424          26 :     get_git()->detect_ssh_agent(true);
     425             : 
     426          26 :     result = sync_repos.run();
     427          26 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     428             : 
     429          52 :     if (!get_multi()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     430           0 :     return ETRC_RET(ESYSREPO_RESULT(do_multi()));
     431          26 : }
     432             : 
     433           0 : Result CmdSync::impl_run_tui()
     434             : {
     435           0 :     Result result;
     436           0 :     ETRC_CALL_RET_NP(result);
     437             : 
     438             : #ifndef ESYSREPO_HAVE_TUI
     439             :     error("--tui requested but esysrepo was built without FTXUI (Conan with_tui / ESYSREPO_WITH_TUI)");
     440             :     return ETRC_RET(ESYSREPO_RESULT(ResultCode::NOT_IMPLEMENTED));
     441             : #else
     442           0 :     if (!tui::is_tty())
     443             :     {
     444           0 :         const char *msg =
     445             :             "--tui requires a real Win32 console (cmd.exe, PowerShell, or Windows "
     446             :             "Terminal). Git Bash/mintty and redirected stdout are not supported.";
     447           0 :         error(msg);
     448           0 :         std::cerr << "ERROR: " << msg << std::endl;
     449           0 :         return ETRC_RET(ESYSREPO_RESULT(ResultCode::GENERIC_ERROR));
     450             :     }
     451             : 
     452           0 :     if (get_force()) warn("Option --force-sync is not implemented yet");
     453             : 
     454           0 :     const std::size_t ui_workers =
     455           0 :         get_job_count() <= 0 ? std::size_t{1} : static_cast<std::size_t>(get_job_count());
     456             : 
     457           0 :     auto work = [this](progress::ProgressSession &session, tui::SyncTuiControl &control) -> Result {
     458           0 :         auto prev_logger = get_logger_if();
     459           0 :         if (control.logger) set_logger_if(control.logger);
     460             : 
     461           0 :         auto restore_logger = [&]() {
     462           0 :             if (prev_logger) set_logger_if(prev_logger);
     463           0 :         };
     464             : 
     465           0 :         if (control.set_phase) control.set_phase("Loading workspace…");
     466             : 
     467           0 :         Result phase = default_handling_folder_workspace();
     468           0 :         if (phase.error())
     469             :         {
     470           0 :             restore_logger();
     471             :             return phase;
     472             :         }
     473             : 
     474           0 :         phase = open_esysrepo_folder();
     475           0 :         if (phase.error())
     476             :         {
     477           0 :             restore_logger();
     478             :             return phase;
     479             :         }
     480             : 
     481           0 :         phase = apply_prefer_branch();
     482           0 :         if (phase.error())
     483             :         {
     484           0 :             restore_logger();
     485             :             return phase;
     486             :         }
     487             : 
     488           0 :         if (control.set_phase) control.set_phase("Loading manifest…");
     489             : 
     490           0 :         phase = sync_manifest();
     491           0 :         if (phase.error())
     492             :         {
     493           0 :             restore_logger();
     494             :             return phase;
     495             :         }
     496             : 
     497           0 :         phase = load_manifest();
     498           0 :         if (phase.error())
     499             :         {
     500           0 :             restore_logger();
     501             :             return phase;
     502             :         }
     503             : 
     504           0 :         phase = apply_revision_set_selection();
     505           0 :         if (phase.error())
     506             :         {
     507           0 :             restore_logger();
     508             :             return phase;
     509             :         }
     510             : 
     511           0 :         phase = apply_revision_pins();
     512           0 :         if (phase.error())
     513             :         {
     514           0 :             restore_logger();
     515             :             return phase;
     516             :         }
     517             : 
     518           0 :         manifest::SyncRepos sync_repos;
     519             : 
     520           0 :         if (!get_branch().empty()) sync_repos.set_branch(get_branch());
     521             : 
     522           0 :         if (get_sub_args().size() != 0)
     523           0 :             sync_repos.set_folders_to_sync(get_sub_args());
     524           0 :         else if (get_groups().size() != 0)
     525             :         {
     526           0 :             std::vector<std::string> repos;
     527           0 :             for (auto &group : get_groups())
     528             :             {
     529           0 :                 auto group_ptr = get_manifest()->get_groups().find_group_by_name(group);
     530           0 :                 if (group_ptr == nullptr) continue;
     531           0 :                 for (auto repo : group_ptr->get_repos()) repos.push_back(repo->get_path());
     532           0 :             }
     533           0 :             sync_repos.set_folders_to_sync(repos);
     534           0 :         }
     535             : 
     536           0 :         if (get_debug()) sync_repos.set_log_level(log::Level::DEBUG);
     537             : 
     538           0 :         sync_repos.set_job_count(get_job_count());
     539           0 :         sync_repos.set_logger_if(get_logger_if());
     540           0 :         sync_repos.set_config_folder(get_config_folder());
     541           0 :         sync_repos.set_git(get_git());
     542           0 :         sync_repos.set_manifest(get_manifest());
     543           0 :         sync_repos.set_tui(false);
     544           0 :         sync_repos.set_alt_address(get_alt_address());
     545           0 :         sync_repos.set_recurse_submodules(get_recurse_submodules());
     546             : 
     547           0 :         get_git()->detect_ssh_agent(true);
     548           0 :         if (control.logger) get_git()->set_logger_if(control.logger);
     549             : 
     550           0 :         phase = sync_repos.run_with_session(session, &control);
     551           0 :         restore_logger();
     552           0 :         return phase;
     553           0 :     };
     554             : 
     555           0 :     tui::SyncTuiOptions tui_options;
     556           0 :     tui_options.demo = get_tui_demo();
     557           0 :     result = tui::run_compact_sync_tui(work, {}, ui_workers, get_logger_if(), tui_options);
     558           0 :     if (result.error()) return ETRC_RET(ESYSREPO_RESULT(result));
     559             : 
     560           0 :     if (!get_multi()) return ETRC_RET(ESYSREPO_RESULT(ResultCode::OK));
     561           0 :     return ETRC_RET(ESYSREPO_RESULT(do_multi()));
     562             : #endif
     563           0 : }
     564             : 
     565             : } // namespace esys::repo::exe

Generated by: LCOV version 1.14