aboutsummaryrefslogtreecommitdiff
path: root/src/nix
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/develop.cc86
-rw-r--r--src/nix/get-env.sh20
2 files changed, 98 insertions, 8 deletions
diff --git a/src/nix/develop.cc b/src/nix/develop.cc
index 2790ff154..9ecfdef5d 100644
--- a/src/nix/develop.cc
+++ b/src/nix/develop.cc
@@ -8,9 +8,12 @@
#include "derivations.hh"
#include "progress-bar.hh"
#include "run.hh"
+#include "util.hh"
+#include <iterator>
#include <memory>
#include <nlohmann/json.hpp>
+#include <algorithm>
using namespace nix;
@@ -51,6 +54,7 @@ struct BuildEnvironment
std::map<std::string, Value> vars;
std::map<std::string, std::string> bashFunctions;
+ std::optional<std::pair<std::string, std::string>> structuredAttrs;
static BuildEnvironment fromJSON(std::string_view in)
{
@@ -74,6 +78,10 @@ struct BuildEnvironment
res.bashFunctions.insert({name, def});
}
+ if (json.contains("structuredAttrs")) {
+ res.structuredAttrs = {json["structuredAttrs"][".attrs.json"], json["structuredAttrs"][".attrs.sh"]};
+ }
+
return res;
}
@@ -102,6 +110,13 @@ struct BuildEnvironment
res["bashFunctions"] = bashFunctions;
+ if (providesStructuredAttrs()) {
+ auto contents = nlohmann::json::object();
+ contents[".attrs.sh"] = getAttrsSH();
+ contents[".attrs.json"] = getAttrsJSON();
+ res["structuredAttrs"] = std::move(contents);
+ }
+
auto json = res.dump();
assert(BuildEnvironment::fromJSON(json) == *this);
@@ -109,6 +124,23 @@ struct BuildEnvironment
return json;
}
+ bool providesStructuredAttrs() const
+ {
+ return structuredAttrs.has_value();
+ }
+
+ std::string getAttrsJSON() const
+ {
+ assert(providesStructuredAttrs());
+ return structuredAttrs->first;
+ }
+
+ std::string getAttrsSH() const
+ {
+ assert(providesStructuredAttrs());
+ return structuredAttrs->second;
+ }
+
void toBash(std::ostream & out, const std::set<std::string> & ignoreVars) const
{
for (auto & [name, value] : vars) {
@@ -290,6 +322,7 @@ struct Common : InstallableCommand, MixProfile
std::string makeRcScript(
ref<Store> store,
const BuildEnvironment & buildEnvironment,
+ const Path & tmpDir,
const Path & outputsDir = absPath(".") + "/outputs")
{
// A list of colon-separated environment variables that should be
@@ -352,9 +385,48 @@ struct Common : InstallableCommand, MixProfile
}
}
+ if (buildEnvironment.providesStructuredAttrs()) {
+ fixupStructuredAttrs(
+ "sh",
+ "NIX_ATTRS_SH_FILE",
+ buildEnvironment.getAttrsSH(),
+ rewrites,
+ buildEnvironment,
+ tmpDir
+ );
+ fixupStructuredAttrs(
+ "json",
+ "NIX_ATTRS_JSON_FILE",
+ buildEnvironment.getAttrsJSON(),
+ rewrites,
+ buildEnvironment,
+ tmpDir
+ );
+ }
+
return rewriteStrings(script, rewrites);
}
+ /**
+ * Replace the value of NIX_ATTRS_*_FILE (`/build/.attrs.*`) with a tmp file
+ * that's accessible from the interactive shell session.
+ */
+ void fixupStructuredAttrs(
+ const std::string & ext,
+ const std::string & envVar,
+ const std::string & content,
+ StringMap & rewrites,
+ const BuildEnvironment & buildEnvironment,
+ const Path & tmpDir)
+ {
+ auto targetFilePath = tmpDir + "/.attrs." + ext;
+ writeFile(targetFilePath, content);
+
+ auto fileInBuilderEnv = buildEnvironment.vars.find(envVar);
+ assert(fileInBuilderEnv != buildEnvironment.vars.end());
+ rewrites.insert({BuildEnvironment::getString(fileInBuilderEnv->second), targetFilePath});
+ }
+
Strings getDefaultFlakeAttrPaths() override
{
Strings paths{
@@ -486,7 +558,9 @@ struct CmdDevelop : Common, MixEnvironment
auto [rcFileFd, rcFilePath] = createTempFile("nix-shell");
- auto script = makeRcScript(store, buildEnvironment);
+ AutoDelete tmpDir(createTempDir("", "nix-develop"), true);
+
+ auto script = makeRcScript(store, buildEnvironment, (Path) tmpDir);
if (verbosity >= lvlDebug)
script += "set -x\n";
@@ -618,10 +692,12 @@ struct CmdPrintDevEnv : Common, MixJSON
stopProgressBar();
- logger->writeToStdout(
- json
- ? buildEnvironment.toJSON()
- : makeRcScript(store, buildEnvironment));
+ if (json) {
+ logger->writeToStdout(buildEnvironment.toJSON());
+ } else {
+ AutoDelete tmpDir(createTempDir("", "nix-dev-env"), true);
+ logger->writeToStdout(makeRcScript(store, buildEnvironment, tmpDir));
+ }
}
};
diff --git a/src/nix/get-env.sh b/src/nix/get-env.sh
index a7a8a01b9..832cc2f11 100644
--- a/src/nix/get-env.sh
+++ b/src/nix/get-env.sh
@@ -1,5 +1,5 @@
set -e
-if [ -e .attrs.sh ]; then source .attrs.sh; fi
+if [ -e "$NIX_ATTRS_SH_FILE" ]; then source "$NIX_ATTRS_SH_FILE"; fi
export IN_NIX_SHELL=impure
export dontAddDisableDepTrack=1
@@ -101,7 +101,21 @@ __dumpEnv() {
printf "}"
done < <(printf "%s\n" "$__vars")
- printf '\n }\n}'
+ printf '\n }'
+
+ if [ -e "$NIX_ATTRS_SH_FILE" ]; then
+ printf ',\n "structuredAttrs": {\n '
+ __escapeString ".attrs.sh"
+ printf ': '
+ __escapeString "$(<"$NIX_ATTRS_SH_FILE")"
+ printf ',\n '
+ __escapeString ".attrs.json"
+ printf ': '
+ __escapeString "$(<"$NIX_ATTRS_JSON_FILE")"
+ printf '\n }'
+ fi
+
+ printf '\n}'
}
__escapeString() {
@@ -117,7 +131,7 @@ __escapeString() {
# In case of `__structuredAttrs = true;` the list of outputs is an associative
# array with a format like `outname => /nix/store/hash-drvname-outname`, so `__olist`
# must contain the array's keys (hence `${!...[@]}`) in this case.
-if [ -e .attrs.sh ]; then
+if [ -e "$NIX_ATTRS_SH_FILE" ]; then
__olist="${!outputs[@]}"
else
__olist=$outputs