Skip to content

Conversation

@edolstra
Copy link
Collaborator

@edolstra edolstra commented Nov 19, 2025

Motivation

  • Include a copy of the upstream flake registry as a fallback for when it can't be downloaded.
  • Add a new command nix registry resolve for doing registry lookups. This is useful for testing.

Context

Summary by CodeRabbit

  • New Features

    • Added nix registry resolve command to resolve indirect flake references to direct upstream URLs.
    • Introduced a built-in fallback registry with common flake mappings (e.g., nixpkgs).
  • Documentation

    • Added documentation and usage examples for nix registry resolve.
  • Tests

    • Updated functional tests for registry commands, including resolve/add/remove scenarios and builtin-registry fallback checks.
  • Refactor

    • Registry loading/resolution now supports in-memory/builtin fallbacks and unified error handling.
  • Chores

    • Excluded the new builtin registry JSON from automatic formatting and added it to the build sources.

@coderabbitai
Copy link

coderabbitai bot commented Nov 19, 2025

Walkthrough

Adds a builtin flake registry JSON and embeds it in the build, refactors Registry APIs to remove Settings dependency and add in-memory JSON parsing with builtin fallback, updates call sites, adds a nix registry resolve command and docs, and updates tests and clang-format excludes.

Changes

Cohort / File(s) Summary
Registry API & implementation
src/libfetchers/include/nix/fetchers/registry.hh, src/libfetchers/registry.cc
Remove Settings member and constructor parameter from Registry; add Registry::read overload for in-memory JSON (whence + jsonStr); unify error handling to use whence; add builtin fallback registry; change getFlagRegistry() and overrideRegistry() signatures to drop Settings.
Call sites updated
src/libcmd/common-eval-args.cc, src/libcmd/installables.cc
Update calls to overrideRegistry to remove the Settings/fetchSettings argument; calls now pass (from, to, extraAttrs).
Builtin registry data & build integration
src/libfetchers/builtin-flake-registry.json, src/libfetchers/meson.build, src/libfetchers/package.nix, maintainers/flake-module.nix
Add static builtin-flake-registry.json; meson build adds generate-header step and includes generated header/source; package.nix adds JSON to fileset; clang-format excludes the JSON file.
CLI command & docs
src/nix/registry.cc, src/nix/registry-resolve.md
Add CmdRegistryResolve command implementing nix registry resolve to resolve indirect flakerefs to direct flakerefs; register the subcommand and add documentation with examples.
Tests
tests/functional/flakes/flakes.sh
Update test header and assertions to cover registry add/remove counts, nix registry resolve outputs (including builtin fallback), and adjust test sequencing.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as "nix registry resolve"
    participant Store
    participant Registries as "Registries\n(Flag, User, System, Global/Builtin)"

    User->>CLI: nix registry resolve <indirect-flakeref>
    CLI->>CLI: parse flakeref
    CLI->>Store: resolveFlake(parsedRef)
    Store->>Registries: lookup indirect ref
    alt Found in a registry
        Registries-->>Store: return direct flakeref
    else Redirect chain
        Registries->>Registries: follow redirects across registries
        Registries-->>Store: return final direct flakeref
    else Not found in registries
        Registries->>Registries: consult builtin JSON fallback
        Registries-->>Store: builtin mapping (if present) or error
    end
    Store-->>CLI: resolved direct flakeref or error
    CLI->>User: print resolved flakeref (stdout)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay special attention to:
    • src/libfetchers/registry.cc — new read overload, fallback logic, unified error messaging and embedding of JSON.
    • Signature changes in src/libfetchers/include/nix/fetchers/registry.hh and all call-site updates.
    • Build integration in meson.build and package.nix for embedding the JSON.
    • New CLI command CmdRegistryResolve and its edge-case handling (parsing/resolution errors).
    • Tests in tests/functional/flakes/flakes.sh asserting resolution behavior.

Suggested reviewers

  • grahamc

Poem

🐇 I hid a JSON under moss and log,
I nudged the Registry, cleaned out one cog,
I hopped through calls and fixed the flow,
Now flake refs find the paths to go,
A rabbit cheers: resolve and run — not a slog!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
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.
Title check ❓ Inconclusive The title 'Registry improvements' is vague and generic, using non-descriptive language that doesn't clearly convey the specific changes made in the changeset. Consider a more specific title that highlights the main changes, such as 'Add builtin flake registry fallback and nix registry resolve command' or 'Refactor registry handling with builtin fallback and resolve command'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch registry-improvements

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 535a168 and 53e73be.

📒 Files selected for processing (1)
  • src/nix/registry-resolve.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
src/nix/registry-resolve.md

[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ...g. nixpkgs) to direct flakerefs (e.g. github:NixOS/nixpkgs) using the flake registr...

(GITHUB)

