1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-29 10:31:15 +02:00

C API: Add nix_store_real_path

This commit is contained in:
Robert Hensing 2024-12-12 18:51:11 +01:00 committed by Mic92
parent 472912f7ca
commit 2a98168942
3 changed files with 112 additions and 0 deletions

View file

@ -100,6 +100,18 @@ bool nix_store_is_valid_path(nix_c_context * context, Store * store, StorePath *
NIXC_CATCH_ERRS_RES(false); 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) StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const char * path)
{ {
if (context) if (context)

View file

@ -149,6 +149,26 @@ void nix_store_path_free(StorePath * p);
* @return true or false, error info in context * @return true or false, error info in context
*/ */
bool nix_store_is_valid_path(nix_c_context * context, Store * store, StorePath * path); 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_ensure(Store*, const char*);
// nix_err nix_store_build_paths(Store*); // nix_err nix_store_build_paths(Store*);
/** /**

View file

@ -119,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)); 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