55
66#include < algorithm>
77#include < filesystem>
8- #include < fstream>
98#include < memory>
109#include < ranges>
1110#include < sstream>
@@ -33,6 +32,7 @@ using cloyster::services::repos::IRepository;
3332
3433namespace cloyster ::services::repos {
3534
35+ // Represents a debian repository file
3636class DebianRepository : public IRepository {
3737private:
3838 std::string m_type; // "deb" or "deb-src"
@@ -61,6 +61,7 @@ class DebianRepository : public IRepository {
6161 void source (const std::filesystem::path value) override ;
6262};
6363
64+ // Represents a RPM Repository inside a repository file (/etc/yum.repo.d/*.repo)
6465class RPMRepository final : public IRepository {
6566 std::string m_id;
6667 bool m_enabled = true ;
@@ -126,16 +127,14 @@ class RPMRepository final : public IRepository {
126127 {
127128 return other.id () == id ();
128129 }
129-
130-
131130};
132131
133132namespace {
134133
135134// Easy conversions for string
136135std::ostream& operator <<(std::ostream& ostr, const RPMRepository& repo)
137136{
138- ostr << " RPMRepository( " ;
137+ ostr << " RPMRepository(" ;
139138 ostr << repo.id () << " " ;
140139 ostr << repo.name () << " " ;
141140 ostr << repo.baseurl ().value_or (" " ) << " " ;
@@ -155,7 +154,7 @@ std::string toString(const T& input)
155154
156155};
157156
158- // Parses .repo files
157+ // Parses RPM .repo files
159158class RPMRepositoryParser final {
160159public:
161160 static void parse (
@@ -213,8 +212,6 @@ class RPMRepositoryParser final {
213212 }
214213
215214 file.save ();
216-
217- LOG_DEBUG (" UNPARSE FILE {}:\n {}" , path.string (), file.toData ());
218215 }
219216};
220217static_assert (IsParser<RPMRepositoryParser, std::filesystem::path,
@@ -232,6 +229,11 @@ class RPMRepositoryFile final {
232229 m_parser.parse (m_path, m_repos);
233230 }
234231
232+ const auto & path ()
233+ {
234+ return m_path;
235+ }
236+
235237 auto & repos ()
236238 {
237239 return m_repos;
@@ -325,11 +327,28 @@ class RPMRepoManager final {
325327 repofile->save ();
326328 }
327329
330+ // Enable a repo but dot not save the repofile, (used internally)
331+ void enable (const auto & repo, auto & repofile, bool value)
332+ {
333+ LOG_DEBUG (" Enabling/Disabling[{}] RPM repo {}" ,
334+ value, repo);
335+ repofile->repo (repo)->enabled (value);
336+ }
337+
328338 // Enable/disable multiple repositories by name
329339 void enable (const std::vector<std::string>& repos, bool value)
330340 {
341+ auto byIdPtr = [](const std::shared_ptr<RPMRepositoryFile>& rptr) {
342+ return std::hash<std::string>{}(rptr->path ());
343+ };
344+ std::unordered_set<std::shared_ptr<RPMRepositoryFile>, decltype (byIdPtr)> toSave;
331345 for (const auto & repo : repos) {
332- enable (repo, value);
346+ auto & rfile = m_filesIdx.at (repo);
347+ toSave.emplace (rfile);
348+ enable (repo, rfile, value);
349+ }
350+ for (const auto & repoFil : toSave) {
351+ repoFil->save ();
333352 }
334353 }
335354
@@ -360,8 +379,6 @@ class RPMRepoManager final {
360379
361380namespace {
362381
363- using cloyster::services::repos::RPMRepository;
364-
365382// These files contains the repositories files data as
366383// format strings with which we inject the values for
367384constexpr std::string_view CLOYSTER_REPO_EL8 = {
@@ -439,6 +456,7 @@ std::vector<std::string> getDependenciesEL(const OS& osinfo)
439456
440457namespace cloyster ::services::repos {
441458
459+ // Hidden implementation
442460struct RepoManager ::Impl {
443461 RPMRepoManager rpm;
444462 // Add debian repo manager here when the day arrives
@@ -531,7 +549,29 @@ void RepoManager::enable(const std::string& repoid)
531549
532550void RepoManager::enable (const std::vector<std::string>& repos)
533551{
534- std::ranges::for_each (repos, [&](const auto & repoid) { enable (repoid); });
552+ if (cloyster::dryRun) {
553+ LOG_WARN (" Dry Run: Would enable these repos: {}" ,
554+ fmt::join (repos, " ," ));
555+ return ;
556+ }
557+ try {
558+ switch (m_os.getPackageType ()) {
559+ case OS::PackageType::RPM:
560+ m_impl->rpm .enable (repos, true );
561+ break ;
562+ default :
563+ throw std::logic_error (" Not implemented" );
564+
565+ }
566+ } catch (const std::out_of_range&) {
567+ LOG_ERROR (" Trying to enable unknown repository {}, "
568+ " failed because the repository was not found." ,
569+ fmt::join (repos, " ," ));
570+
571+ for (const auto & [id, _] : m_repos) {
572+ LOG_ERROR (" Repository available: {}" , id);
573+ }
574+ }
535575}
536576
537577void RepoManager::disable (const std::string& repoid)
@@ -563,8 +603,29 @@ void RepoManager::disable(const std::string& repoid)
563603
564604void RepoManager::disable (const std::vector<std::string>& repos)
565605{
566- std::ranges::for_each (
567- repos, [&](const auto & repoid) { disable (repoid); });
606+ if (cloyster::dryRun) {
607+ LOG_WARN (" Dry Run: Would enable repository {}" , fmt::join (repos, " ," ));
608+ return ;
609+ }
610+
611+ try {
612+ switch (m_os.getPackageType ()) {
613+ case OS::PackageType::RPM:
614+ m_impl->rpm .enable (repos, false );
615+ break ;
616+ default :
617+ throw std::logic_error (" Not implemented" );
618+
619+ }
620+ } catch (const std::out_of_range&) {
621+ LOG_ERROR (" Trying to disable unknown repository {}, "
622+ " failed because the repository was not found." ,
623+ fmt::join (repos, " ," ));
624+
625+ for (const auto & [id, _] : m_repos) {
626+ LOG_ERROR (" Repository available: {}" , id);
627+ }
628+ }
568629}
569630
570631void RepoManager::install (const std::filesystem::path& path)
0 commit comments