Refactoring in preparation of #11411#12065
Open
tdammers wants to merge 9 commits into
Open
Conversation
5a3b13f to
29cf47e
Compare
ffaf1
reviewed
Jun 30, 2026
6 tasks
e9e9f1c to
eee4e1b
Compare
ed859b7 to
fe07a85
Compare
This commit includes a series of refactorings that are necessary to solve haskell#11411: - Abstract the Rebuild monad into the MonadRebuild typeclass, introducing the `withRunRebuildInIO` method of MonadRebuild. This allows us to interleave plain `IO` with `MonadRebuild` without necessarily having to use `Rebuild` itself. This is especially important because `Rebuild` also encodes the "current working directory" concern, which is relevant within `cabal-install`, but something we don't want to require within the `Cabal` library. Since the `MonadRebuild` typeclass allows for arbitrary custom monadic state per instance, it can live in the `Cabal` subproject, together with operations defined in terms of the typeclass, while `Rebuild` itself remains in `cabal-install`, using the custom monadic state to cover the "current working directory" concern. - Change the `StateT` part of `Rebuild` into `WriterT`, since we only ever emit additional files from within a Rebuild context; consuming them happens on the outside, so Writer is sufficient. - Provide `MonadRebuild` instances for the existing `Rebuild` type, and for the most minimal type that can satisfy the typeclass, `WriterT [MonitorFilePath] IO`. - Implement most file monitoring / Rebuild actions in terms of `MonadRebuild`, so they can live in `Cabal` (`Distribution.Simple.RebuildMonad`), leaving only `cabal-install` specific things in the existing `cabal-install` module (`Distribution.Client.RebuildMonad`). Specifically, we implement `rerunIfChanged'` in terms of `MonadRebuild` and a custom function for chaining `IO` actions (serially or in parallel, as needed); the existing `rerunIfChanged` and `rerunConcurrentlyIfChanged` functions, which live in `cabal-install`, are now implemented in terms of `rerunIfChanged'`, which lives in `Cabal`). - Move large parts of the `Distribution.Client.FileMonitor` module from `cabal-install` to `Cabal` (as `Distribution.Simple.FileMonitor`); we will be needing these parts to solve haskell#11411 (`Distribution.Client.FileMonitor` still re-exports all of them though). - Move most of the `Distribution.Client.HashValue` module over to `Cabal` (with the exception of TUF-related functions, which are specific to `cabal-install`; again we re-export everything in `cabal-install` to maintain API compatibility). - Move `getFilePathRootDirectory` from `Distribution.Client.Glob` into `Distribution.Simple.FileMonitor.Types` - it has little to do with actual globs, and is only used for file monitoring purposes. - Shuffle some utility functions around to make them accessible where we need them. The big picture with all this is that we want to reuse the existing file monitoring machinery to keep track of build-tool versions alongside generated source files. However, the tracking needs to happen in the `Cabal` library, while file monitoring has so far only been available in `cabal-install`; hence we need to move the required file monitoring code and its dependencies into the `Cabal` library, but without introducing any `cabal-install` specific concerns into `Cabal`, and without breaking API compatibility on the `cabal-install` side.
e18cbb7 to
11353ea
Compare
Bodigrim
reviewed
Jul 9, 2026
| , deepseq >= 1.4 && < 1.7 | ||
| , base16-bytestring >= 1.0 && < 1.1 | ||
| , binary >= 0.7.3 && < 0.9 | ||
| , cryptohash-sha256 >= 0.11 && < 0.12 |
Collaborator
There was a problem hiding this comment.
Cabal cannot depend on non-boot libraries.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This commit includes a series of refactorings that are necessary to
solve #11411:
withRunRebuildInIOmethod of MonadRebuild. This allows us to interleave plainIOwithMonadRebuildwithout necessarily having to useRebuilditself. This is especially important becauseRebuildalso encodes the "current working directory" concern, which is relevant withincabal-install, but something we don't want to require within theCaballibrary. Since theMonadRebuildtypeclass allows for arbitrary custom monadic state per instance, it can live in theCabalsubproject, together with operations defined in terms of the typeclass, whileRebuilditself remains incabal-install, using the custom monadic state to cover the "current working directory" concern.StateTpart ofRebuildintoWriterT, since we only ever emit additional files from within a Rebuild context; consuming them happens on the outside, so Writer is sufficient.MonadRebuildinstances for the existingRebuildtype, and for the most minimal type that can satisfy the typeclass,WriterT [MonitorFilePath] IO.MonadRebuild, so they can live inCabal(Distribution.Simple.RebuildMonad), leaving onlycabal-installspecific things in the existingcabal-installmodule (Distribution.Client.RebuildMonad). Specifically, we implementrerunIfChanged'in terms ofMonadRebuildand a custom function for chainingIOactions (serially or in parallel, as needed); the existingrerunIfChangedandrerunConcurrentlyIfChangedfunctions, which live incabal-install, are now implemented in terms ofrerunIfChanged', which lives inCabal).Distribution.Client.FileMonitormodule fromcabal-installtoCabal(asDistribution.Simple.FileMonitor); we will be needing these parts to solve Build tool not rerun when build tool version changes #11411 (Distribution.Client.FileMonitorstill re-exports all of them though).Distribution.Client.HashValuemodule over toCabal(with the exception of TUF-related functions, which are specific tocabal-install; again we re-export everything incabal-installto maintain API compatibility).getFilePathRootDirectoryfromDistribution.Client.GlobintoDistribution.Simple.FileMonitor.Types- it has little to do with actual globs, and is only used for file monitoring purposes.The big picture with all this is that we want to reuse the existing file monitoring machinery to keep track of build-tool versions alongside generated source files. However, the tracking needs to happen in the
Caballibrary, while file monitoring has so far only been available incabal-install; hence we need to move the required file monitoring code and its dependencies into theCaballibrary, but without introducing anycabal-installspecific concerns intoCabal, and without breaking API compatibility on thecabal-installside.QA Notes
This PR should not cause any observable changes to existing code, but it does expose some things via the Cabal library that were previously part of cabal-install. Specifically, file monitoring, the glob API, and hash functions are now available as part of the Cabal library API, and can be used e.g. in setup hooks.
significance: significantin the changelog file.