Skip to content

nix-tools: share the git-fetch cache between plan2nix and stack2nix (#1689) - #2544

Open
hamishmack wants to merge 5 commits into
masterfrom
hkm/issue-1689-shared-cache
Open

nix-tools: share the git-fetch cache between plan2nix and stack2nix (#1689)#2544
hamishmack wants to merge 5 commits into
masterfrom
hkm/issue-1689-shared-cache

Conversation

@hamishmack

Copy link
Copy Markdown
Collaborator

Summary

Plan2Nix.Cache and Stack2nix.Cache were supposed to be identical (the
Plan2Nix copy literally opened with -- Note: this is identical to Stack2nix.Cache)
but had drifted apart in a way that mattered:

  • Plan2Nix.Cache stored a NOHASH placeholder for empty hashes, so the
    whitespace-delimited cache format still round-trips through words — but it
    read and wrote the file lazily.
  • Stack2nix.Cache forced the reads/writes strictly (<$!!> / $!) — but
    wrote a raw empty string for a missing hash. Under words an empty field
    simply disappears, so a local-package cache line loses a column and no longer
    parses back to the 6-tuple: latent cache corruption.

This externalises the logic into a single library module NixTools.Cache
that keeps the union of the correct behaviours — the NOHASH placeholder and
the strict IO — then repoints both Stack2nix and Plan2Nix at it and deletes
the two old modules. plan-to-nix already depends on the nix-tools library, so
no new dependency is needed.

Changes

  • Add nix-tools/nix-tools/lib/NixTools/Cache.hs (merged, more-defensive impl).
  • Delete lib/Stack2nix/Cache.hs and plan2nix/Plan2Nix/Cache.hs.
  • import NixTools.Cache in lib/Stack2nix.hs and plan2nix/Plan2Nix.hs.
  • cabal: expose NixTools.Cache in the library (replacing Stack2nix.Cache);
    drop Plan2Nix.Cache from plan-to-nix's other-modules.

Testing

The public API and type signatures are identical to both old modules
(readCache/appendCache/cacheHits), and both call sites only import
(appendCache, cacheHits), so they compile unchanged — this is a
signature-preserving merge. I typechecked the new module standalone with GHC
(ghc -fno-code -Wall): it compiles; the only warnings (non-exhaustive
toTuple, unused sha256 in the cacheHits comprehension) are present
verbatim in both original modules, so there is no new warning/regression.

A full from-source nix-tools build (needs ghc-9.6 + the hnix closure) was
not run in this environment.

Release caveat: haskell.nix consumes nix-tools as a prebuilt static release
binary, so this change reaches haskell.nix builds only once a new nix-tools
release is cut.

Closes #1689.

Plan2Nix.Cache and Stack2nix.Cache were byte-for-byte "identical" copies
(per the stale comment atop the former) that had since drifted apart:

  * Plan2Nix.Cache stored a "NOHASH" placeholder for empty hashes so the
    whitespace-delimited cache format still round-trips through `words`,
    but read/wrote lazily.
  * Stack2nix.Cache forced reads/writes strictly (<$!!> / $!) but wrote a
    raw empty string for missing hashes, which collapses a field under
    `words` and corrupts the cache line for local packages.

Replace both with a single library module NixTools.Cache that keeps the
union of the correct behaviours: the NOHASH placeholder AND the strict IO.
Repoint Stack2nix and Plan2Nix at it, delete the two old modules, and
update the cabal module lists (plan-to-nix already depends on the library).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Consolidates the git-fetch cache implementation used by plan-to-nix and stack-to-nix into a single shared library module (NixTools.Cache) to prevent format drift and cache corruption (notably around missing hashes and strict IO).

Changes:

  • Introduce NixTools.Cache as the unified cache implementation (NOHASH placeholder + strict read/write).
  • Repoint Plan2Nix and Stack2nix to import NixTools.Cache instead of tool-specific cache modules.
  • Update nix-tools.cabal to expose NixTools.Cache and remove the duplicated module wiring.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
nix-tools/nix-tools/lib/NixTools/Cache.hs New shared cache module; merges correct behaviors from both prior implementations.
nix-tools/nix-tools/plan2nix/Plan2Nix.hs Switch cache import to the shared NixTools.Cache.
nix-tools/nix-tools/lib/Stack2nix.hs Switch cache import to the shared NixTools.Cache.
nix-tools/nix-tools/nix-tools.cabal Expose NixTools.Cache from the library; drop the duplicate module from plan-to-nix’s other-modules.
nix-tools/nix-tools/lib/Stack2nix/Cache.hs Removes the now-redundant cache module implementation.
Comments suppressed due to low confidence (1)

nix-tools/nix-tools/lib/NixTools/Cache.hs:29

  • readCache uses a non-exhaustive pattern match in toTuple, so any malformed/blank cache line will throw a PatternMatchFail and abort the entire read. Making this total removes a -Wall warning and yields a clearer error if it ever happens (behaviour still fails fast).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Review follow-up on #2544.  `readCache`'s `toTuple` only matched a six-field
line, so a blank or truncated cache line (e.g. from an interrupted
`appendCache`) raised `PatternMatchFail`.  Because this module now reads
strictly the failure is caught by `cacheHits`, but the whole cache is then
discarded rather than just the bad line, and `-Wall` flagged the incomplete
match.

Use `mapMaybe` and skip lines we cannot parse: the cache is advisory, so a
skipped entry only means we fetch it again. Also silences the `-Wunused-matches`
warning for the unused `sha256` binder in `cacheHits`, so the new shared module
compiles clean under `-Wall`.

Verified with `nix develop` + `cabal build -w ghc lib:nix-tools plan-to-nix
stack-to-nix`: both -Wincomplete-patterns and -Wunused-matches warnings for
NixTools/Cache.hs are gone (they were present before this commit).
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.

Drop duplicate code

2 participants