Skip to content

Commit a9bd253

Browse files
authored
Merge pull request #11995 from cabalism/refactor/ProjectFileKey
Replace strings with ProjectFileKey
2 parents ed1cbcb + 08700c6 commit a9bd253

8 files changed

Lines changed: 101 additions & 61 deletions

File tree

cabal-install/parser-tests/Tests/ParserTests.hs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -567,16 +567,14 @@ readConfig testSubDir projectFileName = do
567567
exists <- liftIO $ doesFileExist projectConfigFp
568568
assertBool ("projectConfig does not exist: " <> projectConfigFp) exists
569569
httpTransport <- liftIO $ configureTransport verbosity [] Nothing
570-
let extensionName = ""
571-
extensionDescription = ""
572570
parsec <-
573571
liftIO $
574572
runRebuild testRootFp $
575-
readProjectFileSkeletonParsec verbosity httpTransport distDirLayout extensionName extensionDescription
573+
readProjectFileSkeletonParsec verbosity httpTransport distDirLayout ProjectFileKeyMain
576574
legacy <-
577575
liftIO $
578576
runRebuild testRootFp $
579-
readProjectFileSkeletonLegacy verbosity httpTransport distDirLayout extensionName extensionDescription
577+
readProjectFileSkeletonLegacy verbosity httpTransport distDirLayout ProjectFileKeyMain
580578
return (parsec, legacy)
581579

582580
assertConfigEquals :: (Eq a, Show a) => a -> ProjectConfigSkeleton -> ProjectConfigSkeleton -> (ProjectConfigSkeleton -> a) -> Assertion
@@ -602,8 +600,7 @@ testDirInfo testSubDir projectFileName = do
602600
let
603601
projectRoot = ProjectRootExplicit projectRootDir projectFileName
604602
distDirLayout = defaultDistDirLayout projectRoot Nothing Nothing
605-
extensionName = ""
606-
projectConfigFp = distProjectFile distDirLayout extensionName
603+
projectConfigFp = distProjectFile distDirLayout ProjectFileKeyMain
607604
return $ TestDir projectRootDir projectConfigFp distDirLayout
608605

609606
-- | Compares two lists element-wise using a comparison function.

cabal-install/src/Distribution/Client/CmdConfigure.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import Distribution.Simple.Utils
4949

5050
import Distribution.Client.DistDirLayout
5151
( DistDirLayout (..)
52+
, ProjectFileKey (ProjectFileKeyLocal)
5253
)
5354
import Distribution.Client.Errors
5455
import Distribution.Client.HttpUtils
@@ -131,7 +132,7 @@ configureAction' flags@NixStyleFlags{..} _extraArgs globalFlags = do
131132

132133
baseCtx <- establishProjectBaseContext v cliConfig OtherCommand
133134

134-
let localFile = distProjectFile (distDirLayout baseCtx) "local"
135+
let localFile = distProjectFile (distDirLayout baseCtx) ProjectFileKeyLocal
135136
-- If cabal.project.local already exists, and the flags allow, back up to cabal.project.local~
136137
let backups = fromFlagOrDefault True $ configBackup configExFlags
137138
appends = fromFlagOrDefault False $ configAppend configExFlags

cabal-install/src/Distribution/Client/CmdFreeze.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import Prelude ()
1212

1313
import Distribution.Client.DistDirLayout
1414
( DistDirLayout (distProjectFile)
15+
, ProjectFileKey (ProjectFileKeyFreeze)
1516
)
1617
import Distribution.Client.IndexUtils (ActiveRepos, TotalIndexState, filterSkippedActiveRepos)
1718
import qualified Distribution.Client.InstallPlan as InstallPlan
@@ -157,7 +158,7 @@ freezeAction flags extraArgs globalFlags = do
157158
else do
158159
writeProjectLocalFreezeConfig distDirLayout freezeConfig
159160
notice verbosity $
160-
"Wrote freeze file: " ++ distProjectFile distDirLayout "freeze"
161+
"Wrote freeze file: " ++ distProjectFile distDirLayout ProjectFileKeyFreeze
161162
where
162163
verbosity = cfgVerbosity normal flags
163164
cliConfig =

