From 87cbea045e4ab40d99ceea4be6f7f1cfa41e672e Mon Sep 17 00:00:00 2001 From: Jaroslav Rohel Date: Wed, 1 Nov 2023 13:08:01 +0100 Subject: [PATCH] [dnf5 plugin] config-manager: Support for creating missing directories New option: --create-missing-dirs - Allow to create missing directories Without this option, an exception is thrown if the directory is missing. --- dnf5-plugins/config-manager_plugin/addrepo.cpp | 12 +++++++++++- dnf5-plugins/config-manager_plugin/addrepo.hpp | 1 + dnf5-plugins/config-manager_plugin/setopts.cpp | 13 +++++++++++++ dnf5-plugins/config-manager_plugin/setopts.hpp | 1 + dnf5-plugins/config-manager_plugin/setvars.cpp | 11 +++++++++++ dnf5-plugins/config-manager_plugin/setvars.hpp | 1 + dnf5-plugins/config-manager_plugin/shared.hpp | 14 ++++++++++++++ 7 files changed, 52 insertions(+), 1 deletion(-) diff --git a/dnf5-plugins/config-manager_plugin/addrepo.cpp b/dnf5-plugins/config-manager_plugin/addrepo.cpp index 5545be8ea5..163ec8bfea 100644 --- a/dnf5-plugins/config-manager_plugin/addrepo.cpp +++ b/dnf5-plugins/config-manager_plugin/addrepo.cpp @@ -135,6 +135,16 @@ void ConfigManagerAddRepoCommand::set_argument_parser() { auto & cmd = *get_argument_parser_command(); cmd.set_description("Add a repository from the specified configuration file or create a new repository"); + auto create_missing_dirs_opt = parser.add_new_named_arg("create-missing-dirs"); + create_missing_dirs_opt->set_long_name("create-missing-dirs"); + create_missing_dirs_opt->set_description("Allow to create missing directories"); + create_missing_dirs_opt->set_has_value(false); + create_missing_dirs_opt->set_parse_hook_func([this](cli::ArgumentParser::NamedArg *, const char *, const char *) { + create_missing_dirs = true; + return true; + }); + cmd.register_named_arg(create_missing_dirs_opt); + auto from_repofile_opt = parser.add_new_named_arg("from-repofile"); from_repofile_opt->set_long_name("from-repofile"); from_repofile_opt->set_description("Download repository configuration file, test it and put it in reposdir"); @@ -245,8 +255,8 @@ void ConfigManagerAddRepoCommand::configure() { if (repo_dirs.empty()) { throw ConfigManagerError(M_("Missing path to repository configuration directory")); } - std::filesystem::path dest_repo_dir = repo_dirs.front(); + resolve_missing_dir(dest_repo_dir, create_missing_dirs); if (source_repofile.location.empty()) { create_repo(repo_id, repo_opts, dest_repo_dir); diff --git a/dnf5-plugins/config-manager_plugin/addrepo.hpp b/dnf5-plugins/config-manager_plugin/addrepo.hpp index 7af1a52a0e..282195b8a1 100644 --- a/dnf5-plugins/config-manager_plugin/addrepo.hpp +++ b/dnf5-plugins/config-manager_plugin/addrepo.hpp @@ -74,6 +74,7 @@ class ConfigManagerAddRepoCommand : public Command { SourceRepofile source_repofile; // Location of source repository configuration file. std::string repo_id; // The user-defined ID of the newly created repository. + bool create_missing_dirs{false}; // Allows to create missing directories. bool overwrite{false}; // Allows to overwrite an existing configuration file. std::string save_filename; // User-defined name of newly saved configuration file. std::map repo_opts; // Options for the new repository. diff --git a/dnf5-plugins/config-manager_plugin/setopts.cpp b/dnf5-plugins/config-manager_plugin/setopts.cpp index e3341bea98..9241ddccdd 100644 --- a/dnf5-plugins/config-manager_plugin/setopts.cpp +++ b/dnf5-plugins/config-manager_plugin/setopts.cpp @@ -131,6 +131,16 @@ void ConfigManagerCommandSetOpts::set_argument_parser() { return true; }); cmd.register_positional_arg(opts_vals); + + auto create_missing_dirs_opt = parser.add_new_named_arg("create-missing-dirs"); + create_missing_dirs_opt->set_long_name("create-missing-dirs"); + create_missing_dirs_opt->set_description("Allow to create missing directories"); + create_missing_dirs_opt->set_has_value(false); + create_missing_dirs_opt->set_parse_hook_func([this](cli::ArgumentParser::NamedArg *, const char *, const char *) { + create_missing_dirs = true; + return true; + }); + cmd.register_named_arg(create_missing_dirs_opt); } @@ -170,6 +180,7 @@ void ConfigManagerCommandSetOpts::configure() { ConfigParser parser; const auto & cfg_filepath = get_config_file_path(ctx.base.get_config()); + resolve_missing_dir(cfg_filepath.parent_path(), create_missing_dirs); const bool exists = std::filesystem::exists(cfg_filepath); if (exists) { @@ -187,6 +198,8 @@ void ConfigManagerCommandSetOpts::configure() { if (!matching_repos_setopts.empty()) { ConfigParser parser; + resolve_missing_dir(libdnf5::REPOS_OVERRIDE_DIR, create_missing_dirs); + const bool exists = std::filesystem::exists(CFG_MANAGER_REPOS_OVERRIDE_FILEPATH); if (exists) { parser.read(CFG_MANAGER_REPOS_OVERRIDE_FILEPATH); diff --git a/dnf5-plugins/config-manager_plugin/setopts.hpp b/dnf5-plugins/config-manager_plugin/setopts.hpp index 5a386bdcdb..3578e8106b 100644 --- a/dnf5-plugins/config-manager_plugin/setopts.hpp +++ b/dnf5-plugins/config-manager_plugin/setopts.hpp @@ -40,6 +40,7 @@ class ConfigManagerCommandSetOpts : public Command { std::map main_setopts; std::map> in_repos_setopts; std::map> matching_repos_setopts; + bool create_missing_dirs{false}; // Allows to create missing directories. }; } // namespace dnf5 diff --git a/dnf5-plugins/config-manager_plugin/setvars.cpp b/dnf5-plugins/config-manager_plugin/setvars.cpp index fab1372d1d..013347f789 100644 --- a/dnf5-plugins/config-manager_plugin/setvars.cpp +++ b/dnf5-plugins/config-manager_plugin/setvars.cpp @@ -75,6 +75,16 @@ void ConfigManagerCommandSetVars::set_argument_parser() { return true; }); cmd.register_positional_arg(vars_vals); + + auto create_missing_dirs_opt = parser.add_new_named_arg("create-missing-dirs"); + create_missing_dirs_opt->set_long_name("create-missing-dirs"); + create_missing_dirs_opt->set_description("Allow to create missing directories"); + create_missing_dirs_opt->set_has_value(false); + create_missing_dirs_opt->set_parse_hook_func([this](cli::ArgumentParser::NamedArg *, const char *, const char *) { + create_missing_dirs = true; + return true; + }); + cmd.register_named_arg(create_missing_dirs_opt); } @@ -86,6 +96,7 @@ void ConfigManagerCommandSetVars::configure() { if (vars_dir.empty()) { throw ConfigManagerError(M_("Missing path to vars directory")); } + resolve_missing_dir(vars_dir, create_missing_dirs); for (const auto & [name, value] : setvars) { const auto filepath = vars_dir / name; diff --git a/dnf5-plugins/config-manager_plugin/setvars.hpp b/dnf5-plugins/config-manager_plugin/setvars.hpp index 2a46371147..0434d3f175 100644 --- a/dnf5-plugins/config-manager_plugin/setvars.hpp +++ b/dnf5-plugins/config-manager_plugin/setvars.hpp @@ -36,6 +36,7 @@ class ConfigManagerCommandSetVars : public Command { private: std::map setvars; + bool create_missing_dirs{false}; // Allows to create missing directories. }; } // namespace dnf5 diff --git a/dnf5-plugins/config-manager_plugin/shared.hpp b/dnf5-plugins/config-manager_plugin/shared.hpp index 7145e45fd1..3262a77982 100644 --- a/dnf5-plugins/config-manager_plugin/shared.hpp +++ b/dnf5-plugins/config-manager_plugin/shared.hpp @@ -40,6 +40,20 @@ struct ConfigManagerError : public libdnf5::Error { const char * get_name() const noexcept override { return "ConfigManagerError"; } }; +// Checks if the `path` directory exists. If not, according to the `create_missing_dirs` argument, +// the directories (missing paths elements) are created or `ConfigManagerError` exception is thrown. +inline void resolve_missing_dir(const std::filesystem::path & path, bool create_missing_dirs) { + if (!std::filesystem::exists(path)) { + if (create_missing_dirs) { + std::filesystem::create_directories(path); + } else { + throw ConfigManagerError( + M_("Creation of missing directories is not allowed and the directory \"{}\" does not exist."), + path.string()); + } + } +} + inline void check_variable_name(const std::string & name) { if (name.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"