Skip to content

Dix 3.0.0: Congrats, you did it!

Latest

Choose a tag to compare

@faukah faukah released this 26 Oct 21:39
· 3 commits to main since this release
17e3373

Sorry my dear friends and lovers of dix, this release truly took a long time. Big thanks to @pieter0101 and @amaanq for their great help with this one. Love you guys ❤️.

Many many API breakages because major release, and many many features. Enjoy.

Added

  • The CHANGED, ADDED and REMOVED headings now show how many packages
    they contain, e.g. CHANGED (12).
  • Each package in the JSON output has a kind field that is version,
    amount or size, depending on the most significant change it went
    through. ChangeKind and PackageDiff::kind expose the same in the library.
  • Added the dix last [N] subcommand, which shows the changes leading up to
    the current profile generation, dix last --all for every generation, and
    dix last --from A --to B for the generations numbered A to B.
  • Added the dix snapshot <PATH> subcommand, which prints the closure of a
    store path as a versioned JSON SnapshotDocument. This lets the closure be
    captured on one machine (e.g. a remote deployment target) and diffed on
    another.
  • StorePath, StorePathInfo and StoreSnapshot now implement
    Serialize/Deserialize. SnapshotDocument serializes with the current
    format version, and SnapshotDocument::from_json rejects unknown format
    versions before parsing anything else.
  • dix diff accepts JSON files written by dix snapshot in place of either
    store path.
  • Size, used in reports and snapshots, is re-exported from the crate root.
  • Added the default cli and store features. Library users that only diff
    snapshots can disable default features to drop the SQLite and command-line
    dependencies. Store requires store.
  • dix diff and dix last take --exit-code to exit with 1 if the compared
    closures differ. -q/--quiet does the same without printing the diff.
    DiffReport::has_changes exposes the same check in the library.

Fixed

  • Versions with a suffix other than a pre-release marker (alpha, beta,
    pre, rc) now sort above their base version, so updating from 7.1.0 to
    7.1.0-unstable-2026-01-25 is an upgrade instead of a downgrade.
  • Numbers inside version components compare by value and letters ignore case,
    so 1.0-rc10 is newer than 1.0-rc9, and 1.0-RC1 newer than
    1.0-alpha.
  • Querying a path that is not a valid store path, e.g. one that exists on disk
    but was never registered, now fails instead of producing an empty closure.

