Skip to content
Open
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
23 changes: 1 addition & 22 deletions src/libexpr/primops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1774,28 +1774,7 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
drv.outputs.insert_or_assign(i, DerivationOutput::Deferred{});
}

auto hashModulo = hashDerivationModulo(*state.store, Derivation(drv), true);
switch (hashModulo.kind) {
case DrvHash::Kind::Regular:
for (auto & i : outputs) {
auto h = get(hashModulo.hashes, i);
if (!h)
state.error<AssertionError>("derivation produced no hash for output '%s'", i).atPos(v).debugThrow();
auto outPath = state.store->makeOutputPath(i, *h, drvName);
drv.env[i] = state.store->printStorePath(outPath);
drv.outputs.insert_or_assign(
i,
DerivationOutput::InputAddressed{
.path = std::move(outPath),
});
}
break;
;
case DrvHash::Kind::Deferred:
for (auto & i : outputs) {
drv.outputs.insert_or_assign(i, DerivationOutput::Deferred{});
}
}
drv.fillInOutputPaths(*state.store);
}

/* Write the resulting term into the Nix store directory. */
Expand Down
73 changes: 68 additions & 5 deletions src/libstore-c/nix_api_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include "nix/store/local-fs-store.hh"

#include "nix/store/globals.hh"
#include "nix/util/base-nix-32.hh"

#include <cstring>
#include <span>

extern "C" {

Expand Down Expand Up @@ -218,22 +222,71 @@ StorePath * nix_store_path_clone(const StorePath * p)
return new StorePath{p->path};
}

nix_derivation * nix_derivation_from_json(nix_c_context * context, Store * store, const char * json)
nix_err
nix_store_path_hash(nix_c_context * context, const StorePath * store_path, nix_store_path_hash_part * hash_part_out)
{
try {
auto hashPart = store_path->path.hashPart();
// Decode from Nix32 (base32) encoding to raw bytes
auto decoded = nix::BaseNix32::decode(hashPart);

assert(decoded.size() == 20);
std::memcpy(hash_part_out->bytes, decoded.data(), 20);
return NIX_OK;
}
NIXC_CATCH_ERRS
}

StorePath * nix_store_create_from_parts(
nix_c_context * context, const nix_store_path_hash_part * hash, const char * name, size_t name_len)
{
if (context)
context->last_err_code = NIX_OK;
try {
auto drv = static_cast<nix::Derivation>(nlohmann::json::parse(json));
// Encode the 20 raw bytes to Nix32 (base32) format
auto hashStr =
nix::BaseNix32::encode(std::span<const std::byte>(reinterpret_cast<const std::byte *>(hash->bytes), 20));

auto drvPath = nix::writeDerivation(*store->ptr, drv, nix::NoRepair, /* read only */ true);
// Construct the store path basename: <hash>-<name>
std::string baseName;
baseName += hashStr;
baseName += "-";
baseName += std::string_view{name, name_len};

drv.checkInvariants(*store->ptr, drvPath);
return new StorePath{nix::StorePath(std::move(baseName))};
}
NIXC_CATCH_ERRS_NULL
}

nix_derivation * nix_derivation_clone(const nix_derivation * d)
{
return new nix_derivation{d->drv};
}

return new nix_derivation{drv};
nix_derivation * nix_derivation_from_json(nix_c_context * context, Store * store, const char * json)
{
if (context)
context->last_err_code = NIX_OK;
try {
return new nix_derivation{nix::Derivation::parseJsonAndValidate(*store->ptr, nlohmann::json::parse(json))};
}
NIXC_CATCH_ERRS_NULL
}

nix_err nix_derivation_to_json(
nix_c_context * context, const nix_derivation * drv, nix_get_string_callback callback, void * userdata)
{
if (context)
context->last_err_code = NIX_OK;
try {
auto result = static_cast<nlohmann::json>(drv->drv).dump();
if (callback) {
callback(result.data(), result.size(), userdata);
}
}
NIXC_CATCH_ERRS
}

StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation)
{
if (context)
Expand All @@ -258,4 +311,14 @@ nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store
NIXC_CATCH_ERRS
}

nix_derivation * nix_store_drv_from_store_path(nix_c_context * context, Store * store, const StorePath * path)
{
if (context)
context->last_err_code = NIX_OK;
try {
return new nix_derivation{store->ptr->derivationFromPath(path->path)};
}
NIXC_CATCH_ERRS_NULL
}

} // extern "C"
18 changes: 17 additions & 1 deletion src/libstore-c/nix_api_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ nix_err
nix_store_get_storedir(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data);

/**
* @brief Parse a Nix store path into a StorePath
* @brief Parse a Nix store path that includes the store dir into a StorePath
*
* @note Don't forget to free this path using nix_store_path_free()!
* @param[out] context Optional, stores error information
Expand Down Expand Up @@ -188,6 +188,12 @@ nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_cal
/**
* @brief Create a `nix_derivation` from a JSON representation of that derivation.
*
* @note Unlike `nix_derivation_to_json`, this needs a `Store`. This is because
* over time we expect the internal representation of derivations in Nix to
* differ from accepted derivation formats. The store argument is here to help
* any logic needed to convert from JSON to the internal representation, in
* excess of just parsing.
*
* @param[out] context Optional, stores error information.
* @param[in] store nix store reference.
* @param[in] json JSON of the derivation as a string.
Expand Down Expand Up @@ -242,6 +248,16 @@ nix_err nix_store_get_fs_closure(
void * userdata,
void (*callback)(nix_c_context * context, void * userdata, const StorePath * store_path));

/**
* @brief Returns the derivation associated with the store path
*
* @param[out] context Optional, stores error information
* @param[in] store The nix store
* @param[in] path The nix store path
* @return A new derivation, or NULL on error
*/
nix_derivation * nix_store_drv_from_store_path(nix_c_context * context, Store * store, const StorePath * path);

// cffi end
#ifdef __cplusplus
}
Expand Down
19 changes: 19 additions & 0 deletions src/libstore-c/nix_api_store/derivation.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ extern "C" {
/** @brief Nix Derivation */
typedef struct nix_derivation nix_derivation;

/**
* @brief Copy a `nix_derivation`
*
* @param[in] d the derivation to copy
* @return a new `nix_derivation`
*/
nix_derivation * nix_derivation_clone(const nix_derivation * d);

/**
* @brief Deallocate a `nix_derivation`
*
Expand All @@ -28,6 +36,17 @@ typedef struct nix_derivation nix_derivation;
*/
void nix_derivation_free(nix_derivation * drv);

/**
* @brief Gets the derivation as a JSON string
*
* @param[out] context Optional, stores error information
* @param[in] drv The derivation
* @param[in] callback Called with the JSON string
* @param[in] userdata Arbitrary data passed to the callback
*/
nix_err nix_derivation_to_json(
nix_c_context * context, const nix_derivation * drv, nix_get_string_callback callback, void * userdata);

// cffi end
#ifdef __cplusplus
}
Expand Down
42 changes: 42 additions & 0 deletions src/libstore-c/nix_api_store/store_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
* @brief Store path operations
*/

#include <stddef.h>
#include <stdint.h>

#include "nix_api_util.h"

#ifdef __cplusplus
Expand Down Expand Up @@ -44,6 +47,45 @@ void nix_store_path_free(StorePath * p);
*/
void nix_store_path_name(const StorePath * store_path, nix_get_string_callback callback, void * user_data);

/**
* @brief A store path hash
*
* Once decoded from "nix32" encoding, a store path hash is 20 raw bytes.
*/
typedef struct nix_store_path_hash_part
{
uint8_t bytes[20];
} nix_store_path_hash_part;

