forked from lix-project/lix
Rework a few things with the experimental features list
- Use struct not `std::pair`, designated initializers - Use `constexpr` array that we can index by enum tag - It no longer segfaults; not sure why.
This commit is contained in:
parent
b2c9315bf2
commit
2585bcaa50
|
@ -5,75 +5,131 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
std::map<ExperimentalFeature, std::pair<std::string, std::string>> stringifiedXpFeatures = {
|
struct ExperimentalFeatureDetails
|
||||||
{ Xp::CaDerivations, {"ca-derivations", R"(
|
{
|
||||||
|
ExperimentalFeature tag;
|
||||||
|
std::string_view name;
|
||||||
|
std::string_view description;
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<ExperimentalFeatureDetails, 11> xpFeatureDetails = {{
|
||||||
|
{
|
||||||
|
.tag = Xp::CaDerivations,
|
||||||
|
.name = "ca-derivations",
|
||||||
|
.description = R"(
|
||||||
Allows derivations to be content-addressed in order to prevent rebuilds
|
Allows derivations to be content-addressed in order to prevent rebuilds
|
||||||
when changes to the derivation do not result in changes to the
|
when changes to the derivation do not result in changes to the
|
||||||
derivation's output. See
|
derivation's output. See
|
||||||
[__contentAddressed](../language/advanced-attributes.md#adv-attr-__contentAddressed)
|
[__contentAddressed](../language/advanced-attributes.md#adv-attr-__contentAddressed)
|
||||||
for more info.
|
for more info.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::ImpureDerivations, {"impure-derivations", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::ImpureDerivations,
|
||||||
|
.name = "impure-derivations",
|
||||||
|
.description = R"(
|
||||||
Allows derivations to produce non-fixed outputs by setting the `__impure`
|
Allows derivations to produce non-fixed outputs by setting the `__impure`
|
||||||
derivation attribute to `true`. See [these release
|
derivation attribute to `true`. See [these release
|
||||||
notes](../release-notes/rl-2.8.md) for an example.
|
notes](../release-notes/rl-2.8.md) for an example.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::Flakes, {"flakes", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::Flakes,
|
||||||
|
.name = "flakes",
|
||||||
|
.description = R"(
|
||||||
Allows for derivations to be packaged in flakes. See the manual entry for
|
Allows for derivations to be packaged in flakes. See the manual entry for
|
||||||
[`nix flake`](../command-ref/new-cli/nix3-flake.md) or this [detailed
|
[`nix flake`](../command-ref/new-cli/nix3-flake.md) or this [detailed
|
||||||
introduction](https://www.tweag.io/blog/2020-05-25-flakes/) for more info.
|
introduction](https://www.tweag.io/blog/2020-05-25-flakes/) for more info.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::NixCommand, {"nix-command", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::NixCommand,
|
||||||
|
.name = "nix-command",
|
||||||
|
.description = R"(
|
||||||
Allows the usage of the new `nix` CLI subcommands, such as `nix build`, `nix
|
Allows the usage of the new `nix` CLI subcommands, such as `nix build`, `nix
|
||||||
develop`, `nix run`, etc. See the manual for
|
develop`, `nix run`, etc. See the manual for
|
||||||
[`nix`](../command-ref/new-cli/nix.md) for more info.
|
[`nix`](../command-ref/new-cli/nix.md) for more info.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::RecursiveNix, {"recursive-nix", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::RecursiveNix,
|
||||||
|
.name = "recursive-nix",
|
||||||
|
.description = R"(
|
||||||
Allow Nix derivations to call Nix in order to recursively build derivations.
|
Allow Nix derivations to call Nix in order to recursively build derivations.
|
||||||
See [this
|
See [this
|
||||||
commit](https://github.com/edolstra/nix/commit/1a27aa7d64ffe6fc36cfca4d82bdf51c4d8cf717)
|
commit](https://github.com/edolstra/nix/commit/1a27aa7d64ffe6fc36cfca4d82bdf51c4d8cf717)
|
||||||
for more info.
|
for more info.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::NoUrlLiterals, {"no-url-literals", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::NoUrlLiterals,
|
||||||
|
.name = "no-url-literals",
|
||||||
|
.description = R"(
|
||||||
Disallows unquoted URLs as part of the Nix language syntax. See [RFC
|
Disallows unquoted URLs as part of the Nix language syntax. See [RFC
|
||||||
45](https://github.com/NixOS/rfcs/pull/45) for more info.
|
45](https://github.com/NixOS/rfcs/pull/45) for more info.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::FetchClosure, {"fetch-closure", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::FetchClosure,
|
||||||
|
.name = "fetch-closure",
|
||||||
|
.description = R"(
|
||||||
Enables the use of the `fetchClosure` function in the standard library. See
|
Enables the use of the `fetchClosure` function in the standard library. See
|
||||||
the docs for [`fetchClosure`](../language/builtins.md#builtins-fetchClosure)
|
the docs for [`fetchClosure`](../language/builtins.md#builtins-fetchClosure)
|
||||||
for more info.
|
for more info.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::ReplFlake, {"repl-flake", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::ReplFlake,
|
||||||
|
.name = "repl-flake",
|
||||||
|
.description = R"(
|
||||||
Allows the user to enter a Nix REPL within a flake, e.g. `nix repl nixpkgs`
|
Allows the user to enter a Nix REPL within a flake, e.g. `nix repl nixpkgs`
|
||||||
or `nix repl .#foo`.
|
or `nix repl .#foo`.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::AutoAllocateUids, {"auto-allocate-uids", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::AutoAllocateUids,
|
||||||
|
.name = "auto-allocate-uids",
|
||||||
|
.description = R"(
|
||||||
Allows Nix to automatically pick UIDs for builds, rather than creating
|
Allows Nix to automatically pick UIDs for builds, rather than creating
|
||||||
`nixbld*` user accounts. See [here](#conf-auto-allocate-uids) for more info.
|
`nixbld*` user accounts. See [here](#conf-auto-allocate-uids) for more info.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::Cgroups, {"cgroups", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::Cgroups,
|
||||||
|
.name = "cgroups",
|
||||||
|
.description = R"(
|
||||||
Allows Nix to execute builds inside cgroups. See
|
Allows Nix to execute builds inside cgroups. See
|
||||||
[`use-cgroups`](#conf-use-cgroups) for more info.
|
[`use-cgroups`](#conf-use-cgroups) for more info.
|
||||||
)"} },
|
)",
|
||||||
{ Xp::DiscardReferences, {"discard-references", R"(
|
},
|
||||||
|
{
|
||||||
|
.tag = Xp::DiscardReferences,
|
||||||
|
.name = "discard-references",
|
||||||
|
.description = R"(
|
||||||
Enables the use of the `unsafeDiscardReferences` attribute in derivations
|
Enables the use of the `unsafeDiscardReferences` attribute in derivations
|
||||||
that use structured attributes. This disables scanning of outputs for
|
that use structured attributes. This disables scanning of outputs for
|
||||||
runtime dependencies.
|
runtime dependencies.
|
||||||
)"} },
|
)",
|
||||||
};
|
},
|
||||||
|
}};
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
[]() constexpr {
|
||||||
|
for (auto [index, feature] : enumerate(xpFeatureDetails))
|
||||||
|
if (index != (size_t)feature.tag)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}(),
|
||||||
|
"array order does not match enum tag order");
|
||||||
|
|
||||||
const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::string_view & name)
|
const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::string_view & name)
|
||||||
{
|
{
|
||||||
using ReverseXpMap = std::map<std::string_view, ExperimentalFeature>;
|
using ReverseXpMap = std::map<std::string_view, ExperimentalFeature>;
|
||||||
|
|
||||||
static auto reverseXpMap = []()
|
static std::unique_ptr<ReverseXpMap> reverseXpMap = [](){
|
||||||
{
|
|
||||||
auto reverseXpMap = std::make_unique<ReverseXpMap>();
|
auto reverseXpMap = std::make_unique<ReverseXpMap>();
|
||||||
std::string_view name;
|
for (auto & xpFeature : xpFeatureDetails)
|
||||||
for (auto & [feature, featureStringPair] : stringifiedXpFeatures) {
|
(*reverseXpMap)[xpFeature.name] = xpFeature.tag;
|
||||||
name = featureStringPair.first;
|
|
||||||
(*reverseXpMap)[name] = feature;
|
|
||||||
}
|
|
||||||
return reverseXpMap;
|
return reverseXpMap;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
@ -83,11 +139,10 @@ const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::str
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view showExperimentalFeature(const ExperimentalFeature feature)
|
std::string_view showExperimentalFeature(const ExperimentalFeature tag)
|
||||||
{
|
{
|
||||||
const auto ret = get(stringifiedXpFeatures, feature);
|
assert((size_t)tag < xpFeatureDetails.size());
|
||||||
assert(ret);
|
return xpFeatureDetails[(size_t)tag].name;
|
||||||
return ret->first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getExperimentalFeaturesList() {
|
std::string getExperimentalFeaturesList() {
|
||||||
|
@ -97,11 +152,16 @@ std::string getExperimentalFeaturesList() {
|
||||||
|
|
||||||
)";
|
)";
|
||||||
|
|
||||||
std::string experimentalFeatureString;
|
for (auto & xpFeature : xpFeatureDetails) {
|
||||||
for (auto& [feature, featureStringPair] : stringifiedXpFeatures) {
|
experimentalFeaturesList += std::string {}
|
||||||
experimentalFeatureString = " - `" + featureStringPair.first + "`\n";
|
/* length of this first string must be 12, matching the indent of
|
||||||
experimentalFeatureString += featureStringPair.second + "\n\n";
|
the descriptions in the xpFeatureDetails literal. FIXME compute
|
||||||
experimentalFeaturesList += experimentalFeatureString;
|
markdown in a less hacky way. */
|
||||||
|
+ " - "
|
||||||
|
+ "`" + xpFeature.name + "`"
|
||||||
|
+ "\n"
|
||||||
|
+ xpFeature.description
|
||||||
|
+ "\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return experimentalFeaturesList;
|
return experimentalFeaturesList;
|
||||||
|
@ -110,10 +170,9 @@ std::string getExperimentalFeaturesList() {
|
||||||
std::set<ExperimentalFeature> parseFeatures(const std::set<std::string> & rawFeatures)
|
std::set<ExperimentalFeature> parseFeatures(const std::set<std::string> & rawFeatures)
|
||||||
{
|
{
|
||||||
std::set<ExperimentalFeature> res;
|
std::set<ExperimentalFeature> res;
|
||||||
for (auto & rawFeature : rawFeatures) {
|
for (auto & rawFeature : rawFeatures)
|
||||||
if (auto feature = parseExperimentalFeature(rawFeature))
|
if (auto feature = parseExperimentalFeature(rawFeature))
|
||||||
res.insert(*feature);
|
res.insert(*feature);
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,9 @@ namespace nix {
|
||||||
/**
|
/**
|
||||||
* The list of available experimental features.
|
* The list of available experimental features.
|
||||||
*
|
*
|
||||||
* If you update this, don’t forget to also change the map defining their string
|
* If you update this, don’t forget to also change the map defining
|
||||||
* representation and documentation in the corresponding `.cc` file as well.
|
* their string representation and documentation in the corresponding
|
||||||
|
* `.cc` file as well.
|
||||||
*/
|
*/
|
||||||
enum struct ExperimentalFeature
|
enum struct ExperimentalFeature
|
||||||
{
|
{
|
||||||
|
|
|
@ -730,16 +730,16 @@ constexpr auto enumerate(T && iterable)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
TIter iter;
|
TIter iter;
|
||||||
bool operator != (const iterator & other) const { return iter != other.iter; }
|
constexpr bool operator != (const iterator & other) const { return iter != other.iter; }
|
||||||
void operator ++ () { ++i; ++iter; }
|
constexpr void operator ++ () { ++i; ++iter; }
|
||||||
auto operator * () const { return std::tie(i, *iter); }
|
constexpr auto operator * () const { return std::tie(i, *iter); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iterable_wrapper
|
struct iterable_wrapper
|
||||||
{
|
{
|
||||||
T iterable;
|
T iterable;
|
||||||
auto begin() { return iterator{ 0, std::begin(iterable) }; }
|
constexpr auto begin() { return iterator{ 0, std::begin(iterable) }; }
|
||||||
auto end() { return iterator{ 0, std::end(iterable) }; }
|
constexpr auto end() { return iterator{ 0, std::end(iterable) }; }
|
||||||
};
|
};
|
||||||
|
|
||||||
return iterable_wrapper{ std::forward<T>(iterable) };
|
return iterable_wrapper{ std::forward<T>(iterable) };
|
||||||
|
|
Loading…
Reference in a new issue