Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/manual/source/protocols/flake-schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Both leaf and non-leaf nodes can have the following attributes:
| Attribute | Description |
| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `forSystems` | A list of Nix system types (e.g. `["x86_64-linux"]`) supported by this node. This is used by tools to skip nodes that cannot be built on the user's system. Setting this on a non-leaf node allows all the children to be skipped, regardless of the `forSystems` attributes of the children. If this attribute is not set, the node is never skipped. |
| `isLegacy` | If set to true, this node is skipped unless the `--legacy` CLI flag is set. |

# Example

Expand Down
8 changes: 7 additions & 1 deletion src/libcmd/builtin-flake-schemas.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
let
mapAttrsToList = f: attrs: map (name: f name attrs.${name}) (builtins.attrNames attrs);

checkModule = module: builtins.isAttrs module || builtins.isFunction module;
checkModule =
module_:
let
module = if builtins.isPath module_ then import module_ else module_;
in
builtins.isAttrs module || builtins.isFunction module;

schemasSchema = {
version = 1;
Expand Down Expand Up @@ -105,6 +110,7 @@
self.lib.mkChildren (
builtins.mapAttrs (systemType: packagesForSystem: {
forSystems = [ systemType ];
isLegacy = true;
children =
let
recurse =
Expand Down
14 changes: 12 additions & 2 deletions src/libcmd/flake-schemas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,23 @@ void forEachOutput(

void visit(
std::optional<std::string> system,
bool includeLegacy,
ref<AttrCursor> node,
std::function<void(const Leaf & leaf)> visitLeaf,
std::function<void(std::function<void(ForEachChild)>)> visitNonLeaf,
std::function<void(ref<AttrCursor> node, const std::vector<std::string> & systems)> visitFiltered)
std::function<void(ref<AttrCursor> node, const std::vector<std::string> & systems)> visitFiltered,
std::function<void(ref<AttrCursor> node)> visitLegacy)
{
Activity act(*logger, lvlInfo, actUnknown, fmt("evaluating '%s'", node->getAttrPathStr()));

/* Filter out legacy outputs, unless --legacy is enabled. */
if (!includeLegacy) {
if (auto b = node->maybeGetAttr("isLegacy"); b && b->getBool()) {
visitLegacy(node);
return;
}
}

/* Apply the system type filter. */
if (system) {
if (auto forSystems = Node(node).forSystems()) {
Expand All @@ -185,7 +195,7 @@ void visit(
try {
f(attrName, children->getAttr(attrName), i + 1 == attrNames.size());
} catch (Error & e) {
// FIXME: make it a flake schema attribute whether to ignore evaluation errors.
// FIXME: use the `isLegacy` attribute.
if (node->root->state.symbols[node->getAttrPath()[0]] != "legacyPackages") {
e.addTrace(
nullptr, "while evaluating the flake output attribute '%s':", node->getAttrPathStr());
Expand Down
4 changes: 3 additions & 1 deletion src/libcmd/include/nix/cmd/flake-schemas.hh
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ typedef std::function<void(Symbol attrName, ref<AttrCursor> attr, bool isLast)>

void visit(
std::optional<std::string> system,
bool includeLegacy,
ref<AttrCursor> node,
std::function<void(const Leaf & leaf)> visitLeaf,
std::function<void(std::function<void(ForEachChild)>)> visitNonLeaf,
std::function<void(ref<AttrCursor> node, const std::vector<std::string> & systems)> visitFiltered);
std::function<void(ref<AttrCursor> node, const std::vector<std::string> & systems)> visitFiltered,
std::function<void(ref<AttrCursor> node)> visitLegacy);

struct OutputInfo
{
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/parallel-eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ void FutureVector::finishAll()
} catch (...) {
if (ex) {
if (!getInterrupted())
ignoreExceptionExceptInterrupt();
logExceptionExceptInterrupt();
} else
ex = std::current_exception();
}
Expand Down
5 changes: 5 additions & 0 deletions src/libutil/include/nix/util/util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ void ignoreExceptionInDestructor(Verbosity lvl = lvlError);
*/
void ignoreExceptionExceptInterrupt(Verbosity lvl = lvlError);

/**
* Like ignoreExceptionExceptInterrupt(), but specifies the error prefix.
*/
void logExceptionExceptInterrupt(std::string_view prefix = "error: ", Verbosity lvl = lvlError);

/**
* Tree formatting.
*/
Expand Down
9 changes: 7 additions & 2 deletions src/libutil/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,20 @@ void ignoreExceptionInDestructor(Verbosity lvl)
}

void ignoreExceptionExceptInterrupt(Verbosity lvl)
{
logExceptionExceptInterrupt("error (ignored): ", lvl);
}

void logExceptionExceptInterrupt(std::string_view prefix, Verbosity lvl)
{
try {
throw;
} catch (const Interrupted & e) {
throw;
} catch (Error & e) {
printMsg(lvl, ANSI_RED "error (ignored):" ANSI_NORMAL " %s", e.info().msg);
printMsg(lvl, ANSI_RED "%s" ANSI_NORMAL "%s", prefix, e.info().msg);
} catch (std::exception & e) {
printMsg(lvl, ANSI_RED "error (ignored):" ANSI_NORMAL " %s", e.what());
printMsg(lvl, ANSI_RED "%s" ANSI_NORMAL "%s", prefix, e.what());
}
}

Expand Down
20 changes: 13 additions & 7 deletions src/nix/flake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ struct CmdFlakeCheck : FlakeCommand, MixFlakeSchemas
visit = [&](ref<eval_cache::AttrCursor> node) {
flake_schemas::visit(
checkAllSystems ? std::optional<std::string>() : localSystem,
false, // FIXME: add a --legacy flag?
node,

[&](const flake_schemas::Leaf & leaf) {
Expand Down Expand Up @@ -452,7 +453,9 @@ struct CmdFlakeCheck : FlakeCommand, MixFlakeSchemas
[&](ref<eval_cache::AttrCursor> node, const std::vector<std::string> & systems) {
for (auto & s : systems)
omittedSystems.lock()->insert(s);
});
},

[&](ref<eval_cache::AttrCursor> node) {});
};

flake_schemas::forEachOutput(
Expand Down Expand Up @@ -898,6 +901,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON, MixFlakeSchemas
visit = [&](ref<eval_cache::AttrCursor> node, nlohmann::json & obj) {
flake_schemas::visit(
showAllSystems ? std::optional<std::string>() : localSystem,
showLegacy,
node,

[&](const flake_schemas::Leaf & leaf) {
Expand Down Expand Up @@ -959,7 +963,9 @@ struct CmdFlakeShow : FlakeCommand, MixJSON, MixFlakeSchemas

[&](ref<eval_cache::AttrCursor> node, const std::vector<std::string> & systems) {
obj.emplace("filtered", true);
});
},

[&](ref<eval_cache::AttrCursor> node) { obj.emplace("isLegacy", true); });
};

auto inv = nlohmann::json::object();
Expand All @@ -972,9 +978,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON, MixFlakeSchemas
bool isLast) {
auto & j = inv.emplace(state->symbols[outputName], nlohmann::json::object()).first.value();

if (!showLegacy && state->symbols[outputName] == "legacyPackages") {
j.emplace("skipped", true);
} else if (output) {
if (output) {
j.emplace("doc", doc);
auto & j2 = j.emplace("output", nlohmann::json::object()).first.value();
state->spawn(futures, 1, [&visit, output, &j2]() { visit(ref(output), j2); });
Expand All @@ -996,6 +1000,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON, MixFlakeSchemas
render = [&](nlohmann::json j, const std::string & headerPrefix, const std::string & nextPrefix) {
auto what = j.find("what");
auto filtered = j.find("filtered");
auto isLegacy = j.find("isLegacy");
auto derivation = j.find("derivation");

auto s = headerPrefix;
Expand All @@ -1012,6 +1017,9 @@ struct CmdFlakeShow : FlakeCommand, MixJSON, MixFlakeSchemas
if (filtered != j.end() && (bool) *filtered)
s += " " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--all-systems' to show)";

if (isLegacy != j.end() && (bool) *isLegacy)
s += " " ANSI_WARNING "omitted" ANSI_NORMAL " (use '--legacy' to show)";

logger->cout(s);

auto children = j.find("children");
Expand Down Expand Up @@ -1042,8 +1050,6 @@ struct CmdFlakeShow : FlakeCommand, MixJSON, MixFlakeSchemas
render(*output, headerPrefix, nextPrefix);
else if (child.value().contains("unknown"))
logger->cout(headerPrefix + ANSI_WARNING " unknown flake output" ANSI_NORMAL);
else if (child.value().contains("skipped"))
logger->cout(headerPrefix + ANSI_WARNING " omitted" ANSI_NORMAL " (use '--legacy' to show)");
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/flakes/show.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let show_output = builtins.fromJSON (builtins.readFile ./show-output.json);
in
assert show_output.inventory.packages.output.children.someOtherSystem.filtered;
assert show_output.inventory.packages.output.children.${builtins.currentSystem}.children.default.derivation.name == "simple";
assert show_output.inventory.legacyPackages.skipped;
assert show_output.inventory.legacyPackages.output.children.${builtins.currentSystem}.isLegacy;
true
'

Expand All @@ -29,7 +29,7 @@ nix eval --impure --expr '
let show_output = builtins.fromJSON (builtins.readFile ./show-output.json);
in
assert show_output.inventory.packages.output.children.someOtherSystem.children.default.derivation.name == "simple";
assert show_output.inventory.legacyPackages.skipped;
assert show_output.inventory.legacyPackages.output.children.${builtins.currentSystem}.isLegacy;
true
'

Expand Down
Loading