Skip to content

Commit ade6050

Browse files
committed
Makes flags overridable on the command line.
This is to fix issue #4452.
1 parent a572a1f commit ade6050

File tree

3 files changed

+46
-23
lines changed

3 files changed

+46
-23
lines changed

Cabal/Distribution/PackageDescription.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ module Distribution.PackageDescription (
9898
nullFlagAssignment, showFlagValue,
9999
diffFlagAssignment, lookupFlagAssignment, insertFlagAssignment,
100100
dispFlagAssignment, parseFlagAssignment, parsecFlagAssignment,
101+
findDuplicateFlagAssignments,
101102
CondTree(..), ConfVar(..), Condition(..),
102103
cNot, cAnd, cOr,
103104

Cabal/Distribution/Types/GenericPackageDescription.hs

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Distribution.Types.GenericPackageDescription (
1616
lookupFlagAssignment,
1717
insertFlagAssignment,
1818
diffFlagAssignment,
19+
findDuplicateFlagAssignments,
1920
nullFlagAssignment,
2021
showFlagValue,
2122
dispFlagAssignment,
@@ -25,11 +26,11 @@ module Distribution.Types.GenericPackageDescription (
2526
) where
2627

2728
import Prelude ()
28-
import Data.List ((\\))
2929
import Distribution.Compat.Prelude
3030
import Distribution.Utils.ShortText
3131
import Distribution.Utils.Generic (lowercase)
3232
import qualified Text.PrettyPrint as Disp
33+
import qualified Data.Map as Map
3334
import qualified Distribution.Compat.ReadP as Parse
3435
import qualified Distribution.Compat.Parsec as P
3536
import Distribution.Compat.ReadP ((+++))
@@ -154,55 +155,74 @@ instance Text FlagName where
154155
-- discovered during configuration. For example @--flags=foo --flags=-bar@
155156
-- becomes @[("foo", True), ("bar", False)]@
156157
--
157-
newtype FlagAssignment = FlagAssignment [(FlagName, Bool)]
158-
deriving (Binary,Eq,Ord,Semigroup,Monoid)
158+
newtype FlagAssignment = FlagAssignment { getFlagAssignment :: Map.Map FlagName (Int, Bool) }
159+
deriving (Binary,Eq,Ord)
159160

160-
-- TODO: the Semigroup/Monoid/Ord/Eq instances would benefit from
161-
-- [(FlagName,Bool)] being in a normal form, i.e. sorted. We could
162-
-- e.g. switch to a `Data.Map.Map` representation, but see duplicates
163-
-- check in `configuredPackageProblems`.
161+
-- | Combines pairs of values contained in the 'FlagAssignment' Map.
164162
--
165-
-- Also, the 'Semigroup' instance currently is left-biased as entries
166-
-- in the left-hand 'FlagAssignment' shadow those occuring in the
167-
-- right-hand side 'FlagAssignment' for the same flagnames.
163+
-- The last flag specified takes precedence, and we record the number
164+
-- of times we have seen the flag.
165+
--
166+
combineFlagValues :: (Int, Bool) -> (Int, Bool) -> (Int, Bool)
167+
combineFlagValues (c1, _) (c2, b2) = (c1 + c2, b2)
168+
169+
-- The 'Semigroup' instance currently is right-biased.
170+
--
171+
-- If duplicate flags are specified, we want the last flag specified to
172+
-- take precedence and we want to know how many times the flag has been
173+
-- specified so that we have the option of warning the user about
174+
-- supplying duplicate flags.
175+
instance Semigroup FlagAssignment where
176+
(<>) (FlagAssignment m1) (FlagAssignment m2) = FlagAssignment (Map.unionWith combineFlagValues m1 m2)
177+
178+
instance Monoid FlagAssignment where
179+
mempty = FlagAssignment Map.empty
180+
mappend = (<>)
168181

169182
-- | Construct a 'FlagAssignment' from a list of flag/value pairs.
170183
--
184+
-- If duplicate flags occur in the input list, the later entries
185+
-- in the list will take precedence.
186+
--
171187
-- @since 2.2.0
172188
mkFlagAssignment :: [(FlagName, Bool)] -> FlagAssignment
173-
mkFlagAssignment = FlagAssignment
189+
mkFlagAssignment = FlagAssignment . Map.fromListWith (flip combineFlagValues) . fmap (fmap (\b -> (1, b)))
174190

175191
-- | Deconstruct a 'FlagAssignment' into a list of flag/value pairs.
176192
--
177-
-- @ ('mkFlagAssignment' . 'unFlagAssignment') fa == fa @
193+
-- @ 'null' ('findDuplicateFlagAssignments' fa) ==> ('mkFlagAssignment' . 'unFlagAssignment') fa == fa @
178194
--
179195
-- @since 2.2.0
180196
unFlagAssignment :: FlagAssignment -> [(FlagName, Bool)]
181-
unFlagAssignment (FlagAssignment xs) = xs
197+
unFlagAssignment = fmap (fmap snd) . Map.toList . getFlagAssignment
182198

183199
-- | Test whether 'FlagAssignment' is empty.
184200
--
185201
-- @since 2.2.0
186202
nullFlagAssignment :: FlagAssignment -> Bool
187-
nullFlagAssignment (FlagAssignment []) = True
188-
nullFlagAssignment _ = False
203+
nullFlagAssignment = Map.null . getFlagAssignment
189204

190205
-- | Lookup the value for a flag
191206
--
192207
-- Returns 'Nothing' if the flag isn't contained in the 'FlagAssignment'.
193208
--
194209
-- @since 2.2.0
195210
lookupFlagAssignment :: FlagName -> FlagAssignment -> Maybe Bool
196-
lookupFlagAssignment fn = lookup fn . unFlagAssignment
211+
lookupFlagAssignment fn = fmap snd . Map.lookup fn . getFlagAssignment
197212

198213
-- | Insert or update the boolean value of a flag.
199214
--
215+
-- If the flag is already present in the 'FlagAssigment', the
216+
-- value will be updated and the fact that multiple values have
217+
-- been provided for that flag will be recorded so that a
218+
-- warning can be generated later on.
219+
--
200220
-- @since 2.2.0
201221
insertFlagAssignment :: FlagName -> Bool -> FlagAssignment -> FlagAssignment
202222
-- TODO: this currently just shadows prior values for an existing flag;
203223
-- rather than enforcing uniqueness at construction, it's verified lateron via
204224
-- `D.C.Dependency.configuredPackageProblems`
205-
insertFlagAssignment flag val = mkFlagAssignment . ((flag,val):) . unFlagAssignment
225+
insertFlagAssignment flag val = FlagAssignment . Map.insertWith (flip combineFlagValues) flag (1, val) . getFlagAssignment
206226

207227
-- | Remove all flag-assignments from the first 'FlagAssignment' that
208228
-- are contained in the second 'FlagAssignment'
@@ -214,7 +234,10 @@ insertFlagAssignment flag val = mkFlagAssignment . ((flag,val):) . unFlagAssignm
214234
--
215235
-- @since 2.2.0
216236
diffFlagAssignment :: FlagAssignment -> FlagAssignment -> FlagAssignment
217-
diffFlagAssignment fa1 fa2 = mkFlagAssignment (unFlagAssignment fa1 \\ unFlagAssignment fa2)
237+
diffFlagAssignment fa1 fa2 = FlagAssignment (Map.difference (getFlagAssignment fa1) (getFlagAssignment fa2))
238+
239+
findDuplicateFlagAssignments :: FlagAssignment -> [FlagName]
240+
findDuplicateFlagAssignments = Map.keys . Map.filter ((> 1) . fst) . getFlagAssignment
218241

219242
-- | @since 2.2.0
220243
instance Read FlagAssignment where
@@ -235,7 +258,7 @@ dispFlagAssignment = Disp.hsep . map (Disp.text . showFlagValue) . unFlagAssignm
235258

236259
-- | Parses a flag assignment.
237260
parsecFlagAssignment :: ParsecParser FlagAssignment
238-
parsecFlagAssignment = FlagAssignment <$> P.sepBy (onFlag <|> offFlag) P.skipSpaces1
261+
parsecFlagAssignment = mkFlagAssignment <$> P.sepBy (onFlag <|> offFlag) P.skipSpaces1
239262
where
240263
onFlag = do
241264
P.optional (P.char '+')
@@ -248,7 +271,7 @@ parsecFlagAssignment = FlagAssignment <$> P.sepBy (onFlag <|> offFlag) P.skipSpa
248271

249272
-- | Parses a flag assignment.
250273
parseFlagAssignment :: Parse.ReadP r FlagAssignment
251-
parseFlagAssignment = FlagAssignment <$> Parse.sepBy parseFlagValue Parse.skipSpaces1
274+
parseFlagAssignment = mkFlagAssignment <$> Parse.sepBy parseFlagValue Parse.skipSpaces1
252275
where
253276
parseFlagValue =
254277
(do Parse.optional (Parse.char '+')

cabal-install/Distribution/Client/Dependency.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ import Distribution.Compiler
9696
import Distribution.System
9797
( Platform )
9898
import Distribution.Client.Utils
99-
( duplicates, duplicatesBy, mergeBy, MergeResult(..) )
99+
( duplicatesBy, mergeBy, MergeResult(..) )
100100
import Distribution.Simple.Utils
101101
( comparing )
102102
import Distribution.Simple.Setup
@@ -889,8 +889,7 @@ configuredPackageProblems :: Platform -> CompilerInfo
889889
-> SolverPackage UnresolvedPkgLoc -> [PackageProblem]
890890
configuredPackageProblems platform cinfo
891891
(SolverPackage pkg specifiedFlags stanzas specifiedDeps' _specifiedExeDeps') =
892-
-- FIXME/TODO: FlagAssignment ought to be duplicate-free as internal invariant
893-
[ DuplicateFlag flag | ((flag,_):_) <- duplicates (PD.unFlagAssignment specifiedFlags) ]
892+
[ DuplicateFlag flag | flag <- PD.findDuplicateFlagAssignments specifiedFlags ]
894893
++ [ MissingFlag flag | OnlyInLeft flag <- mergedFlags ]
895894
++ [ ExtraFlag flag | OnlyInRight flag <- mergedFlags ]
896895
++ [ DuplicateDeps pkgs

0 commit comments

Comments
 (0)