1- #pragma once
1+ #ifndef UTILS_HPP
2+ #define UTILS_HPP
23
34#include < filesystem>
45#include < fstream>
@@ -13,15 +14,10 @@ namespace vix::cli::util
1314{
1415 namespace fs = std::filesystem;
1516
16- // Écrit un fichier texte de manière sûre : fichier temporaire puis renommage.
17- // - Crée les répertoires parents si nécessaires.
18- // - Utilise un fichier .tmp dans le même dossier pour éviter les problèmes de volume.
19- // - Tente un remplacement atomique (selon l’OS / FS).
2017 inline void write_text_file (const fs::path &p, std::string_view content)
2118 {
2219 std::error_code ec;
2320
24- // 1) Assure l'existence du parent (si applicable)
2521 const fs::path parent = p.parent_path ();
2622 if (!parent.empty ())
2723 {
@@ -34,7 +30,6 @@ namespace vix::cli::util
3430 }
3531 }
3632
37- // 2) Fichier temporaire à côté de la cible (avec quelques tentatives)
3833 auto make_tmp_name = [&]()
3934 {
4035 std::mt19937_64 rng{std::random_device{}()};
@@ -55,12 +50,11 @@ namespace vix::cli::util
5550 }
5651 }
5752
58- // 3) Écriture (binaire) + flush + close
5953 {
6054 std::ofstream ofs (tmp, std::ios::binary | std::ios::trunc);
6155 if (!ofs)
6256 {
63- fs::remove (tmp, ec); // best-effort cleanup
57+ fs::remove (tmp, ec);
6458 throw std::runtime_error (
6559 " Cannot open temp file for write: " + tmp.string ());
6660 }
@@ -80,36 +74,31 @@ namespace vix::cli::util
8074 fs::remove (tmp, ec);
8175 throw std::runtime_error (" Failed to flush file: " + tmp.string ());
8276 }
83- // fermeture via le destructeur
8477 }
8578
86- // 4) Rename → p (tentative atomique). Sous Windows, si p existe, rename peut échouer.
8779 fs::rename (tmp, p, ec);
8880 if (ec)
8981 {
90- // Essaye de supprimer la cible existante puis renommer à nouveau
91- fs::remove (p, ec); // ignorer l'erreur (si absent / verrouillé)
82+ fs::remove (p, ec);
9283 ec.clear ();
9384 fs::rename (tmp, p, ec);
9485 if (ec)
9586 {
9687 std::error_code ec2;
97- fs::remove (tmp, ec2); // éviter les orphelins
88+ fs::remove (tmp, ec2);
9889 throw std::runtime_error (
9990 " Failed to move temp file to destination: " +
10091 tmp.string () + " → " + p.string () + " — " + ec.message ());
10192 }
10293 }
10394 }
10495
105- // Renvoie true si le répertoire est vide ou n'existe pas; false sinon.
106- // N'émet **pas** d'exception : utile dans les checks préalables.
10796 inline bool is_dir_empty (const fs::path &p) noexcept
10897 {
10998 std::error_code ec;
11099
111100 if (!fs::exists (p, ec))
112- return true ; // inexistant = considéré vide
101+ return true ;
113102 if (ec)
114103 return false ;
115104 if (!fs::is_directory (p, ec))
@@ -123,9 +112,6 @@ namespace vix::cli::util
123112 return (it == fs::directory_iterator{});
124113 }
125114
126- // Récupère la valeur de --dir / -d si présente.
127- // Supporte: "-d PATH", "--dir PATH", et "--dir=PATH".
128- // Évite de prendre une autre option comme valeur (ex: "-d --flag").
129115 inline std::optional<std::string> pick_dir_opt (
130116 const std::vector<std::string> &args,
131117 std::string_view shortOpt = " -d" ,
@@ -146,16 +132,13 @@ namespace vix::cli::util
146132 {
147133 return args[i + 1 ];
148134 }
149- // option sans valeur → ignorée (caller gère le défaut)
150135 return std::nullopt ;
151136 }
152137
153- // format --dir=/chemin
154138 const std::string prefix (longOpt);
155139 if (!prefix.empty () && a.rfind (prefix + " =" , 0 ) == 0 )
156140 {
157141 std::string val = a.substr (prefix.size () + 1 );
158- // autoriser --dir="" (revient à std::nullopt)
159142 if (val.empty ())
160143 return std::nullopt ;
161144 return val;
@@ -165,3 +148,5 @@ namespace vix::cli::util
165148 }
166149
167150} // namespace vix::cli::util
151+
152+ #endif
0 commit comments