⏰ 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_x86_64-linux / build
  • GitHub Check: build_aarch64-darwin / build
🔇 Additional comments (1)
src/nix/registry-resolve.md (1)

1-28: Well-documented and clear.

The documentation effectively explains the nix registry resolve command with concrete examples and a thorough description. The examples (resolving nixpkgs and blender-bin, and resolving with a branch override) are realistic and help illustrate the command's behavior. The description accurately conveys key behaviors: registry lookup order (flag → user → system → global), support for multiple redirections, and appropriate error handling for unresolvable references.


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

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

Caution

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

⚠️ Outside diff range comments (1)
src/libfetchers/registry.cc (1)

28-66: Consider catching broader exception types.

The catch block at line 61 only catches nlohmann::json::exception, but JSON parsing at line 35 can throw other exceptions (e.g., std::bad_alloc during large allocations). These uncaught exceptions would propagate up, bypassing the fallback mechanism.

Consider broadening the catch to handle unexpected errors gracefully:

     } catch (nlohmann::json::exception & e) {
         warn("cannot parse flake registry '%s': %s", whence, e.what());
+    } catch (std::exception & e) {
+        warn("unexpected error parsing flake registry '%s': %s", whence, e.what());
     }
🧹 Nitpick comments (3)
src/libfetchers/builtin-flake-registry.json (1)

1-425: LGTM! Consider maintenance strategy for future updates.

The builtin flake registry is well-structured with comprehensive mappings for popular flakes. All entries follow a consistent format and the JSON is valid.

As an optional improvement, consider documenting the maintenance strategy for keeping this registry synchronized with upstream changes. Since this is now embedded as static data, stale entries could cause confusion if upstream repositories move or are archived.

src/nix/registry-resolve.md (1)

1-28: LGTM! Documentation is clear and comprehensive.

The documentation effectively explains the command's purpose, provides practical examples, and describes the resolution process. The static analysis warning about "github" capitalization is a false positive—lowercase is correct in URL/code contexts.

As a minor enhancement, consider making the first example more explicit that it's resolving two flake-refs simultaneously:

* Resolve the `nixpkgs` and `blender-bin` flakerefs:

  ```console
  # nix registry resolve nixpkgs blender-bin
  github:NixOS/nixpkgs/nixpkgs-unstable
  github:edolstra/nix-warez?dir=blender

This would immediately clarify that the command accepts multiple arguments.

</blockquote></details>
<details>
<summary>src/libfetchers/registry.cc (1)</summary><blockquote>

`164-169`: **Consider adding a comment to clarify the inline include pattern.**

The `#include` directive at line 167 within the function argument list is valid but unusual. A brief comment explaining that the generated header contains a string literal would improve readability.



