From aa6026731976f825b0505467c771f69fcb7c033a Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Wed, 4 Mar 2026 21:25:18 +0800 Subject: [PATCH 01/26] Monitor imported cabal.project files - Fixes #10255 - Fix assertion failure wrt #11568 'lookupLocalPackageConfig' would ignore --'projectConfigAllPackages' (`package *`) and thus diverge from 'lookupPerPkgOption'. This would then cause further divergence between 'elabStanzasRequested' and 'elabStanzasAvailable'. - Add test for #10255 - Add bootstrap-jsons-ghcup Makefile rule - Be stricter about URI imports - This behavior is documented, but not enforced. We redesign the 'ProjectConfigPath' type to better express the properties we expect. - Revert Cabal-syntax network-uri - Revert boostrap/*.json and Makefile - Revert ProjectConfigPath - Revert ParserTests - Revert ProjectConfig/[Legacy|Parsec] - Revert Compat/Orphans - Revert TreeDiffInstances - Revert deletion of ProjectFileParseError - Revert Arbitrary ProjectConfigProvenance change - Revert Errors/Parser prettyShow removal - Get ProjectConfig compiling --- .../src/Distribution/Client/ProjectConfig.hs | 24 +++- .../Distribution/Client/ProjectPlanning.hs | 109 ++++++++++-------- .../ProjectImport/FileMonitoring/app/Main.hs | 4 + .../FileMonitoring/cabal-project-repro.cabal | 101 ++++++++++++++++ .../FileMonitoring/cabal.project | 6 + .../FileMonitoring/cabal.test.hs | 16 +++ .../nested/deeply-nested/hop.config | 1 + .../FileMonitoring/nested/hop.config | 2 + .../ProjectImport/FileMonitoring/test/Main.hs | 4 + .../FileMonitoring/test/tests-toggle.config | 2 + 10 files changed, 221 insertions(+), 48 deletions(-) create mode 100644 cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/app/Main.hs create mode 100644 cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal-project-repro.cabal create mode 100644 cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal.project create mode 100644 cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/nested/deeply-nested/hop.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/nested/hop.config create mode 100644 cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/test/Main.hs create mode 100644 cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/test/tests-toggle.config diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index a0eea1ac5cc..90422eaff90 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -4,6 +4,7 @@ {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeApplications #-} +{-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -Wno-unused-matches #-} -- | Handling project configuration. @@ -59,7 +60,6 @@ module Distribution.Client.ProjectConfig , fetchAndReadSourcePackages -- * Resolving configuration - , lookupLocalPackageConfig , projectConfigWithBuilderRepoContext , projectConfigWithSolverRepoContext , SolverSettings (..) @@ -853,17 +853,35 @@ readProjectFileSkeletonGen exists <- liftIO $ doesFileExist extensionFile if exists then do + -- Monitor the "main" project file (this could be e.g. 'cabal.project', 'cabal.project.freeze' or + -- 'cabal.project.local'. monitorFiles [monitorFileHashed extensionFile] pcs <- liftIO $ parseConfig extensionFile + + -- We also need to monitor all the (possibly recursive) imports. + -- 'projectSkeletonImports' is a path per imported project file that starts with the leaf + -- and ends with the main project file that is the root. E.g. if 'cabal.project' imports + -- 'cabal.project.foo', which imports 'cabal.project.bar', then we get two paths: + -- + -- > ("cabal.project.bar" :| ["cabal.project.foo", "cabal.project"]) + -- > ("cabal.project.foo" :| ["cabal.project"]) + -- + -- Consequently, we just take the heads of all the paths. monitorFiles - [ monitorFileHashed (projectConfigPathRoot path) - | (Nothing, path) <- projectSkeletonImports pcs + + [ monitorFileHashed $ makeAbsolute path + | (Nothing, currentProjectConfigPath -> path) <- projectSkeletonImports pcs ] + return pcs else do monitorFiles [monitorNonExistentFile extensionFile] return mempty where + -- Do we prefer absolute paths for cache monitoring? + makeAbsolute f + | isAbsolute f = f + | otherwise = distProjectRootDirectory dir f extensionFile = (distProjectFile dir) extensionName -- There are 3 different variants of the project parsing function. diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index f2ace7ff3b5..e51d5f183cd 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -787,6 +787,9 @@ rebuildInstallPlan projectConfig@ProjectConfig { projectConfigShared , projectConfigBuildOnly + , projectConfigAllPackages + , projectConfigLocalPackages + , projectConfigSpecificPackage } (compiler, platform, progdb) localPackages @@ -865,27 +868,32 @@ rebuildInstallPlan -- and packages explicitly mentioned in the project -- let pkgname = pkgSpecifierTarget pkg - testsEnabled = - lookupLocalPackageConfig - packageConfigTests - projectConfig - pkgname - benchmarksEnabled = - lookupLocalPackageConfig - packageConfigBenchmarks - projectConfig - pkgname - isLocal = isJust (shouldBeLocal pkg) - stanzas - | isLocal = - Map.fromList $ - [ (TestStanzas, enabled) - | enabled <- flagToList testsEnabled - ] - ++ [ (BenchStanzas, enabled) - | enabled <- flagToList benchmarksEnabled - ] - | otherwise = Map.fromList [(TestStanzas, False), (BenchStanzas, False)] + stanzas = case shouldBeLocal pkg of + Just pkgId -> + let testsEnabled = + lookupPerPkgOption + pkgId + packageConfigTests + projectConfigAllPackages + projectConfigLocalPackages + (getMapMappend projectConfigSpecificPackage) + (const True) + benchmarksEnabled = + lookupPerPkgOption + pkgId + packageConfigBenchmarks + projectConfigAllPackages + projectConfigLocalPackages + (getMapMappend projectConfigSpecificPackage) + (const True) + in Map.fromList $ + [ (TestStanzas, enabled) + | enabled <- flagToList testsEnabled + ] + ++ [ (BenchStanzas, enabled) + | enabled <- flagToList benchmarksEnabled + ] + Nothing -> Map.fromList [(TestStanzas, False), (BenchStanzas, False)] ] -- Elaborate the solver's install plan to get a fully detailed plan. This @@ -2476,39 +2484,27 @@ elaborateInstallPlan perPkgOptionMaybe :: PackageId -> (PackageConfig -> Flag a) -> Maybe a perPkgOptionList :: PackageId -> (PackageConfig -> [a]) -> [a] - perPkgOptionFlag pkgid def f = fromFlagOrDefault def (lookupPerPkgOption pkgid f) - perPkgOptionMaybe pkgid f = flagToMaybe (lookupPerPkgOption pkgid f) - perPkgOptionList pkgid f = lookupPerPkgOption pkgid f - perPkgOptionNubList pkgid f = fromNubList (lookupPerPkgOption pkgid f) - perPkgOptionMapLast pkgid f = getMapLast (lookupPerPkgOption pkgid f) - perPkgOptionMapMappend pkgid f = getMapMappend (lookupPerPkgOption pkgid f) + perPkgOptionFlag pkgid def f = fromFlagOrDefault def (lookupPerPkgOption' pkgid f) + perPkgOptionMaybe pkgid f = flagToMaybe (lookupPerPkgOption' pkgid f) + perPkgOptionList pkgid f = lookupPerPkgOption' pkgid f + perPkgOptionNubList pkgid f = fromNubList (lookupPerPkgOption' pkgid f) + perPkgOptionMapLast pkgid f = getMapLast (lookupPerPkgOption' pkgid f) + perPkgOptionMapMappend pkgid f = getMapMappend (lookupPerPkgOption' pkgid f) perPkgOptionLibExeFlag pkgid def fboth flib = (exe, lib) where exe = fromFlagOrDefault def bothflag lib = fromFlagOrDefault def (bothflag <> libflag) - bothflag = lookupPerPkgOption pkgid fboth - libflag = lookupPerPkgOption pkgid flib + bothflag = lookupPerPkgOption' pkgid fboth + libflag = lookupPerPkgOption' pkgid flib - lookupPerPkgOption + lookupPerPkgOption' :: (Package pkg, Monoid m) => pkg -> (PackageConfig -> m) -> m - lookupPerPkgOption pkg f = - -- This is where we merge the options from the project config that - -- apply to all packages, all project local packages, and to specific - -- named packages - global `mappend` local `mappend` perpkg - where - global = f allPackagesConfig - local - | isLocalToProject pkg = - f localPackagesConfig - | otherwise = - mempty - perpkg = maybe mempty f (Map.lookup (packageName pkg) perPackageConfig) + lookupPerPkgOption' pkg f = lookupPerPkgOption pkg f allPackagesConfig localPackagesConfig perPackageConfig isLocalToProject inplacePackageDbs = corePackageDbs @@ -2624,8 +2620,8 @@ elaborateInstallPlan fromFlagOrDefault compilerShouldUseProfilingLibByDefault (profBothFlag <> profLibFlag) where pkgid = packageId pkg - profBothFlag = lookupPerPkgOption pkgid packageConfigProf - profLibFlag = lookupPerPkgOption pkgid packageConfigProfLib + profBothFlag = lookupPerPkgOption' pkgid packageConfigProf + profLibFlag = lookupPerPkgOption' pkgid packageConfigProfLib pkgsUseProfilingLibraryShared :: Set PackageId pkgsUseProfilingLibraryShared = @@ -4666,3 +4662,26 @@ determineCoverageFor configuredPkg plan = isIndefiniteOrInstantiation :: ModuleShape -> Bool isIndefiniteOrInstantiation = not . Set.null . modShapeRequires + +lookupPerPkgOption + :: (Package pkg, Monoid m) + => pkg + -> (PackageConfig -> m) + -> PackageConfig + -> PackageConfig + -> Map PackageName PackageConfig + -> (pkg -> Bool) + -> m +lookupPerPkgOption pkg f allPackagesConfig localPackagesConfig perPackageConfig isLocalPkg = + -- This is where we merge the options from the project config that + -- apply to all packages, all project local packages, and to specific + -- named packages + global `mappend` local `mappend` perpkg + where + global = f allPackagesConfig + local + | isLocalPkg pkg = + f localPackagesConfig + | otherwise = + mempty + perpkg = maybe mempty f (Map.lookup (packageName pkg) perPackageConfig) diff --git a/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/app/Main.hs b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/app/Main.hs new file mode 100644 index 00000000000..f16f6f53396 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/app/Main.hs @@ -0,0 +1,4 @@ +module Main (main) where + +main :: IO () +main = putStrLn "Hello, Haskell!" diff --git a/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal-project-repro.cabal b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal-project-repro.cabal new file mode 100644 index 00000000000..fc3fbfd2d15 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal-project-repro.cabal @@ -0,0 +1,101 @@ +cabal-version: 3.0 +-- The cabal-version field refers to the version of the .cabal specification, +-- and can be different from the cabal-install (the tool) version and the +-- Cabal (the library) version you are using. As such, the Cabal (the library) +-- version used must be equal or greater than the version stated in this field. +-- Starting from the specification version 2.2, the cabal-version field must be +-- the first thing in the cabal file. + +-- Initial package description 'cabal-project-repro' generated by +-- 'cabal init'. For further documentation, see: +-- http://haskell.org/cabal/users-guide/ +-- +-- The name of the package. +name: cabal-project-repro + +-- The package version. +-- See the Haskell package versioning policy (PVP) for standards +-- guiding when and how versions should be incremented. +-- https://pvp.haskell.org +-- PVP summary: +-+------- breaking API changes +-- | | +----- non-breaking API additions +-- | | | +--- code changes with no API change +version: 0.1.0.0 + +-- A short (one-line) description of the package. +-- synopsis: + +-- A longer description of the package. +-- description: + +-- The license under which the package is released. +license: BSD-3-Clause + +-- The file containing the license text. +license-file: LICENSE + +-- The package author(s). +author: Julian Ospald + +-- An email address to which users can send suggestions, bug reports, and patches. +maintainer: hasufell@posteo.de + +-- A copyright notice. +-- copyright: +build-type: Simple + +-- Extra doc files to be distributed with the package, such as a CHANGELOG or a README. +extra-doc-files: CHANGELOG.md + +-- Extra source files to be distributed with the package, such as examples, or a tutorial module. +-- extra-source-files: + +common warnings + ghc-options: -Wall + +executable filemonitor-test + -- Import common warning flags. + import: warnings + + -- .hs or .lhs file containing the Main module. + main-is: Main.hs + + -- Modules included in this executable, other than Main. + -- other-modules: + + -- LANGUAGE extensions used by modules in this package. + -- other-extensions: + + -- Other library packages from which modules are imported. + build-depends: base, filepath + + -- Directories containing source files. + hs-source-dirs: app + + -- Base language which the package is written in. + default-language: Haskell2010 + +test-suite cabal-project-repro-test + -- Import common warning flags. + import: warnings + + -- Base language which the package is written in. + default-language: Haskell2010 + + -- Modules included in this executable, other than Main. + -- other-modules: + + -- LANGUAGE extensions used by modules in this package. + -- other-extensions: + + -- The interface type and version of the test suite. + type: exitcode-stdio-1.0 + + -- Directories containing source files. + hs-source-dirs: test + + -- The entrypoint to the test suite. + main-is: Main.hs + + -- Test dependencies. + build-depends: base diff --git a/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal.project b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal.project new file mode 100644 index 00000000000..469e652adaf --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal.project @@ -0,0 +1,6 @@ +packages: ./cabal-project-repro.cabal + +package * + Tests: True + +import: nested/hop.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal.test.hs b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal.test.hs new file mode 100644 index 00000000000..bb4b9504190 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/cabal.test.hs @@ -0,0 +1,16 @@ +import Test.Cabal.Prelude +import System.Exit (ExitCode(ExitFailure)) +import System.IO + +main = cabalTest (withProjectFile "cabal.project" $ do + result <- fails $ recordMode DoNotRecord $ cabal' "build" [] + assertExitCode (ExitFailure 1) result + assertOutputContains "Failed to build cabal-project-repro-0.1.0.0-inplace-cabal-project-repro-test." result + + -- change the imported project file + test_dir <- fmap testTmpDir getTestEnv + liftIO $ writeFile (test_dir "test" "tests-toggle.config") "package *\n Tests: False" + result' <- recordMode DoNotRecord $ cabal' "build" [] + assertOutputDoesNotContain "Test suite not yet implement" result' + assertOutputDoesNotContain "Failed to build cabal-project-repro-0.1.0.0-inplace-cabal-project-repro-test." result' + ) diff --git a/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/nested/deeply-nested/hop.config b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/nested/deeply-nested/hop.config new file mode 100644 index 00000000000..14a44ec1b90 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/nested/deeply-nested/hop.config @@ -0,0 +1 @@ +import: ../../test/tests-toggle.config diff --git a/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/nested/hop.config b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/nested/hop.config new file mode 100644 index 00000000000..5023e425930 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/nested/hop.config @@ -0,0 +1,2 @@ +import: deeply-nested/hop.config + diff --git a/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/test/Main.hs b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/test/Main.hs new file mode 100644 index 00000000000..7e9a17db22b --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/test/Main.hs @@ -0,0 +1,4 @@ +module Main (main) where + +main :: IO () +main = puStrLn "Test suite not yet implemented." diff --git a/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/test/tests-toggle.config b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/test/tests-toggle.config new file mode 100644 index 00000000000..653cd6b9660 --- /dev/null +++ b/cabal-testsuite/PackageTests/ProjectImport/FileMonitoring/test/tests-toggle.config @@ -0,0 +1,2 @@ +package * + Tests: True From 3f18d4a13d5478f2d6f6999193d9ca464abedd23 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Mon, 25 May 2026 16:46:05 -0400 Subject: [PATCH 02/26] Satisfy fourmolu --- cabal-install/src/Distribution/Client/ProjectConfig.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 90422eaff90..59f90b322aa 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -868,7 +868,6 @@ readProjectFileSkeletonGen -- -- Consequently, we just take the heads of all the paths. monitorFiles - [ monitorFileHashed $ makeAbsolute path | (Nothing, currentProjectConfigPath -> path) <- projectSkeletonImports pcs ] From 856fc3f99e7fa99946e891abd5f6102b8147d233 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Mon, 25 May 2026 16:54:52 -0400 Subject: [PATCH 03/26] Undo removal of export of lookupLocalPackageConfig --- cabal-install/src/Distribution/Client/ProjectConfig.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 59f90b322aa..247e63c91ba 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -60,6 +60,7 @@ module Distribution.Client.ProjectConfig , fetchAndReadSourcePackages -- * Resolving configuration + , lookupLocalPackageConfig , projectConfigWithBuilderRepoContext , projectConfigWithSolverRepoContext , SolverSettings (..) From a236eedbc5480c6e148f7227ee66343641c493eb Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 09:49:44 -0400 Subject: [PATCH 04/26] Promote comment to haddocks --- cabal-install/src/Distribution/Client/ProjectPlanning.hs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index e51d5f183cd..dd0335230d2 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -4663,6 +4663,8 @@ determineCoverageFor configuredPkg plan = isIndefiniteOrInstantiation :: ModuleShape -> Bool isIndefiniteOrInstantiation = not . Set.null . modShapeRequires +-- | Look up and merge the options from the project config that apply to all +-- packages, all project local packages, and to specific named packages. lookupPerPkgOption :: (Package pkg, Monoid m) => pkg @@ -4673,9 +4675,6 @@ lookupPerPkgOption -> (pkg -> Bool) -> m lookupPerPkgOption pkg f allPackagesConfig localPackagesConfig perPackageConfig isLocalPkg = - -- This is where we merge the options from the project config that - -- apply to all packages, all project local packages, and to specific - -- named packages global `mappend` local `mappend` perpkg where global = f allPackagesConfig From 3354bea1c9554e9cd5863d59d8d8dbbebf3cae7f Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 09:50:17 -0400 Subject: [PATCH 05/26] Reformat that fourmolu accepts --- cabal-install/src/Distribution/Client/ProjectPlanning.hs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index dd0335230d2..a79081bf3d0 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -4679,8 +4679,6 @@ lookupPerPkgOption pkg f allPackagesConfig localPackagesConfig perPackageConfig where global = f allPackagesConfig local - | isLocalPkg pkg = - f localPackagesConfig - | otherwise = - mempty + | isLocalPkg pkg = f localPackagesConfig + | otherwise = mempty perpkg = maybe mempty f (Map.lookup (packageName pkg) perPackageConfig) From 165b38048ea9d18711e29f31b3c45550ca4c132c Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 10:03:24 -0400 Subject: [PATCH 06/26] Change the arg order for partial application --- .../Distribution/Client/ProjectPlanning.hs | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index a79081bf3d0..a4d299ec182 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -872,20 +872,20 @@ rebuildInstallPlan Just pkgId -> let testsEnabled = lookupPerPkgOption - pkgId - packageConfigTests + (const True) projectConfigAllPackages projectConfigLocalPackages (getMapMappend projectConfigSpecificPackage) - (const True) + pkgId + packageConfigTests benchmarksEnabled = lookupPerPkgOption - pkgId - packageConfigBenchmarks + (const True) projectConfigAllPackages projectConfigLocalPackages (getMapMappend projectConfigSpecificPackage) - (const True) + pkgId + packageConfigBenchmarks in Map.fromList $ [ (TestStanzas, enabled) | enabled <- flagToList testsEnabled @@ -2499,12 +2499,8 @@ elaborateInstallPlan bothflag = lookupPerPkgOption' pkgid fboth libflag = lookupPerPkgOption' pkgid flib - lookupPerPkgOption' - :: (Package pkg, Monoid m) - => pkg - -> (PackageConfig -> m) - -> m - lookupPerPkgOption' pkg f = lookupPerPkgOption pkg f allPackagesConfig localPackagesConfig perPackageConfig isLocalToProject + lookupPerPkgOption' :: (Package pkg, Monoid m) => pkg -> (PackageConfig -> m) -> m + lookupPerPkgOption' = lookupPerPkgOption isLocalToProject allPackagesConfig localPackagesConfig perPackageConfig inplacePackageDbs = corePackageDbs @@ -4667,14 +4663,14 @@ determineCoverageFor configuredPkg plan = -- packages, all project local packages, and to specific named packages. lookupPerPkgOption :: (Package pkg, Monoid m) - => pkg - -> (PackageConfig -> m) + => (pkg -> Bool) -> PackageConfig -> PackageConfig -> Map PackageName PackageConfig - -> (pkg -> Bool) + -> pkg + -> (PackageConfig -> m) -> m -lookupPerPkgOption pkg f allPackagesConfig localPackagesConfig perPackageConfig isLocalPkg = +lookupPerPkgOption isLocalPkg allPackagesConfig localPackagesConfig perPackageConfig pkg f = global `mappend` local `mappend` perpkg where global = f allPackagesConfig From 99b6bb43b7f78573e2a20707cb3dea9f39ede149 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 10:12:27 -0400 Subject: [PATCH 07/26] Rename lookupPerPkgOption' to perPkgOption --- .../Distribution/Client/ProjectPlanning.hs | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index a4d299ec182..e71995a3682 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -2480,27 +2480,26 @@ elaborateInstallPlan elabBenchmarkOptions = perPkgOptionList pkgid packageConfigBenchmarkOptions + perPkgOption :: (Package pkg, Monoid m) => pkg -> (PackageConfig -> m) -> m + perPkgOption = lookupPerPkgOption isLocalToProject allPackagesConfig localPackagesConfig perPackageConfig + perPkgOptionFlag :: PackageId -> a -> (PackageConfig -> Flag a) -> a perPkgOptionMaybe :: PackageId -> (PackageConfig -> Flag a) -> Maybe a perPkgOptionList :: PackageId -> (PackageConfig -> [a]) -> [a] - - perPkgOptionFlag pkgid def f = fromFlagOrDefault def (lookupPerPkgOption' pkgid f) - perPkgOptionMaybe pkgid f = flagToMaybe (lookupPerPkgOption' pkgid f) - perPkgOptionList pkgid f = lookupPerPkgOption' pkgid f - perPkgOptionNubList pkgid f = fromNubList (lookupPerPkgOption' pkgid f) - perPkgOptionMapLast pkgid f = getMapLast (lookupPerPkgOption' pkgid f) - perPkgOptionMapMappend pkgid f = getMapMappend (lookupPerPkgOption' pkgid f) + perPkgOptionFlag pkgid def f = fromFlagOrDefault def (perPkgOption pkgid f) + perPkgOptionMaybe pkgid f = flagToMaybe (perPkgOption pkgid f) + perPkgOptionList pkgid f = perPkgOption pkgid f + perPkgOptionNubList pkgid f = fromNubList (perPkgOption pkgid f) + perPkgOptionMapLast pkgid f = getMapLast (perPkgOption pkgid f) + perPkgOptionMapMappend pkgid f = getMapMappend (perPkgOption pkgid f) perPkgOptionLibExeFlag pkgid def fboth flib = (exe, lib) where exe = fromFlagOrDefault def bothflag lib = fromFlagOrDefault def (bothflag <> libflag) - bothflag = lookupPerPkgOption' pkgid fboth - libflag = lookupPerPkgOption' pkgid flib - - lookupPerPkgOption' :: (Package pkg, Monoid m) => pkg -> (PackageConfig -> m) -> m - lookupPerPkgOption' = lookupPerPkgOption isLocalToProject allPackagesConfig localPackagesConfig perPackageConfig + bothflag = perPkgOption pkgid fboth + libflag = perPkgOption pkgid flib inplacePackageDbs = corePackageDbs @@ -2616,8 +2615,8 @@ elaborateInstallPlan fromFlagOrDefault compilerShouldUseProfilingLibByDefault (profBothFlag <> profLibFlag) where pkgid = packageId pkg - profBothFlag = lookupPerPkgOption' pkgid packageConfigProf - profLibFlag = lookupPerPkgOption' pkgid packageConfigProfLib + profBothFlag = perPkgOption pkgid packageConfigProf + profLibFlag = perPkgOption pkgid packageConfigProfLib pkgsUseProfilingLibraryShared :: Set PackageId pkgsUseProfilingLibraryShared = From c97a74f56f167f4b94afeafe3c60861a97143fa3 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 10:17:02 -0400 Subject: [PATCH 08/26] Change arg order with perPkgOptionFlag, def first --- .../Distribution/Client/ProjectPlanning.hs | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index e71995a3682..b87540504fa 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -2313,7 +2313,7 @@ elaborateInstallPlan elabHaddockTargets = [] elabBuildHaddocks = - perPkgOptionFlag pkgid False packageConfigDocumentation + perPkgOptionFlag False pkgid packageConfigDocumentation -- `documentation: true` should imply `-haddock` for GHC addHaddockIfDocumentationEnabled :: ConfiguredProgram -> ConfiguredProgram @@ -2361,35 +2361,35 @@ elaborateInstallPlan -- 'elabBuildOptions' accurately reflects what will actually be built. elabBuildOptionsRaw = LBC.BuildOptions - { withVanillaLib = perPkgOptionFlag pkgid True packageConfigVanillaLib -- TODO: [required feature]: also needs to be handled recursively + { withVanillaLib = perPkgOptionFlag True pkgid packageConfigVanillaLib -- TODO: [required feature]: also needs to be handled recursively , withSharedLib = canBuildSharedLibs && pkgid `Set.member` pkgsUseSharedLibrary - , withStaticLib = perPkgOptionFlag pkgid False packageConfigStaticLib + , withStaticLib = perPkgOptionFlag False pkgid packageConfigStaticLib , withDynExe = - perPkgOptionFlag pkgid False packageConfigDynExe + perPkgOptionFlag False pkgid packageConfigDynExe -- We can't produce a dynamic executable if the user -- wants to enable executable profiling but the -- compiler doesn't support prof+dyn. && (okProfDyn || not profExe) - , withFullyStaticExe = perPkgOptionFlag pkgid False packageConfigFullyStaticExe - , withGHCiLib = perPkgOptionFlag pkgid False packageConfigGHCiLib -- TODO: [required feature] needs to default to enabled on windows still + , withFullyStaticExe = perPkgOptionFlag False pkgid packageConfigFullyStaticExe + , withGHCiLib = perPkgOptionFlag False pkgid packageConfigGHCiLib -- TODO: [required feature] needs to default to enabled on windows still , withProfExe = profExe , withProfLib = canBuildProfilingLibs && pkgid `Set.member` pkgsUseProfilingLibrary , withProfLibShared = canBuildProfilingSharedLibs && pkgid `Set.member` pkgsUseProfilingLibraryShared - , withBytecodeLib = perPkgOptionFlag pkgid False packageConfigBytecodeLib - , exeCoverage = perPkgOptionFlag pkgid False packageConfigCoverage - , libCoverage = perPkgOptionFlag pkgid False packageConfigCoverage - , withOptimization = perPkgOptionFlag pkgid NormalOptimisation packageConfigOptimization - , splitObjs = perPkgOptionFlag pkgid False packageConfigSplitObjs - , splitSections = perPkgOptionFlag pkgid False packageConfigSplitSections - , stripLibs = perPkgOptionFlag pkgid False packageConfigStripLibs - , stripExes = perPkgOptionFlag pkgid False packageConfigStripExes - , withDebugInfo = perPkgOptionFlag pkgid NoDebugInfo packageConfigDebugInfo - , relocatable = perPkgOptionFlag pkgid False packageConfigRelocatable + , withBytecodeLib = perPkgOptionFlag False pkgid packageConfigBytecodeLib + , exeCoverage = perPkgOptionFlag False pkgid packageConfigCoverage + , libCoverage = perPkgOptionFlag False pkgid packageConfigCoverage + , withOptimization = perPkgOptionFlag NormalOptimisation pkgid packageConfigOptimization + , splitObjs = perPkgOptionFlag False pkgid packageConfigSplitObjs + , splitSections = perPkgOptionFlag False pkgid packageConfigSplitSections + , stripLibs = perPkgOptionFlag False pkgid packageConfigStripLibs + , stripExes = perPkgOptionFlag False pkgid packageConfigStripExes + , withDebugInfo = perPkgOptionFlag NoDebugInfo pkgid packageConfigDebugInfo + , relocatable = perPkgOptionFlag False pkgid packageConfigRelocatable , withProfLibDetail = elabProfExeDetail , withProfExeDetail = elabProfLibDetail } okProfDyn = profilingDynamicSupportedOrUnknown compiler - profExe = perPkgOptionFlag pkgid False packageConfigProf + profExe = perPkgOptionFlag False pkgid packageConfigProf elabBuildOptions = Cabal.adjustBuildOptions compiler compilerprogdb elabBuildOptionsRaw @@ -2402,7 +2402,7 @@ elaborateInstallPlan packageConfigProfDetail packageConfigProfLibDetail - elabDumpBuildInfo = perPkgOptionFlag pkgid NoDumpBuildInfo packageConfigDumpBuildInfo + elabDumpBuildInfo = perPkgOptionFlag NoDumpBuildInfo pkgid packageConfigDumpBuildInfo -- Combine the configured compiler prog settings with the user-supplied -- config. For the compiler progs any user-supplied config was taken @@ -2450,32 +2450,32 @@ elaborateInstallPlan elabProgPrefix = perPkgOptionMaybe pkgid packageConfigProgPrefix elabProgSuffix = perPkgOptionMaybe pkgid packageConfigProgSuffix - elabHaddockHoogle = perPkgOptionFlag pkgid False packageConfigHaddockHoogle - elabHaddockHtml = perPkgOptionFlag pkgid False packageConfigHaddockHtml + elabHaddockHoogle = perPkgOptionFlag False pkgid packageConfigHaddockHoogle + elabHaddockHtml = perPkgOptionFlag False pkgid packageConfigHaddockHtml elabHaddockHtmlLocation = perPkgOptionMaybe pkgid packageConfigHaddockHtmlLocation - elabHaddockForeignLibs = perPkgOptionFlag pkgid False packageConfigHaddockForeignLibs - elabHaddockForHackage = perPkgOptionFlag pkgid Cabal.ForDevelopment packageConfigHaddockForHackage - elabHaddockExecutables = perPkgOptionFlag pkgid False packageConfigHaddockExecutables - elabHaddockTestSuites = perPkgOptionFlag pkgid False packageConfigHaddockTestSuites - elabHaddockBenchmarks = perPkgOptionFlag pkgid False packageConfigHaddockBenchmarks - elabHaddockInternal = perPkgOptionFlag pkgid False packageConfigHaddockInternal + elabHaddockForeignLibs = perPkgOptionFlag False pkgid packageConfigHaddockForeignLibs + elabHaddockForHackage = perPkgOptionFlag Cabal.ForDevelopment pkgid packageConfigHaddockForHackage + elabHaddockExecutables = perPkgOptionFlag False pkgid packageConfigHaddockExecutables + elabHaddockTestSuites = perPkgOptionFlag False pkgid packageConfigHaddockTestSuites + elabHaddockBenchmarks = perPkgOptionFlag False pkgid packageConfigHaddockBenchmarks + elabHaddockInternal = perPkgOptionFlag False pkgid packageConfigHaddockInternal elabHaddockCss = perPkgOptionMaybe pkgid packageConfigHaddockCss - elabHaddockLinkedSource = perPkgOptionFlag pkgid False packageConfigHaddockLinkedSource - elabHaddockQuickJump = perPkgOptionFlag pkgid False packageConfigHaddockQuickJump + elabHaddockLinkedSource = perPkgOptionFlag False pkgid packageConfigHaddockLinkedSource + elabHaddockQuickJump = perPkgOptionFlag False pkgid packageConfigHaddockQuickJump elabHaddockHscolourCss = perPkgOptionMaybe pkgid packageConfigHaddockHscolourCss elabHaddockContents = perPkgOptionMaybe pkgid packageConfigHaddockContents elabHaddockIndex = perPkgOptionMaybe pkgid packageConfigHaddockIndex elabHaddockBaseUrl = perPkgOptionMaybe pkgid packageConfigHaddockBaseUrl elabHaddockResourcesDir = perPkgOptionMaybe pkgid packageConfigHaddockResourcesDir elabHaddockOutputDir = perPkgOptionMaybe pkgid packageConfigHaddockOutputDir - elabHaddockUseUnicode = perPkgOptionFlag pkgid False packageConfigHaddockUseUnicode + elabHaddockUseUnicode = perPkgOptionFlag False pkgid packageConfigHaddockUseUnicode elabTestMachineLog = perPkgOptionMaybe pkgid packageConfigTestMachineLog elabTestHumanLog = perPkgOptionMaybe pkgid packageConfigTestHumanLog elabTestShowDetails = perPkgOptionMaybe pkgid packageConfigTestShowDetails - elabTestKeepTix = perPkgOptionFlag pkgid False packageConfigTestKeepTix + elabTestKeepTix = perPkgOptionFlag False pkgid packageConfigTestKeepTix elabTestWrapper = perPkgOptionMaybe pkgid packageConfigTestWrapper - elabTestFailWhenNoTestSuites = perPkgOptionFlag pkgid False packageConfigTestFailWhenNoTestSuites + elabTestFailWhenNoTestSuites = perPkgOptionFlag False pkgid packageConfigTestFailWhenNoTestSuites elabTestTestOptions = perPkgOptionList pkgid packageConfigTestTestOptions elabBenchmarkOptions = perPkgOptionList pkgid packageConfigBenchmarkOptions @@ -2483,10 +2483,10 @@ elaborateInstallPlan perPkgOption :: (Package pkg, Monoid m) => pkg -> (PackageConfig -> m) -> m perPkgOption = lookupPerPkgOption isLocalToProject allPackagesConfig localPackagesConfig perPackageConfig - perPkgOptionFlag :: PackageId -> a -> (PackageConfig -> Flag a) -> a + perPkgOptionFlag :: a -> PackageId -> (PackageConfig -> Flag a) -> a perPkgOptionMaybe :: PackageId -> (PackageConfig -> Flag a) -> Maybe a perPkgOptionList :: PackageId -> (PackageConfig -> [a]) -> [a] - perPkgOptionFlag pkgid def f = fromFlagOrDefault def (perPkgOption pkgid f) + perPkgOptionFlag def pkgid f = fromFlagOrDefault def (perPkgOption pkgid f) perPkgOptionMaybe pkgid f = flagToMaybe (perPkgOption pkgid f) perPkgOptionList pkgid f = perPkgOption pkgid f perPkgOptionNubList pkgid f = fromNubList (perPkgOption pkgid f) From 913199e996dee364e8a15ded2a581f8e86ba20e7 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 10:33:17 -0400 Subject: [PATCH 09/26] Use function composition for perPkgOption* --- .../src/Distribution/Client/ProjectPlanning.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index b87540504fa..07027ff9b09 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -2486,12 +2486,12 @@ elaborateInstallPlan perPkgOptionFlag :: a -> PackageId -> (PackageConfig -> Flag a) -> a perPkgOptionMaybe :: PackageId -> (PackageConfig -> Flag a) -> Maybe a perPkgOptionList :: PackageId -> (PackageConfig -> [a]) -> [a] - perPkgOptionFlag def pkgid f = fromFlagOrDefault def (perPkgOption pkgid f) - perPkgOptionMaybe pkgid f = flagToMaybe (perPkgOption pkgid f) - perPkgOptionList pkgid f = perPkgOption pkgid f - perPkgOptionNubList pkgid f = fromNubList (perPkgOption pkgid f) - perPkgOptionMapLast pkgid f = getMapLast (perPkgOption pkgid f) - perPkgOptionMapMappend pkgid f = getMapMappend (perPkgOption pkgid f) + perPkgOptionFlag def = fmap (fromFlagOrDefault def) . perPkgOption + perPkgOptionMaybe = fmap flagToMaybe . perPkgOption + perPkgOptionList = perPkgOption + perPkgOptionNubList = fmap fromNubList . perPkgOption + perPkgOptionMapLast = fmap getMapLast . perPkgOption + perPkgOptionMapMappend = fmap getMapMappend . perPkgOption perPkgOptionLibExeFlag pkgid def fboth flib = (exe, lib) where From 5e399c9e20ac5f8ab309bbc7f71082140181363a Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 10:54:47 -0400 Subject: [PATCH 10/26] Add type sigs for all perPkgOption* functions --- .../src/Distribution/Client/ProjectPlanning.hs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 07027ff9b09..f67913a562e 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -4,6 +4,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} -- | @@ -2397,8 +2398,8 @@ elaborateInstallPlan , elabProfLibDetail ) = perPkgOptionLibExeFlag - pkgid ProfDetailDefault + pkgid packageConfigProfDetail packageConfigProfLibDetail @@ -2484,16 +2485,25 @@ elaborateInstallPlan perPkgOption = lookupPerPkgOption isLocalToProject allPackagesConfig localPackagesConfig perPackageConfig perPkgOptionFlag :: a -> PackageId -> (PackageConfig -> Flag a) -> a - perPkgOptionMaybe :: PackageId -> (PackageConfig -> Flag a) -> Maybe a - perPkgOptionList :: PackageId -> (PackageConfig -> [a]) -> [a] perPkgOptionFlag def = fmap (fromFlagOrDefault def) . perPkgOption + + perPkgOptionMaybe :: PackageId -> (PackageConfig -> Flag a) -> Maybe a perPkgOptionMaybe = fmap flagToMaybe . perPkgOption + + perPkgOptionList :: PackageId -> (PackageConfig -> [a]) -> [a] perPkgOptionList = perPkgOption + + perPkgOptionNubList :: PackageId -> (PackageConfig -> NubList FilePath) -> [FilePath] perPkgOptionNubList = fmap fromNubList . perPkgOption + + perPkgOptionMapLast :: Ord k => PackageId -> (PackageConfig -> MapLast k v) -> Map k v perPkgOptionMapLast = fmap getMapLast . perPkgOption + + perPkgOptionMapMappend :: (Ord k, Semigroup v) => PackageId -> (PackageConfig -> MapMappend k v) -> Map k v perPkgOptionMapMappend = fmap getMapMappend . perPkgOption - perPkgOptionLibExeFlag pkgid def fboth flib = (exe, lib) + perPkgOptionLibExeFlag :: a -> PackageId -> (PackageConfig -> Flag a) -> (PackageConfig -> Flag a) -> (a, a) + perPkgOptionLibExeFlag def pkgid fboth flib = (exe, lib) where exe = fromFlagOrDefault def bothflag lib = fromFlagOrDefault def (bothflag <> libflag) From ab32feef0f82ab935a55c310071867250c32edfa Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 11:02:10 -0400 Subject: [PATCH 11/26] Inline each perPkgOption* only used once --- .../src/Distribution/Client/ProjectPlanning.hs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index f67913a562e..4477e621b74 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -2415,7 +2415,8 @@ elaborateInstallPlan [ (programId prog, programPath prog) | prog <- configuredPrograms compilerprogdb ] - <> perPkgOptionMapLast pkgid packageConfigProgramPaths + <> (getMapLast $ perPkgOption pkgid packageConfigProgramPaths) + elabProgramArgs = -- Workaround for -- @@ -2440,8 +2441,9 @@ elaborateInstallPlan , not (null args) ] ) - (perPkgOptionMapMappend pkgid packageConfigProgramArgs) - elabProgramPathExtra = perPkgOptionNubList pkgid packageConfigProgramPathExtra + (getMapMappend $ perPkgOption pkgid packageConfigProgramArgs) + + elabProgramPathExtra = fromNubList $ perPkgOption pkgid packageConfigProgramPathExtra elabConfiguredPrograms = configuredPrograms compilerprogdb elabConfigureScriptArgs = perPkgOptionList pkgid packageConfigConfigureArgs elabExtraLibDirs = perPkgOptionList pkgid packageConfigExtraLibDirs @@ -2493,15 +2495,6 @@ elaborateInstallPlan perPkgOptionList :: PackageId -> (PackageConfig -> [a]) -> [a] perPkgOptionList = perPkgOption - perPkgOptionNubList :: PackageId -> (PackageConfig -> NubList FilePath) -> [FilePath] - perPkgOptionNubList = fmap fromNubList . perPkgOption - - perPkgOptionMapLast :: Ord k => PackageId -> (PackageConfig -> MapLast k v) -> Map k v - perPkgOptionMapLast = fmap getMapLast . perPkgOption - - perPkgOptionMapMappend :: (Ord k, Semigroup v) => PackageId -> (PackageConfig -> MapMappend k v) -> Map k v - perPkgOptionMapMappend = fmap getMapMappend . perPkgOption - perPkgOptionLibExeFlag :: a -> PackageId -> (PackageConfig -> Flag a) -> (PackageConfig -> Flag a) -> (a, a) perPkgOptionLibExeFlag def pkgid fboth flib = (exe, lib) where From a0f9bb93039b5bbf55bf6865b07d68f1b0494dfb Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 11:12:32 -0400 Subject: [PATCH 12/26] Use -XViewPatterns in perPkgOptionLibExeFlag --- .../src/Distribution/Client/ProjectPlanning.hs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 4477e621b74..daf633c73aa 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -6,6 +6,7 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE ViewPatterns #-} -- | -- /Elaborated: worked out with great care and nicety of detail; executed with great minuteness: elaborate preparations; elaborate care./ @@ -2496,13 +2497,8 @@ elaborateInstallPlan perPkgOptionList = perPkgOption perPkgOptionLibExeFlag :: a -> PackageId -> (PackageConfig -> Flag a) -> (PackageConfig -> Flag a) -> (a, a) - perPkgOptionLibExeFlag def pkgid fboth flib = (exe, lib) - where - exe = fromFlagOrDefault def bothflag - lib = fromFlagOrDefault def (bothflag <> libflag) - - bothflag = perPkgOption pkgid fboth - libflag = perPkgOption pkgid flib + perPkgOptionLibExeFlag (fromFlagOrDefault -> f) pkgid (perPkgOption pkgid -> both) (perPkgOption pkgid -> lib) = + (f both, f (both <> lib)) inplacePackageDbs = corePackageDbs From c9acd9e06f04d1df96bbd5129748fe3fd7c0609a Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 11:26:16 -0400 Subject: [PATCH 13/26] Follow hlint suggestion: move bracket to avoid $ --- cabal-install/src/Distribution/Client/ProjectPlanning.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index daf633c73aa..6f610dee7aa 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -2416,7 +2416,7 @@ elaborateInstallPlan [ (programId prog, programPath prog) | prog <- configuredPrograms compilerprogdb ] - <> (getMapLast $ perPkgOption pkgid packageConfigProgramPaths) + <> getMapLast (perPkgOption pkgid packageConfigProgramPaths) elabProgramArgs = -- Workaround for From 8c096b3a301616c40efa4a2a5bef95618364419f Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 11:36:01 -0400 Subject: [PATCH 14/26] Partially apply then use lookupPerPkgOption --- .../src/Distribution/Client/ProjectPlanning.hs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 6f610dee7aa..f07dc4cdbd9 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -872,28 +872,19 @@ rebuildInstallPlan let pkgname = pkgSpecifierTarget pkg stanzas = case shouldBeLocal pkg of Just pkgId -> - let testsEnabled = + let perPkgOption = lookupPerPkgOption (const True) projectConfigAllPackages projectConfigLocalPackages (getMapMappend projectConfigSpecificPackage) pkgId - packageConfigTests - benchmarksEnabled = - lookupPerPkgOption - (const True) - projectConfigAllPackages - projectConfigLocalPackages - (getMapMappend projectConfigSpecificPackage) - pkgId - packageConfigBenchmarks in Map.fromList $ [ (TestStanzas, enabled) - | enabled <- flagToList testsEnabled + | enabled <- flagToList $ perPkgOption packageConfigTests ] ++ [ (BenchStanzas, enabled) - | enabled <- flagToList benchmarksEnabled + | enabled <- flagToList $ perPkgOption packageConfigBenchmarks ] Nothing -> Map.fromList [(TestStanzas, False), (BenchStanzas, False)] ] From 860a8fb9487cbdabbcb767e2425ce01c2c3c26ca Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 11:57:04 -0400 Subject: [PATCH 15/26] Move Map.fromList in list comprehension --- .../Distribution/Client/ProjectPlanning.hs | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index f07dc4cdbd9..661e372e28c 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -5,6 +5,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} @@ -860,10 +861,11 @@ rebuildInstallPlan solverSettings = resolveSolverSettings projectConfig logMsg message rest = debugNoWrap verbosity message >> rest + perPkgOption = lookupPerPkgOption (const True) projectConfigAllPackages projectConfigLocalPackages (getMapMappend projectConfigSpecificPackage) localPackagesEnabledStanzas = Map.fromList - [ (pkgname, stanzas) + [ (pkgname, Map.fromList $ stanzas) | pkg <- localPackages , -- TODO: misnomer: we should separate -- builtin/global/inplace/local packages @@ -872,21 +874,9 @@ rebuildInstallPlan let pkgname = pkgSpecifierTarget pkg stanzas = case shouldBeLocal pkg of Just pkgId -> - let perPkgOption = - lookupPerPkgOption - (const True) - projectConfigAllPackages - projectConfigLocalPackages - (getMapMappend projectConfigSpecificPackage) - pkgId - in Map.fromList $ - [ (TestStanzas, enabled) - | enabled <- flagToList $ perPkgOption packageConfigTests - ] - ++ [ (BenchStanzas, enabled) - | enabled <- flagToList $ perPkgOption packageConfigBenchmarks - ] - Nothing -> Map.fromList [(TestStanzas, False), (BenchStanzas, False)] + ((TestStanzas,) <$> flagToList (perPkgOption pkgId packageConfigTests)) + ++ ((BenchStanzas,) <$> flagToList (perPkgOption pkgId packageConfigBenchmarks)) + Nothing -> [(TestStanzas, False), (BenchStanzas, False)] ] -- Elaborate the solver's install plan to get a fully detailed plan. This From ff99885e5d687381564ea7db0ee065c522cc3286 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 12:11:30 -0400 Subject: [PATCH 16/26] Use -XViewPattern in Just pkgId branch --- cabal-install/src/Distribution/Client/ProjectPlanning.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 661e372e28c..7c9fc4ccd77 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -865,7 +865,7 @@ rebuildInstallPlan localPackagesEnabledStanzas = Map.fromList - [ (pkgname, Map.fromList $ stanzas) + [ (pkgname, Map.fromList stanzas) | pkg <- localPackages , -- TODO: misnomer: we should separate -- builtin/global/inplace/local packages @@ -873,9 +873,9 @@ rebuildInstallPlan -- let pkgname = pkgSpecifierTarget pkg stanzas = case shouldBeLocal pkg of - Just pkgId -> - ((TestStanzas,) <$> flagToList (perPkgOption pkgId packageConfigTests)) - ++ ((BenchStanzas,) <$> flagToList (perPkgOption pkgId packageConfigBenchmarks)) + Just (fmap flagToList . perPkgOption -> f) -> + ((TestStanzas,) <$> f packageConfigTests) + ++ ((BenchStanzas,) <$> f packageConfigBenchmarks) Nothing -> [(TestStanzas, False), (BenchStanzas, False)] ] From c717ba158b33bf31968d06409dfc911a5e860b37 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 12:19:39 -0400 Subject: [PATCH 17/26] Defer (TestStanzas,) & (BenechStanzas,) tuples --- .../src/Distribution/Client/ProjectPlanning.hs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 7c9fc4ccd77..27b5a73900f 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -865,18 +865,16 @@ rebuildInstallPlan localPackagesEnabledStanzas = Map.fromList - [ (pkgname, Map.fromList stanzas) + [ (pkgname, Map.fromList $ ((TestStanzas,) <$> tests) ++ ((BenchStanzas,) <$> benches)) | pkg <- localPackages , -- TODO: misnomer: we should separate -- builtin/global/inplace/local packages -- and packages explicitly mentioned in the project -- let pkgname = pkgSpecifierTarget pkg - stanzas = case shouldBeLocal pkg of - Just (fmap flagToList . perPkgOption -> f) -> - ((TestStanzas,) <$> f packageConfigTests) - ++ ((BenchStanzas,) <$> f packageConfigBenchmarks) - Nothing -> [(TestStanzas, False), (BenchStanzas, False)] + (tests, benches) = case shouldBeLocal pkg of + Just (fmap flagToList . perPkgOption -> f) -> (f packageConfigTests, f packageConfigBenchmarks) + Nothing -> ([False], [False]) ] -- Elaborate the solver's install plan to get a fully detailed plan. This From 899791bf6c588b971e0762d9c4cf415c5b41bfc5 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 12:21:42 -0400 Subject: [PATCH 18/26] Move awkwardly formatted TODO comment --- .../src/Distribution/Client/ProjectPlanning.hs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 27b5a73900f..89421ce16b0 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -863,18 +863,17 @@ rebuildInstallPlan logMsg message rest = debugNoWrap verbosity message >> rest perPkgOption = lookupPerPkgOption (const True) projectConfigAllPackages projectConfigLocalPackages (getMapMappend projectConfigSpecificPackage) + -- TODO: "local" misnomer: we should separate + -- builtin/global/inplace/local packages and packages explicitly + -- mentioned in the project. localPackagesEnabledStanzas = Map.fromList [ (pkgname, Map.fromList $ ((TestStanzas,) <$> tests) ++ ((BenchStanzas,) <$> benches)) | pkg <- localPackages - , -- TODO: misnomer: we should separate - -- builtin/global/inplace/local packages - -- and packages explicitly mentioned in the project - -- - let pkgname = pkgSpecifierTarget pkg - (tests, benches) = case shouldBeLocal pkg of - Just (fmap flagToList . perPkgOption -> f) -> (f packageConfigTests, f packageConfigBenchmarks) - Nothing -> ([False], [False]) + , let pkgname = pkgSpecifierTarget pkg + , let (tests, benches) = case shouldBeLocal pkg of + Just (fmap flagToList . perPkgOption -> f) -> (f packageConfigTests, f packageConfigBenchmarks) + Nothing -> ([False], [False]) ] -- Elaborate the solver's install plan to get a fully detailed plan. This From df22277f4369cbbd08c34bc7453dc0221143a05e Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 12:23:49 -0400 Subject: [PATCH 19/26] Mark a comment for REVIEW --- cabal-install/src/Distribution/Client/ProjectConfig.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 247e63c91ba..069f4c170a9 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -878,7 +878,7 @@ readProjectFileSkeletonGen monitorFiles [monitorNonExistentFile extensionFile] return mempty where - -- Do we prefer absolute paths for cache monitoring? + -- REVIEW: Do we prefer absolute paths for cache monitoring? makeAbsolute f | isAbsolute f = f | otherwise = distProjectRootDirectory dir f From b09adb13d6c4986e0bcdeff91229f8f39bce5e41 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 12:28:15 -0400 Subject: [PATCH 20/26] Don't use cabal.project.[foo|bar] in note --- cabal-install/src/Distribution/Client/ProjectConfig.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 069f4c170a9..6fda1e2b081 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -862,10 +862,10 @@ readProjectFileSkeletonGen -- We also need to monitor all the (possibly recursive) imports. -- 'projectSkeletonImports' is a path per imported project file that starts with the leaf -- and ends with the main project file that is the root. E.g. if 'cabal.project' imports - -- 'cabal.project.foo', which imports 'cabal.project.bar', then we get two paths: + -- 'importee-1.config', which imports 'importee-2.config', then we get two paths: -- - -- > ("cabal.project.bar" :| ["cabal.project.foo", "cabal.project"]) - -- > ("cabal.project.foo" :| ["cabal.project"]) + -- > ("importee-2.config" :| ["importee-1.config", "cabal.project"]) + -- > ("importee-1.config" :| ["cabal.project"]) -- -- Consequently, we just take the heads of all the paths. monitorFiles From 2d9904675a8970703aab325cc55451eec270bf36 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 12:29:25 -0400 Subject: [PATCH 21/26] Don't change haddocks, but word wrap --- cabal-install/src/Distribution/Client/ProjectConfig.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 6fda1e2b081..cfb518c5ee9 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -840,8 +840,9 @@ readProjectLocalFreezeConfig verbosity parserOption httpTransport distDirLayout "freeze" "project freeze file" --- | Reads a named extended (with imports and conditionals) config file in the given project root dir, or returns empty. --- This function is generic and can be used with the legacy or parsec parser, or a combination of both. +-- | Reads a named extended (with imports and conditionals) config file in the +-- given project root dir, or returns empty. This function is generic and can +-- be used with the legacy or parsec parser, or a combination of both. readProjectFileSkeletonGen :: Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> (FilePath -> IO ProjectConfigSkeleton) -> Rebuild ProjectConfigSkeleton readProjectFileSkeletonGen verbosity From b055f5364ca0dd00fe78079406859dd7d501ee5f Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 13:19:54 -0400 Subject: [PATCH 22/26] Take more care and expand monitoring notes --- .../src/Distribution/Client/ProjectConfig.hs | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index cfb518c5ee9..71677b6a619 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -848,30 +848,49 @@ readProjectFileSkeletonGen verbosity httpTransport dir - extensionName + extensionName@(distProjectFile dir -> extensionFile) extensionDescription parseConfig = do exists <- liftIO $ doesFileExist extensionFile if exists then do - -- Monitor the "main" project file (this could be e.g. 'cabal.project', 'cabal.project.freeze' or - -- 'cabal.project.local'. - monitorFiles [monitorFileHashed extensionFile] - pcs <- liftIO $ parseConfig extensionFile - - -- We also need to monitor all the (possibly recursive) imports. - -- 'projectSkeletonImports' is a path per imported project file that starts with the leaf - -- and ends with the main project file that is the root. E.g. if 'cabal.project' imports - -- 'importee-1.config', which imports 'importee-2.config', then we get two paths: + pcs@(projectSkeletonImports -> allProjectFiles) <- liftIO $ parseConfig extensionFile + + -- If we have with .local or .freeze extension, these + -- aren't normally imported but there's nothing stopping the user from + -- importing them, so we throw them in with the other project files. + let additional = + if (isExtensionOf "local" extensionName || isExtensionOf "freeze" extensionName) + then [extensionFile] + else [] + + -- We need to monitor the project and all of its local imports, We + -- can't monitor remote URI imports. + -- + -- We don't allow duplicate import paths but we do allow multiple + -- imports of the same file by different paths so we'll want to take + -- care to only monitor each file once. There should only ever be one + -- root 'cabal.project' file. + -- + -- In the simple case, if 'cabal.project' imports 'importee-1.config', + -- which imports 'importee-2.config', then we get these paths from + -- 'projectSkeletonImports': -- -- > ("importee-2.config" :| ["importee-1.config", "cabal.project"]) -- > ("importee-1.config" :| ["cabal.project"]) + -- > ("cabal.project" :| []) -- - -- Consequently, we just take the heads of all the paths. + -- 'currentProjectConfigPath' gives us the head of the path, an + -- importee or the root project file. monitorFiles - [ monitorFileHashed $ makeAbsolute path - | (Nothing, currentProjectConfigPath -> path) <- projectSkeletonImports pcs + [ monitorFileHashed path + | path <- + ordNub $ + additional + ++ [ p + | (Nothing, makeAbsolute . currentProjectConfigPath -> p) <- allProjectFiles + ] ] return pcs @@ -883,7 +902,6 @@ readProjectFileSkeletonGen makeAbsolute f | isAbsolute f = f | otherwise = distProjectRootDirectory dir f - extensionFile = (distProjectFile dir) extensionName -- There are 3 different variants of the project parsing function. -- 1. readProjectFileSkeletonLegacy: always uses the legacy parser From d18f91f9bd5b306f9e4a4d906021c100b5bd0e16 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 13:20:56 -0400 Subject: [PATCH 23/26] Follow hlint suggestion: use list comprehension --- cabal-install/src/Distribution/Client/ProjectConfig.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 71677b6a619..5c6ecbfa430 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -861,9 +861,7 @@ readProjectFileSkeletonGen -- aren't normally imported but there's nothing stopping the user from -- importing them, so we throw them in with the other project files. let additional = - if (isExtensionOf "local" extensionName || isExtensionOf "freeze" extensionName) - then [extensionFile] - else [] + ([extensionFile | isExtensionOf "local" extensionName || isExtensionOf "freeze" extensionName]) -- We need to monitor the project and all of its local imports, We -- can't monitor remote URI imports. From 4820e7c3639322c92943664bda9df84921495da2 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 13:34:43 -0400 Subject: [PATCH 24/26] Reduce diff --- cabal-install/src/Distribution/Client/ProjectPlanning.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 89421ce16b0..3a7bc33a35d 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -2462,9 +2462,6 @@ elaborateInstallPlan elabBenchmarkOptions = perPkgOptionList pkgid packageConfigBenchmarkOptions - perPkgOption :: (Package pkg, Monoid m) => pkg -> (PackageConfig -> m) -> m - perPkgOption = lookupPerPkgOption isLocalToProject allPackagesConfig localPackagesConfig perPackageConfig - perPkgOptionFlag :: a -> PackageId -> (PackageConfig -> Flag a) -> a perPkgOptionFlag def = fmap (fromFlagOrDefault def) . perPkgOption @@ -2478,6 +2475,9 @@ elaborateInstallPlan perPkgOptionLibExeFlag (fromFlagOrDefault -> f) pkgid (perPkgOption pkgid -> both) (perPkgOption pkgid -> lib) = (f both, f (both <> lib)) + perPkgOption :: (Package pkg, Monoid m) => pkg -> (PackageConfig -> m) -> m + perPkgOption = lookupPerPkgOption isLocalToProject allPackagesConfig localPackagesConfig perPackageConfig + inplacePackageDbs = corePackageDbs ++ [distPackageDB (compilerId compiler)] From 3f26f113988afda698656d62ce9912e035070c40 Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 13:42:12 -0400 Subject: [PATCH 25/26] Remove lookupLocalPackageConfig --- .../src/Distribution/Client/ProjectConfig.hs | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index 5c6ecbfa430..4121bfcb5d8 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig.hs @@ -60,7 +60,6 @@ module Distribution.Client.ProjectConfig , fetchAndReadSourcePackages -- * Resolving configuration - , lookupLocalPackageConfig , projectConfigWithBuilderRepoContext , projectConfigWithSolverRepoContext , SolverSettings (..) @@ -264,28 +263,6 @@ import Distribution.Solver.Types.ProjectConfigPath -- Resolving configuration to settings -- --- | Look up a 'PackageConfig' field in the 'ProjectConfig' for a specific --- 'PackageName'. This returns the configuration that applies to all local --- packages plus any package-specific configuration for this package. -lookupLocalPackageConfig - :: Monoid a - => (PackageConfig -> a) - -> ProjectConfig - -> PackageName - -> a -lookupLocalPackageConfig - field - ProjectConfig - { projectConfigLocalPackages - , projectConfigSpecificPackage - } - pkgname = - field projectConfigLocalPackages - <> maybe - mempty - field - (Map.lookup pkgname (getMapMappend projectConfigSpecificPackage)) - -- | Use a 'RepoContext' based on the 'BuildTimeSettings'. projectConfigWithBuilderRepoContext :: Verbosity From 43a50d1f653e8134e4d72cc5ae9645d38241a33c Mon Sep 17 00:00:00 2001 From: Phil de Joux Date: Tue, 26 May 2026 13:49:13 -0400 Subject: [PATCH 26/26] Add changelog entry --- changelog.d/11884.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 changelog.d/11884.md diff --git a/changelog.d/11884.md b/changelog.d/11884.md new file mode 100644 index 00000000000..82ab94bcf21 --- /dev/null +++ b/changelog.d/11884.md @@ -0,0 +1,12 @@ +--- +synopsis: Fix project file monitoring +packages: [cabal-install] +prs: 11884 +issues: 11567 +--- + +Watch for changes in all project files, the root `cabal.project` and all local +files it imports. We don't monitor remote URI imports. + +Remove `lookupLocalPackageConfig`, an export from module +`Distribution.Client.ProjectConfig`.