    {-# LANGUAGE GeneralizedNewtypeDeriving, ScopedTypeVariables, DeriveDataTypeable #-}
    {-# LANGUAGE TypeFamilies, ConstraintKinds #-}

    -- | Both System.Directory and System.Environment wrappers
    module Development.Shake.Internal.Rules.Directory(
        doesFileExist, doesDirectoryExist,
        getDirectoryContents, getDirectoryFiles, getDirectoryDirs,
        getEnv, getEnvWithDefault, getEnvError,
        removeFiles, removeFilesAfter,
        getDirectoryFilesIO,
        defaultRuleDirectory
        ) where

    import Control.Exception.Extra
    import Control.Monad.Extra
    import Control.Monad.IO.Class
    import Data.Maybe
    import Data.Binary
    import Data.List
    import Data.Tuple.Extra
    import qualified Data.HashSet as Set
    import qualified System.Directory as IO
    import qualified System.Environment as IO

    import Development.Shake.Internal.Core.Types
    import Development.Shake.Internal.Core.Action
    import Development.Shake.Internal.Core.Rules
    import Development.Shake.Internal.Core.Build
    import Development.Shake.Internal.Value
    import Development.Shake.Classes
    import Development.Shake.FilePath
    import Development.Shake.Internal.FilePattern
    import General.Extra
    import General.Binary

    ---------------------------------------------------------------------
    -- KEY/VALUE TYPES

    type instance RuleResult DoesFileExistQ = DoesFileExistA

    newtype DoesFileExistQ = DoesFileExistQ FilePath
        deriving (Typeable,DoesFileExistQ -> DoesFileExistQ -> Bool
    (DoesFileExistQ -> DoesFileExistQ -> Bool)
    -> (DoesFileExistQ -> DoesFileExistQ -> Bool) -> Eq DoesFileExistQ
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: DoesFileExistQ -> DoesFileExistQ -> Bool
    $c/= :: DoesFileExistQ -> DoesFileExistQ -> Bool
    == :: DoesFileExistQ -> DoesFileExistQ -> Bool
    $c== :: DoesFileExistQ -> DoesFileExistQ -> Bool
    Eq,Int -> DoesFileExistQ -> Int
    DoesFileExistQ -> Int
    (Int -> DoesFileExistQ -> Int)
    -> (DoesFileExistQ -> Int) -> Hashable DoesFileExistQ
    forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
    hash :: DoesFileExistQ -> Int
    $chash :: DoesFileExistQ -> Int
    hashWithSalt :: Int -> DoesFileExistQ -> Int
    $chashWithSalt :: Int -> DoesFileExistQ -> Int
    Hashable,Get DoesFileExistQ
    [DoesFileExistQ] -> Put
    DoesFileExistQ -> Put
    (DoesFileExistQ -> Put)
    -> Get DoesFileExistQ
    -> ([DoesFileExistQ] -> Put)
    -> Binary DoesFileExistQ
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    putList :: [DoesFileExistQ] -> Put
    $cputList :: [DoesFileExistQ] -> Put
    get :: Get DoesFileExistQ
    $cget :: Get DoesFileExistQ
    put :: DoesFileExistQ -> Put
    $cput :: DoesFileExistQ -> Put
    Binary,ByteString -> DoesFileExistQ
    DoesFileExistQ -> Builder
    (DoesFileExistQ -> Builder)
    -> (ByteString -> DoesFileExistQ) -> BinaryEx DoesFileExistQ
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> DoesFileExistQ
    $cgetEx :: ByteString -> DoesFileExistQ
    putEx :: DoesFileExistQ -> Builder
    $cputEx :: DoesFileExistQ -> Builder
    BinaryEx,DoesFileExistQ -> ()
    (DoesFileExistQ -> ()) -> NFData DoesFileExistQ
    forall a. (a -> ()) -> NFData a
    rnf :: DoesFileExistQ -> ()
    $crnf :: DoesFileExistQ -> ()
    NFData)

    instance Show DoesFileExistQ where
        show :: DoesFileExistQ -> String
    show (DoesFileExistQ a :: String
    a) = "doesFileExist " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    wrapQuote String
    a

    newtype DoesFileExistA = DoesFileExistA {DoesFileExistA -> Bool
    fromDoesFileExistA :: Bool}
        deriving (Typeable,DoesFileExistA -> DoesFileExistA -> Bool
    (DoesFileExistA -> DoesFileExistA -> Bool)
    -> (DoesFileExistA -> DoesFileExistA -> Bool) -> Eq DoesFileExistA
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: DoesFileExistA -> DoesFileExistA -> Bool
    $c/= :: DoesFileExistA -> DoesFileExistA -> Bool
    == :: DoesFileExistA -> DoesFileExistA -> Bool
    $c== :: DoesFileExistA -> DoesFileExistA -> Bool
    Eq,ByteString -> DoesFileExistA
    DoesFileExistA -> Builder
    (DoesFileExistA -> Builder)
    -> (ByteString -> DoesFileExistA) -> BinaryEx DoesFileExistA
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> DoesFileExistA
    $cgetEx :: ByteString -> DoesFileExistA
    putEx :: DoesFileExistA -> Builder
    $cputEx :: DoesFileExistA -> Builder
    BinaryEx,DoesFileExistA -> ()
    (DoesFileExistA -> ()) -> NFData DoesFileExistA
    forall a. (a -> ()) -> NFData a
    rnf :: DoesFileExistA -> ()
    $crnf :: DoesFileExistA -> ()
    NFData)

    instance Show DoesFileExistA where
        show :: DoesFileExistA -> String
    show (DoesFileExistA a :: Bool
    a) = Bool -> String
    forall a. Show a => a -> String
    show Bool
    a

    type instance RuleResult DoesDirectoryExistQ = DoesDirectoryExistA

    newtype DoesDirectoryExistQ = DoesDirectoryExistQ FilePath
        deriving (Typeable,DoesDirectoryExistQ -> DoesDirectoryExistQ -> Bool
    (DoesDirectoryExistQ -> DoesDirectoryExistQ -> Bool)
    -> (DoesDirectoryExistQ -> DoesDirectoryExistQ -> Bool)
    -> Eq DoesDirectoryExistQ
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: DoesDirectoryExistQ -> DoesDirectoryExistQ -> Bool
    $c/= :: DoesDirectoryExistQ -> DoesDirectoryExistQ -> Bool
    == :: DoesDirectoryExistQ -> DoesDirectoryExistQ -> Bool
    $c== :: DoesDirectoryExistQ -> DoesDirectoryExistQ -> Bool
    Eq,Int -> DoesDirectoryExistQ -> Int
    DoesDirectoryExistQ -> Int
    (Int -> DoesDirectoryExistQ -> Int)
    -> (DoesDirectoryExistQ -> Int) -> Hashable DoesDirectoryExistQ
    forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
    hash :: DoesDirectoryExistQ -> Int
    $chash :: DoesDirectoryExistQ -> Int
    hashWithSalt :: Int -> DoesDirectoryExistQ -> Int
    $chashWithSalt :: Int -> DoesDirectoryExistQ -> Int
    Hashable,Get DoesDirectoryExistQ
    [DoesDirectoryExistQ] -> Put
    DoesDirectoryExistQ -> Put
    (DoesDirectoryExistQ -> Put)
    -> Get DoesDirectoryExistQ
    -> ([DoesDirectoryExistQ] -> Put)
    -> Binary DoesDirectoryExistQ
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    putList :: [DoesDirectoryExistQ] -> Put
    $cputList :: [DoesDirectoryExistQ] -> Put
    get :: Get DoesDirectoryExistQ
    $cget :: Get DoesDirectoryExistQ
    put :: DoesDirectoryExistQ -> Put
    $cput :: DoesDirectoryExistQ -> Put
    Binary,ByteString -> DoesDirectoryExistQ
    DoesDirectoryExistQ -> Builder
    (DoesDirectoryExistQ -> Builder)
    -> (ByteString -> DoesDirectoryExistQ)
    -> BinaryEx DoesDirectoryExistQ
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> DoesDirectoryExistQ
    $cgetEx :: ByteString -> DoesDirectoryExistQ
    putEx :: DoesDirectoryExistQ -> Builder
    $cputEx :: DoesDirectoryExistQ -> Builder
    BinaryEx,DoesDirectoryExistQ -> ()
    (DoesDirectoryExistQ -> ()) -> NFData DoesDirectoryExistQ
    forall a. (a -> ()) -> NFData a
    rnf :: DoesDirectoryExistQ -> ()
    $crnf :: DoesDirectoryExistQ -> ()
    NFData)

    instance Show DoesDirectoryExistQ where
        show :: DoesDirectoryExistQ -> String
    show (DoesDirectoryExistQ a :: String
    a) = "doesDirectoryExist " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    wrapQuote String
    a

    newtype DoesDirectoryExistA = DoesDirectoryExistA {DoesDirectoryExistA -> Bool
    fromDoesDirectoryExistA :: Bool}
        deriving (Typeable,DoesDirectoryExistA -> DoesDirectoryExistA -> Bool
    (DoesDirectoryExistA -> DoesDirectoryExistA -> Bool)
    -> (DoesDirectoryExistA -> DoesDirectoryExistA -> Bool)
    -> Eq DoesDirectoryExistA
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: DoesDirectoryExistA -> DoesDirectoryExistA -> Bool
    $c/= :: DoesDirectoryExistA -> DoesDirectoryExistA -> Bool
    == :: DoesDirectoryExistA -> DoesDirectoryExistA -> Bool
    $c== :: DoesDirectoryExistA -> DoesDirectoryExistA -> Bool
    Eq,ByteString -> DoesDirectoryExistA
    DoesDirectoryExistA -> Builder
    (DoesDirectoryExistA -> Builder)
    -> (ByteString -> DoesDirectoryExistA)
    -> BinaryEx DoesDirectoryExistA
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> DoesDirectoryExistA
    $cgetEx :: ByteString -> DoesDirectoryExistA
    putEx :: DoesDirectoryExistA -> Builder
    $cputEx :: DoesDirectoryExistA -> Builder
    BinaryEx,DoesDirectoryExistA -> ()
    (DoesDirectoryExistA -> ()) -> NFData DoesDirectoryExistA
    forall a. (a -> ()) -> NFData a
    rnf :: DoesDirectoryExistA -> ()
    $crnf :: DoesDirectoryExistA -> ()
    NFData)

    instance Show DoesDirectoryExistA where
        show :: DoesDirectoryExistA -> String
    show (DoesDirectoryExistA a :: Bool
    a) = Bool -> String
    forall a. Show a => a -> String
    show Bool
    a

    type instance RuleResult GetEnvQ = GetEnvA

    newtype GetEnvQ = GetEnvQ String
        deriving (Typeable,GetEnvQ -> GetEnvQ -> Bool
    (GetEnvQ -> GetEnvQ -> Bool)
    -> (GetEnvQ -> GetEnvQ -> Bool) -> Eq GetEnvQ
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: GetEnvQ -> GetEnvQ -> Bool
    $c/= :: GetEnvQ -> GetEnvQ -> Bool
    == :: GetEnvQ -> GetEnvQ -> Bool
    $c== :: GetEnvQ -> GetEnvQ -> Bool
    Eq,Int -> GetEnvQ -> Int
    GetEnvQ -> Int
    (Int -> GetEnvQ -> Int) -> (GetEnvQ -> Int) -> Hashable GetEnvQ
    forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
    hash :: GetEnvQ -> Int
    $chash :: GetEnvQ -> Int
    hashWithSalt :: Int -> GetEnvQ -> Int
    $chashWithSalt :: Int -> GetEnvQ -> Int
    Hashable,Get GetEnvQ
    [GetEnvQ] -> Put
    GetEnvQ -> Put
    (GetEnvQ -> Put)
    -> Get GetEnvQ -> ([GetEnvQ] -> Put) -> Binary GetEnvQ
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    putList :: [GetEnvQ] -> Put
    $cputList :: [GetEnvQ] -> Put
    get :: Get GetEnvQ
    $cget :: Get GetEnvQ
    put :: GetEnvQ -> Put
    $cput :: GetEnvQ -> Put
    Binary,ByteString -> GetEnvQ
    GetEnvQ -> Builder
    (GetEnvQ -> Builder) -> (ByteString -> GetEnvQ) -> BinaryEx GetEnvQ
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> GetEnvQ
    $cgetEx :: ByteString -> GetEnvQ
    putEx :: GetEnvQ -> Builder
    $cputEx :: GetEnvQ -> Builder
    BinaryEx,GetEnvQ -> ()
    (GetEnvQ -> ()) -> NFData GetEnvQ
    forall a. (a -> ()) -> NFData a
    rnf :: GetEnvQ -> ()
    $crnf :: GetEnvQ -> ()
    NFData)

    instance Show GetEnvQ where
        show :: GetEnvQ -> String
    show (GetEnvQ a :: String
    a) = "getEnv " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    wrapQuote String
    a

    newtype GetEnvA = GetEnvA {GetEnvA -> Maybe String
    fromGetEnvA :: Maybe String}
        deriving (Typeable,GetEnvA -> GetEnvA -> Bool
    (GetEnvA -> GetEnvA -> Bool)
    -> (GetEnvA -> GetEnvA -> Bool) -> Eq GetEnvA
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: GetEnvA -> GetEnvA -> Bool
    $c/= :: GetEnvA -> GetEnvA -> Bool
    == :: GetEnvA -> GetEnvA -> Bool
    $c== :: GetEnvA -> GetEnvA -> Bool
    Eq,Int -> GetEnvA -> Int
    GetEnvA -> Int
    (Int -> GetEnvA -> Int) -> (GetEnvA -> Int) -> Hashable GetEnvA
    forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
    hash :: GetEnvA -> Int
    $chash :: GetEnvA -> Int
    hashWithSalt :: Int -> GetEnvA -> Int
    $chashWithSalt :: Int -> GetEnvA -> Int
    Hashable,ByteString -> GetEnvA
    GetEnvA -> Builder
    (GetEnvA -> Builder) -> (ByteString -> GetEnvA) -> BinaryEx GetEnvA
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> GetEnvA
    $cgetEx :: ByteString -> GetEnvA
    putEx :: GetEnvA -> Builder
    $cputEx :: GetEnvA -> Builder
    BinaryEx,GetEnvA -> ()
    (GetEnvA -> ()) -> NFData GetEnvA
    forall a. (a -> ()) -> NFData a
    rnf :: GetEnvA -> ()
    $crnf :: GetEnvA -> ()
    NFData)

    instance Show GetEnvA where
        show :: GetEnvA -> String
    show (GetEnvA a :: Maybe String
    a) = String -> ShowS -> Maybe String -> String
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe "<unset>" ShowS
    wrapQuote Maybe String
    a

    type instance RuleResult GetDirectoryContentsQ = GetDirectoryA
    type instance RuleResult GetDirectoryFilesQ = GetDirectoryA
    type instance RuleResult GetDirectoryDirsQ = GetDirectoryA

    newtype GetDirectoryContentsQ = GetDirectoryContentsQ FilePath
        deriving (Typeable,GetDirectoryContentsQ -> GetDirectoryContentsQ -> Bool
    (GetDirectoryContentsQ -> GetDirectoryContentsQ -> Bool)
    -> (GetDirectoryContentsQ -> GetDirectoryContentsQ -> Bool)
    -> Eq GetDirectoryContentsQ
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: GetDirectoryContentsQ -> GetDirectoryContentsQ -> Bool
    $c/= :: GetDirectoryContentsQ -> GetDirectoryContentsQ -> Bool
    == :: GetDirectoryContentsQ -> GetDirectoryContentsQ -> Bool
    $c== :: GetDirectoryContentsQ -> GetDirectoryContentsQ -> Bool
    Eq,Int -> GetDirectoryContentsQ -> Int
    GetDirectoryContentsQ -> Int
    (Int -> GetDirectoryContentsQ -> Int)
    -> (GetDirectoryContentsQ -> Int) -> Hashable GetDirectoryContentsQ
    forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
    hash :: GetDirectoryContentsQ -> Int
    $chash :: GetDirectoryContentsQ -> Int
    hashWithSalt :: Int -> GetDirectoryContentsQ -> Int
    $chashWithSalt :: Int -> GetDirectoryContentsQ -> Int
    Hashable,Get GetDirectoryContentsQ
    [GetDirectoryContentsQ] -> Put
    GetDirectoryContentsQ -> Put
    (GetDirectoryContentsQ -> Put)
    -> Get GetDirectoryContentsQ
    -> ([GetDirectoryContentsQ] -> Put)
    -> Binary GetDirectoryContentsQ
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    putList :: [GetDirectoryContentsQ] -> Put
    $cputList :: [GetDirectoryContentsQ] -> Put
    get :: Get GetDirectoryContentsQ
    $cget :: Get GetDirectoryContentsQ
    put :: GetDirectoryContentsQ -> Put
    $cput :: GetDirectoryContentsQ -> Put
    Binary,ByteString -> GetDirectoryContentsQ
    GetDirectoryContentsQ -> Builder
    (GetDirectoryContentsQ -> Builder)
    -> (ByteString -> GetDirectoryContentsQ)
    -> BinaryEx GetDirectoryContentsQ
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> GetDirectoryContentsQ
    $cgetEx :: ByteString -> GetDirectoryContentsQ
    putEx :: GetDirectoryContentsQ -> Builder
    $cputEx :: GetDirectoryContentsQ -> Builder
    BinaryEx,GetDirectoryContentsQ -> ()
    (GetDirectoryContentsQ -> ()) -> NFData GetDirectoryContentsQ
    forall a. (a -> ()) -> NFData a
    rnf :: GetDirectoryContentsQ -> ()
    $crnf :: GetDirectoryContentsQ -> ()
    NFData)

    instance Show GetDirectoryContentsQ where
        show :: GetDirectoryContentsQ -> String
    show (GetDirectoryContentsQ dir :: String
    dir) = "getDirectoryContents " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    wrapQuote String
    dir

    newtype GetDirectoryFilesQ = GetDirectoryFilesQ (FilePath, [FilePattern])
        deriving (Typeable,GetDirectoryFilesQ -> GetDirectoryFilesQ -> Bool
    (GetDirectoryFilesQ -> GetDirectoryFilesQ -> Bool)
    -> (GetDirectoryFilesQ -> GetDirectoryFilesQ -> Bool)
    -> Eq GetDirectoryFilesQ
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: GetDirectoryFilesQ -> GetDirectoryFilesQ -> Bool
    $c/= :: GetDirectoryFilesQ -> GetDirectoryFilesQ -> Bool
    == :: GetDirectoryFilesQ -> GetDirectoryFilesQ -> Bool
    $c== :: GetDirectoryFilesQ -> GetDirectoryFilesQ -> Bool
    Eq,Int -> GetDirectoryFilesQ -> Int
    GetDirectoryFilesQ -> Int
    (Int -> GetDirectoryFilesQ -> Int)
    -> (GetDirectoryFilesQ -> Int) -> Hashable GetDirectoryFilesQ
    forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
    hash :: GetDirectoryFilesQ -> Int
    $chash :: GetDirectoryFilesQ -> Int
    hashWithSalt :: Int -> GetDirectoryFilesQ -> Int
    $chashWithSalt :: Int -> GetDirectoryFilesQ -> Int
    Hashable,Get GetDirectoryFilesQ
    [GetDirectoryFilesQ] -> Put
    GetDirectoryFilesQ -> Put
    (GetDirectoryFilesQ -> Put)
    -> Get GetDirectoryFilesQ
    -> ([GetDirectoryFilesQ] -> Put)
    -> Binary GetDirectoryFilesQ
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    putList :: [GetDirectoryFilesQ] -> Put
    $cputList :: [GetDirectoryFilesQ] -> Put
    get :: Get GetDirectoryFilesQ
    $cget :: Get GetDirectoryFilesQ
    put :: GetDirectoryFilesQ -> Put
    $cput :: GetDirectoryFilesQ -> Put
    Binary,ByteString -> GetDirectoryFilesQ
    GetDirectoryFilesQ -> Builder
    (GetDirectoryFilesQ -> Builder)
    -> (ByteString -> GetDirectoryFilesQ)
    -> BinaryEx GetDirectoryFilesQ
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> GetDirectoryFilesQ
    $cgetEx :: ByteString -> GetDirectoryFilesQ
    putEx :: GetDirectoryFilesQ -> Builder
    $cputEx :: GetDirectoryFilesQ -> Builder
    BinaryEx,GetDirectoryFilesQ -> ()
    (GetDirectoryFilesQ -> ()) -> NFData GetDirectoryFilesQ
    forall a. (a -> ()) -> NFData a
    rnf :: GetDirectoryFilesQ -> ()
    $crnf :: GetDirectoryFilesQ -> ()
    NFData)

    instance Show GetDirectoryFilesQ where
        show :: GetDirectoryFilesQ -> String
    show (GetDirectoryFilesQ (dir :: String
    dir, pat :: [String]
    pat)) = "getDirectoryFiles " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    wrapQuote String
    dir String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ " [" String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ [String] -> String
    unwords (ShowS -> [String] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map ShowS
    wrapQuote [String]
    pat) String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ "]"

    newtype GetDirectoryDirsQ = GetDirectoryDirsQ FilePath
        deriving (Typeable,GetDirectoryDirsQ -> GetDirectoryDirsQ -> Bool
    (GetDirectoryDirsQ -> GetDirectoryDirsQ -> Bool)
    -> (GetDirectoryDirsQ -> GetDirectoryDirsQ -> Bool)
    -> Eq GetDirectoryDirsQ
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: GetDirectoryDirsQ -> GetDirectoryDirsQ -> Bool
    $c/= :: GetDirectoryDirsQ -> GetDirectoryDirsQ -> Bool
    == :: GetDirectoryDirsQ -> GetDirectoryDirsQ -> Bool
    $c== :: GetDirectoryDirsQ -> GetDirectoryDirsQ -> Bool
    Eq,Int -> GetDirectoryDirsQ -> Int
    GetDirectoryDirsQ -> Int
    (Int -> GetDirectoryDirsQ -> Int)
    -> (GetDirectoryDirsQ -> Int) -> Hashable GetDirectoryDirsQ
    forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
    hash :: GetDirectoryDirsQ -> Int
    $chash :: GetDirectoryDirsQ -> Int
    hashWithSalt :: Int -> GetDirectoryDirsQ -> Int
    $chashWithSalt :: Int -> GetDirectoryDirsQ -> Int
    Hashable,Get GetDirectoryDirsQ
    [GetDirectoryDirsQ] -> Put
    GetDirectoryDirsQ -> Put
    (GetDirectoryDirsQ -> Put)
    -> Get GetDirectoryDirsQ
    -> ([GetDirectoryDirsQ] -> Put)
    -> Binary GetDirectoryDirsQ
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    putList :: [GetDirectoryDirsQ] -> Put
    $cputList :: [GetDirectoryDirsQ] -> Put
    get :: Get GetDirectoryDirsQ
    $cget :: Get GetDirectoryDirsQ
    put :: GetDirectoryDirsQ -> Put
    $cput :: GetDirectoryDirsQ -> Put
    Binary,ByteString -> GetDirectoryDirsQ
    GetDirectoryDirsQ -> Builder
    (GetDirectoryDirsQ -> Builder)
    -> (ByteString -> GetDirectoryDirsQ) -> BinaryEx GetDirectoryDirsQ
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> GetDirectoryDirsQ
    $cgetEx :: ByteString -> GetDirectoryDirsQ
    putEx :: GetDirectoryDirsQ -> Builder
    $cputEx :: GetDirectoryDirsQ -> Builder
    BinaryEx,GetDirectoryDirsQ -> ()
    (GetDirectoryDirsQ -> ()) -> NFData GetDirectoryDirsQ
    forall a. (a -> ()) -> NFData a
    rnf :: GetDirectoryDirsQ -> ()
    $crnf :: GetDirectoryDirsQ -> ()
    NFData)

    instance Show GetDirectoryDirsQ where
        show :: GetDirectoryDirsQ -> String
    show (GetDirectoryDirsQ dir :: String
    dir) = "getDirectoryDirs " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    wrapQuote String
    dir

    newtype GetDirectoryA = GetDirectoryA {GetDirectoryA -> [String]
    fromGetDirectoryA :: [FilePath]}
        deriving (Typeable,GetDirectoryA -> GetDirectoryA -> Bool
    (GetDirectoryA -> GetDirectoryA -> Bool)
    -> (GetDirectoryA -> GetDirectoryA -> Bool) -> Eq GetDirectoryA
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: GetDirectoryA -> GetDirectoryA -> Bool
    $c/= :: GetDirectoryA -> GetDirectoryA -> Bool
    == :: GetDirectoryA -> GetDirectoryA -> Bool
    $c== :: GetDirectoryA -> GetDirectoryA -> Bool
    Eq,Int -> GetDirectoryA -> Int
    GetDirectoryA -> Int
    (Int -> GetDirectoryA -> Int)
    -> (GetDirectoryA -> Int) -> Hashable GetDirectoryA
    forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
    hash :: GetDirectoryA -> Int
    $chash :: GetDirectoryA -> Int
    hashWithSalt :: Int -> GetDirectoryA -> Int
    $chashWithSalt :: Int -> GetDirectoryA -> Int
    Hashable,ByteString -> GetDirectoryA
    GetDirectoryA -> Builder
    (GetDirectoryA -> Builder)
    -> (ByteString -> GetDirectoryA) -> BinaryEx GetDirectoryA
    forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
    getEx :: ByteString -> GetDirectoryA
    $cgetEx :: ByteString -> GetDirectoryA
    putEx :: GetDirectoryA -> Builder
    $cputEx :: GetDirectoryA -> Builder
    BinaryEx,GetDirectoryA -> ()
    (GetDirectoryA -> ()) -> NFData GetDirectoryA
    forall a. (a -> ()) -> NFData a
    rnf :: GetDirectoryA -> ()
    $crnf :: GetDirectoryA -> ()
    NFData)

    instance Show GetDirectoryA where
        show :: GetDirectoryA -> String
    show (GetDirectoryA xs :: [String]
    xs) = [String] -> String
    unwords ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $ ShowS -> [String] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map ShowS
    wrapQuote [String]
    xs

    ---------------------------------------------------------------------
    -- RULE DEFINITIONS

    queryRule :: (RuleResult key ~ value
                 ,BinaryEx witness, Eq witness
                 ,BinaryEx key, ShakeValue key
                 ,Typeable value, NFData value, Show value, Eq value)
              => (value -> witness) -> (key -> IO value) -> Rules ()
    queryRule :: (value -> witness) -> (key -> IO value) -> Rules ()
    queryRule witness :: value -> witness
    witness query :: key -> IO value
    query = BuiltinLint key value
    -> BuiltinIdentity key value -> BuiltinRun key value -> Rules ()
    forall key value.
    (RuleResult key ~ value, ShakeValue key, BinaryEx key,
     Typeable value, NFData value, Show value, Partial) =>
    BuiltinLint key value
    -> BuiltinIdentity key value -> BuiltinRun key value -> Rules ()
    addBuiltinRuleEx
        (\k :: key
    k old :: value
    old -> do
            value
    new <- key -> IO value
    query key
    k
            Maybe String -> IO (Maybe String)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Maybe String -> IO (Maybe String))
    -> Maybe String -> IO (Maybe String)
    forall a b. (a -> b) -> a -> b
    $ if value
    old value -> value -> Bool
    forall a. Eq a => a -> a -> Bool
    == value
    new then Maybe String
    forall a. Maybe a
    Nothing else String -> Maybe String
    forall a. a -> Maybe a
    Just (String -> Maybe String) -> String -> Maybe String
    forall a b. (a -> b) -> a -> b
    $ value -> String
    forall a. Show a => a -> String
    show value
    new)
        (\_ v :: value
    v -> ByteString -> Maybe ByteString
    forall a. a -> Maybe a
    Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
    forall a b. (a -> b) -> a -> b
    $ Builder -> ByteString
    runBuilder (Builder -> ByteString) -> Builder -> ByteString
    forall a b. (a -> b) -> a -> b
    $ witness -> Builder
    forall a. BinaryEx a => a -> Builder
    putEx (witness -> Builder) -> witness -> Builder
    forall a b. (a -> b) -> a -> b
    $ value -> witness
    witness value
    v)
        (\k :: key
    k old :: Maybe ByteString
    old _ -> IO (RunResult value) -> Action (RunResult value)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (RunResult value) -> Action (RunResult value))
    -> IO (RunResult value) -> Action (RunResult value)
    forall a b. (a -> b) -> a -> b
    $ do
            value
    new <- key -> IO value
    query key
    k
            let wnew :: witness
    wnew = value -> witness
    witness value
    new
            RunResult value -> IO (RunResult value)
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (RunResult value -> IO (RunResult value))
    -> RunResult value -> IO (RunResult value)
    forall a b. (a -> b) -> a -> b
    $ case Maybe ByteString
    old of
                Just old :: ByteString
    old | witness
    wnew witness -> witness -> Bool
    forall a. Eq a => a -> a -> Bool
    == ByteString -> witness
    forall a. BinaryEx a => ByteString -> a
    getEx ByteString
    old -> RunChanged -> ByteString -> value -> RunResult value
    forall value. RunChanged -> ByteString -> value -> RunResult value
    RunResult RunChanged
    ChangedNothing ByteString
    old value
    new
                _ -> RunChanged -> ByteString -> value -> RunResult value
    forall value. RunChanged -> ByteString -> value -> RunResult value
    RunResult RunChanged
    ChangedRecomputeDiff (Builder -> ByteString
    runBuilder (Builder -> ByteString) -> Builder -> ByteString
    forall a b. (a -> b) -> a -> b
    $ witness -> Builder
    forall a. BinaryEx a => a -> Builder
    putEx witness
    wnew) value
    new)

    defaultRuleDirectory :: Rules ()
    defaultRuleDirectory :: Rules ()
    defaultRuleDirectory = do
        -- for things we are always going to rerun, and which might take up a lot of memory to store,
        -- we only store their hash, so we can compute change, but not know what changed happened
        (DoesFileExistA -> DoesFileExistA)
    -> (DoesFileExistQ -> IO DoesFileExistA) -> Rules ()
    forall key value witness.
    (RuleResult key ~ value, BinaryEx witness, Eq witness,
     BinaryEx key, ShakeValue key, Typeable value, NFData value,
     Show value, Eq value) =>
    (value -> witness) -> (key -> IO value) -> Rules ()
    queryRule DoesFileExistA -> DoesFileExistA
    forall a. a -> a
    id (\(DoesFileExistQ x :: String
    x) -> Bool -> DoesFileExistA
    DoesFileExistA (Bool -> DoesFileExistA) -> IO Bool -> IO DoesFileExistA
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> IO Bool
    IO.doesFileExist String
    x)
        (DoesDirectoryExistA -> DoesDirectoryExistA)
    -> (DoesDirectoryExistQ -> IO DoesDirectoryExistA) -> Rules ()
    forall key value witness.
    (RuleResult key ~ value, BinaryEx witness, Eq witness,
     BinaryEx key, ShakeValue key, Typeable value, NFData value,
     Show value, Eq value) =>
    (value -> witness) -> (key -> IO value) -> Rules ()
    queryRule DoesDirectoryExistA -> DoesDirectoryExistA
    forall a. a -> a
    id (\(DoesDirectoryExistQ x :: String
    x) -> Bool -> DoesDirectoryExistA
    DoesDirectoryExistA (Bool -> DoesDirectoryExistA) -> IO Bool -> IO DoesDirectoryExistA
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> IO Bool
    IO.doesDirectoryExist String
    x)
        (GetEnvA -> Int) -> (GetEnvQ -> IO GetEnvA) -> Rules ()
    forall key value witness.
    (RuleResult key ~ value, BinaryEx witness, Eq witness,
     BinaryEx key, ShakeValue key, Typeable value, NFData value,
     Show value, Eq value) =>
    (value -> witness) -> (key -> IO value) -> Rules ()
    queryRule GetEnvA -> Int
    forall a. Hashable a => a -> Int
    hash (\(GetEnvQ x :: String
    x) -> Maybe String -> GetEnvA
    GetEnvA (Maybe String -> GetEnvA) -> IO (Maybe String) -> IO GetEnvA
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> IO (Maybe String)
    IO.lookupEnv String
    x)
        (GetDirectoryA -> Int)
    -> (GetDirectoryContentsQ -> IO GetDirectoryA) -> Rules ()
    forall key value witness.
    (RuleResult key ~ value, BinaryEx witness, Eq witness,
     BinaryEx key, ShakeValue key, Typeable value, NFData value,
     Show value, Eq value) =>
    (value -> witness) -> (key -> IO value) -> Rules ()
    queryRule GetDirectoryA -> Int
    forall a. Hashable a => a -> Int
    hash (\(GetDirectoryContentsQ x :: String
    x) -> [String] -> GetDirectoryA
    GetDirectoryA ([String] -> GetDirectoryA) -> IO [String] -> IO GetDirectoryA
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> IO [String]
    getDirectoryContentsIO String
    x)
        (GetDirectoryA -> Int)
    -> (GetDirectoryFilesQ -> IO GetDirectoryA) -> Rules ()
    forall key value witness.
    (RuleResult key ~ value, BinaryEx witness, Eq witness,
     BinaryEx key, ShakeValue key, Typeable value, NFData value,
     Show value, Eq value) =>
    (value -> witness) -> (key -> IO value) -> Rules ()
    queryRule GetDirectoryA -> Int
    forall a. Hashable a => a -> Int
    hash (\(GetDirectoryFilesQ (a :: String
    a,b :: [String]
    b)) -> [String] -> GetDirectoryA
    GetDirectoryA ([String] -> GetDirectoryA) -> IO [String] -> IO GetDirectoryA
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> [String] -> IO [String]
    getDirectoryFilesIO String
    a [String]
    b)
        (GetDirectoryA -> Int)
    -> (GetDirectoryDirsQ -> IO GetDirectoryA) -> Rules ()
    forall key value witness.
    (RuleResult key ~ value, BinaryEx witness, Eq witness,
     BinaryEx key, ShakeValue key, Typeable value, NFData value,
     Show value, Eq value) =>
    (value -> witness) -> (key -> IO value) -> Rules ()
    queryRule GetDirectoryA -> Int
    forall a. Hashable a => a -> Int
    hash (\(GetDirectoryDirsQ x :: String
    x) -> [String] -> GetDirectoryA
    GetDirectoryA ([String] -> GetDirectoryA) -> IO [String] -> IO GetDirectoryA
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> IO [String]
    getDirectoryDirsIO String
    x)

    ---------------------------------------------------------------------
    -- RULE ENTRY POINTS

    -- | Returns 'True' if the file exists. The existence of the file is tracked as a
    --   dependency, and if the file is created or deleted the rule will rerun in subsequent builds.
    --
    --   You should not call 'doesFileExist' on files which can be created by the build system.
    doesFileExist :: FilePath -> Action Bool
    doesFileExist :: String -> Action Bool
    doesFileExist = (DoesFileExistA -> Bool) -> Action DoesFileExistA -> Action Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DoesFileExistA -> Bool
    fromDoesFileExistA (Action DoesFileExistA -> Action Bool)
    -> (String -> Action DoesFileExistA) -> String -> Action Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DoesFileExistQ -> Action DoesFileExistA
    forall key value.
    (Partial, RuleResult key ~ value, ShakeValue key,
     Typeable value) =>
    key -> Action value
    apply1 (DoesFileExistQ -> Action DoesFileExistA)
    -> (String -> DoesFileExistQ) -> String -> Action DoesFileExistA
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> DoesFileExistQ
    DoesFileExistQ (String -> DoesFileExistQ) -> ShowS -> String -> DoesFileExistQ
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ShowS
    toStandard

    -- | Returns 'True' if the directory exists. The existence of the directory is tracked as a
    --   dependency, and if the directory is created or delete the rule will rerun in subsequent builds.
    --
    --   You should not call 'doesDirectoryExist' on directories which can be created by the build system.
    doesDirectoryExist :: FilePath -> Action Bool
    doesDirectoryExist :: String -> Action Bool
    doesDirectoryExist = (DoesDirectoryExistA -> Bool)
    -> Action DoesDirectoryExistA -> Action Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DoesDirectoryExistA -> Bool
    fromDoesDirectoryExistA (Action DoesDirectoryExistA -> Action Bool)
    -> (String -> Action DoesDirectoryExistA) -> String -> Action Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DoesDirectoryExistQ -> Action DoesDirectoryExistA
    forall key value.
    (Partial, RuleResult key ~ value, ShakeValue key,
     Typeable value) =>
    key -> Action value
    apply1 (DoesDirectoryExistQ -> Action DoesDirectoryExistA)
    -> (String -> DoesDirectoryExistQ)
    -> String
    -> Action DoesDirectoryExistA
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> DoesDirectoryExistQ
    DoesDirectoryExistQ (String -> DoesDirectoryExistQ)
    -> ShowS -> String -> DoesDirectoryExistQ
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ShowS
    toStandard

    -- | Return 'Just' the value of the environment variable, or 'Nothing'
    --   if the variable is not set. The environment variable is tracked as a
    --   dependency, and if it changes the rule will rerun in subsequent builds.
    --   This function is a tracked version of 'getEnv' / 'lookupEnv' from the base library.
    --
    -- @
    -- flags <- getEnv \"CFLAGS\"
    -- 'cmd' \"gcc -c\" [out] (maybe [] words flags)
    -- @
    getEnv :: String -> Action (Maybe String)
    getEnv :: String -> Action (Maybe String)
    getEnv = (GetEnvA -> Maybe String)
    -> Action GetEnvA -> Action (Maybe String)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap GetEnvA -> Maybe String
    fromGetEnvA (Action GetEnvA -> Action (Maybe String))
    -> (String -> Action GetEnvA) -> String -> Action (Maybe String)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GetEnvQ -> Action GetEnvA
    forall key value.
    (Partial, RuleResult key ~ value, ShakeValue key,
     Typeable value) =>
    key -> Action value
    apply1 (GetEnvQ -> Action GetEnvA)
    -> (String -> GetEnvQ) -> String -> Action GetEnvA
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> GetEnvQ
    GetEnvQ

    -- | @'getEnvWithDefault' def var@ returns the value of the environment variable @var@, or the
    --   default value @def@ if it is not set. Similar to 'getEnv'.
    --
    -- @
    -- flags <- getEnvWithDefault \"-Wall\" \"CFLAGS\"
    -- 'cmd' \"gcc -c\" [out] flags
    -- @
    getEnvWithDefault :: String -> String -> Action String
    getEnvWithDefault :: String -> String -> Action String
    getEnvWithDefault def :: String
    def var :: String
    var = String -> Maybe String -> String
    forall a. a -> Maybe a -> a
    fromMaybe String
    def (Maybe String -> String) -> Action (Maybe String) -> Action String
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> String -> Action (Maybe String)
    getEnv String
    var

    -- | A partial variant of 'getEnv' that returns the environment variable variable or fails.
    getEnvError :: Partial => String -> Action String
    getEnvError :: String -> Action String
    getEnvError name :: String
    name = String -> String -> Action String
    getEnvWithDefault (ShowS
    forall a. Partial => String -> a
    error ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ "getEnvError: Environment variable " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    name String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ " is undefined") String
    name

    -- | Get the contents of a directory. The result will be sorted, and will not contain
    --   the entries @.@ or @..@ (unlike the standard Haskell version).
    --   The resulting paths will be relative to the first argument.
    --   The result itself is tracked as a dependency, but the files in the result are not.
    --   If the list of files changes in subsequent builds any rule calling it will rerun.
    --
    --   It is usually simpler to call either 'getDirectoryFiles' or 'getDirectoryDirs'.
    getDirectoryContents :: FilePath -> Action [FilePath]
    getDirectoryContents :: String -> Action [String]
    getDirectoryContents = (GetDirectoryA -> [String])
    -> Action GetDirectoryA -> Action [String]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap GetDirectoryA -> [String]
    fromGetDirectoryA (Action GetDirectoryA -> Action [String])
    -> (String -> Action GetDirectoryA) -> String -> Action [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GetDirectoryContentsQ -> Action GetDirectoryA
    forall key value.
    (Partial, RuleResult key ~ value, ShakeValue key,
     Typeable value) =>
    key -> Action value
    apply1 (GetDirectoryContentsQ -> Action GetDirectoryA)
    -> (String -> GetDirectoryContentsQ)
    -> String
    -> Action GetDirectoryA
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> GetDirectoryContentsQ
    GetDirectoryContentsQ

    -- | Get the files anywhere under a directory that match any of a set of patterns.
    --   For the interpretation of the patterns see '?=='. All results will be
    --   relative to the directory argument.
    --   The result itself is tracked as a dependency, but the files in the result are not.
    --   If the list of files changes in subsequent builds any rule calling it will rerun.
    --   Some examples:
    --
    -- > getDirectoryFiles "Config" ["//*.xml"]
    -- >     -- All .xml files anywhere under the Config directory
    -- >     -- If Config/foo/bar.xml exists it will return ["foo/bar.xml"]
    -- > getDirectoryFiles "Modules" ["*.hs","*.lhs"]
    -- >     -- All .hs or .lhs in the Modules directory
    -- >     -- If Modules/foo.hs and Modules/foo.lhs exist, it will return ["foo.hs","foo.lhs"]
    --
    --   If you require a qualified file name it is often easier to use @\"\"@ as the 'FilePath' argument,
    --   for example the following two expressions are equivalent:
    --
    -- > fmap (map ("Config" </>)) (getDirectoryFiles "Config" ["//*.xml"])
    -- > getDirectoryFiles "" ["Config//*.xml"]
    --
    --   If the first argument directory does not exist it will raise an error.
    --   If @foo@ does not exist, then the first of these error, but the second will not.
    --
    -- > getDirectoryFiles "foo" ["//*"] -- error
    -- > getDirectoryFiles "" ["foo//*"] -- returns []
    --
    --   This function is tracked and serves as a dependency. If a rule calls
    --   @getDirectoryFiles \"\" [\"*.c\"]@ and someone adds @foo.c@ to the
    --   directory, that rule will rebuild. If someone changes one of the @.c@ files,
    --   but the /list/ of @.c@ files doesn't change, then it will not rebuild.
    --   As a consequence of being tracked, if the contents change during the build
    --   (e.g. you are generating @.c@ files in this directory) then the build not reach
    --   a stable point, which is an error - detected by running with @--lint@.
    --   You should normally only call this function returning source files.
    --
    --   For an untracked variant see 'getDirectoryFilesIO'.
    getDirectoryFiles :: FilePath -> [FilePattern] -> Action [FilePath]
    getDirectoryFiles :: String -> [String] -> Action [String]
    getDirectoryFiles dir :: String
    dir pat :: [String]
    pat = (GetDirectoryA -> [String])
    -> Action GetDirectoryA -> Action [String]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap GetDirectoryA -> [String]
    fromGetDirectoryA (Action GetDirectoryA -> Action [String])
    -> Action GetDirectoryA -> Action [String]
    forall a b. (a -> b) -> a -> b
    $ GetDirectoryFilesQ -> Action GetDirectoryA
    forall key value.
    (Partial, RuleResult key ~ value, ShakeValue key,
     Typeable value) =>
    key -> Action value
    apply1 (GetDirectoryFilesQ -> Action GetDirectoryA)
    -> GetDirectoryFilesQ -> Action GetDirectoryA
    forall a b. (a -> b) -> a -> b
    $ (String, [String]) -> GetDirectoryFilesQ
    GetDirectoryFilesQ (String
    dir,[String]
    pat)

    -- | Get the directories in a directory, not including @.@ or @..@.
    --   All directories are relative to the argument directory.
    --   The result itself is tracked as a dependency, but the directories in the result are not.
    --   If the list of directories changes in subsequent builds any rule calling it will rerun.

    --   The rules about creating entries described in 'getDirectoryFiles' also apply here.
    --
    -- > getDirectoryDirs "/Users"
    -- >    -- Return all directories in the /Users directory
    -- >    -- e.g. ["Emily","Henry","Neil"]
    getDirectoryDirs :: FilePath -> Action [FilePath]
    getDirectoryDirs :: String -> Action [String]
    getDirectoryDirs = (GetDirectoryA -> [String])
    -> Action GetDirectoryA -> Action [String]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap GetDirectoryA -> [String]
    fromGetDirectoryA (Action GetDirectoryA -> Action [String])
    -> (String -> Action GetDirectoryA) -> String -> Action [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . GetDirectoryDirsQ -> Action GetDirectoryA
    forall key value.
    (Partial, RuleResult key ~ value, ShakeValue key,
     Typeable value) =>
    key -> Action value
    apply1 (GetDirectoryDirsQ -> Action GetDirectoryA)
    -> (String -> GetDirectoryDirsQ) -> String -> Action GetDirectoryA
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> GetDirectoryDirsQ
    GetDirectoryDirsQ

    ---------------------------------------------------------------------
    -- IO ROUTINES

    getDirectoryContentsIO :: FilePath -> IO [FilePath]
    -- getDirectoryContents "" is equivalent to getDirectoryContents "." on Windows,
    -- but raises an error on Linux. We smooth out the difference.
    getDirectoryContentsIO :: String -> IO [String]
    getDirectoryContentsIO dir :: String
    dir = ([String] -> [String]) -> IO [String] -> IO [String]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([String] -> [String]
    forall a. Ord a => [a] -> [a]
    sort ([String] -> [String])
    -> ([String] -> [String]) -> [String] -> [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String -> Bool) -> [String] -> [String]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Bool) -> String -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == '.'))) (IO [String] -> IO [String]) -> IO [String] -> IO [String]
    forall a b. (a -> b) -> a -> b
    $ String -> IO [String]
    IO.getDirectoryContents (String -> IO [String]) -> String -> IO [String]
    forall a b. (a -> b) -> a -> b
    $ if String
    dir String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    == "" then "." else String
    dir

    getDirectoryDirsIO :: FilePath -> IO [FilePath]
    getDirectoryDirsIO :: String -> IO [String]
    getDirectoryDirsIO dir :: String
    dir = (String -> IO Bool) -> [String] -> IO [String]
    forall (m :: * -> *) a.
    Applicative m =>
    (a -> m Bool) -> [a] -> m [a]
    filterM String -> IO Bool
    f ([String] -> IO [String]) -> IO [String] -> IO [String]
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< String -> IO [String]
    getDirectoryContentsIO String
    dir
        where f :: String -> IO Bool
    f x :: String
    x = String -> IO Bool
    IO.doesDirectoryExist (String -> IO Bool) -> String -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ String
    dir String -> ShowS
    </> String
    x

    -- | A version of 'getDirectoryFiles' that is in IO, and thus untracked.
    getDirectoryFilesIO :: FilePath -> [FilePattern] -> IO [FilePath]
    -- Known infelicity: on Windows, if you search for "foo", but have the file "FOO",
    -- it will match if on its own, or not if it is paired with "*", since that forces
    -- a full directory scan, and then it uses Haskell equality (case sensitive)
    getDirectoryFilesIO :: String -> [String] -> IO [String]
    getDirectoryFilesIO root :: String
    root pat :: [String]
    pat = String -> Walk -> IO [String]
    f "" (Walk -> IO [String]) -> Walk -> IO [String]
    forall a b. (a -> b) -> a -> b
    $ (Bool, Walk) -> Walk
    forall a b. (a, b) -> b
    snd ((Bool, Walk) -> Walk) -> (Bool, Walk) -> Walk
    forall a b. (a -> b) -> a -> b
    $ [String] -> (Bool, Walk)
    walk [String]
    pat
        where
            -- Even after we know they are there because we called contents, we still have to check they are directories/files
            -- as required
            f :: String -> Walk -> IO [String]
    f dir :: String
    dir (Walk op :: [String] -> ([String], [(String, Walk)])
    op) = String -> Walk -> IO [String]
    f String
    dir (Walk -> IO [String])
    -> ([String] -> Walk) -> [String] -> IO [String]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([String], [(String, Walk)]) -> Walk
    WalkTo (([String], [(String, Walk)]) -> Walk)
    -> ([String] -> ([String], [(String, Walk)])) -> [String] -> Walk
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [String] -> ([String], [(String, Walk)])
    op ([String] -> IO [String]) -> IO [String] -> IO [String]
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< String -> IO [String]
    getDirectoryContentsIO (String
    root String -> ShowS
    </> String
    dir)
            f dir :: String
    dir (WalkTo (files :: [String]
    files, dirs :: [(String, Walk)]
    dirs)) = do
                [String]
    files <- (String -> IO Bool) -> [String] -> IO [String]
    forall (m :: * -> *) a.
    Applicative m =>
    (a -> m Bool) -> [a] -> m [a]
    filterM (String -> IO Bool
    IO.doesFileExist (String -> IO Bool) -> ShowS -> String -> IO Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String
    root String -> ShowS
    </>)) ([String] -> IO [String]) -> [String] -> IO [String]
    forall a b. (a -> b) -> a -> b
    $ ShowS -> [String] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map (String
    dir String -> ShowS
    </>) [String]
    files
                [String]
    dirs <- ((String, Walk) -> IO [String]) -> [(String, Walk)] -> IO [String]
    forall (m :: * -> *) a b. Monad m => (a -> m [b]) -> [a] -> m [b]
    concatMapM ((String -> Walk -> IO [String]) -> (String, Walk) -> IO [String]
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry String -> Walk -> IO [String]
    f) ([(String, Walk)] -> IO [String])
    -> IO [(String, Walk)] -> IO [String]
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< ((String, Walk) -> IO Bool)
    -> [(String, Walk)] -> IO [(String, Walk)]
    forall (m :: * -> *) a.
    Applicative m =>
    (a -> m Bool) -> [a] -> m [a]
    filterM (String -> IO Bool
    IO.doesDirectoryExist (String -> IO Bool)
    -> ((String, Walk) -> String) -> (String, Walk) -> IO Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String
    root String -> ShowS
    </>) ShowS -> ((String, Walk) -> String) -> (String, Walk) -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String, Walk) -> String
    forall a b. (a, b) -> a
    fst) (((String, Walk) -> (String, Walk))
    -> [(String, Walk)] -> [(String, Walk)]
    forall a b. (a -> b) -> [a] -> [b]
    map (ShowS -> (String, Walk) -> (String, Walk)
    forall a a' b. (a -> a') -> (a, b) -> (a', b)
    first (String
    dir String -> ShowS
    </>)) [(String, Walk)]
    dirs)
                [String] -> IO [String]
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ([String] -> IO [String]) -> [String] -> IO [String]
    forall a b. (a -> b) -> a -> b
    $ [String]
    files [String] -> [String] -> [String]
    forall a. [a] -> [a] -> [a]
    ++ [String]
    dirs

    ---------------------------------------------------------------------
    -- REMOVE UTILITIES

    -- | Remove all files and directories that match any of the patterns within a directory.
    --   Some examples:
    --
    -- @
    -- 'removeFiles' \"output\" [\"\/\/*\"]        -- delete everything inside \'output\'
    -- 'removeFiles' \"output\" [\"\/\/\"]         -- delete \'output\' itself
    -- 'removeFiles' \".\" [\"\/\/*.hi\",\"\/\/*.o\"] -- delete all \'.hi\' and \'.o\' files
    -- @
    --
    --   If the argument directory is missing no error is raised.
    --   This function will follow symlinks, so should be used with care.
    --
    --   This function is often useful when writing a @clean@ action for your build system,
    --   often as a 'phony' rule.
    removeFiles :: FilePath -> [FilePattern] -> IO ()
    removeFiles :: String -> [String] -> IO ()
    removeFiles dir :: String
    dir pat :: [String]
    pat =
        IO Bool -> IO () -> IO ()
    forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
    whenM (String -> IO Bool
    IO.doesDirectoryExist String
    dir) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
            let (b :: Bool
    b,w :: Walk
    w) = [String] -> (Bool, Walk)
    walk [String]
    pat
            if Bool
    b then String -> IO ()
    removeDir String
    dir else String -> Walk -> IO ()
    f String
    dir Walk
    w
        where
            f :: String -> Walk -> IO ()
    f dir :: String
    dir (Walk op :: [String] -> ([String], [(String, Walk)])
    op) = String -> Walk -> IO ()
    f String
    dir (Walk -> IO ()) -> ([String] -> Walk) -> [String] -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([String], [(String, Walk)]) -> Walk
    WalkTo (([String], [(String, Walk)]) -> Walk)
    -> ([String] -> ([String], [(String, Walk)])) -> [String] -> Walk
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [String] -> ([String], [(String, Walk)])
    op ([String] -> IO ()) -> IO [String] -> IO ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< String -> IO [String]
    getDirectoryContentsIO String
    dir
            f dir :: String
    dir (WalkTo (files :: [String]
    files, dirs :: [(String, Walk)]
    dirs)) = do
                [String] -> (String -> IO (Either IOException ())) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ [String]
    files ((String -> IO (Either IOException ())) -> IO ())
    -> (String -> IO (Either IOException ())) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \fil :: String
    fil ->
                    IO () -> IO (Either IOException ())
    forall a. IO a -> IO (Either IOException a)
    tryIO (IO () -> IO (Either IOException ()))
    -> IO () -> IO (Either IOException ())
    forall a b. (a -> b) -> a -> b
    $ String -> IO ()
    removeItem (String -> IO ()) -> String -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String
    dir String -> ShowS
    </> String
    fil
                let done :: HashSet String
    done = [String] -> HashSet String
    forall a. (Eq a, Hashable a) => [a] -> HashSet a
    Set.fromList [String]
    files
                [(String, Walk)] -> ((String, Walk) -> IO ()) -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    t a -> (a -> m b) -> m ()
    forM_ (((String, Walk) -> Bool) -> [(String, Walk)] -> [(String, Walk)]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool)
    -> ((String, Walk) -> Bool) -> (String, Walk) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String -> HashSet String -> Bool)
    -> HashSet String -> String -> Bool
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip String -> HashSet String -> Bool
    forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
    Set.member HashSet String
    done (String -> Bool)
    -> ((String, Walk) -> String) -> (String, Walk) -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String, Walk) -> String
    forall a b. (a, b) -> a
    fst) [(String, Walk)]
    dirs) (((String, Walk) -> IO ()) -> IO ())
    -> ((String, Walk) -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \(d :: String
    d,w :: Walk
    w) -> do
                    let dir2 :: String
    dir2 = String
    dir String -> ShowS
    </> String
    d
                    IO Bool -> IO () -> IO ()
    forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
    whenM (String -> IO Bool
    IO.doesDirectoryExist String
    dir2) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ String -> Walk -> IO ()
    f String
    dir2 Walk
    w

            removeItem :: FilePath -> IO ()
            removeItem :: String -> IO ()
    removeItem x :: String
    x = String -> IO ()
    IO.removeFile String
    x IO () -> (IOException -> IO ()) -> IO ()
    forall a. IO a -> (IOException -> IO a) -> IO a
    `catchIO` \_ -> String -> IO ()
    removeDir String
    x

            -- In newer GHC's removeDirectoryRecursive is probably better, but doesn't follow
            -- symlinks, so it's got different behaviour
            removeDir :: FilePath -> IO ()
            removeDir :: String -> IO ()
    removeDir x :: String
    x = do
                (String -> IO ()) -> [String] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (String -> IO ()
    removeItem (String -> IO ()) -> ShowS -> String -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (String
    x String -> ShowS
    </>)) ([String] -> IO ()) -> IO [String] -> IO ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< String -> IO [String]
    getDirectoryContentsIO String
    x
                String -> IO ()
    IO.removeDirectory String
    x

    -- | Remove files, like 'removeFiles', but executed after the build completes successfully using 'runAfter'.
    --   Useful for implementing @clean@ actions that delete files Shake may have open for building, e.g. 'shakeFiles'.
    --   Where possible, delete the files as a normal part of the build, e.g. using @'liftIO' $ 'removeFiles' dir pats@.
    removeFilesAfter :: FilePath -> [FilePattern] -> Action ()
    removeFilesAfter :: String -> [String] -> Action ()
    removeFilesAfter a :: String
    a b :: [String]
    b = do
        String -> Action ()
    putVerbose (String -> Action ()) -> String -> Action ()
    forall a b. (a -> b) -> a -> b
    $ "Will remove " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ [String] -> String
    unwords [String]
    b String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ " from " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    a
        IO () -> Action ()
    runAfter (IO () -> Action ()) -> IO () -> Action ()
    forall a b. (a -> b) -> a -> b
    $ String -> [String] -> IO ()
    removeFiles String
    a [String]
    b