Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 23 additions & 19 deletions src/libstore/derivations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,7 @@ adl_serializer<DerivationOutput>::from_json(const json & _json, const Experiment
}
}

void adl_serializer<Derivation>::to_json(json & res, const Derivation & d)
void adl_serializer<BasicDerivation>::to_json(json & res, const BasicDerivation & d)
{
res = nlohmann::json::object();

Expand All @@ -1549,24 +1549,6 @@ void adl_serializer<Derivation>::to_json(json & res, const Derivation & d)
for (auto & input : d.inputSrcs)
inputsList.emplace_back(input);
}

auto doInput = [&](this const auto & doInput, const auto & inputNode) -> nlohmann::json {
auto value = nlohmann::json::object();
value["outputs"] = inputNode.value;
{
auto next = nlohmann::json::object();
for (auto & [outputId, childNode] : inputNode.childMap)
next[outputId] = doInput(childNode);
value["dynamicOutputs"] = std::move(next);
}
return value;
};

auto & inputDrvsObj = inputsObj["drvs"];
inputDrvsObj = nlohmann::json::object();
for (auto & [inputDrv, inputNode] : d.inputDrvs.map) {
inputDrvsObj[inputDrv.to_string()] = doInput(inputNode);
}
}

res["system"] = d.platform;
Expand All @@ -1578,6 +1560,28 @@ void adl_serializer<Derivation>::to_json(json & res, const Derivation & d)
res["structuredAttrs"] = d.structuredAttrs->structuredAttrs;
}

void adl_serializer<Derivation>::to_json(json & res, const Derivation & d)
{
adl_serializer<BasicDerivation>::to_json(res, static_cast<const BasicDerivation &>(d));

auto doInput = [&](this const auto & doInput, const auto & inputNode) -> nlohmann::json {
auto value = nlohmann::json::object();
value["outputs"] = inputNode.value;
{
auto next = nlohmann::json::object();
for (auto & [outputId, childNode] : inputNode.childMap)
next[outputId] = doInput(childNode);
value["dynamicOutputs"] = std::move(next);
}
return value;
};

auto & inputDrvsObj = res["inputs"]["drvs"];
inputDrvsObj = nlohmann::json::object();
for (auto & [inputDrv, inputNode] : d.inputDrvs.map)
inputDrvsObj[inputDrv.to_string()] = doInput(inputNode);
}

Derivation adl_serializer<Derivation>::from_json(const json & _json, const ExperimentalFeatureSettings & xpSettings)
{
using nlohmann::detail::value_t;
Expand Down
1 change: 1 addition & 0 deletions src/libstore/include/nix/store/derivations.hh
Original file line number Diff line number Diff line change
Expand Up @@ -614,3 +614,4 @@ constexpr unsigned expectedJsonVersionDerivation = 4;

JSON_IMPL_WITH_XP_FEATURES(nix::DerivationOutput)
JSON_IMPL_WITH_XP_FEATURES(nix::Derivation)
JSON_IMPL_WITH_XP_FEATURES(nix::BasicDerivation)
22 changes: 18 additions & 4 deletions src/libstore/include/nix/store/globals.hh
Original file line number Diff line number Diff line change
Expand Up @@ -1081,10 +1081,24 @@ public:
captured by the derivation model itself and are too variable between
different versions of the same system to be hard-coded into nix.

The hook is passed the derivation path and, if sandboxes are
enabled, the sandbox directory. It can then modify the sandbox and
send a series of commands to modify various settings to stdout. The
currently recognized commands are:
The hook receives the derivation to be built as JSON in the file
pointed to by the environment variable `NIX_DERIVATION_V4`. See
[@docroot@/protocols/json/derivation/index.md](@docroot@/protocols/json/derivation/index.md)
for the format. For example, to read the `requiredSystemFeatures`
attribute:

```sh
jq -r '.env.requiredSystemFeatures' < "$NIX_DERIVATION_V4"
```

> **Deprecated**
> Using the derivation store path passed as `argv[1]` to inspect the
> derivation is deprecated and not recommended. This path may not
> exist when Nix is invoked as a remote builder.

If sandboxes are enabled, the hook also receives the sandbox
directory as `argv[2]`. It can send a series of commands to modify
various settings to stdout. The currently recognized commands are:

- `extra-sandbox-paths`\
Pass a list of files and directories to be included in the
Expand Down
22 changes: 21 additions & 1 deletion src/libstore/unix/build/derivation-builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "nix/util/terminal.hh"
#include "nix/store/provenance.hh"

#include <nlohmann/json.hpp>
#include <queue>

#include <sys/un.h>
Expand Down Expand Up @@ -932,8 +933,27 @@ PathsInChroot DerivationBuilderImpl::getPathsInSandbox()

enum BuildHookState { stBegin, stExtraChrootDirs };

nlohmann::json drvJson = drv;

auto [tmpFd, drvJsonPath] = createTempFile("nix-drv-json");
writeFile(drvJsonPath, drvJson.dump());
AutoDelete drvJsonFile(drvJsonPath, false);

auto hookEnv = getEnv();
static_assert(expectedJsonVersionDerivation == 4);
hookEnv["NIX_DERIVATION_V4"] = drvJsonPath;

auto [hookStatus, lines] = runProgram(
RunOptions{
.program = settings.preBuildHook,
.lookupPath = false,
.args = getPreBuildHookArgs(),
.environment = std::move(hookEnv),
});
if (!statusOk(hookStatus))
throw ExecError(hookStatus, "pre-build hook '%1%' %2%", settings.preBuildHook, statusToString(hookStatus));

auto state = stBegin;
auto lines = runProgram(settings.preBuildHook, false, getPreBuildHookArgs());
auto lastPos = std::string::size_type{0};
for (auto nlPos = lines.find('\n'); nlPos != std::string::npos; nlPos = lines.find('\n', lastPos)) {
auto line = lines.substr(lastPos, nlPos - lastPos);
Expand Down
21 changes: 21 additions & 0 deletions tests/functional/linux-sandbox.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,24 @@ nix-sandbox-build symlink-derivation.nix -A test_sandbox_paths \
expectStderr 1 nix-sandbox-build --option extra-sandbox-paths '/does-not-exist' \
-E 'with import '"${config_nix}"'; mkDerivation { name = "trivial"; buildCommand = "echo > $out"; }' |
grepQuiet "path '/does-not-exist' is configured as part of the \`sandbox-paths\` option, but is inaccessible"

# Test pre-build-hook.
DEST="$TEST_ROOT/hook-output"
HOOK="$TEST_ROOT/pre-build-hook"

echo foo > "$TEST_ROOT"/fnord

cat > "$HOOK" <<EOF
#! $SHELL -e
jq -r .env.name < "\$NIX_DERIVATION_V4" > "$DEST"
echo "hello from hook!" >&2
echo "extra-sandbox-paths"
echo "/foo/bar=$TEST_ROOT/fnord"
EOF
chmod +x "$HOOK"

outPath=$(nix-build --no-out-link --sandbox-paths /nix/store --pre-build-hook "$HOOK" symlink-derivation.nix -A test_sandbox_paths_2)

[[ $(cat "$TEST_ROOT/store0/nix/store/$(basename "$outPath")/xyzzy") = foo ]]

[[ "$(cat "$DEST")" == "test-sandbox-paths-2" ]]
8 changes: 8 additions & 0 deletions tests/functional/symlink-derivation.nix
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,12 @@ in
touch $out
'';
};

test_sandbox_paths_2 = mkDerivation {
name = "test-sandbox-paths-2";
buildCommand = ''
mkdir $out
cat /foo/bar > $out/xyzzy
'';
};
}
Loading