Skip to content

Conversation

@RossComputerGuy
Copy link
Member

@RossComputerGuy RossComputerGuy commented Sep 19, 2025

Motivation

Need to be able to read some derivation information from Rust.

Context

Summary by CodeRabbit

  • New Features

    • Public C API to create/clone/free derivations, add derivations to the store, enumerate outputs (with associated opaque store-path objects), and serialize/parse derivations to/from JSON.
  • API Changes

    • Improved const-safety; callbacks now deliver opaque store-path objects instead of raw path strings.
  • Tests

    • Unified pre-build test helper, new test entry points and utilities, and a self-contained derivation integration test.
  • Documentation

    • Clarified callback lifetime semantics.

@coderabbitai
Copy link

coderabbitai bot commented Sep 19, 2025

Walkthrough

Add C API wrappers and internal types for derivations and outputs, make StorePath parameters const-correct for validation/realise callbacks, implement derivation JSON parse/serialize/clone/free and store add/query/build helpers, and introduce a test pre-build helper, test mains, test-harness refactor, test data, and a derivation unit test.

Changes

Cohort / File(s) Summary
C API: derivation types & ops
src/libstore-c/nix_api_store.h, src/libstore-c/nix_api_store.cc, src/libstore-c/nix_api_store_internal.h
Add opaque nix_derivation and related wrappers and functions: parse derivation from JSON, serialize to JSON, make outputs from JSON, add/write derivations to store, clone/free derivations and outputs, enumerate outputs and optpaths, query derivation from path, batch build/query helpers. Update nix_store_is_valid_path and nix_store_realise callback signatures to accept const StorePath *.
Test pre-build helper & test mains
src/libstore-test-support/test-main.cc, src/libstore-test-support/include/nix/store/tests/test-main.hh, src/libstore-test-support/meson.build, src/libstore-tests/main.cc, src/libstore-tests/meson.build, src/libexpr-tests/main.cc
Add nix::testMainForBuidingPre() and header; export and compile it into test-support; call it from test mains and libexpr tests to perform pre-test store configuration (disable buildHook/substituters, sandbox tweaks, handle __build-remote).
Test harness: store test refactor
src/libstore-test-support/include/nix/store/tests/nix_api_store.hh
Introduce nix_api_store_test_base to centralize libstore init and conditional nixDir cleanup; create derived nix_api_store_test that owns Store* and calls open_local_store() / init_local_store(); adjust EXPECT/ASSERT usage and ownership semantics.
Unit test: derivation test & adapter
src/libstore-tests/nix_api_store.cc
Add build_from_json test that enables ca-derivations, parses a derivation JSON, adds it to the store, realises it via the new C API and validates produced StorePath. Add LambdaAdapter to bridge lambdas to C callbacks; include necessary headers and cleanup.
Test data: derivation fixture
src/libstore-tests/data/derivation/ca/self-contained.json
Add a self-contained derivation JSON fixture ("myname") with a single out output used by the new unit test.
Build export: test header
src/libstore-test-support/include/nix/store/tests/meson.build
Export test-main.hh as a public header in the test-support component; add test-main.cc to sources in test-support build.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Test as Test client
  participant C_API as C API (nix_api_store)
  participant Store
  participant Callback

  Test->>C_API: nix_derivation_from_json(ctx, store, json)
  activate C_API
  C_API->>C_API: parse JSON -> nix_derivation*
  C_API-->>Test: return nix_derivation* wrapper
  deactivate C_API

  Test->>C_API: nix_add_derivation(ctx, store, derivation)
  activate C_API
  C_API->>Store: writeDerivation(derivation)
  Store-->>C_API: StorePath
  C_API-->>Test: StorePath* wrapper
  deactivate C_API
Loading
sequenceDiagram
  autonumber
  participant Test as Test client
  participant C_API as C API (nix_api_store)
  participant Store
  participant Callback

  Test->>C_API: nix_store_realise(ctx, store, path, userdata, cb)
  activate C_API
  C_API->>Store: realise(path)
  Store-->>C_API: event(outname, out_path)
  C_API-->>Callback: cb(userdata, outname, const StorePath * out)
  deactivate C_API
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • edolstra
  • cole-h

Poem

I nibble JSON, stitch each trace,
I hop through outputs, wrap with grace.
I hand you paths as pointers neat,
I clone and free, then skip a beat.
A rabbit cheers when tests complete. 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately conveys that the primary change is the addition of derivation-related functions to the libstore-c API surface, making it clear to reviewers what the main focus of the pull request is.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch RossComputerGuy/feat/expose-drvfrompath

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Sep 19, 2025

@github-actions github-actions bot temporarily deployed to pull request September 19, 2025 21:29 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (10)
src/libstore-c/nix_api_store_internal.h (2)

16-20: Wrappers store full nix::Derivation by value; consider pointer semantics to avoid heavy copies.

Owning by value simplifies lifetime but can be costly to copy in callbacks and clones. Consider:

  • Make struct Derivation { std::shared_ptr<nix::Derivation> drv; }
  • Make struct DerivationOutput { std::shared_ptr<nix::DerivationOutput> drv_out; }
    This preserves C ABI (opaque pointer) while reducing copies.

21-24: Same consideration for DerivationOutput.

Storing by value copies on every callback iteration; shared ownership avoids that without changing the public C surface.

src/libstore-c/nix_api_store.cc (4)

184-201: Avoid an extra deep copy; also add basic null-arg guards.

  • Move the derived value into the wrapper to skip one copy.
  • Optional: early-return or throw on !store || !path to avoid UB via deref.

Apply:

 nix_err nix_store_drv_from_path(
@@
     try {
-        nix::Derivation drv = store->ptr->derivationFromPath(path->path);
+        if (!store || !path) { /* keep style consistent with the rest of the file if throwing */
+            throw std::invalid_argument("nix_store_drv_from_path: null store or path");
+        }
+        nix::Derivation drv = store->ptr->derivationFromPath(path->path);
         if (callback) {
-            const Derivation tmp{drv};
+            const Derivation tmp{std::move(drv)};
             callback(userdata, &tmp);
         }
     }

203-206: Cloning performs a full deep copy.

If you switch wrappers to shared_ptr, clone becomes a cheap ref bump:

-Derivation * nix_drv_clone(const Derivation * d)
-{
-    return new Derivation{d->drv};
-}
+Derivation * nix_drv_clone(const Derivation * d) {
+    return new Derivation{d->drv}; // shared_ptr copy if refactor applied
+}

If keeping value semantics, please confirm typical derivation sizes in your workloads to ensure cloning cost is acceptable.


213-230: Borrowed name lifetime not documented; potential misuse.

name.c_str() points into the derivation’s internal map. Add a doc note in the header: the name pointer is valid only during the callback.

Would you like me to patch the header comments to state this explicitly?


232-257: Same lifetime note for name and StorePath; consider avoiding per-iteration copies.

  • Document that both name and path are borrowed for the duration of the callback.
  • Optional: if wrappers move to pointer semantics, you can pass views without copying DerivationOutput and StorePath each iteration.
src/libstore-c/nix_api_store.h (4)

224-241: Clarify callback contract and nullability.

Suggest amending docs:

  • Callback may be NULL (no-op).
  • The Derivation pointer is borrowed only for the duration of the call and must not be freed; use nix_drv_clone to retain it.

Proposed doc tweak:

 /**
  * @brief Returns the derivation associated with the store path
  *
- * @note The callback borrows the Derivation only for the duration of the call.
+ * @note The callback may be NULL (no-op).
+ * @note The callback borrows the Derivation only for the duration of the call.
+ *       Do not call nix_drv_free() on this pointer; use nix_drv_clone() to retain.

242-257: Clone/free API: document ownership expectations.

Add a brief note that only objects returned by *_clone are owned and must be freed with the matching *_free.


258-273: Document name lifetime and encoding.

Add:

  • name is borrowed and valid only during the callback.
  • Encoding: UTF‑8, no NUL bytes.
  * @param[in] callback The function to call on every output
+ * @note The `name` argument is borrowed (valid only during the callback).

274-291: Document name and path lifetimes; clarify that path may be NULL.

Add:

  * @param[in] callback The function to call on every output and store path
  * @param[in] userdata The userdata to pass to the callback
+ * @note `name` and `path` are borrowed and valid only during the callback.
+ *       `path` may be NULL when the output has no associated store path.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 044c43c and 84a4ea6.

📒 Files selected for processing (3)
  • src/libstore-c/nix_api_store.cc (1 hunks)
  • src/libstore-c/nix_api_store.h (2 hunks)
  • src/libstore-c/nix_api_store_internal.h (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.cc (1)
src/libstore/include/nix/store/store-api.hh (16)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (18)
  • nix_store_drv_from_path (184-201)
  • nix_store_drv_from_path (184-189)
  • callback (132-132)
  • callback (188-188)
  • callback (216-216)
  • callback (236-236)
  • nix_drv_clone (203-206)
  • nix_drv_clone (203-203)
  • nix_drv_free (208-211)
  • nix_drv_free (208-208)
  • nix_drv_get_outputs (213-230)
  • nix_drv_get_outputs (213-217)
  • nix_drv_get_outputs_and_optpaths (232-257)
  • nix_drv_get_outputs_and_optpaths (232-237)
  • nix_drv_output_clone (259-262)
  • nix_drv_output_clone (259-259)
  • nix_drv_output_free (264-267)
  • nix_drv_output_free (264-264)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_x86_64-linux / manual
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (4)
src/libstore-c/nix_api_store.cc (1)

259-267: LGTM for output clone/free.

Simple and consistent with the rest of the API.

src/libstore-c/nix_api_store.h (2)

26-29: Opaque typedefs: good addition.

Keeps the C ABI stable while allowing internal evolution.


292-306: LGTM for DerivationOutput clone/free docs and API.

Consistent with the Derivation ownership model.

src/libstore-c/nix_api_store_internal.h (1)

3-3: Include verified — header and required APIs are present.
Found src/libstore/include/nix/store/derivations.hh (and parsed-derivations.hh); Derivation and outputsAndOptPaths are defined there, and derivationFromPath is declared in src/libstore/include/nix/store/store-api.hh.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (6)
src/libstore-test-support/include/nix/store/tests/test-main.hh (1)

11-11: Fix the typo in the function name.

There's a typo in the function name - "Buiding" should be "Building".

Apply this fix:

-int testMainForBuidingPre(int argc, char ** argv);
+int testMainForBuildingPre(int argc, char ** argv);

Note that this typo appears in multiple files across the PR and should be fixed consistently.

src/libstore-tests/nix_api_store.cc (2)

205-221: Consider simplifying the lambda adapter pattern.

While the LambdaAdapter template works, consider using std::function or a simpler approach for better readability and maintainability.

Alternative implementation using a simpler approach:

// Option 1: Direct function pointer with capture-less lambda
auto cb = [](void * userdata, const char * outname, const char * outPath) {
    auto * ctx_store = static_cast<std::pair<nix_c_context*, Store*>*>(userdata);
    StorePath sp{outPath};
    auto is_valid_path = nix_store_is_valid_path(ctx_store->first, ctx_store->second, &sp);
    ASSERT_EQ(is_valid_path, true);
};

std::pair<nix_c_context*, Store*> userdata{ctx, store};
auto ret = nix_store_realise(ctx, store, drvPath, &userdata, cb);

233-235: Add file existence check and error handling.

The test should verify the JSON file exists and handle potential I/O errors gracefully.

Improve error handling:

+    auto jsonPath = unitTestData / "derivation/ca/self-contained.json";
+    ASSERT_TRUE(std::filesystem::exists(jsonPath)) << "Test data file not found: " << jsonPath;
+    
-    std::ifstream t{unitTestData / "derivation/ca/self-contained.json"};
+    std::ifstream t{jsonPath};
+    ASSERT_TRUE(t.is_open()) << "Failed to open test data file: " << jsonPath;
     std::stringstream buffer;
     buffer << t.rdbuf();
src/libstore-test-support/test-main.cc (2)

10-10: Typo in function name: testMainForBuidingPre

The function name contains a typo - "Buiding" should be "Building".

Apply this diff to fix the typo:

-int testMainForBuidingPre(int argc, char ** argv)
+int testMainForBuildingPre(int argc, char ** argv)

Note that this will require updating all references to this function in other files, including the header declaration and any callers.


13-13: Minor: Typo in error message

The error message mentions "libexpr unit tests" but this code is part of libstore test support.

Apply this diff to fix the error message:

-        printError("test-build-remote: not supported in libexpr unit tests");
+        printError("test-build-remote: not supported in libstore unit tests");
src/libstore-c/nix_api_store.h (1)

233-233: Typo in documentation comment

Missing closing quote in the comment.

Apply this diff to fix the typo:

- * @brief Deallocate a `nix_derivation'
+ * @brief Deallocate a `nix_derivation`
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84a4ea6 and 46af567.

📒 Files selected for processing (13)
  • src/libexpr-tests/main.cc (1 hunks)
  • src/libstore-c/nix_api_store.cc (2 hunks)
  • src/libstore-c/nix_api_store.h (3 hunks)
  • src/libstore-c/nix_api_store_internal.h (2 hunks)
  • src/libstore-test-support/include/nix/store/tests/meson.build (1 hunks)
  • src/libstore-test-support/include/nix/store/tests/nix_api_store.hh (2 hunks)
  • src/libstore-test-support/include/nix/store/tests/test-main.hh (1 hunks)
  • src/libstore-test-support/meson.build (1 hunks)
  • src/libstore-test-support/test-main.cc (1 hunks)
  • src/libstore-tests/data/derivation/ca/self-contained.json (1 hunks)
  • src/libstore-tests/main.cc (1 hunks)
  • src/libstore-tests/meson.build (1 hunks)
  • src/libstore-tests/nix_api_store.cc (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/libstore-c/nix_api_store_internal.h
🧰 Additional context used
🧬 Code graph analysis (7)
src/libstore-test-support/test-main.cc (1)
src/libutil/include/nix/util/environment-variables.hh (1)
  • setEnv (52-52)
src/libstore-tests/main.cc (2)
src/libstore-test-support/include/nix/store/tests/test-main.hh (1)
  • testMainForBuidingPre (11-11)
src/libstore-test-support/test-main.cc (2)
  • testMainForBuidingPre (10-45)
  • testMainForBuidingPre (10-10)
src/libexpr-tests/main.cc (2)
src/libstore-test-support/include/nix/store/tests/test-main.hh (1)
  • testMainForBuidingPre (11-11)
src/libstore-test-support/test-main.cc (2)
  • testMainForBuidingPre (10-45)
  • testMainForBuidingPre (10-10)
src/libstore-tests/nix_api_store.cc (2)
src/libstore-test-support/include/nix/store/tests/nix_api_store.hh (1)
  • store (95-98)
src/libstore-c/nix_api_store.cc (14)
  • nix_derivation_from_json (177-191)
  • nix_derivation_from_json (177-177)
  • nix_add_derivation (193-203)
  • nix_add_derivation (193-193)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • nix_store_realise (127-154)
  • nix_store_realise (127-132)
  • nix_store_path_free (162-165)
  • nix_store_path_free (162-162)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_store_free (55-58)
  • nix_store_free (55-55)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (16)
  • nix_derivation_from_json (177-191)
  • nix_derivation_from_json (177-177)
  • nix_add_derivation (193-203)
  • nix_add_derivation (193-193)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_store_drv_from_path (217-234)
  • nix_store_drv_from_path (217-222)
  • callback (132-132)
  • callback (221-221)
  • callback (239-239)
  • callback (259-259)
  • nix_derivation_get_outputs (236-253)
  • nix_derivation_get_outputs (236-240)
  • nix_derivation_get_outputs_and_optpaths (255-280)
  • nix_derivation_get_outputs_and_optpaths (255-260)
src/libstore-c/nix_api_store.cc (1)
src/libstore/include/nix/store/store-api.hh (4)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
src/libstore-test-support/include/nix/store/tests/nix_api_store.hh (1)
src/libstore-c/nix_api_store.cc (6)
  • nix_libstore_init (13-21)
  • nix_libstore_init (13-13)
  • nix_store_open (33-53)
  • nix_store_open (33-33)
  • nix_store_free (55-58)
  • nix_store_free (55-55)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (8)
src/libstore-test-support/meson.build (1)

37-37: LGTM! Test main source file properly added to build.

The addition of test-main.cc to the sources list is correctly integrated with the existing build configuration.

src/libstore-tests/meson.build (1)

69-69: LGTM! Main test entry point correctly added.

The main.cc file is properly added to the test executable sources list.

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

12-12: LGTM! Test header properly exposed.

The test-main.hh header is correctly added to the public headers list.

src/libstore-tests/data/derivation/ca/self-contained.json (1)

1-23: LGTM! Well-structured test fixture.

The JSON derivation fixture is properly formatted and contains all necessary fields for a self-contained content-addressed derivation test case.

src/libstore-tests/nix_api_store.cc (1)

245-248: Type mismatch in the callback signature.

The callback expects const char * for the second parameter but the lambda is using const StorePath *. This type mismatch could cause undefined behavior.

Let me verify the actual callback signature expected by nix_store_realise:

Based on the search results, please ensure the callback signature matches what nix_store_realise expects. The callback should likely use const char * for both parameters.

src/libstore-tests/main.cc (1)

9-11: Fix the logic error in the return condition.

The condition is inverted. When testMainForBuidingPre returns 0 (success), the main function should continue. Currently it exits early on success.

Apply this fix:

    auto res = testMainForBuidingPre(argc, argv);
-    if (!res)
+    if (res)
        return res;

Likely an incorrect or invalid review comment.

src/libstore-test-support/test-main.cc (1)

41-41: Verify the correct function for setting environment variables

The code uses setEnv but based on the relevant code snippets, this might not be the correct function name in this context.

Let me verify the correct function name for setting environment variables in this codebase:

src/libstore-c/nix_api_store.cc (1)

184-184: Verify the intent of passing true for readOnly parameter

The code passes /* read only */ true to writeDerivation, but then the result is discarded. This seems to be for validation purposes only.

Let me verify the intent and usage of this pattern:

Comment on lines +9 to +11
auto res = testMainForBuidingPre(argc, argv);
if (!res)
return res;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the inverted logic condition.

The condition logic appears to be inverted. When testMainForBuidingPre returns 0 (EXIT_SUCCESS), the test should continue rather than exit.

Apply this fix:

    auto res = testMainForBuidingPre(argc, argv);
-    if (!res)
+    if (res)
        return res;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
auto res = testMainForBuidingPre(argc, argv);
if (!res)
return res;
auto res = testMainForBuidingPre(argc, argv);
if (res)
return res;
🤖 Prompt for AI Agents
In src/libexpr-tests/main.cc around lines 9 to 11, the logic is inverted:
currently it returns when testMainForBuidingPre returns 0 (success). Change the
condition to return only on non-zero (error) — e.g. check if (res != 0) or if
(res) and then return res; so the test continues when res == 0.

Comment on lines +71 to +72
EXPECT_NE(store, nullptr) << "Could not open store: " << errMsg;
assert(store);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Error handling pattern is inconsistent

Using EXPECT_NE followed by assert(store) creates an inconsistent error handling pattern. If the store is null, EXPECT_NE will report the failure but continue execution, then assert will crash the test harness.

Apply this diff to use consistent error handling:

-            EXPECT_NE(store, nullptr) << "Could not open store: " << errMsg;
-            assert(store);
+            ASSERT_NE(store, nullptr) << "Could not open store: " << errMsg;

Using ASSERT_NE will properly fail the test and stop execution if the store is null, which is the intended behavior.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
EXPECT_NE(store, nullptr) << "Could not open store: " << errMsg;
assert(store);
ASSERT_NE(store, nullptr) << "Could not open store: " << errMsg;
🤖 Prompt for AI Agents
In src/libstore-test-support/include/nix/store/tests/nix_api_store.hh around
lines 71 to 72, the test uses EXPECT_NE(store, nullptr) followed by
assert(store) which mixes a non-fatal GoogleTest expectation with a hard abort;
replace this with a single fatal check using ASSERT_NE(store, nullptr) << "Could
not open store: " << errMsg; and remove the subsequent assert(store) so the test
fails and stops cleanly when the store is null.

Comment on lines +225 to +227
// FIXME get rid of these
nix::experimentalFeatureSettings.set("extra-experimental-features", "ca-derivations");
nix::settings.substituters = {};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use proper settings API for test configuration.

Setting experimental features and substituters directly on global settings objects may not be thread-safe and could affect other tests.

Consider using the proper API for test isolation:

-    // FIXME get rid of these
-    nix::experimentalFeatureSettings.set("extra-experimental-features", "ca-derivations");
-    nix::settings.substituters = {};
+    // Use store-specific configuration or proper test setup
+    const char * ca_feature[] = {"experimental-features", "ca-derivations"};
+    const char * no_subst[] = {"substituters", ""};
+    const char ** kvs[] = {ca_feature, no_subst, nullptr};
+    auto * store = nix_store_open(ctx, "local", kvs);

Committable suggestion skipped: line range outside the PR's diff.


auto * store = open_local_store();

std::filesystem::path unitTestData{getenv("_NIX_TEST_UNIT_DATA")};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential null pointer dereference.

The environment variable _NIX_TEST_UNIT_DATA might not be set, leading to undefined behavior when passed to std::filesystem::path.

Add null check:

+    const char* test_data_env = getenv("_NIX_TEST_UNIT_DATA");
+    ASSERT_NE(test_data_env, nullptr) << "_NIX_TEST_UNIT_DATA environment variable not set";
-    std::filesystem::path unitTestData{getenv("_NIX_TEST_UNIT_DATA")};
+    std::filesystem::path unitTestData{test_data_env};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
std::filesystem::path unitTestData{getenv("_NIX_TEST_UNIT_DATA")};
const char* test_data_env = getenv("_NIX_TEST_UNIT_DATA");
ASSERT_NE(test_data_env, nullptr) << "_NIX_TEST_UNIT_DATA environment variable not set";
std::filesystem::path unitTestData{test_data_env};
🤖 Prompt for AI Agents
In src/libstore-tests/nix_api_store.cc around line 231, the code calls
getenv("_NIX_TEST_UNIT_DATA") directly into std::filesystem::path which can
dereference a null pointer if the env var is unset; modify the code to call
getenv into a temporary char* variable, check it for nullptr, and handle the
error (e.g., log and return/throw or use a fallback path) before constructing
std::filesystem::path from the non-null value so no null pointer is passed to
the path constructor.

@github-actions github-actions bot temporarily deployed to pull request September 19, 2025 22:16 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
src/libstore-c/nix_api_store.h (3)

26-29: Fix typedef typo to expose nix_derivation_output in C

Currently the alias is misspelled, breaking C consumers (prototypes use nix_derivation_output* but no such typedef exists in C). Correct the alias.

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivatio_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;

302-309: Header/impl mismatch: nix_derivation_output_clone vs nix_drv_output_clone

Implementation still uses nix_drv_output_clone. Rename impl to match header to avoid link errors.

I’ve proposed the corresponding .cc fix below.


310-317: Header/impl mismatch: nix_derivation_output_free vs nix_drv_output_free

Same naming mismatch for the free function.

src/libstore-c/nix_api_store.cc (1)

282-290: Rename functions to match header (nix_derivation_output_*)

These names must match the header to avoid unresolved symbols.

-nix_derivation_output * nix_drv_output_clone(const nix_derivation_output * o)
+nix_derivation_output * nix_derivation_output_clone(const nix_derivation_output * o)
 {
     return new nix_derivation_output{o->drv_out};
 }
 
-void nix_drv_output_free(nix_derivation_output * o)
+void nix_derivation_output_free(nix_derivation_output * o)
 {
     delete o;
 }
#!/bin/bash
# Verify no remaining mismatched names
rg -nP 'nix_drv_output_(clone|free)|nix_derivatio_noutput'
🧹 Nitpick comments (7)
src/libstore-c/nix_api_store.h (6)

192-198: Realise callback type is good; mark input path as const and clarify borrow

The output pointer is borrowed-only; also the input path isn’t mutated—make it const.

-nix_err nix_store_realise(
-    nix_c_context * context,
-    Store * store,
-    StorePath * path,
-    void * userdata,
-    void (*callback)(void * userdata, const char * outname, const StorePath * out));
+nix_err nix_store_realise(
+    nix_c_context * context,
+    Store * store,
+    const StorePath * path,
+    void * userdata,
+    void (*callback)(void * userdata, const char * outname, const StorePath * out));

Also consider adding: “The StorePath* passed to callback is valid only for the duration of the call.”


214-222: Document ownership and side effects for nix_derivation_from_json

Clarify that the return value must be freed and that no store write occurs (read-only check).

 /**
  * @brief Create a `nix_derivation` from a JSON representation of that derivation.
  *
  * @param[out] context Optional, stores error information.
  * @param[in] store nix store reference.
  * @param[in] json JSON of the derivation as a string.
+ * @return Owned pointer; call `nix_derivation_free` when done.
+ * @note Validates invariants without writing to the store.
  */

223-231: Explain that this writes to the store and return ownership of StorePath

Small doc tweak to set expectations.

 /**
  * @brief Add the given `nix_derivation` to the given store
  *
  * @param[out] context Optional, stores error information.
  * @param[in] store nix store reference. The derivation will be inserted here.
  * @param[in] derivation nix_derivation to insert into the given store.
+ * @return Owned `StorePath*` of the written derivation; free with `nix_store_path_free`.
+ * @note Writes the derivation to the store.
  */

232-239: Fix mismatched quote in docstring

Use matching backticks.

-/**
- * @brief Deallocate a `nix_derivation'
+/**
+ * @brief Deallocate a `nix_derivation`

268-283: Clarify name and drv_output lifetimes in callback

State explicitly that both pointers are valid only during the callback.

 /**
  * @brief Iterate through all of the outputs in a derivation
  *
- * @note The callback borrows the DerivationOutput only for the duration of the call.
+ * @note The callback borrows `name` and `drv_output` only for the duration of the call.

284-301: Document nullable path and borrow

Make it clear that path may be NULL and is borrowed.

 /**
  * @brief Iterate and get all of the derivation outputs and their store paths.
  *
- * @note The callback borrows the DerivationOutput and StorePath only for the duration of the call.
+ * @note The callback borrows the `drv_output` and `path` only for the duration of the call.
+ *       `path` may be NULL if no store path is associated.
src/libstore-c/nix_api_store.cc (1)

127-133: Make input path const to match header suggestion

The path isn’t mutated; align with proposed header change.

-nix_err nix_store_realise(
-    nix_c_context * context,
-    Store * store,
-    StorePath * path,
-    void * userdata,
-    void (*callback)(void * userdata, const char *, const StorePath *))
+nix_err nix_store_realise(
+    nix_c_context * context,
+    Store * store,
+    const StorePath * path,
+    void * userdata,
+    void (*callback)(void * userdata, const char *, const StorePath *))
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46af567 and c14c3ca.

📒 Files selected for processing (2)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (18)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (221-221)
  • callback (239-239)
  • callback (259-259)
  • nix_derivation_from_json (177-191)
  • nix_derivation_from_json (177-177)
  • nix_add_derivation (193-203)
  • nix_add_derivation (193-193)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_store_drv_from_path (217-234)
  • nix_store_drv_from_path (217-222)
  • nix_derivation_get_outputs (236-253)
  • nix_derivation_get_outputs (236-240)
  • nix_derivation_get_outputs_and_optpaths (255-280)
  • nix_derivation_get_outputs_and_optpaths (255-260)
src/libstore-c/nix_api_store.cc (1)
src/libstore/include/nix/store/store-api.hh (22)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
  • name (563-570)
  • name (577-583)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (10)
src/libstore-c/nix_api_store.h (2)

155-155: Const-correctness LGTM

Using const StorePath * here is correct and matches the implementation.


250-267: API shape LGTM; borrowed lifetime note is good

Signature and const usage look correct.

src/libstore-c/nix_api_store.cc (8)

94-102: Const-correctness LGTM

Matches header and underlying API; good.


147-149: Borrowed StorePath passed to callback; ensure callers don’t retain

We construct a local StorePath and pass its address. Fine as a borrow, but callers must not store the pointer.

Please confirm downstream callbacks don’t capture or retain out beyond the call.


167-171: Destructor wrapper LGTM

Ownership and behavior are correct.


177-191: JSON -> derivation flow LGTM

Good use of fromJSON, read-only write for path, and invariant checks with proper error handling.


193-204: Store insertion LGTM

Straightforward write and return an owned StorePath.


217-234: Borrowed nix_derivation in callback LGTM

Borrowing semantics are clear; error handling consistent.


236-253: Outputs iteration LGTM

Pattern is correct and safe under borrow semantics.


255-279: Outputs + optional paths LGTM

Null handling and temp wrappers are sound under borrow semantics.

@github-actions github-actions bot temporarily deployed to pull request September 19, 2025 22:48 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/libstore-c/nix_api_store.h (1)

26-29: Fix typedef typo: breaks C callers using nix_derivation_output

Header uses nix_derivation_output in APIs but the typedef declares nix_derivatio_noutput, so C code will fail to compile without struct keyword. Correct the alias.

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivatio_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;
🧹 Nitpick comments (4)
src/libstore-c/nix_api_store.h (4)

192-198: Make input path const for realise API, to match callback and intent

The callback now receives const StorePath * out (good). The input path should also be const StorePath * for consistency and to signal no mutation.

 nix_err nix_store_realise(
     nix_c_context * context,
     Store * store,
-    StorePath * path,
+    const StorePath * path,
     void * userdata,
     void (*callback)(void * userdata, const char * outname, const StorePath * out));

223-231: Clarify ownership of returned StorePath

Document that the returned StorePath * must be freed by the caller (via nix_store_path_free). Avoids leaks for C consumers.

 /**
  * @brief Add the given `nix_derivation` to the given store
  *
  * @param[out] context Optional, stores error information.
  * @param[in] store nix store reference. The derivation will be inserted here.
  * @param[in] derivation nix_derivation to insert into the given store.
+ * @note The returned StorePath is owned by the caller and must be freed with nix_store_path_free().
  */
 StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation);

268-283: Document borrow semantics for name argument in outputs callback

