aboutsummaryrefslogtreecommitdiff
path: root/src/libcmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcmd')
-rw-r--r--src/libcmd/command.cc63
-rw-r--r--src/libcmd/command.hh21
-rw-r--r--src/libcmd/installables.cc104
-rw-r--r--src/libcmd/installables.hh16
-rw-r--r--src/libcmd/local.mk2
-rw-r--r--src/libcmd/markdown.cc4
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");