mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11:15 +02:00
C API: (breaking) remove nix-flake-c global init
This commit is contained in:
parent
3c4c0953e0
commit
6a192ec0cd
12 changed files with 124 additions and 69 deletions
20
doc/manual/rl-next/c-api-flake-init.md
Normal file
20
doc/manual/rl-next/c-api-flake-init.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
synopsis: C API `nix_flake_init_global` removed
|
||||
prs: 12759
|
||||
issues: 5638
|
||||
---
|
||||
|
||||
In order to improve the modularity of the code base, we are removing a use of global state, and therefore the `nix_flake_init_global` function.
|
||||
|
||||
Instead, use `nix_flake_settings_add_to_eval_state_builder`. For example:
|
||||
|
||||
```diff
|
||||
- nix_flake_init_global(ctx, settings);
|
||||
- HANDLE_ERROR(ctx);
|
||||
-
|
||||
nix_eval_state_builder * builder = nix_eval_state_builder_new(ctx, store);
|
||||
HANDLE_ERROR(ctx);
|
||||
|
||||
+ nix_flake_settings_add_to_eval_state_builder(ctx, settings, builder);
|
||||
+ HANDLE_ERROR(ctx);
|
||||
```
|
|
@ -1,6 +1,7 @@
|
|||
#include "nix_api_flake.h"
|
||||
#include "nix_api_flake_internal.hh"
|
||||
#include "nix_api_util_internal.h"
|
||||
#include "nix_api_expr_internal.h"
|
||||
|
||||
#include "flake/flake.hh"
|
||||
|
||||
|
@ -18,15 +19,11 @@ void nix_flake_settings_free(nix_flake_settings * settings)
|
|||
delete settings;
|
||||
}
|
||||
|
||||
nix_err nix_flake_init_global(nix_c_context * context, nix_flake_settings * settings)
|
||||
nix_err nix_flake_settings_add_to_eval_state_builder(
|
||||
nix_c_context * context, nix_flake_settings * settings, nix_eval_state_builder * builder)
|
||||
{
|
||||
static std::shared_ptr<nix::flake::Settings> registeredSettings;
|
||||
try {
|
||||
if (registeredSettings)
|
||||
throw nix::Error("nix_flake_init_global already initialized");
|
||||
|
||||
registeredSettings = settings->settings;
|
||||
nix::flake::initLib(*registeredSettings);
|
||||
settings->settings->configureEvalSettings(builder->settings);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
|
|
@ -35,9 +35,15 @@ nix_flake_settings * nix_flake_settings_new(nix_c_context * context);
|
|||
void nix_flake_settings_free(nix_flake_settings * settings);
|
||||
|
||||
/**
|
||||
* @brief Register Flakes support process-wide.
|
||||
* @brief Initialize a `nix_flake_settings` to contain `builtins.getFlake` and
|
||||
* potentially more.
|
||||
*
|
||||
* @param[out] context Optional, stores error information
|
||||
* @param[in] settings The settings to use for e.g. `builtins.getFlake`
|
||||
* @param[in] builder The builder to modify
|
||||
*/
|
||||
nix_err nix_flake_init_global(nix_c_context * context, nix_flake_settings * settings);
|
||||
nix_err nix_flake_settings_add_to_eval_state_builder(
|
||||
nix_c_context * context, nix_flake_settings * settings, nix_eval_state_builder * builder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
@ -25,13 +25,13 @@ TEST_F(nix_api_store_test, nix_api_init_global_getFlake_exists)
|
|||
assert_ctx_ok();
|
||||
ASSERT_NE(nullptr, settings);
|
||||
|
||||
nix_flake_init_global(ctx, settings);
|
||||
assert_ctx_ok();
|
||||
|
||||
nix_eval_state_builder * builder = nix_eval_state_builder_new(ctx, store);
|
||||
ASSERT_NE(nullptr, builder);
|
||||
assert_ctx_ok();
|
||||
|
||||
nix_flake_settings_add_to_eval_state_builder(ctx, settings, builder);
|
||||
assert_ctx_ok();
|
||||
|
||||
auto state = nix_eval_state_build(ctx, builder);
|
||||
assert_ctx_ok();
|
||||
ASSERT_NE(nullptr, state);
|
||||
|
|
59
src/libflake/flake/flake-primops.cc
Normal file
59
src/libflake/flake/flake-primops.cc
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "flake-primops.hh"
|
||||
#include "eval.hh"
|
||||
#include "flake.hh"
|
||||
#include "flakeref.hh"
|
||||
#include "settings.hh"
|
||||
|
||||
namespace nix::flake::primops {
|
||||
|
||||
PrimOp getFlake(const Settings & settings)
|
||||
{
|
||||
auto prim_getFlake = [&settings](EvalState & state, const PosIdx pos, Value ** args, Value & v) {
|
||||
std::string flakeRefS(
|
||||
state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
|
||||
auto flakeRef = nix::parseFlakeRef(state.fetchSettings, flakeRefS, {}, true);
|
||||
if (state.settings.pureEval && !flakeRef.input.isLocked())
|
||||
throw Error(
|
||||
"cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)",
|
||||
flakeRefS,
|
||||
state.positions[pos]);
|
||||
|
||||
callFlake(
|
||||
state,
|
||||
lockFlake(
|
||||
settings,
|
||||
state,
|
||||
flakeRef,
|
||||
LockFlags{
|
||||
.updateLockFile = false,
|
||||
.writeLockFile = false,
|
||||
.useRegistries = !state.settings.pureEval && settings.useRegistries,
|
||||
.allowUnlocked = !state.settings.pureEval,
|
||||
}),
|
||||
v);
|
||||
};
|
||||
|
||||
return PrimOp{
|
||||
.name = "__getFlake",
|
||||
.args = {"args"},
|
||||
.doc = R"(
|
||||
Fetch a flake from a flake reference, and return its output attributes and some metadata. For example:
|
||||
|
||||
```nix
|
||||
(builtins.getFlake "nix/55bc52401966fbffa525c574c14f67b00bc4fb3a").packages.x86_64-linux.nix
|
||||
```
|
||||
|
||||
Unless impure evaluation is allowed (`--impure`), the flake reference
|
||||
must be "locked", e.g. contain a Git revision or content hash. An
|
||||
example of an unlocked usage is:
|
||||
|
||||
```nix
|
||||
(builtins.getFlake "github:edolstra/dwarffs").rev
|
||||
```
|
||||
)",
|
||||
.fun = prim_getFlake,
|
||||
.experimentalFeature = Xp::Flakes,
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace nix::flake::primops
|
13
src/libflake/flake/flake-primops.hh
Normal file
13
src/libflake/flake/flake-primops.hh
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "eval.hh"
|
||||
#include "flake/settings.hh"
|
||||
|
||||
namespace nix::flake::primops {
|
||||
|
||||
/**
|
||||
* Returns a `builtins.getFlake` primop with the given nix::flake::Settings.
|
||||
*/
|
||||
nix::PrimOp getFlake(const Settings & settings);
|
||||
|
||||
} // namespace nix::flake
|
|
@ -973,49 +973,6 @@ void callFlake(EvalState & state,
|
|||
state.callFunction(*vCallFlake, args, vRes, noPos);
|
||||
}
|
||||
|
||||
void initLib(const Settings & settings)
|
||||
{
|
||||
auto prim_getFlake = [&settings](EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||
{
|
||||
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
|
||||
auto flakeRef = parseFlakeRef(state.fetchSettings, flakeRefS, {}, true);
|
||||
if (state.settings.pureEval && !flakeRef.input.isLocked())
|
||||
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.positions[pos]);
|
||||
|
||||
callFlake(state,
|
||||
lockFlake(settings, state, flakeRef,
|
||||
LockFlags {
|
||||
.updateLockFile = false,
|
||||
.writeLockFile = false,
|
||||
.useRegistries = !state.settings.pureEval && settings.useRegistries,
|
||||
.allowUnlocked = !state.settings.pureEval,
|
||||
}),
|
||||
v);
|
||||
};
|
||||
|
||||
RegisterPrimOp::primOps->push_back({
|
||||
.name = "__getFlake",
|
||||
.args = {"args"},
|
||||
.doc = R"(
|
||||
Fetch a flake from a flake reference, and return its output attributes and some metadata. For example:
|
||||
|
||||
```nix
|
||||
(builtins.getFlake "nix/55bc52401966fbffa525c574c14f67b00bc4fb3a").packages.x86_64-linux.nix
|
||||
```
|
||||
|
||||
Unless impure evaluation is allowed (`--impure`), the flake reference
|
||||
must be "locked", e.g. contain a Git revision or content hash. An
|
||||
example of an unlocked usage is:
|
||||
|
||||
```nix
|
||||
(builtins.getFlake "github:edolstra/dwarffs").rev
|
||||
```
|
||||
)",
|
||||
.fun = prim_getFlake,
|
||||
.experimentalFeature = Xp::Flakes,
|
||||
});
|
||||
}
|
||||
|
||||
static void prim_parseFlakeRef(
|
||||
EvalState & state,
|
||||
const PosIdx pos,
|
||||
|
|
|
@ -14,14 +14,6 @@ namespace flake {
|
|||
|
||||
struct Settings;
|
||||
|
||||
/**
|
||||
* Initialize `libnixflake`
|
||||
*
|
||||
* So far, this registers the `builtins.getFlake` primop, which depends
|
||||
* on the choice of `flake:Settings`.
|
||||
*/
|
||||
void initLib(const Settings & settings);
|
||||
|
||||
struct FlakeInput;
|
||||
|
||||
typedef std::map<FlakeId, FlakeInput> FlakeInputs;
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
#include "flake/settings.hh"
|
||||
#include "flake/flake-primops.hh"
|
||||
|
||||
namespace nix::flake {
|
||||
|
||||
Settings::Settings() {}
|
||||
|
||||
void Settings::configureEvalSettings(nix::EvalSettings & evalSettings)
|
||||
{
|
||||
evalSettings.addPrimOp(primops::getFlake(*this));
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "types.hh"
|
||||
#include "config.hh"
|
||||
#include "util.hh"
|
||||
|
||||
#include <map>
|
||||
#include <limits>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace nix {
|
||||
// Forward declarations
|
||||
struct EvalSettings;
|
||||
|
||||
} // namespace nix
|
||||
|
||||
namespace nix::flake {
|
||||
|
||||
struct Settings : public Config
|
||||
{
|
||||
Settings();
|
||||
|
||||
void configureEvalSettings(nix::EvalSettings & evalSettings);
|
||||
|
||||
Setting<bool> useRegistries{
|
||||
this,
|
||||
true,
|
||||
|
|
|
@ -44,6 +44,7 @@ sources = files(
|
|||
'flake/flake.cc',
|
||||
'flake/flakeref.cc',
|
||||
'flake/lockfile.cc',
|
||||
'flake/flake-primops.cc',
|
||||
'flake/settings.cc',
|
||||
'flake/url-name.cc',
|
||||
)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "network-proxy.hh"
|
||||
#include "eval-cache.hh"
|
||||
#include "flake/flake.hh"
|
||||
#include "flake/settings.hh"
|
||||
#include "self-exe.hh"
|
||||
#include "json-utils.hh"
|
||||
#include "crash-handler.hh"
|
||||
|
@ -368,7 +369,7 @@ void mainWrapped(int argc, char * * argv)
|
|||
|
||||
initNix();
|
||||
initGC();
|
||||
flake::initLib(flakeSettings);
|
||||
flakeSettings.configureEvalSettings(evalSettings);
|
||||
|
||||
/* Set the build hook location
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue