Skip to content

Commit

Permalink
Make releasever_major, releasever_minor read-only
Browse files Browse the repository at this point in the history
  • Loading branch information
evan-goode committed Aug 24, 2023
1 parent 341d037 commit 975b8c9
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 23 deletions.
7 changes: 6 additions & 1 deletion dnf5/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,12 @@ void RootCommand::set_argument_parser() {
throw libdnf5::cli::ArgumentParserError(M_("setvar: Badly formatted argument value \"{}\""), value);
}
auto name = std::string(value, val);
ctx.base.get_vars()->set(name, val + 1, libdnf5::Vars::Priority::COMMANDLINE);
try {
ctx.base.get_vars()->set(name, val + 1, libdnf5::Vars::Priority::COMMANDLINE);
} catch (libdnf5::Error & ex) {
std::string message{ex.what()};
throw libdnf5::cli::ArgumentParserError(M_("setvar: {}"), message);
}
return true;
});
global_options_group->register_argument(setvar);
Expand Down
8 changes: 7 additions & 1 deletion include/libdnf5/conf/vars.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
#include "libdnf5/base/base_weak.hpp"

#include <map>
#include <set>
#include <string>
#include <vector>


namespace libdnf5 {

/// @class Vars
Expand Down Expand Up @@ -70,6 +70,12 @@ struct Vars {
/// @param prio Source/Priority of the value
void set(const std::string & name, const std::string & value, Priority prio = Priority::RUNTIME);

/// @brief Checks whether a variable is read-only
///
/// @param name Name of the variable
/// @return true if the variable is read-only, false if it is writable
bool is_read_only(const std::string & name);

/// @brief Checks if there is an variable with name equivalent to name in the container.
///
/// @param name Name of the variable
Expand Down
67 changes: 46 additions & 21 deletions libdnf5/conf/vars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ extern char ** environ;

namespace libdnf5 {

static const std::unordered_set<std::string> READ_ONLY_VARIABLES = {"releasever_major", "releasever_minor"};

// ==================================================================
// The following helper functions should be moved e.g. into a library

Expand Down Expand Up @@ -180,11 +182,13 @@ std::unique_ptr<std::string> Vars::detect_release(const BaseWeakPtr & base, cons

Vars::Vars(Base & base) : Vars(base.get_weak_ptr()) {}

std::string Vars::substitute(const std::string & text) const {
return substitute_expression(text, 0).first;
}

const unsigned int MAXIMUM_EXPRESSION_DEPTH = 32;

// Expand variables in a subexpression
//
// @param text String with variable expressions
// @param depth The recursive depth
// @return Pair of the resulting string and the number of characters scanned in `text`
std::pair<std::string, size_t> Vars::substitute_expression(const std::string_view & text, unsigned int depth) const {
if (depth > MAXIMUM_EXPRESSION_DEPTH) {
return std::make_pair(std::string(text), text.length());
Expand Down Expand Up @@ -346,6 +350,10 @@ std::pair<std::string, size_t> Vars::substitute_expression(const std::string_vie
return std::make_pair(res, text.length());
}

std::string Vars::substitute(const std::string & text) const {
return substitute_expression(text, 0).first;
}

std::tuple<std::string, std::string> Vars::split_releasever(const std::string & releasever) {
// Uses the same logic as splitReleaseverTo in libzypp
std::string releasever_major;
Expand All @@ -360,27 +368,44 @@ std::tuple<std::string, std::string> Vars::split_releasever(const std::string &
return std::make_tuple(releasever_major, releasever_minor);
}

void Vars::set(const std::string & name, const std::string & value, Priority prio) {
auto it = variables.find(name);
bool Vars::is_read_only(const std::string & name) {
return READ_ONLY_VARIABLES.contains(name);
}

// Do nothing if the var is already set with a higher priority
if (it != variables.end() && prio < it->second.priority) {
return;
void Vars::set(const std::string & name, const std::string & value, Priority prio) {
if (is_read_only(name)) {
throw RuntimeError(M_("Variable \"{}\" is read-only"), name);
}

// Whenever releasever is set, split it into major and minor parts
if (name == "releasever") {
const auto [releasever_major, releasever_minor] = split_releasever(value);
set("releasever_major", releasever_major, prio);
set("releasever_minor", releasever_minor, prio);
}
// set_unsafe sets the variable without checking whether it's read-only
std::function<void(const std::string, const std::string, Priority)> set_unsafe =
[&](const std::string & name, const std::string & value, Priority prio) {
auto it = variables.find(name);

if (it == variables.end()) {
variables.insert({name, {value, prio}});
} else {
it->second.value = value;
it->second.priority = prio;
}
// Do nothing if the var is already set with a higher priority
if (it != variables.end() && prio < it->second.priority) {
return;
}

// Whenever releasever is set, split it into major and minor parts
if (name == "releasever") {
const auto [releasever_major, releasever_minor] = split_releasever(value);
if (!releasever_major.empty()) {
set_unsafe("releasever_major", releasever_major, prio);
}
if (!releasever_minor.empty()) {
set_unsafe("releasever_minor", releasever_minor, prio);
}
}

if (it == variables.end()) {
variables.insert({name, {value, prio}});
} else {
it->second.value = value;
it->second.priority = prio;
}
};
set_unsafe(name, value, prio);
}

void Vars::set_lazy(
Expand Down

0 comments on commit 975b8c9

Please sign in to comment.