cabal-constraints (empty) → 0.0.0.1
raw patch · 4 files changed
+223/−0 lines, 4 filesdep +Cabaldep +basedep +optparse-applicativesetup-changed
Dependencies added: Cabal, base, optparse-applicative
Files
- LICENSE +21/−0
- Setup.hs +2/−0
- cabal-constraints.cabal +107/−0
- src/CabalConstraints.hs +93/−0
+ LICENSE view
@@ -0,0 +1,21 @@+The MIT License (MIT)++Copyright (c) 2013 Benjamen Armston++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cabal-constraints.cabal view
@@ -0,0 +1,107 @@+name: cabal-constraints+-- The package version. See the Haskell package versioning policy (PVP) +-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 0.0.0.1+synopsis: Repeatable builds for cabalized Haskell projects.+description:+ /Repeatable builds for cabalized Haskell projects/+ .+ \'cabal-constraints\' provides repeatable builds for cabalized Haskell+ projects by \"freezing\" the exact versions of the dependencies selected by+ \'cabal-install\'. All build environments for the project, such as the test+ or staging build environments, or other developers collaborating on the+ project, will then use the same dependency versions.+ .+ It is designed to be used alongside \'cabal-install\' sandboxes, in which+ case isolated, repeatable builds can be achieved.+ .+ /Using cabal-constraints/+ .+ \'cabal-constraints\' should be run from the root directory of a cabalized+ Haskell project and given the path to the `setup-config` file to use. It will+ print out all dependencies of the project in a format suitable for use in a+ `cabal-install` config file. For example, running \'cabal-constraints\'+ against itself produces the following:+ .+ @+ $ cabal-constraints dist\/dist-sandbox-500003c6\/setup-config+ constraints: Cabal == 1.19.0+ , array == 0.4.0.1+ , base == 4.6.0.1+ , bytestring == 0.10.0.2+ , containers == 0.5.0.0+ , deepseq == 1.3.0.1+ , directory == 1.2.0.1+ , filepath == 1.3.0.1+ , ghc-prim == 0.3.0.0+ , integer-gmp == 0.5.0.0+ , old-locale == 1.0.0.5+ , pretty == 1.1.1.0+ , process == 1.1.0.2+ , rts == 1.0+ , time == 1.4.0.1+ , unix == 2.6.0.1+ @+ .+ A single mandatory argument must be provided which is the path to the+ @setup-config@ file to use. The file will be located under the @dist@+ directory. Usually there will be a single @setup-config@ file which can be+ found by running @find dist -name setup-config@ from the root directory of the+ project. If your project has more than one such file, it is likely because+ you have built it either with and without sandboxes or with multiple+ sandboxes. You probably want the most recently modified file which can be+ found with @ls -tr $( find dist -name setup-config ) | tail -n1@.+ .+ To use these constraints for reproducible builds, one should make use of the+ new sandbox feature of @cabal-install@ 1.18. The constraints can be redirected+ to @cabal.config@ and committed to your code repository. When the project is+ built, the same set of dependency versions will be resolved by @cabal-install@+ ensuring repeatable builds.+ .+ If @cabal.config@ contains no other information the simplest solution is to+ overwrite it:+ .+ @+ $ cabal-constraints > cabal.config+ @+ .+ If @cabal.config@ contains information that needs to be preserved, the+ following will replace the @constraints@ section and everything following it+ with the new constraints. If you ensure that the @constraints@ section is the+ last section of the file, all other information in it will be kept.+ .+ @+ $ sed -i \/^constraints:\/,$d cabal.config && cabal-constraints >> cabal.config+ @+++homepage: https://github.com/benarmston/cabal-constraints+license: MIT+license-file: LICENSE+author: Ben Armston+maintainer: ben.armston@googlemail.com+-- A copyright notice.+-- copyright: +category: Development, Distribution+build-type: Simple+cabal-version: >=1.8++source-repository head+ type: git+ location: https://github.com/benarmston/cabal-constraints.git++executable cabal-constraints+ -- .hs or .lhs file containing the Main module.+ main-is: src/CabalConstraints.hs+ + -- Modules included in this executable, other than Main.+ -- other-modules: + + -- Other library packages from which modules are imported.+ build-depends: base ==4.6.*+ , Cabal >= 1.18+ , optparse-applicative >= 0.5.2.1
+ src/CabalConstraints.hs view
@@ -0,0 +1,93 @@+import Data.Maybe (fromMaybe)+import Data.Function (on)+import Data.List (intercalate, sortBy)+import Data.Version (showVersion)++import Distribution.Package (PackageName(PackageName), Dependency(Dependency), pkgVersion)+import Distribution.Simple.Configure (tryGetConfigStateFile)+import Distribution.Simple.PackageIndex (allPackagesByName)+import Distribution.InstalledPackageInfo (sourcePackageId)+import Distribution.Simple.LocalBuildInfo (LocalBuildInfo, configFlags, installedPkgs)+import Distribution.Simple.Setup (configConstraints)+import Distribution.Version (Version, isSpecificVersion)++import Options.Applicative++data Args = Args { depth :: Depth+ , setupConfigPath :: String+ }++data Depth = Deep | Shallow+++options :: Parser Args+options = Args+ <$> flag Deep Shallow+ ( long "shallow"+ <> help "Only show the dependencies specified in the .cabal file"+ )+ <*> argument Just+ ( metavar "<PATH TO setup-config>"+ <> action "file"+ )+++main :: IO ()+main = execParser opts >>= printConstraints+ where+ opts = info (helper <*> options)+ ( fullDesc+ <> progDesc (unlines [ "Show exact dependency constraints for a cabal project, by reading"+ , " the setup-config file located at PATH, defaulting to \"dist/setup-config\"."+ ])+ )+++printConstraints :: Args -> IO ()+printConstraints args = do+ let deps = case depth args of+ Deep -> deepDeps+ Shallow -> shallowDeps+ lbi' <- tryGetConfigStateFile (setupConfigPath args)+ either printError (putStrLn . formattedConstraints . deps) lbi'+ where+ printError = putStrLn . fst+++shallowDeps :: LocalBuildInfo -> [(PackageName, [Version])]+shallowDeps = sortBy (compare `on` fst)+ . map format . configConstraints . configFlags+ where+ format dependency@(Dependency name versionRange) =+ let version = fromMaybe (error $ errorMsg dependency)+ (isSpecificVersion versionRange)+ in (name, [version])+ errorMsg dependency =+ "malformed setup-config: " +++ "dependency is not constrained to a specific version: "+ ++ show dependency+++deepDeps :: LocalBuildInfo -> [(PackageName, [Version])]+deepDeps = map format+ . allPackagesByName+ . installedPkgs+ where+ format (name, pkgInfos) = (name, map (pkgVersion. sourcePackageId) pkgInfos)+++formattedConstraints :: [(PackageName, [Version])] -> String+formattedConstraints = (prefix ++)+ . intercalate separator+ . map formatConstraint+ where+ prefix = "constraints: "+ separator = "\n" ++ replicate (length prefix - 2) ' ' ++ ", " +++formatConstraint :: (PackageName, [Version]) -> String+formatConstraint (PackageName name, versions) =+ name ++ " == " ++ allVersionConstraints versions+ where+ allVersionConstraints = intercalate " || "+ . map showVersion