mirror of
https://github.com/NixOS/nix
synced 2025-06-25 06:31:14 +02:00
Merge pull request #12044 from roberth/c-api-nix-store
C API: nix_store_open doc, add storedir, real_path
This commit is contained in:
commit
6a23803066
5 changed files with 192 additions and 7 deletions
|
@ -67,6 +67,17 @@ nix_err nix_store_get_uri(nix_c_context * context, Store * store, nix_get_string
|
|||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
nix_err
|
||||
nix_store_get_storedir(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data)
|
||||
{
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
return call_nix_get_string_callback(store->ptr->storeDir, callback, user_data);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
nix_err
|
||||
nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data)
|
||||
{
|
||||
|
@ -89,6 +100,18 @@ bool nix_store_is_valid_path(nix_c_context * context, Store * store, StorePath *
|
|||
NIXC_CATCH_ERRS_RES(false);
|
||||
}
|
||||
|
||||
nix_err nix_store_real_path(
|
||||
nix_c_context * context, Store * store, StorePath * path, nix_get_string_callback callback, void * user_data)
|
||||
{
|
||||
if (context)
|
||||
context->last_err_code = NIX_OK;
|
||||
try {
|
||||
auto res = store->ptr->toRealPath(path->path);
|
||||
return call_nix_get_string_callback(res, callback, user_data);
|
||||
}
|
||||
NIXC_CATCH_ERRS
|
||||
}
|
||||
|
||||
StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const char * path)
|
||||
{
|
||||
if (context)
|
||||
|
|
|
@ -48,12 +48,27 @@ nix_err nix_libstore_init_no_load_config(nix_c_context * context);
|
|||
* Store instances may share state and resources behind the scenes.
|
||||
*
|
||||
* @param[out] context Optional, stores error information
|
||||
* @param[in] uri URI of the Nix store, copied. See [*Store URL format* in the Nix Reference
|
||||
*
|
||||
* @param[in] uri @parblock
|
||||
* URI of the Nix store, copied.
|
||||
*
|
||||
* If `NULL`, the store from the settings will be used.
|
||||
* Note that `"auto"` holds a strange middle ground, reading part of the general environment, but not all of it. It
|
||||
* ignores `NIX_REMOTE` and the `store` option. For this reason, `NULL` is most likely the better choice.
|
||||
*
|
||||
* For supported store URLs, see [*Store URL format* in the Nix Reference
|
||||
* Manual](https://nixos.org/manual/nix/stable/store/types/#store-url-format).
|
||||
* @param[in] params optional, null-terminated array of key-value pairs, e.g. {{"endpoint",
|
||||
* "https://s3.local"}}. See [*Store Types* in the Nix Reference
|
||||
* Manual](https://nixos.org/manual/nix/stable/store/types).
|
||||
* @endparblock
|
||||
*
|
||||
* @param[in] params @parblock
|
||||
* optional, null-terminated array of key-value pairs, e.g. {{"endpoint",
|
||||
* "https://s3.local"}}.
|
||||
*
|
||||
* See [*Store Types* in the Nix Reference Manual](https://nixos.org/manual/nix/stable/store/types).
|
||||
* @endparblock
|
||||
*
|
||||
* @return a Store pointer, NULL in case of errors
|
||||
*
|
||||
* @see nix_store_free
|
||||
*/
|
||||
Store * nix_store_open(nix_c_context * context, const char * uri, const char *** params);
|
||||
|
@ -78,7 +93,18 @@ void nix_store_free(Store * store);
|
|||
*/
|
||||
nix_err nix_store_get_uri(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data);
|
||||
|
||||
// returns: owned StorePath*
|
||||
/**
|
||||
* @brief get the storeDir of a Nix store, typically `"/nix/store"`
|
||||
* @param[out] context Optional, stores error information
|
||||
* @param[in] store nix store reference
|
||||
* @param[in] callback Called with the URI.
|
||||
* @param[in] user_data optional, arbitrary data, passed to the callback when it's called.
|
||||
* @see nix_get_string_callback
|
||||
* @return error code, NIX_OK on success.
|
||||
*/
|
||||
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
|
||||
*
|
||||
|
@ -123,6 +149,26 @@ void nix_store_path_free(StorePath * p);
|
|||
* @return true or false, error info in context
|
||||
*/
|
||||
bool nix_store_is_valid_path(nix_c_context * context, Store * store, StorePath * path);
|
||||
|
||||
/**
|
||||
* @brief Get the physical location of a store path
|
||||
*
|
||||
* A store may reside at a different location than its `storeDir` suggests.
|
||||
* This situation is called a relocated store.
|
||||
* Relocated stores are used during NixOS installation, as well as in restricted computing environments that don't offer
|
||||
* a writable `/nix/store`.
|
||||
*
|
||||
* Not all types of stores support this operation.
|
||||
*
|
||||
* @param[in] context Optional, stores error information
|
||||
* @param[in] store nix store reference
|
||||
* @param[in] path the path to get the real path from
|
||||
* @param[in] callback called with the real path
|
||||
* @param[in] user_data arbitrary data, passed to the callback when it's called.
|
||||
*/
|
||||
nix_err nix_store_real_path(
|
||||
nix_c_context * context, Store * store, StorePath * path, nix_get_string_callback callback, void * user_data);
|
||||
|
||||
// nix_err nix_store_ensure(Store*, const char*);
|
||||
// nix_err nix_store_build_paths(Store*);
|
||||
/**
|
||||
|
|
|
@ -16,8 +16,10 @@ cxx = meson.get_compiler('cpp')
|
|||
|
||||
subdir('nix-meson-build-support/deps-lists')
|
||||
|
||||
nix_store = dependency('nix-store')
|
||||
|
||||
deps_private_maybe_subproject = [
|
||||
dependency('nix-store'),
|
||||
nix_store,
|
||||
dependency('nix-store-c'),
|
||||
dependency('nix-store-test-support'),
|
||||
]
|
||||
|
@ -90,6 +92,7 @@ this_exe = executable(
|
|||
include_directories : include_dirs,
|
||||
# TODO: -lrapidcheck, see ../libutil-support/build.meson
|
||||
link_args: linker_export_flags + ['-lrapidcheck'],
|
||||
cpp_args : [ '-DNIX_STORE_DIR="' + nix_store.get_variable('storedir') + '"' ],
|
||||
# get main from gtest
|
||||
install : true,
|
||||
)
|
||||
|
|
|
@ -24,6 +24,39 @@ TEST_F(nix_api_store_test, nix_store_get_uri)
|
|||
ASSERT_STREQ("local", str.c_str());
|
||||
}
|
||||
|
||||
TEST_F(nix_api_util_context, nix_store_get_storedir_default)
|
||||
{
|
||||
if (nix::getEnv("HOME").value_or("") == "/homeless-shelter") {
|
||||
// skipping test in sandbox because nix_store_open tries to create /nix/var/nix/profiles
|
||||
GTEST_SKIP();
|
||||
}
|
||||
nix_libstore_init(ctx);
|
||||
Store * store = nix_store_open(ctx, nullptr, nullptr);
|
||||
assert_ctx_ok();
|
||||
ASSERT_NE(store, nullptr);
|
||||
|
||||
std::string str;
|
||||
auto ret = nix_store_get_storedir(ctx, store, OBSERVE_STRING(str));
|
||||
assert_ctx_ok();
|
||||
ASSERT_EQ(NIX_OK, ret);
|
||||
|
||||
// These tests run with a unique storeDir, but not a relocated store
|
||||
ASSERT_STREQ(NIX_STORE_DIR, str.c_str());
|
||||
|
||||
nix_store_free(store);
|
||||
}
|
||||
|
||||
TEST_F(nix_api_store_test, nix_store_get_storedir)
|
||||
{
|
||||
std::string str;
|
||||
auto ret = nix_store_get_storedir(ctx, store, OBSERVE_STRING(str));
|
||||
assert_ctx_ok();
|
||||
ASSERT_EQ(NIX_OK, ret);
|
||||
|
||||
// These tests run with a unique storeDir, but not a relocated store
|
||||
ASSERT_STREQ(nixStoreDir.c_str(), str.c_str());
|
||||
}
|
||||
|
||||
TEST_F(nix_api_store_test, InvalidPathFails)
|
||||
{
|
||||
nix_store_parse_path(ctx, store, "invalid-path");
|
||||
|
@ -86,4 +119,84 @@ TEST_F(nix_api_store_test, nix_store_is_valid_path_not_in_store)
|
|||
ASSERT_EQ(false, nix_store_is_valid_path(ctx, store, path));
|
||||
}
|
||||
|
||||
TEST_F(nix_api_store_test, nix_store_real_path)
|
||||
{
|
||||
StorePath * path = nix_store_parse_path(ctx, store, (nixStoreDir + PATH_SUFFIX).c_str());
|
||||
std::string rp;
|
||||
auto ret = nix_store_real_path(ctx, store, path, OBSERVE_STRING(rp));
|
||||
assert_ctx_ok();
|
||||
ASSERT_EQ(NIX_OK, ret);
|
||||
// Assumption: we're not testing with a relocated store
|
||||
ASSERT_STREQ((nixStoreDir + PATH_SUFFIX).c_str(), rp.c_str());
|
||||
|
||||
nix_store_path_free(path);
|
||||
}
|
||||
|
||||
TEST_F(nix_api_util_context, nix_store_real_path_relocated)
|
||||
{
|
||||
if (nix::getEnv("HOME").value_or("") == "/homeless-shelter") {
|
||||
// Can't open default store from within sandbox
|
||||
GTEST_SKIP();
|
||||
}
|
||||
auto tmp = nix::createTempDir();
|
||||
std::string storeRoot = tmp + "/store";
|
||||
std::string stateDir = tmp + "/state";
|
||||
std::string logDir = tmp + "/log";
|
||||
const char * rootkv[] = {"root", storeRoot.c_str()};
|
||||
const char * statekv[] = {"state", stateDir.c_str()};
|
||||
const char * logkv[] = {"log", logDir.c_str()};
|
||||
// const char * rokv[] = {"read-only", "true"};
|
||||
const char ** kvs[] = {rootkv, statekv, logkv, NULL};
|
||||
|
||||
nix_libstore_init(ctx);
|
||||
assert_ctx_ok();
|
||||
|
||||
Store * store = nix_store_open(ctx, "local", kvs);
|
||||
assert_ctx_ok();
|
||||
ASSERT_NE(store, nullptr);
|
||||
|
||||
std::string nixStoreDir;
|
||||
auto ret = nix_store_get_storedir(ctx, store, OBSERVE_STRING(nixStoreDir));
|
||||
ASSERT_EQ(NIX_OK, ret);
|
||||
ASSERT_STREQ(NIX_STORE_DIR, nixStoreDir.c_str());
|
||||
|
||||
StorePath * path = nix_store_parse_path(ctx, store, (nixStoreDir + PATH_SUFFIX).c_str());
|
||||
assert_ctx_ok();
|
||||
ASSERT_NE(path, nullptr);
|
||||
|
||||
std::string rp;
|
||||
ret = nix_store_real_path(ctx, store, path, OBSERVE_STRING(rp));
|
||||
assert_ctx_ok();
|
||||
ASSERT_EQ(NIX_OK, ret);
|
||||
|
||||
// Assumption: we're not testing with a relocated store
|
||||
ASSERT_STREQ((storeRoot + NIX_STORE_DIR + PATH_SUFFIX).c_str(), rp.c_str());
|
||||
|
||||
nix_store_path_free(path);
|
||||
}
|
||||
|
||||
TEST_F(nix_api_util_context, nix_store_real_path_binary_cache)
|
||||
{
|
||||
if (nix::getEnv("HOME").value_or("") == "/homeless-shelter") {
|
||||
// TODO: override NIX_CACHE_HOME?
|
||||
// skipping test in sandbox because narinfo cache can't be written
|
||||
GTEST_SKIP();
|
||||
}
|
||||
|
||||
Store * store = nix_store_open(ctx, "https://cache.nixos.org", nullptr);
|
||||
assert_ctx_ok();
|
||||
ASSERT_NE(store, nullptr);
|
||||
|
||||
std::string path_raw = std::string(NIX_STORE_DIR) + PATH_SUFFIX;
|
||||
StorePath * path = nix_store_parse_path(ctx, store, path_raw.c_str());
|
||||
assert_ctx_ok();
|
||||
ASSERT_NE(path, nullptr);
|
||||
|
||||
std::string rp;
|
||||
auto ret = nix_store_real_path(ctx, store, path, OBSERVE_STRING(rp));
|
||||
assert_ctx_ok();
|
||||
ASSERT_EQ(NIX_OK, ret);
|
||||
ASSERT_STREQ(path_raw.c_str(), rp.c_str());
|
||||
}
|
||||
|
||||
} // namespace nixC
|
||||
|
|
|
@ -47,7 +47,7 @@ extern "C" {
|
|||
*/
|
||||
// Error codes
|
||||
/**
|
||||
* @brief Type for error codes in the NIX system
|
||||
* @brief Type for error codes in the Nix system
|
||||
*
|
||||
* This type can have one of several predefined constants:
|
||||
* - NIX_OK: No error occurred (0)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue