LCOV - code coverage report
Current view: top level - src/esys/repo - userfolder.cpp (source / functions) Hit Total Coverage
Test: esysrepo_coverage.info Lines: 59 122 48.4 %
Date: 2026-08-01 10:43:40 Functions: 12 17 70.6 %

          Line data    Source code
       1             : /*!
       2             :  * \file esys/repo/userfolder.cpp
       3             :  * \brief
       4             :  *
       5             :  * \cond
       6             :  * __legal_b__
       7             :  *
       8             :  * Copyright (c) 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/userfolder.h"
      20             : #include "esys/repo/userconfigfile.h"
      21             : 
      22             : #ifdef WIN32
      23             : #include <shlobj.h>
      24             : #endif
      25             : 
      26             : #include <boost/filesystem.hpp>
      27             : #include <boost/locale.hpp>
      28             : 
      29             : namespace esys::repo
      30             : {
      31             : 
      32          69 : UserFolder::UserFolder() = default;
      33             : 
      34         138 : UserFolder::~UserFolder() = default;
      35             : 
      36          79 : void UserFolder::set_path(const std::string &path)
      37             : {
      38          79 :     m_path = path;
      39          79 : }
      40             : 
      41           0 : const std::string &UserFolder::get_path() const
      42             : {
      43           0 :     return m_path;
      44             : }
      45             : 
      46          69 : void UserFolder::set_user_home_path(const std::string &user_home_path)
      47             : {
      48          69 :     m_user_home_path = user_home_path;
      49          69 : }
      50             : 
      51         158 : const std::string &UserFolder::get_user_home_path() const
      52             : {
      53         158 :     return m_user_home_path;
      54             : }
      55             : 
      56          79 : void UserFolder::set_user_config_file_path(const std::string &user_config_file_path)
      57             : {
      58          79 :     m_user_config_file_path = user_config_file_path;
      59          79 : }
      60             : 
      61          58 : const std::string &UserFolder::get_user_config_file_path() const
      62             : {
      63          58 :     return m_user_config_file_path;
      64             : }
      65             : 
      66          69 : void UserFolder::set_user_config(std::shared_ptr<UserConfig> user_config)
      67             : {
      68          69 :     m_user_config = user_config;
      69          69 : }
      70             : 
      71         374 : std::shared_ptr<UserConfig> UserFolder::get_user_config() const
      72             : {
      73         374 :     return m_user_config;
      74             : }
      75             : 
      76           0 : Result UserFolder::create_folder(const std::string &folder_path, bool ok_if_exists)
      77             : {
      78           0 :     if (!boost::filesystem::exists(folder_path))
      79             :     {
      80           0 :         bool result = boost::filesystem::create_directory(folder_path);
      81           0 :         if (!result)
      82             :         {
      83           0 :             error("The following folder couldn't be created : " + folder_path);
      84           0 :             return ESYSREPO_RESULT(ResultCode::FOLDER_CREATION_ERROR, folder_path);
      85             :         }
      86             :         else
      87           0 :             info("Created folder : " + folder_path);
      88             :     }
      89             :     else
      90             :     {
      91           0 :         if (!ok_if_exists)
      92             :         {
      93           0 :             error("The following folder already exits : " + folder_path);
      94           0 :             return ESYSREPO_RESULT(ResultCode::FOLDER_ALREADY_EXISTS, folder_path);
      95             :         }
      96             :     }
      97           0 :     return ESYSREPO_RESULT(ResultCode::OK);
      98             : }
      99             : 
     100           0 : Result UserFolder::create(bool ok_if_exists)
     101             : {
     102           0 :     auto result = populate_all_pathes();
     103           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     104             : 
     105           0 :     if (get_user_config() == nullptr) ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     106             : 
     107           0 :     result = create_folder(get_path(), ok_if_exists);
     108           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     109             : 
     110           0 :     result = create_folder(get_user_config()->get_temp_path(), ok_if_exists);
     111           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     112             : 
     113           0 :     result = create_folder(get_user_config()->get_manifest_directories_path(), ok_if_exists);
     114           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     115             : 
     116           0 :     result = create_folder(get_user_config()->get_traces_path(), ok_if_exists);
     117           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     118             : 
     119           0 :     UserConfigFile user_cfg_file;
     120           0 :     user_cfg_file.set_config(get_user_config());
     121           0 :     result = user_cfg_file.write(get_user_config_file_path());
     122           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     123             : 
     124           0 :     return ESYSREPO_RESULT(ResultCode::OK);
     125           0 : }
     126             : 
     127          58 : Result UserFolder::read(const std::string &path, bool print_error)
     128             : {
     129          58 :     boost::filesystem::path esysrepo_path = path;
     130             : 
     131          58 :     if (path.empty())
     132             :     {
     133          58 :         auto result = populate_all_pathes();
     134          58 :         if (result.error()) return ESYSREPO_RESULT(result);
     135          58 :     }
     136             :     else
     137             :     {
     138           0 :         if (!boost::filesystem::exists(path)) return ESYSREPO_RESULT(ResultCode::FILE_NOT_EXISTING, path);
     139             : 
     140           0 :         if (boost::filesystem::is_regular_file(esysrepo_path))
     141           0 :             esysrepo_path = esysrepo_path.parent_path();
     142           0 :         else if (boost::filesystem::is_directory(esysrepo_path))
     143             :         {
     144           0 :             if (boost::filesystem::exists(esysrepo_path / ".esysrepo"))
     145           0 :                 esysrepo_path /= ".esysrepo";
     146           0 :             else if (esysrepo_path.filename() != ".esysrepo")
     147           0 :                 return ESYSREPO_RESULT(ResultCode::FILE_NOT_EXISTING);
     148             :         }
     149             :         else
     150           0 :             return ESYSREPO_RESULT(ResultCode::GENERIC_ERROR);
     151             : 
     152           0 :         if (esysrepo_path.filename() == ".esysrepo")
     153           0 :             set_user_home_path(esysrepo_path.parent_path().string());
     154             :         else
     155           0 :             return ESYSREPO_RESULT(ResultCode::FILE_NOT_EXISTING);
     156             : 
     157           0 :         auto result = populate_all_pathes();
     158           0 :         if (result.error()) return ESYSREPO_RESULT(result);
     159           0 :     }
     160             : 
     161          58 :     UserConfigFile user_cfg_file;
     162          58 :     user_cfg_file.set_config(get_user_config());
     163          58 :     auto result = user_cfg_file.read(get_user_config_file_path());
     164          58 :     if (result.error()) return ESYSREPO_RESULT(result);
     165             : 
     166          58 :     return ESYSREPO_RESULT(ResultCode::OK);
     167         116 : }
     168             : 
     169           0 : Result UserFolder::write(const std::string &path)
     170             : {
     171           0 :     auto result = populate_all_pathes();
     172           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     173             : 
     174           0 :     if (get_user_config() == nullptr) ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR);
     175             : 
     176           0 :     result = create_folder(get_path(), true);
     177           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     178             : 
     179           0 :     if (boost::filesystem::exists(get_user_config_file_path()))
     180             :     {
     181           0 :         boost::filesystem::remove(get_user_config_file_path());
     182             :     }
     183             : 
     184           0 :     UserConfigFile user_cfg_file;
     185           0 :     user_cfg_file.set_config(get_user_config());
     186           0 :     result = user_cfg_file.write(get_user_config_file_path());
     187           0 :     if (result.error()) return ESYSREPO_RESULT(result);
     188             : 
     189           0 :     return ESYSREPO_RESULT(ResultCode::OK);
     190           0 : }
     191             : 
     192          79 : Result UserFolder::populate_all_pathes()
     193             : {
     194          79 :     if (get_user_home_path().empty())
     195             :     {
     196          69 :         auto result = detect_home_folder();
     197          69 :         if (result.error()) return ESYSREPO_RESULT(result);
     198          69 :     }
     199          79 :     boost::filesystem::path base_path = get_user_home_path();
     200         158 :     boost::filesystem::path user_folder_path = base_path / ".esysrepo";
     201         158 :     boost::filesystem::path temp_path = user_folder_path / "temp";
     202         158 :     boost::filesystem::path user_config_file_path = user_folder_path / "user_config.xml";
     203         158 :     boost::filesystem::path manifest_directories_path = user_folder_path / "manifest_directories";
     204         158 :     boost::filesystem::path manifest_directories_file_path = user_folder_path / "manifest_directories.xml";
     205         158 :     boost::filesystem::path traces_path = user_folder_path / "traces";
     206             : 
     207          79 :     set_path(user_folder_path.string());
     208          79 :     set_user_config_file_path(user_config_file_path.string());
     209             : 
     210         158 :     if (get_user_config() == nullptr) set_user_config(std::make_shared<UserConfig>());
     211             : 
     212          79 :     get_user_config()->set_temp_path(temp_path.string());
     213          79 :     get_user_config()->set_manifest_directories_path(manifest_directories_path.string());
     214          79 :     get_user_config()->set_traces_path(traces_path.string());
     215             : 
     216          79 :     return ESYSREPO_RESULT(ResultCode::OK);
     217         158 : }
     218             : 
     219          69 : Result UserFolder::detect_home_folder()
     220             : {
     221             : #ifdef WIN32
     222             :     PWSTR path = nullptr;
     223             :     auto hresult = SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, &path);
     224             :     if (SUCCEEDED(hresult))
     225             :     {
     226             :         auto char_path = boost::locale::conv::utf_to_utf<char>(path);
     227             :         set_user_home_path(char_path);
     228             :         CoTaskMemFree(path);
     229             :         return ESYSREPO_RESULT(ResultCode::OK);
     230             :     }
     231             :     else
     232             :     {
     233             :         CoTaskMemFree(path);
     234             :         return ESYSREPO_RESULT(ResultCode::GENERIC_ERROR);
     235             :     }
     236             : #else
     237          69 :     auto path = std::getenv("XDG_CONFIG_HOME");
     238          69 :     if (path != nullptr)
     239             :     {
     240           0 :         set_user_home_path(path);
     241           0 :         return ESYSREPO_RESULT(ResultCode::OK);
     242             :     }
     243          69 :     path = std::getenv("HOME");
     244          69 :     if (path != nullptr)
     245             :     {
     246          69 :         set_user_home_path(path);
     247          69 :         return ESYSREPO_RESULT(ResultCode::OK);
     248             :     }
     249           0 :     return ESYSREPO_RESULT(ResultCode::GENERIC_ERROR);
     250             : #endif
     251             : }
     252             : 
     253             : } // namespace esys::repo

Generated by: LCOV version 1.14