Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
aa60267
Monitor imported cabal.project files
hasufell Mar 4, 2026
3f18d4a
Satisfy fourmolu
philderbeast May 25, 2026
856fc3f
Undo removal of export of lookupLocalPackageConfig
philderbeast May 25, 2026
a236eed
Promote comment to haddocks
philderbeast May 26, 2026
3354bea
Reformat that fourmolu accepts
philderbeast May 26, 2026
165b380
Change the arg order for partial application
philderbeast May 26, 2026
99b6bb4
Rename lookupPerPkgOption' to perPkgOption
philderbeast May 26, 2026
c97a74f
Change arg order with perPkgOptionFlag, def first
philderbeast May 26, 2026
913199e
Use function composition for perPkgOption*
philderbeast May 26, 2026
5e399c9
Add type sigs for all perPkgOption* functions
philderbeast May 26, 2026
ab32fee
Inline each perPkgOption* only used once
philderbeast May 26, 2026
a0f9bb9
Use -XViewPatterns in perPkgOptionLibExeFlag
philderbeast May 26, 2026
c9acd9e
Follow hlint suggestion: move bracket to avoid $
philderbeast May 26, 2026
8c096b3
Partially apply then use lookupPerPkgOption
philderbeast May 26, 2026
860a8fb
Move Map.fromList in list comprehension
philderbeast May 26, 2026
ff99885
Use -XViewPattern in Just pkgId branch
philderbeast May 26, 2026
c717ba1
Defer (TestStanzas,) & (BenechStanzas,) tuples
philderbeast May 26, 2026
899791b
Move awkwardly formatted TODO comment
philderbeast May 26, 2026
df22277
Mark a comment for REVIEW
philderbeast May 26, 2026
b09adb1
Don't use cabal.project.[foo|bar] in note
philderbeast May 26, 2026
2d99046
Don't change haddocks, but word wrap
philderbeast May 26, 2026
b055f53
Take more care and expand monitoring notes
philderbeast May 26, 2026
d18f91f
Follow hlint suggestion: use list comprehension
philderbeast May 26, 2026
4820e7c
Reduce diff
philderbeast May 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions cabal-install/src/Distribution/Client/ProjectConfig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wno-unused-matches #-}

-- | Handling project configuration.
Expand Down Expand Up @@ -839,32 +840,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 <extensionName> 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
Expand Down
182 changes: 85 additions & 97 deletions cabal-install/src/Distribution/Client/ProjectPlanning.hs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Main (main) where

main :: IO ()
main = putStrLn "Hello, Haskell!"
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
packages: ./cabal-project-repro.cabal

package *
Tests: True

import: nested/hop.config
Original file line number Diff line number Diff line change
@@ -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'
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import: ../../test/tests-toggle.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import: deeply-nested/hop.config

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Main (main) where

main :: IO ()
main = puStrLn "Test suite not yet implemented."
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
package *
Tests: True
Loading