Skip to content

Commit ca96f52

Browse files
committedMay 17, 2021
Split the parsing of an App and its resolving
That way things (like `nix flake check`) can evaluate the `app` outputs without having to build anything
1 parent bd6cf25 commit ca96f52

File tree

4 files changed

+41
-38
lines changed

4 files changed

+41
-38
lines changed
 

‎src/libcmd/installables.hh

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ struct App
2323
// FIXME: add args, sandbox settings, metadata, ...
2424
};
2525

26+
struct UnresolvedApp
27+
{
28+
App unresolved;
29+
App resolve(ref<Store>);
30+
};
31+
2632
struct Installable
2733
{
2834
virtual ~Installable() { }
@@ -33,7 +39,7 @@ struct Installable
3339

3440
DerivedPath toDerivedPath();
3541

36-
App toApp(EvalState & state);
42+
UnresolvedApp toApp(EvalState & state);
3743

3844
virtual std::pair<Value *, Pos> toValue(EvalState & state)
3945
{

‎src/nix/app.cc

+32-32
Original file line numberDiff line numberDiff line change
@@ -58,33 +58,24 @@ std::string resolveString(Store & store, const std::string & toResolve, const Bu
5858
return rewriteStrings(toResolve, rewrites);
5959
}
6060

61-
App Installable::toApp(EvalState & state)
61+
UnresolvedApp Installable::toApp(EvalState & state)
6262
{
6363
auto [cursor, attrPath] = getCursor(state);
6464

6565
auto type = cursor->getAttr("type")->getString();
6666

67-
auto checkProgram = [&](const Path & program)
68-
{
69-
if (!state.store->isInStore(program))
70-
throw Error("app program '%s' is not in the Nix store", program);
71-
};
67+
if (type == "app") {
68+
auto [program, context] = cursor->getAttr("program")->getStringWithContext();
7269

73-
std::vector<std::shared_ptr<Installable>> context;
74-
std::string unresolvedProgram;
7570

71+
std::vector<StorePathWithOutputs> context2;
72+
for (auto & [path, name] : context)
73+
context2.push_back({state.store->parseStorePath(path), {name}});
7674

77-
if (type == "app") {
78-
auto [program, context_] = cursor->getAttr("program")->getStringWithContext();
79-
unresolvedProgram = program;
80-
81-
for (auto & [path, name] : context_)
82-
context.push_back(std::make_shared<InstallableDerivedPath>(
83-
state.store,
84-
DerivedPathBuilt{
85-
.drvPath = state.store->parseStorePath(path),
86-
.outputs = {name},
87-
}));
75+
return UnresolvedApp{App {
76+
.context = std::move(context2),
77+
.program = program,
78+
}};
8879
}
8980

9081
else if (type == "derivation") {
@@ -98,24 +89,33 @@ App Installable::toApp(EvalState & state)
9889
aMainProgram
9990
? aMainProgram->getString()
10091
: DrvName(name).name;
101-
unresolvedProgram = outPath + "/bin/" + mainProgram;
102-
context = {std::make_shared<InstallableDerivedPath>(
103-
state.store,
104-
DerivedPathBuilt{
105-
.drvPath = drvPath,
106-
.outputs = {outputName},
107-
})};
92+
auto program = outPath + "/bin/" + mainProgram;
93+
return UnresolvedApp { App {
94+
.context = { { drvPath, {outputName} } },
95+
.program = program,
96+
}};
10897
}
10998

11099
else
111100
throw Error("attribute '%s' has unsupported type '%s'", attrPath, type);
101+
}
102+
103+
App UnresolvedApp::resolve(ref<Store> store)
104+
{
105+
auto res = unresolved;
106+
107+
std::vector<std::shared_ptr<Installable>> installableContext;
108+
109+
for (auto & ctxElt : unresolved.context)
110+
installableContext.push_back(
111+
std::make_shared<InstallableDerivedPath>(store, ctxElt.toDerivedPath()));
112112

113-
auto builtContext = build(state.store, Realise::Outputs, context);
114-
auto program = resolveString(*state.store, unresolvedProgram, builtContext);
115-
checkProgram(program);
116-
return App {
117-
.program = program,
118-
};
113+
auto builtContext = build(store, Realise::Outputs, installableContext);
114+
res.program = resolveString(*store, unresolved.program, builtContext);
115+
if (store->isInStore(res.program))
116+
throw Error("app program '%s' is not in the Nix store", res.program);
117+
118+
return res;
119119
}
120120

121121
}

‎src/nix/bundle.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ struct CmdBundle : InstallableCommand
6969
{
7070
auto evalState = getEvalState();
7171

72-
auto app = installable->toApp(*evalState);
73-
store->buildPaths(toDerivedPaths(app.context));
72+
auto app = installable->toApp(*evalState).resolve(store);
7473

7574
auto [bundlerFlakeRef, bundlerName] = parseFlakeRefWithFragment(bundler, absPath("."));
7675
const flake::LockFlags lockFlags{ .writeLockFile = false };

‎src/nix/run.cc

+1-3
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,7 @@ struct CmdRun : InstallableCommand, RunCommon
178178
{
179179
auto state = getEvalState();
180180

181-
auto app = installable->toApp(*state);
182-
183-
state->store->buildPaths(toDerivedPaths(app.context));
181+
auto app = installable->toApp(*state).resolve(store);
184182

185183
Strings allArgs{app.program};
186184
for (auto & i : args) allArgs.push_back(i);

0 commit comments

Comments
 (0)
Please sign in to comment.