diff options
Diffstat (limited to 'src/Propellor/Property/List.hs')
| -rw-r--r-- | src/Propellor/Property/List.hs | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/Propellor/Property/List.hs b/src/Propellor/Property/List.hs new file mode 100644 index 00000000..283c5ec7 --- /dev/null +++ b/src/Propellor/Property/List.hs @@ -0,0 +1,63 @@ +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE FlexibleInstances #-} + +module Propellor.Property.List ( + PropertyList(..), + PropertyListType, +) where + +import Propellor.Types +import Propellor.Engine +import Propellor.PropAccum + +import Data.Monoid + +class PropertyList l where + -- | Combines a list of properties, resulting in a single property + -- that when run will run each property in the list in turn, + -- and print out the description of each as it's run. Does not stop + -- on failure; does propigate overall success/failure. + -- + -- Note that Property HasInfo and Property NoInfo are not the same + -- type, and so cannot be mixed in a list. To make a list of + -- mixed types, which can also include RevertableProperty, + -- use `props`: + -- + -- > propertyList "foo" $ props + -- > & someproperty + -- > ! oldproperty + -- > & otherproperty + propertyList :: Desc -> l -> Property (PropertyListType l) + + -- | Combines a list of properties, resulting in one property that + -- ensures each in turn. Stops if a property fails. + combineProperties :: Desc -> l -> Property (PropertyListType l) + +-- | Type level function to calculate whether a PropertyList has Info. +type family PropertyListType t +type instance PropertyListType [Property HasInfo] = HasInfo +type instance PropertyListType [Property NoInfo] = NoInfo +type instance PropertyListType PropList = HasInfo + +instance PropertyList [Property NoInfo] where + propertyList desc ps = simpleProperty desc (ensureProperties ps) ps + combineProperties desc ps = simpleProperty desc (combineSatisfy ps NoChange) ps + +instance PropertyList [Property HasInfo] where + -- It's ok to use ignoreInfo here, because the ps are made the + -- child properties of the property, and so their info is visible + -- that way. + propertyList desc ps = infoProperty desc (ensureProperties $ map ignoreInfo ps) mempty ps + combineProperties desc ps = infoProperty desc (combineSatisfy ps NoChange) mempty ps + +instance PropertyList PropList where + propertyList desc = propertyList desc . getProperties + combineProperties desc = combineProperties desc . getProperties + +combineSatisfy :: [Property i] -> Result -> Propellor Result +combineSatisfy [] rs = return rs +combineSatisfy (l:ls) rs = do + r <- ensureProperty $ ignoreInfo l + case r of + FailedChange -> return FailedChange + _ -> combineSatisfy ls (r <> rs) |
