Skip to content

Invalidate per-project restore skip when paket.lock content changes#4334

Open
randrag wants to merge 2 commits intofsprojects:masterfrom
AgricoZA:i4333-lock-content-invalidates-project-props
Open

Invalidate per-project restore skip when paket.lock content changes#4334
randrag wants to merge 2 commits intofsprojects:masterfrom
AgricoZA:i4333-lock-content-invalidates-project-props

Conversation

@randrag
Copy link
Copy Markdown

@randrag randrag commented Apr 26, 2026

This is to fix #4333 — Step 2a's skip in Paket.Restore.targets previously only watched paket.references, so transitive changes in paket.lock left the per-project paket.props stale. The fix adds a paket.lock content-hash check (Step 2 a-bis) and a one-line write of that hash after each successful per-project restore (Step 3 a-bis), plus a fall-through that fires once on first encounter for legacy checkouts that pre-date the cache file.

Test in RestoreSpecs.fs follows the existing #2684 / #3527 patterns: full restore, mutate paket.lock content, assert that the next dotnet restore requests a per-project restore (via PAKET_ERROR_ON_MSBUILD_EXEC=true).

randrag added 2 commits April 26, 2026 20:17
…ket.props stale

Step 2a's per-project skip optimisation in Paket.Restore.targets only
invalidates on paket.references content change. When a merge bumps a
transitive package version, paket.lock and paket.resolved change but
paket.references does not, and (with BaseIntermediateOutputPath
redirected per-platform) the per-project paket.props stays at the
pre-merge content. NuGet then resolves to the previous version
indefinitely.

This test reproduces that path: full restore, mutate paket.lock content,
expect the next restore to invalidate the per-project skip. With the
unfixed targets file the skip stays in effect and the test fails.

Companion fix to follow.
Add Step 2 a-bis to Paket.Restore.targets that hashes paket.lock and
compares to a per-project hash cache file written after each successful
per-project restore. If the cached hash differs from the current hash,
the per-project skip is invalidated and a paket restore runs. A
fall-through case fires once on first encounter for legacy checkouts
that pre-date the cache file, so installations upgrading to this
version self-correct on the next restore.

This complements Step 2a (which hashes paket.references content) so
that pure-transitive package version changes — where paket.lock and
paket.resolved change but paket.references does not — also invalidate
the per-project skip.

The hash is computed locally rather than reusing $(PaketRestoreLockFileHash)
from Step 1 because Step 1 may be disabled via PaketDisableGlobalRestore.
A new file $(PaketIntermediateOutputPath)\<proj>.fsproj.paket.lock.hash
records the lock hash at the time of the last successful per-project
restore.

Greens the integration test added in the previous 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.

Per-project restore skip misses paket.lock content changes when paket.references is unchanged

1 participant