1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-29 02:11:15 +02:00

Merge remote-tracking branch 'upstream/master' into single-ca-drv-build

This commit is contained in:
John Ericson 2020-09-01 18:01:48 +00:00
commit ef278d00f9
267 changed files with 12456 additions and 17851 deletions

View file

@ -3,6 +3,8 @@
#include <glob.h>
#include <nlohmann/json.hpp>
namespace nix {
void Args::addFlag(Flag && flag_)
@ -205,6 +207,43 @@ bool Args::processArgs(const Strings & args, bool finish)
return res;
}
nlohmann::json Args::toJSON()
{
auto flags = nlohmann::json::object();
for (auto & [name, flag] : longFlags) {
auto j = nlohmann::json::object();
if (flag->shortName)
j["shortName"] = std::string(1, flag->shortName);
if (flag->description != "")
j["description"] = flag->description;
if (flag->category != "")
j["category"] = flag->category;
if (flag->handler.arity != ArityAny)
j["arity"] = flag->handler.arity;
if (!flag->labels.empty())
j["labels"] = flag->labels;
flags[name] = std::move(j);
}
auto args = nlohmann::json::array();
for (auto & arg : expectedArgs) {
auto j = nlohmann::json::object();
j["label"] = arg.label;
j["optional"] = arg.optional;
if (arg.handler.arity != ArityAny)
j["arity"] = arg.handler.arity;
args.push_back(std::move(j));
}
auto res = nlohmann::json::object();
res["description"] = description();
res["flags"] = std::move(flags);
res["args"] = std::move(args);
return res;
}
static void hashTypeCompleter(size_t index, std::string_view prefix)
{
for (auto & type : hashTypes)
@ -313,11 +352,29 @@ void Command::printHelp(const string & programName, std::ostream & out)
}
}
nlohmann::json Command::toJSON()
{
auto exs = nlohmann::json::array();
for (auto & example : examples()) {
auto ex = nlohmann::json::object();
ex["description"] = example.description;
ex["command"] = chomp(stripIndentation(example.command));
exs.push_back(std::move(ex));
}
auto res = Args::toJSON();
res["examples"] = std::move(exs);
auto s = doc();
if (s != "") res.emplace("doc", stripIndentation(s));
return res;
}
MultiCommand::MultiCommand(const Commands & commands)
: commands(commands)
{
expectArgs({
.label = "command",
.label = "subcommand",
.optional = true,
.handler = {[=](std::string s) {
assert(!command);
@ -387,4 +444,20 @@ bool MultiCommand::processArgs(const Strings & args, bool finish)
return Args::processArgs(args, finish);
}
nlohmann::json MultiCommand::toJSON()
{
auto cmds = nlohmann::json::object();
for (auto & [name, commandFun] : commands) {
auto command = commandFun();
auto j = command->toJSON();
j["category"] = categories[command->category()];
cmds[name] = std::move(j);
}
auto res = Args::toJSON();
res["commands"] = std::move(cmds);
return res;
}
}

View file

@ -4,6 +4,8 @@
#include <map>
#include <memory>
#include <nlohmann/json_fwd.hpp>
#include "util.hh"
namespace nix {
@ -20,6 +22,7 @@ public:
virtual void printHelp(const string & programName, std::ostream & out);
/* Return a short one-line description of the command. */
virtual std::string description() { return ""; }
protected:
@ -203,6 +206,8 @@ public:
});
}
virtual nlohmann::json toJSON();
friend class MultiCommand;
};
@ -217,6 +222,9 @@ struct Command : virtual Args
virtual void prepare() { };
virtual void run() = 0;
/* Return documentation about this command, in Markdown format. */
virtual std::string doc() { return ""; }
struct Example
{
std::string description;
@ -234,6 +242,8 @@ struct Command : virtual Args
virtual Category category() { return catDefault; }
void printHelp(const string & programName, std::ostream & out) override;
nlohmann::json toJSON() override;
};
typedef std::map<std::string, std::function<ref<Command>()>> Commands;
@ -259,6 +269,8 @@ public:
bool processFlag(Strings::iterator & pos, Strings::iterator end) override;
bool processArgs(const Strings & args, bool finish) override;
nlohmann::json toJSON() override;
};
Strings argvToStrings(int argc, char * * argv);

View file

