You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by vi...@apache.org on 2016/05/12 19:15:12 UTC
[6/6] mesos git commit: Added alias support for flags.
Added alias support for flags.
This lets a user to load a flag either by the original name or an
alias.
Review: https://reviews.apache.org/r/46621
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/01d4cae2
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/01d4cae2
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/01d4cae2
Branch: refs/heads/master
Commit: 01d4cae238373a667cac82892ca58c5231e35a67
Parents: eba1699
Author: Vinod Kone <vi...@gmail.com>
Authored: Sun Apr 24 15:07:51 2016 -0700
Committer: Vinod Kone <vi...@gmail.com>
Committed: Thu May 12 12:14:54 2016 -0700
----------------------------------------------------------------------
3rdparty/stout/include/stout/flags/flag.hpp | 20 ++
3rdparty/stout/include/stout/flags/flags.hpp | 212 ++++++++++++++++++----
2 files changed, 201 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/01d4cae2/3rdparty/stout/include/stout/flags/flag.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/flags/flag.hpp b/3rdparty/stout/include/stout/flags/flag.hpp
index 3a5930b..d869904 100644
--- a/3rdparty/stout/include/stout/flags/flag.hpp
+++ b/3rdparty/stout/include/stout/flags/flag.hpp
@@ -37,6 +37,11 @@ struct Name
Name(const char* _value)
: value(_value) {}
+ bool operator==(const Name& other) const
+ {
+ return value == other.value;
+ }
+
std::string value;
};
@@ -44,11 +49,26 @@ struct Name
struct Flag
{
Name name;
+ Option<Name> alias;
+
+ // This is the name that the user uses to specifically load the flag (e.g, via
+ // command line `--foo=val`). This is optional because a flag might not be
+ // explicitly loaded by the user (e.g., flag with a default value). Note that
+ // this name should be one of `name` or `alias`.
+ Option<Name> loaded_name;
+
std::string help;
bool boolean;
lambda::function<Try<Nothing>(FlagsBase*, const std::string&)> load;
lambda::function<Option<std::string>(const FlagsBase&)> stringify;
lambda::function<Option<Error>(const FlagsBase&)> validate;
+
+ // This is the name of the flag that the user loads. If the loading is
+ // implicit this defaults to the `name`.
+ const Name& effective_name() const
+ {
+ return loaded_name.isSome() ? loaded_name.get() : name;
+ }
};
} // namespace flags {
http://git-wip-us.apache.org/repos/asf/mesos/blob/01d4cae2/3rdparty/stout/include/stout/flags/flags.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/flags/flags.hpp b/3rdparty/stout/include/stout/flags/flags.hpp
index 21c9a02..02584e2 100644
--- a/3rdparty/stout/include/stout/flags/flags.hpp
+++ b/3rdparty/stout/include/stout/flags/flags.hpp
@@ -144,10 +144,22 @@ public:
void add(
T1* t1,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
const T2& t2,
F validate);
+ template <typename T1, typename T2, typename F>
+ void add(
+ T1* t1,
+ const Name& name,
+ const std::string& help,
+ const T2& t2,
+ F validate)
+ {
+ add(t1, name, None(), help, t2, validate);
+ }
+
template <typename T1, typename T2>
void add(
T1* t1,
@@ -155,23 +167,55 @@ public:
const std::string& help,
const T2& t2)
{
- add(t1, name, help, t2, [](const T1&) { return None(); });
+ add(t1, name, None(), help, t2, [](const T1&) { return None(); });
+ }
+
+ template <typename T1, typename T2>
+ void add(
+ T1* t1,
+ const Name& name,
+ const Option<Name>& alias,
+ const std::string& help,
+ const T2& t2)
+ {
+ add(t1, name, alias, help, t2, [](const T1&) { return None(); });
}
template <typename T, typename F>
void add(
Option<T>* option,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
F validate);
+ template <typename T, typename F>
+ void add(
+ Option<T>* option,
+ const Name& name,
+ const std::string& help,
+ F validate)
+ {
+ add(option, name, None(), help, validate);
+ }
+
template <typename T>
void add(
Option<T>* option,
const Name& name,
const std::string& help)
{
- add(option, name, help, [](const Option<T>&) { return None(); });
+ add(option, name, None(), help, [](const Option<T>&) { return None(); });
+ }
+
+ template <typename T>
+ void add(
+ Option<T>* option,
+ const Name& name,
+ const Option<Name>& alias,
+ const std::string& help)
+ {
+ add(option, name, alias, help, [](const Option<T>&) { return None(); });
}
protected:
@@ -179,34 +223,78 @@ protected:
void add(
T1 Flags::*t1,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
const T2& t2,
F validate);
+ template <typename Flags, typename T1, typename T2, typename F>
+ void add(
+ T1 Flags::*t1,
+ const Name& name,
+ const std::string& help,
+ const T2& t2,
+ F validate)
+ {
+ add(t1, name, None(), help, t2, validate);
+ }
+
+ template <typename Flags, typename T1, typename T2>
+ void add(
+ T1 Flags::*t1,
+ const Name& name,
+ const std::string& help,
+ const T2& t2)
+ {
+ add(t1, name, None(), help, t2, [](const T1&) { return None(); });
+ }
+
template <typename Flags, typename T1, typename T2>
void add(
T1 Flags::*t1,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
const T2& t2)
{
- add(t1, name, help, t2, [](const T1&) { return None(); });
+ add(t1, name, alias, help, t2, [](const T1&) { return None(); });
}
template <typename Flags, typename T, typename F>
void add(
Option<T> Flags::*option,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
F validate);
+ template <typename Flags, typename T, typename F>
+ void add(
+ Option<T> Flags::*option,
+ const Name& name,
+ const std::string& help,
+ F validate)
+ {
+ add(option, name, None(), help, validate);
+ }
+
template <typename Flags, typename T>
void add(
Option<T> Flags::*option,
const Name& name,
const std::string& help)
{
- add(option, name, help, [](const Option<T>&) { return None(); });
+ add(option, name, None(), help, [](const Option<T>&) { return None(); });
+ }
+
+ template <typename Flags, typename T>
+ void add(
+ Option<T> Flags::*option,
+ const Name& name,
+ const Option<Name>& alias,
+ const std::string& help)
+ {
+ add(option, name, alias, help, [](const Option<T>&) { return None(); });
}
void add(const Flag& flag);
@@ -235,7 +323,11 @@ private:
std::map<std::string, Option<std::string>> extract(
const std::string& prefix);
+ // Maps flag's name to flag.
std::map<std::string, Flag> flags_;
+
+ // Maps flag's alias to flag's name.
+ std::map<std::string, std::string> aliases;
};
@@ -261,6 +353,7 @@ template <typename T1, typename T2, typename F>
void FlagsBase::add(
T1* t1,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
const T2& t2,
F validate)
@@ -274,6 +367,7 @@ void FlagsBase::add(
Flag flag;
flag.name = name;
+ flag.alias = alias;
flag.help = help;
flag.boolean = typeid(T1) == typeid(bool);
@@ -292,6 +386,7 @@ void FlagsBase::add(
} else {
return Error("Failed to load value '" + value + "': " + t.error());
}
+
return Nothing();
};
@@ -318,6 +413,7 @@ template <typename T, typename F>
void FlagsBase::add(
Option<T>* option,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
F validate)
{
@@ -328,6 +424,7 @@ void FlagsBase::add(
Flag flag;
flag.name = name;
+ flag.alias = alias;
flag.help = help;
flag.boolean = typeid(T) == typeid(bool);
@@ -343,6 +440,7 @@ void FlagsBase::add(
} else {
return Error("Failed to load value '" + value + "': " + t.error());
}
+
return Nothing();
};
@@ -365,6 +463,7 @@ template <typename Flags, typename T1, typename T2, typename F>
void FlagsBase::add(
T1 Flags::*t1,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
const T2& t2,
F validate)
@@ -384,6 +483,7 @@ void FlagsBase::add(
Flag flag;
flag.name = name;
+ flag.alias = alias;
flag.help = help;
flag.boolean = typeid(T1) == typeid(bool);
@@ -406,6 +506,7 @@ void FlagsBase::add(
return Error("Failed to load value '" + value + "': " + t.error());
}
}
+
return Nothing();
};
@@ -440,6 +541,7 @@ template <typename Flags, typename T, typename F>
void FlagsBase::add(
Option<T> Flags::*option,
const Name& name,
+ const Option<Name>& alias,
const std::string& help,
F validate)
{
@@ -456,6 +558,7 @@ void FlagsBase::add(
Flag flag;
flag.name = name;
+ flag.alias = alias;
flag.help = help;
flag.boolean = typeid(T) == typeid(bool);
@@ -465,19 +568,20 @@ void FlagsBase::add(
flag.load =
[option](FlagsBase* base, const std::string& value) -> Try<Nothing> {
- Flags* flags = dynamic_cast<Flags*>(base);
- if (flags != NULL) {
- // NOTE: 'fetch' "retrieves" the value if necessary and then
- // invokes 'parse'. See 'fetch' for more details.
- Try<T> t = fetch<T>(value);
- if (t.isSome()) {
- flags->*option = Some(t.get());
- } else {
- return Error("Failed to load value '" + value + "': " + t.error());
- }
+ Flags* flags = dynamic_cast<Flags*>(base);
+ if (flags != NULL) {
+ // NOTE: 'fetch' "retrieves" the value if necessary and then
+ // invokes 'parse'. See 'fetch' for more details.
+ Try<T> t = fetch<T>(value);
+ if (t.isSome()) {
+ flags->*option = Some(t.get());
+ } else {
+ return Error("Failed to load value '" + value + "': " + t.error());
}
- return Nothing();
- };
+ }
+
+ return Nothing();
+ };
flag.stringify = [option](const FlagsBase& base) -> Option<std::string> {
const Flags* flags = dynamic_cast<const Flags*>(&base);
@@ -503,16 +607,33 @@ void FlagsBase::add(
inline void FlagsBase::add(const Flag& flag)
{
- if (flags_.count(flag.name.value) > 0) {
- EXIT(EXIT_FAILURE)
- << "Attempted to add duplicate flag '" << flag.name.value << "'";
- } else if (flag.name.value.find("no-") == 0) {
- EXIT(EXIT_FAILURE)
- << "Attempted to add flag '" << flag.name.value
- << "' that starts with the reserved 'no-' prefix";
+ // Check if the name and alias of the flag are valid.
+ std::vector<Name> names = {flag.name};
+ if (flag.alias.isSome()) {
+ if (flag.alias.get() == flag.name) {
+ EXIT(EXIT_FAILURE)
+ << "Attempted to add flag '" << flag.name.value << "' with an alias"
+ << " that is same as the flag name";
+ }
+
+ names.push_back(flag.alias.get());
+ }
+
+ foreach (const Name& name, names) {
+ if (flags_.count(name.value) > 0) {
+ EXIT(EXIT_FAILURE)
+ << "Attempted to add duplicate flag '" << name.value << "'";
+ } else if (name.value.find("no-") == 0) {
+ EXIT(EXIT_FAILURE)
+ << "Attempted to add flag '" << name.value
+ << "' that starts with the reserved 'no-' prefix";
+ }
}
flags_[flag.name.value] = flag;
+ if (flag.alias.isSome()) {
+ aliases[flag.alias.get().value] = flag.name.value;
+ }
}
@@ -709,7 +830,11 @@ inline Try<Nothing> FlagsBase::load(
bool is_negated = strings::startsWith(name, "no-");
std::string flag_name = !is_negated ? name : name.substr(3);
- auto iter = flags_.find(flag_name);
+
+ auto iter = aliases.count(flag_name)
+ ? flags_.find(aliases[flag_name])
+ : flags_.find(flag_name);
+
if (iter == flags_.end()) {
if (!unknowns) {
return Error("Failed to load unknown flag '" + flag_name + "'" +
@@ -719,10 +844,16 @@ inline Try<Nothing> FlagsBase::load(
}
}
- const Flag& flag = iter->second;
- std::string value_;
+ Flag* flag = &(iter->second);
+
+ if (flag->loaded_name.isSome()) {
+ return Error("Flag is already loaded via name '" +
+ flag->loaded_name->value + "'");
+ }
- if (!flag.boolean) { // Non-boolean flag.
+ // Validate the flag value.
+ std::string value_;
+ if (!flag->boolean) { // Non-boolean flag.
if (is_negated) { // Non-boolean flag cannot be loaded with "no-" prefix.
return Error("Failed to load non-boolean flag '" + flag_name +
"' via '" + name + "'");
@@ -746,10 +877,19 @@ inline Try<Nothing> FlagsBase::load(
}
}
- Try<Nothing> load = flag.load(this, value_);
+ Try<Nothing> load = flag->load(this, value_);
if (load.isError()) {
return Error("Failed to load flag '" + flag_name + "': " + load.error());
}
+
+ // TODO(vinod): Move this logic inside `Flag::load()`.
+ // Set `loaded_name` to the Name corresponding to `flag_name`.
+ if (aliases.count(flag_name)) {
+ CHECK_SOME(flag->alias);
+ flag->loaded_name = flag->alias.get();
+ } else {
+ flag->loaded_name = flag->name;
+ }
}
// Validate the flags value.
@@ -806,13 +946,22 @@ inline std::string FlagsBase::usage( const Option<std::string>& message) const
foreachvalue (const flags::Flag& flag, *this) {
if (flag.boolean) {
- col1[flag.name.value] = " --[no-]" + flag.name.value;
+ col1[flag.name.value] += " --[no-]" + flag.name.value;
+ if (flag.alias.isSome()) {
+ col1[flag.name.value] += ", --[no-]" + flag.alias->value;
+ }
} else {
- col1[flag.name.value] = " --" + flag.name.value + "=VALUE";
+ // TODO(vinod): Rename "=VALUE" to "=<VALUE>".
+ col1[flag.name.value] += " --" + flag.name.value + "=VALUE";
+ if (flag.alias.isSome()) {
+ col1[flag.name.value] += ", --" + flag.alias->value + "=VALUE";
+ }
}
width = std::max(width, col1[flag.name.value].size());
}
+ // TODO(vinod): Print the help on the next line instead of on the same line as
+ // the names.
foreachvalue (const flags::Flag& flag, *this) {
std::string line = col1[flag.name.value];
@@ -846,7 +995,8 @@ inline std::ostream& operator<<(std::ostream& stream, const FlagsBase& flags)
foreachvalue (const flags::Flag& flag, flags) {
const Option<std::string> value = flag.stringify(flags);
if (value.isSome()) {
- _flags.push_back("--" + flag.name.value + "=\"" + value.get() + '"');
+ _flags.push_back("--" + flag.effective_name().value + "=\"" +
+ value.get() + '"');
}
}