aboutsummaryrefslogtreecommitdiff
path: root/src/libcmd
diff options
context:
space:
mode:
authorBen Burdette <bburdette@protonmail.com>2022-04-07 13:42:01 -0600
committerBen Burdette <bburdette@protonmail.com>2022-04-07 13:42:01 -0600
commit1a93ac8133381eb692416c4e46b1706faa5cd89f (patch)
tree9a559f977ad6213c055099f6f2ab6be96f0c551b /src/libcmd
parentd2ec9b4e15718e42720787140d7825dcbfd73249 (diff)
parent8b1e328d5d0ae7d3a4a8f6012ec065b59674ed4a (diff)
Merge remote-tracking branch 'upstream/master' into upstream-merge
Diffstat (limited to 'src/libcmd')
-rw-r--r--src/libcmd/command.cc5
-rw-r--r--src/libcmd/command.hh54
-rw-r--r--src/libcmd/installables.cc226
-rw-r--r--src/libcmd/installables.hh68
-rw-r--r--src/libcmd/repl.cc112
5 files changed, 276 insertions, 189 deletions
diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc
index e3c8fb29f..5cb8728e9 100644
--- a/src/libcmd/command.cc
+++ b/src/libcmd/command.cc
@@ -209,7 +209,7 @@ void BuiltPathsCommand::run(ref<Store> store)
for (auto & p : store->queryAllValidPaths())
paths.push_back(BuiltPath::Opaque{p});
} else {
- paths = toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
+ paths = Installable::toBuiltPaths(getEvalStore(), store, realiseMode, operateOn, installables);
if (recursive) {
// XXX: This only computes the store path closure, ignoring
// intermediate realisations
@@ -260,7 +260,8 @@ Strings editorFor(const Pos & pos)
if (pos.line > 0 && (
editor.find("emacs") != std::string::npos ||
editor.find("nano") != std::string::npos ||
- editor.find("vim") != 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);
return args;
diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh
index 146a08ed6..94ad80210 100644
--- a/src/libcmd/command.hh
+++ b/src/libcmd/command.hh
@@ -5,7 +5,6 @@
#include "common-eval-args.hh"
#include "path.hh"
#include "flake/lockfile.hh"
-#include "store-api.hh"
#include <optional>
@@ -84,14 +83,6 @@ struct MixFlakeOptions : virtual Args, EvalCommand
{ return {}; }
};
-/* How to handle derivations in commands that operate on store paths. */
-enum class OperateOn {
- /* Operate on the output path. */
- Output,
- /* Operate on the .drv path. */
- Derivation
-};
-
struct SourceExprCommand : virtual Args, MixFlakeOptions
{
std::optional<Path> file;
@@ -115,19 +106,6 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
void completeInstallable(std::string_view prefix);
};
-enum class Realise {
- /* Build the derivation. Postcondition: the
- derivation outputs exist. */
- Outputs,
- /* Don't build the derivation. Postcondition: the store derivation
- exists. */
- Derivation,
- /* Evaluate in dry-run mode. Postcondition: nothing. */
- // FIXME: currently unused, but could be revived if we can
- // evaluate derivations in-memory.
- Nothing
-};
-
/* A command that operates on a list of "installables", which can be
store paths, attribute paths, Nix expressions, etc. */
struct InstallablesCommand : virtual Args, SourceExprCommand
@@ -240,38 +218,6 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
}
-BuiltPaths build(
- ref<Store> evalStore,
- ref<Store> store, Realise mode,
- const std::vector<std::shared_ptr<Installable>> & installables,
- BuildMode bMode = bmNormal);
-
-std::set<StorePath> toStorePaths(
- ref<Store> evalStore,
- ref<Store> store,
- Realise mode,
- OperateOn operateOn,
- const std::vector<std::shared_ptr<Installable>> & installables);
-
-StorePath toStorePath(
- ref<Store> evalStore,
- ref<Store> store,
- Realise mode,
- OperateOn operateOn,
- std::shared_ptr<Installable> installable);
-
-std::set<StorePath> toDerivations(
- ref<Store> store,
- const std::vector<std::shared_ptr<Installable>> & installables,
- bool useDeriver = false);
-
-BuiltPaths toBuiltPaths(
- ref<Store> evalStore,
- ref<Store> store,
- Realise mode,
- OperateOn operateOn,
- const std::vector<std::shared_ptr<Installable>> & installables);
-
/* Helper function to generate args that invoke $EDITOR on
filename:lineno. */
Strings editorFor(const Pos & pos);
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index 38a177f80..955bbe6fb 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -12,6 +12,7 @@
#include "eval-cache.hh"
#include "url.hh"
#include "registry.hh"
+#include "build-result.hh"
#include <regex>
#include <queue>
@@ -97,7 +98,7 @@ MixFlakeOptions::MixFlakeOptions()
lockFlags.writeLockFile = false;
lockFlags.inputOverrides.insert_or_assign(
flake::parseInputPath(inputPath),
- parseFlakeRef(flakeRef, absPath(".")));
+ parseFlakeRef(flakeRef, absPath("."), true));
}}
});
@@ -133,7 +134,9 @@ SourceExprCommand::SourceExprCommand()
addFlag({
.longName = "file",
.shortName = 'f',
- .description = "Interpret installables as attribute paths relative to the Nix expression stored in *file*.",
+ .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.",
.category = installablesCategory,
.labels = {"file"},
.handler = {&file},
@@ -158,7 +161,10 @@ SourceExprCommand::SourceExprCommand()
Strings SourceExprCommand::getDefaultFlakeAttrPaths()
{
- return {"defaultPackage." + settings.thisSystem.get()};
+ return {
+ "packages." + settings.thisSystem.get() + ".default",
+ "defaultPackage." + settings.thisSystem.get()
+ };
}
Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
@@ -269,9 +275,9 @@ void completeFlakeRefWithFragment(
auto attr = root->findAlongAttrPath(attrPath);
if (!attr) continue;
- for (auto & attr2 : attr->getAttrs()) {
+ for (auto & attr2 : (*attr)->getAttrs()) {
if (hasPrefix(attr2, lastAttr)) {
- auto attrPath2 = attr->getAttrPath(attr2);
+ auto attrPath2 = (*attr)->getAttrPath(attr2);
/* Strip the attrpath prefix. */
attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size());
completions->add(flakeRefS + "#" + concatStringsSep(".", attrPath2));
@@ -465,11 +471,10 @@ std::vector<InstallableValue::DerivationInfo> InstallableAttrPath::toDerivations
std::vector<DerivationInfo> res;
for (auto & drvInfo : drvInfos) {
- res.push_back({
- state->store->parseStorePath(drvInfo.queryDrvPath()),
- state->store->maybeParseStorePath(drvInfo.queryOutPath()),
- drvInfo.queryOutputName()
- });
+ auto drvPath = drvInfo.queryDrvPath();
+ if (!drvPath)
+ throw Error("'%s' is not a derivation", what());
+ res.push_back({ *drvPath, drvInfo.queryOutputName() });
}
return res;
@@ -545,13 +550,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())
@@ -565,29 +571,37 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
auto cache = openEvalCache(*state, lockedFlake);
auto root = cache->getRoot();
+ Suggestions suggestions;
+
for (auto & attrPath : getActualAttrPaths()) {
- auto attr = root->findAlongAttrPath(
+ debug("trying flake output attribute '%s'", attrPath);
+
+ auto attrOrSuggestions = root->findAlongAttrPath(
parseAttrPath(*state, attrPath),
true
);
- if (!attr) continue;
+ if (!attrOrSuggestions) {
+ suggestions += attrOrSuggestions.getSuggestions();
+ continue;
+ }
+
+ auto attr = *attrOrSuggestions;
if (!attr->isDerivation())
throw Error("flake output attribute '%s' is not a derivation", attrPath);
auto drvPath = attr->forceDerivation();
- auto drvInfo = DerivationInfo{
+ auto drvInfo = DerivationInfo {
std::move(drvPath),
- state->store->maybeParseStorePath(attr->getAttr(state->sOutPath)->getString()),
attr->getAttr(state->sOutputName)->getString()
};
return {attrPath, lockedFlake->flake.lockedRef, std::move(drvInfo)};
}
- throw Error("flake '%s' does not provide attribute %s",
+ throw Error(suggestions, "flake '%s' does not provide attribute %s",
flakeRef, showAttrPaths(getActualAttrPaths()));
}
@@ -606,17 +620,24 @@ std::pair<Value *, Pos> InstallableFlake::toValue(EvalState & state)
auto emptyArgs = state.allocBindings(0);
+ Suggestions suggestions;
+
for (auto & attrPath : getActualAttrPaths()) {
try {
auto [v, pos] = findAlongAttrPath(state, attrPath, *emptyArgs, *vOutputs);
state.forceValue(*v, pos);
return {v, pos};
} catch (AttrPathNotFound & e) {
+ suggestions += e.info().suggestions;
}
}
- throw Error("flake '%s' does not provide attribute %s",
- flakeRef, showAttrPaths(getActualAttrPaths()));
+ throw Error(
+ suggestions,
+ "flake '%s' does not provide attribute %s",
+ flakeRef,
+ showAttrPaths(getActualAttrPaths())
+ );
}
std::vector<std::pair<std::shared_ptr<eval_cache::AttrCursor>, std::string>>
@@ -631,7 +652,7 @@ InstallableFlake::getCursors(EvalState & state)
for (auto & attrPath : getActualAttrPaths()) {
auto attr = root->findAlongAttrPath(parseAttrPath(state, attrPath));
- if (attr) res.push_back({attr, attrPath});
+ if (attr) res.push_back({*attr, attrPath});
}
return res;
@@ -676,7 +697,10 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
auto state = getEvalState();
auto vFile = state->allocValue();
- if (file)
+ if (file == "-") {
+ auto e = state->parseStdin();
+ state->eval(e, *vFile);
+ } else if (file)
state->evalFile(lookupFileArg(*state, *file), *vFile);
else {
auto e = state->parseExprFromString(*expr, absPath("."));
@@ -708,7 +732,8 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
this,
getEvalState(),
std::move(flakeRef),
- fragment == "" ? getDefaultFlakeAttrPaths() : Strings{fragment},
+ fragment,
+ getDefaultFlakeAttrPaths(),
getDefaultFlakeAttrPathPrefixes(),
lockFlags));
continue;
@@ -731,56 +756,20 @@ std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
return installables.front();
}
-BuiltPaths getBuiltPaths(ref<Store> evalStore, ref<Store> store, const DerivedPaths & hopefullyBuiltPaths)
+BuiltPaths Installable::build(
+ ref<Store> evalStore,
+ ref<Store> store,
+ Realise mode,
+ const std::vector<std::shared_ptr<Installable>> & installables,
+ BuildMode bMode)
{
BuiltPaths res;
- for (const auto & b : hopefullyBuiltPaths)
- std::visit(
- overloaded{
- [&](const DerivedPath::Opaque & bo) {
- res.push_back(BuiltPath::Opaque{bo.path});
- },
- [&](const DerivedPath::Built & bfd) {
- OutputPathMap outputs;
- auto drv = evalStore->readDerivation(bfd.drvPath);
- auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
- auto drvOutputs = drv.outputsAndOptPaths(*store);
- for (auto & output : bfd.outputs) {
- if (!outputHashes.count(output))
- throw Error(
- "the derivation '%s' doesn't have an output named '%s'",
- store->printStorePath(bfd.drvPath), output);
- if (settings.isExperimentalFeatureEnabled(
- Xp::CaDerivations)) {
- auto outputId =
- DrvOutput{outputHashes.at(output), output};
- auto realisation =
- store->queryRealisation(outputId);
- if (!realisation)
- throw Error(
- "cannot operate on an output of unbuilt "
- "content-addressed 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);
- outputs.insert_or_assign(
- output, *drvOutputs.at(output).second);
- }
- }
- res.push_back(BuiltPath::Built{bfd.drvPath, outputs});
- },
- },
- b.raw());
-
+ for (auto & [_, builtPath] : build2(evalStore, store, mode, installables, bMode))
+ res.push_back(builtPath);
return res;
}
-BuiltPaths build(
+std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> Installable::build2(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
@@ -791,21 +780,96 @@ BuiltPaths build(
settings.readOnlyMode = true;
std::vector<DerivedPath> pathsToBuild;
+ std::map<DerivedPath, std::vector<std::shared_ptr<Installable>>> backmap;
for (auto & i : installables) {
- auto b = i->toDerivedPaths();
- pathsToBuild.insert(pathsToBuild.end(), b.begin(), b.end());
+ for (auto b : i->toDerivedPaths()) {
+ pathsToBuild.push_back(b);
+ backmap[b].push_back(i);
+ }
}
- if (mode == Realise::Nothing || mode == Realise::Derivation)
+ std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> res;
+
+ switch (mode) {
+
+ case Realise::Nothing:
+ case Realise::Derivation:
printMissing(store, pathsToBuild, lvlError);
- else if (mode == Realise::Outputs)
- store->buildPaths(pathsToBuild, bMode, evalStore);
- return getBuiltPaths(evalStore, store, pathsToBuild);
+ for (auto & path : pathsToBuild) {
+ for (auto & installable : backmap[path]) {
+ std::visit(overloaded {
+ [&](const DerivedPath::Built & bfd) {
+ OutputPathMap outputs;
+ auto drv = evalStore->readDerivation(bfd.drvPath);
+ auto outputHashes = staticOutputHashes(*evalStore, drv); // FIXME: expensive
+ auto drvOutputs = drv.outputsAndOptPaths(*store);
+ for (auto & output : bfd.outputs) {
+ if (!outputHashes.count(output))
+ 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 };
+ auto realisation = store->queryRealisation(outputId);
+ if (!realisation)
+ throw Error(
+ "cannot operate on an output of unbuilt "
+ "content-addressed 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);
+ outputs.insert_or_assign(
+ output, *drvOutputs.at(output).second);
+ }
+ }
+ res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }});
+ },
+ [&](const DerivedPath::Opaque & bo) {
+ res.push_back({installable, BuiltPath::Opaque { bo.path }});
+ },
+ }, path.raw());
+ }
+ }
+
+ break;
+
+ case Realise::Outputs: {
+ for (auto & buildResult : store->buildPathsWithResults(pathsToBuild, bMode, evalStore)) {
+ if (!buildResult.success())
+ buildResult.rethrow();
+
+ for (auto & installable : backmap[buildResult.path]) {
+ std::visit(overloaded {
+ [&](const DerivedPath::Built & bfd) {
+ std::map<std::string, StorePath> outputs;
+ for (auto & path : buildResult.builtOutputs)
+ outputs.emplace(path.first.outputName, path.second.outPath);
+ res.push_back({installable, BuiltPath::Built { bfd.drvPath, outputs }});
+ },
+ [&](const DerivedPath::Opaque & bo) {
+ res.push_back({installable, BuiltPath::Opaque { bo.path }});
+ },
+ }, buildResult.path.raw());
+ }
+ }
+
+ break;
+ }
+
+ default:
+ assert(false);
+ }
+
+ return res;
}
-BuiltPaths toBuiltPaths(
+BuiltPaths Installable::toBuiltPaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode,
@@ -813,19 +877,19 @@ BuiltPaths toBuiltPaths(
const std::vector<std::shared_ptr<Installable>> & installables)
{
if (operateOn == OperateOn::Output)
- return build(evalStore, store, mode, installables);
+ return Installable::build(evalStore, store, mode, installables);
else {
if (mode == Realise::Nothing)
settings.readOnlyMode = true;
BuiltPaths res;
- for (auto & drvPath : toDerivations(store, installables, true))
+ for (auto & drvPath : Installable::toDerivations(store, installables, true))
res.push_back(BuiltPath::Opaque{drvPath});
return res;
}
}
-StorePathSet toStorePaths(
+StorePathSet Installable::toStorePaths(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn,
@@ -839,7 +903,7 @@ StorePathSet toStorePaths(
return outPaths;
}
-StorePath toStorePath(
+StorePath Installable::toStorePath(
ref<Store> evalStore,
ref<Store> store,
Realise mode, OperateOn operateOn,
@@ -853,7 +917,7 @@ StorePath toStorePath(
return *paths.begin();
}
-StorePathSet toDerivations(
+StorePathSet Installable::toDerivations(
ref<Store> store,
const std::vector<std::shared_ptr<Installable>> & installables,
bool useDeriver)
diff --git a/src/libcmd/installables.hh b/src/libcmd/installables.hh
index ced6b3f10..f4bf0d406 100644
--- a/src/libcmd/installables.hh
+++ b/src/libcmd/installables.hh
@@ -5,6 +5,7 @@
#include "path-with-outputs.hh"
#include "derived-path.hh"
#include "eval.hh"
+#include "store-api.hh"
#include "flake/flake.hh"
#include <optional>
@@ -29,6 +30,27 @@ struct UnresolvedApp
App resolve(ref<Store> evalStore, ref<Store> store);
};
+enum class Realise {
+ /* Build the derivation. Postcondition: the
+ derivation outputs exist. */
+ Outputs,
+ /* Don't build the derivation. Postcondition: the store derivation
+ exists. */
+ Derivation,
+ /* Evaluate in dry-run mode. Postcondition: nothing. */
+ // FIXME: currently unused, but could be revived if we can
+ // evaluate derivations in-memory.
+ Nothing
+};
+
+/* How to handle derivations in commands that operate on store paths. */
+enum class OperateOn {
+ /* Operate on the output path. */
+ Output,
+ /* Operate on the .drv path. */
+ Derivation
+};
+
struct Installable
{
virtual ~Installable() { }
@@ -68,6 +90,46 @@ struct Installable
{
return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
}
+
+ static BuiltPaths build(
+ ref<Store> evalStore,
+ ref<Store> store,
+ Realise mode,
+ const std::vector<std::shared_ptr<Installable>> & installables,
+ BuildMode bMode = bmNormal);
+
+ static std::vector<std::pair<std::shared_ptr<Installable>, BuiltPath>> build2(
+ ref<Store> evalStore,
+ ref<Store> store,
+ Realise mode,
+ const std::vector<std::shared_ptr<Installable>> & installables,
+ BuildMode bMode = bmNormal);
+
+ static std::set<StorePath> toStorePaths(
+ ref<Store> evalStore,
+ ref<Store> store,
+ Realise mode,
+ OperateOn operateOn,
+ const std::vector<std::shared_ptr<Installable>> & installables);
+
+ static StorePath toStorePath(
+ ref<Store> evalStore,
+ ref<Store> store,
+ Realise mode,
+ OperateOn operateOn,
+ std::shared_ptr<Installable> installable);
+
+ static std::set<StorePath> toDerivations(
+ ref<Store> store,
+ const std::vector<std::shared_ptr<Installable>> & installables,
+ bool useDeriver = false);
+
+ static BuiltPaths toBuiltPaths(
+ ref<Store> evalStore,
+ ref<Store> store,
+ Realise mode,
+ OperateOn operateOn,
+ const std::vector<std::shared_ptr<Installable>> & installables);
};
struct InstallableValue : Installable
@@ -79,7 +141,6 @@ struct InstallableValue : Installable
struct DerivationInfo
{
StorePath drvPath;
- std::optional<StorePath> outPath;
std::string outputName;
};
@@ -102,8 +163,9 @@ 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() const override { return flakeRef.to_string() + "#" + *attrPaths.begin(); }
diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc
index 31d0019d4..3dd55e104 100644
--- a/src/libcmd/repl.cc
+++ b/src/libcmd/repl.cc
@@ -25,6 +25,7 @@ extern "C" {
#include "eval-inline.hh"
#include "attr-path.hh"
#include "store-api.hh"
+#include "log-store.hh"
#include "common-eval-args.hh"
#include "get-drvs.hh"
#include "derivations.hh"
@@ -45,7 +46,7 @@ struct NixRepl
: gc
#endif
{
- string curDir;
+ std::string curDir;
ref<EvalState> state;
Bindings * autoArgs;
@@ -65,10 +66,10 @@ struct NixRepl
NixRepl(ref<EvalState> state);
~NixRepl();
void mainLoop(const std::vector<std::string> & files);
- StringSet completePrefix(string prefix);
- bool getLine(string & input, const std::string &prompt);
+ StringSet completePrefix(const std::string & prefix);
+ bool getLine(std::string & input, const std::string &prompt);
StorePath getDerivationPath(Value & v);
- bool processLine(string line);
+ bool processLine(std::string line);
void loadFile(const Path & path);
void loadFlake(const std::string & flakeRef);
void initEnv();
@@ -76,22 +77,21 @@ struct NixRepl
void reloadFiles();
void addAttrsToScope(Value & attrs);
void addVarToScope(const Symbol & name, Value & v);
- Expr * parseString(string s);
- void evalString(string s, Value & v);
+ Expr * parseString(std::string s);
+ void evalString(std::string s, Value & v);
void loadDebugTraceEnv(DebugTrace &dt);
- typedef set<Value *> ValuesSeen;
+ typedef std::set<Value *> ValuesSeen;
std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth);
std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth, ValuesSeen & seen);
};
-string removeWhitespace(string s)
+std::string removeWhitespace(std::string s)
{
s = chomp(s);
size_t n = s.find_first_not_of(" \n\r\t");
- if (n != string::npos) s = string(s, n);
-
+ if (n != std::string::npos) s = std::string(s, n);
return s;
}
@@ -111,7 +111,7 @@ NixRepl::~NixRepl()
write_history(historyFile.c_str());
}
-string runNix(Path program, const Strings & args,
+std::string runNix(Path program, const Strings & args,
const std::optional<std::string> & input = {})
{
auto subprocessEnv = getEnv();
@@ -229,7 +229,7 @@ std::ostream& showDebugTrace(std::ostream &out, const DebugTrace &dt)
void NixRepl::mainLoop(const std::vector<std::string> & files)
{
- string error = ANSI_RED "error:" ANSI_NORMAL " ";
+ std::string error = ANSI_RED "error:" ANSI_NORMAL " ";
notice("Welcome to Nix " + nixVersion + ". Type :? for help.\n");
if (!files.empty()) {
@@ -297,7 +297,7 @@ void NixRepl::mainLoop(const std::vector<std::string> & files)
}
-bool NixRepl::getLine(string & input, const std::string &prompt)
+bool NixRepl::getLine(std::string & input, const std::string & prompt)
{
struct sigaction act, old;
sigset_t savedSignalMask, set;
@@ -342,7 +342,7 @@ bool NixRepl::getLine(string & input, const std::string &prompt)
}
-StringSet NixRepl::completePrefix(string prefix)
+StringSet NixRepl::completePrefix(const std::string & prefix)
{
StringSet completions;
@@ -358,7 +358,7 @@ StringSet NixRepl::completePrefix(string prefix)
size_t slash, dot;
- if ((slash = cur.rfind('/')) != string::npos) {
+ if ((slash = cur.rfind('/')) != std::string::npos) {
try {
auto dir = std::string(cur, 0, slash);
auto prefix2 = std::string(cur, slash + 1);
@@ -368,11 +368,11 @@ StringSet NixRepl::completePrefix(string prefix)
}
} catch (Error &) {
}
- } else if ((dot = cur.rfind('.')) == string::npos) {
+ } else if ((dot = cur.rfind('.')) == std::string::npos) {
/* This is a variable name; look it up in the current scope. */
StringSet::iterator i = varNames.lower_bound(cur);
while (i != varNames.end()) {
- if (string(*i, 0, cur.size()) != cur) break;
+ if (i->substr(0, cur.size()) != cur) break;
completions.insert(prev + *i);
i++;
}
@@ -381,8 +381,8 @@ StringSet NixRepl::completePrefix(string prefix)
/* This is an expression that should evaluate to an
attribute set. Evaluate it to get the names of the
attributes. */
- string expr(cur, 0, dot);
- string cur2 = string(cur, dot + 1);
+ auto expr = cur.substr(0, dot);
+ auto cur2 = cur.substr(dot + 1);
Expr * e = parseString(expr);
Value v;
@@ -390,8 +390,8 @@ StringSet NixRepl::completePrefix(string prefix)
state->forceAttrs(v, noPos);
for (auto & i : *v.attrs) {
- string name = i.name;
- if (string(name, 0, cur2.size()) != cur2) continue;
+ std::string name = i.name;
+ if (name.substr(0, cur2.size()) != cur2) continue;
completions.insert(prev + expr + "." + name);
}
@@ -410,7 +410,7 @@ StringSet NixRepl::completePrefix(string prefix)
}
-bool isVarName(const string & s)
+static bool isVarName(std::string_view s)
{
if (s.size() == 0) return false;
char c = s[0];
@@ -429,13 +429,12 @@ StorePath NixRepl::getDerivationPath(Value & v) {
auto drvInfo = getDerivation(*state, v, false);
if (!drvInfo)
throw Error("expression does not evaluate to a derivation, so I can't build it");
- Path drvPathRaw = drvInfo->queryDrvPath();
- if (drvPathRaw == "")
- throw Error("expression did not evaluate to a valid derivation (no drv path)");
- StorePath drvPath = state->store->parseStorePath(drvPathRaw);
- if (!state->store->isValidPath(drvPath))
- throw Error("expression did not evaluate to a valid derivation (invalid drv path)");
- return drvPath;
+ auto drvPath = drvInfo->queryDrvPath();
+ if (!drvPath)
+ throw Error("expression did not evaluate to a valid derivation (no 'drvPath' attribute)");
+ if (!state->store->isValidPath(*drvPath))
+ throw Error("expression evaluated to invalid derivation '%s'", state->store->printStorePath(*drvPath));
+ return *drvPath;
}
void NixRepl::loadDebugTraceEnv(DebugTrace &dt)
@@ -457,18 +456,19 @@ void NixRepl::loadDebugTraceEnv(DebugTrace &dt)
}
}
-bool NixRepl::processLine(string line)
+bool NixRepl::processLine(std::string line)
{
+ line = trim(line);
if (line == "") return true;
_isInterrupted = false;
- string command, arg;
+ std::string command, arg;
if (line[0] == ':') {
size_t p = line.find_first_of(" \n\r\t");
- command = string(line, 0, p);
- if (p != string::npos) arg = removeWhitespace(string(line, p));
+ command = line.substr(0, p);
+ if (p != std::string::npos) arg = removeWhitespace(line.substr(p));
} else {
arg = line;
}
@@ -667,9 +667,16 @@ bool NixRepl::processLine(string line)
bool foundLog = false;
RunPager pager;
for (auto & sub : subs) {
- auto log = sub->getBuildLog(drvPath);
+ auto * logSubP = dynamic_cast<LogStore *>(&*sub);
+ if (!logSubP) {
+ printInfo("Skipped '%s' which does not support retrieving build logs", sub->getUri());
+ continue;
+ }
+ auto & logSub = *logSubP;
+
+ auto log = logSub.getBuildLog(drvPath);
if (log) {
- printInfo("got build log for '%s' from '%s'", drvPathRaw, sub->getUri());
+ printInfo("got build log for '%s' from '%s'", drvPathRaw, logSub.getUri());
logger->writeToStdout(*log);
foundLog = true;
break;
@@ -733,13 +740,13 @@ bool NixRepl::processLine(string line)
else {
size_t p = line.find('=');
- string name;
- if (p != string::npos &&
+ std::string name;
+ if (p != std::string::npos &&
p < line.size() &&
line[p + 1] != '=' &&
- isVarName(name = removeWhitespace(string(line, 0, p))))
+ isVarName(name = removeWhitespace(line.substr(0, p))))
{
- Expr * e = parseString(string(line, p + 1));
+ Expr * e = parseString(line.substr(p + 1));
Value & v(*state->allocValue());
v.mkThunk(env, e);
addVarToScope(state->symbols.create(name), v);
@@ -766,9 +773,12 @@ void NixRepl::loadFile(const Path & path)
void NixRepl::loadFlake(const std::string & flakeRefS)
{
+ if (flakeRefS.empty())
+ throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");
+
auto flakeRef = parseFlakeRef(flakeRefS, absPath("."), true);
- if (evalSettings.pureEval && !flakeRef.input.isImmutable())
- throw Error("cannot use ':load-flake' on mutable flake reference '%s' (use --impure to override)", flakeRefS);
+ if (evalSettings.pureEval && !flakeRef.input.isLocked())
+ throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);
Value v;
@@ -829,7 +839,7 @@ void NixRepl::addAttrsToScope(Value & attrs)
for (auto & i : *attrs.attrs) {
staticEnv->vars.emplace_back(i.name, displ);
env->values[displ++] = i.value;
- varNames.insert((string) i.name);
+ varNames.insert((std::string) i.name);
}
staticEnv->sort();
staticEnv->deduplicate();
@@ -846,17 +856,18 @@ void NixRepl::addVarToScope(const Symbol & name, Value & v)
staticEnv->vars.emplace_back(name, displ);
staticEnv->sort();
env->values[displ++] = &v;
- varNames.insert((string) name);
+ varNames.insert((std::string) name);
}
-Expr * NixRepl::parseString(string s)
+
+Expr * NixRepl::parseString(std::string s)
{
Expr * e = state->parseExprFromString(std::move(s), curDir, staticEnv);
return e;
}
-void NixRepl::evalString(string s, Value & v)
+void NixRepl::evalString(std::string s, Value & v)
{
Expr * e = parseString(s);
e->eval(*state, *env, v);
@@ -925,14 +936,17 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
str << "«derivation ";
Bindings::iterator i = v.attrs->find(state->sDrvPath);
PathSet context;
- Path drvPath = i != v.attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "???";
- str << drvPath << "»";
+ if (i != v.attrs->end())
+ str << state->store->printStorePath(state->coerceToStorePath(*i->pos, *i->value, context));
+ else
+ str << "???";
+ str << "»";
}
else if (maxDepth > 0) {
str << "{ ";
- typedef std::map<string, Value *> Sorted;
+ typedef std::map<std::string, Value *> Sorted;
Sorted sorted;
for (auto & i : *v.attrs)
sorted[i.name] = i.value;
@@ -943,7 +957,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
else
printStringValue(str, i.first.c_str());
str << " = ";
- if (seen.find(i.second) != seen.end())
+ if (seen.count(i.second))
str << "«repeated»";
else
try {