1 #include "globals.hh"
2 #include "shared.hh"
3 #include "eval.hh"
4 #include "eval-inline.hh"
5 #include "get-drvs.hh"
6 #include "attr-path.hh"
7 #include "value-to-xml.hh"
8 #include "value-to-json.hh"
9 #include "util.hh"
10 #include "store-api.hh"
11 #include "common-eval-args.hh"
12 #include "legacy.hh"
13
14 #include <map>
15 #include <iostream>
16
17
18 using namespace nix;
19
20
21 static Path gcRoot;
22 static int rootNr = 0;
23 static bool indirectRoot = false;
24
25
26 enum OutputKind { okPlain, okXML, okJSON };
27
28
processExpr(EvalState & state,const Strings & attrPaths,bool parseOnly,bool strict,Bindings & autoArgs,bool evalOnly,OutputKind output,bool location,Expr * e)29 void processExpr(EvalState & state, const Strings & attrPaths,
30 bool parseOnly, bool strict, Bindings & autoArgs,
31 bool evalOnly, OutputKind output, bool location, Expr * e)
32 {
33 if (parseOnly) {
34 std::cout << format("%1%\n") % *e;
35 return;
36 }
37
38 Value vRoot;
39 state.eval(e, vRoot);
40
41 for (auto & i : attrPaths) {
42 Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot));
43 state.forceValue(v);
44
45 PathSet context;
46 if (evalOnly) {
47 Value vRes;
48 if (autoArgs.empty())
49 vRes = v;
50 else
51 state.autoCallFunction(autoArgs, v, vRes);
52 if (output == okXML)
53 printValueAsXML(state, strict, location, vRes, std::cout, context);
54 else if (output == okJSON)
55 printValueAsJSON(state, strict, vRes, std::cout, context);
56 else {
57 if (strict) state.forceValueDeep(vRes);
58 std::cout << vRes << std::endl;
59 }
60 } else {
61 DrvInfos drvs;
62 getDerivations(state, v, "", autoArgs, drvs, false);
63 for (auto & i : drvs) {
64 Path drvPath = i.queryDrvPath();
65
66 /* What output do we want? */
67 string outputName = i.queryOutputName();
68 if (outputName == "")
69 throw Error(format("derivation '%1%' lacks an 'outputName' attribute ") % drvPath);
70
71 if (gcRoot == "")
72 printGCWarning();
73 else {
74 Path rootName = indirectRoot ? absPath(gcRoot) : gcRoot;
75 if (++rootNr > 1) rootName += "-" + std::to_string(rootNr);
76 auto store2 = state.store.dynamic_pointer_cast<LocalFSStore>();
77 if (store2)
78 drvPath = store2->addPermRoot(drvPath, rootName, indirectRoot);
79 }
80 std::cout << format("%1%%2%\n") % drvPath % (outputName != "out" ? "!" + outputName : "");
81 }
82 }
83 }
84 }
85
86
_main(int argc,char ** argv)87 static int _main(int argc, char * * argv)
88 {
89 {
90 Strings files;
91 bool readStdin = false;
92 bool fromArgs = false;
93 bool findFile = false;
94 bool evalOnly = false;
95 bool parseOnly = false;
96 OutputKind outputKind = okPlain;
97 bool xmlOutputSourceLocation = true;
98 bool strict = false;
99 Strings attrPaths;
100 bool wantsReadWrite = false;
101 RepairFlag repair = NoRepair;
102
103 struct MyArgs : LegacyArgs, MixEvalArgs
104 {
105 using LegacyArgs::LegacyArgs;
106 };
107
108 MyArgs myArgs(baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) {
109 if (*arg == "--help")
110 showManPage("nix-instantiate");
111 else if (*arg == "--version")
112 printVersion("nix-instantiate");
113 else if (*arg == "-")
114 readStdin = true;
115 else if (*arg == "--expr" || *arg == "-E")
116 fromArgs = true;
117 else if (*arg == "--eval" || *arg == "--eval-only")
118 evalOnly = true;
119 else if (*arg == "--read-write-mode")
120 wantsReadWrite = true;
121 else if (*arg == "--parse" || *arg == "--parse-only")
122 parseOnly = evalOnly = true;
123 else if (*arg == "--find-file")
124 findFile = true;
125 else if (*arg == "--attr" || *arg == "-A")
126 attrPaths.push_back(getArg(*arg, arg, end));
127 else if (*arg == "--add-root")
128 gcRoot = getArg(*arg, arg, end);
129 else if (*arg == "--indirect")
130 indirectRoot = true;
131 else if (*arg == "--xml")
132 outputKind = okXML;
133 else if (*arg == "--json")
134 outputKind = okJSON;
135 else if (*arg == "--no-location")
136 xmlOutputSourceLocation = false;
137 else if (*arg == "--strict")
138 strict = true;
139 else if (*arg == "--repair")
140 repair = Repair;
141 else if (*arg == "--dry-run")
142 settings.readOnlyMode = true;
143 else if (*arg != "" && arg->at(0) == '-')
144 return false;
145 else
146 files.push_back(*arg);
147 return true;
148 });
149
150 myArgs.parseCmdline(argvToStrings(argc, argv));
151
152 initPlugins();
153
154 if (evalOnly && !wantsReadWrite)
155 settings.readOnlyMode = true;
156
157 auto store = openStore();
158
159 auto state = std::make_unique<EvalState>(myArgs.searchPath, store);
160 state->repair = repair;
161
162 Bindings & autoArgs = *myArgs.getAutoArgs(*state);
163
164 if (attrPaths.empty()) attrPaths = {""};
165
166 if (findFile) {
167 for (auto & i : files) {
168 Path p = state->findFile(i);
169 if (p == "") throw Error(format("unable to find '%1%'") % i);
170 std::cout << p << std::endl;
171 }
172 return 0;
173 }
174
175 if (readStdin) {
176 Expr * e = state->parseStdin();
177 processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
178 evalOnly, outputKind, xmlOutputSourceLocation, e);
179 } else if (files.empty() && !fromArgs)
180 files.push_back("./default.nix");
181
182 for (auto & i : files) {
183 Expr * e = fromArgs
184 ? state->parseExprFromString(i, absPath("."))
185 : state->parseExprFromFile(resolveExprPath(state->checkSourcePath(lookupFileArg(*state, i))));
186 processExpr(*state, attrPaths, parseOnly, strict, autoArgs,
187 evalOnly, outputKind, xmlOutputSourceLocation, e);
188 }
189
190 state->printStats();
191
192 return 0;
193 }
194 }
195
196 static RegisterLegacyCommand s1("nix-instantiate", _main);
197