about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/installer/tools/tools.nix8
-rw-r--r--pkgs/tools/nix/nixos-option/CMakeLists.txt5
-rw-r--r--pkgs/tools/nix/nixos-option/default.nix12
-rw-r--r--pkgs/tools/nix/nixos-option/libnix-copy-paste.cc9
-rw-r--r--pkgs/tools/nix/nixos-option/nixos-option.cc101
-rw-r--r--pkgs/top-level/all-packages.nix2
6 files changed, 74 insertions, 63 deletions
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
index 1e36d10b391f..54b0f81ee780 100644
--- a/nixos/modules/installer/tools/tools.nix
+++ b/nixos/modules/installer/tools/tools.nix
@@ -42,10 +42,7 @@ let
     xserverEnabled = config.services.xserver.enable;
   };
 
-  nixos-option =
-    if lib.versionAtLeast (lib.getVersion config.nix.package) "2.4pre"
-    then null
-    else pkgs.nixos-option;
+  inherit (pkgs) nixos-option;
 
   nixos-version = makeProg {
     name = "nixos-version";
@@ -232,9 +229,10 @@ in
         nixos-install
         nixos-rebuild
         nixos-generate-config
+        nixos-option
         nixos-version
         nixos-enter
-      ] ++ lib.optional (nixos-option != null) nixos-option;
+      ];
 
     documentation.man.man-db.skipPackages = [ nixos-version ];
 
diff --git a/pkgs/tools/nix/nixos-option/CMakeLists.txt b/pkgs/tools/nix/nixos-option/CMakeLists.txt
index e5834598c4fd..3c2223c535a8 100644
--- a/pkgs/tools/nix/nixos-option/CMakeLists.txt
+++ b/pkgs/tools/nix/nixos-option/CMakeLists.txt
@@ -1,8 +1,11 @@
 cmake_minimum_required (VERSION 2.6)
 project (nixos-option)
 
+set(NIX_DEV_INCLUDEPATH "" CACHE STRING "path to nix include directory")
+
 add_executable(nixos-option nixos-option.cc libnix-copy-paste.cc)
-target_link_libraries(nixos-option PRIVATE -lnixmain -lnixexpr -lnixstore -lnixutil)
+target_include_directories(nixos-option PUBLIC "${NIX_DEV_INCLUDEPATH}")
+target_link_libraries(nixos-option PRIVATE -lnixmain -lnixexpr -lnixstore -lnixutil -lnixcmd)
 target_compile_features(nixos-option PRIVATE cxx_std_17)
 
 install (TARGETS nixos-option DESTINATION bin)
diff --git a/pkgs/tools/nix/nixos-option/default.nix b/pkgs/tools/nix/nixos-option/default.nix
index a9cc967d7680..56cb3e130038 100644
--- a/pkgs/tools/nix/nixos-option/default.nix
+++ b/pkgs/tools/nix/nixos-option/default.nix
@@ -1,14 +1,18 @@
-{lib, stdenv, boost, cmake, pkg-config, nix, ... }:
+{ lib, stdenv, boost, cmake, pkg-config, nix }:
 
-stdenv.mkDerivation rec {
+stdenv.mkDerivation {
   name = "nixos-option";
+
   src = ./.;
+
   strictDeps = true;
   nativeBuildInputs = [ cmake pkg-config ];
   buildInputs = [ boost nix ];
+  cmakeFlags = [ "-DNIX_DEV_INCLUDEPATH=${nix.dev}/include/nix" ];
+
   meta = with lib; {
     license = licenses.lgpl2Plus;
-    maintainers = with maintainers; [ chkno ];
-    platforms = platforms.all;
+    maintainers = with maintainers; [ ];
+    inherit (nix.meta) platforms;
   };
 }
diff --git a/pkgs/tools/nix/nixos-option/libnix-copy-paste.cc b/pkgs/tools/nix/nixos-option/libnix-copy-paste.cc
index 875c07da6399..ad6084844e57 100644
--- a/pkgs/tools/nix/nixos-option/libnix-copy-paste.cc
+++ b/pkgs/tools/nix/nixos-option/libnix-copy-paste.cc
@@ -7,15 +7,12 @@
 #include "libnix-copy-paste.hh"
 #include <boost/format/alt_sstream.hpp>           // for basic_altstringbuf...
 #include <boost/format/alt_sstream_impl.hpp>      // for basic_altstringbuf...
-#include <boost/format/format_class.hpp>          // for basic_format
-#include <boost/format/format_fwd.hpp>            // for format
-#include <boost/format/format_implementation.hpp> // for basic_format::basi...
 #include <boost/optional/optional.hpp>            // for get_pointer
 #include <iostream>                               // for operator<<, basic_...
-#include <nix/types.hh>                           // for Strings, Error
+#include <nix/types.hh>                           // for Strings
+#include <nix/error.hh>                           // for Error
 #include <string>                                 // for string, basic_string
 
-using boost::format;
 using nix::Error;
 using nix::Strings;
 using std::string;
@@ -34,7 +31,7 @@ Strings parseAttrPath(const string & s)
             ++i;
             while (1) {
                 if (i == s.end())
-                    throw Error(format("missing closing quote in selection path '%1%'") % s);
+                    throw Error("missing closing quote in selection path '%1%'", s);
                 if (*i == '"')
                     break;
                 cur.push_back(*i++);
diff --git a/pkgs/tools/nix/nixos-option/nixos-option.cc b/pkgs/tools/nix/nixos-option/nixos-option.cc
index f779d82edbd6..e4f7bff3c662 100644
--- a/pkgs/tools/nix/nixos-option/nixos-option.cc
+++ b/pkgs/tools/nix/nixos-option/nixos-option.cc
@@ -37,13 +37,26 @@ using nix::Path;
 using nix::PathSet;
 using nix::Strings;
 using nix::Symbol;
-using nix::tAttrs;
+using nix::nAttrs;
 using nix::ThrownError;
 using nix::tLambda;
-using nix::tString;
+using nix::nString;
 using nix::UsageError;
 using nix::Value;
 
+struct Context
+{
+    Context(EvalState & state, Bindings & autoArgs, Value optionsRoot, Value configRoot)
+        : state(state), autoArgs(autoArgs), optionsRoot(optionsRoot), configRoot(configRoot),
+          underscoreType(state.symbols.create("_type"))
+    {}
+    EvalState & state;
+    Bindings & autoArgs;
+    Value optionsRoot;
+    Value configRoot;
+    Symbol underscoreType;
+};
+
 // An ostream wrapper to handle nested indentation
 class Out
 {
@@ -74,6 +87,8 @@ class Out
     LinePolicy policy;
     bool writeSinceSep;
     template <typename T> friend Out & operator<<(Out & o, T thing);
+
+    friend void printValue(Context & ctx, Out & out, std::variant<Value, std::exception_ptr> maybeValue, const std::string & path);
 };
 
 template <typename T> Out & operator<<(Out & o, T thing)
@@ -101,23 +116,10 @@ Out::Out(Out & o, const std::string & start, const std::string & end, LinePolicy
     *this << Out::sep;
 }
 
-// Stuff needed for evaluation
-struct Context
-{
-    Context(EvalState & state, Bindings & autoArgs, Value optionsRoot, Value configRoot)
-        : state(state), autoArgs(autoArgs), optionsRoot(optionsRoot), configRoot(configRoot),
-          underscoreType(state.symbols.create("_type"))
-    {}
-    EvalState & state;
-    Bindings & autoArgs;
-    Value optionsRoot;
-    Value configRoot;
-    Symbol underscoreType;
-};
 
 Value evaluateValue(Context & ctx, Value & v)
 {
-    ctx.state.forceValue(v);
+    ctx.state.forceValue(v, v.attrs->pos);
     if (ctx.autoArgs.empty()) {
         return v;
     }
@@ -128,7 +130,7 @@ Value evaluateValue(Context & ctx, Value & v)
 
 bool isOption(Context & ctx, const Value & v)
 {
-    if (v.type != tAttrs) {
+    if (v.type() != nAttrs) {
         return false;
     }
     const auto & actualType = v.attrs->find(ctx.underscoreType);
@@ -137,7 +139,7 @@ bool isOption(Context & ctx, const Value & v)
     }
     try {
         Value evaluatedType = evaluateValue(ctx, *actualType->value);
-        if (evaluatedType.type != tString) {
+        if (evaluatedType.type() != nString) {
             return false;
         }
         return static_cast<std::string>(evaluatedType.string.s) == "option";
@@ -168,7 +170,14 @@ const std::string appendPath(const std::string & prefix, const std::string & suf
     return prefix + "." + quoteAttribute(suffix);
 }
 
-bool forbiddenRecursionName(std::string name) { return (!name.empty() && name[0] == '_') || name == "haskellPackages"; }
+bool forbiddenRecursionName(const nix::Symbol symbol, const nix::SymbolTable & symbolTable) {
+    // note: this is created from a pointer
+    // According to standard, it may never point to null, and hence attempts to check against nullptr are not allowed.
+    // However, at the time of writing, I am not certain about the full implications of the omission of a nullptr check here.
+    const std::string & name = symbolTable[symbol];
+    // TODO: figure out why haskellPackages is not recursed here
+    return (!name.empty() && name[0] == '_') || name == "haskellPackages";
+}
 
 void recurse(const std::function<bool(const std::string & path, std::variant<Value, std::exception_ptr>)> & f,
              Context & ctx, Value v, const std::string & path)
@@ -186,14 +195,14 @@ void recurse(const std::function<bool(const std::string & path, std::variant<Val
         return;
     }
     const Value & evaluated_value = std::get<Value>(evaluated);
-    if (evaluated_value.type != tAttrs) {
+    if (evaluated_value.type() != nAttrs) {
         return;
     }
-    for (const auto & child : evaluated_value.attrs->lexicographicOrder()) {
-        if (forbiddenRecursionName(child->name)) {
+    for (const auto & child : evaluated_value.attrs->lexicographicOrder(ctx.state.symbols)) {
+        if (forbiddenRecursionName(child->name, ctx.state.symbols)) {
             continue;
         }
-        recurse(f, ctx, *child->value, appendPath(path, child->name));
+        recurse(f, ctx, *child->value, appendPath(path, ctx.state.symbols[child->name]));
     }
 }
 
@@ -205,7 +214,7 @@ bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType)
             return false;
         }
         Value type = evaluateValue(ctx, *typeLookup->value);
-        if (type.type != tAttrs) {
+        if (type.type() != nAttrs) {
             return false;
         }
         const auto & nameLookup = type.attrs->find(ctx.state.sName);
@@ -213,7 +222,7 @@ bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType)
             return false;
         }
         Value name = evaluateValue(ctx, *nameLookup->value);
-        if (name.type != tString) {
+        if (name.type() != nString) {
             return false;
         }
         return name.string.s == soughtType;
@@ -231,14 +240,14 @@ 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) {
+    Value getSubOptions = evaluateValue(ctx, *findAlongAttrPath(ctx.state, "type.getSubOptions", ctx.autoArgs, option).first);
+    if (getSubOptions.isLambda()) {
         throw OptionPathError("Option's type.getSubOptions isn't a function");
     }
     Value emptyString{};
-    nix::mkString(emptyString, "");
+    emptyString.mkString("");
     Value v;
-    ctx.state.callFunction(getSubOptions, emptyString, v, nix::Pos{});
+    ctx.state.callFunction(getSubOptions, emptyString, v, nix::PosIdx{});
     return v;
 }
 
@@ -273,7 +282,7 @@ FindAlongOptionPathRet findAlongOptionPath(Context & ctx, const std::string & pa
                 v = subOptions;
                 // 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) {
+            } else if (v.type() != nAttrs) {
                 throw OptionPathError("Value is %s while a set was expected", showType(v));
             } else {
                 const auto & next = v.attrs->find(ctx.state.symbols.create(attr));
@@ -336,14 +345,14 @@ void mapConfigValuesInOption(
 {
     Value * option;
     try {
-        option = findAlongAttrPath(ctx.state, path, ctx.autoArgs, ctx.configRoot);
+        option = findAlongAttrPath(ctx.state, path, ctx.autoArgs, ctx.configRoot).first;
     } catch (Error &) {
         f(path, std::current_exception());
         return;
     }
     recurse(
         [f, ctx](const std::string & path, std::variant<Value, std::exception_ptr> v) {
-            bool leaf = std::holds_alternative<std::exception_ptr>(v) || std::get<Value>(v).type != tAttrs ||
+            bool leaf = std::holds_alternative<std::exception_ptr>(v) || std::get<Value>(v).type() != nAttrs ||
                         ctx.state.isDerivation(std::get<Value>(v));
             if (!leaf) {
                 return true; // Keep digging
@@ -362,7 +371,7 @@ void describeDerivation(Context & ctx, Out & out, Value v)
     Bindings::iterator i = v.attrs->find(ctx.state.sDrvPath);
     PathSet pathset;
     try {
-        Path drvPath = i != v.attrs->end() ? ctx.state.coerceToPath(*i->pos, *i->value, pathset) : "???";
+        Path drvPath = i != v.attrs->end() ? ctx.state.coerceToPath(i->pos, *i->value, pathset, "while evaluating the drvPath of a derivation") : "???";
         out << "«derivation " << drvPath << "»";
     } catch (Error & e) {
         out << describeError(e);
@@ -390,9 +399,9 @@ void printList(Context & ctx, Out & out, Value & v)
 void printAttrs(Context & ctx, Out & out, Value & v, const std::string & path)
 {
     Out attrsOut(out, "{", "}", v.attrs->size());
-    for (const auto & a : v.attrs->lexicographicOrder()) {
-        std::string name = a->name;
-        if (!forbiddenRecursionName(name)) {
+    for (const auto & a : v.attrs->lexicographicOrder(ctx.state.symbols)) {
+        if (!forbiddenRecursionName(a->name, ctx.state.symbols)) {
+            const std::string name = ctx.state.symbols[a->name];
             attrsOut << name << " = ";
             printValue(ctx, attrsOut, *a->value, appendPath(path, name));
             attrsOut << ";" << Out::sep;
@@ -447,13 +456,13 @@ void printValue(Context & ctx, Out & out, std::variant<Value, std::exception_ptr
             describeDerivation(ctx, out, v);
         } else if (v.isList()) {
             printList(ctx, out, v);
-        } else if (v.type == tAttrs) {
+        } else if (v.type() == nAttrs) {
             printAttrs(ctx, out, v, path);
-        } else if (v.type == tString && std::string(v.string.s).find('\n') != std::string::npos) {
+        } else if (v.type() == nString && std::string(v.string.s).find('\n') != std::string::npos) {
             printMultiLineString(out, v);
         } else {
             ctx.state.forceValueDeep(v);
-            out << v;
+            v.print(ctx.state.symbols, out.ostream);
         }
     } catch (ThrownError & e) {
         if (e.msg() == "The option `" + path + "' is used but not defined.") {
@@ -505,7 +514,7 @@ void printRecursive(Context & ctx, Out & out, const std::string & path)
 void printAttr(Context & ctx, Out & out, const std::string & path, Value & root)
 {
     try {
-        printValue(ctx, out, *findAlongAttrPath(ctx.state, path, ctx.autoArgs, root), path);
+        printValue(ctx, out, *findAlongAttrPath(ctx.state, path, ctx.autoArgs, root).first, path);
     } catch (Error & e) {
         out << describeError(e);
     }
@@ -548,11 +557,11 @@ void printOption(Context & ctx, Out & out, const std::string & path, Value & opt
     out << "\n";
 }
 
-void printListing(Out & out, Value & v)
+void printListing(Context & ctx, Out & out, Value & v)
 {
     out << "This attribute set contains:\n";
-    for (const auto & a : v.attrs->lexicographicOrder()) {
-        std::string name = a->name;
+    for (const auto & a : v.attrs->lexicographicOrder(ctx.state.symbols)) {
+        const std::string & name = ctx.state.symbols[a->name];
         if (!name.empty() && name[0] != '_') {
             out << name << "\n";
         }
@@ -571,7 +580,7 @@ void printOne(Context & ctx, Out & out, const std::string & path)
         if (isOption(ctx, option)) {
             printOption(ctx, out, result.path, option);
         } else {
-            printListing(out, option);
+            printListing(ctx, out, option);
         }
     } catch (Error & e) {
         std::cerr << "error: " << e.msg()
@@ -594,7 +603,7 @@ int main(int argc, char ** argv)
         using nix::LegacyArgs::LegacyArgs;
     };
 
-    MyArgs myArgs(nix::baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) {
+    MyArgs myArgs(std::string(nix::baseNameOf(argv[0])), [&](Strings::iterator & arg, const Strings::iterator & end) {
         if (*arg == "--help") {
             nix::showManPage("nixos-option");
         } else if (*arg == "--version") {
@@ -617,7 +626,7 @@ int main(int argc, char ** argv)
 
     myArgs.parseCmdline(nix::argvToStrings(argc, argv));
 
-    nix::initPlugins();
+    nix::initNix();
     nix::initGC();
     nix::settings.readOnlyMode = true;
     auto store = nix::openStore();
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 97c8dd4185d7..1a7fb252bad3 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -39986,7 +39986,7 @@ with pkgs;
 
   nix-melt = callPackage ../tools/nix/nix-melt { };
 
-  nixos-option = callPackage ../tools/nix/nixos-option { nix = nixVersions.nix_2_3; };
+  nixos-option = callPackage ../tools/nix/nixos-option { };
 
   nix-pin = callPackage ../tools/package-management/nix-pin { };