```diff
             // Use builtin registry as fallback
+            // Note: builtin-flake-registry.json.gen.hh contains a string literal with the registry JSON
             return Registry::read(
                 settings,
                 "builtin flake registry",
 #include "builtin-flake-registry.json.gen.hh"
                 ,
                 Registry::Global);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be871f9 and 0f6572c.

📒 Files selected for processing (10)
  • maintainers/flake-module.nix (1 hunks)
  • src/libcmd/common-eval-args.cc (1 hunks)
  • src/libcmd/installables.cc (0 hunks)
  • src/libfetchers/builtin-flake-registry.json (1 hunks)
  • src/libfetchers/include/nix/fetchers/registry.hh (2 hunks)
  • src/libfetchers/meson.build (1 hunks)
  • src/libfetchers/registry.cc (4 hunks)
  • src/nix/registry-resolve.md (1 hunks)
  • src/nix/registry.cc (2 hunks)
  • tests/functional/flakes/flakes.sh (1 hunks)
💤 Files with no reviewable changes (1)
  • src/libcmd/installables.cc
🧰 Additional context used
🧬 Code graph analysis (4)
src/libcmd/common-eval-args.cc (2)
src/libfetchers/include/nix/fetchers/registry.hh (2)
  • overrideRegistry (61-61)
  • from (46-46)
src/libfetchers/registry.cc (2)
  • overrideRegistry (136-139)
  • overrideRegistry (136-136)
tests/functional/flakes/flakes.sh (2)
src/nix/registry.cc (2)
  • registry (31-41)
  • registry (146-151)
src/libfetchers/registry.cc (4)
  • add (90-93)
  • add (90-90)
  • remove (95-100)
  • remove (95-95)
src/nix/registry.cc (2)
src/libflake/include/nix/flake/flakeref.hh (4)
  • parseFlakeRef (89-95)
  • fetchSettings (67-70)
  • fetchSettings (72-72)
  • fetchSettings (75-75)
src/libflake/flakeref.cc (2)
  • parseFlakeRef (45-58)
  • parseFlakeRef (45-51)
src/libfetchers/registry.cc (1)
src/libfetchers/include/nix/fetchers/registry.hh (4)
  • settings (39-39)
  • settings (42-42)
  • path (44-44)
  • from (46-46)
🪛 LanguageTool
src/nix/registry-resolve.md

[uncategorized] ~22-~22: The official name of this software platform is spelled with a capital “H”.
Context: ...g. nixpkgs) to direct flakerefs (e.g. github:NixOS/nixpkgs) using the flake registr...

(GITHUB)

⏰ 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 (12)
src/libfetchers/meson.build (1)

59-64: LGTM!

The build configuration correctly integrates the builtin flake registry by generating a header from the JSON file, which aligns with the PR's objective of including a copy of the upstream flake registry as a fallback.

maintainers/flake-module.nix (1)

103-103: LGTM!

Appropriately excludes the new JSON data file from clang-format processing.

src/libcmd/common-eval-args.cc (1)

130-130: LGTM!

The call to overrideRegistry correctly matches the updated API signature that no longer requires a Settings parameter.

src/libfetchers/include/nix/fetchers/registry.hh (3)

34-36: LGTM!

The constructor simplification removes the Settings dependency, aligning with the PR's objective to support builtin registry handling without requiring Settings configuration.


41-42: LGTM!

The new read overload accepting jsonStr enables in-memory registry parsing, which is essential for loading the builtin flake registry from the generated header.


61-61: LGTM!

The simplified overrideRegistry signature is consistent with removing Settings dependencies from the registry API.

src/nix/registry.cc (2)

205-237: LGTM!

The CmdRegistryResolve implementation is clean and straightforward. It correctly:

  • Accepts multiple flake-refs as documented
  • Resolves each via the registry using the store
  • Outputs resolved URLs line-by-line

249-249: LGTM!

The new resolve subcommand is properly registered in the registry command set.

tests/functional/flakes/flakes.sh (1)

268-282: LGTM!

The test changes comprehensively cover the new nix registry resolve command functionality, including:

  • Resolution with percent-encoded paths
  • Registry count verification after add/remove operations
  • Builtin fallback registry behavior when the upstream registry is unreachable

The test at line 281 cleverly uses --download-attempts 1 and an invalid URL to force fallback to the builtin registry, validating that the embedded registry serves as a proper fallback mechanism.

src/libfetchers/registry.cc (3)

13-26: LGTM! Graceful fallback on registry read errors.

The error handling approach returns an empty registry when the path doesn't exist or when reading/parsing fails, which aligns well with the fallback mechanism introduced in this PR. This ensures the system remains functional even when registries are unavailable.


130-139: LGTM! Clean removal of Settings dependency.

The signature changes successfully decouple the flag registry from Settings, and the static initialization is thread-safe due to C++11 guarantees for static local variables.


141-174: Build system correctly generates the registry header - code is verified.

The verification confirms:

  • src/libfetchers/builtin-flake-registry.json exists as the source
  • src/libfetchers/meson.build (lines 59-64) properly configures the build rule via gen_header.process()
  • The generator wraps JSON in a C++ raw string literal (R"__NIX_STR(...content...)__NIX_STR"), which is a valid expression for the #include in the function argument

The fallback mechanism is well-designed and will function correctly.

This makes Nix more resilient if the registry is down or we're offline.
@edolstra edolstra force-pushed the registry-improvements branch from 0f6572c to 535a168 Compare November 19, 2025 13:20
@github-actions
Copy link

github-actions bot commented Nov 19, 2025

@github-actions github-actions bot temporarily deployed to pull request November 19, 2025 13:24 Inactive
for (auto & url : urls) {
auto ref = parseFlakeRef(fetchSettings, url);
auto resolved = ref.resolve(fetchSettings, store);
logger->cout("%s", resolved.to_string());
Copy link
Member

Choose a reason for hiding this comment

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

nit: since it's possible there's more than 1 flake ref supplied, could be prefix them which each, so it's immediately obvious? (i.e. if someone had typo'd their local flake registry and had an entry "nixos-unstable" pointing to 25.11, while "nixos-25.11" pointed at unstable, they wouldn't have to reason about "why are they out of order?", it'd just be "oh I guess I swapped them oops")

Copy link
Member

Choose a reason for hiding this comment

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

I'd be fine special casing that behavior "if more than 1 flakeref was supplied", as well as "if --json was supplied" (in the future that it grows a --json flag)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

IMHO that makes it harder to script.

Co-authored-by: Cole Helbling <cole.e.helbling@outlook.com>
@github-actions github-actions bot temporarily deployed to pull request November 19, 2025 15:43 Inactive
@edolstra edolstra added this pull request to the merge queue Nov 19, 2025
Merged via the queue into main with commit e681209 Nov 19, 2025
28 checks passed
@edolstra edolstra deleted the registry-improvements branch November 19, 2025 20:20
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.

3 participants