Skip to content

Add store and util versions getter, add util init#12

Merged
RossComputerGuy merged 1 commit into
integrationfrom
feat/more-functions
Feb 25, 2026
Merged

Add store and util versions getter, add util init#12
RossComputerGuy merged 1 commit into
integrationfrom
feat/more-functions

Conversation

@RossComputerGuy
Copy link
Copy Markdown
Member

@RossComputerGuy RossComputerGuy commented Feb 23, 2026

Binds:

  • nix_libutil_init
  • nix_version_get
  • nix_store_get_version

These make it useful to ensure libutil is initialized and check the version, especially when statically linked.

Downstream of nixops4#56

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced method to retrieve store version information
    • Added library initialization function for utility setup
  • Tests

    • Added unit tests to validate new functionality

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

The changes introduce version retrieval and initialization capabilities across the nix bindings library. A new get_version() method is added to the Store struct, while the utility module exposes raw_sys and provides init() and get_version() functions. Test setup is refactored to use the new higher-level initialization method.

Changes

Cohort / File(s) Summary
Version Retrieval
nix-bindings-store/src/store.rs, nix-bindings-util/src/lib.rs
Added get_version() methods to Store and util module following FFI callback pattern; includes unit tests validating version string retrieval with different initialization states.
Initialization & Test Refactoring
nix-bindings-util/src/lib.rs, nix-bindings-util/src/settings.rs
Exposed raw_sys re-export and added init() function for context initialization via libutil_init. Updated settings test to use new init() instead of manual unsafe FFI calls.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 Hop hop goes the binding code,
Versions flowing down the road,
Init and get in perfect stride,
Nix utilities open wide! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main changes: adding version getters for store and util, plus util initialization. It directly reflects the core functionality added across the modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/more-functions

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
nix-bindings-util/src/lib.rs (1)

14-21: Consider guarding init() against concurrent calls since nix_libutil_init is not thread-safe.
Although the C API is safe to call multiple times (idempotent), it is not re-entrant—concurrent calls from multiple threads could race. Use LazyLock or OnceLock (already established patterns in nix-bindings-store and nix-bindings-expr) to ensure single-threaded initialization:

♻️ Suggested guard with LazyLock
+use std::sync::LazyLock;
+
+static INIT: LazyLock<Result<()>> = LazyLock::new(|| unsafe {
+    let mut ctx = context::Context::new();
+    check_call!(raw::libutil_init(&mut ctx))
+});
+
 #[doc(alias = "nix_libutil_init")]
 pub fn init() -> Result<()> {
-    let mut ctx = context::Context::new();
-    unsafe {
-        check_call!(raw::libutil_init(&mut ctx))?;
-    }
-    Ok(())
+    INIT.as_ref().copied()
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nix-bindings-util/src/lib.rs` around lines 14 - 21, init() currently calls
raw::libutil_init(&mut ctx) directly and can race if invoked concurrently; guard
it with a process-wide one-time initializer (use OnceLock or LazyLock as used in
nix-bindings-store / nix-bindings-expr). Replace the direct call in init() with
a static OnceLock or LazyLock holding a Result<(), Error> (or similar) and run
the libutil_init logic (creating context::Context and calling raw::libutil_init)
inside the get_or_init / get_or_try_init closure so concurrent callers wait and
reuse the single initialized result; return that stored Result from init() to
preserve error propagation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nix-bindings-store/src/store.rs`:
- Around line 275-287: The get_version() wrapper calls raw::store_get_version
which is only present in Nix >= 2.17, so add a compile-time guard: annotate the
get_version function with #[cfg(nix_at_least = "2.17")] (and #[cfg_attr(docsrs,
doc(cfg(nix_at_least = "2.17")))] if you want docs visibility) so it is only
compiled when that feature exists; alternatively, update build.rs to emit cfg
for "2.17" in addition to the existing versions so the nix_at_least macro will
enable get_version for that release. Ensure the change references the
get_version function and the raw::store_get_version call.

---

Nitpick comments:
In `@nix-bindings-util/src/lib.rs`:
- Around line 14-21: init() currently calls raw::libutil_init(&mut ctx) directly
and can race if invoked concurrently; guard it with a process-wide one-time
initializer (use OnceLock or LazyLock as used in nix-bindings-store /
nix-bindings-expr). Replace the direct call in init() with a static OnceLock or
LazyLock holding a Result<(), Error> (or similar) and run the libutil_init logic
(creating context::Context and calling raw::libutil_init) inside the get_or_init
/ get_or_try_init closure so concurrent callers wait and reuse the single
initialized result; return that stored Result from init() to preserve error
propagation.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d3a7ee and 84a48c1.

📒 Files selected for processing (3)
  • nix-bindings-store/src/store.rs
  • nix-bindings-util/src/lib.rs
  • nix-bindings-util/src/settings.rs

Comment on lines +275 to +287
#[doc(alias = "nix_store_get_version")]
pub fn get_version(&mut self) -> Result<String> {
let mut r = result_string_init!();
unsafe {
check_call!(raw::store_get_version(
&mut self.context,
self.inner.ptr(),
Some(callback_get_result_string),
callback_get_result_string_data(&mut r)
))
}?;
r
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Feb 23, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

nix_store_get_version Nix C API introduction version minimum

💡 Result:

nix_store_get_version() is part of the libstore C bindings (src/libstore/c/nix_api_store.h). In the published external C-API docs for Nix 2.17.0, nix_api_store.h exists and documents nix_store_get_version(), so the minimum Nix version you can rely on for this function is Nix 2.17.0 (2023-07-24). [1][2]

Sources:
[1] Nix 2.17.0 external C-API docs file list (shows nix_api_store.h) — https://pub.yori.cc/nix-c-api-docs/files.html
[2] nix_api_store.h / libstore docs (shows nix_store_get_version() signature) — https://pub.yori.cc/nix-c-api-docs/group__libstore.html


🏁 Script executed:

# Check the crate structure and minimum Nix version requirement
git ls-files | head -20

Repository: DeterminateSystems/nix-bindings-rust

Length of output: 403


🏁 Script executed:

# Look for version gating patterns and Cargo.toml
fd "Cargo.toml" -x cat {}

Repository: DeterminateSystems/nix-bindings-rust

Length of output: 9296


🏁 Script executed:

# Search for existing cfg(nix_at_least) or similar version gating
rg "nix_at_least|cfg.*nix" --type rust

Repository: DeterminateSystems/nix-bindings-rust

Length of output: 3995


🏁 Script executed:

# Check if there are any version requirements or comments about Nix versions
rg "version|nix.*version" nix-bindings-store/src/ -i --type rust | head -20

Repository: DeterminateSystems/nix-bindings-rust

Length of output: 852


🏁 Script executed:

# Check the exact context around get_version function
sed -n '270,290p' nix-bindings-store/src/store.rs

Repository: DeterminateSystems/nix-bindings-rust

Length of output: 665


🏁 Script executed:

# Check the build.rs to see the full version cfg setup
cat nix-bindings-store/build.rs

Repository: DeterminateSystems/nix-bindings-rust

Length of output: 305


🏁 Script executed:

# Look for any comments or documentation about minimum Nix version
rg "minimum.*nix|nix.*version.*require|MSRV" -i nix-bindings-store/ nix-bindings-expr/ nix-bindings-flake/

Repository: DeterminateSystems/nix-bindings-rust

Length of output: 62


Add version gate to get_version(); nix_store_get_version requires Nix 2.17.0+.

The get_version() function calls nix_store_get_version(), which was introduced in Nix 2.17.0 (2023-07-24). Without a version guard, builds against older Nix versions will fail at link time. Your build.rs currently emits cfg only for ["2.26", "2.31", "2.33.0pre", "2.33"], leaving this function unguarded. Add #[cfg(nix_at_least = "2.17")] to the function, or extend the version list in build.rs to include "2.17".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nix-bindings-store/src/store.rs` around lines 275 - 287, The get_version()
wrapper calls raw::store_get_version which is only present in Nix >= 2.17, so
add a compile-time guard: annotate the get_version function with
#[cfg(nix_at_least = "2.17")] (and #[cfg_attr(docsrs, doc(cfg(nix_at_least =
"2.17")))] if you want docs visibility) so it is only compiled when that feature
exists; alternatively, update build.rs to emit cfg for "2.17" in addition to the
existing versions so the nix_at_least macro will enable get_version for that
release. Ensure the change references the get_version function and the
raw::store_get_version call.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The minimum version is basically 2.26, at least for the fetchers it is. It may be possible to use this with < 2.17 but afaik, it's not tested nor really supported. Most people are going to be on 2.26 or newer.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@RossComputerGuy, thanks for clarifying! Since the project's minimum supported version is 2.26, I'd suggest adding #[cfg(nix_at_least = "2.26")] to get_version() for consistency with other version-specific functions like get_storedir() (line 259). This ensures the function is only available when building against supported Nix versions.

#[cfg(nix_at_least = "2.26")]
#[doc(alias = "nix_store_get_version")]
pub fn get_version(&mut self) -> Result<String> {
    // ... existing implementation
}

✏️ Learnings added
Learnt from: RossComputerGuy
Repo: DeterminateSystems/nix-bindings-rust PR: 12
File: nix-bindings-store/src/store.rs:275-287
Timestamp: 2026-02-23T23:54:54.401Z
Learning: The nix-bindings-rust project's minimum supported Nix version is 2.26, particularly for the fetchers. While some functionality may work with earlier versions, they are not tested or officially supported.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No like, I am pretty sure nix-bindings-rust won't even compile even if we do this. This function has been around for long enough that version compatibility isn't a problem.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@RossComputerGuy, understood! You're right—if the project already requires Nix 2.26+ to compile and nix_store_get_version() existed well before that, then adding a version gate here is unnecessary. I appreciate the clarification. The implementation looks good as-is.


🧠 Learnings used
Learnt from: RossComputerGuy
Repo: DeterminateSystems/nix-bindings-rust PR: 12
File: nix-bindings-store/src/store.rs:275-287
Timestamp: 2026-02-23T23:54:54.401Z
Learning: Enforce and document the minimum Nix version (2.26) for fetcher-related code in this project. Ensure tests and CI assume Nix 2.26+ and clearly note compatibility in the code comments or README. If a fetcher path or related logic exists elsewhere, consider applying the same version requirement there or referencing a central compatibility document to avoid drift.

@RossComputerGuy RossComputerGuy merged commit 0b80fcf into integration Feb 25, 2026
5 checks passed
@RossComputerGuy RossComputerGuy deleted the feat/more-functions branch February 25, 2026 18:00
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.

2 participants