From 3a7b3492e965196c3d45c7b6b97c8cf87bbc1185 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A1n=20Kupec?= Date: Sun, 26 Apr 2009 16:49:09 +0200 Subject: [PATCH] Config file handling improved. - $HOME/.zypper.conf reading enabled - --config option added to read custom file, default conf files are ingored, if an existing file is specified - do not fail if config can't be parsed, just log --- src/Config.cc | 168 +++++++++++++++++++++++++++------------------------- src/Config.h | 2 +- src/Zypper.cc | 11 ++-- src/Zypper.h | 1 - src/utils/Augeas.cc | 94 ++++++++++++++++++++++------- src/utils/Augeas.h | 10 +++- 6 files changed, 175 insertions(+), 111 deletions(-) diff --git a/src/Config.cc b/src/Config.cc index 99be31c..ad25dce 100644 --- a/src/Config.cc +++ b/src/Config.cc @@ -115,117 +115,123 @@ Config::Config() , color_promptOption("grey") {} -void Config::read() +void Config::read(const string & file) { - debug::Measure m("ReadConfig"); + try + { + debug::Measure m("ReadConfig"); + string s; - Augeas augeas; + Augeas augeas(file); - m.elapsed(); + m.elapsed(); - string s; + // ---------------[ main ]-------------------------------------------------- - // ---------------[ main ]-------------------------------------------------- + // TODO - // TODO + // ---------------[ main ]-------------------------------------------------- - // ---------------[ main ]-------------------------------------------------- + s = augeas.getOption(ConfigOption::SOLVER_INSTALL_RECOMMENDS.asString()); + if (s.empty()) + solver_installRecommends = ZConfig::instance().solver_onlyRequires(); + else + solver_installRecommends = str::strToBool(s, true); - s = augeas.getOption(ConfigOption::SOLVER_INSTALL_RECOMMENDS.asString()); - if (s.empty()) - solver_installRecommends = ZConfig::instance().solver_onlyRequires(); - else - solver_installRecommends = str::strToBool(s, true); + // ---------------[ colors ]------------------------------------------------ - // ---------------[ colors ]------------------------------------------------ + color_useColors = augeas.getOption(ConfigOption::COLOR_USE_COLORS.asString()); + do_colors = + (color_useColors == "autodetect" && has_colors()) + || color_useColors == "always"; - color_useColors = augeas.getOption(ConfigOption::COLOR_USE_COLORS.asString()); - do_colors = - (color_useColors == "autodetect" && has_colors()) - || color_useColors == "always"; + ////// color/background ////// - ////// color/background ////// + s = augeas.getOption(ConfigOption::COLOR_BACKGROUND.asString()); + if (s == "light") + color_background = true; + else if (!s.empty() && s != "dark") + ERR << "invalid color/background value: " << s << endl; - s = augeas.getOption(ConfigOption::COLOR_BACKGROUND.asString()); - if (s == "light") - color_background = true; - else if (!s.empty() && s != "dark") - ERR << "invalid color/background value: " << s << endl; + Color c(""); - Color c(""); + ////// color/colorResult ////// - ////// color/colorResult ////// + c = Color(augeas.getOption(ConfigOption::COLOR_RESULT.asString())); + if (c.value().empty()) + { + // set a default for light background + if (color_background) + color_result = Color("black"); + } + else + color_result = c; - c = Color(augeas.getOption(ConfigOption::COLOR_RESULT.asString())); - if (c.value().empty()) - { - // set a default for light background - if (color_background) - color_result = Color("black"); - } - else - color_result = c; + ////// color/colorMsgStatus ////// - ////// color/colorMsgStatus ////// + c = Color(augeas.getOption(ConfigOption::COLOR_MSG_STATUS.asString())); + if (c.value().empty()) + { + // set a default for light background + if (color_background) + color_msgStatus = Color("default"); + } + else + color_msgStatus = c; - c = Color(augeas.getOption(ConfigOption::COLOR_MSG_STATUS.asString())); - if (c.value().empty()) - { - // set a default for light background - if (color_background) - color_msgStatus = Color("default"); - } - else - color_msgStatus = c; + ////// color/colorMsgError ////// - ////// color/colorMsgError ////// + c = Color(augeas.getOption(ConfigOption::COLOR_MSG_ERROR.asString())); + if (!c.value().empty()) + color_msgError = c; - c = Color(augeas.getOption(ConfigOption::COLOR_MSG_ERROR.asString())); - if (!c.value().empty()) - color_msgError = c; + ////// color/colorMsgWarning ////// - ////// color/colorMsgWarning ////// + c = Color(augeas.getOption(ConfigOption::COLOR_MSG_WARNING.asString())); + if (c.value().empty()) + { + // set a default for light background + if (color_background) + color_msgWarning = Color("brown"); + } + else + color_msgWarning = c; - c = Color(augeas.getOption(ConfigOption::COLOR_MSG_WARNING.asString())); - if (c.value().empty()) - { - // set a default for light background - if (color_background) - color_msgWarning = Color("brown"); - } - else - color_msgWarning = c; + ////// color/colorPositive ////// - ////// color/colorPositive ////// + c = Color(augeas.getOption(ConfigOption::COLOR_POSITIVE.asString())); + if (!c.value().empty()) + color_positive = c; - c = Color(augeas.getOption(ConfigOption::COLOR_POSITIVE.asString())); - if (!c.value().empty()) - color_positive = c; + ////// color/colorNegative ////// - ////// color/colorNegative ////// + c = Color(augeas.getOption(ConfigOption::COLOR_NEGATIVE.asString())); + if (!c.value().empty()) + color_negative = c; - c = Color(augeas.getOption(ConfigOption::COLOR_NEGATIVE.asString())); - if (!c.value().empty()) - color_negative = c; + ////// color/highlight ////// - ////// color/highlight ////// + c = Color(augeas.getOption(ConfigOption::COLOR_HIGHLIGHT.asString())); + if (!c.value().empty()) + color_highlight = c; - c = Color(augeas.getOption(ConfigOption::COLOR_HIGHLIGHT.asString())); - if (!c.value().empty()) - color_highlight = c; + ////// color/colorPromptOption ////// - ////// color/colorPromptOption ////// + c = Color(augeas.getOption(ConfigOption::COLOR_PROMPT_OPTION.asString())); + if (c.value().empty()) + { + // set a default for light background + if (color_background) + color_promptOption = Color("darkgrey"); + } + else + color_promptOption = c; - c = Color(augeas.getOption(ConfigOption::COLOR_PROMPT_OPTION.asString())); - if (c.value().empty()) + m.stop(); + } + catch (Exception & e) { - // set a default for light background - if (color_background) - color_promptOption = Color("darkgrey"); + DBG << "Augeas exception. No config read, sticking with defaults." << endl; } - else - color_promptOption = c; - - m.stop(); } diff --git a/src/Config.h b/src/Config.h index 402387f..0c4397c 100644 --- a/src/Config.h +++ b/src/Config.h @@ -70,7 +70,7 @@ struct Config Config(); /** Reads zypper.conf and stores the result */ - void read(); + void read(const std::string & file = ""); bool solver_installRecommends; diff --git a/src/Zypper.cc b/src/Zypper.cc index 6fd8072..6eaa889 100644 --- a/src/Zypper.cc +++ b/src/Zypper.cc @@ -103,7 +103,6 @@ int Zypper::main(int argc, char ** argv) // parse global options and the command try { - readConfig(); processGlobalOptions(); } catch (const ExitRequestException & e) @@ -148,16 +147,13 @@ Out & Zypper::out() ZYPP_THROW(ExitRequestException("no output writer")); } -void Zypper::readConfig() -{ - _config.read(); -} void print_main_help(Zypper & zypper) { static string help_global_options = _(" Global Options:\n" "\t--help, -h\t\tHelp.\n" "\t--version, -V\t\tOutput the version number.\n" + "\t--config, -c\t\tUse specified config file instead of the deafult.\n" "\t--quiet, -q\t\tSuppress normal output, print only error\n" "\t\t\t\tmessages.\n" "\t--verbose, -v\t\tIncrease verbosity.\n" @@ -342,6 +338,7 @@ void Zypper::processGlobalOptions() {"no-cd", no_argument, 0, 0 }, {"no-remote", no_argument, 0, 0 }, {"xmlout", no_argument, 0, 'x'}, + {"config", required_argument, 0, 'c'}, {0, 0, 0, 0} }; @@ -355,6 +352,10 @@ void Zypper::processGlobalOptions() parsed_opts::const_iterator it; + // read config from specified file or default config files + _config.read( + (it = gopts.find("config")) != gopts.end() ? it->second.front() : ""); + // ====== output setup ====== // depends on global options, that's we set it up here //! \todo create a default in the zypper constructor, recreate here. diff --git a/src/Zypper.h b/src/Zypper.h index d5189da..0eead52 100644 --- a/src/Zypper.h +++ b/src/Zypper.h @@ -188,7 +188,6 @@ public: private: Zypper(); - void readConfig(); void processGlobalOptions(); void processCommandOptions(); void commandShell(); diff --git a/src/utils/Augeas.cc b/src/utils/Augeas.cc index d1d7578..e3580f1 100644 --- a/src/utils/Augeas.cc +++ b/src/utils/Augeas.cc @@ -8,41 +8,84 @@ #include #include "zypp/base/Logger.h" +#include "zypp/Pathname.h" #include "Zypper.h" #include "utils/Augeas.h" using namespace zypp; using namespace std; -Augeas::Augeas() +Augeas::Augeas(const string & file) : _augeas(NULL), _got_global_zypper_conf(false), _got_user_zypper_conf(false) { MIL << "Going to read zypper config using Augeas..." << endl; - //! \todo use specified root dir - _augeas = ::aug_init(NULL, "/usr/share/zypper", AUG_NO_STDINC); - + // init + _augeas = ::aug_init(NULL, "/usr/share/zypper", AUG_NO_STDINC | AUG_NO_LOAD); if (_augeas == NULL) ZYPP_THROW(Exception(_("Cannot initialize configuration file parser."))); + // tell augeas which file to load + // if file is specified, try to load the file, fall back to default files + // default - /etc/zypp/zypper.conf & $HOME/.zypper.conf + Pathname filepath(file); + bool want_custom = false; + if (!file.empty() && PathInfo(filepath).isExist()) + { + want_custom = true; + if (filepath.relative()) + { + string wd = ::getenv("PWD"); + filepath = wd / filepath; + } - _got_global_zypper_conf = - ::aug_get(_augeas, "/files/etc/zypp/zypper.conf", NULL) != 0; + if (::aug_set(_augeas, "/augeas/load/ZYpper/incl", filepath.asString().c_str()) != 0) + ZYPP_THROW(Exception(_("Augeas error: setting config file to load failed."))); + } + else + { + _homedir = ::getenv("HOME"); + if (_homedir.empty()) + WAR << "Cannot figure out user's home directory. Skipping user's config." << endl; + else + { + // add $HOME/.zypper.conf; /etc/zypp/zypper.conf should already be included + filepath = _homedir + "/.zypper.conf"; + if (::aug_set(_augeas, "/augeas/load/ZYpper/incl[2]", filepath.asString().c_str()) != 0) + ZYPP_THROW(Exception(_("Augeas error: setting config file to load failed."))); + } + } + // load the file + if (aug_load(_augeas) != 0) + ZYPP_THROW(Exception(_("Could not parse the config files."))); + + // collect eventual errors const char *value[1] = {}; string error; - if (::aug_get(_augeas, "/augeas/files/etc/zypp/zypper.conf/error/message", value)) - error = value[0]; - - _homedir = ::getenv("HOME"); - if (_homedir.empty()) - WAR << "Cannot figure out user's home directory." << endl; + if (want_custom) + _user_conf_path = "/files" + filepath.asString(); else { - //! \todo cherry-pick this file as soon as the API allows it - string user_zypper_conf = "/files" + _homedir + "/.zypper.conf"; + if (!_homedir.empty()) + _user_conf_path = "/files" + _homedir + "/.zypper.conf"; + + // global conf errors + _got_global_zypper_conf = + ::aug_get(_augeas, "/files/etc/zypp/zypper.conf", NULL) != 0; + if (::aug_get(_augeas, "/augeas/files/etc/zypp/zypper.conf/error/message", value)) + error = value[0]; + + } + + // user conf errors + if (!_user_conf_path.empty()) + { _got_user_zypper_conf = - ::aug_get(_augeas, user_zypper_conf.c_str(), NULL) != 0; + ::aug_get(_augeas, _user_conf_path.c_str(), NULL) != 0; + string user_conf_err = "/augeas" + _user_conf_path + "/error/message"; + if (::aug_get(_augeas, user_conf_err.c_str(), value)) + error += string("\n") + value[0]; } if (!_got_global_zypper_conf && !_got_user_zypper_conf) @@ -58,8 +101,13 @@ Augeas::Augeas() } MIL << "Done reading conf files:" << endl; - MIL << "user conf read: " << (_got_user_zypper_conf ? "yes" : "no") << endl; - MIL << "global conf read: " << (_got_global_zypper_conf ? "yes" : "no") << endl; + if (want_custom) + MIL << "custom conf read: " << (_got_user_zypper_conf ? "yes" : "no") << endl; + else + { + MIL << "user conf read: " << (_got_user_zypper_conf ? "yes" : "no") << endl; + MIL << "global conf read: " << (_got_global_zypper_conf ? "yes" : "no") << endl; + } } // --------------------------------------------------------------------------- @@ -78,10 +126,12 @@ static string global_option_path( return "/files/etc/zypp/zypper.conf/" + section + "/*/" + option; } -static string user_option_path( - const string & section, const string & option, const string & homedir) +string Augeas::userOptionPath( + const string & section, const string & option) const { - return "/files" + homedir + "/.zypper.conf/" + section + "/*/" + option; + if (_user_conf_path.empty()) + return "(empty)"; + return _user_conf_path + "/" + section + "/*/" + option; } // --------------------------------------------------------------------------- @@ -118,7 +168,7 @@ string Augeas::getOption(const string & option) const if (_got_user_zypper_conf) { - string augpath_u = user_option_path(opt[0], opt[1], _homedir); + string augpath_u = userOptionPath(opt[0], opt[1]); string result = get(augpath_u); if (_last_get_result && !isCommented(opt[0], opt[1], false)) return result; @@ -147,7 +197,7 @@ TriBool Augeas::isCommented( Pathname path(global ? global_option_path(section, option) : - user_option_path(section, option, _homedir)); + userOptionPath(section, option)); TriBool result; diff --git a/src/utils/Augeas.h b/src/utils/Augeas.h index d0feebf..db2248d 100644 --- a/src/utils/Augeas.h +++ b/src/utils/Augeas.h @@ -28,7 +28,7 @@ extern "C" class Augeas : private zypp::base::NonCopyable { public: - Augeas(); + Augeas(const std::string & file = ""); ~Augeas(); std::string get(const std::string & augpath) const; @@ -42,6 +42,9 @@ public: { return _augeas; } private: + std::string userOptionPath( + const std::string & section, const std::string & option) const; + zypp::TriBool isCommented(const std::string & section, const std::string & option, bool global) const; @@ -49,6 +52,11 @@ private: private: ::augeas * _augeas; std::string _homedir; + /** + * Path of the config file in the augeas tree, + * e.g. /files/path/to/user/zypper.conf + */ + std::string _user_conf_path; bool _got_global_zypper_conf; bool _got_user_zypper_conf; -- 2.7.4