From e0e37349543f14fdcd79c1c473e21bc5b0d4f9dc 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-dir - 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/setopt.cpp | 13 +++++++++++++ dnf5-plugins/config-manager_plugin/setopt.hpp | 1 + dnf5-plugins/config-manager_plugin/setvar.cpp | 11 +++++++++++ dnf5-plugins/config-manager_plugin/setvar.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 eb4d384f50..2a5ae63115 100644 --- a/dnf5-plugins/config-manager_plugin/addrepo.cpp +++ b/dnf5-plugins/config-manager_plugin/addrepo.cpp @@ -211,6 +211,16 @@ void ConfigManagerAddRepoCommand::set_argument_parser() { }); cmd.register_named_arg(set_opt); + auto create_missing_dirs_opt = parser.add_new_named_arg("create-missing-dir"); + create_missing_dirs_opt->set_long_name("create-missing-dir"); + create_missing_dirs_opt->set_description("Allow creation of 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 overwrite_opt = parser.add_new_named_arg("overwrite"); overwrite_opt->set_long_name("overwrite"); overwrite_opt->set_description("Allow overwriting of existing repository configuration file"); @@ -248,8 +258,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/setopt.cpp b/dnf5-plugins/config-manager_plugin/setopt.cpp index d4b5be8c0f..030ea54f91 100644 --- a/dnf5-plugins/config-manager_plugin/setopt.cpp +++ b/dnf5-plugins/config-manager_plugin/setopt.cpp @@ -131,6 +131,16 @@ void ConfigManagerSetOptCommand::set_argument_parser() { return true; }); cmd.register_positional_arg(opts_vals); + + auto create_missing_dirs_opt = parser.add_new_named_arg("create-missing-dir"); + create_missing_dirs_opt->set_long_name("create-missing-dir"); + 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 ConfigManagerSetOptCommand::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 ConfigManagerSetOptCommand::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/setopt.hpp b/dnf5-plugins/config-manager_plugin/setopt.hpp index 27a52e01b8..5b595ac9e7 100644 --- a/dnf5-plugins/config-manager_plugin/setopt.hpp +++ b/dnf5-plugins/config-manager_plugin/setopt.hpp @@ -40,6 +40,7 @@ class ConfigManagerSetOptCommand : 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/setvar.cpp b/dnf5-plugins/config-manager_plugin/setvar.cpp index 7ba9dd5106..8002d32532 100644 --- a/dnf5-plugins/config-manager_plugin/setvar.cpp +++ b/dnf5-plugins/config-manager_plugin/setvar.cpp @@ -75,6 +75,16 @@ void ConfigManagerSetVarCommand::set_argument_parser() { return true; }); cmd.register_positional_arg(vars_vals); + + auto create_missing_dirs_opt = parser.add_new_named_arg("create-missing-dir"); + create_missing_dirs_opt->set_long_name("create-missing-dir"); + 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 ConfigManagerSetVarCommand::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/setvar.hpp b/dnf5-plugins/config-manager_plugin/setvar.hpp index e897a9add6..54c27c6241 100644 --- a/dnf5-plugins/config-manager_plugin/setvar.hpp +++ b/dnf5-plugins/config-manager_plugin/setvar.hpp @@ -36,6 +36,7 @@ class ConfigManagerSetVarCommand : 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..b121cca5fe 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_("Directory \"{}\" does not exist. Add \"--create-missing-dir\" to create missing directories."), + path.string()); + } + } +} + inline void check_variable_name(const std::string & name) { if (name.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"