/**
* @brief Get the path hash (e.g. "<hash>" in /nix/store/<hash>-<name>)
*
* The hash is returned as raw bytes, decoded from "nix32" encoding.
*
* @param[out] context Optional, stores error information
* @param[in] store_path the path to get the hash from
* @param[out] hash_part_out the decoded hash as 20 raw bytes
* @return NIX_OK on success, error code on failure
*/
nix_err
nix_store_path_hash(nix_c_context * context, const StorePath * store_path, nix_store_path_hash_part * hash_part_out);

/**
* @brief Create a StorePath from its constituent parts (hash and name)
*
* This function constructs a store path from a hash and name, without needing
* a Store reference or the store directory prefix.
*
* @note Don't forget to free this path using nix_store_path_free()!
* @param[out] context Optional, stores error information
* @param[in] hash The store path hash (20 raw bytes)
* @param[in] name The store path name (the part after the hash)
* @param[in] name_len Length of the name string
* @return owned store path, NULL on error
*/
StorePath * nix_store_create_from_parts(
nix_c_context * context, const nix_store_path_hash_part * hash, const char name[/*name_len*/], size_t name_len);

// cffi end
#ifdef __cplusplus
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"args": [],
"builder": "/bin/sh",
"env": {
"__doc": "InputAddressed throws when should be deferred",
"out": ""
},
"inputs": {
"drvs": {
"lg4c4b8r9hlczwprl6kgnzfd9mc1xmkk-dependency.drv": {
"dynamicOutputs": {},
"outputs": [
"out"
]
}
},
"srcs": []
},
"name": "depends-on-drv",
"outputs": {
"out": {
"path": "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-wrong-name"
}
},
"system": "x86_64-linux",
"version": 4
}
18 changes: 18 additions & 0 deletions src/libstore-tests/data/derivation/invariants/bad-env-var.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"args": [],
"builder": "/bin/sh",
"env": {
"__doc": "Wrong env var value throws error",
"out": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-wrong-name"
},
"inputs": {
"drvs": {},
"srcs": []
},
"name": "bad-env-var",
"outputs": {
"out": {}
},
"system": "x86_64-linux",
"version": 4
}
20 changes: 20 additions & 0 deletions src/libstore-tests/data/derivation/invariants/bad-path.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"args": [],
"builder": "/bin/sh",
"env": {
"__doc": "Wrong InputAddressed path throws error",
"out": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-wrong-name"
},
"inputs": {
"drvs": {},
"srcs": []
},
"name": "bad-path",
"outputs": {
"out": {
"path": "c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-wrong-name"
}
},
"system": "x86_64-linux",
"version": 4
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"args": [],
"builder": "/bin/sh",
"env": {
"__doc": "Deferred stays deferred with CA dependencies",
"out": ""
},
"inputs": {
"drvs": {
"lg4c4b8r9hlczwprl6kgnzfd9mc1xmkk-dependency.drv": {
"dynamicOutputs": {},
"outputs": [
"out"
]
}
},
"srcs": []
},
"name": "depends-on-drv",
"outputs": {
"out": {}
},
"system": "x86_64-linux",
"version": 4
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"args": [],
"builder": "/bin/sh",
"env": {
"__doc": "Fill in deferred output with empty env var",
"out": "/nix/store/bilpz1nq8qi9r3bzsp72n34yjgqg43ws-filled-in-deferred-empty-env-var"
},
"inputs": {
"drvs": {},
"srcs": []
},
"name": "filled-in-deferred-empty-env-var",
"outputs": {
"out": {
"path": "bilpz1nq8qi9r3bzsp72n34yjgqg43ws-filled-in-deferred-empty-env-var"
}
},
"system": "x86_64-linux",
"version": 4
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"args": [],
"builder": "/bin/sh",
"env": {
"__doc": "Fill in deferred output with empty env var",
"out": ""
},
"inputs": {
"drvs": {},
"srcs": []
},
"name": "filled-in-deferred-empty-env-var",
"outputs": {
"out": {}
},
"system": "x86_64-linux",
"version": 4
}
Loading
Loading