feat(diff): init internal differ#192
Conversation
b06629e to
2eb3562
Compare
2eb3562 to
208202b
Compare
7492abf to
702d074
Compare
702d074 to
c162141
Compare
fbb48fb to
c457a47
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
📝 WalkthroughWalkthroughA new builtin differ for Nix store closures has been implemented via SQLite database queries, replacing the previous Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.11.3)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (4)
cmd/root/root.go (1)
32-34: Remove duplicatecobra.EnableTraverseRunHooksinitialization.After moving this to
init(), the assignment inExecute()is redundant. Keep it in one place to avoid configuration drift.Proposed cleanup
func Execute() { - cobra.EnableTraverseRunHooks = true - cmd, err := mainCommand() if err != nil { os.Exit(1) }Also applies to: 179-181
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/root/root.go` around lines 32 - 34, The init() function already sets cobra.EnableTraverseRunHooks, so remove the redundant assignment from Execute() (and any other duplicate at the other mentioned location) to keep configuration in one place; locate the duplicate use of cobra.EnableTraverseRunHooks in the Execute() function and delete that line, leaving the init() initialization as the sole assignment.cmd/generation/rollback/rollback.go (1)
72-74: Consider updating the comment to reflect the new differ options.The comment mentions "nvd" and "nix store diff-closures" but doesn't account for the new internal differ, which is now the default. Consider updating to reflect all available differ options.
📝 Suggested comment update
// While it is possible to use the `rollback` command, we still need // to find the previous generation number ourselves in order to run - // `nvd` or `nix store diff-closures` properly. + // the configured differ properly.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/generation/rollback/rollback.go` around lines 72 - 74, Update the explanatory comment above the rollback logic to mention the new internal differ (now the default) alongside the legacy tools; specifically reference the `rollback` command behavior and list/acknowledge the available differ options (e.g., the internal differ, `nvd`, and `nix store diff-closures`) so the comment reflects current behavior and choices used when finding the previous generation number in functions around rollback handling in rollback.go.internal/settings/completion.go (1)
30-31: Inconsistent use ofreflect.Pointervsreflect.Ptr.Lines 30 and 42 use
reflect.Pointer, but line 60 still usesreflect.Ptr. While both are functionally equivalent (aliases since Go 1.18), consider using one consistently throughout the file for clarity.♻️ Suggested fix for consistency
if current.Kind() == reflect.Ptr { + if current.Kind() == reflect.Pointer { if current.IsNil() { current.Set(reflect.New(current.Type().Elem())) } current = current.Elem() }Also applies to: 42-48, 60-65
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/settings/completion.go` around lines 30 - 31, The code uses both reflect.Pointer and reflect.Ptr inconsistently (seen where current.Kind() is compared), so standardize on one alias throughout the file (e.g., replace all occurrences of reflect.Pointer with reflect.Ptr or vice versa) so every check like current.Kind() == reflect.Pointer/current.Kind() == reflect.Ptr uses the same symbol; update every instance in internal/settings/completion.go (including the blocks around the current.Kind() checks and any other uses) to the chosen alias for consistency.internal/diff/diff.go (1)
218-237: Redundantchangedvariable.The
changedvariable (line 218-221) duplicates the condition already checked at line 233. The logic can be simplified.Proposed simplification
if len(uniqueOldVersions) == 0 && len(uniqueNewVersions) == 0 { continue } - changed := false - if len(uniqueOldVersions) > 0 && len(uniqueNewVersions) > 0 { - changed = true - } - diff := PathDiff{ Name: name, } if len(uniqueOldVersions) > 0 && len(uniqueNewVersions) == 0 { diff.Change = ChangeTypeRemove diff.Old = uniqueOldVersions } else if len(uniqueOldVersions) == 0 && len(uniqueNewVersions) > 0 { diff.Change = ChangeTypeAdd diff.New = uniqueNewVersions - } else if changed { + } else { + // Both have unique versions - this is a change diff.Change = ChangeTypeChange diff.Old = uniqueOldVersions diff.New = uniqueNewVersions }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@internal/diff/diff.go` around lines 218 - 237, The local boolean variable `changed` is redundant—remove its declaration and assignment and instead use the direct condition when building the PathDiff: replace the `else if changed { ... }` branch with `else if len(uniqueOldVersions) > 0 && len(uniqueNewVersions) > 0 { ... }`, leaving the other branches that set `diff.Change` to ChangeTypeRemove/Add and populate `diff.Old`/`diff.New` unchanged; this simplifies the logic around constructing the PathDiff (the surrounding symbols are `changed`, `PathDiff`, `ChangeTypeChange`, `ChangeTypeRemove`, `ChangeTypeAdd`, and the slices `uniqueOldVersions`/`uniqueNewVersions`).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@internal/diff/closure.go`:
- Around line 126-129: The error return after rows.Scan currently returns
partial results plus an error; make it consistent with getClosure by returning
nil and the wrapped error instead: replace the "return results, fmt.Errorf(...)"
in the rows.Scan error path with "return nil, fmt.Errorf(...)" so both the rows
scanning block and getClosure return nil on error (adjust callers if they expect
partial slices).
In `@internal/diff/display.go`:
- Around line 114-128: The formatSize function currently truncates sizes < 1024
to "0 KiB"; update formatSize so that when size < kb it returns the size in
bytes (e.g., "123 B") instead of dividing by kb, otherwise keep existing
KiB/MiB/GiB branches; modify the format logic inside formatSize to check size <
kb first and format with "%d B" for bytes, then fall through to KiB, MiB, GiB
branches.
In `@internal/settings/settings.go`:
- Around line 435-454: The migration for cfg.UseNvd currently unconditionally
overwrites any explicit differ settings; change it to only apply when the
existing cfg.Differ.Tool is the default/unspecified (e.g., empty string or the
default constant DifferNix) so we don't clobber user-provided values. In the
block that appends DeprecatedSettingError for UseNvd, guard the assignments to
cfg.Differ.Tool and cfg.Differ.Command with a conditional that checks
cfg.Differ.Tool is unset/default before setting it to DifferCommand and
[]string{"nvd","diff"}; leave explicit user settings intact. Ensure the
subsequent switch on cfg.Differ.Tool still validates and falls back as before.
---
Nitpick comments:
In `@cmd/generation/rollback/rollback.go`:
- Around line 72-74: Update the explanatory comment above the rollback logic to
mention the new internal differ (now the default) alongside the legacy tools;
specifically reference the `rollback` command behavior and list/acknowledge the
available differ options (e.g., the internal differ, `nvd`, and `nix store
diff-closures`) so the comment reflects current behavior and choices used when
finding the previous generation number in functions around rollback handling in
rollback.go.
In `@cmd/root/root.go`:
- Around line 32-34: The init() function already sets
cobra.EnableTraverseRunHooks, so remove the redundant assignment from Execute()
(and any other duplicate at the other mentioned location) to keep configuration
in one place; locate the duplicate use of cobra.EnableTraverseRunHooks in the
Execute() function and delete that line, leaving the init() initialization as
the sole assignment.
In `@internal/diff/diff.go`:
- Around line 218-237: The local boolean variable `changed` is redundant—remove
its declaration and assignment and instead use the direct condition when
building the PathDiff: replace the `else if changed { ... }` branch with `else
if len(uniqueOldVersions) > 0 && len(uniqueNewVersions) > 0 { ... }`, leaving
the other branches that set `diff.Change` to ChangeTypeRemove/Add and populate
`diff.Old`/`diff.New` unchanged; this simplifies the logic around constructing
the PathDiff (the surrounding symbols are `changed`, `PathDiff`,
`ChangeTypeChange`, `ChangeTypeRemove`, `ChangeTypeAdd`, and the slices
`uniqueOldVersions`/`uniqueNewVersions`).
In `@internal/settings/completion.go`:
- Around line 30-31: The code uses both reflect.Pointer and reflect.Ptr
inconsistently (seen where current.Kind() is compared), so standardize on one
alias throughout the file (e.g., replace all occurrences of reflect.Pointer with
reflect.Ptr or vice versa) so every check like current.Kind() ==
reflect.Pointer/current.Kind() == reflect.Ptr uses the same symbol; update every
instance in internal/settings/completion.go (including the blocks around the
current.Kind() checks and any other uses) to the chosen alias for consistency.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 03740ae1-2033-4cdd-bac8-7ef868958b29
⛔ Files ignored due to path filters (2)
go.modis excluded by!go.modgo.sumis excluded by!**/*.sum,!go.sum
📒 Files selected for processing (18)
cmd/apply/apply.gocmd/generation/diff/diff.gocmd/generation/rollback/rollback.gocmd/generation/switch/switch.gocmd/root/root.godoc/man/nixos-cli-generation-diff.1.scddoc/man/nixos-cli.1.scdinternal/constants/constants.gointernal/diff/closure.gointernal/diff/diff.gointernal/diff/display.gointernal/diff/version.gointernal/generation/diff.gointernal/settings/completion.gointernal/settings/settings.gointernal/settings/settings_test.gointernal/utils/set/set.gonix/package/unwrapped.nix
💤 Files with no reviewable changes (1)
- internal/generation/diff.go
4f03d4e to
089b85d
Compare
This PR creates an internal differ that uses the Nix store DB to calculate the differences between two NixOS system closures, and also makes the differ settings much more configurable than just
use_nvd.This particular differ is different from tools such as
nvdanddix(but takes inspiration!) in that it also queries derivers on the system for more accurate version strings than simplepname-versionparsing.use_nvdis also marked as deprecated in this PR, and will be removed in a future release.Closes #189.
Summary by CodeRabbit
Release Notes
New Features
differsettings (supports internal, nix, or custom command options)Documentation
differconfiguration mechanismuse_nvdsetting as deprecated; usediffer.toolinsteadChores