Like the output object, name is only valid during the callback. Add a brief note to prevent misuse.

 /**
  * @brief Iterate through all of the outputs in a derivation
  *
- * @note The callback borrows the DerivationOutput only for the duration of the call.
+ * @note The callback borrows the DerivationOutput and the `name` string only for the duration of the call.
  *
  * @param[out] context Optional, stores error information
  * @param[in] drv The derivation
  * @param[in] callback The function to call on every output
  * @param[in] userdata Userdata to pass to the callback
  */

284-301: Explicitly state that path may be NULL

The API name says “optpaths”; make it explicit in the docs that path can be NULL.

 /**
  * @brief Iterate and get all of the derivation outputs and their store paths.
  *
- * @note The callback borrows the DerivationOutput and StorePath only for the duration of the call.
+ * @note The callback borrows the DerivationOutput and StorePath only for the duration of the call.
+ *       The StorePath pointer may be NULL if the output has no store path.
  *
  * @param[out] context Optional, stores error information
  * @param[in] drv The derivation
  * @param[in] store The nix store
  * @param[in] callback The function to call on every output and store path
  * @param[in] userdata The userdata to pass to the callback
  */
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c14c3ca and 6f6f94a.

📒 Files selected for processing (2)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/libstore-c/nix_api_store.cc
🧰 Additional context used
🧬 Code graph analysis (1)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (20)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (221-221)
  • callback (239-239)
  • callback (259-259)
  • nix_derivation_from_json (177-191)
  • nix_derivation_from_json (177-177)
  • nix_add_derivation (193-203)
  • nix_add_derivation (193-193)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_store_drv_from_path (217-234)
  • nix_store_drv_from_path (217-222)
  • nix_derivation_get_outputs (236-253)
  • nix_derivation_get_outputs (236-240)
  • nix_derivation_get_outputs_and_optpaths (255-280)
  • nix_derivation_get_outputs_and_optpaths (255-260)
  • nix_derivation_get_structured_attrs (282-295)
  • nix_derivation_get_structured_attrs (282-284)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build_aarch64-darwin / manual
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_x86_64-linux / test
🔇 Additional comments (5)
src/libstore-c/nix_api_store.h (5)

155-155: Const-correctness improvement LGTM

Switching nix_store_is_valid_path to take const StorePath * is correct and consistent with read-only semantics.


238-238: Free function LGTM

nix_derivation_free matches the ownership model introduced by the new constructor.


250-267: API shape LGTM; good borrowing semantics note

The borrow-lifetime note for nix_store_drv_from_path is clear and safe for stack-backed wrapper usage in the implementation.


312-319: Clone API LGTM

Clear ownership and symmetry with free.


320-327: Free API LGTM

Consistent with other object lifetimes in this header.

@github-actions github-actions bot temporarily deployed to pull request September 19, 2025 23:14 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/libstore-c/nix_api_store.h (1)

26-29: Fix typedef: alias name typo breaks build

nix_derivation_output functions below rely on a proper typedef, but Line 29 defines nix_derivation_noutput. This prevents use of the unqualified name in prototypes and will fail to compile.

Apply:

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivation_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;
🧹 Nitpick comments (5)
src/libstore-c/nix_api_store.h (3)

192-198: Document borrowed lifetime for out in realise callback

The callback now receives const StorePath *. Like other APIs here, the pointer is a borrowed view valid only during the callback, but this isn’t documented for nix_store_realise.

Proposed doc tweak:

  /**
   * @brief Realise a Nix store path
   *
   * Blocking, calls callback once for each realised output.
   *
   * @note When working with expressions, consider using e.g. nix_string_realise to get the output. `.drvPath` may not be
   * accurate or available in the future. See https://github.com/NixOS/nix/issues/6507
+  *
+  * @note The `out` StorePath passed to the callback is borrowed and only valid
+  *       for the duration of the callback. Clone it if you need to retain it.
   *
   * @param[out] context Optional, stores error information

223-231: Const-qualify the derivation parameter

nix_add_derivation does not mutate derivation. Prefer const nix_derivation * for API clarity.

Header change:

-StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation);
+StorePath * nix_add_derivation(nix_c_context * context, Store * store, const nix_derivation * derivation);

I’ve included the matching .cc change in a later comment.


303-313: Define behavior when structured attrs are absent; fix minor param-name inconsistency

When structuredAttrs is missing, the implementation currently does nothing and still returns NIX_OK. Please specify behavior (e.g., call back with "null" or return a not-found error) to avoid ambiguity for callers. Also, docs mention user_data but the parameter is userdata elsewhere.

I’ve included a concrete .cc diff to emit "null" below. If preferred, we can document the “no callback on absence” rule instead.

src/libstore-c/nix_api_store.cc (2)

193-203: Const-qualify derivation parameter to mirror header suggestion

No mutation occurs; const is appropriate.

-StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation)
+StorePath * nix_add_derivation(nix_c_context * context, Store * store, const nix_derivation * derivation)

283-297: Emit explicit value when structuredAttrs is absent

Currently returns NIX_OK but never invokes the callback if attrs are missing. Consider invoking the callback with "null" to make absence explicit and keep behavior uniform.

 nix_err nix_derivation_get_structured_attrs(
     nix_c_context * context, const nix_derivation * drv, nix_get_string_callback callback, void * userdata)
 {
     if (context)
         context->last_err_code = NIX_OK;
     try {
-        if (auto structuredAttrs = drv->drv.structuredAttrs) {
-            if (callback) {
-                auto result = structuredAttrs->structuredAttrs.dump();
-                callback(result.data(), result.size(), userdata);
-            }
-        }
+        if (auto structuredAttrs = drv->drv.structuredAttrs) {
+            if (callback) {
+                auto result = structuredAttrs->structuredAttrs.dump();
+                callback(result.data(), result.size(), userdata);
+            }
+        } else if (callback) {
+            static const char null_json[] = "null";
+            callback(null_json, sizeof null_json - 1, userdata);
+        }
     }
     NIXC_CATCH_ERRS
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f6f94a and 02fc921.

📒 Files selected for processing (2)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (24)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (221-221)
  • callback (239-239)
  • callback (259-260)
  • nix_derivation_from_json (177-191)
  • nix_derivation_from_json (177-177)
  • nix_add_derivation (193-203)
  • nix_add_derivation (193-193)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_store_drv_from_path (217-234)
  • nix_store_drv_from_path (217-222)
  • nix_derivation_get_outputs (236-253)
  • nix_derivation_get_outputs (236-240)
  • nix_derivation_get_outputs_and_optpaths (255-281)
  • nix_derivation_get_outputs_and_optpaths (255-261)
  • nix_derivation_get_structured_attrs (283-297)
  • nix_derivation_get_structured_attrs (283-284)
  • nix_derivation_output_clone (299-302)
  • nix_derivation_output_clone (299-299)
  • nix_derivation_output_free (304-307)
  • nix_derivation_output_free (304-304)
src/libstore-c/nix_api_store.cc (1)
src/libstore/include/nix/store/store-api.hh (20)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build_aarch64-darwin / manual
  • GitHub Check: build_x86_64-linux / test
🔇 Additional comments (14)
src/libstore-c/nix_api_store.h (6)

155-155: Const-correctness on path parameter — looks good

Changing nix_store_is_valid_path to take const StorePath * is correct and matches usage in the implementation.


214-222: Clarify side effects of nix_derivation_from_json

Header says “Create a nix_derivation from JSON,” but the implementation parses JSON and calls writeDerivation (read-only mode) and checkInvariants. Please confirm and document whether this function is guaranteed to be side‑effect free with respect to the store (i.e., does not persist anything) and that insertion should happen only via nix_add_derivation.


250-267: Borrowed-lifetime contract is clear — LGTM

The API notes the derivation is only borrowed during the callback. Matches the implementation pattern.


278-283: Output iteration API — LGTM

Callback shape and borrowing semantics look consistent.


295-302: Outputs + optional paths — LGTM

Good use of const Store * and explicit “borrowed” note.


320-328: Clone/free wrappers — LGTM

Names and signatures now match the header; simple ownership semantics.

src/libstore-c/nix_api_store.cc (8)

94-102: isValidPath wrapper — LGTM

Matches the new const StorePath * signature and returns false on exceptions via NIXC_CATCH_ERRS_RES(false).


127-149: Realise callback receives StorePath * — implementation OK

Passing a stack StorePath to the callback is fine given the synchronous, borrowed-lifetime contract. No change requested.

Please ensure downstream callbacks do not stash the StorePath * beyond the call.


167-171: Destructor — LGTM

Simple delete wrapper; no issues.


177-191: Confirm from_json store side effects

This parses JSON, invokes writeDerivation with /* read only */ true, then checks invariants. Please confirm that this does not write to the store and is intended purely for validation + wrapping. If so, consider adding a note in the header.


217-234: Derivation-from-path callback — LGTM

Temporary wrapper and borrowed-lifetime behavior are correct and documented in the header.


236-253: Outputs iteration — LGTM

Straightforward mapping to drv.outputs; good.


255-281: Outputs + opt paths — LGTM

Correctly handles both present and absent paths.


299-307: Clone/free — LGTM

Names now align with the header; ownership is clear.

@github-actions github-actions bot temporarily deployed to pull request September 20, 2025 00:06 Inactive
@RossComputerGuy RossComputerGuy force-pushed the RossComputerGuy/feat/expose-drvfrompath branch 2 times, most recently from 5f2c94b to dca4c01 Compare September 22, 2025 18:35
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (9)
src/libstore-c/nix_api_store.h (5)

173-174: Make nix_store_real_path take a const path

No mutation; const matches other getters.

-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_real_path(
+    nix_c_context * context, Store * store, const StorePath * path, nix_get_string_callback callback, void * user_data);

Companion .cc change provided below.


192-198: Clarify lifetime and const‑qualify path in realise; standardize user_data name

  • Path isn’t mutated; mark it const.
  • Document that out only lives for the callback duration (you pass a pointer to a stack object).
  • Use user_data consistently across APIs.
-nix_err nix_store_realise(
-    nix_c_context * context,
-    Store * store,
-    StorePath * path,
-    void * userdata,
-    void (*callback)(void * userdata, const char * outname, const StorePath * out));
+nix_err nix_store_realise(
+    nix_c_context * context,
+    Store * store,
+    const StorePath * path,
+    void * user_data,
+    void (*callback)(void * user_data, const char * outname, const StorePath * out));

Add to the doc block above:

  • “The out pointer is only valid for the duration of the callback.”
  • path must be a derivation path (.drv). If you intend to realise an output path, use or pass the corresponding .drv.” (Or implement support for both; see .cc note.)

214-222: Document side effects in nix_derivation_from_json

This calls writeDerivation(..., /*read only*/ true) to compute the drv path and then checkInvariants. Clarify that it does not persist in the store and that nix_add_derivation performs the write.

Suggest updating the comment:

- * @brief Create a `nix_derivation` from a JSON representation of that derivation.
+ * @brief Parse a derivation from JSON.
+ *
+ * Does not persist to the store; writes in read-only mode only to compute the drv path for invariant checks.
+ * Use nix_add_derivation() to insert into the store.

230-230: Naming consistency: consider nix_store_add_derivation

Most store ops are prefixed with nix_store_*. Consider adding nix_store_add_derivation as the public name (keep nix_add_derivation as an alias if already used).

Would you like a follow-up patch that adds nix_store_add_derivation as a thin wrapper and marks nix_add_derivation for deprecation in the header comments?


285-291: Rename “derived_path” to “deriver_path” and document lifetime

The callback receives the path of the deriver, not a “derived” path. Also note the pointer is only valid during the callback (local stack object).

- * @param[in] callback Called for when the path info is resolved
+ * @param[in] callback Called when the path info is resolved; if present, receives the deriver path (.drv).
+ *                    The provided StorePath pointer is valid only for the duration of the callback.
...
-nix_err nix_store_query_path_info(
+nix_err nix_store_query_path_info(
     nix_c_context * context,
     Store * store,
     const StorePath * store_path,
-    void * userdata,
-    void (*callback)(void * userdata, const StorePath * derived_path));
+    void * user_data,
+    void (*callback)(void * user_data, const StorePath * deriver_path));

Companion .cc param-name alignment optional (names don’t affect ABI).

src/libstore-c/nix_api_store.cc (4)

104-112: Make nix_store_real_path take const StorePath *

No mutation; update signature to match header change.

-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_real_path(
+    nix_c_context * context, Store * store, const StorePath * path, nix_get_string_callback callback, void * user_data)

182-196: nix_derivation_from_json: behavior note

Reads JSON, computes drv path in read-only mode, checks invariants, returns wrapper. Please mirror this in the header doc to set expectations.


210-220: Make nix_store_copy_closure path const

Path isn’t mutated.

-nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store * dstStore, StorePath * path)
+nix_err nix_store_copy_closure(nix_c_context * context, Store * srcStore, Store * dstStore, const StorePath * path)
@@
-        paths.insert(path->path);
+        paths.insert(path->path);

Header change provided above.


241-262: Clarify “deriver path” and lifetime; standardize user_data

The pointer you pass is to a stack StorePath; add a brief comment and consider renaming the parameter to deriver_path. Also align param name with user_data.

-nix_err nix_store_query_path_info(
+nix_err nix_store_query_path_info(
     nix_c_context * context,
     Store * store,
     const StorePath * store_path,
-    void * userdata,
-    void (*callback)(void * userdata, const StorePath * derived_path))
+    void * user_data,
+    void (*callback)(void * user_data, const StorePath * deriver_path))
@@
-                callback(userdata, &deriver_tmp);
+                // NOTE: deriver_tmp is stack-allocated; only valid during this callback.
+                callback(user_data, &deriver_tmp);
@@
-                callback(userdata, nullptr);
+                callback(user_data, nullptr);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5962284 and 5f2c94b.

📒 Files selected for processing (2)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (29)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (226-226)
  • callback (246-246)
  • callback (267-267)
  • callback (287-288)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_add_derivation (198-208)
  • nix_add_derivation (198-198)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (222-239)
  • nix_store_drv_from_path (222-227)
  • nix_store_query_path_info (241-262)
  • nix_store_query_path_info (241-246)
  • nix_derivation_get_outputs (264-281)
  • nix_derivation_get_outputs (264-268)
  • nix_derivation_get_outputs_and_optpaths (283-309)
  • nix_derivation_get_outputs_and_optpaths (283-289)
  • nix_derivation_to_json (311-323)
  • nix_derivation_to_json (311-312)
  • nix_derivation_output_clone (325-328)
  • nix_derivation_output_clone (325-325)
  • nix_derivation_output_free (330-333)
  • nix_derivation_output_free (330-330)
src/libstore-c/nix_api_store.cc (1)
src/libstore/include/nix/store/store-api.hh (22)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • callback (425-425)
  • callback (453-453)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (18)
src/libstore-c/nix_api_store.h (7)

155-156: LGTM: const-correctness on is_valid_path

The const StorePath * parameter aligns with underlying API and avoids accidental mutation.


258-275: LGTM: borrow semantics documented

Borrowed derivation pointer for the duration of the callback is appropriate; matches implementation.


302-307: LGTM: outputs enumerator

Borrowed output wrapper per-callback is safe and mirrors typical pattern.


319-326: LGTM: outputs + optional paths

Good use of outputsAndOptPaths; borrow semantics are clear.


335-336: LGTM: JSON via callback

Matches the project’s string-callback pattern; avoids dangling pointers.


344-352: LGTM: clone/free of nix_derivation_output

Signatures now match; simple ownership model is clear.


26-30: Fix typedef typo: breaks public API and CFFI generation

nix_derivation_noutput is a typo; callers expect nix_derivation_output. This will confuse users and break bindings.

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivation_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;
src/libstore-c/nix_api_store.cc (11)

94-102: LGTM: const-correct is_valid_path implementation

Pass-through to Store::isValidPath(const StorePath&) is correct with error capture.


156-160: LGTM: callback lifetime for StorePath

You correctly pass a pointer to a stack StorePath only during the callback.

Please add a one-line comment above the callback to warn consumers not to retain the pointer.


167-170: LGTM: nix_derivation_free

Straightforward delete.


177-181: LGTM: nix_derivation_clone

Value-copy wrapper is fine.


198-208: LGTM: nix_add_derivation

Writes to store and returns StorePath.


222-239: LGTM: nix_store_drv_from_path

Borrow semantics clear and implemented safely.


264-281: LGTM: outputs enumerator

Correct wrapping and safe callback usage.


283-309: LGTM: outputs + optional paths

Good handling of optional path and borrow semantics.


311-323: LGTM: derivation to JSON

Local std::string lifetime is correctly scoped to the callback.


325-333: LGTM: clone/free names now match header

Consistency restored versus earlier mismatch.


127-154: Realise: make path const and clarify .drv vs output-path handling

Use const StorePath*, rename userdata->user_data and pass it to the callback. Either require callers to pass a .drv, or support output paths by using DerivedPath::Opaque and branching on a predicate such as StorePath::isDerivation(). Verification failed (rg returned "nix: No such file or directory"); confirm whether a derivation predicate exists or run the search below.

-nix_err nix_store_realise(
+nix_err nix_store_realise(
     nix_c_context * context,
     Store * store,
-    StorePath * path,
-    void * userdata,
-    void (*callback)(void * userdata, const char *, const StorePath *))
+    const StorePath * path,
+    void * user_data,
+    void (*callback)(void * user_data, const char *, const StorePath *))
 {
@@
-        const auto nixStore = store->ptr;
-        auto results = nixStore->buildPathsWithResults(paths, nix::bmNormal, nixStore);
@@
-                    callback(userdata, outputName.c_str(), &p);
+                    callback(user_data, outputName.c_str(), &p);

Run from repo root to verify availability of a derivation predicate:
rg -nP --type=cpp -C2 '\b(isDerivation\s*(|.isDerivation\s*()'

@github-actions github-actions bot temporarily deployed to pull request September 22, 2025 18:37 Inactive
@github-actions github-actions bot temporarily deployed to pull request September 22, 2025 23:23 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (9)
src/libstore-c/nix_api_store.h (6)

192-198: Document borrowed lifetime and make input path const.

  • Clarify the callback gets a borrowed StorePath* valid only during the call.
  • Input path can be const.
-nix_err nix_store_realise(
-    nix_c_context * context,
-    Store * store,
-    StorePath * path,
-    void * userdata,
-    void (*callback)(void * userdata, const char * outname, const StorePath * out));
+nix_err nix_store_realise(
+    nix_c_context * context,
+    Store * store,
+    const StorePath * path,
+    void * userdata,
+    void (*callback)(void * userdata, const char * outname, const StorePath * out));

Add to the docblock: “The out pointer is borrowed and valid only for the duration of the callback.”


214-221: Add ownership note for return value.

State that the returned nix_derivation* must be freed with nix_derivation_free.

  /**
   * @brief Create a `nix_derivation` from a JSON representation of that derivation.
   *
   * @param[out] context Optional, stores error information.
   * @param[in] store nix store reference.
   * @param[in] json JSON of the derivation as a string.
+  * @return owned pointer; free with `nix_derivation_free`.
   */

233-239: Clarify callback string lifetime (and consider consistent string-callback style).

  • Document that both output_name and path are borrowed and valid only during the callback.
  • Consider switching path to nix_get_string_callback for consistency with other getters.
  /**
   * @brief Hashes the derivation and gives the output paths
   ...
- * @param[in] callback Called for every output to provide the output path.
+ * @param[in] callback Called for every output. The `output_name` and `path`
+ *                     pointers are borrowed and valid only during the call.

247-248: Add ownership note for returned StorePath.

Mention the caller must nix_store_path_free the result.

- * @param[in] derivation nix_derivation to insert into the given store.
+ * @param[in] derivation nix_derivation to insert into the given store.
+ * @return owned StorePath; free with `nix_store_path_free`.

302-307: Document nullable and borrowed result.

derived_path can be null; also clarify borrowed lifetime.

- * @param[in] callback Called for when the path info is resolved
+ * @param[in] callback Called when the path info is resolved. If the path has no
+ *                     deriver, `derived_path` is NULL. The pointer is borrowed
+ *                     and valid only during the callback.

353-359: Consider using the common string-callback helper.

For consistency with other APIs, prefer call_nix_get_string_callback (see .cc suggestion).

src/libstore-c/nix_api_store.cc (3)

127-133: Make input path const to match header suggestion.

-nix_err nix_store_realise(
-    nix_c_context * context,
-    Store * store,
-    StorePath * path,
+nix_err nix_store_realise(
+    nix_c_context * context,
+    Store * store,
+    const StorePath * path,

198-221: Avoid passing c_str() of a temporary directly; hold it in a local.

Safer and clearer across FFI boundaries; also document borrowing in the header.

-            if (callback) {
-                callback(userdata, output.first.c_str(), store->ptr->printStorePath(outPath).c_str());
-            }
+            if (callback) {
+                const auto pathStr = store->ptr->printStorePath(outPath);
+                callback(userdata, output.first.c_str(), pathStr.c_str());
+            }

336-352: Use common helper for string callbacks for consistency.

-        auto result = drv->drv.toJSON(store->ptr->config).dump();
-        if (callback) {
-            callback(result.data(), result.size(), userdata);
-        }
+        auto result = drv->drv.toJSON(store->ptr->config).dump();
+        return call_nix_get_string_callback(result, callback, user_data);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dca4c01 and af1c1fc.

📒 Files selected for processing (2)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.cc (1)
src/libstore/include/nix/store/store-api.hh (22)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • callback (425-425)
  • callback (453-453)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (32)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (251-251)
  • callback (271-271)
  • callback (292-292)
  • callback (312-313)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (247-264)
  • nix_store_drv_from_path (247-252)
  • nix_store_query_path_info (266-287)
  • nix_store_query_path_info (266-271)
  • nix_derivation_get_outputs (289-306)
  • nix_derivation_get_outputs (289-293)
  • nix_derivation_get_outputs_and_optpaths (308-334)
  • nix_derivation_get_outputs_and_optpaths (308-314)
  • nix_derivation_to_json (336-352)
  • nix_derivation_to_json (336-341)
  • nix_derivation_output_clone (354-357)
  • nix_derivation_output_clone (354-354)
  • nix_derivation_output_free (359-362)
  • nix_derivation_output_free (359-359)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_x86_64-linux / manual
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (11)
src/libstore-c/nix_api_store.h (3)

155-155: Const-correctness on is_valid_path looks good.


366-374: Output clone/free API looks coherent.


26-29: Fix broken typedef: use nix_derivation_output (build-blocker).

The forward typedef misspells the public alias; all later prototypes use nix_derivation_output, which currently isn’t defined, causing compile errors.

Apply:

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivation_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;
+/* (optional temporary compat) */
+/* typedef struct nix_derivation_output nix_derivation_noutput; */

Run to catch any remaining typos:

#!/bin/bash
rg -nP '\b(nix_derivation_noutput|nix_derivatio_noutput)\b' -S -g '!**/build/**'
src/libstore-c/nix_api_store.cc (8)

94-102: LGTM: const path in is_valid_path and direct passthrough.


146-149: Borrowed StorePath lifetime is limited to the callback.

Implementation matches the intended borrowing pattern; ensure the header documents this (see related comment).


182-196: Confirm side effects of writeDerivation(readOnly=true).

This calls writeDerivation(..., /* read only */ true) during JSON parsing. Verify this does not persist anything or mutate store state unexpectedly (to avoid surprising IO before nix_add_derivation).

Would you like me to add an inline comment explaining the rationale once confirmed?


247-264: Borrowed derivation lifetime matches doc; good.

Ensure downstream callbacks don’t retain the pointer beyond the call.


266-287: Nullable deriver handling looks correct; add doc note (see header).


289-306: Output iteration wrapper: OK.


308-334: Outputs-and-paths wrapper: OK; clear null-path branch.


354-361: Output clone/free: straightforward.

@RossComputerGuy RossComputerGuy force-pushed the RossComputerGuy/feat/expose-drvfrompath branch from af1c1fc to 90e65c1 Compare September 22, 2025 23:34
@github-actions github-actions bot temporarily deployed to pull request September 22, 2025 23:37 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/libstore-c/nix_api_store.h (2)

192-198: Clarify lifetime of callback StorePath; consider const for input path

The callback receives const StorePath * out that borrows a stack wrapper; document that it’s valid only during the call. Also, the path input param can be const StorePath *.

- * @param[in] path Path to build
+ * @param[in] path Path to build
+ * @note The `out` StorePath passed to the callback is borrowed and only valid
+ *       for the duration of the callback invocation.
@@
-    StorePath * path,
+    const StorePath * path,

Matching .cc change shown in its comment.


301-307: Document borrowed StorePath lifetime in callback

derived_path points to a stack wrapper; add the same borrowing note used elsewhere.

  /**
   * @brief Queries for the nix store path info.
   *
+  * @note The `derived_path` argument, when non-null, is borrowed and only valid
+  *       during the callback invocation.
src/libstore-c/nix_api_store.cc (2)

127-149: Realise: pass borrowed StorePath; make input path const

You create a stack StorePath and pass its address—good. Make the input path param const StorePath * to be fully const-correct.

-nix_err nix_store_realise(
-    nix_c_context * context,
-    Store * store,
-    StorePath * path,
+nix_err nix_store_realise(
+    nix_c_context * context,
+    Store * store,
+    const StorePath * path,

336-352: to_json: consider using helper for consistency

Minor: other functions use call_nix_get_string_callback; using it here would unify behavior and return codes.

-        auto result = drv->drv.toJSON(store->ptr->config).dump();
-        if (callback) {
-            callback(result.data(), result.size(), userdata);
-        }
+        auto result = drv->drv.toJSON(store->ptr->config).dump();
+        return call_nix_get_string_callback(result, callback, userdata);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af1c1fc and 90e65c1.

📒 Files selected for processing (2)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.cc (3)
src/libstore/include/nix/store/store-api.hh (26)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • callback (425-425)
  • callback (453-453)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
  • info (535-539)
  • info (762-762)
  • name (563-570)
  • name (577-583)
src/libstore/include/nix/store/realisation.hh (1)
  • outPath (80-83)
src/libstore/include/nix/store/store-dir-config.hh (3)
  • name (83-83)
  • name (85-85)
  • name (91-97)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (32)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (251-251)
  • callback (271-271)
  • callback (292-292)
  • callback (312-313)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (247-264)
  • nix_store_drv_from_path (247-252)
  • nix_store_query_path_info (266-287)
  • nix_store_query_path_info (266-271)
  • nix_derivation_get_outputs (289-306)
  • nix_derivation_get_outputs (289-293)
  • nix_derivation_get_outputs_and_optpaths (308-334)
  • nix_derivation_get_outputs_and_optpaths (308-314)
  • nix_derivation_to_json (336-352)
  • nix_derivation_to_json (336-341)
  • nix_derivation_output_clone (354-357)
  • nix_derivation_output_clone (354-354)
  • nix_derivation_output_free (359-362)
  • nix_derivation_output_free (359-359)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_x86_64-linux / manual
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (20)
src/libstore-c/nix_api_store.h (10)

246-246: Add-derivation API shape is good

Consistent with other alloc-returning functions.


254-262: Free/clone API for derivation looks good

Simple and consistent with other wrappers.


285-291: Borrowed derivation lifetime note: good

The “borrows for duration of the call” contract is clear and matches implementation.


318-323: Output enumeration API looks solid

Borrowing semantics are documented; clone/free helpers provided.


335-342: Outputs+optpaths API looks solid

Consistent with other borrowed-pointer callbacks.


352-357: JSON serialization via callback is correct

Matches the project’s callback pattern for strings.


359-373: Derivation output clone/free look correct

No concerns.


155-155: Approve: const StorePath parameter is safe*

Call sites in src/libstore-tests and src/libexpr-tests pass StorePath* (implicit conversion to const is valid) and none mutate the path — no changes required.


26-29: Fix typedef: breaks compilation by aliasing the wrong name

You forward-declare the struct but typedef it to nix_derivation_noutput while all APIs use nix_derivation_output. This will not compile in C headers using the typedef’d name.

Apply:

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivation_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;
+/* (optional compat) */
+/* typedef nix_derivation_output nix_derivation_noutput; */

214-221: API addition: from-JSON derivation — transitive nlohmann/json.hpp confirmed

Interface is fine.

Verified include chains from src/libstore-c/nix_api_store.cc to <nlohmann/json.hpp>:

  • src/libstore-c/nix_api_store.cc -> src/libstore-c/nix_api_store_internal.h -> src/libstore/include/nix/store/derivations.hh -> src/libstore/include/nix/store/parsed-derivations.hh -> <nlohmann/json.hpp>
  • src/libstore-c/nix_api_store.cc -> src/libstore/include/nix/store/globals.hh -> src/libstore/include/nix/store/build/derivation-builder.hh -> src/libstore/include/nix/store/derivation-options.hh -> <nlohmann/json.hpp>

No changes required.

src/libstore-c/nix_api_store.cc (10)

94-101: Const StorePath in is_valid_path: good

Matches header and underlying isValidPath API.


167-171: Derivation free: OK

Straight delete—fine.


177-181: Derivation clone: OK

Shallow copy of wrapper—fine.


223-233: add_derivation: OK

Writes and returns wrapper path.


247-264: drv_from_path: OK with borrowed wrapper

Temporary wrapper and lifetime are documented in header.


266-287: query_path_info: OK; add borrowed-path doc in header

Implementation aligns with suggested doc change.


289-306: get_outputs: OK

Borrowed output wrapper; clone/free available.


308-334: get_outputs_and_optpaths: OK

Borrowed output and optional path—consistent.


354-361: derivation_output clone/free: OK

Simple and correct.


182-196: from_json: add explicit JSON include or confirm PCH; annotate read-only writeDerivation

  • src/libstore/pch/precompiled-headers.hh already includes <nlohmann/json.hpp>. Either add #include <nlohmann/json.hpp> to src/libstore-c/nix_api_store.cc (or one of its direct headers) or ensure this translation unit is guaranteed to use that precompiled header — avoid relying on fragile transitive includes.
  • Add a one-line comment before the writeDerivation(..., /* read only */ true) call stating that read-only=true is only used to compute drvPath for invariant checking and does not mutate the store.

@github-actions github-actions bot temporarily deployed to pull request September 23, 2025 15:39 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/libstore-test-support/include/nix/store/tests/nix_api_store.hh (2)

51-55: Fix UB: mkdtemp modifies a const buffer; use std::string::data()

Casting c_str() to char* is undefined. Use a mutable buffer.

Apply this diff:

-        auto tmpl = nix::absPath(std::filesystem::path(nix::defaultTempDir()) / "tests_nix-store.XXXXXX", true);
-        nixDir = mkdtemp((char *) tmpl.c_str());
+        std::string tmpl = nix::absPath(
+            std::filesystem::path(nix::defaultTempDir()) / "tests_nix-store.XXXXXX", true);
+        // mkdtemp mutates tmpl in place
+        nixDir = mkdtemp(tmpl.data());

45-49: Windows path suffix construction is wrong; use std::to_string(i)

std::string{i} creates a 1-char string, not a decimal of i. Generates invalid paths.

-        for (size_t i = 0; true; ++i) {
-            nixDir = tmpl + std::string{i};
+        for (size_t i = 0; true; ++i) {
+            nixDir = tmpl + std::to_string(i);
             if (std::filesystem::create_directory(nixDir))
                 break;
         }
🧹 Nitpick comments (4)
src/libstore-test-support/include/nix/store/tests/test-main.hh (1)

8-10: Tighten the Doxygen summary and clarify return contract.

Shorter, clearer, and documents expected return semantics.

-/**
- * Call this for a GTest test suite that will including performing Nix
- * builds, before running tests.
- */
+/**
+ * Prepare the environment for tests that perform Nix builds.
+ * Call this before InitGoogleTest().
+ * Returns 0 (EXIT_SUCCESS) on success; non-zero on failure.
+ */
src/libstore-test-support/include/nix/store/tests/nix_api_store.hh (1)

11-11: Remove duplicate include

Minor cleanup.

-#include <filesystem>
src/libstore-c/nix_api_store.h (1)

173-175: Const-correctness: accept const StorePath in real_path/realise

Neither function mutates the StorePath.

-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_real_path(
+    nix_c_context * context, Store * store, const StorePath * path, nix_get_string_callback callback, void * user_data);
@@
-nix_err nix_store_realise(
+nix_err nix_store_realise(
     nix_c_context * context,
     Store * store,
-    StorePath * path,
+    const StorePath * path,
     void * userdata,
     void (*callback)(void * userdata, const char * outname, const StorePath * out));

Also applies to: 192-199

src/libstore-c/nix_api_store.cc (1)

104-114: Consider const StorePath for real_path*

The path isn’t mutated; mirror const-correctness throughout.

-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_real_path(
+    nix_c_context * context, Store * store, const StorePath * path, nix_get_string_callback callback, void * user_data)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90e65c1 and d30a11c.

📒 Files selected for processing (13)
  • src/libexpr-tests/main.cc (1 hunks)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
  • src/libstore-c/nix_api_store_internal.h (2 hunks)
  • src/libstore-test-support/include/nix/store/tests/meson.build (1 hunks)
  • src/libstore-test-support/include/nix/store/tests/nix_api_store.hh (2 hunks)
  • src/libstore-test-support/include/nix/store/tests/test-main.hh (1 hunks)
  • src/libstore-test-support/meson.build (1 hunks)
  • src/libstore-test-support/test-main.cc (1 hunks)
  • src/libstore-tests/data/derivation/ca/self-contained.json (1 hunks)
  • src/libstore-tests/main.cc (1 hunks)
  • src/libstore-tests/meson.build (1 hunks)
  • src/libstore-tests/nix_api_store.cc (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/libstore-tests/meson.build
  • src/libstore-c/nix_api_store_internal.h
  • src/libstore-test-support/test-main.cc
  • src/libstore-test-support/meson.build
  • src/libstore-test-support/include/nix/store/tests/meson.build
  • src/libstore-tests/nix_api_store.cc
  • src/libstore-tests/main.cc
  • src/libstore-tests/data/derivation/ca/self-contained.json
🧰 Additional context used
🧬 Code graph analysis (4)
src/libexpr-tests/main.cc (2)
src/libstore-test-support/include/nix/store/tests/test-main.hh (1)
  • testMainForBuidingPre (11-11)
src/libstore-test-support/test-main.cc (2)
  • testMainForBuidingPre (10-45)
  • testMainForBuidingPre (10-10)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (33)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (255-255)
  • callback (279-279)
  • callback (299-299)
  • callback (320-320)
  • callback (340-341)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (275-292)
  • nix_store_drv_from_path (275-280)
  • nix_store_query_path_info (294-315)
  • nix_store_query_path_info (294-299)
  • nix_derivation_get_outputs (317-334)
  • nix_derivation_get_outputs (317-321)
  • nix_derivation_get_outputs_and_optpaths (336-362)
  • nix_derivation_get_outputs_and_optpaths (336-342)
  • nix_derivation_to_json (364-380)
  • nix_derivation_to_json (364-369)
  • nix_derivation_output_clone (382-385)
  • nix_derivation_output_clone (382-382)
  • nix_derivation_output_free (387-390)
  • nix_derivation_output_free (387-387)
src/libstore-test-support/include/nix/store/tests/nix_api_store.hh (1)
src/libstore-c/nix_api_store.cc (6)
  • nix_libstore_init (13-21)
  • nix_libstore_init (13-13)
  • nix_store_open (33-53)
  • nix_store_open (33-33)
  • nix_store_free (55-58)
  • nix_store_free (55-55)
src/libstore-c/nix_api_store.cc (1)
src/libstore/include/nix/store/store-api.hh (22)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • callback (425-425)
  • callback (453-453)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_x86_64-linux / manual
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (8)
src/libexpr-tests/main.cc (2)

3-3: Include looks correct.

Header path and namespace usage align with the new helper.


9-11: Fix inverted return check — currently exits on success and skips tests.

Return only on non‑zero.

-    auto res = testMainForBuidingPre(argc, argv);
-    if (!res)
-        return res;
+    auto res = testMainForBuidingPre(argc, argv);
+    if (res)
+        return res;
src/libstore-test-support/include/nix/store/tests/nix_api_store.hh (1)

71-73: Use ASSERT_NE instead of EXPECT_NE + assert

Avoid mixed non-fatal + hard abort. Use a single fatal assertion.

-            EXPECT_NE(store, nullptr) << "Could not open store: " << errMsg;
-            assert(store);
+            ASSERT_NE(store, nullptr) << "Could not open store: " << errMsg;
src/libstore-c/nix_api_store.cc (3)

94-102: LGTM: const-correct is_valid_path

Switch to const StorePath* matches store-api.hh and improves safety.


146-149: LGTM: realise now borrows StorePath in callback

Constructing a temporary StorePath per output and borrowing it during the callback aligns with other APIs.


198-217: Avoid dangling C-string in make_outputs; pass StorePath to callback

Match the header change and borrow a StorePath.

-nix_err nix_derivation_make_outputs(
-    nix_c_context * context,
-    Store * store,
-    const char * json,
-    void (*callback)(void * userdata, const char * output_name, const char * path),
-    void * userdata)
+nix_err nix_derivation_make_outputs(
+    nix_c_context * context,
+    Store * store,
+    const char * json,
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
+    void * userdata)
@@
-            if (callback) {
-                callback(userdata, output.first.c_str(), store->ptr->printStorePath(outPath).c_str());
-            }
+            if (callback) {
+                const StorePath tmp_path{outPath};
+                callback(userdata, output.first.c_str(), &tmp_path);
+            }
src/libstore-c/nix_api_store.h (2)

232-238: API hazard: callback receives ephemeral C-string; pass StorePath instead

Returning printStorePath(...).c_str() is short-lived and unsafe if retained. Align with other APIs by borrowing a StorePath in the callback.

-nix_err nix_derivation_make_outputs(
-    nix_c_context * context,
-    Store * store,
-    const char * json,
-    void (*callback)(void * userdata, const char * output_name, const char * path),
-    void * userdata);
+nix_err nix_derivation_make_outputs(
+    nix_c_context * context,
+    Store * store,
+    const char * json,
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
+    void * userdata);

Also update the doc comment to note the StorePath is borrowed only for the duration of the callback.


26-29: Typo breaks C API: wrong typedef alias for derivation output

Public alias must be nix_derivation_output, not nix_derivation_noutput.

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivation_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;

Comment on lines +26 to 31
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);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Destructor can throw and uses unqualified exists(); switch to error_code overloads

Throwing from a destructor risks std::terminate; also qualifies exists().

-        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::error_code ec;
+        if (std::filesystem::exists(std::filesystem::path{nixDir})) {
+            for (const auto & entry : std::filesystem::recursive_directory_iterator(
+                     nixDir, std::filesystem::directory_options::skip_permission_denied)) {
+                std::filesystem::permissions(
+                    entry.path(),
+                    std::filesystem::perms::owner_all,
+                    std::filesystem::perm_options::replace,
+                    ec);
+            }
+            std::filesystem::remove_all(nixDir, ec);
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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::error_code ec;
if (std::filesystem::exists(std::filesystem::path{nixDir})) {
for (const auto & entry : std::filesystem::recursive_directory_iterator(
nixDir, std::filesystem::directory_options::skip_permission_denied)) {
std::filesystem::permissions(
entry.path(),
std::filesystem::perms::owner_all,
std::filesystem::perm_options::replace,
ec);
}
std::filesystem::remove_all(nixDir, ec);
}
🤖 Prompt for AI Agents
In src/libstore-test-support/include/nix/store/tests/nix_api_store.hh around
lines 26-31, the destructor currently calls unqualified exists() and other
filesystem functions that can throw; change to the std::filesystem::exists
overload that accepts a std::error_code and fully-qualify the call
(std::filesystem::exists), then use the error_code overloads for
recursive_directory_iterator, permissions and remove_all so no exceptions
propagate from the destructor: create a std::error_code ec; check if
(std::filesystem::exists(std::filesystem::path{nixDir}, ec)) and only iterate
using std::filesystem::recursive_directory_iterator(nixDir,
std::filesystem::directory_options::none, ec) (or construct and check ec per
entry), call std::filesystem::permissions(path, perms, ec) and
std::filesystem::remove_all(nixDir, ec); handle or ignore ec values
appropriately to ensure the destructor cannot throw.

nix_store_free(store);
}

Store * store;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Initialize member to avoid deleting indeterminate pointer

store is uninitialized until init_local_store(); initialize to nullptr.

-    Store * store;
+    Store * store{nullptr};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Store * store;
Store * store{nullptr};
🤖 Prompt for AI Agents
In src/libstore-test-support/include/nix/store/tests/nix_api_store.hh around
line 92, the member "Store * store;" is left uninitialized which can lead to
deleting an indeterminate pointer; initialize it to nullptr (or = nullptr) in
the declaration so the pointer has a defined value until init_local_store() sets
it, and update any destructor/reset logic to safely handle the nullptr case if
needed.

* Call this for a GTest test suite that will including performing Nix
* builds, before running tests.
*/
int testMainForBuidingPre(int argc, char ** argv);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

🧩 Analysis chain

Fix typo in public symbol: “Buiding” → “Building”.

Public API name should be correct; best to rename now while churn is low.

-int testMainForBuidingPre(int argc, char ** argv);
+int testMainForBuildingPre(int argc, char ** argv);

Also update all call sites and the definition (e.g., src/libstore-test-support/test-main.cc). To find and verify:


🏁 Script executed:

#!/bin/bash
rg -n 'testMainForBuidingPre|testMainForBuildingPre' -C2

Length of output: 1317


Rename public symbol: testMainForBuidingPre → testMainForBuildingPre

Fix typo in public API — rename the declaration, definition and all call sites.

Files to update:

  • src/libstore-test-support/include/nix/store/tests/test-main.hh (line 11)
  • src/libstore-test-support/test-main.cc (line 10)
  • src/libstore-tests/main.cc (line 9)
  • src/libexpr-tests/main.cc (line 9)

Diff (header):
-int testMainForBuidingPre(int argc, char ** argv);
+int testMainForBuildingPre(int argc, char ** argv);

🤖 Prompt for AI Agents
In src/libstore-test-support/include/nix/store/tests/test-main.hh around line
11, the public function name has a typo; rename the declaration from
testMainForBuidingPre to testMainForBuildingPre and update the matching
definition and all call sites accordingly: change the definition in
src/libstore-test-support/test-main.cc (line ~10) and update callers in
src/libstore-tests/main.cc (line ~9) and src/libexpr-tests/main.cc (line ~9) so
they use testMainForBuildingPre(int argc, char **argv); ensure signatures match
exactly and rebuild to verify all references are fixed.

@github-actions github-actions bot temporarily deployed to pull request September 23, 2025 16:34 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/libstore-c/nix_api_store.h (2)

325-351: Clarify the callback parameter semantics.

The documentation states that "Path and result for the callback only exist for the lifetime of the call" but doesn't specify what format the path parameter takes. Based on the implementation, it appears to be a string representation of the path.

 /**
  * @brief Builds the paths, if they are a derivation then they get built.
  *
- * @note Path and result for the callback only exist for the lifetime of
- * the call. Result is a string containing the build result in JSON.
+ * @note Path (string) and result (JSON string) for the callback only exist for 
+ * the lifetime of the call.
  *
  * @param[out] context Optional, stores error information
  * @param[in] store nix store reference
  * @param[in] store_paths Pointer to list of nix store paths
  * @param[in] num_store_paths Number of nix store paths
  * @param[in] callback The callback to trigger for build results
  * @param[in] userdata User data to pass to the callback
+ * @return error code, NIX_OK on success.
  */

397-402: Fix parameter name mismatch in function declaration.

The parameter is declared as userdata but the documentation refers to it as user_data. This inconsistency should be resolved.

 nix_err nix_derivation_to_json(
     nix_c_context * context,
     const nix_derivation * drv,
     const Store * store,
     nix_get_string_callback callback,
-    void * userdata);
+    void * user_data);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d30a11c and 3375bb0.

📒 Files selected for processing (2)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (36)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (255-255)
  • callback (279-279)
  • callback (299-299)
  • callback (322-322)
  • callback (349-349)
  • callback (369-370)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (275-292)
  • nix_store_drv_from_path (275-280)
  • nix_store_query_path_info (294-315)
  • nix_store_query_path_info (294-299)
  • nix_store_build_paths (317-344)
  • nix_store_build_paths (317-323)
  • nix_derivation_get_outputs (346-363)
  • nix_derivation_get_outputs (346-350)
  • nix_derivation_get_outputs_and_optpaths (365-391)
  • nix_derivation_get_outputs_and_optpaths (365-371)
  • nix_derivation_to_json (393-409)
  • nix_derivation_to_json (393-398)
  • nix_derivation_output_clone (411-414)
  • nix_derivation_output_clone (411-411)
  • nix_derivation_output_free (416-419)
  • nix_derivation_output_free (416-416)
src/libstore-c/nix_api_store.cc (2)
src/libstore/include/nix/store/store-api.hh (22)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • callback (425-425)
  • callback (453-453)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
src/libstore/include/nix/store/realisation.hh (1)
  • outPath (80-83)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_x86_64-linux / manual
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (17)
src/libstore-c/nix_api_store.h (2)

29-29: Fix the typedef name.

The typedef has a typo - it should be nix_derivation_output not nix_derivatio_noutput. This is inconsistent with how the type is used throughout the rest of the file.

Apply this diff to fix the typedef:

-typedef struct nix_derivation_output nix_derivatio_noutput;
+typedef struct nix_derivation_output nix_derivation_output;

232-237: Address existing feedback: use StorePath instead of const char * for path parameter.

Switch to passing a borrowed StorePath to the callback (consistent with nix_store_realise) to prevent accidental retention of a dangling C-string.

-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
src/libstore-c/nix_api_store.cc (15)

94-94: LGTM!

The parameter is now correctly declared as const StorePath * path, which improves const-correctness and aligns with the function's read-only nature.


132-132: LGTM!

The callback signature has been updated to use const StorePath * instead of const char *, which provides better type safety and consistency with other APIs.


147-148: LGTM!

The implementation correctly creates a temporary StorePath object and passes its address to the callback, ensuring the callback receives a valid pointer for the duration of the call.


167-170: LGTM!

Simple and correct deallocation function for derivation wrappers.


177-180: LGTM!

Correct implementation of derivation cloning using the copy constructor.


182-196: LGTM!

The implementation correctly parses JSON, writes the derivation to the store, validates invariants, and follows the established error handling pattern.


198-221: Address existing feedback: use StorePath instead of const char * for path parameter.

Switch to passing a borrowed StorePath to the callback (consistent with nix_store_realise) to prevent accidental retention of a dangling C-string.

Apply this diff to match the corrected header signature:

-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
@@
-            if (callback) {
-                callback(userdata, output.first.c_str(), store->ptr->printStorePath(outPath).c_str());
-            }
+            if (callback) {
+                const StorePath tmp_path{outPath};
+                callback(userdata, output.first.c_str(), &tmp_path);
+            }

223-233: LGTM!

The function correctly writes the derivation to the store and returns a wrapped StorePath. The error handling follows the established pattern.


275-292: LGTM!

The implementation correctly retrieves a derivation from a path and provides it via callback using a temporary wrapper. The callback receives a valid pointer for the duration of the call.


294-315: LGTM!

The implementation correctly queries path info and handles the optional deriver by passing either a valid StorePath or nullptr to the callback.


346-363: LGTM!

The implementation correctly iterates over derivation outputs and provides each via callback using temporary wrappers.


365-391: LGTM!

The implementation correctly handles optional paths by passing either a valid StorePath or nullptr to the callback, maintaining consistency with other optional parameter patterns in the API.


411-414: LGTM!

Correct implementation of derivation output cloning.


416-419: LGTM!

Correct implementation of derivation output deallocation.


317-344: Avoid per-result JSON serialization in the callback loop (src/libstore-c/nix_api_store.cc:317-344)

  • Serializing with json.dump() for every result is potentially expensive for large result sets — batch results into a single JSON array or reuse/pre-allocate a buffer and reduce the number of dumps/callback calls.
  • Also verify string lifetime: passing .c_str() from temporaries (result.path.to_string(...).c_str() and json.dump().c_str()) is only safe if the callback copies the strings synchronously; if the callback may retain them, allocate persistent strings or change the API to accept/own std::string.

Comment on lines 393 to 409
nix_err nix_derivation_to_json(
nix_c_context * context,
const nix_derivation * drv,
const Store * store,
nix_get_string_callback callback,
void * userdata)
{
if (context)
context->last_err_code = NIX_OK;
try {
auto result = drv->drv.toJSON(store->ptr->config).dump();
if (callback) {
callback(result.data(), result.size(), userdata);
}
}
NIXC_CATCH_ERRS
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick

Fix parameter name to match header declaration.

The parameter should be named user_data to match the header declaration, not userdata.

 nix_err nix_derivation_to_json(
     nix_c_context * context,
     const nix_derivation * drv,
     const Store * store,
     nix_get_string_callback callback,
-    void * userdata)
+    void * user_data)
 {
     if (context)
         context->last_err_code = NIX_OK;
     try {
         auto result = drv->drv.toJSON(store->ptr->config).dump();
         if (callback) {
-            callback(result.data(), result.size(), userdata);
+            callback(result.data(), result.size(), user_data);
         }
     }
     NIXC_CATCH_ERRS
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
nix_err nix_derivation_to_json(
nix_c_context * context,
const nix_derivation * drv,
const Store * store,
nix_get_string_callback callback,
void * userdata)
{
if (context)
context->last_err_code = NIX_OK;
try {
auto result = drv->drv.toJSON(store->ptr->config).dump();
if (callback) {
callback(result.data(), result.size(), userdata);
}
}
NIXC_CATCH_ERRS
}
nix_err nix_derivation_to_json(
nix_c_context * context,
const nix_derivation * drv,
const Store * store,
nix_get_string_callback callback,
void * user_data)
{
if (context)
context->last_err_code = NIX_OK;
try {
auto result = drv->drv.toJSON(store->ptr->config).dump();
if (callback) {
callback(result.data(), result.size(), user_data);
}
}
NIXC_CATCH_ERRS
}
🤖 Prompt for AI Agents
In src/libstore-c/nix_api_store.cc around lines 393 to 409, the function
parameter is named "userdata" but the header declares "user_data"; rename the
parameter to "user_data" in the nix_derivation_to_json signature and update all
uses inside the function (e.g., the callback invocation) to pass user_data
instead of userdata so the implementation matches the header.

@github-actions github-actions bot temporarily deployed to pull request September 23, 2025 17:03 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/libstore-c/nix_api_store.h (4)

316-331: Doc polish: rename param to store_path and note possible NULL deriver.

Align param name with signature and clarify callback may receive NULL when there’s no deriver.

Apply:

  /**
   * @brief Queries for the nix store path info.
   *
   * @param[out] context Optional, stores error information
   * @param[in] store nix store reference
-  * @param[in] path A store path
+  * @param[in] store_path A store path
   * @param[in] userdata The data to pass to the callback
-  * @param[in] callback Called for when the path info is resolved
+  * @param[in] callback Called when the path info is resolved; derived_path may be NULL if there is no deriver
   */

345-352: Optional: consider passing StorePath * for path for consistency.

build_paths currently passes strings; other new callbacks use StorePath *. Consider switching for consistency and to avoid string lifetimes, or keep as-is since the doc notes the lifetime.

-    void (*callback)(void * userdata, const char * path, const char * result),
+    void (*callback)(void * userdata, const StorePath * path, const char * result),

239-247: Take derivation by const pointer in nix_add_derivation

derivation isn't mutated — change the parameter to const in both the header and the implementation.

--- a/src/libstore-c/nix_api_store.h
+++ b/src/libstore-c/nix_api_store.h
@@
-StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation);
+StorePath * nix_add_derivation(nix_c_context * context, Store * store, const nix_derivation * derivation);
--- a/src/libstore-c/nix_api_store.cc
+++ b/src/libstore-c/nix_api_store.cc
@@
-StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation)
+StorePath * nix_add_derivation(nix_c_context * context, Store * store, const nix_derivation * derivation)

192-198: Const-qualify the input path in nix_store_realise (header + implementation)

path is not modified; change the parameter to const StorePath * path in both src/libstore-c/nix_api_store.h and src/libstore-c/nix_api_store.cc (call sites need no changes).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3375bb0 and d777eec.

📒 Files selected for processing (1)
  • src/libstore-c/nix_api_store.h (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (36)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (255-255)
  • callback (279-279)
  • callback (299-299)
  • callback (322-322)
  • callback (349-349)
  • callback (369-370)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (275-292)
  • nix_store_drv_from_path (275-280)
  • nix_store_query_path_info (294-315)
  • nix_store_query_path_info (294-299)
  • nix_store_build_paths (317-344)
  • nix_store_build_paths (317-323)
  • nix_derivation_get_outputs (346-363)
  • nix_derivation_get_outputs (346-350)
  • nix_derivation_get_outputs_and_optpaths (365-391)
  • nix_derivation_get_outputs_and_optpaths (365-371)
  • nix_derivation_to_json (393-409)
  • nix_derivation_to_json (393-398)
  • nix_derivation_output_clone (411-414)
  • nix_derivation_output_clone (411-411)
  • nix_derivation_output_free (416-419)
  • nix_derivation_output_free (416-416)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_x86_64-linux / manual
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (11)
src/libstore-c/nix_api_store.h (11)

155-155: LGTM: const-correct is_valid_path parameter.


214-222: LGTM: nix_derivation_from_json API and docs.


254-254: LGTM: destructor for nix_derivation.


262-262: LGTM: clone semantics for nix_derivation.


298-315: LGTM: doc style and borrow semantics for nix_store_drv_from_path.


353-368: LGTM: outputs iterator borrows output objects.


369-387: LGTM: outputs+optpaths iterator with borrow semantics.


388-403: LGTM: callback-based JSON getter avoids dangling pointers.


410-418: LGTM: clone/free for nix_derivation_output.


232-238: Avoid ephemeral C-strings in callback; pass StorePath * instead.

Currently header exposes const char * path, but implementation passes printStorePath(...).c_str() from a temporary. Switch to borrowing a StorePath like other APIs.

Apply:

 nix_err nix_derivation_make_outputs(
     nix_c_context * context,
     Store * store,
     const char * json,
-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
     void * userdata);

Note: Implementation needs to wrap outPath in a StorePath tmp{outPath}; callback(userdata, name, &tmp);.


26-29: Fix typedef alias: should be nix_derivation_output (compile error).

The alias name is misspelled; prototypes below use nix_derivation_output as a typedef, so this breaks compilation.

Apply:

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivation_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;

@github-actions github-actions bot temporarily deployed to pull request September 23, 2025 23:07 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/libstore-c/nix_api_store.h (2)

298-308: Doc: add @return for error code.

Add return documentation for consistency with other APIs.

  /**
   * @brief Returns the derivation associated with the store path
   *
   * @note The callback borrows the Derivation only for the duration of the call.
   *
   * @param[out] context Optional, stores error information
   * @param[in] store The nix store
   * @param[in] path The nix store path
   * @param[in] callback The callback to call
   * @param[in] userdata The userdata to pass to the callback
+  * @return error code, NIX_OK on success.
   */

173-174: Const-correctness: make path parameter const.

The function does not mutate path; prefer const StorePath * (would require matching .cc change).

-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_real_path(
+    nix_c_context * context, Store * store, const StorePath * path, nix_get_string_callback callback, void * user_data);
src/libstore-c/nix_api_store.cc (1)

104-106: Const-correctness follow-up (if header changes): real_path arg can be const.

If you adopt the header const change, mirror it here.

-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_real_path(
+    nix_c_context * context, Store * store, const StorePath * path, nix_get_string_callback callback, void * user_data)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d777eec and 291e303.

📒 Files selected for processing (3)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
  • src/libstore-c/nix_api_store_internal.h (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/libstore-c/nix_api_store_internal.h
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (36)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (255-255)
  • callback (279-279)
  • callback (299-299)
  • callback (322-322)
  • callback (349-349)
  • callback (369-370)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (275-292)
  • nix_store_drv_from_path (275-280)
  • nix_store_query_path_info (294-315)
  • nix_store_query_path_info (294-299)
  • nix_store_build_paths (317-344)
  • nix_store_build_paths (317-323)
  • nix_derivation_get_outputs (346-363)
  • nix_derivation_get_outputs (346-350)
  • nix_derivation_get_outputs_and_optpaths (365-391)
  • nix_derivation_get_outputs_and_optpaths (365-371)
  • nix_derivation_to_json (393-405)
  • nix_derivation_to_json (393-394)
  • nix_derivation_output_clone (407-410)
  • nix_derivation_output_clone (407-407)
  • nix_derivation_output_free (412-415)
  • nix_derivation_output_free (412-412)
src/libstore-c/nix_api_store.cc (1)
src/libstore/include/nix/store/store-api.hh (26)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • callback (425-425)
  • callback (453-453)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
  • output (620-623)
  • output (620-620)
  • output (625-628)
  • output (625-625)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_x86_64-linux / manual
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (23)
src/libstore-c/nix_api_store.h (13)

155-155: LGTM: const-correctness for is_valid_path.

Signature updated to const StorePath *. Matches implementation and upstream API expectations.


192-198: LGTM: realise callback now returns StorePath wrapper.

Avoids passing ephemeral C-strings; consistent with other APIs.


246-246: LGTM: add_derivation returns StorePath wrapper.

Matches implementation and ownership model.


254-254: LGTM: derivation_free API.


262-262: Confirm clone semantics preserve store pointer.

Header is fine; ensure implementation copies the associated Store so downstream calls (e.g., to_json) don’t deref null store.


325-331: LGTM: query_path_info borrows StorePath in callback.


345-352: LGTM: build_paths API shape and lifetime note.


363-368: LGTM: get_outputs API borrows output wrapper.


380-387: LGTM: get_outputs_and_optpaths returns optional StorePath.


396-397: LGTM: derivation_to_json via string-callback.


405-413: LGTM: derivation_output clone/free APIs.


26-29: Blocker: typedef typo breaks API (unknown type ‘nix_derivation_output’).

Forward-declares the wrong alias (nix_derivation_noutput) while the API uses nix_derivation_output*. This will not compile.

Apply:

-/** @brief Nix Derivation Output */
-typedef struct nix_derivation_output nix_derivation_noutput;
+/** @brief Nix Derivation Output */
+typedef struct nix_derivation_output nix_derivation_output;

232-238: Avoid ephemeral C-string; pass StorePath in callback.

Current signature exposes const char * path that’s built from a temporary; switch to borrowed const StorePath * like other APIs to prevent dangling pointers.

Proposed header change:

-nix_err nix_derivation_make_outputs(
-    nix_c_context * context,
-    Store * store,
-    const char * json,
-    void (*callback)(void * userdata, const char * output_name, const char * path),
-    void * userdata);
+nix_err nix_derivation_make_outputs(
+    nix_c_context * context,
+    Store * store,
+    const char * json,
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
+    void * userdata);

I’ve included the matching .cc fix in that file’s comment.

src/libstore-c/nix_api_store.cc (10)

94-102: LGTM: is_valid_path matches new const StorePath * signature.


132-149: LGTM: realise now passes StorePath wrapper to callback.

Borrowed StorePath on the stack is fine for callback-scoped use.


182-196: LGTM: from_json writes/validates, wraps with store.


223-233: LGTM: add_derivation writes and returns StorePath wrapper.


294-315: LGTM: query_path_info borrows optional deriver path.


317-344: LGTM with note: JSON/result strings are callback-scoped.

Header documents lifetime; usage aligns.

Please confirm downstream callbacks don’t retain these pointers after return.


346-363: LGTM: get_outputs borrows per-output wrapper.


365-391: LGTM: get_outputs_and_optpaths borrows output/path, handles null.


393-405: LGTM: derivation_to_json returns via string-callback.


198-221: Avoid dangling C-string in make_outputs; return StorePath.

printStorePath(...).c_str() points to a temporary. Align with other APIs and pass a borrowed StorePath.

-nix_err nix_derivation_make_outputs(
+nix_err nix_derivation_make_outputs(
     nix_c_context * context,
     Store * store,
     const char * json,
-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
     void * userdata)
 {
@@
-        for (auto & output : drv.outputs) {
+        for (auto & output : drv.outputs) {
             nix::Hash h = hashesModulo.hashes.at(output.first);
             auto outPath = store->ptr->makeOutputPath(output.first, h, drv.name);
 
             if (callback) {
-                callback(userdata, output.first.c_str(), store->ptr->printStorePath(outPath).c_str());
+                const StorePath tmp_path{outPath};
+                callback(userdata, output.first.c_str(), &tmp_path);
             }
         }
     }

@github-actions github-actions bot temporarily deployed to pull request September 23, 2025 23:14 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
src/libstore-c/nix_api_store.h (5)

192-198: Realise callback now returns StorePath — clarify borrow/lifetime in docs.*

Please add a brief note that the StorePath pointer is only valid during the callback and that outname is only valid for the duration of the call.


214-221: Creation from JSON LGTM; document ownership.

Consider adding “Free with nix_derivation_free” to the docblock to make ownership explicit.


239-247: Make derivation param const and document return ownership.

The function doesn’t mutate the derivation; mark it const and note the caller must free the returned StorePath.

Header:

-StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation);
+StorePath * nix_add_derivation(nix_c_context * context, Store * store, const nix_derivation * derivation);

Implementation (src/libstore-c/nix_api_store.cc, Lines 222-232):

-StorePath * nix_add_derivation(nix_c_context * context, Store * store, nix_derivation * derivation)
+StorePath * nix_add_derivation(nix_c_context * context, Store * store, const nix_derivation * derivation)

316-331: Clarify nullability and standardize parameter order.

  • Document that derived_path may be NULL if there is no deriver (matches implementation).
  • For API consistency with most functions here, consider using (callback, user_data) ordering.

Header:

- * @param[in] userdata The data to pass to the callback
- * @param[in] callback Called for when the path info is resolved
+ * @param[in] callback Called when the path info is resolved. The derived_path can be NULL if absent.
+ * @param[in] userdata The data to pass to the callback
@@
-nix_err nix_store_query_path_info(
+nix_err nix_store_query_path_info(
@@
-    void * userdata,
-    void (*callback)(void * userdata, const StorePath * derived_path));
+    void (*callback)(void * userdata, const StorePath * derived_path),
+    void * userdata);

Implementation (src/libstore-c/nix_api_store.cc, Lines 293-314):

-nix_err nix_store_query_path_info(
+nix_err nix_store_query_path_info(
@@
-    void * userdata,
-    void (*callback)(void * userdata, const StorePath * derived_path))
+    void (*callback)(void * userdata, const StorePath * derived_path),
+    void * userdata)

332-352: Prefer passing StorePath for ‘path’ to avoid ephemeral strings.*

Current callback receives const char * path built via to_string(...).c_str(), whose lifetime ends after the call; while documented, this is easy to misuse. Passing a StorePath pointer aligns with other APIs and is safer.

Header:

- * @param[in] callback The callback to trigger for build results
+ * @param[in] callback The callback to trigger for build results. The path is borrowed and only valid during the call.
@@
-    void (*callback)(void * userdata, const char * path, const char * result),
+    void (*callback)(void * userdata, const StorePath * path, const char * result),

Implementation (src/libstore-c/nix_api_store.cc, Lines 316-343):

-                callback(userdata, result.path.to_string(store->ptr->config).c_str(), json.dump().c_str());
+                const StorePath tmp{result.path};
+                callback(userdata, &tmp, json.dump().c_str());
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 291e303 and e6d6dfd.

📒 Files selected for processing (1)
  • src/libstore-c/nix_api_store.h (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (36)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (255-255)
  • callback (279-279)
  • callback (299-299)
  • callback (322-322)
  • callback (349-349)
  • callback (369-370)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (275-292)
  • nix_store_drv_from_path (275-280)
  • nix_store_query_path_info (294-315)
  • nix_store_query_path_info (294-299)
  • nix_store_build_paths (317-344)
  • nix_store_build_paths (317-323)
  • nix_derivation_get_outputs (346-363)
  • nix_derivation_get_outputs (346-350)
  • nix_derivation_get_outputs_and_optpaths (365-391)
  • nix_derivation_get_outputs_and_optpaths (365-371)
  • nix_derivation_to_json (393-405)
  • nix_derivation_to_json (393-394)
  • nix_derivation_output_clone (407-410)
  • nix_derivation_output_clone (407-407)
  • nix_derivation_output_free (412-415)
  • nix_derivation_output_free (412-412)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build_aarch64-darwin / manual
  • GitHub Check: build_aarch64-darwin / test
  • GitHub Check: build_x86_64-linux / test
🔇 Additional comments (7)
src/libstore-c/nix_api_store.h (7)

26-29: Typedefs LGTM; earlier typo fixed.

The public aliases look correct and consistent.


155-155: Const-correctness LGTM.

Signature matches the implementation and improves safety.


353-368: Outputs enumeration LGTM.

Borrowing semantics are documented; implementation constructs a temporary per-callback as expected.


369-387: Outputs+optpaths LGTM.

Nullability of path is handled and documented; borrowing semantics are clear.


388-398: Callback-style JSON getter LGTM; resolves dangling return risk.

This replaces the unsafe const char * return with a safe callback pattern.


399-413: Derivation output clone/free LGTM.

Ownership semantics are clear and consistent with other wrappers.


223-238: Avoid ephemeral C-strings in callback; pass StorePath instead.

The implementation calls callback with printStorePath(...).c_str(), which is a temporary. Switch the callback to accept a StorePath pointer to avoid dangling pointers and align with other APIs.

Apply this header diff:

- * @param[in] callback Called for every output to provide the output path.
+ * @param[in] callback Called for every output to provide the output path (borrowed; valid only during the call).
@@
-nix_err nix_derivation_make_outputs(
+nix_err nix_derivation_make_outputs(
@@
-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),

And update the implementation (src/libstore-c/nix_api_store.cc, Lines 197-220):

-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
@@
-            if (callback) {
-                callback(userdata, output.first.c_str(), store->ptr->printStorePath(outPath).c_str());
-            }
+            if (callback) {
+                const StorePath tmp{outPath};
+                callback(userdata, output.first.c_str(), &tmp);
+            }

@RossComputerGuy RossComputerGuy force-pushed the RossComputerGuy/feat/expose-drvfrompath branch from e6d6dfd to 284a700 Compare September 23, 2025 23:23
@RossComputerGuy RossComputerGuy force-pushed the RossComputerGuy/feat/expose-drvfrompath branch from 284a700 to b2fff15 Compare September 23, 2025 23:24
@github-actions github-actions bot temporarily deployed to pull request September 23, 2025 23:27 Inactive
@github-actions github-actions bot temporarily deployed to pull request September 26, 2025 21:14 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (6)
src/libstore-c/nix_api_store_internal.h (1)

16-25: Clarify ownership/borrowing of Store in nix_derivation.
Callers must ensure Store outlives any nix_derivation instances; add a brief note to prevent UAFs.

Apply this diff to annotate intent:

 struct nix_derivation
 {
     nix::Derivation drv;
-    Store * store;
+    // Borrowed; must outlive this wrapper.
+    Store * store;
 };
src/libstore-c/nix_api_store.h (3)

192-198: Document borrowed lifetime and make input path const in realise.
The callback receives a pointer to a stack-allocated StorePath; document borrowing. Also make the input path const.

 /**
  * @brief Realise a Nix store path
  *
  * Blocking, calls callback once for each realised output.
  *
+ * @note The callback borrows the output StorePath only for the duration of the call.
+ *
  * @note When working with expressions, consider using e.g. nix_string_realise to get the output. `.drvPath` may not be
  * accurate or available in the future. See https://github.com/NixOS/nix/issues/6507
  *
  * @param[out] context Optional, stores error information
  * @param[in] store Nix Store reference
  * @param[in] path Path to build
  * @param[in] userdata data to pass to every callback invocation
  * @param[in] callback called for every realised output
  */
 nix_err nix_store_realise(
     nix_c_context * context,
     Store * store,
-    StorePath * path,
+    const StorePath * path,
     void * userdata,
     void (*callback)(void * userdata, const char * outname, const StorePath * out));

Also applies to: 179-191


298-315: Doc: callback borrows both derivation and its Store.
Header says derivation is borrowed; explicitly mention the associated Store is borrowed as well to prevent misuse.

- * @note The callback borrows the Derivation only for the duration of the call.
+ * @note The callback borrows the Derivation and its associated Store only for the duration of the call.

325-331: Standardize parameter order and fix doc param name in query_path_info.
Other APIs use (callback, user_data). Also the doc uses “path” but the parameter is “store_path”.

 /**
  * @brief Queries for the nix store path info.
  *
  * @param[out] context Optional, stores error information
  * @param[in] store nix store reference
- * @param[in] path A store path
- * @param[in] userdata The data to pass to the callback
- * @param[in] callback Called for when the path info is resolved
+ * @param[in] store_path A store path
+ * @param[in] callback Called for when the path info is resolved
+ * @param[in] user_data The data to pass to the callback
  */
 nix_err nix_store_query_path_info(
     nix_c_context * context,
     Store * store,
     const StorePath * store_path,
-    void * userdata,
-    nix_get_string_callback callback);
+    nix_get_string_callback callback,
+    void * user_data);

Matching .cc fix provided in nix_api_store.cc comment.

src/libstore-c/nix_api_store.cc (2)

132-133: Realise: pass borrowed StorePath; also make input path const.
The callback receives a stack-allocated StorePath; safe if callers don’t retain it. Align the function signature with const input.

-nix_err nix_store_realise(
+nix_err nix_store_realise(
     nix_c_context * context,
     Store * store,
-    StorePath * path,
+    const StorePath * path,
     void * userdata,
     void (*callback)(void * userdata, const char *, const StorePath *))
@@
-                for (const auto & [outputName, realisation] : result.builtOutputs) {
-                    StorePath p{realisation.outPath};
-                    callback(userdata, outputName.c_str(), &p);
+                for (const auto & [outputName, realisation] : result.builtOutputs) {
+                    const StorePath p{realisation.outPath};
+                    callback(userdata, outputName.c_str(), &p);
                 }

Also applies to: 147-149


294-311: Standardize parameter order for query_path_info (callback before user_data).
Matches the majority of APIs and reduces cognitive overhead.

-nix_err nix_store_query_path_info(
-    nix_c_context * context,
-    Store * store,
-    const StorePath * store_path,
-    void * userdata,
-    nix_get_string_callback callback)
+nix_err nix_store_query_path_info(
+    nix_c_context * context,
+    Store * store,
+    const StorePath * store_path,
+    nix_get_string_callback callback,
+    void * user_data)
 {
@@
-        if (callback) {
+        if (callback) {
             auto result = info->toJSON(store->ptr->config, true, nix::HashFormat::Nix32).dump();
-            callback(result.data(), result.size(), userdata);
+            callback(result.data(), result.size(), user_data);
         }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6d6dfd and d7ce101.

📒 Files selected for processing (3)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
  • src/libstore-c/nix_api_store_internal.h (2 hunks)
🔇 Additional comments (9)
src/libstore-c/nix_api_store_internal.h (1)

4-4: LGTM: necessary include for derivation types.
Brings in nix::Derivation and nix::DerivationOutput; required for the new wrappers.

src/libstore-c/nix_api_store.h (5)

26-29: LGTM: public derivation wrapper typedefs.
Consistent with the internal wrappers.


155-155: LGTM: const-correctness for is_valid_path.
Prevents accidental mutation.


246-263: LGTM: add/clone/free for derivations.
Clone preserves the Store pointer (per implementation); good.


345-352: LGTM: outputs iteration, JSON serialization, and output lifetimes.
Borrowing semantics are documented; API surface is coherent.

Also applies to: 363-387, 396-413


214-238: Avoid dangling C-strings in make_outputs; pass StorePath instead.
Current signature exposes a transient C-string from printStorePath; align with other APIs that pass StorePath.

 nix_err nix_derivation_make_outputs(
     nix_c_context * context,
     Store * store,
     const char * json,
-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
     void * userdata);

Matching .cc fix provided in nix_api_store.cc comment.

src/libstore-c/nix_api_store.cc (3)

94-102: LGTM: const-correct is_valid_path.
Straight passthrough to nix::Store::isValidPath.


167-170: LGTM: derivation lifecycle, path/build helpers, and JSON I/O.
Implementations are consistent with the header and follow the borrowing pattern.

Also applies to: 177-181, 182-196, 223-233, 275-292, 313-340, 342-359, 361-387, 389-401, 403-411


198-221: Fix: avoid dangling C-strings in make_outputs; pass StorePath instead.
printStorePath(...).c_str() is a temporary. Mirror realise/closure patterns by passing a borrowed StorePath.

-nix_err nix_derivation_make_outputs(
-    nix_c_context * context,
-    Store * store,
-    const char * json,
-    void (*callback)(void * userdata, const char * output_name, const char * path),
-    void * userdata)
+nix_err nix_derivation_make_outputs(
+    nix_c_context * context,
+    Store * store,
+    const char * json,
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
+    void * userdata)
 {
@@
-        for (auto & output : drv.outputs) {
+        for (auto & output : drv.outputs) {
             nix::Hash h = hashesModulo.hashes.at(output.first);
             auto outPath = store->ptr->makeOutputPath(output.first, h, drv.name);
 
             if (callback) {
-                callback(userdata, output.first.c_str(), store->ptr->printStorePath(outPath).c_str());
+                const StorePath tmp_path{outPath};
+                callback(userdata, output.first.c_str(), &tmp_path);
             }
         }

Update header declaration accordingly (see nix_api_store.h comment).

@github-actions github-actions bot temporarily deployed to pull request September 30, 2025 21:42 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
src/libstore-c/nix_api_store.h (1)

230-236: Critical: callback path must not be a temporary C-string

Change callback to take a borrowed StorePath (consistent with other APIs) to avoid dangling pointers.

Header diff (see matching .cc change in its comment):

-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
src/libstore-c/nix_api_store.cc (1)

198-221: Bug: callback receives pointer to temporary C-string (use StorePath or string-callback)

printStorePath(...).c_str() returns a pointer to a temporary; callers might retain it, leading to UAF. Align with other APIs by passing a borrowed StorePath.

Apply these changes (header and impl):

In src/libstore-c/nix_api_store.h:

-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),

In src/libstore-c/nix_api_store.cc:

-            if (callback) {
-                callback(userdata, output.first.c_str(), store->ptr->printStorePath(outPath).c_str());
-            }
+            if (callback) {
+                const StorePath tmp_path{outPath};
+                callback(userdata, output.first.c_str(), &tmp_path);
+            }
🧹 Nitpick comments (10)
src/libstore-c/nix_api_store_internal.h (1)

16-20: nix_derivation holds a raw Store — clarify lifetime or hold a strong ref*

Raw pointer risks dangling if Store is freed before the derivation. Either:

  • Document that nix_derivation borrows Store and Store must outlive it (minimal), or
  • Store a nix::refnix::Store in nix_derivation to enforce lifetime.

Example (if choosing strong ref):

-struct nix_derivation
-{
-    nix::Derivation drv;
-    Store * store;
-};
+struct nix_derivation
+{
+    nix::Derivation drv;
+    // Prefer strong reference to avoid dangling pointers.
+    nix::ref<nix::Store> store_ref;
+};

If you keep Store*, please add explicit borrow semantics in the public header near the typedef and constructors.

src/libstore-c/nix_api_store.cc (2)

147-149: Borrowed StorePath in realise callback — add header note

Passing a pointer to a stack-allocated StorePath is fine if the header documents that the pointer is only valid during the callback. Please add that note to nix_store_realise in the header for clarity.


313-340: build_paths: temporaries passed as const char; prefer StorePath/string-callback*

Even with the doc note, passing result.path.to_string(...).c_str() and json.dump().c_str() risks misuse. Consider:

  • Passing a StorePath for the path, and
  • Delivering the JSON via nix_get_string_callback.

Example:

-    void (*callback)(void * userdata, const char * path, const char * result),
+    void (*callback)(void * userdata, const StorePath * path, const char * result),
@@
-                callback(userdata, result.path.to_string(store->ptr->config).c_str(), json.dump().c_str());
+                const StorePath tmp{result.path};
+                callback(userdata, &tmp, json.dump().c_str());
src/libstore-c/nix_api_store.h (7)

26-27: Add borrow-lifetime note for nix_derivation

Please document that nix_derivation borrows its Store; the Store must outlive the derivation instance, unless you switch to holding a strong reference internally.

Proposed doc:

 /** @brief Nix Derivation */
 typedef struct nix_derivation nix_derivation;
+/** @note A nix_derivation borrows its Store; ensure the Store outlives the derivation. */

190-196: Realise callback lifetime note

Please add “The out StorePath pointer is only valid for the duration of the callback” to match actual usage in the implementation.

Suggested doc tweak:

- * @param[in] callback called for every realised output
+ * @param[in] callback called for every realised output. The passed StorePath is borrowed
+ *                    and valid only for the duration of the callback.

212-220: from_json: clarify Store ownership semantics

Document that the returned nix_derivation borrows the Store passed in; the Store must remain alive until nix_derivation_free.


244-245: Add note about freeing returned StorePath

Mention that the returned StorePath must be freed with nix_store_path_free.

- * @param[in] derivation nix_derivation to insert into the given store.
+ * @param[in] derivation nix_derivation to insert into the given store.
+ * @return owned StorePath of the derivation; free with nix_store_path_free().

252-252: Doc nit: mismatched quote

Use consistent quoting in the brief.

- * @brief Deallocate a `nix_derivation'
+ * @brief Deallocate a `nix_derivation`

343-350: build_paths: consider safer callback types

Even with the note, prefer passing a StorePath for the path or using nix_get_string_callback to eliminate temporary C-string risks.


378-379: to_json: add note about Store lifetime

Since implementation uses drv->store->ptr->config, document that drv must have an associated Store that is still alive.

- * @param[in] drv The derivation
+ * @param[in] drv The derivation (must be associated with a live Store)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7ce101 and 0d30905.

📒 Files selected for processing (3)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
  • src/libstore-c/nix_api_store_internal.h (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (28)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (255-255)
  • callback (279-279)
  • callback (318-318)
  • callback (346-347)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (275-292)
  • nix_store_drv_from_path (275-280)
  • nix_store_query_path_info (294-311)
  • nix_store_query_path_info (294-299)
  • nix_store_build_paths (313-340)
  • nix_store_build_paths (313-319)
  • nix_derivation_get_outputs_and_optpaths (342-366)
  • nix_derivation_get_outputs_and_optpaths (342-348)
  • nix_derivation_to_json (368-380)
  • nix_derivation_to_json (368-369)
src/libstore-c/nix_api_store.cc (2)
src/libstore/include/nix/store/store-api.hh (22)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • callback (425-425)
  • callback (453-453)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
src/libstore/include/nix/store/realisation.hh (1)
  • outPath (80-83)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (13)
src/libstore-c/nix_api_store_internal.h (1)

4-4: Include looks correct

Including nix/store/derivations.hh here is appropriate for nix::Derivation usage.

src/libstore-c/nix_api_store.cc (9)

94-102: Const-correct path check

Changing to const StorePath * is right and consistent with usage.


167-171: Derivation free

Destructor is correct.


177-181: Derivation clone preserves Store pointer

Good fix preserving the associated store pointer. Please ensure header docs mention that the cloned object still borrows the same Store lifetime.


182-196: from_json: invariants check is good

Parsing, computing drvPath read-only, and checkInvariants look correct.


223-233: nix_add_derivation OK

Writes derivation and returns StorePath wrapper; looks good.


275-292: drv_from_path wrapper

Constructing a temporary nix_derivation with matching store is correct; borrowed for callback duration.


294-312: query_path_info JSON via callback

Looks correct and consistent.


342-366: outputs_and_optpaths

API shape and borrowed StorePath usage look good.


368-380: to_json via drv->store config

OK, consistent with wrapper design.

src/libstore-c/nix_api_store.h (3)

153-154: Const-correctness improvement

Good change to const StorePath *.


260-260: Clone API fine

Signature is fine; ensure callers understand it borrows the same Store as the source.


296-313: Doc style already fixed; looks good

Doxygen-style block and params are present.

@RossComputerGuy RossComputerGuy force-pushed the RossComputerGuy/feat/expose-drvfrompath branch from 0d30905 to ad566a9 Compare September 30, 2025 23:08
@github-actions github-actions bot temporarily deployed to pull request September 30, 2025 23:10 Inactive
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/libstore-c/nix_api_store.h (1)

221-235: Callback uses const char * for path parameter.

The callback signature (line 234) uses const char * path which is consistent with the implementation, but creates the dangling pointer risk discussed in the .cc file review (lines 198-221).

See the review comment on src/libstore-c/nix_api_store.cc lines 198-221 for the detailed analysis and suggested fix.

src/libstore-c/nix_api_store.cc (1)

198-221: Potential dangling pointer in callback.

Line 216 passes store->ptr->printStorePath(outPath).c_str() to the callback. While the temporary survives the immediate call, if the callback stores this pointer for later use, it will dangle.

Past review comments suggested using const StorePath * instead of const char *. If this was intentional (for API simplicity), document that the path string is only valid during the callback:

 /**
  * @brief Hashes the derivation and gives the output paths
  *
+ * @note The path string passed to the callback is only valid for the duration
+ * of the callback invocation. Callers must copy it if they need to retain it.
+ *
  * @param[in] context Optional, stores error information.

Alternatively, apply the safer API pattern used in other functions:

 nix_err nix_derivation_make_outputs(
     nix_c_context * context,
     Store * store,
     const char * json,
-    void (*callback)(void * userdata, const char * output_name, const char * path),
+    void (*callback)(void * userdata, const char * output_name, const StorePath * path),
     void * userdata)
 {
     // ... existing code ...
             if (callback) {
-                callback(userdata, output.first.c_str(), store->ptr->printStorePath(outPath).c_str());
+                const StorePath tmp{outPath};
+                callback(userdata, output.first.c_str(), &tmp);
             }

This would require updating both the header (line 234) and implementation.

🧹 Nitpick comments (7)
src/libstore-c/nix_api_store.cc (3)

313-340: Document temporary string lifetimes in callback.

Lines 335 passes temporary C-strings (from .c_str()) to the callback. While these survive the immediate call, storing them leads to use-after-free.

Add documentation clarifying the string lifetimes:

 /**
  * @brief Builds the paths, if they are a derivation then they get built.
  *
- * @note Path and result for the callback only exist for the lifetime of
- * the call. Result is a string containing the build result in JSON.
+ * @note The path and result strings passed to the callback are only valid
+ * for the duration of the callback invocation. Callers must copy them
+ * if they need to retain the data.
+ * Result is a string containing the build result in JSON.

This matches the pattern in other callback-based APIs and makes the contract explicit.


127-154: Document StorePath lifetime in header

Augment the @param callback doc (around line 188–189) to note that the StorePath *out pointer is borrowed and only valid during the callback invocation.


182-196: Add explanatory comment for read-only derivation path

Explain that the readOnly = true flag bypasses adding to the store and only computes the fixed-output path for validation:

src/libstore-c/nix_api_store.cc:189

-        auto drvPath = nix::writeDerivation(*store->ptr, drv, nix::NoRepair, /* read only */ true);
+        // In read-only mode we compute the fixed-output (CA) path for validation without writing to the store
+        // (writeDerivation returns a path derived from the derivation contents)
+        auto drvPath = nix::writeDerivation(*store->ptr, drv, nix::NoRepair, /* read only */ true);
src/libstore-c/nix_api_store.h (3)

190-195: Document borrowed StorePath in callback.

The callback signature correctly uses const StorePath * (line 195), but the documentation should explicitly state that the StorePath is borrowed and only valid during the callback.

 /**
  * @brief Realise a Nix store path
  *
  * Blocking, calls callback once for each realised output.
  *
+ * @note The StorePath passed to the callback is borrowed and only valid
+ * for the duration of the callback invocation.
+ *
  * @note When working with expressions, consider using e.g. nix_string_realise to get the output. `.drvPath` may not be

246-252: Document Store lifetime requirements.

The documentation should clarify that freeing a derivation does not affect the associated Store, and that the Store must remain valid for all derivations that reference it.

 /**
- * @brief Deallocate a `nix_derivation'
+ * @brief Deallocate a `nix_derivation`
  *
+ * @note This does not free the associated Store. The Store must outlive
+ * all derivations that reference it.
+ *
  * Does not fail.
  * @param[in] drv the derivation to free
  */

254-260: Document Store sharing in clone.

The clone shares the same Store pointer as the original. Document this to clarify lifetime requirements.

 /**
  * @brief Copy a `nix_derivation`
  *
+ * @note The cloned derivation shares the same Store reference as the original.
+ * The Store must remain valid for both the original and all clones.
+ *
  * @param[in] d the derivation to copy
  * @return a new `nix_derivation`
  */
src/libstore-c/nix_api_store_internal.h (1)

16-20: Document Store lifetime requirements for nix_derivation.

The nix_derivation struct holds a borrowed Store * pointer. Users must ensure the Store outlives any nix_derivation that references it, otherwise dereferencing drv->store leads to use-after-free.

Consider adding this comment to the internal header:

 struct nix_derivation
 {
     nix::Derivation drv;
+    // Borrowed pointer; the Store must outlive this nix_derivation.
+    // Ownership remains with the caller who provided the Store.
     Store * store;
 };

The public API header currently lacks any mention of this requirement. To verify, you can run:

rg -n -C3 -P "(outlive|lifetime|must remain valid|borrowed)" src/libstore-c/nix_api_store.h

No matches for Store indicate the lifetime contract isn’t documented there. Add a corresponding note in nix_api_store.h near the functions that produce or accept nix_derivation.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d30905 and ad566a9.

📒 Files selected for processing (3)
  • src/libstore-c/nix_api_store.cc (5 hunks)
  • src/libstore-c/nix_api_store.h (5 hunks)
  • src/libstore-c/nix_api_store_internal.h (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/libstore-c/nix_api_store.h (1)
src/libstore-c/nix_api_store.cc (28)
  • nix_store_is_valid_path (94-102)
  • nix_store_is_valid_path (94-94)
  • callback (132-132)
  • callback (202-202)
  • callback (255-255)
  • callback (279-279)
  • callback (318-318)
  • callback (346-346)
  • nix_derivation_from_json (182-196)
  • nix_derivation_from_json (182-182)
  • nix_derivation_make_outputs (198-221)
  • nix_derivation_make_outputs (198-203)
  • nix_add_derivation (223-233)
  • nix_add_derivation (223-223)
  • nix_derivation_free (167-170)
  • nix_derivation_free (167-167)
  • nix_derivation_clone (177-180)
  • nix_derivation_clone (177-177)
  • nix_store_drv_from_path (275-292)
  • nix_store_drv_from_path (275-280)
  • nix_store_query_path_info (294-311)
  • nix_store_query_path_info (294-299)
  • nix_store_build_paths (313-340)
  • nix_store_build_paths (313-319)
  • nix_derivation_get_outputs_and_optpaths (342-365)
  • nix_derivation_get_outputs_and_optpaths (342-347)
  • nix_derivation_to_json (367-379)
  • nix_derivation_to_json (367-368)
src/libstore-c/nix_api_store.cc (2)
src/libstore/include/nix/store/store-api.hh (24)
  • path (318-318)
  • path (340-340)
  • path (346-346)
  • path (353-353)
  • path (357-357)
  • path (394-394)
  • path (400-400)
  • path (405-405)
  • path (415-415)
  • path (451-451)
  • path (461-464)
  • path (461-461)
  • path (474-477)
  • path (474-474)
  • path (482-482)
  • path (490-490)
  • callback (425-425)
  • callback (453-453)
  • drvPath (697-697)
  • drvPath (772-772)
  • drvPath (777-777)
  • drvPath (782-782)
  • info (535-539)
  • info (762-762)
src/libstore/include/nix/store/realisation.hh (1)
  • outPath (80-83)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_x86_64-linux / vm_tests_smoke
  • GitHub Check: build_x86_64-linux / test
  • GitHub Check: build_x86_64-linux / manual
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (17)
src/libstore-c/nix_api_store.cc (8)

94-102: LGTM: const-correctness improvement.

The parameter is now correctly marked const since the path is not modified.


167-170: LGTM: proper resource cleanup.

Correctly frees the nix_derivation without touching the borrowed Store pointer.


177-180: LGTM: clone now preserves Store pointer.

The clone correctly copies both drv and store. Both the original and clone share the same borrowed Store pointer, which is the expected behavior.


223-233: LGTM: correctly writes derivation to store.

This function actually writes the derivation (unlike nix_derivation_from_json which uses read-only mode) and returns the resulting store path.


275-292: LGTM: derivation wrapper now includes Store.

The temporary wrapper (line 287) correctly includes both drv and store, fixing the issue from past reviews. The callback receives a borrowed derivation valid only during its execution.


294-311: LGTM: correct string callback pattern.

The JSON string is created as a local variable and passed to the callback via data() and size(). The string remains valid for the callback duration.


342-365: LGTM: proper handling of optional paths.

Correctly creates a temporary StorePath wrapper when a path exists (line 356) and passes nullptr when absent (line 359). The callback receives borrowed pointers valid only during the call.


367-379: No parameter name mismatch; userdata is consistent in header and implementation.

src/libstore-c/nix_api_store.h (9)

26-27: LGTM: opaque type declaration.

Standard C API pattern for opaque types.


153-153: LGTM: const-qualified parameter.

Correctly marks the path parameter as const since it's not modified.


212-219: LGTM: function declaration.

Declaration is clear and matches the implementation.


237-244: LGTM: clear API declaration.

Documentation and signature are clear and match the implementation.


296-312: LGTM: well-documented API.

The documentation correctly uses Doxygen format and notes that the derivation is borrowed during the callback.


314-328: LGTM: documentation matches parameter.

Parameter name in documentation (line 319) correctly matches the function parameter (line 326).


330-349: Documentation mentions temporary strings.

The note at lines 333-334 correctly states that strings are temporary, though the wording could be more explicit (see review comment on implementation in .cc file lines 313-340).


351-367: LGTM: accurate documentation.

Documentation correctly describes that the callback receives output names and optional store paths, not full DerivationOutput structures.


369-378: Verify implementation parameter name.

Header uses userdata (line 378). Verify this matches the implementation (see review comment on src/libstore-c/nix_api_store.cc lines 367-379).

@RossComputerGuy RossComputerGuy added this pull request to the merge queue Oct 1, 2025
Merged via the queue into main with commit 1f8e871 Oct 1, 2025
35 checks passed
@RossComputerGuy RossComputerGuy deleted the RossComputerGuy/feat/expose-drvfrompath branch October 1, 2025 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants