Skip to content

Commit 9bc218c

Browse files
committed
Add new C API for working with derivations
Also test the APIs we just added.
1 parent 1a69fc6 commit 9bc218c

File tree

13 files changed

+270
-47
lines changed

13 files changed

+270
-47
lines changed

src/libexpr-tests/main.cc

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,14 @@
11
#include <gtest/gtest.h>
2-
#include <cstdlib>
3-
#include "nix/store/globals.hh"
4-
#include "nix/util/logging.hh"
2+
3+
#include "nix/store/tests/test-main.hh"
54

65
using namespace nix;
76

87
int main(int argc, char ** argv)
98
{
10-
if (argc > 1 && std::string_view(argv[1]) == "__build-remote") {
11-
printError("test-build-remote: not supported in libexpr unit tests");
12-
return 1;
13-
}
14-
15-
// Disable build hook. We won't be testing remote builds in these unit tests. If we do, fix the above build hook.
16-
settings.buildHook = {};
17-
18-
#ifdef __linux__ // should match the conditional around sandboxBuildDir declaration.
19-
20-
// When building and testing nix within the host's Nix sandbox, our store dir will be located in the host's
21-
// sandboxBuildDir, e.g.: Host
22-
// storeDir = /nix/store
23-
// sandboxBuildDir = /build
24-
// This process
25-
// storeDir = /build/foo/bar/store
26-
// sandboxBuildDir = /build
27-
// However, we have a rule that the store dir must not be inside the storeDir, so we need to pick a different
28-
// sandboxBuildDir.
29-
settings.sandboxBuildDir = "/test-build-dir-instead-of-usual-build-dir";
30-
#endif
31-
32-
#ifdef __APPLE__
33-
// Avoid this error, when already running in a sandbox:
34-
// sandbox-exec: sandbox_apply: Operation not permitted
35-
settings.sandboxMode = smDisabled;
36-
setEnv("_NIX_TEST_NO_SANDBOX", "1");
37-
#endif
38-
39-
// For pipe operator tests in trivial.cc
40-
experimentalFeatureSettings.set("experimental-features", "pipe-operators");
9+
auto res = testMainForBuidingPre(argc, argv);
10+
if (!res)
11+
return res;
4112

4213
::testing::InitGoogleTest(&argc, argv);
4314
return RUN_ALL_TESTS();

src/libstore-c/nix_api_store.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,44 @@ void nix_store_path_free(StorePath * sp)
166166
delete sp;
167167
}
168168

169+
void nix_derivation_free(nix_derivation * drv)
170+
{
171+
delete drv;
172+
}
173+
169174
StorePath * nix_store_path_clone(const StorePath * p)
170175
{
171176
return new StorePath{p->path};
172177
}
173178

