aboutsummaryrefslogtreecommitdiff
path: root/src/libcmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcmd')
-rw-r--r--src/libcmd/command.cc2
-rw-r--r--src/libcmd/common-eval-args.cc10
-rw-r--r--src/libcmd/common-eval-args.hh6
-rw-r--r--src/libcmd/editor-for.cc7
-rw-r--r--src/libcmd/editor-for.hh3
-rw-r--r--src/libcmd/installable-attr-path.cc10
-rw-r--r--src/libcmd/installable-flake.cc33
-rw-r--r--src/libcmd/installable-flake.hh15
-rw-r--r--src/libcmd/installable-value.cc22
-rw-r--r--src/libcmd/installable-value.hh23
-rw-r--r--src/libcmd/installables.cc2
-rw-r--r--src/libcmd/repl.cc16
12 files changed, 95 insertions, 54 deletions
diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc
index bedf11e2c..6c4648b34 100644
--- a/src/libcmd/command.cc
+++ b/src/libcmd/command.cc
@@ -121,6 +121,8 @@ ref<EvalState> EvalCommand::getEvalState()
#endif
;
+ evalState->repair = repair;
+
if (startReplOnEvalErrors) {
evalState->debugRepl = &AbstractNixRepl::runSimple;
};
diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc
index 5b6477c82..ff3abd534 100644
--- a/src/libcmd/common-eval-args.cc
+++ b/src/libcmd/common-eval-args.cc
@@ -153,7 +153,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
for (auto & i : autoArgs) {
auto v = state.allocValue();
if (i.second[0] == 'E')
- state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), absPath(".")));
+ state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), state.rootPath(CanonPath::fromCwd())));
else
v->mkString(((std::string_view) i.second).substr(1));
res.insert(state.symbols.create(i.first), v);
@@ -161,19 +161,19 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
return res.finish();
}
-Path lookupFileArg(EvalState & state, std::string_view s)
+SourcePath lookupFileArg(EvalState & state, std::string_view s)
{
if (EvalSettings::isPseudoUrl(s)) {
auto storePath = fetchers::downloadTarball(
state.store, EvalSettings::resolvePseudoUrl(s), "source", false).first.storePath;
- return state.store->toRealPath(storePath);
+ return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
}
else if (hasPrefix(s, "flake:")) {
experimentalFeatureSettings.require(Xp::Flakes);
auto flakeRef = parseFlakeRef(std::string(s.substr(6)), {}, true, false);
auto storePath = flakeRef.resolve(state.store).fetchTree(state.store).first.storePath;
- return state.store->toRealPath(storePath);
+ return state.rootPath(CanonPath(state.store->toRealPath(storePath)));
}
else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') {
@@ -182,7 +182,7 @@ Path lookupFileArg(EvalState & state, std::string_view s)
}
else
- return absPath(std::string(s));
+ return state.rootPath(CanonPath::fromCwd(s));
}
}
diff --git a/src/libcmd/common-eval-args.hh b/src/libcmd/common-eval-args.hh
index b69db11dd..b65cb5b20 100644
--- a/src/libcmd/common-eval-args.hh
+++ b/src/libcmd/common-eval-args.hh
@@ -2,14 +2,16 @@
///@file
#include "args.hh"
+#include "common-args.hh"
namespace nix {
class Store;
class EvalState;
class Bindings;
+struct SourcePath;
-struct MixEvalArgs : virtual Args
+struct MixEvalArgs : virtual Args, virtual MixRepair
{
static constexpr auto category = "Common evaluation options";
@@ -25,6 +27,6 @@ private:
std::map<std::string, std::string> autoArgs;
};
-Path lookupFileArg(EvalState & state, std::string_view s);
+SourcePath lookupFileArg(EvalState & state, std::string_view s);
}
diff --git a/src/libcmd/editor-for.cc b/src/libcmd/editor-for.cc
index f674f32bd..a17c6f12a 100644
--- a/src/libcmd/editor-for.cc
+++ b/src/libcmd/editor-for.cc
@@ -3,8 +3,11 @@
namespace nix {
-Strings editorFor(const Path & file, uint32_t line)
+Strings editorFor(const SourcePath & file, uint32_t line)
{
+ auto path = file.getPhysicalPath();
+ if (!path)
+ throw Error("cannot open '%s' in an editor because it has no physical path", file);
auto editor = getEnv("EDITOR").value_or("cat");
auto args = tokenizeString<Strings>(editor);
if (line > 0 && (
@@ -13,7 +16,7 @@ Strings editorFor(const Path & file, uint32_t line)
editor.find("vim") != std::string::npos ||
editor.find("kak") != std::string::npos))
args.push_back(fmt("+%d", line));
- args.push_back(file);
+ args.push_back(path->abs());
return args;
}
diff --git a/src/libcmd/editor-for.hh b/src/libcmd/editor-for.hh
index c8c4e9d9b..fbf4307c9 100644
--- a/src/libcmd/editor-for.hh
+++ b/src/libcmd/editor-for.hh
@@ -2,6 +2,7 @@
///@file
#include "types.hh"
+#include "input-accessor.hh"
namespace nix {
@@ -9,6 +10,6 @@ namespace nix {
* Helper function to generate args that invoke $EDITOR on
* filename:lineno.
*/
-Strings editorFor(const Path & file, uint32_t line);
+Strings editorFor(const SourcePath & file, uint32_t line);
}
diff --git a/src/libcmd/installable-attr-path.cc b/src/libcmd/installable-attr-path.cc
index cf513126d..b35ca2910 100644
--- a/src/libcmd/installable-attr-path.cc
+++ b/src/libcmd/installable-attr-path.cc
@@ -46,7 +46,15 @@ std::pair<Value *, PosIdx> InstallableAttrPath::toValue(EvalState & state)
DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
{
- auto v = toValue(*state).first;
+ auto [v, pos] = toValue(*state);
+
+ if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths(
+ *v,
+ pos,
+ fmt("while evaluating the attribute '%s'", attrPath)))
+ {
+ return { *derivedPathWithInfo };
+ }
Bindings & autoArgs = *cmd.getAutoArgs(*state);
diff --git a/src/libcmd/installable-flake.cc b/src/libcmd/installable-flake.cc
index a3352af76..eb944240b 100644
--- a/src/libcmd/installable-flake.cc
+++ b/src/libcmd/installable-flake.cc
@@ -95,32 +95,13 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
// FIXME: use eval cache?
auto v = attr->forceValue();
- if (v.type() == nPath) {
- PathSet context;
- auto storePath = state->copyPathToStore(context, Path(v.path));
- return {{
- .path = DerivedPath::Opaque {
- .path = std::move(storePath),
- },
- .info = make_ref<ExtraPathInfo>(),
- }};
- }
-
- else if (v.type() == nString) {
- PathSet context;
- auto s = state->forceString(v, context, noPos, fmt("while evaluating the flake output attribute '%s'", attrPath));
- auto storePath = state->store->maybeParseStorePath(s);
- if (storePath && context.count(std::string(s))) {
- return {{
- .path = DerivedPath::Opaque {
- .path = std::move(*storePath),
- },
- .info = make_ref<ExtraPathInfo>(),
- }};
- } else
- throw Error("flake output attribute '%s' evaluates to the string '%s' which is not a store path", attrPath, s);
+ if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths(
+ v,
+ noPos,
+ fmt("while evaluating the flake output attribute '%s'", attrPath)))
+ {
+ return { *derivedPathWithInfo };
}
-
else
throw Error("flake output attribute '%s' is not a derivation or path", attrPath);
}
@@ -235,7 +216,7 @@ FlakeRef InstallableFlake::nixpkgsFlakeRef() const
}
}
- return InstallableValue::nixpkgsFlakeRef();
+ return defaultNixpkgsFlakeRef();
}
}
diff --git a/src/libcmd/installable-flake.hh b/src/libcmd/installable-flake.hh
index afe64d977..7ac4358d2 100644
--- a/src/libcmd/installable-flake.hh
+++ b/src/libcmd/installable-flake.hh
@@ -67,9 +67,22 @@ struct InstallableFlake : InstallableValue
std::shared_ptr<flake::LockedFlake> getLockedFlake() const;
- FlakeRef nixpkgsFlakeRef() const override;
+ FlakeRef nixpkgsFlakeRef() const;
};
+/**
+ * Default flake ref for referring to Nixpkgs. For flakes that don't
+ * have their own Nixpkgs input, or other installables.
+ *
+ * It is a layer violation for Nix to know about Nixpkgs; currently just
+ * `nix develop` does. Be wary of using this /
+ * `InstallableFlake::nixpkgsFlakeRef` more places.
+ */
+static inline FlakeRef defaultNixpkgsFlakeRef()
+{
+ return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
+}
+
ref<eval_cache::EvalCache> openEvalCache(
EvalState & state,
std::shared_ptr<flake::LockedFlake> lockedFlake);
diff --git a/src/libcmd/installable-value.cc b/src/libcmd/installable-value.cc
index 3a7ede4e2..1eff293cc 100644
--- a/src/libcmd/installable-value.cc
+++ b/src/libcmd/installable-value.cc
@@ -41,4 +41,26 @@ ref<InstallableValue> InstallableValue::require(ref<Installable> installable)
return ref { castedInstallable };
}
+std::optional<DerivedPathWithInfo> InstallableValue::trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx)
+{
+ if (v.type() == nPath) {
+ auto storePath = v.path().fetchToStore(state->store);
+ return {{
+ .path = DerivedPath::Opaque {
+ .path = std::move(storePath),
+ },
+ .info = make_ref<ExtraPathInfo>(),
+ }};
+ }
+
+ else if (v.type() == nString) {
+ return {{
+ .path = state->coerceToDerivedPath(pos, v, errorCtx),
+ .info = make_ref<ExtraPathInfo>(),
+ }};
+ }
+
+ else return std::nullopt;
+}
+
}
diff --git a/src/libcmd/installable-value.hh b/src/libcmd/installable-value.hh
index bfb3bfeed..3138ce8ec 100644
--- a/src/libcmd/installable-value.hh
+++ b/src/libcmd/installable-value.hh
@@ -96,13 +96,26 @@ struct InstallableValue : Installable
UnresolvedApp toApp(EvalState & state);
- virtual FlakeRef nixpkgsFlakeRef() const
- {
- return FlakeRef::fromAttrs({{"type","indirect"}, {"id", "nixpkgs"}});
- }
-
static InstallableValue & require(Installable & installable);
static ref<InstallableValue> require(ref<Installable> installable);
+
+protected:
+
+ /**
+ * Handles either a plain path, or a string with a single string
+ * context elem in the right format. The latter case is handled by
+ * `EvalState::coerceToDerivedPath()`; see it for details.
+ *
+ * @param v Value that is hopefully a string or path per the above.
+ *
+ * @param pos Position of value to aid with diagnostics.
+ *
+ * @param errorCtx Arbitrary message for use in potential error message when something is wrong with `v`.
+ *
+ * @result A derived path (with empty info, for now) if the value
+ * matched the above criteria.
+ */
+ std::optional<DerivedPathWithInfo> trySinglePathToDerivedPaths(Value & v, const PosIdx pos, std::string_view errorCtx);
};
}
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index 0a2fe0073..a2b882355 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -449,7 +449,7 @@ Installables SourceExprCommand::parseInstallables(
else if (file)
state->evalFile(lookupFileArg(*state, *file), *vFile);
else {
- auto e = state->parseExprFromString(*expr, absPath("."));
+ auto e = state->parseExprFromString(*expr, state->rootPath(CanonPath::fromCwd()));
state->eval(e, *vFile);
}
diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc
index 80c08bf1c..4b160a100 100644
--- a/src/libcmd/repl.cc
+++ b/src/libcmd/repl.cc
@@ -55,8 +55,6 @@ struct NixRepl
, gc
#endif
{
- std::string curDir;
-
size_t debugTraceIndex;
Strings loadedFiles;
@@ -114,7 +112,6 @@ NixRepl::NixRepl(const Strings & searchPath, nix::ref<Store> store, ref<EvalStat
, staticEnv(new StaticEnv(false, state->staticBaseEnv.get()))
, historyFile(getDataDir() + "/nix/repl-history")
{
- curDir = absPath(".");
}
@@ -594,14 +591,14 @@ bool NixRepl::processLine(std::string line)
Value v;
evalString(arg, v);
- const auto [path, line] = [&] () -> std::pair<Path, uint32_t> {
+ const auto [path, line] = [&] () -> std::pair<SourcePath, uint32_t> {
if (v.type() == nPath || v.type() == nString) {
- PathSet context;
+ NixStringContext context;
auto path = state->coerceToPath(noPos, v, context, "while evaluating the filename to edit");
return {path, 0};
} else if (v.isLambda()) {
auto pos = state->positions[v.lambda.fun->pos];
- if (auto path = std::get_if<Path>(&pos.origin))
+ if (auto path = std::get_if<SourcePath>(&pos.origin))
return {*path, pos.line};
else
throw Error("'%s' cannot be shown in an editor", pos);
@@ -876,8 +873,7 @@ void NixRepl::addVarToScope(const Symbol name, Value & v)
Expr * NixRepl::parseString(std::string s)
{
- Expr * e = state->parseExprFromString(std::move(s), curDir, staticEnv);
- return e;
+ return state->parseExprFromString(std::move(s), state->rootPath(CanonPath::fromCwd()), staticEnv);
}
@@ -925,7 +921,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
break;
case nPath:
- str << ANSI_GREEN << v.path << ANSI_NORMAL; // !!! escaping?
+ str << ANSI_GREEN << v.path().to_string() << ANSI_NORMAL; // !!! escaping?
break;
case nNull:
@@ -940,7 +936,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
if (isDrv) {
str << "«derivation ";
Bindings::iterator i = v.attrs->find(state->sDrvPath);
- PathSet context;
+ NixStringContext context;
if (i != v.attrs->end())
str << state->store->printStorePath(state->coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation"));
else