mirror of
https://github.com/NixOS/nix
synced 2025-06-25 19:01:16 +02:00
WIP: broken merge but need a git checkpoint
This commit is contained in:
commit
eb460a9529
241 changed files with 7587 additions and 2694 deletions
|
@ -23,17 +23,6 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
void completeFlakeInputPath(
|
||||
ref<EvalState> evalState,
|
||||
const FlakeRef & flakeRef,
|
||||
std::string_view prefix)
|
||||
{
|
||||
auto flake = flake::getFlake(*evalState, flakeRef, true);
|
||||
for (auto & input : flake.inputs)
|
||||
if (hasPrefix(input.first, prefix))
|
||||
completions->add(input.first);
|
||||
}
|
||||
|
||||
MixFlakeOptions::MixFlakeOptions()
|
||||
{
|
||||
auto category = "Common flake-related options";
|
||||
|
@ -86,8 +75,7 @@ MixFlakeOptions::MixFlakeOptions()
|
|||
lockFlags.inputUpdates.insert(flake::parseInputPath(s));
|
||||
}},
|
||||
.completer = {[&](size_t, std::string_view prefix) {
|
||||
if (auto flakeRef = getFlakeRefForCompletion())
|
||||
completeFlakeInputPath(getEvalState(), *flakeRef, prefix);
|
||||
needsFlakeInputCompletion = {std::string(prefix)};
|
||||
}}
|
||||
});
|
||||
|
||||
|
@ -103,12 +91,10 @@ MixFlakeOptions::MixFlakeOptions()
|
|||
parseFlakeRef(flakeRef, absPath("."), true));
|
||||
}},
|
||||
.completer = {[&](size_t n, std::string_view prefix) {
|
||||
if (n == 0) {
|
||||
if (auto flakeRef = getFlakeRefForCompletion())
|
||||
completeFlakeInputPath(getEvalState(), *flakeRef, prefix);
|
||||
} else if (n == 1) {
|
||||
if (n == 0)
|
||||
needsFlakeInputCompletion = {std::string(prefix)};
|
||||
else if (n == 1)
|
||||
completeFlakeRef(getEvalState()->store, prefix);
|
||||
}
|
||||
}}
|
||||
});
|
||||
|
||||
|
@ -139,6 +125,24 @@ MixFlakeOptions::MixFlakeOptions()
|
|||
});
|
||||
}
|
||||
|
||||
void MixFlakeOptions::completeFlakeInput(std::string_view prefix)
|
||||
{
|
||||
auto evalState = getEvalState();
|
||||
for (auto & flakeRefS : getFlakesForCompletion()) {
|
||||
auto flakeRef = parseFlakeRefWithFragment(expandTilde(flakeRefS), absPath(".")).first;
|
||||
auto flake = flake::getFlake(*evalState, flakeRef, true);
|
||||
for (auto & input : flake.inputs)
|
||||
if (hasPrefix(input.first, prefix))
|
||||
completions->add(input.first);
|
||||
}
|
||||
}
|
||||
|
||||
void MixFlakeOptions::completionHook()
|
||||
{
|
||||
if (auto & prefix = needsFlakeInputCompletion)
|
||||
completeFlakeInput(*prefix);
|
||||
}
|
||||
|
||||
SourceExprCommand::SourceExprCommand(bool supportReadOnlyMode)
|
||||
{
|
||||
addFlag({
|
||||
|
@ -146,7 +150,8 @@ SourceExprCommand::SourceExprCommand(bool supportReadOnlyMode)
|
|||
.shortName = 'f',
|
||||
.description =
|
||||
"Interpret installables as attribute paths relative to the Nix expression stored in *file*. "
|
||||
"If *file* is the character -, then a Nix expression will be read from standard input.",
|
||||
"If *file* is the character -, then a Nix expression will be read from standard input. "
|
||||
"Implies `--impure`.",
|
||||
.category = installablesCategory,
|
||||
.labels = {"file"},
|
||||
.handler = {&file},
|
||||
|
@ -440,10 +445,8 @@ DerivedPaths InstallableValue::toDerivedPaths()
|
|||
|
||||
// Group by derivation, helps with .all in particular
|
||||
for (auto & drv : toDerivations()) {
|
||||
auto outputName = drv.outputName;
|
||||
if (outputName == "")
|
||||
throw Error("derivation '%s' lacks an 'outputName' attribute", state->store->printStorePath(drv.drvPath));
|
||||
drvsToOutputs[drv.drvPath].insert(outputName);
|
||||
for (auto & outputName : drv.outputsToInstall)
|
||||
drvsToOutputs[drv.drvPath].insert(outputName);
|
||||
drvsToCopy.insert(drv.drvPath);
|
||||
}
|
||||
|
||||
|
@ -466,9 +469,19 @@ struct InstallableAttrPath : InstallableValue
|
|||
SourceExprCommand & cmd;
|
||||
RootValue v;
|
||||
std::string attrPath;
|
||||
OutputsSpec outputsSpec;
|
||||
|
||||
InstallableAttrPath(ref<EvalState> state, SourceExprCommand & cmd, Value * v, const std::string & attrPath)
|
||||
: InstallableValue(state), cmd(cmd), v(allocRootValue(v)), attrPath(attrPath)
|
||||
InstallableAttrPath(
|
||||
ref<EvalState> state,
|
||||
SourceExprCommand & cmd,
|
||||
Value * v,
|
||||
const std::string & attrPath,
|
||||
OutputsSpec outputsSpec)
|
||||
: InstallableValue(state)
|
||||
, cmd(cmd)
|
||||
, v(allocRootValue(v))
|
||||
, attrPath(attrPath)
|
||||
, outputsSpec(std::move(outputsSpec))
|
||||
{ }
|
||||
|
||||
std::string what() const override { return attrPath; }
|
||||
|
@ -497,7 +510,19 @@ std::vector<InstallableValue::DerivationInfo> InstallableAttrPath::toDerivations
|
|||
auto drvPath = drvInfo.queryDrvPath();
|
||||
if (!drvPath)
|
||||
throw Error("'%s' is not a derivation", what());
|
||||
res.push_back({ *drvPath, drvInfo.queryOutputName() });
|
||||
|
||||
std::set<std::string> outputsToInstall;
|
||||
|
||||
if (auto outputNames = std::get_if<OutputNames>(&outputsSpec))
|
||||
outputsToInstall = *outputNames;
|
||||
else
|
||||
for (auto & output : drvInfo.queryOutputs(false, std::get_if<DefaultOutputs>(&outputsSpec)))
|
||||
outputsToInstall.insert(output.first);
|
||||
|
||||
res.push_back(DerivationInfo {
|
||||
.drvPath = *drvPath,
|
||||
.outputsToInstall = std::move(outputsToInstall)
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -574,6 +599,7 @@ InstallableFlake::InstallableFlake(
|
|||
ref<EvalState> state,
|
||||
FlakeRef && flakeRef,
|
||||
std::string_view fragment,
|
||||
OutputsSpec outputsSpec,
|
||||
Strings attrPaths,
|
||||
Strings prefixes,
|
||||
const flake::LockFlags & lockFlags)
|
||||
|
@ -581,6 +607,7 @@ InstallableFlake::InstallableFlake(
|
|||
flakeRef(flakeRef),
|
||||
attrPaths(fragment == "" ? attrPaths : Strings{(std::string) fragment}),
|
||||
prefixes(fragment == "" ? Strings{} : prefixes),
|
||||
outputsSpec(std::move(outputsSpec)),
|
||||
lockFlags(lockFlags)
|
||||
{
|
||||
if (cmd && cmd->getAutoArgs(*state)->size())
|
||||
|
@ -589,6 +616,8 @@ InstallableFlake::InstallableFlake(
|
|||
|
||||
std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableFlake::toDerivation()
|
||||
{
|
||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("evaluating derivation '%s'", what()));
|
||||
|
||||
auto attr = getCursor(*state);
|
||||
|
||||
auto attrPath = attr->getAttrPathStr();
|
||||
|
@ -598,9 +627,41 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
|
|||
|
||||
auto drvPath = attr->forceDerivation();
|
||||
|
||||
std::set<std::string> outputsToInstall;
|
||||
std::optional<NixInt> priority;
|
||||
|
||||
if (auto aOutputSpecified = attr->maybeGetAttr(state->sOutputSpecified)) {
|
||||
if (aOutputSpecified->getBool()) {
|
||||
if (auto aOutputName = attr->maybeGetAttr("outputName"))
|
||||
outputsToInstall = { aOutputName->getString() };
|
||||
}
|
||||
}
|
||||
|
||||
else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) {
|
||||
if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall"))
|
||||
for (auto & s : aOutputsToInstall->getListOfStrings())
|
||||
outputsToInstall.insert(s);
|
||||
if (auto aPriority = aMeta->maybeGetAttr("priority"))
|
||||
priority = aPriority->getInt();
|
||||
}
|
||||
|
||||
if (outputsToInstall.empty() || std::get_if<AllOutputs>(&outputsSpec)) {
|
||||
outputsToInstall.clear();
|
||||
if (auto aOutputs = attr->maybeGetAttr(state->sOutputs))
|
||||
for (auto & s : aOutputs->getListOfStrings())
|
||||
outputsToInstall.insert(s);
|
||||
}
|
||||
|
||||
if (outputsToInstall.empty())
|
||||
outputsToInstall.insert("out");
|
||||
|
||||
if (auto outputNames = std::get_if<OutputNames>(&outputsSpec))
|
||||
outputsToInstall = *outputNames;
|
||||
|
||||
auto drvInfo = DerivationInfo {
|
||||
std::move(drvPath),
|
||||
attr->getAttr(state->sOutputName)->getString()
|
||||
.drvPath = std::move(drvPath),
|
||||
.outputsToInstall = std::move(outputsToInstall),
|
||||
.priority = priority,
|
||||
};
|
||||
|
||||
return {attrPath, getLockedFlake()->flake.lockedRef, std::move(drvInfo)};
|
||||
|
@ -723,8 +784,14 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
|||
state->eval(e, *vFile);
|
||||
}
|
||||
|
||||
for (auto & s : ss)
|
||||
result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vFile, s == "." ? "" : s));
|
||||
for (auto & s : ss) {
|
||||
auto [prefix, outputsSpec] = parseOutputsSpec(s);
|
||||
result.push_back(
|
||||
std::make_shared<InstallableAttrPath>(
|
||||
state, *this, vFile,
|
||||
prefix == "." ? "" : prefix,
|
||||
outputsSpec));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -743,12 +810,13 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
|||
}
|
||||
|
||||
try {
|
||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(s, absPath("."));
|
||||
auto [flakeRef, fragment, outputsSpec] = parseFlakeRefWithFragmentAndOutputsSpec(s, absPath("."));
|
||||
result.push_back(std::make_shared<InstallableFlake>(
|
||||
this,
|
||||
getEvalState(),
|
||||
std::move(flakeRef),
|
||||
fragment,
|
||||
outputsSpec,
|
||||
getDefaultFlakeAttrPaths(),
|
||||
getDefaultFlakeAttrPathPrefixes(),
|
||||
lockFlags));
|
||||
|
@ -822,12 +890,13 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
|
|||
auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
|
||||
auto drvOutputs = drv.outputsAndOptPaths(*store);
|
||||
for (auto & output : bfd.outputs) {
|
||||
if (!outputHashes.count(output))
|
||||
auto outputHash = get(outputHashes, output);
|
||||
if (!outputHash)
|
||||
throw Error(
|
||||
"the derivation '%s' doesn't have an output named '%s'",
|
||||
store->printStorePath(bfd.drvPath), output);
|
||||
if (settings.isExperimentalFeatureEnabled(Xp::CaDerivations)) {
|
||||
DrvOutput outputId { outputHashes.at(output), output };
|
||||
DrvOutput outputId { *outputHash, output };
|
||||
auto realisation = store->queryRealisation(outputId);
|
||||
if (!realisation)
|
||||
throw Error(
|
||||
|
@ -838,10 +907,11 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
|
|||
} else {
|
||||
// If ca-derivations isn't enabled, assume that
|
||||
// the output path is statically known.
|
||||
assert(drvOutputs.count(output));
|
||||
assert(drvOutputs.at(output).second);
|
||||
auto drvOutput = get(drvOutputs, output);
|
||||
assert(drvOutput);
|
||||
assert(drvOutput->second);
|
||||
outputs.insert_or_assign(
|
||||
output, *drvOutputs.at(output).second);
|
||||
output, *drvOutput->second);
|
||||
}
|
||||
}
|
||||
res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }});
|
||||
|
@ -856,6 +926,9 @@ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::bui
|
|||
break;
|
||||
|
||||
case Realise::Outputs: {
|
||||
if (settings.printMissing)
|
||||
printMissing(store, pathsToBuild, lvlInfo);
|
||||
|
||||
for (auto & buildResult : store->buildPathsWithResults(pathsToBuild, bMode, evalStore)) {
|
||||
if (!buildResult.success())
|
||||
buildResult.rethrow();
|
||||
|
@ -969,21 +1042,26 @@ InstallablesCommand::InstallablesCommand()
|
|||
|
||||
void InstallablesCommand::prepare()
|
||||
{
|
||||
installables = load();
|
||||
}
|
||||
|
||||
Installables InstallablesCommand::load() {
|
||||
Installables installables;
|
||||
if (_installables.empty() && useDefaultInstallables())
|
||||
// FIXME: commands like "nix profile install" should not have a
|
||||
// default, probably.
|
||||
_installables.push_back(".");
|
||||
installables = parseInstallables(getStore(), _installables);
|
||||
return parseInstallables(getStore(), _installables);
|
||||
}
|
||||
|
||||
std::optional<FlakeRef> InstallablesCommand::getFlakeRefForCompletion()
|
||||
std::vector<std::string> InstallablesCommand::getFlakesForCompletion()
|
||||
{
|
||||
if (_installables.empty()) {
|
||||
if (useDefaultInstallables())
|
||||
return parseFlakeRefWithFragment(".", absPath(".")).first;
|
||||
return {"."};
|
||||
return {};
|
||||
}
|
||||
return parseFlakeRefWithFragment(_installables.front(), absPath(".")).first;
|
||||
return _installables;
|
||||
}
|
||||
|
||||
InstallableCommand::InstallableCommand(bool supportReadOnlyMode)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue