diff --git a/cabal-install/src/Distribution/Client/ProjectConfig.hs b/cabal-install/src/Distribution/Client/ProjectConfig.hs index a0eea1ac5cc..4121bfcb5d8 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 (..) @@ -263,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 @@ -839,32 +817,66 @@ 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 httpTransport dir - extensionName + extensionName@(distProjectFile dir -> extensionFile) extensionDescription parseConfig = do exists <- liftIO $ doesFileExist extensionFile if exists then do - monitorFiles [monitorFileHashed extensionFile] - pcs <- liftIO $ parseConfig extensionFile + 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 = + ([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. + -- + -- 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" :| []) + -- + -- 'currentProjectConfigPath' gives us the head of the path, an + -- importee or the root project file. monitorFiles - [ monitorFileHashed (projectConfigPathRoot path) - | (Nothing, path) <- projectSkeletonImports pcs + [ monitorFileHashed path + | path <- + ordNub $ + additional + ++ [ p + | (Nothing, makeAbsolute . currentProjectConfigPath -> p) <- allProjectFiles + ] ] + return pcs else do monitorFiles [monitorNonExistentFile extensionFile] return mempty where - extensionFile = (distProjectFile dir) extensionName + -- REVIEW: Do we prefer absolute paths for cache monitoring? + makeAbsolute f + | isAbsolute f = f + | otherwise = distProjectRootDirectory dir f -- There are 3 different variants of the project parsing function. -- 1. readProjectFileSkeletonLegacy: always uses the legacy parser diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index f2ace7ff3b5..3a7bc33a35d 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -4,7 +4,10 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE ViewPatterns #-} -- | -- /Elaborated: worked out with great care and nicety of detail; executed with great minuteness: elaborate preparations; elaborate care./ @@ -787,6 +790,9 @@ rebuildInstallPlan projectConfig@ProjectConfig { projectConfigShared , projectConfigBuildOnly + , projectConfigAllPackages + , projectConfigLocalPackages + , projectConfigSpecificPackage } (compiler, platform, progdb) localPackages @@ -855,37 +861,19 @@ rebuildInstallPlan solverSettings = resolveSolverSettings projectConfig 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, 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 - 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)] + , 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 @@ -2305,7 +2293,7 @@ elaborateInstallPlan elabHaddockTargets = [] elabBuildHaddocks = - perPkgOptionFlag pkgid False packageConfigDocumentation + perPkgOptionFlag False pkgid packageConfigDocumentation -- `documentation: true` should imply `-haddock` for GHC addHaddockIfDocumentationEnabled :: ConfiguredProgram -> ConfiguredProgram @@ -2353,35 +2341,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 @@ -2389,12 +2377,12 @@ elaborateInstallPlan , elabProfLibDetail ) = perPkgOptionLibExeFlag - pkgid ProfDetailDefault + pkgid 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 @@ -2406,7 +2394,8 @@ elaborateInstallPlan [ (programId prog, programPath prog) | prog <- configuredPrograms compilerprogdb ] - <> perPkgOptionMapLast pkgid packageConfigProgramPaths + <> getMapLast (perPkgOption pkgid packageConfigProgramPaths) + elabProgramArgs = -- Workaround for -- @@ -2431,8 +2420,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 @@ -2442,73 +2432,51 @@ 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 - perPkgOptionFlag :: PackageId -> a -> (PackageConfig -> Flag a) -> a + perPkgOptionFlag :: a -> PackageId -> (PackageConfig -> Flag 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 - 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 :: a -> PackageId -> (PackageConfig -> Flag a) -> (PackageConfig -> Flag a) -> (a, a) + perPkgOptionLibExeFlag (fromFlagOrDefault -> f) pkgid (perPkgOption pkgid -> both) (perPkgOption pkgid -> lib) = + (f both, f (both <> lib)) - 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 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) + perPkgOption :: (Package pkg, Monoid m) => pkg -> (PackageConfig -> m) -> m + perPkgOption = lookupPerPkgOption isLocalToProject allPackagesConfig localPackagesConfig perPackageConfig inplacePackageDbs = corePackageDbs @@ -2624,8 +2592,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 = @@ -4666,3 +4634,23 @@ 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 -> Bool) + -> PackageConfig + -> PackageConfig + -> Map PackageName PackageConfig + -> pkg + -> (PackageConfig -> m) + -> m +lookupPerPkgOption isLocalPkg allPackagesConfig localPackagesConfig perPackageConfig pkg f = + 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 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`.