Changed

  • Breaking: Diffing moved into the diff subcommand, so dix <OLD> <NEW>
    is now dix diff <OLD> <NEW>. Its options, like --output, belong to
    diff.
  • Breaking: Removed --force-correctness; its behaviour is now the only
    one. dix never opens the Nix database with ?immutable=1, and falls back
    to Nix commands instead.
  • Breaking: The store module is now private, so StoreBackend,
    CombinedStoreBackend, DbConnection, CommandBackend and
    query_store_snapshot_with_backend are no longer public. StorePathInfo is
    re-exported from the crate root. Remote stores were only reachable through
    CommandBackend::store_url(...), which dix snapshot replaces.
  • Breaking: Removed the json cargo feature. serde and serde_json are
    now always required.
  • Breaking: Errors now exit with 2 instead of 1, since --exit-code uses 1
    to report that the compared closures differ.
  • Breaking: -q/--quiet no longer decreases logging verbosity. It is now
    the --quiet of dix diff and dix last.
  • Logs are now written to stderr instead of stdout.
  • RUST_LOG is no longer read. Use -v (repeatable) to show more log output.
  • Packages whose version did not change are hidden unless their size changed
    by at least --min-size-delta (default 1 MiB). A note at the end of the
    output says how many were hidden. Pass --full to dix diff or dix last
    to show them.
  • Names of packages that are not selected are now dimmed, instead of names of
    selected packages being bold.
  • Breaking: write_diff_report takes a RenderOptions argument and
    returns the number of hidden package diffs instead of the number written.
  • Breaking: Removed query_diff_report, query_adjacent_diff_reports and
    query_store_snapshot. Open a Store once and use diff_store_snapshots
    on the snapshot of its query_snapshot_document results instead.
  • Breaking: The report and snapshot modules are private. Their items
    are still exported from the crate root.
  • Breaking: StorePathInfo exposes public path and nar_size fields
    instead of new, path() and nar_size().
  • Breaking: StorePath is created with TryFrom<String> instead of
    TryFrom<PathBuf>, only accepts paths of the form /nix/store/<hash>-<name>
    and dereferences to Path instead of PathBuf. StorePath::as_str returns
    it as a string.
  • Breaking: Packages without a version, such as flake sources, have a
    None version instead of the version "<none>". VersionAmount::version
    and the version of VersionDiff::AmountChanged are Option<Version>, and
    their name in the JSON output is null.
  • Breaking: json::display_diff is replaced by json::JsonReport, which
    serializes an already queried report instead of querying and printing it.
  • Breaking: DiffReport, PathStats and PackageSizeDelta expose public
    fields instead of accessor methods, reverting the 2.0.0 change for
    DiffReport and PathStats. Read and construct the fields directly, e.g.
    report.size_old instead of report.size_old(), stats.added instead of
    stats.added_count() and PackageSizeDelta { old, new } instead of
    PackageSizeDelta::new(old, new).
  • dix links against the system SQLite instead of bundling its own copy, so
    building it needs libsqlite3 and its headers.
  • Breaking: The dix-diff crate is merged back into dix and is no
    longer published. DiffStatus, Version, VersionAmount and VersionDiff
    are still exported from dix, and the rest of the diff engine is internal.
  • The repository is a single package again, so cargo install --path . works.
  • Breaking: PackageDiff holds the version change of a package in
    change: Option<VersionChange> instead of the versions, status and
    has_omitted_versions fields, and VersionChange is exported from dix.
    change is None for packages whose size changed but whose versions did
    not. PackageDiff::status() still reports those as DiffStatus::Changed.

What's Changed

  • build(deps): bump nixpkgs from e1c1b84 to f205b55 by @dependabot[bot] in #96
  • build(deps): bump nixpkgs from f205b55 to 3b32825 by @dependabot[bot] in #97
  • render: inline size diff into SIZE reporting by @faukah in #101
  • build(deps): bump nixpkgs from 3b32825 to d3498f7 by @dependabot[bot] in #105
  • build(deps): bump actions/checkout from 7.0.0 to 7.0.1 by @dependabot[bot] in #104
  • build(deps): bump nixpkgs from d3498f7 to 9387b3f by @dependabot[bot] in #115
  • update and drop cargo dependencies by @faukah in #108
  • build(deps): bump nixpkgs from 9387b3f to 34ca302 by @dependabot[bot] in #119
  • dix: add snapshot subcommand for versioned closure snapshots by @faukah in #124
  • dix: add snapshot subcommand for versioned closure snapshots by @faukah in #125
  • dix: drop --force-correctness, cleanup by @faukah in #126
  • dix: add last subcommand by @faukah in #127
  • render: add a count to the diff headings by @faukah in #129
  • build: update nix + cargo dependencies by @faukah in #128
  • report: classify package diffs by change kind by @faukah in #130
  • ci: move to manic-systems/workflows v2 by @amaanq in #131
  • dix: replace clap with pound and eyre with misstep by @amaanq in #132
  • dix: drop the store backend connection lifecycle by @faukah in #137
  • build: update cargo dependencies by @faukah in #136
  • build: link against system sqlite instead of bundling it by @amaanq in #140
  • dix: merge dix-diff back into dix by @faukah in #139
  • dix: diff snapshot files by @faukah in #141
  • BIG cleanup by @faukah in #142
  • ci: bump the actions group with 4 updates by @dependabot[bot] in #134
  • ci: bump the actions group with 4 updates by @dependabot[bot] in #143
  • dix: fix version comparison! by @faukah in #144
  • dix: add --exit-code and --quiet to diff and last by @faukah in #145

Full Changelog: v2.2.0...v3.0.0