Skip to content
Draft
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
156 changes: 151 additions & 5 deletions src/libstore-c/nix_api_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "nix/store/store-api.hh"
#include "nix/store/store-open.hh"
#include "nix/store/build-result.hh"
#include "nix/store/build/derivation-builder.hh"
#include "nix/store/build/derivation-env-desugar.hh"

#include "nix/store/globals.hh"

Expand Down Expand Up @@ -126,6 +128,28 @@ StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const c
NIXC_CATCH_ERRS_NULL
}

StorePath * nix_store_parse_path2(nix_c_context * context, StoreDir store_dir, const char * path)
{
if (context)
context->last_err_code = NIX_OK;
try {
nix::Path sdInner = store_dir.store_directory;
nix::StoreDirConfig sd{sdInner};
nix::StorePath s = sd.parseStorePath(path);
return new StorePath{std::move(s)};
}
NIXC_CATCH_ERRS_NULL
}

void nix_print_store_path(
StoreDir store_dir, const StorePath * path, nix_get_string_callback callback, void * user_data)
{
nix::Path sdInner = store_dir.store_directory;
nix::StoreDirConfig sd{sdInner};
std::string s = sd.printStorePath(path->path);
callback(s.c_str(), s.size(), user_data);
}

nix_err nix_store_realise(
nix_c_context * context,
Store * store,
Expand Down Expand Up @@ -176,16 +200,18 @@ StorePath * nix_store_path_clone(const StorePath * p)
return new StorePath{p->path};
}

nix_derivation * nix_derivation_from_json(nix_c_context * context, Store * store, const char * json)
nix_derivation * nix_derivation_from_json(nix_c_context * context, StoreDir store_dir, const char * json)
{
if (context)
context->last_err_code = NIX_OK;
try {
auto drv = nix::Derivation::fromJSON(*store->ptr, nlohmann::json::parse(json));

auto drvPath = nix::writeDerivation(*store->ptr, drv, nix::NoRepair, /* read only */ true);
nix::Path sdInner = store_dir.store_directory;
nix::StoreDirConfig sd{sdInner};
auto drv = nix::Derivation::fromJSON(sd, nlohmann::json::parse(json));

drv.checkInvariants(*store->ptr, drvPath);
// auto drvPath = nix::writeDerivation(*store->ptr, drv, nix::NoRepair, /* read only */ true);
//
// drv.checkInvariants(*store->ptr, drvPath);

return new nix_derivation{drv};
}
Expand Down Expand Up @@ -216,4 +242,124 @@ nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store
NIXC_CATCH_ERRS
}

struct nix_derivation_builder
{
nix::BuildResult buildResult;
nix::DerivationOptions drvOptions;
const nix::StorePathSet inputPaths;
std::map<std::string, nix::InitialOutput> initialOutputs;
nix::AutoCloseFD builderOut;
std::unique_ptr<nix::DerivationBuilder> builder;
};

nix_derivation_builder * nix_make_derivation_builder(
nix_c_context * context,
StoreDir storeDir,
const char * buildDir,
const nix_derivation * drv,
const StorePath * drvPath,
const StorePath * inputPaths[])
{
if (context)
context->last_err_code = NIX_OK;
try {
struct CBuildingStore : nix::BuildingStore
{
nix::Path storeDir;
nix::Path buildDir;

CBuildingStore(StoreDir storeDir_, const char * buildDir_)
: nix::BuildingStore{this->storeDir}
, storeDir{storeDir_.store_directory}
, buildDir{buildDir_}
{
}

virtual nix::Path getRealStoreDir() const override
{
return storeDir;
}

virtual nix::Path getBuildDir() const override
{
return buildDir;
}

std::thread startDaemon(
nix::Descriptor daemonListeningSocket,
nix::RestrictionContext & ctx,
std::vector<std::thread> & daemonWorkerThreads) override
{
throw nix::Unsupported("Recursive Nix is not yet supported from C builder interface");
}
};

void * p = ::operator new(sizeof(nix_derivation_builder));
auto & ref = *static_cast<nix_derivation_builder *>(p);
return new (p) nix_derivation_builder{
.builder = nix::makeDerivationBuilder(
std::make_unique<CBuildingStore>(storeDir, buildDir),
std::make_unique<nix::DerivationBuilderCallbacks>(),
nix::DerivationBuilderParams{
.drvPath{drvPath->path},
.buildResult = ref.buildResult,
.drv = drv->drv,
.drvOptions = ref.drvOptions,
.inputPaths = ref.inputPaths,
.initialOutputs = ref.initialOutputs,
.buildMode = nix::bmNormal,
// TODO
.defaultPathsInChroot{nix::settings.sandboxPaths.get()},
// TODO
.desugaredEnv{[&] {
nix::DesugaredEnv res;
for (auto & [n, v] : drv->drv.env) {
res.variables.insert_or_assign(n, nix::DesugaredEnv::EnvEntry{.value = v});
}
return res;
}()},
}),
};
}
NIXC_CATCH_ERRS_NULL
}

