diff options
Diffstat (limited to 'src/libcmd')
-rw-r--r-- | src/libcmd/command.cc | 8 | ||||
-rw-r--r-- | src/libcmd/command.hh | 2 | ||||
-rw-r--r-- | src/libcmd/installables.cc | 103 | ||||
-rw-r--r-- | src/libcmd/installables.hh | 8 | ||||
-rw-r--r-- | src/libcmd/markdown.cc | 4 |
5 files changed, 90 insertions, 35 deletions
diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index a53b029b7..f28cfe5de 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -197,17 +197,17 @@ void StorePathCommand::run(ref<Store> store, std::vector<StorePath> && storePath run(store, *storePaths.begin()); } -Strings editorFor(const Pos & pos) +Strings editorFor(const Path & file, uint32_t line) { auto editor = getEnv("EDITOR").value_or("cat"); auto args = tokenizeString<Strings>(editor); - if (pos.line > 0 && ( + if (line > 0 && ( editor.find("emacs") != std::string::npos || editor.find("nano") != std::string::npos || editor.find("vim") != std::string::npos || editor.find("kak") != std::string::npos)) - args.push_back(fmt("+%d", pos.line)); - args.push_back(pos.file); + args.push_back(fmt("+%d", line)); + args.push_back(file); return args; } diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 84bbb5292..078e2a2ce 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -219,7 +219,7 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name) /* Helper function to generate args that invoke $EDITOR on filename:lineno. */ -Strings editorFor(const Pos & pos); +Strings editorFor(const Path & file, uint32_t line); struct MixProfile : virtual StoreCommand { diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 483bc1421..e0a95118d 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -235,7 +235,7 @@ void SourceExprCommand::completeInstallable(std::string_view prefix) if (v2.type() == nAttrs) { for (auto & i : *v2.attrs) { - std::string name = i.name; + std::string name = state->symbols[i.name]; if (name.find(searchWord) == 0) { if (prefix_ == "") completions->add(name); @@ -291,7 +291,7 @@ void completeFlakeRefWithFragment( std::string lastAttr; if (!attrPath.empty() && !hasSuffix(attrPathS, ".")) { - lastAttr = attrPath.back(); + lastAttr = evalState->symbols[attrPath.back()]; attrPath.pop_back(); } @@ -299,11 +299,11 @@ void completeFlakeRefWithFragment( if (!attr) continue; for (auto & attr2 : (*attr)->getAttrs()) { - if (hasPrefix(attr2, lastAttr)) { + if (hasPrefix(evalState->symbols[attr2], lastAttr)) { auto attrPath2 = (*attr)->getAttrPath(attr2); /* Strip the attrpath prefix. */ attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size()); - completions->add(flakeRefS + "#" + concatStringsSep(".", attrPath2)); + completions->add(flakeRefS + "#" + concatStringsSep(".", evalState->symbols.resolve(attrPath2))); } } } @@ -460,10 +460,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); } @@ -486,14 +484,24 @@ struct InstallableAttrPath : InstallableValue SourceExprCommand & cmd; RootValue v; std::string attrPath; - - InstallableAttrPath(ref<EvalState> state, SourceExprCommand & cmd, Value * v, const std::string & attrPath) - : InstallableValue(state), cmd(cmd), v(allocRootValue(v)), attrPath(attrPath) + OutputsSpec outputsSpec; + + 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; } - std::pair<Value *, Pos> toValue(EvalState & state) override + std::pair<Value *, PosIdx> toValue(EvalState & state) override { auto [vRes, pos] = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(state), **v); state.forceValue(*vRes, pos); @@ -517,7 +525,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; @@ -594,6 +614,7 @@ InstallableFlake::InstallableFlake( ref<EvalState> state, FlakeRef && flakeRef, std::string_view fragment, + OutputsSpec outputsSpec, Strings attrPaths, Strings prefixes, const flake::LockFlags & lockFlags) @@ -601,6 +622,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()) @@ -618,9 +640,29 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF auto drvPath = attr->forceDerivation(); + std::set<std::string> outputsToInstall; + + if (auto aMeta = attr->maybeGetAttr(state->sMeta)) + if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall")) + for (auto & s : aOutputsToInstall->getListOfStrings()) + outputsToInstall.insert(s); + + 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), }; return {attrPath, getLockedFlake()->flake.lockedRef, std::move(drvInfo)}; @@ -633,7 +675,7 @@ std::vector<InstallableValue::DerivationInfo> InstallableFlake::toDerivations() return res; } -std::pair<Value *, Pos> InstallableFlake::toValue(EvalState & state) +std::pair<Value *, PosIdx> InstallableFlake::toValue(EvalState & state) { return {&getCursor(state)->forceValue(), noPos}; } @@ -743,8 +785,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 { @@ -777,12 +825,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)); @@ -856,26 +905,28 @@ 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( - "cannot operate on an output of unbuilt " - "content-addressed derivation '%s'", + "cannot operate on an output of the " + "unbuilt derivation '%s'", outputId.to_string()); outputs.insert_or_assign(output, realisation->outPath); } 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 }}); diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index b847f8939..1a5a96153 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -68,7 +68,7 @@ struct Installable UnresolvedApp toApp(EvalState & state); - virtual std::pair<Value *, Pos> toValue(EvalState & state) + virtual std::pair<Value *, PosIdx> toValue(EvalState & state) { throw Error("argument '%s' cannot be evaluated", what()); } @@ -141,7 +141,7 @@ struct InstallableValue : Installable struct DerivationInfo { StorePath drvPath; - std::string outputName; + std::set<std::string> outputsToInstall; }; virtual std::vector<DerivationInfo> toDerivations() = 0; @@ -156,6 +156,7 @@ struct InstallableFlake : InstallableValue FlakeRef flakeRef; Strings attrPaths; Strings prefixes; + OutputsSpec outputsSpec; const flake::LockFlags & lockFlags; mutable std::shared_ptr<flake::LockedFlake> _lockedFlake; @@ -164,6 +165,7 @@ struct InstallableFlake : InstallableValue ref<EvalState> state, FlakeRef && flakeRef, std::string_view fragment, + OutputsSpec outputsSpec, Strings attrPaths, Strings prefixes, const flake::LockFlags & lockFlags); @@ -178,7 +180,7 @@ struct InstallableFlake : InstallableValue std::vector<DerivationInfo> toDerivations() override; - std::pair<Value *, Pos> toValue(EvalState & state) override; + std::pair<Value *, PosIdx> toValue(EvalState & state) override; /* Get a cursor to every attrpath in getActualAttrPaths() that exists. */ diff --git a/src/libcmd/markdown.cc b/src/libcmd/markdown.cc index 29bb4d31e..71f9c8dff 100644 --- a/src/libcmd/markdown.cc +++ b/src/libcmd/markdown.cc @@ -9,10 +9,12 @@ namespace nix { std::string renderMarkdownToTerminal(std::string_view markdown) { + int windowWidth = getWindowSize().second; + struct lowdown_opts opts { .type = LOWDOWN_TERM, .maxdepth = 20, - .cols = std::max(getWindowSize().second, (unsigned short) 80), + .cols = (size_t) std::max(windowWidth - 5, 60), .hmargin = 0, .vmargin = 0, .feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES, |