Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge queue: embarking master (77e391b) and #12044 together #12057

Closed
wants to merge 5 commits into from
Closed
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: 23 additions & 0 deletions src/libstore-c/nix_api_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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)
Expand Down
56 changes: 51 additions & 5 deletions src/libstore-c/nix_api_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
*
Expand Down Expand Up @@ -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*);
/**
Expand Down
5 changes: 4 additions & 1 deletion src/libstore-tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
]
Expand Down Expand Up @@ -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,
)
Expand Down
113 changes: 113 additions & 0 deletions src/libstore-tests/nix_api_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/libutil-c/nix_api_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading