    -- | Maintainer: Sean Whitton <spwhitton@spwhitton.name>

    {-# LANGUAGE DeriveDataTypeable #-}

    module Propellor.Property.Schroot where

    import Propellor.Base
    import Propellor.Types.Info
    import qualified Propellor.Property.File as File
    import qualified Propellor.Property.Apt as Apt

    data UseOverlays = UseOverlays deriving (UseOverlays -> UseOverlays -> Bool
    (UseOverlays -> UseOverlays -> Bool)
    -> (UseOverlays -> UseOverlays -> Bool) -> Eq UseOverlays
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: UseOverlays -> UseOverlays -> Bool
    == :: UseOverlays -> UseOverlays -> Bool
    $c/= :: UseOverlays -> UseOverlays -> Bool
    /= :: UseOverlays -> UseOverlays -> Bool
    Eq, Int -> UseOverlays -> ShowS
    [UseOverlays] -> ShowS
    UseOverlays -> String
    (Int -> UseOverlays -> ShowS)
    -> (UseOverlays -> String)
    -> ([UseOverlays] -> ShowS)
    -> Show UseOverlays
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> UseOverlays -> ShowS
    showsPrec :: Int -> UseOverlays -> ShowS
    $cshow :: UseOverlays -> String
    show :: UseOverlays -> String
    $cshowList :: [UseOverlays] -> ShowS
    showList :: [UseOverlays] -> ShowS
    Show, Typeable)

    -- | Indicate that a schroots on a host should use @union-type=overlay@
    --
    -- Setting this property does not actually ensure that the line
    -- @union-type=overlay@ is present in any schroot config files.  See
    -- 'Propellor.Property.Sbuild.built' for example usage.
    useOverlays :: Property (HasInfo + UnixLike)
    useOverlays :: Property
      (HasInfo
       + MetaTypes
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
              'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    useOverlays = String
    -> InfoVal UseOverlays
    -> Property
         (HasInfo
          + MetaTypes
              '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                 'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    forall v.
    IsInfo v =>
    String
    -> v
    -> Property
         (HasInfo
          + MetaTypes
              '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                 'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    pureInfoProperty String
    "use schroot overlays" (UseOverlays -> InfoVal UseOverlays
    forall v. v -> InfoVal v
    InfoVal UseOverlays
    UseOverlays)

    -- | Gets whether a host uses overlays.
    usesOverlays :: Propellor Bool
    usesOverlays :: Propellor Bool
    usesOverlays = Maybe UseOverlays -> Bool
    forall a. Maybe a -> Bool
    isJust (Maybe UseOverlays -> Bool)
    -> (InfoVal UseOverlays -> Maybe UseOverlays)
    -> InfoVal UseOverlays
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . InfoVal UseOverlays -> Maybe UseOverlays
    forall v. InfoVal v -> Maybe v
    fromInfoVal
    	(InfoVal UseOverlays -> Bool)
    -> Propellor (InfoVal UseOverlays) -> Propellor Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Propellor (InfoVal UseOverlays)
    forall v. IsInfo v => Propellor v
    askInfo :: Propellor (InfoVal UseOverlays))

    -- | Configure schroot such that all schroots with @union-type=overlay@ in their
    -- configuration will run their overlays in a tmpfs.
    --
    -- Implicitly sets 'useOverlays' info property.
    --
    -- Shell script from <https://wiki.debian.org/sbuild>.
    overlaysInTmpfs :: RevertableProperty (HasInfo + DebianLike) UnixLike
    overlaysInTmpfs :: RevertableProperty
      (HasInfo + DebianLike)
      (MetaTypes
         '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    overlaysInTmpfs = (Property
      (MetaTypes
         '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    Property
      (HasInfo
       + MetaTypes
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
              'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    go Property
      (MetaTypes
         '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> Property DebianLike
    -> CombinedType
         (Property
            (MetaTypes
               '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                  'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
         (Property DebianLike)
    forall x y. Combines x y => x -> y -> CombinedType x y
    `requires` Property DebianLike
    installed) Property
      (Sing '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish])
    -> Property
         (MetaTypes
            '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> RevertableProperty
         (Sing '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish])
         (MetaTypes
            '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    forall setupmetatypes undometatypes.
    Property setupmetatypes
    -> Property undometatypes
    -> RevertableProperty setupmetatypes undometatypes
    <!> Property
      (MetaTypes
         '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    undo
      where
    	f :: String
    f = String
    "/etc/schroot/setup.d/04tmpfs"
    	go :: Property (HasInfo + UnixLike)
    	go :: Property
      (HasInfo
       + MetaTypes
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
              'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    go = String
    -> Props
         (MetaTypes
            '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> Property
         (MetaTypes
            '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    forall {k} (metatypes :: k).
    SingI metatypes =>
    String
    -> Props (MetaTypes metatypes) -> Property (MetaTypes metatypes)
    combineProperties String
    "schroot overlays in tmpfs" (Props
       (MetaTypes
          '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
             'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
     -> Property
          (MetaTypes
             '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
    -> Props
         (MetaTypes
            '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> Property
         (MetaTypes
            '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    forall a b. (a -> b) -> a -> b
    $ Props
      (MetaTypes
         '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    props
    		Props
      (MetaTypes
         '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> Property
         (MetaTypes
            '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> Props
         (Sing
            (Combine
               '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                  'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
               '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                  'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
    forall {a} p (y :: [a]) (x :: [a]).
    (IsProp p, MetaTypes y ~ GetMetaTypes p,
     CheckCombinableNote x y (NoteFor ('Text "&"))) =>
    Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
    & Property
      (MetaTypes
         '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    Property
      (HasInfo
       + MetaTypes
           '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
              'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    useOverlays
    		Props
      (Sing
         (Combine
            '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
            '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
    -> Property
         (MetaTypes
            '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> Props
         (MetaTypes
            (Combine
               (Combine
                  '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                     'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]
                  '[ 'WithInfo, 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                     'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
               '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                  'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
    forall {a} p (y :: [a]) (x :: [a]).
    (IsProp p, MetaTypes y ~ GetMetaTypes p,
     CheckCombinableNote x y (NoteFor ('Text "&"))) =>
    Props (MetaTypes x) -> p -> Props (MetaTypes (Combine x y))
    & String
    f String
    -> [String]
    -> Property
         (MetaTypes
            '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    `File.hasContent`
    			[ String
    "#!/bin/sh"
    			, String
    ""
    			, String
    "set -e"
    			, String
    ""
    			, String
    ". \"$SETUP_DATA_DIR/common-data\""
    			, String
    ". \"$SETUP_DATA_DIR/common-functions\""
    			, String
    ". \"$SETUP_DATA_DIR/common-config\""
    			, String
    ""
    			, String
    ""
    			, String
    "if [ $STAGE = \"setup-start\" ]; then"
    			, String
    "  mount -t tmpfs overlay /var/lib/schroot/union/overlay"
    			, String
    "elif [ $STAGE = \"setup-recover\" ]; then"
    			, String
    "  mount -t tmpfs overlay /var/lib/schroot/union/overlay"
    			, String
    "elif [ $STAGE = \"setup-stop\" ]; then"
    			, String
    "  umount -f /var/lib/schroot/union/overlay"
    			, String
    "fi"
    			]
    		Property
      (MetaTypes
         '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> Property
         (MetaTypes
            '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    -> CombinedType
         (Property
            (MetaTypes
               '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                  'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
         (Property
            (MetaTypes
               '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
                  'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD]))
    forall x y. Combines x y => x -> y -> CombinedType x y
    `onChange` (String
    f String
    -> FileMode
    -> Property
         (MetaTypes
            '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    `File.mode` [FileMode] -> FileMode
    combineModes ([FileMode]
    readModes [FileMode] -> [FileMode] -> [FileMode]
    forall a. [a] -> [a] -> [a]
    ++ [FileMode]
    executeModes))
    	undo :: Property
      (MetaTypes
         '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
            'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    undo = String
    -> Property
         (MetaTypes
            '[ 'Targeting 'OSDebian, 'Targeting 'OSBuntish,
               'Targeting 'OSArchLinux, 'Targeting 'OSFreeBSD])
    File.notPresent String
    f

    installed :: Property DebianLike
    installed :: Property DebianLike
    installed = [String] -> Property DebianLike
    Apt.installed [String
    "schroot"]