cabal-install/src/Distribution/Client/DistDirLayout.hs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE LambdaCase #-}
12
{-# LANGUAGE RecordWildCards #-}
23

34
-- |
@@ -8,8 +9,8 @@ module Distribution.Client.DistDirLayout
89
( -- * 'DistDirLayout'
910
DistDirLayout (..)
1011
, DistDirParams (..)
12+
, ProjectFileKey (..)
1113
, defaultDistDirLayout
12-
, distProjectFileMain
1314

1415
-- * 'ProjectRoot'
1516
, ProjectRoot (..)
@@ -71,16 +72,32 @@ data DistDirParams = DistDirParams
7172
-- Optimization
7273
}
7374

75+
-- | The principal project file is read and parsed. Its file name was either
76+
-- provided with the @--project-file@ option, or it had the default name of
77+
-- @cabal.project@.
78+
--
79+
-- Related ``.local`` and ``.freeze`` files are read and parsed separately.
80+
--
81+
-- This key datatype distinguishes between the different project files, so that
82+
-- we can give better error messages, such as encountering an unexpected
83+
-- extension to the principal project file or when a ``.local`` or ``.freeze``
84+
-- is itself passed as the principal project file or when either are explicitly
85+
-- imported. They should only ever be implicitly imported.
86+
data ProjectFileKey
87+
= ProjectFileKeyMain
88+
| ProjectFileKeyLocal
89+
| ProjectFileKeyFreeze
90+
deriving (Eq, Ord, Show)
91+
7492
-- | The layout of the project state directory. Traditionally this has been
7593
-- called the @dist@ directory.
7694
data DistDirLayout = DistDirLayout
7795
{ distProjectRootDirectory :: FilePath
7896
-- ^ The root directory of the project. Many other files are relative to
7997
-- this location (e.g. the @cabal.project@ file).
80-
, distProjectFile :: String -> FilePath
81-
-- ^ The @cabal.project@ file and related like @cabal.project.freeze@.
82-
-- The parameter is for the extension, like \"freeze\", or \"\" for the
83-
-- main file.
98+
, distProjectFile :: ProjectFileKey -> FilePath
99+
-- ^ Files that are project parsing roots, the main @cabal.project@ file and
100+
-- its related freeze file and local file.
84101
, distDirectory :: FilePath
85102
-- ^ The \"dist\" directory, which is the root of where cabal keeps all
86103
-- its state including the build artifacts from each package we build.
@@ -184,8 +201,11 @@ defaultDistDirLayout projectRoot mdistDirectory haddockOutputDir =
184201
distProjectRootDirectory :: FilePath
185202
distProjectRootDirectory = projectRootDir
186203

187-
distProjectFile :: String -> FilePath
188-
distProjectFile ext = projectFile <.> ext
204+
distProjectFile :: ProjectFileKey -> FilePath
205+
distProjectFile = \case
206+
ProjectFileKeyMain -> projectFile
207+
ProjectFileKeyLocal -> projectFile <.> "local"
208+
ProjectFileKeyFreeze -> projectFile <.> "freeze"
189209

190210
distDirectory :: FilePath
191211
distDirectory =
@@ -317,8 +337,3 @@ mkCabalDirLayout mstoreDir mlogDir = do
317337
cabalLogsDirectory <-
318338
maybe defaultLogsDir pure mlogDir
319339
pure $ CabalDirLayout{..}
320-
321-
-- | Given the 'DistDirLayout''s distProjectFile function, returns the
322-
-- main project file (i.e. cabal.project).
323-
distProjectFileMain :: (String -> FilePath) -> FilePath
324-
distProjectFileMain f = f ""

cabal-install/src/Distribution/Client/ProjectConfig.hs

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ import Distribution.Client.Config
121121
import Distribution.Client.DistDirLayout
122122
( CabalDirLayout (..)
123123
, DistDirLayout (..)
124+
, ProjectFileKey (..)
124125
, ProjectRoot (..)
125126
, defaultProjectFile
126127
)
@@ -786,11 +787,11 @@ readProjectLocalConfigOrDefault
786787
-> DistDirLayout
787788
-> Rebuild ProjectConfigSkeleton
788789
readProjectLocalConfigOrDefault verbosity parserOption httpTransport distDirLayout = do
789-
let projectFile = distProjectFile distDirLayout ""
790+
let projectFile = distProjectFile distDirLayout ProjectFileKeyMain
790791
usesExplicitProjectRoot <- liftIO $ doesFileExist projectFile
791792
if usesExplicitProjectRoot
792793
then do
793-
readProjectFileSkeleton parserOption verbosity httpTransport distDirLayout "" "project file"
794+
readProjectFileSkeleton parserOption verbosity httpTransport distDirLayout ProjectFileKeyMain
794795
else do
795796
monitorFiles [monitorNonExistentFile projectFile]
796797
return (singletonProjectConfigSkeleton defaultImplicitProjectConfig)
@@ -803,6 +804,13 @@ defaultImplicitProjectConfig =
803804
, projectConfigProvenance = Set.singleton Implicit
804805
}
805806

807+
-- | A human readable description of the project file.
808+
extensionDescription :: ProjectFileKey -> String
809+
extensionDescription = \case
810+
ProjectFileKeyMain -> "project file"
811+
ProjectFileKeyLocal -> "project local configuration file"
812+
ProjectFileKeyFreeze -> "project freeze file"
813+
806814
-- | Reads a @cabal.project.local@ file in the given project root dir,
807815
-- or returns empty. This file gets written by @cabal configure@, or in
808816
-- principle can be edited manually or by other tools.
@@ -818,8 +826,7 @@ readProjectLocalExtraConfig verbosity parserOption httpTransport distDirLayout =
818826
verbosity
819827
httpTransport
820828
distDirLayout
821-
"local"
822-
"project local configuration file"
829+
ProjectFileKeyLocal
823830

824831
-- | Reads a @cabal.project.freeze@ file in the given project root dir,
825832
-- or returns empty. This file gets written by @cabal freeze@, or in
@@ -836,18 +843,16 @@ readProjectLocalFreezeConfig verbosity parserOption httpTransport distDirLayout
836843
verbosity
837844
httpTransport
838845
distDirLayout
839-
"freeze"
840-
"project freeze file"
846+
ProjectFileKeyFreeze
841847

842848
-- | Reads a named extended (with imports and conditionals) config file in the given project root dir, or returns empty.
843849
-- This function is generic and can be used with the legacy or parsec parser, or a combination of both.
844-
readProjectFileSkeletonGen :: Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> (FilePath -> IO ProjectConfigSkeleton) -> Rebuild ProjectConfigSkeleton
850+
readProjectFileSkeletonGen :: Verbosity -> HttpTransport -> DistDirLayout -> ProjectFileKey -> (FilePath -> IO ProjectConfigSkeleton) -> Rebuild ProjectConfigSkeleton
845851
readProjectFileSkeletonGen
846852
verbosity
847853
httpTransport
848854
dir
849-
extensionName
850-
extensionDescription
855+
key
851856
parseConfig =
852857
do
853858
exists <- liftIO $ doesFileExist extensionFile
@@ -864,7 +869,7 @@ readProjectFileSkeletonGen
864869
monitorFiles [monitorNonExistentFile extensionFile]
865870
return mempty
866871
where
867-
extensionFile = distProjectFile dir extensionName
872+
extensionFile = distProjectFile dir key
868873

869874
-- There are 3 different variants of the project parsing function.
870875
-- 1. readProjectFileSkeletonLegacy: always uses the legacy parser
@@ -884,7 +889,7 @@ readProjectFileSkeletonGen
884889
-- 1. reportParseResult: reports legacy parse errors to the user
885890
-- 2. reportParseResultParsec: reports parsec parse errors to the user
886891

887-
readProjectFileSkeleton :: ProjectFileParser -> Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> Rebuild ProjectConfigSkeleton
892+
readProjectFileSkeleton :: ProjectFileParser -> Verbosity -> HttpTransport -> DistDirLayout -> ProjectFileKey -> Rebuild ProjectConfigSkeleton
888893
readProjectFileSkeleton option =
889894
case option of
890895
LegacyParser -> readProjectFileSkeletonLegacy
@@ -893,50 +898,50 @@ readProjectFileSkeleton option =
893898
CompareParser -> readProjectFileSkeletonCompare
894899

895900
-- | Read a project file using the legacy parser.
896-
readProjectFileSkeletonLegacy :: Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> Rebuild ProjectConfigSkeleton
897-
readProjectFileSkeletonLegacy verbosity httpTransport distDirLayout extensionName extensionDescription = do
898-
readProjectFileSkeletonGen verbosity httpTransport distDirLayout extensionName extensionDescription $ \fp -> do
901+
readProjectFileSkeletonLegacy :: Verbosity -> HttpTransport -> DistDirLayout -> ProjectFileKey -> Rebuild ProjectConfigSkeleton
902+
readProjectFileSkeletonLegacy verbosity httpTransport distDirLayout key = do
903+
readProjectFileSkeletonGen verbosity httpTransport distDirLayout key $ \fp -> do
899904
debug verbosity "Reading project file using the legacy parser"
900-
parseProjectFileSkeletonLegacy verbosity httpTransport distDirLayout extensionName extensionDescription fp
901-
>>= liftIO . reportParseResult verbosity extensionDescription fp
905+
parseProjectFileSkeletonLegacy verbosity httpTransport distDirLayout key fp
906+
>>= liftIO . reportParseResult verbosity (extensionDescription key) fp
902907

903908
-- | Read a project file using the parsec parser, but if that fails, it falls back to the legacy parser.
904-
readProjectFileSkeletonFallback :: Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> Rebuild ProjectConfigSkeleton
905-
readProjectFileSkeletonFallback verbosity httpTransport distDirLayout extensionName extensionDescription = do
906-
readProjectFileSkeletonGen verbosity httpTransport distDirLayout extensionName extensionDescription $ \fp -> do
909+
readProjectFileSkeletonFallback :: Verbosity -> HttpTransport -> DistDirLayout -> ProjectFileKey -> Rebuild ProjectConfigSkeleton
910+
readProjectFileSkeletonFallback verbosity httpTransport distDirLayout key = do
911+
readProjectFileSkeletonGen verbosity httpTransport distDirLayout key $ \fp -> do
907912
debug verbosity "Reading project file using the fallback parser"
908-
(res, bs) <- parseProjectFileSkeletonParsec verbosity httpTransport distDirLayout extensionName extensionDescription fp
913+
(res, bs) <- parseProjectFileSkeletonParsec verbosity httpTransport distDirLayout key fp
909914
let (_, pres) = runParseResult res
910915
case pres of
911916
-- 1. Successful parse with parsec parser, handle the result as normal.
912917
Right{} -> liftIO $ reportParseResultParsec verbosity fp bs res
913918
-- 2. The parse failed with the parsec parser, fallback to the legacy parser.
914919
Left{} -> do
915-
lres <- parseProjectFileSkeletonLegacy verbosity httpTransport distDirLayout extensionName extensionDescription fp
920+
lres <- parseProjectFileSkeletonLegacy verbosity httpTransport distDirLayout key fp
916921
case lres of
917922
-- 3a. The legacy parser worked, but the parsec parser failed!
918923
-- Report a warning to the user that this happened.
919924
OldParser.ProjectParseOk{} -> do
920925
warn verbosity "The new parsec parser failed, but the legacy parser worked. This is unexpected, please report this as a bug.\nThe legacy parser will be removed in the next major version."
921-
liftIO $ reportParseResult verbosity extensionDescription fp lres
926+
liftIO $ reportParseResult verbosity (extensionDescription key) fp lres
922927
-- 3b. The legacy parser failed as well, report the original error.
923928
OldParser.ProjectParseFailed{} -> do
924929
liftIO $ reportParseResultParsec verbosity fp bs res
925930

926931
-- | Read a project file using the parsec parser.
927-
readProjectFileSkeletonParsec :: Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> Rebuild ProjectConfigSkeleton
928-
readProjectFileSkeletonParsec verbosity httpTransport distDirLayout extensionName extensionDescription = do
929-
readProjectFileSkeletonGen verbosity httpTransport distDirLayout extensionName extensionDescription $ \fp -> do
932+
readProjectFileSkeletonParsec :: Verbosity -> HttpTransport -> DistDirLayout -> ProjectFileKey -> Rebuild ProjectConfigSkeleton
933+
readProjectFileSkeletonParsec verbosity httpTransport distDirLayout key = do
934+
readProjectFileSkeletonGen verbosity httpTransport distDirLayout key $ \fp -> do
930935
debug verbosity "Reading project file using the parsec parser"
931-
(res, bs) <- parseProjectFileSkeletonParsec verbosity httpTransport distDirLayout extensionName extensionDescription fp
936+
(res, bs) <- parseProjectFileSkeletonParsec verbosity httpTransport distDirLayout key fp
932937
liftIO $ reportParseResultParsec verbosity fp bs res
933938

934-
readProjectFileSkeletonCompare :: Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> Rebuild ProjectConfigSkeleton
935-
readProjectFileSkeletonCompare verbosity httpTransport distDirLayout extensionName extensionDescription = do
936-
readProjectFileSkeletonGen verbosity httpTransport distDirLayout extensionName extensionDescription $ \fp -> do
939+
readProjectFileSkeletonCompare :: Verbosity -> HttpTransport -> DistDirLayout -> ProjectFileKey -> Rebuild ProjectConfigSkeleton
940+
readProjectFileSkeletonCompare verbosity httpTransport distDirLayout key = do
941+
readProjectFileSkeletonGen verbosity httpTransport distDirLayout key $ \fp -> do
937942
debug verbosity "Reading project file using the comparative parser"
938-
(pres, bs) <- parseProjectFileSkeletonParsec verbosity httpTransport distDirLayout extensionName extensionDescription fp
939-
lres <- parseProjectFileSkeletonLegacy verbosity httpTransport distDirLayout extensionName extensionDescription fp
943+
(pres, bs) <- parseProjectFileSkeletonParsec verbosity httpTransport distDirLayout key fp
944+
lres <- parseProjectFileSkeletonLegacy verbosity httpTransport distDirLayout key fp
940945
let (_, ppres) = runParseResult pres
941946
case (lres, ppres) of
942947
-- 1. Both succeed, compare the results
@@ -947,12 +952,12 @@ readProjectFileSkeletonCompare verbosity httpTransport distDirLayout extensionNa
947952
-- Report a warning to the user that this happened.
948953
(OldParser.ProjectParseFailed{}, Right{}) -> do
949954
warn verbosity "The legacy parser failed, but the new parsec parser worked. This is unexpected, please report this as a bug.\nThe legacy parser will be removed in the next major version."
950-
liftIO $ reportParseResult verbosity extensionDescription fp lres
955+
liftIO $ reportParseResult verbosity (extensionDescription key) fp lres
951956
-- 3. The legacy parser succeeded, but the parsec parser failed.
952957
-- Report a warning to the user that this happened.
953958
(OldParser.ProjectParseOk{}, Left{}) -> do
954959
warn verbosity "The new parsec parser failed, but the legacy parser worked. This is unexpected, please report this as a bug.\nThe legacy parser will be removed in the next major version."
955-
liftIO $ reportParseResult verbosity extensionDescription fp lres
960+
liftIO $ reportParseResult verbosity (extensionDescription key) fp lres
956961
(OldParser.ProjectParseFailed{}, Left{}) -> do
957962
-- 4. Both failed, report the original error. We don't check that the same errors are reported.
958963
liftIO $ reportParseResultParsec verbosity fp bs pres
@@ -975,16 +980,16 @@ reportParseResultParsec verbosity fpath contents pr = do
975980
dieWithException verbosity $ ProjectConfigParseFailure $ ProjectConfigParseError errors warnings
976981

977982
-- | Reads a named extended (with imports and conditionals) config file in the given project root dir, or returns empty.
978-
parseProjectFileSkeletonLegacy :: Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> FilePath -> IO (OldParser.ProjectParseResult ProjectConfigSkeleton)
979-
parseProjectFileSkeletonLegacy verbosity httpTransport distDirLayout extensionName extensionDescription extensionFile = do
983+
parseProjectFileSkeletonLegacy :: Verbosity -> HttpTransport -> DistDirLayout -> ProjectFileKey -> FilePath -> IO (OldParser.ProjectParseResult ProjectConfigSkeleton)
984+
parseProjectFileSkeletonLegacy verbosity httpTransport distDirLayout key extensionFile = do
980985
bs <- BS.readFile extensionFile
981986
res <- parseProject extensionFile (distDownloadSrcDirectory distDirLayout) httpTransport verbosity $ ProjectConfigToParse bs
982987
case res of
983988
x@(OldParser.ProjectParseOk _ skeleton) -> reportDuplicateImports verbosity skeleton >> pure x
984989
x@OldParser.ProjectParseFailed{} -> pure x
985990

986-
parseProjectFileSkeletonParsec :: Verbosity -> HttpTransport -> DistDirLayout -> String -> String -> FilePath -> IO (Parsec.ParseResult ProjectFileSource ProjectConfigSkeleton, BS.ByteString)
987-
parseProjectFileSkeletonParsec verbosity httpTransport distDirLayout extensionName extensionDescription extensionFile = do
991+
parseProjectFileSkeletonParsec :: Verbosity -> HttpTransport -> DistDirLayout -> ProjectFileKey -> FilePath -> IO (Parsec.ParseResult ProjectFileSource ProjectConfigSkeleton, BS.ByteString)
992+
parseProjectFileSkeletonParsec verbosity httpTransport distDirLayout key extensionFile = do
988993
bs <- BS.readFile extensionFile
989994
res <- Parsec.parseProject extensionFile (distDownloadSrcDirectory distDirLayout) httpTransport verbosity $ ProjectConfigToParse bs
990995
case snd $ runParseResult res of
@@ -1002,12 +1007,12 @@ showProjectConfig =
10021007
-- | Write a @cabal.project.local@ file in the given project root dir.
10031008
writeProjectLocalExtraConfig :: DistDirLayout -> ProjectConfig -> IO ()
10041009
writeProjectLocalExtraConfig DistDirLayout{distProjectFile} =
1005-
writeProjectConfigFile (distProjectFile "local")
1010+
writeProjectConfigFile (distProjectFile ProjectFileKeyLocal)
10061011

10071012
-- | Write a @cabal.project.freeze@ file in the given project root dir.
10081013
writeProjectLocalFreezeConfig :: DistDirLayout -> ProjectConfig -> IO ()
10091014
writeProjectLocalFreezeConfig DistDirLayout{distProjectFile} =
1010-
writeProjectConfigFile (distProjectFile "freeze")
1015+
writeProjectConfigFile (distProjectFile ProjectFileKeyFreeze)
10111016

10121017
-- | Write in the @cabal.project@ format to the given file.
10131018
writeProjectConfigFile :: FilePath -> ProjectConfig -> IO ()

cabal-install/src/Distribution/Client/ProjectOrchestration.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ establishProjectBaseContextWithRoot verbosity cliConfig projectRoot currentComma
309309

310310
-- https://github.com/haskell/cabal/issues/6013
311311
-- https://github.com/haskell/cabal/issues/7401
312-
let projPath = distProjectFileMain (distProjectFile distDirLayout)
312+
let projPath = distProjectFile distDirLayout ProjectFileKeyMain
313313
when (null (projectPackages projectConfig) && null (projectPackagesOptional projectConfig)) $
314314
dieWithException verbosity (ProjectConfigNoPackages projPath)
315315

0 commit comments

Comments
 (0)