mirror of
https://github.com/NixOS/nix
synced 2025-06-27 21:01:16 +02:00
libexpr-c: Add nix_eval_state_builder
This commit is contained in:
parent
838d3c1ad0
commit
82a23d9b6b
4 changed files with 183 additions and 9 deletions
|
@ -6,6 +6,7 @@
|
||||||
#include "eval-gc.hh"
|
#include "eval-gc.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
|
#include "ref.hh"
|
||||||
|
|
||||||
#include "nix_api_expr.h"
|
#include "nix_api_expr.h"
|
||||||
#include "nix_api_expr_internal.h"
|
#include "nix_api_expr_internal.h"
|
||||||
|
@ -93,7 +94,46 @@ nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_val
|
||||||
NIXC_CATCH_ERRS
|
NIXC_CATCH_ERRS
|
||||||
}
|
}
|
||||||
|
|
||||||
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store)
|
nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Store * store)
|
||||||
|
{
|
||||||
|
if (context)
|
||||||
|
context->last_err_code = NIX_OK;
|
||||||
|
try {
|
||||||
|
// Allocate ahead of time, because .settings needs self-reference
|
||||||
|
void * p = ::operator new(
|
||||||
|
sizeof(nix_eval_state_builder),
|
||||||
|
static_cast<std::align_val_t>(alignof(nix_eval_state_builder)));
|
||||||
|
auto * p2 = static_cast<nix_eval_state_builder *>(p);
|
||||||
|
new (p) nix_eval_state_builder{
|
||||||
|
.store = nix::ref<nix::Store>(store->ptr),
|
||||||
|
.settings = nix::EvalSettings{/* &bool */ p2->readOnlyMode},
|
||||||
|
.fetchSettings = nix::fetchers::Settings{},
|
||||||
|
.readOnlyMode = true,
|
||||||
|
};
|
||||||
|
return p2;
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS_NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
void nix_eval_state_builder_free(nix_eval_state_builder * builder)
|
||||||
|
{
|
||||||
|
delete builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_builder * builder)
|
||||||
|
{
|
||||||
|
if (context)
|
||||||
|
context->last_err_code = NIX_OK;
|
||||||
|
try {
|
||||||
|
// TODO: load in one go?
|
||||||
|
builder->settings.readOnlyMode = nix::settings.readOnlyMode;
|
||||||
|
loadConfFile(builder->settings);
|
||||||
|
loadConfFile(builder->fetchSettings);
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS
|
||||||
|
}
|
||||||
|
|
||||||
|
nix_err nix_eval_state_builder_set_lookup_path(nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath_c)
|
||||||
{
|
{
|
||||||
if (context)
|
if (context)
|
||||||
context->last_err_code = NIX_OK;
|
context->last_err_code = NIX_OK;
|
||||||
|
@ -102,28 +142,51 @@ EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c
|
||||||
if (lookupPath_c != nullptr)
|
if (lookupPath_c != nullptr)
|
||||||
for (size_t i = 0; lookupPath_c[i] != nullptr; i++)
|
for (size_t i = 0; lookupPath_c[i] != nullptr; i++)
|
||||||
lookupPath.push_back(lookupPath_c[i]);
|
lookupPath.push_back(lookupPath_c[i]);
|
||||||
|
builder->lookupPath = nix::LookupPath::parse(lookupPath);
|
||||||
|
}
|
||||||
|
NIXC_CATCH_ERRS
|
||||||
|
}
|
||||||
|
|
||||||
|
EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder * builder)
|
||||||
|
{
|
||||||
|
if (context)
|
||||||
|
context->last_err_code = NIX_OK;
|
||||||
|
try {
|
||||||
|
// Allocate ahead of time, because .state init needs self-reference
|
||||||
void * p = ::operator new(
|
void * p = ::operator new(
|
||||||
sizeof(EvalState),
|
sizeof(EvalState),
|
||||||
static_cast<std::align_val_t>(alignof(EvalState)));
|
static_cast<std::align_val_t>(alignof(EvalState)));
|
||||||
auto * p2 = static_cast<EvalState *>(p);
|
auto * p2 = static_cast<EvalState *>(p);
|
||||||
new (p) EvalState {
|
new (p) EvalState {
|
||||||
.fetchSettings = nix::fetchers::Settings{},
|
.fetchSettings = std::move(builder->fetchSettings),
|
||||||
.settings = nix::EvalSettings{
|
.settings = std::move(builder->settings),
|
||||||
nix::settings.readOnlyMode,
|
|
||||||
},
|
|
||||||
.state = nix::EvalState(
|
.state = nix::EvalState(
|
||||||
nix::LookupPath::parse(lookupPath),
|
builder->lookupPath,
|
||||||
store->ptr,
|
builder->store,
|
||||||
p2->fetchSettings,
|
p2->fetchSettings,
|
||||||
p2->settings),
|
p2->settings),
|
||||||
};
|
};
|
||||||
loadConfFile(p2->settings);
|
|
||||||
return p2;
|
return p2;
|
||||||
}
|
}
|
||||||
NIXC_CATCH_ERRS_NULL
|
NIXC_CATCH_ERRS_NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath_c, Store * store)
|
||||||
|
{
|
||||||
|
auto builder = nix_eval_state_builder_new(context, store);
|
||||||
|
if (builder == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (nix_eval_state_builder_load(context, builder) != NIX_OK)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (nix_eval_state_builder_set_lookup_path(context, builder, lookupPath_c)
|
||||||
|
!= NIX_OK)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return nix_eval_state_build(context, builder);
|
||||||
|
}
|
||||||
|
|
||||||
void nix_state_free(EvalState * state)
|
void nix_state_free(EvalState * state)
|
||||||
{
|
{
|
||||||
delete state;
|
delete state;
|
||||||
|
|
|
@ -30,6 +30,11 @@ extern "C" {
|
||||||
// cffi start
|
// cffi start
|
||||||
|
|
||||||
// Type definitions
|
// Type definitions
|
||||||
|
/**
|
||||||
|
* @brief Builder for EvalState
|
||||||
|
*/
|
||||||
|
typedef struct nix_eval_state_builder nix_eval_state_builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Represents a state of the Nix language evaluator.
|
* @brief Represents a state of the Nix language evaluator.
|
||||||
*
|
*
|
||||||
|
@ -174,12 +179,70 @@ nix_err nix_value_force(nix_c_context * context, EvalState * state, nix_value *
|
||||||
nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value);
|
nix_err nix_value_force_deep(nix_c_context * context, EvalState * state, nix_value * value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new Nix language evaluator state.
|
* @brief Create a new nix_eval_state_builder
|
||||||
|
*
|
||||||
|
* The settings are initialized to their default value.
|
||||||
|
* Values can be sourced elsewhere with nix_eval_state_builder_load.
|
||||||
|
*
|
||||||
|
* @param[out] context Optional, stores error information
|
||||||
|
* @param[in] store The Nix store to use.
|
||||||
|
* @return A new nix_eval_state_builder or NULL on failure.
|
||||||
|
*/
|
||||||
|
nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Store * store);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read settings from the ambient environment
|
||||||
|
*
|
||||||
|
* Settings are sourced from environment variables and configuration files,
|
||||||
|
* as documented in the Nix manual.
|
||||||
|
*
|
||||||
|
* @param[out] context Optional, stores error information
|
||||||
|
* @param[out] builder The builder to modify.
|
||||||
|
* @return NIX_OK if successful, an error code otherwise.
|
||||||
|
*/
|
||||||
|
nix_err nix_eval_state_builder_load(nix_c_context * context, nix_eval_state_builder * builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the lookup path for `<...>` expressions
|
||||||
|
*
|
||||||
|
* @param[in] context Optional, stores error information
|
||||||
|
* @param[in] builder The builder to modify.
|
||||||
|
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
|
||||||
|
*/
|
||||||
|
nix_err nix_eval_state_builder_set_lookup_path(
|
||||||
|
nix_c_context * context, nix_eval_state_builder * builder, const char ** lookupPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new Nix language evaluator state
|
||||||
|
*
|
||||||
|
* Remember to nix_eval_state_builder_free after building the state.
|
||||||
|
*
|
||||||
|
* @param[out] context Optional, stores error information
|
||||||
|
* @param[in] builder The builder to use and free
|
||||||
|
* @return A new Nix state or NULL on failure.
|
||||||
|
* @see nix_eval_state_builder_new, nix_eval_state_builder_free
|
||||||
|
*/
|
||||||
|
EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder * builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a nix_eval_state_builder
|
||||||
|
*
|
||||||
|
* Does not fail.
|
||||||
|
*
|
||||||
|
* @param[in] builder The builder to free.
|
||||||
|
*/
|
||||||
|
void nix_eval_state_builder_free(nix_eval_state_builder * builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new Nix language evaluator state
|
||||||
|
*
|
||||||
|
* For more control, use nix_eval_state_builder
|
||||||
*
|
*
|
||||||
* @param[out] context Optional, stores error information
|
* @param[out] context Optional, stores error information
|
||||||
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
|
* @param[in] lookupPath Null-terminated array of strings corresponding to entries in NIX_PATH.
|
||||||
* @param[in] store The Nix store to use.
|
* @param[in] store The Nix store to use.
|
||||||
* @return A new Nix state or NULL on failure.
|
* @return A new Nix state or NULL on failure.
|
||||||
|
* @see nix_state_builder_new
|
||||||
*/
|
*/
|
||||||
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath, Store * store);
|
EvalState * nix_state_create(nix_c_context * context, const char ** lookupPath, Store * store);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,17 @@
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
#include "attr-set.hh"
|
#include "attr-set.hh"
|
||||||
#include "nix_api_value.h"
|
#include "nix_api_value.h"
|
||||||
|
#include "search-path.hh"
|
||||||
|
|
||||||
|
struct nix_eval_state_builder
|
||||||
|
{
|
||||||
|
nix::ref<nix::Store> store;
|
||||||
|
nix::EvalSettings settings;
|
||||||
|
nix::fetchers::Settings fetchSettings;
|
||||||
|
nix::LookupPath lookupPath;
|
||||||
|
// TODO: make an EvalSettings setting own this instead?
|
||||||
|
bool readOnlyMode;
|
||||||
|
};
|
||||||
|
|
||||||
struct EvalState
|
struct EvalState
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,12 +7,49 @@
|
||||||
|
|
||||||
#include "tests/nix_api_expr.hh"
|
#include "tests/nix_api_expr.hh"
|
||||||
#include "tests/string_callback.hh"
|
#include "tests/string_callback.hh"
|
||||||
|
#include "file-system.hh"
|
||||||
|
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
namespace nixC {
|
namespace nixC {
|
||||||
|
|
||||||
|
TEST_F(nix_api_store_test, nix_eval_state_lookup_path)
|
||||||
|
{
|
||||||
|
auto tmpDir = nix::createTempDir();
|
||||||
|
auto delTmpDir = std::make_unique<nix::AutoDelete>(tmpDir, true);
|
||||||
|
auto nixpkgs = tmpDir + "/pkgs";
|
||||||
|
auto nixos = tmpDir + "/cfg";
|
||||||
|
std::filesystem::create_directories(nixpkgs);
|
||||||
|
std::filesystem::create_directories(nixos);
|
||||||
|
|
||||||
|
std::string nixpkgsEntry = "nixpkgs=" + nixpkgs;
|
||||||
|
std::string nixosEntry = "nixos-config=" + nixos;
|
||||||
|
const char * lookupPath[] = {nixpkgsEntry.c_str(), nixosEntry.c_str(), nullptr};
|
||||||
|
|
||||||
|
auto builder = nix_eval_state_builder_new(ctx, store);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
ASSERT_EQ(NIX_OK, nix_eval_state_builder_set_lookup_path(ctx, builder, lookupPath));
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
auto state = nix_eval_state_build(ctx, builder);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
nix_eval_state_builder_free(builder);
|
||||||
|
|
||||||
|
Value * value = nix_alloc_value(ctx, state);
|
||||||
|
nix_expr_eval_from_string(ctx, state, "builtins.seq <nixos-config> <nixpkgs>", ".", value);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
ASSERT_EQ(nix_get_type(ctx, value), NIX_TYPE_PATH);
|
||||||
|
assert_ctx_ok();
|
||||||
|
|
||||||
|
auto pathStr = nix_get_path_string(ctx, value);
|
||||||
|
assert_ctx_ok();
|
||||||
|
ASSERT_EQ(0, strcmp(pathStr, nixpkgs.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(nix_api_expr_test, nix_expr_eval_from_string)
|
TEST_F(nix_api_expr_test, nix_expr_eval_from_string)
|
||||||
{
|
{
|
||||||
nix_expr_eval_from_string(nullptr, state, "builtins.nixVersion", ".", value);
|
nix_expr_eval_from_string(nullptr, state, "builtins.nixVersion", ".", value);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue