mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11:15 +02:00
The existing header is a bit too big. Now the following use-cases are separated, and get their own headers: - Using or implementing an arbitrary store: remaining `store-api.hh` This is closer to just being about the `Store` (and `StoreConfig`) classes, as one would expect. - Opening a store from a textual description: `store-open.hh` Opening an aribtrary store implementation like this requires some sort of store registration mechanism to exists, but the caller doesn't need to know how it works. This just exposes the functions which use such a mechanism, without exposing the mechanism itself - Registering a store implementation: `store-registration.hh` This requires understanding how the mechanism actually works, and the mechanism in question involves templated machinery in headers we rather not expose to things that don't need it, as it would slow down compilation for no reason.
206 lines
7.3 KiB
C++
206 lines
7.3 KiB
C++
#include "nix/store/globals.hh"
|
|
#include "nix/expr/print-ambiguous.hh"
|
|
#include "nix/main/shared.hh"
|
|
#include "nix/expr/eval.hh"
|
|
#include "nix/expr/eval-inline.hh"
|
|
#include "nix/expr/get-drvs.hh"
|
|
#include "nix/expr/attr-path.hh"
|
|
#include "nix/util/signals.hh"
|
|
#include "nix/expr/value-to-xml.hh"
|
|
#include "nix/expr/value-to-json.hh"
|
|
#include "nix/store/store-open.hh"
|
|
#include "nix/store/local-fs-store.hh"
|
|
#include "nix/cmd/common-eval-args.hh"
|
|
#include "nix/cmd/legacy.hh"
|
|
#include "man-pages.hh"
|
|
|
|
#include <map>
|
|
#include <iostream>
|
|
|
|
|
|
using namespace nix;
|
|
|
|
|
|
static Path gcRoot;
|
|
static int rootNr = 0;
|
|
|
|
|
|
enum OutputKind { okPlain, okRaw, okXML, okJSON };
|
|
|
|
void processExpr(EvalState & state, const Strings & attrPaths,
|
|
bool parseOnly, bool strict, Bindings & autoArgs,
|
|
bool evalOnly, OutputKind output, bool location, Expr * e)
|
|
{
|
|
if (parseOnly) {
|
|
e->show(state.symbols, std::cout);
|
|
std::cout << "\n";
|
|
return;
|
|
}
|
|
|
|
Value vRoot;
|
|
state.eval(e, vRoot);
|
|
|
|
for (auto & i : attrPaths) {
|
|
Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot).first);
|
|
state.forceValue(v, v.determinePos(noPos));
|
|
|
|
NixStringContext context;
|
|
if (evalOnly) {
|
|
Value vRes;
|
|
if (autoArgs.empty())
|
|
vRes = v;
|
|
else
|
|
state.autoCallFunction(autoArgs, v, vRes);
|
|
if (output == okRaw)
|
|
std::cout << *state.coerceToString(noPos, vRes, context, "while generating the nix-instantiate output");
|
|
// We intentionally don't output a newline here. The default PS1 for Bash in NixOS starts with a newline
|
|
// and other interactive shells like Zsh are smart enough to print a missing newline before the prompt.
|
|
else if (output == okXML)
|
|
printValueAsXML(state, strict, location, vRes, std::cout, context, noPos);
|
|
else if (output == okJSON) {
|
|
printValueAsJSON(state, strict, vRes, v.determinePos(noPos), std::cout, context);
|
|
std::cout << std::endl;
|
|
} else {
|
|
if (strict) state.forceValueDeep(vRes);
|
|
std::set<const void *> seen;
|
|
printAmbiguous(vRes, state.symbols, std::cout, &seen, std::numeric_limits<int>::max());
|
|
std::cout << std::endl;
|
|
}
|
|
} else {
|
|
PackageInfos drvs;
|
|
getDerivations(state, v, "", autoArgs, drvs, false);
|
|
for (auto & i : drvs) {
|
|
auto drvPath = i.requireDrvPath();
|
|
auto drvPathS = state.store->printStorePath(drvPath);
|
|
|
|
/* What output do we want? */
|
|
std::string outputName = i.queryOutputName();
|
|
if (outputName == "")
|
|
throw Error("derivation '%1%' lacks an 'outputName' attribute", drvPathS);
|
|
|
|
if (gcRoot == "")
|
|
printGCWarning();
|
|
else {
|
|
Path rootName = absPath(gcRoot);
|
|
if (++rootNr > 1) rootName += "-" + std::to_string(rootNr);
|
|
auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>();
|
|
if (store2)
|
|
drvPathS = store2->addPermRoot(drvPath, rootName);
|
|
}
|
|
std::cout << fmt("%s%s\n", drvPathS, (outputName != "out" ? "!" + outputName : ""));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static int main_nix_instantiate(int argc, char * * argv)
|
|
{
|
|
{
|
|
Strings files;
|
|
bool readStdin = false;
|
|
bool fromArgs = false;
|
|
bool findFile = false;
|
|
bool evalOnly = false;
|
|
bool parseOnly = false;
|
|
OutputKind outputKind = okPlain;
|
|
bool xmlOutputSourceLocation = true;
|
|
bool strict = false;
|
|
Strings attrPaths;
|
|
bool wantsReadWrite = false;
|
|
|
|
struct MyArgs : LegacyArgs, MixEvalArgs
|
|
{
|
|
using LegacyArgs::LegacyArgs;
|
|
};
|
|
|
|
MyArgs myArgs(std::string(baseNameOf(argv[0])), [&](Strings::iterator & arg, const Strings::iterator & end) {
|
|
if (*arg == "--help")
|
|
showManPage("nix-instantiate");
|
|
else if (*arg == "--version")
|
|
printVersion("nix-instantiate");
|
|
else if (*arg == "-")
|
|
readStdin = true;
|
|
else if (*arg == "--expr" || *arg == "-E")
|
|
fromArgs = true;
|
|
else if (*arg == "--eval" || *arg == "--eval-only")
|
|
evalOnly = true;
|
|
else if (*arg == "--read-write-mode")
|
|
wantsReadWrite = true;
|
|
else if (*arg == "--parse" || *arg == "--parse-only")
|
|
parseOnly = evalOnly = true;
|
|
else if (*arg == "--find-file")
|
|
findFile = true;
|
|
else if (*arg == "--attr" || *arg == "-A")
|
|
attrPaths.push_back(getArg(*arg, arg, end));
|
|
else if (*arg == "--add-root")
|
|
gcRoot = getArg(*arg, arg, end);
|
|
else if (*arg == "--indirect")
|
|
;
|
|
else if (*arg == "--raw")
|
|
outputKind = okRaw;
|
|
else if (*arg == "--xml")
|
|
outputKind = okXML;
|
|
else if (*arg == "--json")
|
|
outputKind = okJSON;
|
|
else if (*arg == "--no-location")
|
|
xmlOutputSourceLocation = false;
|
|
else if (*arg == "--strict")
|
|
strict = true;
|
|
else if (*arg == "--dry-run")
|
|
settings.readOnlyMode = true;
|
|
else if (*arg != "" && arg->at(0) == '-')
|
|
return false;
|
|
else
|
|
files.push_back(*arg);
|
|
return true;
|
|
});
|
|
|
|
myArgs.parseCmdline(argvToStrings(argc, argv));
|
|
|
|
if (evalOnly && !wantsReadWrite)
|
|
settings.readOnlyMode = true;
|
|
|
|
auto store = openStore();
|
|
auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store;
|
|
|
|
auto state = std::make_unique<EvalState>(myArgs.lookupPath, evalStore, fetchSettings, evalSettings, store);
|
|
state->repair = myArgs.repair;
|
|
|
|
Bindings & autoArgs = *myArgs.getAutoArgs(*state);
|
|
|
|
if (attrPaths.empty()) attrPaths = {""};
|
|
|
|
if (findFile) {
|
|
for (auto & i : files) {
|
|
auto p = state->findFile(i);
|
|
if (auto fn = p.getPhysicalPath())
|
|
std::cout << fn->string() << std::endl;
|
|
else
|
|
throw Error("'%s' has no physical path", p);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (readStdin) {
|
|
Expr * e = state->parseStdin();
|
|
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
|
|
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
|
} else if (files.empty() && !fromArgs)
|
|
files.push_back("./default.nix");
|
|
|
|
for (auto & i : files) {
|
|
Expr * e = fromArgs
|
|
? state->parseExprFromString(i, state->rootPath("."))
|
|
: state->parseExprFromFile(resolveExprPath(lookupFileArg(*state, i)));
|
|
processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
|
|
evalOnly, outputKind, xmlOutputSourceLocation, e);
|
|
}
|
|
|
|
state->maybePrintStats();
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static RegisterLegacyCommand r_nix_instantiate("nix-instantiate", main_nix_instantiate);
|