summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlarsk <>2018-08-21 22:57:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2018-08-21 22:57:00 (GMT)
commit0dd48f5be838c1b9a8161a9d3e7802f45c5ea760 (patch)
tree1f63ef6e5530a4fc34c327d434642fab2b13820a
parent6ea2560d97689e22b7939c97c89fc6b86c6aff5c (diff)
version 0.4.00.4.0
-rw-r--r--CHANGELOG.md14
-rw-r--r--INSTALL_ON_WINDOWS.md118
-rw-r--r--Setup.hs251
-rw-r--r--configuration-tools.cabal69
-rw-r--r--constraints94
-rw-r--r--examples/Example.hs4
-rw-r--r--src/Configuration/Utils/Maybe.hs9
-rw-r--r--src/Configuration/Utils/Operators.hs10
-rw-r--r--src/Configuration/Utils/Setup.hs251
-rw-r--r--src/Configuration/Utils/Validation.hs10
-rw-r--r--test/TestExample.hs5
11 files changed, 292 insertions, 543 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f47288..0ff4da8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+0.4.0 (2018-08-21)
+==================
+
+* Drop support for GHC < 7.10 and base < 4.8
+* Drop support for Cabal < 1.24
+* Drop support for transformers < 0.4
+* Don't run CI tests for Cabal < 2
+
+* With Cabal 2.0 or later package info modules are placed in per component
+ `autogen` directories. All package info modules are named just `PkgInfo`.
+ For backward compatibility modules with the old legacy names (`PkgInfo_*`)
+ are still generated but marked deprecated. With Cabal 1.24 only the legacy
+ behavior is available and a deprecation warning is raised.
+
0.3.1 (2018-03-16)
==================
diff --git a/INSTALL_ON_WINDOWS.md b/INSTALL_ON_WINDOWS.md
deleted file mode 100644
index c5a749e..0000000
--- a/INSTALL_ON_WINDOWS.md
+++ /dev/null
@@ -1,118 +0,0 @@
-When using the `Setup.hs` script from the *configuration-tools* package
-with a source build from a git repository a git binary must be available
-in the `PATH` environment of the installation command. This is, for instance,
-the case for the test-suite of the *configuration-tools* package itself.
-
-The first step in the following description installs a git binary that
-is globally available in the system. Steps two through seven explain
-how to setup a Haskell build environment on a Windows system in general.
-Those steps are not specific to the *configuration-tools* package. Steps
-eight and nine explain how to install and test the *configuration-tools*
-package.
-
-Windows
-=======
-
-The following steps make use of the `Git Bash` terminal. Beside of being
-convenient for users that are familiar with POSIX systems, it is also a
-requirement for installing the *network* package, which is a dependency of
-*cabal*. Most other Haskell packages can be installed from a windows shell
-(PowerShell or cmd shell) as well.
-
-1. Install Git from: [Git for windows](http://git-scm.com/download/win)
-
- During the installation, when ask about the environment settings,
- select the second option that makes the git command available at
- the windows shell prompt. Otherwise the git binary is available
- only when `cabal` is executed from the *Git Bash* terminal.
-
-2. Download the
- [GHC binary distribution for windows](http://www.haskell.org/ghc/dist/7.8.3/ghc-7.8.3-x86_64-unknown-mingw32.tar.bz2)
- and unpack it in a convenient place.
-
- In the following we assume that it was unpacked in `C:\` into the default directory `C:\ghc-7.8.3`.
-
-3. Obtain a windows cabal binary, for example from the Haskell Platform distribution
- or a previous GHC installation (the version doesn't matter).
-
-4. Open the *Git Bash* terminal. A link to it should have been created in the start menu
- during the Git installation.
-
-5. Include the `bin` directory and `mingw/bin` directory from the GHC binary distribution into
- the `PATH` environment:
-
- ~~~{.sh}
- export PATH=/c/ghc-7.8.3/bin:/c/ghc-7.8.3/mingw/bin:$PATH
- ~~~
-
-6. Make sure a cabal binary is available in the `PATH`
-
- ~~~{.sh}
- which cabal
- ~~~
-
- and check that `ghc`, `ld`, and `gcc` are used from the respective directories under
- `/c/ghc-7.8.3/*`:
-
- ~~~{.sh}
- which ghc
- which ld
- which gcc
- ~~~
-
-7. Install an updated version of `cabal`:
-
- ~~~{.sh}
- cabal update
- cabal install cabal-install
- ~~~
-
- Make sure that the location into which the resulting cabal binary is installed
- (the location is configured in `~/AppData/Roaming/cabal/config` and it is also
- printed to the installation logs) is in your `PATH`.
-
- Check that you are now using the most recent version of cabal:
-
- ~~~{.sh}
- which cabal
- cabal --version
- ~~~
-
-8. Install the *configuration-tools* package from Hackage:
-
- ~~~{.sh}
- cabal install configuration-tools --enable-tests
- ~~~
-
- Alternativly, you my clone and install it from
- [GitHub](https://github.com/alephcloud/hs-configuration-tools.git):
-
- ~~~{.sh}
- git clone https://github.com/alephcloud/hs-configuration-tools.git
- cd hs-configuration-tools
- cabal install --enable-tests
- ~~~
-
-9. When you installed *configuration-tools* from source you may run the tests
- from within the package directory as follows:
-
- ~~~{.sh}
- cabal test
- ~~~
-
- You can run the test with different command line options using cabals `--test-option`
- flag. For instance[^1]:
-
- ~~~{.sh}
- cabal test --show-details=always --test-option=--help
- cabal test --show-details=always --test-option=--long-info
- ~~~
-
- [^1]: Note: the windows terminal reacts ungracefully to Unicode characters. In order to have
- it at least not crash the program you should run the following command before you
- exectute any command that may print unicode characters (like the copyright symbol in the
- test examples):
-
- ~~~{.sh}
- chcp.com 65001
- ~~~
diff --git a/Setup.hs b/Setup.hs
index 73f7e7d..a41ddb4 100644
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,9 +1,8 @@
-- ------------------------------------------------------ --
--- Copyright © 2015-2016 Lars Kuhtz <lakuhtz@gmail.com>
+-- Copyright © 2015-2018 Lars Kuhtz <lakuhtz@gmail.com>
-- Copyright © 2014 AlephCloud Systems, Inc.
-- ------------------------------------------------------ --
-{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
@@ -14,19 +13,8 @@
-- process at the end of the configuration phase and generates a module with
-- package information for each component of the cabal package.
--
--- The modules are created in the /autogen/ build directory where also the
--- @Path_@ module is created by cabal's simple build setup. This is usually the
--- directory @.\/dist\/build\/autogen@.
---
--- For a library component the module is named just @PkgInfo@. For all other
--- components the module is named @PkgInfo_COMPONENT_NAME@ where
--- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by
--- @_@.
---
--- For instance, if a cabal package contains a library and an executable that is
--- called /my-app/, the following modules are created: @PkgInfo@ and
--- @PkgInfo_my_app@.
---
+-- The modules are created in the /autogen/ build directories where also the
+-- @Path_@ modules are created by cabal's simple build setup.
--
-- = Usage as Setup Script
--
@@ -111,7 +99,6 @@ module Main
) where
#ifndef MIN_VERSION_Cabal
-#define NO_CABAL_MACROS 1
#define MIN_VERSION_Cabal(a,b,c) 0
#endif
@@ -125,6 +112,7 @@ import Distribution.Simple.PackageIndex
import Distribution.Text
#if MIN_VERSION_Cabal(2,0,0)
+import qualified Distribution.Compat.Graph as Graph
import Distribution.Types.LocalBuildInfo
import Distribution.Types.UnqualComponentName
#endif
@@ -146,15 +134,16 @@ import Data.Monoid
import Prelude hiding (readFile, writeFile)
-import System.Directory (doesFileExist, doesDirectoryExist, createDirectoryIfMissing, getCurrentDirectory, canonicalizePath)
+import System.Directory
+ ( doesFileExist
+ , doesDirectoryExist
+ , createDirectoryIfMissing
+ , getCurrentDirectory
+ , canonicalizePath
+ )
import System.FilePath (isDrive, (</>), takeDirectory)
import System.Exit (ExitCode(ExitSuccess))
-#ifdef NO_CABAL_MACROS
-import Data.Maybe
-import Data.Typeable
-#endif
-
-- | Include this function when your setup doesn't contain any
-- extra functionality.
--
@@ -168,14 +157,8 @@ main = defaultMainWithHooks (mkPkgInfoModules simpleUserHooks)
-- If your setup doesn't contain any other function you can just import
-- the 'main' function from this module.
--
--- The modules are created in the /autogen/ build directory where also the
--- @Path_@ module is created by cabal's simple build setup. This is usually the
--- directory @.\/dist\/build\/autogen@.
---
--- For a library component the module is named just @PkgInfo@. For all other
--- components the module is named @PkgInfo_COMPONENT_NAME@ where
--- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by
--- @_@.
+-- The modules are created in the /autogen/ build directories where also the
+-- @Path_@ modules are created by cabal's simple build setup.
--
mkPkgInfoModules
:: UserHooks
@@ -184,6 +167,77 @@ mkPkgInfoModules hooks = hooks
{ postConf = mkPkgInfoModulesPostConf (postConf hooks)
}
+-- -------------------------------------------------------------------------- --
+-- Compat Implementations
+
+#if !MIN_VERSION_Cabal(2,0,0)
+unFlagName :: FlagName -> String
+unFlagName (FlagName s) = s
+#endif
+
+#if !MIN_VERSION_Cabal(2,2,0)
+unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
+unFlagAssignment = id
+#endif
+
+#if !MIN_VERSION_Cabal(2,2,0)
+prettyShow :: Text a => a -> String
+prettyShow = display
+#endif
+
+#if !MIN_VERSION_Cabal(2,0,0)
+-- unUnqualComponentName :: UnqualComponentName -> String
+unUnqualComponentName :: String -> String
+unUnqualComponentName = id
+#endif
+
+prettyLicense :: I.InstalledPackageInfo -> String
+#if MIN_VERSION_Cabal(2,2,0)
+prettyLicense = either prettyShow prettyShow . I.license
+#else
+prettyLicense = prettyShow . I.license
+#endif
+
+-- -------------------------------------------------------------------------- --
+-- Cabal 2.0
+
+#if MIN_VERSION_Cabal(2,0,0)
+mkPkgInfoModulesPostConf
+ :: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())
+ -> Args
+ -> ConfigFlags
+ -> PackageDescription
+ -> LocalBuildInfo
+ -> IO ()
+mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do
+ mapM_ (updatePkgInfoModule pkgDesc bInfo) $ Graph.toList $ componentGraph bInfo
+ hook args flags pkgDesc bInfo
+
+updatePkgInfoModule :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> IO ()
+updatePkgInfoModule pkgDesc bInfo clbInfo = do
+ createDirectoryIfMissing True dirName
+ moduleBytes <- pkgInfoModule moduleName cName pkgDesc bInfo
+ updateFile fileName moduleBytes
+
+ -- legacy module
+ legacyModuleBytes <- pkgInfoModule legacyModuleName cName pkgDesc bInfo
+ updateFile legacyFileName legacyModuleBytes
+
+ where
+ dirName = autogenComponentModulesDir bInfo clbInfo
+ cName = unUnqualComponentName <$> componentNameString (componentLocalName clbInfo)
+
+ moduleName = pkgInfoModuleName
+ fileName = dirName ++ "/" ++ moduleName ++ ".hs"
+
+ legacyModuleName = legacyPkgInfoModuleName cName
+ legacyFileName = dirName ++ "/" ++ legacyModuleName ++ ".hs"
+
+-- -------------------------------------------------------------------------- --
+-- Cabal 1.24
+
+#else
+
mkPkgInfoModulesPostConf
:: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())
-> Args
@@ -202,22 +256,41 @@ mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do
CTestName s -> updatePkgInfoModule (Just $ unUnqualComponentName s) pkgDesc bInfo
CBenchName s -> updatePkgInfoModule (Just $ unUnqualComponentName s) pkgDesc bInfo
-#if !MIN_VERSION_Cabal(2,0,0)
- unUnqualComponentName = id
+updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO ()
+updatePkgInfoModule cName pkgDesc bInfo = do
+ createDirectoryIfMissing True dirName
+ moduleBytes <- pkgInfoModule moduleName cName pkgDesc bInfo
+ updateFile fileName moduleBytes
+ where
+ dirName = autogenModulesDir bInfo
+ moduleName = legacyPkgInfoModuleName cName
+ fileName = dirName ++ "/" ++ moduleName ++ ".hs"
#endif
-pkgInfoModuleName :: Maybe String -> String
-pkgInfoModuleName Nothing = "PkgInfo"
-pkgInfoModuleName (Just cn) = "PkgInfo_" ++ map tr cn
+-- -------------------------------------------------------------------------- --
+-- Generate PkgInfo Module
+
+pkgInfoModuleName :: String
+pkgInfoModuleName = "PkgInfo"
+
+updateFile :: FilePath -> B.ByteString -> IO ()
+updateFile fileName content = do
+ doesFileExist fileName >>= \x -> if x
+ then do
+ oldRevisionFile <- B.readFile fileName
+ when (oldRevisionFile /= content) update
+ else
+ update
+ where
+ update = B.writeFile fileName content
+
+legacyPkgInfoModuleName :: Maybe String -> String
+legacyPkgInfoModuleName Nothing = "PkgInfo"
+legacyPkgInfoModuleName (Just cn) = "PkgInfo_" ++ map tr cn
where
tr '-' = '_'
tr c = c
--- FIXME: autoModulesDir is deprecated and should be replaced by
--- autogenComponentModulesDir.
-pkgInfoFileName :: Maybe String -> LocalBuildInfo -> FilePath
-pkgInfoFileName cn bInfo = autogenModulesDir bInfo ++ "/" ++ pkgInfoModuleName cn ++ ".hs"
-
trim :: String -> String
trim = f . f
where f = reverse . dropWhile isSpace
@@ -236,23 +309,8 @@ getVcsOfDir d = do
then return Nothing
else getVcsOfDir (takeDirectory canonicDir)
-#if !MIN_VERSION_Cabal(2,0,0)
-unFlagName :: FlagName -> String
-unFlagName (FlagName s) = s
-#endif
-
-#if !MIN_VERSION_Cabal(2,2,0)
-unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
-unFlagAssignment = id
-#endif
-
-#if !MIN_VERSION_Cabal(2,2,0)
-prettyShow :: Text a => a -> String
-prettyShow = display
-#endif
-
-pkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString
-pkgInfoModule cName pkgDesc bInfo = do
+pkgInfoModule :: String -> Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString
+pkgInfoModule moduleName cName pkgDesc bInfo = do
(tag, revision, branch) <- getVCS >>= \x -> case x of
Just Mercurial -> hgInfo
Just Git -> gitInfo
@@ -268,10 +326,11 @@ pkgInfoModule cName pkgDesc bInfo = do
[ "{-# LANGUAGE OverloadedStrings #-}"
, "{-# LANGUAGE RankNTypes #-}"
, ""
- , "module " <> (pack . pkgInfoModuleName) cName <> " where"
+ , "module " <> pack moduleName <> " " <> deprecatedMsg <> " where"
, ""
, " import Data.String (IsString)"
, " import Data.Monoid"
+ , " import Prelude hiding ((<>))"
, ""
, " name :: IsString a => Maybe a"
, " name = " <> maybe "Nothing" (\x -> "Just \"" <> pack x <> "\"") cName
@@ -365,83 +424,19 @@ pkgInfoModule cName pkgDesc bInfo = do
displayOptimisationLevel NormalOptimisation = "normal"
displayOptimisationLevel MaximumOptimisation = "maximum"
-updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO ()
-updatePkgInfoModule cName pkgDesc bInfo = do
- createDirectoryIfMissing True $ autogenModulesDir bInfo
- newFile <- pkgInfoModule cName pkgDesc bInfo
- let update = B.writeFile fileName newFile
- doesFileExist fileName >>= \x -> if x
- then do
- oldRevisionFile <- B.readFile fileName
- when (oldRevisionFile /= newFile) update
- else
- update
- where
- fileName = pkgInfoFileName cName bInfo
+ deprecatedMsg = if moduleName /= pkgInfoModuleName
+ then "{-# DEPRECATED \"Update to Cabal 2.0 or later and use just PkgInfo as module name.\" #-}"
+ else ""
licenseFilesText :: PackageDescription -> IO B.ByteString
licenseFilesText pkgDesc =
B.intercalate "\n------------------------------------------------------------\n" <$> mapM fileText
-#ifdef NO_CABAL_MACROS
- (getLicenseFiles pkgDesc)
-#elif MIN_VERSION_Cabal(1,20,0)
(licenseFiles pkgDesc)
-#else
- [licenseFile pkgDesc]
-#endif
where
fileText file = doesFileExist file >>= \x -> if x
then B.readFile file
else return ""
-#ifdef NO_CABAL_MACROS
--- The name and the type of the @licenseFile :: String@ field of
--- 'PackageDescription' changed in Cabal version 1.20 to @licenseFiles ::
--- [String]@. Both versions are used with GHC-7.8. In Cabal version 1.24 the
--- number of constructor fields changed for PackageDescription. When compiling
--- @Setup.hs@ the @MIN_VERSION_...@ macros are not available. This function is
--- an ugly hack to do conditional compilation without CPP. It depends on the
--- @RecordWildCards@ and @Typeable@ extensions and abuses shaddowing of
--- existing symbols.
---
--- Alternative methods would include:
---
--- * Use typeable to pattern match on the number of constructor arguments for
--- 'PackageDescription',
--- * use TH hacks ala @$( if versionBranch cabalVersion < [...] ... )@, and/or
--- * make guesses about the cabal version based on the @__GLASGOW_HASKELL__@
--- macro.
-
--- Return license files of from the @PackageDescription@.
---
-getLicenseFiles :: PackageDescription -> [FilePath]
-getLicenseFiles pkgDesc = f pkgDesc
- where
- -- Recent versions of @PackageDescription@ define a @licenseFiles@ field.
- -- For older versions the function @licenseFiles@ that is defined below is
- -- used.
- --
- f PackageDescription{..} = licenseFiles
-
- -- If @PackageDescription@ doesn't define @licenseFiles@ this definition
- -- will be used. In that case @PackageDescription@ is assumed to define
- -- @licenseFile@.
- --
- licenseFiles :: [FilePath]
- licenseFiles = fromMaybe (error "unsupported Cabal library version") $
- return <$> cast (g pkgDesc)
-
- g PackageDescription{..} = licenseFile
-
- -- The only purpose of this function is to ensure that licenseFile is
- -- defined in case PackageDescription doesn't have a @licenseFile@ field.
- -- This function won't be called with any supported version of the Cabal
- -- library.
- --
- licenseFile :: [FilePath]
- licenseFile = error "unexpected Cabal library version"
-#endif
-
hgInfo :: IO (String, String, String)
hgInfo = do
tag <- trim <$> readProcess "hg" ["id", "-r", "max(ancestors(\".\") and tag())", "-t"] ""
@@ -466,11 +461,7 @@ noVcsInfo = return ("", "", "")
pkgIdWithLicense :: I.InstalledPackageInfo -> String
pkgIdWithLicense a = (display . packageId) a
++ " ["
-#if MIN_VERSION_Cabal(2,2,0)
- ++ (either prettyShow prettyShow . I.license) a
-#else
- ++ (prettyShow . I.license) a
-#endif
+ ++ prettyLicense a
++ (if cr /= "" then ", " ++ cr else "")
++ "]"
where
diff --git a/configuration-tools.cabal b/configuration-tools.cabal
index 85b5401..02a2d75 100644
--- a/configuration-tools.cabal
+++ b/configuration-tools.cabal
@@ -4,7 +4,7 @@
-- ------------------------------------------------------ --
Name: configuration-tools
-Version: 0.3.1
+Version: 0.4.0
Synopsis: Tools for specifying and parsing configurations
description:
Tools for specifying and parsing configurations
@@ -39,16 +39,25 @@ Copyright:
(c) 2014-2015 AlephCloud, Inc.
Category: Configuration, Console
Build-type: Custom
-
-cabal-version: >= 1.18
+cabal-version: 1.24
+tested-with:
+ GHC==8.4.3
+ , GHC==8.2.2
+ , GHC==8.0.2
+ , GHC==7.10.3
extra-doc-files:
README.md,
CHANGELOG.md
- INSTALL_ON_WINDOWS.md
-extra-source-files:
- constraints
+custom-setup
+ setup-depends:
+ Cabal >= 1.24,
+ base >= 4.8 && < 5.0,
+ bytestring >= 0.10.0.2,
+ directory >= 1.2.1.0,
+ filepath >= 1.3.0.1,
+ process >= 1.2.0.0
source-repository head
type: git
@@ -58,18 +67,13 @@ source-repository head
source-repository this
type: git
location: https://github.com/alephcloud/hs-configuration-tools.git
- tag: 0.3.1
+ tag: 0.4.0
flag remote-configs
Description: enable loading of configuration files from HTTP URLs
Default: True
Manual: True
-flag old-transformers
- Description: use old transformers
- Default: False
- Manual: False
-
Library
hs-source-dirs: src
default-language: Haskell2010
@@ -91,11 +95,11 @@ Library
Configuration.Utils.Internal.HttpsCertPolicy
build-depends:
- Cabal >= 1.18,
+ Cabal >= 1.24,
aeson >= 0.7.0.6,
ansi-wl-pprint >= 0.6,
attoparsec >= 0.11.3.4,
- base >= 4.6 && < 5.0,
+ base >= 4.8 && < 5.0,
base-unicode-symbols >= 0.2.2.4,
bytestring >= 0.10.0.2,
case-insensitive >= 1.2,
@@ -103,25 +107,16 @@ Library
directory >= 1.2.1.0,
dlist >= 0.7.1,
filepath >= 1.3.0.1,
+ mtl >= 2.2,
network-uri >= 2.6.0.1,
optparse-applicative >= 0.11.0.2,
process >= 1.2.0.0,
+ profunctors >= 4.0.4,
+ semigroups >= 0.18,
text >= 1.0,
+ transformers >= 0.4,
unordered-containers >= 0.2.4.0,
- yaml >= 0.8.8.3,
- profunctors >= 4.0.4,
- semigroups >= 0.18
-
- if flag(old-transformers)
- build-depends:
- mtl >= 2.1,
- mtl-compat >= 0.2,
- transformers >= 0.3 && < 0.4,
- transformers-compat >= 0.4
- else
- build-depends:
- mtl >= 2.2,
- transformers >= 0.4
+ yaml >= 0.8.8.3
if flag(remote-configs)
build-depends:
@@ -156,25 +151,17 @@ Test-Suite url-example-test
Tests.MonoidConfig
build-depends:
- base >= 4.6 && < 5.0,
+ Cabal >= 1.24,
+ base >= 4.8 && < 5.0,
base-unicode-symbols >= 0.2.2.4,
bytestring >= 0.10,
- Cabal >= 1.18,
configuration-tools,
+ mtl >= 2.2,
text >= 1.0,
+ transformers >= 0.4,
unordered-containers >= 0.2.4.0,
yaml >= 0.8.8.3
- if flag(old-transformers)
- build-depends:
- mtl >= 2.1,
- mtl-compat >= 0.2,
- transformers-compat >= 0.4
- else
- build-depends:
- mtl >= 2.2,
- transformers >= 0.4
-
if flag(remote-configs)
build-depends:
enclosed-exceptions >= 1.0,
@@ -195,7 +182,7 @@ Test-Suite trivial
hs-source-dirs: examples
build-depends:
- base >= 4.6 && < 5.0,
+ base >= 4.8 && < 5.0,
base-unicode-symbols >= 0.2.2.4,
configuration-tools
diff --git a/constraints b/constraints
deleted file mode 100644
index 2bcf6ef..0000000
--- a/constraints
+++ /dev/null
@@ -1,94 +0,0 @@
-constraints: Cabal ==1.23.1.0,
- array ==0.5.1.0,
- base ==4.9.0.0,
- ghc-prim ==0.5.0.0,
- rts ==1.0,
- integer-gmp ==1.0.0.1,
- binary ==0.8.2.0,
- bytestring ==0.10.7.0,
- deepseq ==1.4.2.0,
- containers ==0.5.7.1,
- directory ==1.2.5.0,
- filepath ==1.4.1.0,
- time ==1.6,
- unix ==2.7.2.0,
- pretty ==1.1.3.2,
- process ==1.4.2.0,
- aeson ==0.11.0.0,
- attoparsec ==0.13.0.1,
- scientific ==0.3.4.4,
- hashable ==1.2.4.0,
- text ==1.2.2.0,
- vector ==0.11.0.0,
- primitive ==0.6.1.0,
- transformers ==0.5.1.0,
- dlist ==0.7.1.2,
- fail ==4.9.0.0,
- mtl ==2.2.1,
- syb ==0.6,
- template-haskell ==2.11.0.0,
- ghc-boot ==8.0.0.20160204,
- unordered-containers ==0.2.6.0,
- ansi-wl-pprint ==0.6.7.3,
- ansi-terminal ==0.6.2.3,
- base-unicode-symbols ==0.2.2.4,
- base64-bytestring ==1.0.0.1,
- case-insensitive ==1.2.0.5,
- connection ==0.2.5,
- byteable ==0.1.1,
- data-default-class ==0.0.1,
- network ==2.6.2.1,
- socks ==0.5.4,
- cereal ==0.5.1.0,
- tls ==1.3.4,
- asn1-encoding ==0.9.3,
- asn1-types ==0.3.2,
- hourglass ==0.2.9,
- memory ==0.11,
- async ==2.1.0,
- stm ==2.4.4.1,
- cryptonite ==0.11,
- x509 ==1.6.3,
- asn1-parse ==0.9.4,
- pem ==0.2.2,
- x509-store ==1.6.1,
- x509-validation ==1.6.3,
- x509-system ==1.6.3,
- data-default ==0.5.3,
- data-default-instances-base ==0.0.1,
- data-default-instances-containers ==0.0.1,
- data-default-instances-dlist ==0.0.1,
- data-default-instances-old-locale ==0.0.1,
- old-locale ==1.0.0.7,
- enclosed-exceptions ==1.0.1.1,
- lifted-base ==0.2.3.6,
- monad-control ==1.0.0.5,
- transformers-base ==0.4.4,
- transformers-compat ==0.5.1.4,
- http-client ==0.4.27,
- blaze-builder ==0.4.0.1,
- cookie ==0.4.1.6,
- exceptions ==0.8.2.1,
- http-types ==0.9,
- mime-types ==0.1.0.6,
- network-uri ==2.6.0.3,
- parsec ==3.1.9,
- random ==1.0.1.1,
- streaming-commons ==0.1.15.1,
- zlib ==0.6.1.1,
- http-client-tls ==0.2.2,
- optparse-applicative ==0.12.1.0,
- profunctors ==5.2,
- base-orphans ==0.5.1,
- bifunctors ==5.2.1,
- comonad ==5,
- contravariant ==1.4,
- StateVar ==1.1.0.3,
- semigroups ==0.18.1,
- void ==0.7.1,
- distributive ==0.5.0.2,
- tagged ==0.8.3,
- yaml ==0.8.16,
- conduit ==1.2.6.2,
- mmorph ==1.0.6,
- resourcet ==1.1.7.2
diff --git a/examples/Example.hs b/examples/Example.hs
index eb8e884..1e8a963 100644
--- a/examples/Example.hs
+++ b/examples/Example.hs
@@ -44,7 +44,11 @@ import Prelude.Unicode
-- This assumes usage of cabal with custom Setup.hs
--
+#if MIN_VERSION_Cabal(2,0,0)
+import PkgInfo
+#else
import PkgInfo_url_example_test
+#endif
-- | Specification of the authentication section of a URL.
--
diff --git a/src/Configuration/Utils/Maybe.hs b/src/Configuration/Utils/Maybe.hs
index 2a5e8ab..b2881ac 100644
--- a/src/Configuration/Utils/Maybe.hs
+++ b/src/Configuration/Utils/Maybe.hs
@@ -1,17 +1,11 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-#ifndef MIN_VERSION_base
-#define MIN_VERSION_base(x,y,z) 1
-#endif
-
-- |
-- Module: Configuration.Utils.Maybe
-- Description: Configuration of Optional Values
@@ -33,9 +27,6 @@ module Configuration.Utils.Maybe
) where
-#if ! MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
import Data.Aeson
-- -------------------------------------------------------------------------- --
diff --git a/src/Configuration/Utils/Operators.hs b/src/Configuration/Utils/Operators.hs
index f7313ca..2b1de53 100644
--- a/src/Configuration/Utils/Operators.hs
+++ b/src/Configuration/Utils/Operators.hs
@@ -1,13 +1,7 @@
{-# LANGUAGE CPP #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
-#ifndef MIN_VERSION_base
-#define MIN_VERSION_base(x,y,z) 1
-#endif
-
-- |
-- Module: Configuration.Utils.Operators
-- Description: Useful operators for defining functions in an applicative context
@@ -29,10 +23,6 @@ module Configuration.Utils.Operators
, (⊙)
) where
-#if ! MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
-
-- -------------------------------------------------------------------------- --
-- Useful Operators
diff --git a/src/Configuration/Utils/Setup.hs b/src/Configuration/Utils/Setup.hs
index 98aeb10..7dbe865 100644
--- a/src/Configuration/Utils/Setup.hs
+++ b/src/Configuration/Utils/Setup.hs
@@ -1,9 +1,8 @@
-- ------------------------------------------------------ --
--- Copyright © 2015-2016 Lars Kuhtz <lakuhtz@gmail.com>
+-- Copyright © 2015-2018 Lars Kuhtz <lakuhtz@gmail.com>
-- Copyright © 2014 AlephCloud Systems, Inc.
-- ------------------------------------------------------ --
-{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
@@ -14,19 +13,8 @@
-- process at the end of the configuration phase and generates a module with
-- package information for each component of the cabal package.
--
--- The modules are created in the /autogen/ build directory where also the
--- @Path_@ module is created by cabal's simple build setup. This is usually the
--- directory @.\/dist\/build\/autogen@.
---
--- For a library component the module is named just @PkgInfo@. For all other
--- components the module is named @PkgInfo_COMPONENT_NAME@ where
--- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by
--- @_@.
---
--- For instance, if a cabal package contains a library and an executable that is
--- called /my-app/, the following modules are created: @PkgInfo@ and
--- @PkgInfo_my_app@.
---
+-- The modules are created in the /autogen/ build directories where also the
+-- @Path_@ modules are created by cabal's simple build setup.
--
-- = Usage as Setup Script
--
@@ -111,7 +99,6 @@ module Configuration.Utils.Setup
) where
#ifndef MIN_VERSION_Cabal
-#define NO_CABAL_MACROS 1
#define MIN_VERSION_Cabal(a,b,c) 0
#endif
@@ -125,6 +112,7 @@ import Distribution.Simple.PackageIndex
import Distribution.Text
#if MIN_VERSION_Cabal(2,0,0)
+import qualified Distribution.Compat.Graph as Graph
import Distribution.Types.LocalBuildInfo
import Distribution.Types.UnqualComponentName
#endif
@@ -146,15 +134,16 @@ import Data.Monoid
import Prelude hiding (readFile, writeFile)
-import System.Directory (doesFileExist, doesDirectoryExist, createDirectoryIfMissing, getCurrentDirectory, canonicalizePath)
+import System.Directory
+ ( doesFileExist
+ , doesDirectoryExist
+ , createDirectoryIfMissing
+ , getCurrentDirectory
+ , canonicalizePath
+ )
import System.FilePath (isDrive, (</>), takeDirectory)
import System.Exit (ExitCode(ExitSuccess))
-#ifdef NO_CABAL_MACROS
-import Data.Maybe
-import Data.Typeable
-#endif
-
-- | Include this function when your setup doesn't contain any
-- extra functionality.
--
@@ -168,14 +157,8 @@ main = defaultMainWithHooks (mkPkgInfoModules simpleUserHooks)
-- If your setup doesn't contain any other function you can just import
-- the 'main' function from this module.
--
--- The modules are created in the /autogen/ build directory where also the
--- @Path_@ module is created by cabal's simple build setup. This is usually the
--- directory @.\/dist\/build\/autogen@.
---
--- For a library component the module is named just @PkgInfo@. For all other
--- components the module is named @PkgInfo_COMPONENT_NAME@ where
--- @COMPONENT_NAME@ is the name of the component with @-@ characters replaced by
--- @_@.
+-- The modules are created in the /autogen/ build directories where also the
+-- @Path_@ modules are created by cabal's simple build setup.
--
mkPkgInfoModules
:: UserHooks
@@ -184,6 +167,77 @@ mkPkgInfoModules hooks = hooks
{ postConf = mkPkgInfoModulesPostConf (postConf hooks)
}
+-- -------------------------------------------------------------------------- --
+-- Compat Implementations
+
+#if !MIN_VERSION_Cabal(2,0,0)
+unFlagName :: FlagName -> String
+unFlagName (FlagName s) = s
+#endif
+
+#if !MIN_VERSION_Cabal(2,2,0)
+unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
+unFlagAssignment = id
+#endif
+
+#if !MIN_VERSION_Cabal(2,2,0)
+prettyShow :: Text a => a -> String
+prettyShow = display
+#endif
+
+#if !MIN_VERSION_Cabal(2,0,0)
+-- unUnqualComponentName :: UnqualComponentName -> String
+unUnqualComponentName :: String -> String
+unUnqualComponentName = id
+#endif
+
+prettyLicense :: I.InstalledPackageInfo -> String
+#if MIN_VERSION_Cabal(2,2,0)
+prettyLicense = either prettyShow prettyShow . I.license
+#else
+prettyLicense = prettyShow . I.license
+#endif
+
+-- -------------------------------------------------------------------------- --
+-- Cabal 2.0
+
+#if MIN_VERSION_Cabal(2,0,0)
+mkPkgInfoModulesPostConf
+ :: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())
+ -> Args
+ -> ConfigFlags
+ -> PackageDescription
+ -> LocalBuildInfo
+ -> IO ()
+mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do
+ mapM_ (updatePkgInfoModule pkgDesc bInfo) $ Graph.toList $ componentGraph bInfo
+ hook args flags pkgDesc bInfo
+
+updatePkgInfoModule :: PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> IO ()
+updatePkgInfoModule pkgDesc bInfo clbInfo = do
+ createDirectoryIfMissing True dirName
+ moduleBytes <- pkgInfoModule moduleName cName pkgDesc bInfo
+ updateFile fileName moduleBytes
+
+ -- legacy module
+ legacyModuleBytes <- pkgInfoModule legacyModuleName cName pkgDesc bInfo
+ updateFile legacyFileName legacyModuleBytes
+
+ where
+ dirName = autogenComponentModulesDir bInfo clbInfo
+ cName = unUnqualComponentName <$> componentNameString (componentLocalName clbInfo)
+
+ moduleName = pkgInfoModuleName
+ fileName = dirName ++ "/" ++ moduleName ++ ".hs"
+
+ legacyModuleName = legacyPkgInfoModuleName cName
+ legacyFileName = dirName ++ "/" ++ legacyModuleName ++ ".hs"
+
+-- -------------------------------------------------------------------------- --
+-- Cabal 1.24
+
+#else
+
mkPkgInfoModulesPostConf
:: (Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ())
-> Args
@@ -202,22 +256,41 @@ mkPkgInfoModulesPostConf hook args flags pkgDesc bInfo = do
CTestName s -> updatePkgInfoModule (Just $ unUnqualComponentName s) pkgDesc bInfo
CBenchName s -> updatePkgInfoModule (Just $ unUnqualComponentName s) pkgDesc bInfo
-#if !MIN_VERSION_Cabal(2,0,0)
- unUnqualComponentName = id
+updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO ()
+updatePkgInfoModule cName pkgDesc bInfo = do
+ createDirectoryIfMissing True dirName
+ moduleBytes <- pkgInfoModule moduleName cName pkgDesc bInfo
+ updateFile fileName moduleBytes
+ where
+ dirName = autogenModulesDir bInfo
+ moduleName = legacyPkgInfoModuleName cName
+ fileName = dirName ++ "/" ++ moduleName ++ ".hs"
#endif
-pkgInfoModuleName :: Maybe String -> String
-pkgInfoModuleName Nothing = "PkgInfo"
-pkgInfoModuleName (Just cn) = "PkgInfo_" ++ map tr cn
+-- -------------------------------------------------------------------------- --
+-- Generate PkgInfo Module
+
+pkgInfoModuleName :: String
+pkgInfoModuleName = "PkgInfo"
+
+updateFile :: FilePath -> B.ByteString -> IO ()
+updateFile fileName content = do
+ doesFileExist fileName >>= \x -> if x
+ then do
+ oldRevisionFile <- B.readFile fileName
+ when (oldRevisionFile /= content) update
+ else
+ update
+ where
+ update = B.writeFile fileName content
+
+legacyPkgInfoModuleName :: Maybe String -> String
+legacyPkgInfoModuleName Nothing = "PkgInfo"
+legacyPkgInfoModuleName (Just cn) = "PkgInfo_" ++ map tr cn
where
tr '-' = '_'
tr c = c
--- FIXME: autoModulesDir is deprecated and should be replaced by
--- autogenComponentModulesDir.
-pkgInfoFileName :: Maybe String -> LocalBuildInfo -> FilePath
-pkgInfoFileName cn bInfo = autogenModulesDir bInfo ++ "/" ++ pkgInfoModuleName cn ++ ".hs"
-
trim :: String -> String
trim = f . f
where f = reverse . dropWhile isSpace
@@ -236,23 +309,8 @@ getVcsOfDir d = do
then return Nothing
else getVcsOfDir (takeDirectory canonicDir)
-#if !MIN_VERSION_Cabal(2,0,0)
-unFlagName :: FlagName -> String
-unFlagName (FlagName s) = s
-#endif
-
-#if !MIN_VERSION_Cabal(2,2,0)
-unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
-unFlagAssignment = id
-#endif
-
-#if !MIN_VERSION_Cabal(2,2,0)
-prettyShow :: Text a => a -> String
-prettyShow = display
-#endif
-
-pkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString
-pkgInfoModule cName pkgDesc bInfo = do
+pkgInfoModule :: String -> Maybe String -> PackageDescription -> LocalBuildInfo -> IO B.ByteString
+pkgInfoModule moduleName cName pkgDesc bInfo = do
(tag, revision, branch) <- getVCS >>= \x -> case x of
Just Mercurial -> hgInfo
Just Git -> gitInfo
@@ -268,10 +326,11 @@ pkgInfoModule cName pkgDesc bInfo = do
[ "{-# LANGUAGE OverloadedStrings #-}"
, "{-# LANGUAGE RankNTypes #-}"
, ""
- , "module " <> (pack . pkgInfoModuleName) cName <> " where"
+ , "module " <> pack moduleName <> " " <> deprecatedMsg <> " where"
, ""
, " import Data.String (IsString)"
, " import Data.Monoid"
+ , " import Prelude hiding ((<>))"
, ""
, " name :: IsString a => Maybe a"
, " name = " <> maybe "Nothing" (\x -> "Just \"" <> pack x <> "\"") cName
@@ -365,83 +424,19 @@ pkgInfoModule cName pkgDesc bInfo = do
displayOptimisationLevel NormalOptimisation = "normal"
displayOptimisationLevel MaximumOptimisation = "maximum"
-updatePkgInfoModule :: Maybe String -> PackageDescription -> LocalBuildInfo -> IO ()
-updatePkgInfoModule cName pkgDesc bInfo = do
- createDirectoryIfMissing True $ autogenModulesDir bInfo
- newFile <- pkgInfoModule cName pkgDesc bInfo
- let update = B.writeFile fileName newFile
- doesFileExist fileName >>= \x -> if x
- then do
- oldRevisionFile <- B.readFile fileName
- when (oldRevisionFile /= newFile) update
- else
- update
- where
- fileName = pkgInfoFileName cName bInfo
+ deprecatedMsg = if moduleName /= pkgInfoModuleName
+ then "{-# DEPRECATED \"Update to Cabal 2.0 or later and use just PkgInfo as module name.\" #-}"
+ else ""
licenseFilesText :: PackageDescription -> IO B.ByteString
licenseFilesText pkgDesc =
B.intercalate "\n------------------------------------------------------------\n" <$> mapM fileText
-#ifdef NO_CABAL_MACROS
- (getLicenseFiles pkgDesc)
-#elif MIN_VERSION_Cabal(1,20,0)
(licenseFiles pkgDesc)
-#else
- [licenseFile pkgDesc]
-#endif
where
fileText file = doesFileExist file >>= \x -> if x
then B.readFile file
else return ""
-#ifdef NO_CABAL_MACROS
--- The name and the type of the @licenseFile :: String@ field of
--- 'PackageDescription' changed in Cabal version 1.20 to @licenseFiles ::
--- [String]@. Both versions are used with GHC-7.8. In Cabal version 1.24 the
--- number of constructor fields changed for PackageDescription. When compiling
--- @Setup.hs@ the @MIN_VERSION_...@ macros are not available. This function is
--- an ugly hack to do conditional compilation without CPP. It depends on the
--- @RecordWildCards@ and @Typeable@ extensions and abuses shaddowing of
--- existing symbols.
---
--- Alternative methods would include:
---
--- * Use typeable to pattern match on the number of constructor arguments for
--- 'PackageDescription',
--- * use TH hacks ala @$( if versionBranch cabalVersion < [...] ... )@, and/or
--- * make guesses about the cabal version based on the @__GLASGOW_HASKELL__@
--- macro.
-
--- Return license files of from the @PackageDescription@.
---
-getLicenseFiles :: PackageDescription -> [FilePath]
-getLicenseFiles pkgDesc = f pkgDesc
- where
- -- Recent versions of @PackageDescription@ define a @licenseFiles@ field.
- -- For older versions the function @licenseFiles@ that is defined below is
- -- used.
- --
- f PackageDescription{..} = licenseFiles
-
- -- If @PackageDescription@ doesn't define @licenseFiles@ this definition
- -- will be used. In that case @PackageDescription@ is assumed to define
- -- @licenseFile@.
- --
- licenseFiles :: [FilePath]
- licenseFiles = fromMaybe (error "unsupported Cabal library version") $
- return <$> cast (g pkgDesc)
-
- g PackageDescription{..} = licenseFile
-
- -- The only purpose of this function is to ensure that licenseFile is
- -- defined in case PackageDescription doesn't have a @licenseFile@ field.
- -- This function won't be called with any supported version of the Cabal
- -- library.
- --
- licenseFile :: [FilePath]
- licenseFile = error "unexpected Cabal library version"
-#endif
-
hgInfo :: IO (String, String, String)
hgInfo = do
tag <- trim <$> readProcess "hg" ["id", "-r", "max(ancestors(\".\") and tag())", "-t"] ""
@@ -466,11 +461,7 @@ noVcsInfo = return ("", "", "")
pkgIdWithLicense :: I.InstalledPackageInfo -> String
pkgIdWithLicense a = (display . packageId) a
++ " ["
-#if MIN_VERSION_Cabal(2,2,0)
- ++ (either prettyShow prettyShow . I.license) a
-#else
- ++ (prettyShow . I.license) a
-#endif
+ ++ prettyLicense a
++ (if cr /= "" then ", " ++ cr else "")
++ "]"
where
diff --git a/src/Configuration/Utils/Validation.hs b/src/Configuration/Utils/Validation.hs
index fecd458..001d598 100644
--- a/src/Configuration/Utils/Validation.hs
+++ b/src/Configuration/Utils/Validation.hs
@@ -6,10 +6,6 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
-#ifndef MIN_VERSION_base
-#define MIN_VERSION_base(x,y,z) 1
-#endif
-
-- |
-- Module: Configuration.Utils.Validation
-- Copyright: Copyright © 2014 AlephCloud Systems, Inc.
@@ -71,18 +67,12 @@ module Configuration.Utils.Validation
import Configuration.Utils.Internal
-#if ! MIN_VERSION_base(4,8,0)
-import Control.Applicative
-#endif
import Control.Monad.Error.Class
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Writer.Class
import qualified Data.Foldable as F
-#if ! MIN_VERSION_base(4,8,0)
-import Data.Monoid
-#endif
import Data.Monoid.Unicode
import qualified Data.Text as T
diff --git a/test/TestExample.hs b/test/TestExample.hs
index 6a571e8..6ed64c8 100644
--- a/test/TestExample.hs
+++ b/test/TestExample.hs
@@ -2,7 +2,6 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
-{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
@@ -38,7 +37,11 @@ import Example hiding (main)
import Prelude.Unicode
+#if MIN_VERSION_Cabal(2,0,0)
+import PkgInfo
+#else
import PkgInfo_url_example_test
+#endif
-- -------------------------------------------------------------------------- --
-- main