nix_err nix_derivation_builder_start(nix_c_context * context, nix_derivation_builder * builder)
{
try {
if (auto optD = builder->builder->startBuild())
builder->builderOut = *std::move(optD);
else
throw nix::Error("Could not get build user");
}
NIXC_CATCH_ERRS
}

nix_err nix_derivation_builder_finish(nix_c_context * context, nix_derivation_builder * builder)
{
try {
nix::StringSink sink;
try {
nix::drainFD(builder->builderOut.get(), sink);
} catch (nix::SysError &) {
if (errno == EIO)
builder->builderOut.release();
else
throw;
}

std::cout << sink.s;

auto [status, diskFull] = builder->builder->unprepareBuild();

nix::warn("RESULT: %s", nix::statusToString(status));
}
NIXC_CATCH_ERRS
}

void nix_derivation_builder_free(nix_derivation_builder * builder)
{
delete builder;
}

} // extern "C"
29 changes: 28 additions & 1 deletion src/libstore-c/nix_api_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ typedef struct StorePath StorePath;
/** @brief Nix Derivation */
typedef struct nix_derivation nix_derivation;

typedef struct StoreDir
{
const char * store_directory;
} StoreDir;

/**
* @brief Initializes the Nix store library
*
Expand Down Expand Up @@ -118,6 +123,11 @@ nix_store_get_storedir(nix_c_context * context, Store * store, nix_get_string_ca
*/
StorePath * nix_store_parse_path(nix_c_context * context, Store * store, const char * path);

StorePath * nix_store_parse_path2(nix_c_context * context, StoreDir store_dir, const char * path);

void nix_print_store_path(
StoreDir store_dir, const StorePath * path, nix_get_string_callback callback, void * user_data);

/**
* @brief Get the path name (e.g. "name" in /nix/store/...-name)
*
Expand Down Expand Up @@ -216,7 +226,7 @@ nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_cal
* @param[in] store nix store reference.
* @param[in] json JSON of the derivation as a string.
*/
nix_derivation * nix_derivation_from_json(nix_c_context * context, Store * store, const char * json);
nix_derivation * nix_derivation_from_json(nix_c_context * context, StoreDir storeDir, const char * json);

/**
* @brief Add the given `nix_derivation` to the given store
Expand Down Expand Up @@ -245,6 +255,23 @@ void nix_derivation_free(nix_derivation * drv);
*/
nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store * dstStore, StorePath * path);

/** @brief Nix Derivation */
typedef struct nix_derivation_builder nix_derivation_builder;

nix_derivation_builder * nix_make_derivation_builder(
nix_c_context * context,
StoreDir storeDir,
const char * buildDir,
const nix_derivation * drv,
const StorePath * drvPath,
const StorePath * inputPaths[]);

nix_err nix_derivation_builder_start(nix_c_context * context, nix_derivation_builder * builder);

nix_err nix_derivation_builder_finish(nix_c_context * context, nix_derivation_builder * builder);

void nix_derivation_builder_free(nix_derivation_builder * builder);

// cffi end
#ifdef __cplusplus
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,7 @@ public:
nix_api_store_test_base()
{
nix_libstore_init(ctx);
};

~nix_api_store_test_base() override
{
if (exists(std::filesystem::path{nixDir})) {
for (auto & path : std::filesystem::recursive_directory_iterator(nixDir)) {
std::filesystem::permissions(path, std::filesystem::perms::owner_all);
}
std::filesystem::remove_all(nixDir);
}
}

std::string nixDir;
std::string nixStoreDir;
std::string nixStateDir;
std::string nixLogDir;

protected:
Store * open_local_store()
{
#ifdef _WIN32
// no `mkdtemp` with MinGW
auto tmpl = nix::defaultTempDir() + "/tests_nix-store.";
Expand All @@ -57,7 +38,26 @@ protected:
nixStoreDir = nixDir + "/my_nix_store";
nixStateDir = nixDir + "/my_state";
nixLogDir = nixDir + "/my_log";
};

~nix_api_store_test_base() override
{
if (exists(std::filesystem::path{nixDir})) {
for (auto & path : std::filesystem::recursive_directory_iterator(nixDir)) {
std::filesystem::permissions(path, std::filesystem::perms::owner_all);
}
std::filesystem::remove_all(nixDir);
}
}

std::string nixDir;
std::string nixStoreDir;
std::string nixStateDir;
std::string nixLogDir;

protected:
Store * open_local_store()
{
// Options documented in `nix help-stores`
const char * p1[] = {"store", nixStoreDir.c_str()};
const char * p2[] = {"state", nixStateDir.c_str()};
Expand Down
Loading
Loading