@ -1,6 +1,7 @@
#include "config.hh"
#include "args.hh"
#include "json.hh"
#include <nlohmann/json.hpp>
namespace nix {
@ -131,15 +132,18 @@ void Config::resetOverriden()
s.second.setting->overriden = false;
}
void Config::toJSON(JSONObject & out)
nlohmann::json Config::toJSON()
{
auto res = nlohmann::json::object();
for (auto & s : _settings)
if (!s.second.isAlias) {
JSONObject out2(out.object(s.first));
out2.attr("description", s.second.setting->description);
JSONPlaceholder out3(out2.placeholder("value"));
s.second.setting->toJSON(out3);
auto obj = nlohmann::json::object();
obj.emplace("description", s.second.setting->description);
obj.emplace("aliases", s.second.setting->aliases);
obj.emplace("value", s.second.setting->toJSON());
res.emplace(s.first, obj);
}
return res;
}
void Config::convertToArgs(Args & args, const std::string & category)
@ -153,7 +157,7 @@ AbstractSetting::AbstractSetting(
const std::string & name,
const std::string & description,
const std::set<std::string> & aliases)
: name(name), description(description), aliases(aliases)
: name(name), description(stripIndentation(description)), aliases(aliases)
{
}
@ -162,9 +166,9 @@ void AbstractSetting::setDefault(const std::string & str)
if (!overriden) set(str);
}
void AbstractSetting::toJSON(JSONPlaceholder & out)
nlohmann::json AbstractSetting::toJSON()
{
out.write(to_string());
return to_string();
}
void AbstractSetting::convertToArg(Args & args, const std::string & category)
@ -172,9 +176,9 @@ void AbstractSetting::convertToArg(Args & args, const std::string & category)
}
template<typename T>
void BaseSetting<T>::toJSON(JSONPlaceholder & out)
nlohmann::json BaseSetting<T>::toJSON()
{
out.write(value);
return value;
}
template<typename T>
@ -255,11 +259,9 @@ template<> std::string BaseSetting<Strings>::to_string() const
return concatStringsSep(" ", value);
}
template<> void BaseSetting<Strings>::toJSON(JSONPlaceholder & out)
template<> nlohmann::json BaseSetting<Strings>::toJSON()
{
JSONList list(out.list());
for (auto & s : value)
list.elem(s);
return value;
}
template<> void BaseSetting<StringSet>::set(const std::string & str)
@ -272,11 +274,9 @@ template<> std::string BaseSetting<StringSet>::to_string() const
return concatStringsSep(" ", value);
}
template<> void BaseSetting<StringSet>::toJSON(JSONPlaceholder & out)
template<> nlohmann::json BaseSetting<StringSet>::toJSON()
{
JSONList list(out.list());
for (auto & s : value)
list.elem(s);
return value;
}
template class BaseSetting<int>;
@ -323,10 +323,12 @@ void GlobalConfig::resetOverriden()
config->resetOverriden();
}
void GlobalConfig::toJSON(JSONObject & out)
nlohmann::json GlobalConfig::toJSON()
{
auto res = nlohmann::json::object();
for (auto & config : *configRegistrations)
config->toJSON(out);
res.update(config->toJSON());
return res;
}
void GlobalConfig::convertToArgs(Args & args, const std::string & category)

View file

@ -4,6 +4,8 @@
#include "types.hh"
#include <nlohmann/json_fwd.hpp>
#pragma once
namespace nix {
@ -42,8 +44,6 @@ namespace nix {
class Args;
class AbstractSetting;
class JSONPlaceholder;
class JSONObject;
class AbstractConfig
{
@ -97,7 +97,7 @@ public:
* Outputs all settings to JSON
* - out: JSONObject to write the configuration to
*/
virtual void toJSON(JSONObject & out) = 0;
virtual nlohmann::json toJSON() = 0;
/**
* Converts settings to `Args` to be used on the command line interface
@ -167,7 +167,7 @@ public:
void resetOverriden() override;
void toJSON(JSONObject & out) override;
nlohmann::json toJSON() override;
void convertToArgs(Args & args, const std::string & category) override;
};
@ -206,7 +206,7 @@ protected:
virtual std::string to_string() const = 0;
virtual void toJSON(JSONPlaceholder & out);
virtual nlohmann::json toJSON();
virtual void convertToArg(Args & args, const std::string & category);
@ -251,7 +251,7 @@ public:
void convertToArg(Args & args, const std::string & category) override;
void toJSON(JSONPlaceholder & out) override;
nlohmann::json toJSON() override;
};
template<typename T>
@ -319,7 +319,7 @@ struct GlobalConfig : public AbstractConfig
void resetOverriden() override;
void toJSON(JSONObject & out) override;
nlohmann::json toJSON() override;
void convertToArgs(Args & args, const std::string & category) override;

View file

@ -37,10 +37,12 @@ typedef uint64_t ActivityId;
struct LoggerSettings : Config
{
Setting<bool> showTrace{this,
false,
"show-trace",
"Whether to show a stack trace on evaluation errors."};
Setting<bool> showTrace{
this, false, "show-trace",
R"(
Where Nix should print out a stack trace in case of Nix
expression evaluation errors.
)"};
};
extern LoggerSettings loggerSettings;

View file

@ -1,9 +1,9 @@
#include "json.hh"
#include "config.hh"
#include "args.hh"
#include <sstream>
#include <gtest/gtest.h>
#include <nlohmann/json.hpp>
namespace nix {
@ -33,7 +33,7 @@ namespace nix {
const auto iter = settings.find("name-of-the-setting");
ASSERT_NE(iter, settings.end());
ASSERT_EQ(iter->second.value, "");
ASSERT_EQ(iter->second.description, "description");
ASSERT_EQ(iter->second.description, "description\n");
}
TEST(Config, getDefinedOverridenSettingNotSet) {
@ -59,7 +59,7 @@ namespace nix {
const auto iter = settings.find("name-of-the-setting");
ASSERT_NE(iter, settings.end());
ASSERT_EQ(iter->second.value, "value");
ASSERT_EQ(iter->second.description, "description");
ASSERT_EQ(iter->second.description, "description\n");
}
TEST(Config, getDefinedSettingSet2) {
@ -73,7 +73,7 @@ namespace nix {
const auto e = settings.find("name-of-the-setting");
ASSERT_NE(e, settings.end());
ASSERT_EQ(e->second.value, "value");
ASSERT_EQ(e->second.description, "description");
ASSERT_EQ(e->second.description, "description\n");
}
TEST(Config, addSetting) {
@ -152,29 +152,16 @@ namespace nix {
}
TEST(Config, toJSONOnEmptyConfig) {
std::stringstream out;
{ // Scoped to force the destructor of JSONObject to write the final `}`
JSONObject obj(out);
Config config;
config.toJSON(obj);
}
ASSERT_EQ(out.str(), "{}");
ASSERT_EQ(Config().toJSON().dump(), "{}");
}
TEST(Config, toJSONOnNonEmptyConfig) {
std::stringstream out;
{ // Scoped to force the destructor of JSONObject to write the final `}`
JSONObject obj(out);
Config config;
std::map<std::string, Config::SettingInfo> settings;
Setting<std::string> setting{&config, "", "name-of-the-setting", "description"};
setting.assign("value");
Config config;
std::map<std::string, Config::SettingInfo> settings;
Setting<std::string> setting{&config, "", "name-of-the-setting", "description"};
setting.assign("value");
config.toJSON(obj);
}
ASSERT_EQ(out.str(), R"#({"name-of-the-setting":{"description":"description","value":"value"}})#");
ASSERT_EQ(config.toJSON().dump(), R"#({"name-of-the-setting":{"aliases":[],"description":"description\n","value":"value"}})#");
}
TEST(Config, setSettingAlias) {

View file

@ -1464,6 +1464,47 @@ string base64Decode(std::string_view s)
}
std::string stripIndentation(std::string_view s)
{
size_t minIndent = 10000;
size_t curIndent = 0;
bool atStartOfLine = true;
for (auto & c : s) {
if (atStartOfLine && c == ' ')
curIndent++;
else if (c == '\n') {
if (atStartOfLine)
minIndent = std::max(minIndent, curIndent);
curIndent = 0;
atStartOfLine = true;
} else {
if (atStartOfLine) {
minIndent = std::min(minIndent, curIndent);
atStartOfLine = false;
}
}
}
std::string res;
size_t pos = 0;
while (pos < s.size()) {
auto eol = s.find('\n', pos);
if (eol == s.npos) eol = s.size();
if (eol - pos > minIndent)
res.append(s.substr(pos + minIndent, eol - pos - minIndent));
res.push_back('\n');
pos = eol + 1;
}
return res;
}
//////////////////////////////////////////////////////////////////////
static Sync<std::pair<unsigned short, unsigned short>> windowSize{{0, 0}};

View file

@ -464,6 +464,12 @@ string base64Encode(std::string_view s);
string base64Decode(std::string_view s);
/* Remove common leading whitespace from the lines in the string
's'. For example, if every line is indented by at least 3 spaces,
then we remove 3 spaces from the start of every line. */
std::string stripIndentation(std::string_view s);
/* Get a value for the specified key from an associate container. */
template <class T>
std::optional<typename T::mapped_type> get(const T & map, const typename T::key_type & key)