THROW_CHECK1(runtime_error, key, rv.second);
}
-const map<string, string> &
+const map<string, BeesConfig::VersionAlias> &
BeesConfig::version_aliases()
{
- static const map<string, string> s_aliases {
- { "STABLE", s_stable_version },
- { "CURRENT", s_current_version },
+ static const map<string, VersionAlias> s_aliases {
+ { "STABLE", { s_stable_version, false } },
+ { "CURRENT", { s_current_version, false } },
// bees v0.11 shipped config schema version 1. That schema is
// frozen, so the release name goes on selecting it however far
// CURRENT moves ahead.
- { "v0.11", "1" },
+ { "v0.11", { "1", true } },
};
return s_aliases;
}
+string
+BeesConfig::resolve_version(const string &name)
+{
+ const auto &aliases = version_aliases();
+ const auto found = aliases.find(name);
+ return found == aliases.end() ? name : string(found->second.target);
+}
+
BeesConfig::BeesConfig(const string &path, const Fd &fd) :
m_root_fd(fd),
m_root_path(path)
// Set version aliases
for (const auto &i : version_aliases()) {
- insert_map_unique(*s_defaults, i.first, s_defaults->at(i.second));
+ insert_map_unique(*s_defaults, i.first, s_defaults->at(i.second.target));
}
}
/// that version 1 lacks.
static constexpr const char *s_stable_version = "1";
- /** \brief Named aliases accepted wherever a config schema version is.
+ /** \brief What a version alias resolves to, and whether it can move.
+
+ A frozen alias names one fixed schema and goes on naming it however
+ far development moves ahead, so it is safe to write anywhere a
+ reference outlives the build that read it: a config file, or a
+ schema's inheritance edge.
+
+ A tracking alias resolves through one of the build constants above
+ instead, so what it names changes when that constant is bumped.
+ That is what makes it useful as a choice a person makes at the
+ outermost layer, and what makes it unsafe as stored structure --
+ an inheritance edge written as CURRENT would silently re-parent
+ itself, and become a self-edge once CURRENT reached that schema.
+ */
+ struct VersionAlias {
+ /// Concrete schema version this name resolves to.
+ const char *target;
+ /// False when @c target follows a build constant and may move.
+ bool frozen;
+ };
- Two kinds of name live here. STABLE and CURRENT track this build
- and therefore resolve through the constants above, so they name a
- different schema as the constants move. A release alias such as
- "v0.11" names a frozen schema directly and keeps naming it no
- matter how far development has moved on.
+ /** \brief Named aliases accepted wherever a config schema version is.
Every consumer resolves through this one table so a name cannot
mean one thing in the defaults map and another somewhere else.
*/
- static const map<string, string> &version_aliases();
+ static const map<string, VersionAlias> &version_aliases();
+
+ /// Resolve @p name through version_aliases(). Returns @p name unchanged
+ /// when it is not an alias, so callers can pass either and check the
+ /// result against the registered versions once.
+ static string resolve_version(const string &name);
/// Hierarchy of Innies (one per config layer)
Innie m_argv; ///< Values provided via command-line flags.