aboutsummaryrefslogtreecommitdiff
path: root/src/libcmd
diff options
context:
space:
mode:
authorRobert Hensing <roberth@users.noreply.github.com>2023-05-15 15:42:57 +0200
committerGitHub <noreply@github.com>2023-05-15 15:42:57 +0200
commit0c49c1af28c7128d9dd140eb3ba392300778bd59 (patch)
treea9c989bec1f54c60a4e6dab1111f55a2d3b0da7f /src/libcmd
parent914672dc4f955afc3478c256145e7f6098b7da63 (diff)
parentd2162e7acdad4818788d229ed2d4600412b2be52 (diff)
Merge pull request #7601 from obsidiansystems/string-installables
Make more string values work as installables
Diffstat (limited to 'src/libcmd')
-rw-r--r--src/libcmd/installable-attr-path.cc10
-rw-r--r--src/libcmd/installable-flake.cc30
-rw-r--r--src/libcmd/installable-value.cc22
-rw-r--r--src/libcmd/installable-value.hh18
4 files changed, 55 insertions, 25 deletions
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 37e59cfdf..eb944240b 100644
--- a/src/libcmd/installable-flake.cc
+++ b/src/libcmd/installable-flake.cc
@@ -95,31 +95,13 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
// FIXME: use eval cache?
auto v = attr->forceValue();
- 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) {
- NixStringContext 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(NixStringContextElem::Opaque { .path = *storePath })) {
- 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);
}
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 5ab7eee16..3138ce8ec 100644
--- a/src/libcmd/installable-value.hh
+++ b/src/libcmd/installable-value.hh
@@ -98,6 +98,24 @@ struct InstallableValue : Installable
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);
};
}