about summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorChuck <chuck@intelligence.org>2019-09-16 08:39:20 -0700
committerLinus Heckemann <git@sphalerite.org>2019-11-04 15:11:45 +0100
commitaa8e1d5f1e44d5b24538f4b105b9323bd586be61 (patch)
treed0c0667ec3f4bf8e8599685b64e40ee2f612823f /nixos
parent4ded9beea2ea5d0dd739c78a5bf1e5f42a1e1c39 (diff)
Always say which path component had trouble
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/installer/tools/nixos-option/nixos-option.cc48
1 files changed, 27 insertions, 21 deletions
diff --git a/nixos/modules/installer/tools/nixos-option/nixos-option.cc b/nixos/modules/installer/tools/nixos-option/nixos-option.cc
index 79a58e510afca..fc9315423dd01 100644
--- a/nixos/modules/installer/tools/nixos-option/nixos-option.cc
+++ b/nixos/modules/installer/tools/nixos-option/nixos-option.cc
@@ -31,6 +31,7 @@
 using nix::absPath;
 using nix::Bindings;
 using nix::Error;
+using nix::EvalError;
 using nix::EvalState;
 using nix::Path;
 using nix::PathSet;
@@ -465,12 +466,14 @@ bool optionTypeIs(Context * ctx, Value & v, const std::string & sought_type)
     }
 }
 
+MakeError(OptionPathError, EvalError);
+
 Value getSubOptions(Context * ctx, Value & option)
 {
     Value getSubOptions =
         evaluateValue(ctx, findAlongAttrPath(*ctx->state, "type.getSubOptions", *ctx->autoArgs, option));
     if (getSubOptions.type != tLambda) {
-        throw Error("Option's type.getSubOptions isn't a function");
+        throw OptionPathError("Option's type.getSubOptions isn't a function");
     }
     Value emptyString{};
     nix::mkString(emptyString, "");
@@ -486,28 +489,31 @@ Value findAlongOptionPath(Context * ctx, const std::string & path)
     Strings tokens = parseAttrPath(path);
     Value v = ctx->options_root;
     for (auto i = tokens.begin(); i != tokens.end(); i++) {
-        bool last_attribute = std::next(i) == tokens.end();
         const auto & attr = *i;
-        v = evaluateValue(ctx, &v);
-        if (attr.empty()) {
-            throw Error("empty attribute name in selection path '%s'", path);
-        }
-        if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) {
-            v = getSubOptions(ctx, v);
-        }
-        if (isOption(ctx, v) && optionTypeIs(ctx, v, "loaOf") && !last_attribute) {
-            v = getSubOptions(ctx, v);
-            // Note that we've consumed attr, but didn't actually use it.  This is the path component that's looked up
-            // in the list or attribute set that doesn't name an option -- the "root" in "users.users.root.name".
-        } else if (v.type != tAttrs) {
-            throw Error("attribute '%s' in path '%s' attempts to index a value that should be a set but is %s", attr,
-                        path, showType(v));
-        } else {
-            const auto & next = v.attrs->find(ctx->state->symbols.create(attr));
-            if (next == v.attrs->end()) {
-                throw Error("attribute '%s' in path '%s' not found", attr, path);
+        try {
+            bool last_attribute = std::next(i) == tokens.end();
+            v = evaluateValue(ctx, &v);
+            if (attr.empty()) {
+                throw OptionPathError("empty attribute name");
+            }
+            if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) {
+                v = getSubOptions(ctx, v);
+            }
+            if (isOption(ctx, v) && optionTypeIs(ctx, v, "loaOf") && !last_attribute) {
+                v = getSubOptions(ctx, v);
+                // Note that we've consumed attr, but didn't actually use it.  This is the path component that's looked
+                // up in the list or attribute set that doesn't name an option -- the "root" in "users.users.root.name".
+            } else if (v.type != tAttrs) {
+                throw OptionPathError("Value is %s while a set was expected", showType(v));
+            } else {
+                const auto & next = v.attrs->find(ctx->state->symbols.create(attr));
+                if (next == v.attrs->end()) {
+                    throw OptionPathError("Attribute not found", attr, path);
+                }
+                v = *next->value;
             }
-            v = *next->value;
+        } catch (OptionPathError & e) {
+            throw OptionPathError("At '%s' in path '%s': %s", attr, path, e.msg());
         }
     }
     return v;