179+
nix_derivation * nix_derivation_from_json(nix_c_context * context, Store * store, const char * json)
180+
{
181+
if (context)
182+
context->last_err_code = NIX_OK;
183+
try {
184+
auto drv = nix::Derivation::fromJSON(*store->ptr, nlohmann::json::parse(json));
185+
186+
auto drvPath = nix::writeDerivation(*store->ptr, drv, nix::NoRepair, /* read only */ true);
187+
188+
drv.checkInvariants(*store->ptr, drvPath);
189+
190+
return new nix_derivation{drv};
191+
}
192+
NIXC_CATCH_ERRS_NULL
193+
}
194+
195+
StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation)
196+
{
197+
if (context)
198+
context->last_err_code = NIX_OK;
199+
try {
200+
auto ret = nix::writeDerivation(*store->ptr, derivation->drv, nix::NoRepair);
201+
202+
return new StorePath{ret};
203+
}
204+
NIXC_CATCH_ERRS_NULL
205+
}
206+
174207
nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store * dstStore, StorePath * path)
175208
{
176209
if (context)

src/libstore-c/nix_api_store.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ extern "C" {
2323
typedef struct Store Store;
2424
/** @brief Nix store path */
2525
typedef struct StorePath StorePath;
26+
/** @brief Nix Derivation */
27+
typedef struct nix_derivation nix_derivation;
2628

2729
/**
2830
* @brief Initializes the Nix store library
@@ -207,6 +209,32 @@ nix_err nix_store_realise(
207209
nix_err
208210
nix_store_get_version(nix_c_context * context, Store * store, nix_get_string_callback callback, void * user_data);
209211

212+
/**
213+
* @brief Create a `nix_derivation` from a JSON representation of that derivation.
214+
*
215+
* @param[out] context Optional, stores error information.
216+
* @param[in] store nix store reference.
217+
* @param[in] json JSON of the derivation as a string.
218+
*/
219+
nix_derivation * nix_derivation_from_json(nix_c_context * context, Store * store, const char * json);
220+
221+
/**
222+
* @brief Add the given `nix_derivation` to the given store
223+
*
224+
* @param[out] context Optional, stores error information.
225+
* @param[in] store nix store reference. The derivation will be inserted here.
226+
* @param[in] derivation nix_derivation to insert into the given store.
227+
*/
228+
StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation);
229+
230+
/**
231+
* @brief Deallocate a `nix_derivation`
232+
*
233+
* Does not fail.
234+
* @param[in] drv the derivation to free
235+
*/
236+
void nix_derivation_free(nix_derivation * drv);
237+
210238
/**
211239
* @brief Copy the closure of `path` from `srcStore` to `dstStore`.
212240
*

src/libstore-c/nix_api_store_internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef NIX_API_STORE_INTERNAL_H
22
#define NIX_API_STORE_INTERNAL_H
33
#include "nix/store/store-api.hh"
4+
#include "nix/store/derivations.hh"
45

56
extern "C" {
67

@@ -14,6 +15,11 @@ struct StorePath
1415
nix::StorePath path;
1516
};
1617

18+
struct nix_derivation
19+
{
20+
nix::Derivation drv;
21+
};
22+
1723
} // extern "C"
1824

1925
#endif

src/libstore-test-support/include/nix/store/tests/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ headers = files(
99
'outputs-spec.hh',
1010
'path.hh',
1111
'protocol.hh',
12+
'test-main.hh',
1213
)

src/libstore-test-support/include/nix/store/tests/nix_api_store.hh

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,32 @@
1212
#include <gtest/gtest.h>
1313

1414
namespace nixC {
15-
class nix_api_store_test : public nix_api_util_context
15+
16+
class nix_api_store_test_base : public nix_api_util_context
1617
{
1718
public:
18-
nix_api_store_test()
19+
nix_api_store_test_base()
1920
{
2021
nix_libstore_init(ctx);
21-
init_local_store();
2222
};
2323

24-
~nix_api_store_test() override
24+
~nix_api_store_test_base() override
2525
{
26-
nix_store_free(store);
27-
28-
for (auto & path : std::filesystem::recursive_directory_iterator(nixDir)) {
29-
std::filesystem::permissions(path, std::filesystem::perms::owner_all);
26+
if (exists(std::filesystem::path{nixDir})) {
27+
for (auto & path : std::filesystem::recursive_directory_iterator(nixDir)) {
28+
std::filesystem::permissions(path, std::filesystem::perms::owner_all);
29+
}
30+
std::filesystem::remove_all(nixDir);
3031
}
31-
std::filesystem::remove_all(nixDir);
3232
}
3333

34-
Store * store;
3534
std::string nixDir;
3635
std::string nixStoreDir;
3736
std::string nixStateDir;
3837
std::string nixLogDir;
3938

4039
protected:
41-
void init_local_store()
40+
Store * open_local_store()
4241
{
4342
#ifdef _WIN32
4443
// no `mkdtemp` with MinGW
@@ -66,11 +65,37 @@ protected:
6665

6766
const char ** params[] = {p1, p2, p3, nullptr};
6867

69-
store = nix_store_open(ctx, "local", params);
68+
auto * store = nix_store_open(ctx, "local", params);
7069
if (!store) {
7170
std::string errMsg = nix_err_msg(nullptr, ctx, nullptr);
72-
ASSERT_NE(store, nullptr) << "Could not open store: " << errMsg;
71+
EXPECT_NE(store, nullptr) << "Could not open store: " << errMsg;
72+
assert(store);
7373
};
74+
return store;
7475
}
7576
};
77+
78+
class nix_api_store_test : public nix_api_store_test_base
79+
{
80+
public:
81+
nix_api_store_test()
82+
: nix_api_store_test_base{}
83+
{
84+
init_local_store();
85+
};
86+
87+
~nix_api_store_test() override
88+
{
89+
nix_store_free(store);
90+
}
91+
92+
Store * store;
93+
94+
protected:
95+
void init_local_store()
96+
{
97+
store = open_local_store();
98+
}
99+
};
100+
76101
} // namespace nixC
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#pragma once
2+
3+
///@file
4+
5+
namespace nix {
6+
7+
/**
8+
* Call this for a GTest test suite that will including performing Nix
9+
* builds, before running tests.
10+
*/
11+
int testMainForBuidingPre(int argc, char ** argv);
12+
13+
} // namespace nix

src/libstore-test-support/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ sources = files(
3434
'derived-path.cc',
3535
'outputs-spec.cc',
3636
'path.cc',
37+
'test-main.cc',
3738
)
3839

3940
subdir('include/nix/store/tests')
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <cstdlib>
2+
3+
#include "nix/store/globals.hh"
4+
#include "nix/util/logging.hh"
5+
6+
#include "nix/store/tests/test-main.hh"
7+
8+
namespace nix {
9+
10+
int testMainForBuidingPre(int argc, char ** argv)
11+
{
12+
if (argc > 1 && std::string_view(argv[1]) == "__build-remote") {
13+
printError("test-build-remote: not supported in libexpr unit tests");
14+
return EXIT_FAILURE;
15+
}
16+
17+
// Disable build hook. We won't be testing remote builds in these unit tests. If we do, fix the above build hook.
18+
settings.buildHook = {};
19+
20+
// No substituters, unless a test specifically requests.
21+
settings.substituters = {};
22+
23+
#ifdef __linux__ // should match the conditional around sandboxBuildDir declaration.
24+
25+
// When building and testing nix within the host's Nix sandbox, our store dir will be located in the host's
26+
// sandboxBuildDir, e.g.: Host
27+
// storeDir = /nix/store
28+
// sandboxBuildDir = /build
29+
// This process
30+
// storeDir = /build/foo/bar/store
31+
// sandboxBuildDir = /build
32+
// However, we have a rule that the store dir must not be inside the storeDir, so we need to pick a different
33+
// sandboxBuildDir.
34+
settings.sandboxBuildDir = "/test-build-dir-instead-of-usual-build-dir";
35+
#endif
36+
37+
#ifdef __APPLE__
38+
// Avoid this error, when already running in a sandbox:
39+
// sandbox-exec: sandbox_apply: Operation not permitted
40+
settings.sandboxMode = smDisabled;
41+
setEnv("_NIX_TEST_NO_SANDBOX", "1");
42+
#endif
43+
44+
return EXIT_SUCCESS;
45+
}
46+
47+
} // namespace nix
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"args": [
3+
"-c",
4+
"echo $name foo > $out"
5+
],
6+
"builder": "/bin/sh",
7+
"env": {
8+
"builder": "/bin/sh",
9+
"name": "myname",
10+
"out": "/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9",
11+
"system": "x86_64-linux"
12+
},
13+
"inputDrvs": {},
14+
"inputSrcs": [],
15+
"name": "myname",
16+
"outputs": {
17+
"out": {
18+
"hashAlgo": "sha256",
19+
"method": "nar"
20+
}
21+
},
22+
"system": "x86_64-linux"
23+
}

0 commit comments

Comments
 (0)