mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-22 15:03:28 +00:00
nixos-option: fix build against nix 2.24 (#355745)
This commit is contained in:
commit
501505f8c7
@ -1,24 +1,28 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, boost
|
||||
, cmake
|
||||
, pkg-config
|
||||
, installShellFiles
|
||||
, nix
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
boost,
|
||||
meson,
|
||||
ninja,
|
||||
pkg-config,
|
||||
installShellFiles,
|
||||
nix,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "nixos-option";
|
||||
|
||||
src = ./src;
|
||||
src = ./.;
|
||||
|
||||
postInstall = ''
|
||||
installManPage ${./nixos-option.8}
|
||||
installManPage ../nixos-option.8
|
||||
'';
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
installShellFiles
|
||||
];
|
||||
@ -26,9 +30,6 @@ stdenv.mkDerivation {
|
||||
boost
|
||||
nix
|
||||
];
|
||||
cmakeFlags = [
|
||||
"-DNIX_DEV_INCLUDEPATH=${nix.dev}/include/nix"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
license = licenses.lgpl2Plus;
|
||||
|
15
pkgs/tools/nix/nixos-option/meson.build
Normal file
15
pkgs/tools/nix/nixos-option/meson.build
Normal file
@ -0,0 +1,15 @@
|
||||
project('nixos-option', 'cpp',
|
||||
version : '0.1.6',
|
||||
license : 'GPL-3.0',
|
||||
)
|
||||
|
||||
nix_main_dep = dependency('nix-main', required: true)
|
||||
nix_store_dep = dependency('nix-store', required: true)
|
||||
nix_expr_dep = dependency('nix-expr', required: true)
|
||||
nix_cmd_dep = dependency('nix-cmd', required: true)
|
||||
nix_flake_dep = dependency('nix-flake', required: true)
|
||||
threads_dep = dependency('threads', required: true)
|
||||
nlohmann_json_dep = dependency('nlohmann_json', required: true)
|
||||
boost_dep = dependency('boost', required: true)
|
||||
|
||||
subdir('src')
|
@ -1,11 +0,0 @@
|
||||
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_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_20)
|
||||
|
||||
install (TARGETS nixos-option DESTINATION bin)
|
@ -2,79 +2,21 @@
|
||||
// Since they are not, copy/paste them here.
|
||||
// TODO: Delete these and use the ones in the library as they become available.
|
||||
|
||||
#include <nix/config.h> // for nix/globals.hh's reference to SYSTEM
|
||||
|
||||
#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/optional/optional.hpp> // for get_pointer
|
||||
#include <iostream> // for operator<<, basic_...
|
||||
#include <nix/types.hh> // for Strings
|
||||
#include <nix/error.hh> // for Error
|
||||
#include <string> // for string, basic_string
|
||||
|
||||
using nix::Error;
|
||||
using nix::Strings;
|
||||
using std::string;
|
||||
|
||||
// From nix/src/libexpr/attr-path.cc
|
||||
Strings parseAttrPath(const string & s)
|
||||
{
|
||||
Strings res;
|
||||
string cur;
|
||||
string::const_iterator i = s.begin();
|
||||
while (i != s.end()) {
|
||||
if (*i == '.') {
|
||||
res.push_back(cur);
|
||||
cur.clear();
|
||||
} else if (*i == '"') {
|
||||
++i;
|
||||
while (1) {
|
||||
if (i == s.end())
|
||||
throw Error("missing closing quote in selection path '%1%'", s);
|
||||
if (*i == '"')
|
||||
break;
|
||||
cur.push_back(*i++);
|
||||
}
|
||||
} else
|
||||
cur.push_back(*i);
|
||||
++i;
|
||||
}
|
||||
if (!cur.empty())
|
||||
res.push_back(cur);
|
||||
return res;
|
||||
}
|
||||
#include <nix/print.hh> // for Strings
|
||||
|
||||
// From nix/src/nix/repl.cc
|
||||
bool isVarName(const string & s)
|
||||
bool isVarName(const std::string_view & s)
|
||||
{
|
||||
if (s.size() == 0)
|
||||
return false;
|
||||
if (s.size() == 0) return false;
|
||||
if (nix::isReservedKeyword(s)) return false;
|
||||
char c = s[0];
|
||||
if ((c >= '0' && c <= '9') || c == '-' || c == '\'')
|
||||
return false;
|
||||
if ((c >= '0' && c <= '9') || c == '-' || c == '\'') return false;
|
||||
for (auto & i : s)
|
||||
if (!((i >= 'a' && i <= 'z') || (i >= 'A' && i <= 'Z') || (i >= '0' && i <= '9') || i == '_' || i == '-' ||
|
||||
i == '\''))
|
||||
if (!((i >= 'a' && i <= 'z') ||
|
||||
(i >= 'A' && i <= 'Z') ||
|
||||
(i >= '0' && i <= '9') ||
|
||||
i == '_' || i == '-' || i == '\''))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// From nix/src/nix/repl.cc
|
||||
std::ostream & printStringValue(std::ostream & str, const char * string)
|
||||
{
|
||||
str << "\"";
|
||||
for (const char * i = string; *i; i++)
|
||||
if (*i == '\"' || *i == '\\')
|
||||
str << "\\" << *i;
|
||||
else if (*i == '\n')
|
||||
str << "\\n";
|
||||
else if (*i == '\r')
|
||||
str << "\\r";
|
||||
else if (*i == '\t')
|
||||
str << "\\t";
|
||||
else
|
||||
str << *i;
|
||||
str << "\"";
|
||||
return str;
|
||||
}
|
||||
|
@ -1,9 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <nix/types.hh>
|
||||
#include <string>
|
||||
|
||||
nix::Strings parseAttrPath(const std::string & s);
|
||||
bool isVarName(const std::string & s);
|
||||
std::ostream & printStringValue(std::ostream & str, const char * string);
|
||||
bool isVarName(const std::string_view & s);
|
||||
|
20
pkgs/tools/nix/nixos-option/src/meson.build
Normal file
20
pkgs/tools/nix/nixos-option/src/meson.build
Normal file
@ -0,0 +1,20 @@
|
||||
src = [
|
||||
'nixos-option.cc',
|
||||
'libnix-copy-paste.cc',
|
||||
]
|
||||
|
||||
cc = meson.get_compiler('cpp')
|
||||
|
||||
executable('nixos-option', src,
|
||||
dependencies : [
|
||||
nix_main_dep,
|
||||
nix_store_dep,
|
||||
nix_expr_dep,
|
||||
nix_cmd_dep,
|
||||
nix_flake_dep,
|
||||
boost_dep,
|
||||
nlohmann_json_dep,
|
||||
threads_dep
|
||||
],
|
||||
install: true,
|
||||
cpp_args: ['-std=c++2a', '--include', 'nix/config.h'])
|
@ -1,16 +1,8 @@
|
||||
#include <nix/config.h> // for nix/globals.hh's reference to SYSTEM
|
||||
|
||||
#include <exception> // for exception_ptr, current_exception
|
||||
#include <functional> // for function
|
||||
#include <iostream> // for operator<<, basic_ostream, ostrin...
|
||||
#include <iterator> // for next
|
||||
#include <list> // for _List_iterator
|
||||
#include <memory> // for allocator, unique_ptr, make_unique
|
||||
#include <new> // for operator new
|
||||
#include <nix/args.hh> // for argvToStrings, UsageError
|
||||
#include <nix/attr-path.hh> // for findAlongAttrPath
|
||||
#include <nix/attr-path.hh> // for findAlongAttrPath, parseAttrPath
|
||||
#include <nix/attr-set.hh> // for Attr, Bindings, Bindings::iterator
|
||||
#include <nix/common-eval-args.hh> // for MixEvalArgs
|
||||
#include <nix/eval-gc.hh> // for initGC, initNix
|
||||
#include <nix/eval-inline.hh> // for EvalState::forceValue
|
||||
#include <nix/eval.hh> // for EvalState, initGC, operator<<
|
||||
#include <nix/globals.hh> // for initPlugins, Settings, settings
|
||||
@ -23,8 +15,6 @@
|
||||
#include <nix/value.hh> // for Value, Value::(anonymous), Value:...
|
||||
#include <string> // for string, operator+, operator==
|
||||
#include <utility> // for move
|
||||
#include <variant> // for get, holds_alternative, variant
|
||||
#include <vector> // for vector<>::iterator, vector
|
||||
|
||||
#include "libnix-copy-paste.hh"
|
||||
|
||||
@ -119,7 +109,7 @@ Out::Out(Out & o, const std::string & start, const std::string & end, LinePolicy
|
||||
|
||||
Value evaluateValue(Context & ctx, Value & v)
|
||||
{
|
||||
ctx.state.forceValue(v, [&]() { return v.determinePos(nix::noPos); });
|
||||
ctx.state.forceValue(v, v.determinePos(nix::noPos));
|
||||
if (ctx.autoArgs.empty()) {
|
||||
return v;
|
||||
}
|
||||
@ -133,8 +123,8 @@ bool isOption(Context & ctx, const Value & v)
|
||||
if (v.type() != nAttrs) {
|
||||
return false;
|
||||
}
|
||||
const auto & actualType = v.attrs->find(ctx.underscoreType);
|
||||
if (actualType == v.attrs->end()) {
|
||||
const auto & actualType = v.attrs()->find(ctx.underscoreType);
|
||||
if (actualType == v.attrs()->end()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
@ -142,7 +132,7 @@ bool isOption(Context & ctx, const Value & v)
|
||||
if (evaluatedType.type() != nString) {
|
||||
return false;
|
||||
}
|
||||
return static_cast<std::string>(evaluatedType.string.s) == "option";
|
||||
return evaluatedType.string_view() == "option";
|
||||
} catch (Error &) {
|
||||
return false;
|
||||
}
|
||||
@ -152,17 +142,17 @@ bool isOption(Context & ctx, const Value & v)
|
||||
// These are needed for paths like:
|
||||
// fileSystems."/".fsType
|
||||
// systemd.units."dbus.service".text
|
||||
std::string quoteAttribute(const std::string & attribute)
|
||||
std::string quoteAttribute(const std::string_view & attribute)
|
||||
{
|
||||
if (isVarName(attribute)) {
|
||||
return attribute;
|
||||
return std::string(attribute);
|
||||
}
|
||||
std::ostringstream buf;
|
||||
printStringValue(buf, attribute.c_str());
|
||||
nix::printLiteralString(buf, attribute);
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
const std::string appendPath(const std::string & prefix, const std::string & suffix)
|
||||
const std::string appendPath(const std::string & prefix, const std::string_view & suffix)
|
||||
{
|
||||
if (prefix.empty()) {
|
||||
return quoteAttribute(suffix);
|
||||
@ -174,7 +164,7 @@ bool forbiddenRecursionName(const nix::Symbol symbol, const nix::SymbolTable & s
|
||||
// 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];
|
||||
const std::string_view & name = symbolTable[symbol];
|
||||
// TODO: figure out why haskellPackages is not recursed here
|
||||
return (!name.empty() && name[0] == '_') || name == "haskellPackages";
|
||||
}
|
||||
@ -198,34 +188,35 @@ void recurse(const std::function<bool(const std::string & path, std::variant<Val
|
||||
if (evaluated_value.type() != nAttrs) {
|
||||
return;
|
||||
}
|
||||
for (const auto & child : evaluated_value.attrs->lexicographicOrder(ctx.state.symbols)) {
|
||||
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, ctx.state.symbols[child->name]));
|
||||
std::string_view name = ctx.state.symbols[child->name];
|
||||
recurse(f, ctx, *child->value, appendPath(path, name));
|
||||
}
|
||||
}
|
||||
|
||||
bool optionTypeIs(Context & ctx, Value & v, const std::string & soughtType)
|
||||
{
|
||||
try {
|
||||
const auto & typeLookup = v.attrs->find(ctx.state.sType);
|
||||
if (typeLookup == v.attrs->end()) {
|
||||
const auto & typeLookup = v.attrs()->find(ctx.state.sType);
|
||||
if (typeLookup == v.attrs()->end()) {
|
||||
return false;
|
||||
}
|
||||
Value type = evaluateValue(ctx, *typeLookup->value);
|
||||
if (type.type() != nAttrs) {
|
||||
return false;
|
||||
}
|
||||
const auto & nameLookup = type.attrs->find(ctx.state.sName);
|
||||
if (nameLookup == type.attrs->end()) {
|
||||
const auto & nameLookup = type.attrs()->find(ctx.state.sName);
|
||||
if (nameLookup == type.attrs()->end()) {
|
||||
return false;
|
||||
}
|
||||
Value name = evaluateValue(ctx, *nameLookup->value);
|
||||
if (name.type() != nString) {
|
||||
return false;
|
||||
}
|
||||
return name.string.s == soughtType;
|
||||
return name.string_view() == soughtType;
|
||||
} catch (Error &) {
|
||||
return false;
|
||||
}
|
||||
@ -242,7 +233,7 @@ Value getSubOptions(Context & ctx, Value & option)
|
||||
{
|
||||
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");
|
||||
throw OptionPathError(ctx.state, "Option's type.getSubOptions isn't a function");
|
||||
}
|
||||
Value emptyString{};
|
||||
emptyString.mkString("");
|
||||
@ -260,40 +251,40 @@ struct FindAlongOptionPathRet
|
||||
};
|
||||
FindAlongOptionPathRet findAlongOptionPath(Context & ctx, const std::string & path)
|
||||
{
|
||||
Strings tokens = parseAttrPath(path);
|
||||
std::vector<Symbol> tokens = nix::parseAttrPath(ctx.state, path);
|
||||
Value v = ctx.optionsRoot;
|
||||
std::string processedPath;
|
||||
for (auto i = tokens.begin(); i != tokens.end(); i++) {
|
||||
const auto & attr = *i;
|
||||
const std::string_view attr = ctx.state.symbols[*i];
|
||||
try {
|
||||
bool lastAttribute = std::next(i) == tokens.end();
|
||||
v = evaluateValue(ctx, v);
|
||||
if (attr.empty()) {
|
||||
throw OptionPathError("empty attribute name");
|
||||
throw OptionPathError(ctx.state, "empty attribute name");
|
||||
}
|
||||
if (isOption(ctx, v) && optionTypeIs(ctx, v, "submodule")) {
|
||||
v = getSubOptions(ctx, v);
|
||||
}
|
||||
if (isOption(ctx, v) && isAggregateOptionType(ctx, v)) {
|
||||
auto subOptions = getSubOptions(ctx, v);
|
||||
if (lastAttribute && subOptions.attrs->empty()) {
|
||||
if (lastAttribute && subOptions.attrs()->empty()) {
|
||||
break;
|
||||
}
|
||||
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() != nAttrs) {
|
||||
throw OptionPathError("Value is %s while a set was expected", showType(v));
|
||||
throw OptionPathError(ctx.state, "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);
|
||||
const auto & next = v.attrs()->find(ctx.state.symbols.create(attr));
|
||||
if (next == v.attrs()->end()) {
|
||||
throw OptionPathError(ctx.state, "Attribute not found", attr, path);
|
||||
}
|
||||
v = *next->value;
|
||||
}
|
||||
processedPath = appendPath(processedPath, attr);
|
||||
} catch (OptionPathError & e) {
|
||||
throw OptionPathError("At '%s' in path '%s': %s", attr, path, e.msg());
|
||||
throw OptionPathError(ctx.state, "At '%s' in path '%s': %s", attr, path, e.msg());
|
||||
}
|
||||
}
|
||||
return {v, processedPath};
|
||||
@ -367,21 +358,23 @@ std::string describeError(const Error & e) { return "«error: " + e.msg() + "»"
|
||||
|
||||
void describeDerivation(Context & ctx, Out & out, Value v)
|
||||
{
|
||||
// Copy-pasted from nix/src/nix/repl.cc :(
|
||||
// Copy-pasted from nix/src/nix/repl.cc printDerivation() :(
|
||||
std::optional<nix::StorePath> storePath = std::nullopt;
|
||||
if (auto i = v.attrs()->get(ctx.state.sDrvPath)) {
|
||||
nix::NixStringContext context;
|
||||
storePath = ctx.state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation");
|
||||
}
|
||||
out << "«derivation ";
|
||||
Bindings::iterator i = v.attrs->find(ctx.state.sDrvPath);
|
||||
nix::NixStringContext strContext;
|
||||
if (i != v.attrs->end())
|
||||
out << ctx.state.store->printStorePath(ctx.state.coerceToStorePath(i->pos, *i->value, strContext, "while evaluating the drvPath of a derivation"));
|
||||
else
|
||||
out << "???";
|
||||
if (storePath) {
|
||||
out << " " << ctx.state.store->printStorePath(*storePath);
|
||||
}
|
||||
out << "»";
|
||||
}
|
||||
|
||||
Value parseAndEval(EvalState & state, const std::string & expression, const std::string & path)
|
||||
{
|
||||
Value v{};
|
||||
state.eval(state.parseExprFromString(expression, nix::SourcePath(nix::CanonPath::fromCwd(path))), v);
|
||||
state.eval(state.parseExprFromString(expression, state.rootPath(".")), v);
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -398,10 +391,10 @@ 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(ctx.state.symbols)) {
|
||||
Out attrsOut(out, "{", "}", v.attrs()->size());
|
||||
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];
|
||||
std::string_view name = ctx.state.symbols[a->name];
|
||||
attrsOut << name << " = ";
|
||||
printValue(ctx, attrsOut, *a->value, appendPath(path, name));
|
||||
attrsOut << ";" << Out::sep;
|
||||
@ -409,9 +402,9 @@ void printAttrs(Context & ctx, Out & out, Value & v, const std::string & path)
|
||||
}
|
||||
}
|
||||
|
||||
void multiLineStringEscape(Out & out, const std::string & s)
|
||||
void multiLineStringEscape(Out & out, const std::string_view & s)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
for (i = 1; i < s.size(); i++) {
|
||||
if (s[i - 1] == '$' && s[i] == '{') {
|
||||
out << "''${";
|
||||
@ -430,7 +423,7 @@ void multiLineStringEscape(Out & out, const std::string & s)
|
||||
|
||||
void printMultiLineString(Out & out, const Value & v)
|
||||
{
|
||||
std::string s = v.string.s;
|
||||
std::string_view s = v.string_view();
|
||||
Out strOut(out, "''", "''", Out::MULTI_LINE);
|
||||
std::string::size_type begin = 0;
|
||||
while (begin < s.size()) {
|
||||
@ -458,11 +451,11 @@ void printValue(Context & ctx, Out & out, std::variant<Value, std::exception_ptr
|
||||
printList(ctx, out, v);
|
||||
} else if (v.type() == nAttrs) {
|
||||
printAttrs(ctx, out, v, path);
|
||||
} else if (v.type() == nString && std::string(v.string.s).find('\n') != std::string::npos) {
|
||||
} else if (v.type() == nString && std::string(v.string_view()).find('\n') != std::string::npos) {
|
||||
printMultiLineString(out, v);
|
||||
} else {
|
||||
ctx.state.forceValueDeep(v);
|
||||
v.print(ctx.state.symbols, out.ostream);
|
||||
v.print(ctx.state, out.ostream);
|
||||
}
|
||||
} catch (ThrownError & e) {
|
||||
if (e.msg() == "The option `" + path + "' was accessed but has no value defined. Try setting the option.") {
|
||||
@ -560,8 +553,8 @@ void printOption(Context & ctx, Out & out, const std::string & path, Value & opt
|
||||
void printListing(Context & ctx, Out & out, Value & v)
|
||||
{
|
||||
out << "This attribute set contains:\n";
|
||||
for (const auto & a : v.attrs->lexicographicOrder(ctx.state.symbols)) {
|
||||
const std::string & name = ctx.state.symbols[a->name];
|
||||
for (const auto & a : v.attrs()->lexicographicOrder(ctx.state.symbols)) {
|
||||
const std::string_view & name = ctx.state.symbols[a->name];
|
||||
if (!name.empty() && name[0] != '_') {
|
||||
out << name << "\n";
|
||||
}
|
||||
@ -630,7 +623,11 @@ int main(int argc, char ** argv)
|
||||
nix::initGC();
|
||||
nix::settings.readOnlyMode = true;
|
||||
auto store = nix::openStore();
|
||||
auto state = std::make_unique<EvalState>(myArgs.searchPath, store);
|
||||
|
||||
auto evalStore = myArgs.evalStoreUrl ? nix::openStore(*myArgs.evalStoreUrl)
|
||||
: nix::openStore();
|
||||
auto state = nix::make_ref<nix::EvalState>(
|
||||
myArgs.lookupPath, evalStore, nix::fetchSettings, nix::evalSettings);
|
||||
|
||||
Value optionsRoot = parseAndEval(*state, optionsExpr, path);
|
||||
Value configRoot = parseAndEval(*state, configExpr, path);
|
||||
@ -646,7 +643,7 @@ int main(int argc, char ** argv)
|
||||
print(ctx, out, arg);
|
||||
}
|
||||
|
||||
ctx.state.printStats();
|
||||
ctx.state.maybePrintStats();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -18681,9 +18681,7 @@ with pkgs;
|
||||
|
||||
nix-linter = haskell.lib.compose.justStaticExecutables (haskellPackages.nix-linter);
|
||||
|
||||
nixos-option = callPackage ../tools/nix/nixos-option {
|
||||
nix = nixVersions.nix_2_18;
|
||||
};
|
||||
nixos-option = callPackage ../tools/nix/nixos-option { };
|
||||
|
||||
nix-pin = callPackage ../tools/package-management/nix-pin { };
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user