3 -----------------------------------------------------------------------------
5 -----------------------------------------------------------------------------
8 -- Module : Distribution.Client.GenBounds
9 -- Copyright : (c) Doug Beardsley 2015
12 -- Maintainer : cabal-devel@gmail.com
13 -- Stability : provisional
14 -- Portability : portable
16 -- The cabal gen-bounds command for generating PVP-compliant version bounds.
17 module Distribution
.Client
.GenBounds
21 import Distribution
.Client
.Compat
.Prelude
24 import Distribution
.Client
.Freeze
27 import Distribution
.Client
.Setup
32 import Distribution
.Client
.Utils
36 import Distribution
.Package
42 import Distribution
.PackageDescription
45 import Distribution
.PackageDescription
.Configuration
48 import Distribution
.Simple
.Compiler
53 import Distribution
.Simple
.PackageDescription
54 ( readGenericPackageDescription
56 import Distribution
.Simple
.Program
59 import Distribution
.Simple
.Utils
63 import Distribution
.System
66 import Distribution
.Types
.ComponentRequestedSpec
67 ( defaultComponentRequestedSpec
69 import Distribution
.Types
.Dependency
70 import Distribution
.Version
74 , VersionInterval
(..)
80 , intersectVersionRanges
83 import System
.Directory
87 -- | Given a version, return an API-compatible (according to PVP) version range.
89 -- Example: @0.4.1.2@ produces the version range @>= 0.4.1 && < 0.5@.
91 -- This version is slightly different than the one in
92 -- 'Distribution.Client.Init'. This one uses a.b.c as the lower bound because
93 -- the user could be using a new function introduced in a.b.c which would make
94 -- ">= a.b" incorrect.
95 pvpize
:: Version
-> VersionRange
98 `intersectVersionRanges` earlierVersion
(incVersion
1 (vn
2))
100 vn n
= alterVersion
(take n
) v
102 -- | Show the PVP-mandated version range for this package. The @padTo@ parameter
103 -- specifies the width of the package name column.
104 showBounds
:: Package pkg
=> Int -> pkg
-> String
107 padAfter padTo
(unPackageName
$ packageName p
)
109 -- TODO: use normaliseVersionRange
110 map showInterval
(asVersionIntervals
$ pvpize
$ packageVersion p
)
112 padAfter
:: Int -> String -> String
113 padAfter n str
= str
++ replicate (n
- length str
) ' '
115 showInterval
:: VersionInterval
-> String
116 showInterval
(VersionInterval
(LowerBound _ _
) NoUpperBound
) =
117 error "Error: expected upper bound...this should never happen!"
118 showInterval
(VersionInterval
(LowerBound l _
) (UpperBound u _
)) =
119 unwords [">=", prettyShow l
, "&& <", prettyShow u
]
121 -- | Entry point for the @gen-bounds@ command.
132 genBounds verbosity packageDBs repoCtxt comp platform progdb globalFlags freezeFlags
= do
133 let cinfo
= compilerInfo comp
135 cwd
<- getCurrentDirectory
136 path
<- tryFindPackageDesc verbosity cwd
137 gpd
<- readGenericPackageDescription verbosity path
138 -- NB: We don't enable tests or benchmarks, since often they
139 -- don't really have useful bounds.
143 defaultComponentRequestedSpec
150 Left _
-> putStrLn "finalizePD failed"
154 filter (not . hasUpperBound
. depVersion
) $
155 enabledBuildDepends pd defaultComponentRequestedSpec
168 let isNeeded
= hasElem needBounds
. unPackageName
. packageName
169 let thePkgs
= filter isNeeded pkgs
171 let padTo
= maximum $ map (length . unPackageName
. packageName
) pkgs
177 "Congratulations, all your dependencies have upper bounds!"
179 notice verbosity boundsNeededMsg
180 traverse_
(notice verbosity
. (++ ",") . showBounds padTo
) thePkgs
182 depName
:: Dependency
-> String
183 depName
(Dependency pn _ _
) = unPackageName pn
185 depVersion
:: Dependency
-> VersionRange
186 depVersion
(Dependency _ vr _
) = vr
188 -- | The message printed when some dependencies are found to be lacking proper
189 -- PVP-mandated bounds.
190 boundsNeededMsg
:: String
194 , "The following packages need bounds and here is a suggested starting point."
195 , "You can copy and paste this into the build-depends section in your .cabal"
196 , "file and it should work (with the appropriate removal of commas)."
198 , "Note that version bounds are a statement that you've successfully built and"
199 , "tested your package and expect it to work with any of the specified package"
200 , "versions (PROVIDED that those packages continue to conform with the PVP)."
201 , "Therefore, the version bounds generated here are the most conservative"
202 , "based on the versions that you are currently building with. If you know"
203 , "your package will work with versions outside the ranges generated here,"
204 , "feel free to widen them."