diff options
Diffstat (limited to 'src/libcmd')
-rw-r--r-- | src/libcmd/command.cc | 63 | ||||
-rw-r--r-- | src/libcmd/command.hh | 21 | ||||
-rw-r--r-- | src/libcmd/installables.cc | 104 | ||||
-rw-r--r-- | src/libcmd/installables.hh | 16 | ||||
-rw-r--r-- | src/libcmd/local.mk | 2 | ||||
-rw-r--r-- | src/libcmd/markdown.cc | 4 |
6 files changed, 156 insertions, 54 deletions
diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index 2daf43aa7..6d183dfad 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -54,6 +54,36 @@ void StoreCommand::run() run(getStore()); } +CopyCommand::CopyCommand() +{ + addFlag({ + .longName = "from", + .description = "URL of the source Nix store.", + .labels = {"store-uri"}, + .handler = {&srcUri}, + }); + + addFlag({ + .longName = "to", + .description = "URL of the destination Nix store.", + .labels = {"store-uri"}, + .handler = {&dstUri}, + }); +} + +ref<Store> CopyCommand::createStore() +{ + return srcUri.empty() ? StoreCommand::createStore() : openStore(srcUri); +} + +ref<Store> CopyCommand::getDstStore() +{ + if (srcUri.empty() && dstUri.empty()) + throw UsageError("you must pass '--from' and/or '--to'"); + + return dstUri.empty() ? openStore() : openStore(dstUri); +} + EvalCommand::EvalCommand() { } @@ -74,7 +104,15 @@ ref<Store> EvalCommand::getEvalStore() ref<EvalState> EvalCommand::getEvalState() { if (!evalState) - evalState = std::make_shared<EvalState>(searchPath, getEvalStore(), getStore()); + evalState = + #if HAVE_BOEHMGC + std::allocate_shared<EvalState>(traceable_allocator<EvalState>(), + searchPath, getEvalStore(), getStore()) + #else + std::make_shared<EvalState>( + searchPath, getEvalStore(), getStore()) + #endif + ; return ref<EvalState>(evalState); } @@ -120,7 +158,7 @@ void BuiltPathsCommand::run(ref<Store> store) // XXX: This only computes the store path closure, ignoring // intermediate realisations StorePathSet pathsRoots, pathsClosure; - for (auto & root: paths) { + for (auto & root : paths) { auto rootFromThis = root.outPaths(); pathsRoots.insert(rootFromThis.begin(), rootFromThis.end()); } @@ -138,17 +176,20 @@ StorePathsCommand::StorePathsCommand(bool recursive) { } -void StorePathsCommand::run(ref<Store> store, BuiltPaths paths) +void StorePathsCommand::run(ref<Store> store, BuiltPaths && paths) { - StorePaths storePaths; - for (auto& builtPath : paths) - for (auto& p : builtPath.outPaths()) - storePaths.push_back(p); + StorePathSet storePaths; + for (auto & builtPath : paths) + for (auto & p : builtPath.outPaths()) + storePaths.insert(p); + + auto sorted = store->topoSortPaths(storePaths); + std::reverse(sorted.begin(), sorted.end()); - run(store, std::move(storePaths)); + run(store, std::move(sorted)); } -void StorePathCommand::run(ref<Store> store, std::vector<StorePath> storePaths) +void StorePathCommand::run(ref<Store> store, std::vector<StorePath> && storePaths) { if (storePaths.size() != 1) throw UsageError("this command requires exactly one store path"); @@ -200,10 +241,10 @@ void MixProfile::updateProfile(const BuiltPaths & buildables) for (auto & buildable : buildables) { std::visit(overloaded { - [&](BuiltPath::Opaque bo) { + [&](const BuiltPath::Opaque & bo) { result.push_back(bo.path); }, - [&](BuiltPath::Built bfd) { + [&](const BuiltPath::Built & bfd) { for (auto & output : bfd.outputs) { result.push_back(output.second); } diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index dac146d24..bd2a0a7ee 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -43,6 +43,19 @@ private: std::shared_ptr<Store> _store; }; +/* A command that copies something between `--from` and `--to` + stores. */ +struct CopyCommand : virtual StoreCommand +{ + std::string srcUri, dstUri; + + CopyCommand(); + + ref<Store> createStore() override; + + ref<Store> getDstStore(); +}; + struct EvalCommand : virtual StoreCommand, MixEvalArgs { EvalCommand(); @@ -169,7 +182,7 @@ public: using StoreCommand::run; - virtual void run(ref<Store> store, BuiltPaths paths) = 0; + virtual void run(ref<Store> store, BuiltPaths && paths) = 0; void run(ref<Store> store) override; @@ -182,9 +195,9 @@ struct StorePathsCommand : public BuiltPathsCommand using BuiltPathsCommand::run; - virtual void run(ref<Store> store, std::vector<StorePath> storePaths) = 0; + virtual void run(ref<Store> store, std::vector<StorePath> && storePaths) = 0; - void run(ref<Store> store, BuiltPaths paths) override; + void run(ref<Store> store, BuiltPaths && paths) override; }; /* A command that operates on exactly one store path. */ @@ -194,7 +207,7 @@ struct StorePathCommand : public StorePathsCommand virtual void run(ref<Store> store, const StorePath & storePath) = 0; - void run(ref<Store> store, std::vector<StorePath> storePaths) override; + void run(ref<Store> store, std::vector<StorePath> && storePaths) override; }; /* A helper class for registering commands globally. */ diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 8015cff4d..c07e39628 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -97,7 +97,7 @@ MixFlakeOptions::MixFlakeOptions() lockFlags.writeLockFile = false; lockFlags.inputOverrides.insert_or_assign( flake::parseInputPath(inputPath), - parseFlakeRef(flakeRef, absPath("."))); + parseFlakeRef(flakeRef, absPath("."), true)); }} }); @@ -158,7 +158,10 @@ SourceExprCommand::SourceExprCommand() Strings SourceExprCommand::getDefaultFlakeAttrPaths() { - return {"defaultPackage." + settings.thisSystem.get()}; + return { + "packages." + settings.thisSystem.get() + ".default", + "defaultPackage." + settings.thisSystem.get() + }; } Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes() @@ -191,18 +194,21 @@ void SourceExprCommand::completeInstallable(std::string_view prefix) auto sep = prefix_.rfind('.'); std::string searchWord; if (sep != std::string::npos) { - searchWord = prefix_.substr(sep, std::string::npos); + searchWord = prefix_.substr(sep + 1, std::string::npos); prefix_ = prefix_.substr(0, sep); } else { searchWord = prefix_; prefix_ = ""; } - Value &v1(*findAlongAttrPath(*state, prefix_, *autoArgs, root).first); - state->forceValue(v1); + auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root); + Value &v1(*v); + state->forceValue(v1, pos); Value v2; state->autoCallFunction(*autoArgs, v1, v2); + completionType = ctAttrs; + if (v2.type() == nAttrs) { for (auto & i : *v2.attrs) { std::string name = i.name; @@ -232,7 +238,9 @@ void completeFlakeRefWithFragment( prefix. */ try { auto hash = prefix.find('#'); - if (hash != std::string::npos) { + if (hash == std::string::npos) { + completeFlakeRef(evalState->store, prefix); + } else { auto fragment = prefix.substr(hash + 1); auto flakeRefS = std::string(prefix.substr(0, hash)); // FIXME: do tilde expansion. @@ -248,6 +256,8 @@ void completeFlakeRefWithFragment( flake. */ attrPathPrefixes.push_back(""); + completionType = ctAttrs; + for (auto & attrPathPrefixS : attrPathPrefixes) { auto attrPathPrefix = parseAttrPath(*evalState, attrPathPrefixS); auto attrPathS = attrPathPrefixS + std::string(fragment); @@ -285,12 +295,13 @@ void completeFlakeRefWithFragment( } catch (Error & e) { warn(e.msg()); } - - completeFlakeRef(evalState->store, prefix); } void completeFlakeRef(ref<Store> store, std::string_view prefix) { + if (!settings.isExperimentalFeatureEnabled(Xp::Flakes)) + return; + if (prefix == "") completions->add("."); @@ -338,6 +349,18 @@ Installable::getCursor(EvalState & state) return cursors[0]; } +static StorePath getDeriver( + ref<Store> store, + const Installable & i, + const StorePath & drvPath) +{ + auto derivers = store->queryValidDerivers(drvPath); + if (derivers.empty()) + throw Error("'%s' does not have a known deriver", i.what()); + // FIXME: use all derivers? + return *derivers.begin(); +} + struct InstallableStorePath : Installable { ref<Store> store; @@ -346,7 +369,7 @@ struct InstallableStorePath : Installable InstallableStorePath(ref<Store> store, StorePath && storePath) : store(store), storePath(std::move(storePath)) { } - std::string what() override { return store->printStorePath(storePath); } + std::string what() const override { return store->printStorePath(storePath); } DerivedPaths toDerivedPaths() override { @@ -367,6 +390,15 @@ struct InstallableStorePath : Installable } } + StorePathSet toDrvPaths(ref<Store> store) override + { + if (storePath.isDerivation()) { + return {storePath}; + } else { + return {getDeriver(store, *this, storePath)}; + } + } + std::optional<StorePath> getStorePath() override { return storePath; @@ -395,6 +427,14 @@ DerivedPaths InstallableValue::toDerivedPaths() return res; } +StorePathSet InstallableValue::toDrvPaths(ref<Store> store) +{ + StorePathSet res; + for (auto & drv : toDerivations()) + res.insert(drv.drvPath); + return res; +} + struct InstallableAttrPath : InstallableValue { SourceExprCommand & cmd; @@ -405,12 +445,12 @@ struct InstallableAttrPath : InstallableValue : InstallableValue(state), cmd(cmd), v(allocRootValue(v)), attrPath(attrPath) { } - std::string what() override { return attrPath; } + std::string what() const override { return attrPath; } std::pair<Value *, Pos> toValue(EvalState & state) override { auto [vRes, pos] = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(state), **v); - state.forceValue(*vRes); + state.forceValue(*vRes, pos); return {vRes, pos}; } @@ -460,7 +500,7 @@ Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::Locked auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs")); assert(aOutputs); - state.forceValue(*aOutputs->value); + state.forceValue(*aOutputs->value, [&]() { return aOutputs->value->determinePos(noPos); }); return aOutputs->value; } @@ -485,7 +525,7 @@ ref<eval_cache::EvalCache> openEvalCache( auto vFlake = state.allocValue(); flake::callFlake(state, *lockedFlake, *vFlake); - state.forceAttrs(*vFlake); + state.forceAttrs(*vFlake, noPos); auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs")); assert(aOutputs); @@ -508,13 +548,14 @@ InstallableFlake::InstallableFlake( SourceExprCommand * cmd, ref<EvalState> state, FlakeRef && flakeRef, - Strings && attrPaths, - Strings && prefixes, + std::string_view fragment, + Strings attrPaths, + Strings prefixes, const flake::LockFlags & lockFlags) : InstallableValue(state), flakeRef(flakeRef), - attrPaths(attrPaths), - prefixes(prefixes), + attrPaths(fragment == "" ? attrPaths : Strings{(std::string) fragment}), + prefixes(fragment == "" ? Strings{} : prefixes), lockFlags(lockFlags) { if (cmd && cmd->getAutoArgs(*state)->size()) @@ -529,6 +570,8 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF auto root = cache->getRoot(); for (auto & attrPath : getActualAttrPaths()) { + debug("trying flake output attribute '%s'", attrPath); + auto attr = root->findAlongAttrPath( parseAttrPath(*state, attrPath), true @@ -572,7 +615,7 @@ std::pair<Value *, Pos> InstallableFlake::toValue(EvalState & state) for (auto & attrPath : getActualAttrPaths()) { try { auto [v, pos] = findAlongAttrPath(state, attrPath, *emptyArgs, *vOutputs); - state.forceValue(*v); + state.forceValue(*v, pos); return {v, pos}; } catch (AttrPathNotFound & e) { } @@ -671,7 +714,8 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables( this, getEvalState(), std::move(flakeRef), - fragment == "" ? getDefaultFlakeAttrPaths() : Strings{fragment}, + fragment, + getDefaultFlakeAttrPaths(), getDefaultFlakeAttrPathPrefixes(), lockFlags)); continue; @@ -697,13 +741,13 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable( BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPaths & hopefullyBuiltPaths) { BuiltPaths res; - for (auto & b : hopefullyBuiltPaths) + for (const auto & b : hopefullyBuiltPaths) std::visit( overloaded{ - [&](DerivedPath::Opaque bo) { + [&](const DerivedPath::Opaque & bo) { res.push_back(BuiltPath::Opaque{bo.path}); }, - [&](DerivedPath::Built bfd) { + [&](const DerivedPath::Built & bfd) { OutputPathMap outputs; auto drv = evalStore->readDerivation(bfd.drvPath); auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive @@ -714,7 +758,7 @@ BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPa "the derivation '%s' doesn't have an output named '%s'", store->printStorePath(bfd.drvPath), output); if (settings.isExperimentalFeatureEnabled( - "ca-derivations")) { + Xp::CaDerivations)) { auto outputId = DrvOutput{outputHashes.at(output), output}; auto realisation = @@ -823,19 +867,15 @@ StorePathSet toDerivations( { StorePathSet drvPaths; - for (auto & i : installables) - for (auto & b : i->toDerivedPaths()) + for (const auto & i : installables) + for (const auto & b : i->toDerivedPaths()) std::visit(overloaded { - [&](DerivedPath::Opaque bo) { + [&](const DerivedPath::Opaque & bo) { if (!useDeriver) throw Error("argument '%s' did not evaluate to a derivation", i->what()); - auto derivers = store->queryValidDerivers(bo.path); - if (derivers.empty()) - throw Error("'%s' does not have a known deriver", i->what()); - // FIXME: use all derivers? - drvPaths.insert(*derivers.begin()); + drvPaths.insert(getDeriver(store, *i, bo.path)); }, - [&](DerivedPath::Built bfd) { + [&](const DerivedPath::Built & bfd) { drvPaths.insert(bfd.drvPath); }, }, b.raw()); diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh index 79931ad3e..3d2563e4b 100644 --- a/src/libcmd/installables.hh +++ b/src/libcmd/installables.hh @@ -33,10 +33,15 @@ struct Installable { virtual ~Installable() { } - virtual std::string what() = 0; + virtual std::string what() const = 0; virtual DerivedPaths toDerivedPaths() = 0; + virtual StorePathSet toDrvPaths(ref<Store> store) + { + throw Error("'%s' cannot be converted to a derivation path", what()); + } + DerivedPath toDerivedPath(); UnresolvedApp toApp(EvalState & state); @@ -81,6 +86,8 @@ struct InstallableValue : Installable virtual std::vector<DerivationInfo> toDerivations() = 0; DerivedPaths toDerivedPaths() override; + + StorePathSet toDrvPaths(ref<Store> store) override; }; struct InstallableFlake : InstallableValue @@ -95,11 +102,12 @@ struct InstallableFlake : InstallableValue SourceExprCommand * cmd, ref<EvalState> state, FlakeRef && flakeRef, - Strings && attrPaths, - Strings && prefixes, + std::string_view fragment, + Strings attrPaths, + Strings prefixes, const flake::LockFlags & lockFlags); - std::string what() override { return flakeRef.to_string() + "#" + *attrPaths.begin(); } + std::string what() const override { return flakeRef.to_string() + "#" + *attrPaths.begin(); } std::vector<std::string> getActualAttrPaths(); diff --git a/src/libcmd/local.mk b/src/libcmd/local.mk index 8b0662753..7a2f83cc7 100644 --- a/src/libcmd/local.mk +++ b/src/libcmd/local.mk @@ -8,7 +8,7 @@ libcmd_SOURCES := $(wildcard $(d)/*.cc) libcmd_CXXFLAGS += -I src/libutil -I src/libstore -I src/libexpr -I src/libmain -I src/libfetchers -libcmd_LDFLAGS += -llowdown -pthread +libcmd_LDFLAGS += $(LOWDOWN_LIBS) -pthread libcmd_LIBS = libstore libutil libexpr libmain libfetchers diff --git a/src/libcmd/markdown.cc b/src/libcmd/markdown.cc index 737356284..29bb4d31e 100644 --- a/src/libcmd/markdown.cc +++ b/src/libcmd/markdown.cc @@ -25,7 +25,7 @@ std::string renderMarkdownToTerminal(std::string_view markdown) Finally freeDoc([&]() { lowdown_doc_free(doc); }); size_t maxn = 0; - auto node = lowdown_doc_parse(doc, &maxn, markdown.data(), markdown.size()); + auto node = lowdown_doc_parse(doc, &maxn, markdown.data(), markdown.size(), nullptr); if (!node) throw Error("cannot parse Markdown document"); Finally freeNode([&]() { lowdown_node_free(node); }); @@ -40,7 +40,7 @@ std::string renderMarkdownToTerminal(std::string_view markdown) throw Error("cannot allocate Markdown output buffer"); Finally freeBuffer([&]() { lowdown_buf_free(buf); }); - int rndr_res = lowdown_term_rndr(buf, nullptr, renderer, node); + int rndr_res = lowdown_term_rndr(buf, renderer, node); if (!rndr_res) throw Error("allocation error while rendering Markdown"); |