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

module Development.Shake.Internal.Rules.Files(
    (&?>), (&%>), defaultRuleFiles
    ) where

import Control.Monad
import Control.Monad.IO.Class
import Data.Maybe
import Data.List.Extra
import Data.Typeable
import General.Binary

import Development.Shake.Internal.Core.Action
import Development.Shake.Internal.Core.Types hiding (Result)
import Development.Shake.Internal.Core.Build
import Development.Shake.Internal.Core.Rules
import Development.Shake.Internal.Errors
import General.Extra
import Development.Shake.Internal.FileName
import Development.Shake.Classes
import Development.Shake.Internal.Rules.Rerun
import Development.Shake.Internal.Rules.File
import Development.Shake.Internal.FilePattern
import Development.Shake.FilePath
import Development.Shake.Internal.FileInfo
import Development.Shake.Internal.Options
import Data.Monoid
import Prelude


infix 1 &?>, &%>


type instance RuleResult FilesQ = FilesA

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

newtype FilesA = FilesA [FileA]
    deriving (Typeable,ByteString -> FilesA
FilesA -> Builder
(FilesA -> Builder) -> (ByteString -> FilesA) -> BinaryEx FilesA
forall a. (a -> Builder) -> (ByteString -> a) -> BinaryEx a
getEx :: ByteString -> FilesA
$cgetEx :: ByteString -> FilesA
putEx :: FilesA -> Builder
$cputEx :: FilesA -> Builder
BinaryEx,FilesA -> ()
(FilesA -> ()) -> NFData FilesA
forall a. (a -> ()) -> NFData a
rnf :: FilesA -> ()
$crnf :: FilesA -> ()
NFData)

instance Show FilesA where show :: FilesA -> String
show (FilesA xs :: [FileA]
xs) = [String] -> String
unwords ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ "Files" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: (FileA -> String) -> [FileA] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> ShowS
forall a. Int -> [a] -> [a]
drop 5 ShowS -> (FileA -> String) -> FileA -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileA -> String
forall a. Show a => a -> String
show) [FileA]
xs

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

data FilesRule = FilesRule String (FilesQ -> Maybe (Action FilesA))
    deriving Typeable

data Result = Result Ver FilesA

instance BinaryEx Result where
    putEx :: Result -> Builder
putEx (Result v :: Ver
v x :: FilesA
x) = Ver -> Builder
forall a. Storable a => a -> Builder
putExStorable Ver
v Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> FilesA -> Builder
forall a. BinaryEx a => a -> Builder
putEx FilesA
x
    getEx :: ByteString -> Result
getEx s :: ByteString
s = let (a :: Ver
a,b :: ByteString
b) = ByteString -> (Ver, ByteString)
forall a. Storable a => ByteString -> (a, ByteString)
binarySplit ByteString
s in Ver -> FilesA -> Result
Result Ver
a (FilesA -> Result) -> FilesA -> Result
forall a b. (a -> b) -> a -> b
$ ByteString -> FilesA
forall a. BinaryEx a => ByteString -> a
getEx ByteString
b


filesStoredValue :: ShakeOptions -> FilesQ -> IO (Maybe FilesA)
filesStoredValue :: ShakeOptions -> FilesQ -> IO (Maybe FilesA)
filesStoredValue opts :: ShakeOptions
opts (FilesQ xs :: [FileQ]
xs) = ([FileA] -> FilesA) -> Maybe [FileA] -> Maybe FilesA
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [FileA] -> FilesA
FilesA (Maybe [FileA] -> Maybe FilesA)
-> ([Maybe FileA] -> Maybe [FileA])
-> [Maybe FileA]
-> Maybe FilesA
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe FileA] -> Maybe [FileA]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Maybe FileA] -> Maybe FilesA)
-> IO [Maybe FileA] -> IO (Maybe FilesA)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FileQ -> IO (Maybe FileA)) -> [FileQ] -> IO [Maybe FileA]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (ShakeOptions -> FileQ -> IO (Maybe FileA)
fileStoredValue ShakeOptions
opts) [FileQ]
xs

filesEqualValue :: ShakeOptions -> FilesA -> FilesA -> EqualCost
filesEqualValue :: ShakeOptions -> FilesA -> FilesA -> EqualCost
filesEqualValue opts :: ShakeOptions
opts (FilesA xs :: [FileA]
xs) (FilesA ys :: [FileA]
ys)
    | [FileA] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FileA]
xs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= [FileA] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FileA]
ys = EqualCost
NotEqual
    | Bool
otherwise = (EqualCost -> EqualCost -> EqualCost)
-> EqualCost -> [EqualCost] -> EqualCost
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr EqualCost -> EqualCost -> EqualCost
and_ EqualCost
EqualCheap ([EqualCost] -> EqualCost) -> [EqualCost] -> EqualCost
forall a b. (a -> b) -> a -> b
$ (FileA -> FileA -> EqualCost) -> [FileA] -> [FileA] -> [EqualCost]
forall a b c. Partial => (a -> b -> c) -> [a] -> [b] -> [c]
zipWithExact (ShakeOptions -> FileA -> FileA -> EqualCost
fileEqualValue ShakeOptions
opts) [FileA]
xs [FileA]
ys
        where and_ :: EqualCost -> EqualCost -> EqualCost
and_ NotEqual _ = EqualCost
NotEqual
              and_ EqualCheap x :: EqualCost
x = EqualCost
x
              and_ EqualExpensive x :: EqualCost
x = if EqualCost
x EqualCost -> EqualCost -> Bool
forall a. Eq a => a -> a -> Bool
== EqualCost
NotEqual then EqualCost
NotEqual else EqualCost
EqualExpensive

defaultRuleFiles :: Rules ()
defaultRuleFiles :: Rules ()
defaultRuleFiles = do
    ShakeOptions
opts <- Rules ShakeOptions
getShakeOptionsRules
    -- A rule from FilesQ to FilesA. The result value is only useful for linting.
    BuiltinLint FilesQ FilesA
-> BuiltinIdentity FilesQ FilesA
-> BuiltinRun FilesQ FilesA
-> 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 (ShakeOptions -> BuiltinLint FilesQ FilesA
ruleLint ShakeOptions
opts) (ShakeOptions -> BuiltinIdentity FilesQ FilesA
ruleIdentity ShakeOptions
opts) (ShakeOptions -> (String -> Rebuild) -> BuiltinRun FilesQ FilesA
ruleRun ShakeOptions
opts ((String -> Rebuild) -> BuiltinRun FilesQ FilesA)
-> (String -> Rebuild) -> BuiltinRun FilesQ FilesA
forall a b. (a -> b) -> a -> b
$ ShakeOptions -> String -> Rebuild
shakeRebuildApply ShakeOptions
opts)

ruleLint :: ShakeOptions -> BuiltinLint FilesQ FilesA
ruleLint :: ShakeOptions -> BuiltinLint FilesQ FilesA
ruleLint _ _ (FilesA []) = Maybe String -> IO (Maybe String)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe String
forall a. Maybe a
Nothing -- in the case of disabling lint
ruleLint opts :: ShakeOptions
opts k :: FilesQ
k v :: FilesA
v = do
    Maybe FilesA
now <- ShakeOptions -> FilesQ -> IO (Maybe FilesA)
filesStoredValue ShakeOptions
opts FilesQ
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
$ case Maybe FilesA
now of
        Nothing -> String -> Maybe String
forall a. a -> Maybe a
Just "<missing>"
        Just now :: FilesA
now | ShakeOptions -> FilesA -> FilesA -> EqualCost
filesEqualValue ShakeOptions
opts FilesA
v FilesA
now EqualCost -> EqualCost -> Bool
forall a. Eq a => a -> a -> Bool
== EqualCost
EqualCheap -> Maybe String
forall a. Maybe a
Nothing
                 | Bool
otherwise -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ FilesA -> String
forall a. Show a => a -> String
show FilesA
now

ruleIdentity :: ShakeOptions -> BuiltinIdentity FilesQ FilesA
ruleIdentity :: ShakeOptions -> BuiltinIdentity FilesQ FilesA
ruleIdentity opts :: ShakeOptions
opts | ShakeOptions -> Change
shakeChange ShakeOptions
opts Change -> Change -> Bool
forall a. Eq a => a -> a -> Bool
== Change
ChangeModtime = SomeException -> BuiltinIdentity FilesQ FilesA
forall a. SomeException -> a
throwImpure (SomeException -> BuiltinIdentity FilesQ FilesA)
-> SomeException -> BuiltinIdentity FilesQ FilesA
forall a b. (a -> b) -> a -> b
$ String -> [(String, Maybe String)] -> String -> SomeException
errorStructured
    "Cannot use shakeChange=ChangeModTime with shakeShare" [] ""
ruleIdentity _ = \_ (FilesA files :: [FileA]
files) ->
    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
$ [Builder] -> Builder
putExList [FileSize -> Builder
forall a. Storable a => a -> Builder
putExStorable FileSize
size Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> FileHash -> Builder
forall a. Storable a => a -> Builder
putExStorable FileHash
hash | FileA _ size :: FileSize
size hash :: FileHash
hash <- [FileA]
files]



ruleRun :: ShakeOptions -> (FilePath -> Rebuild) -> BuiltinRun FilesQ FilesA
ruleRun :: ShakeOptions -> (String -> Rebuild) -> BuiltinRun FilesQ FilesA
ruleRun opts :: ShakeOptions
opts rebuildFlags :: String -> Rebuild
rebuildFlags k :: FilesQ
k o :: Maybe ByteString
o@((ByteString -> Result) -> Maybe ByteString -> Maybe Result
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Result
forall a. BinaryEx a => ByteString -> a
getEx -> Maybe Result
old :: Maybe Result) mode :: RunMode
mode = do
    let r :: [Rebuild]
r = (FileQ -> Rebuild) -> [FileQ] -> [Rebuild]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Rebuild
rebuildFlags (String -> Rebuild) -> (FileQ -> String) -> FileQ -> Rebuild
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileName -> String
fileNameToString (FileName -> String) -> (FileQ -> FileName) -> FileQ -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FileQ -> FileName
fromFileQ) ([FileQ] -> [Rebuild]) -> [FileQ] -> [Rebuild]
forall a b. (a -> b) -> a -> b
$ FilesQ -> [FileQ]
fromFilesQ FilesQ
k

    (ruleVer :: Maybe Ver
ruleVer, ruleAct :: [(Int, Action FilesA)]
ruleAct, ruleErr :: SomeException
ruleErr) <- FilesQ
-> (FilesRule -> Maybe String)
-> (FilesRule -> Maybe (Action FilesA))
-> Action (Maybe Ver, [(Int, Action FilesA)], SomeException)
forall key a b.
(ShakeValue key, Typeable a) =>
key
-> (a -> Maybe String)
-> (a -> Maybe b)
-> Action (Maybe Ver, [(Int, b)], SomeException)
getUserRuleInternal FilesQ
k (\(FilesRule s :: String
s _) -> String -> Maybe String
forall a. a -> Maybe a
Just String
s) ((FilesRule -> Maybe (Action FilesA))
 -> Action (Maybe Ver, [(Int, Action FilesA)], SomeException))
-> (FilesRule -> Maybe (Action FilesA))
-> Action (Maybe Ver, [(Int, Action FilesA)], SomeException)
forall a b. (a -> b) -> a -> b
$ \(FilesRule _ f :: FilesQ -> Maybe (Action FilesA)
f) -> FilesQ -> Maybe (Action FilesA)
f FilesQ
k
    let verEq :: Ver -> Bool
verEq v :: Ver
v = Ver -> Maybe Ver
forall a. a -> Maybe a
Just Ver
v Maybe Ver -> Maybe Ver -> Bool
forall a. Eq a => a -> a -> Bool
== Maybe Ver
ruleVer Bool -> Bool -> Bool
|| ((Int, Action FilesA) -> Ver) -> [(Int, Action FilesA)] -> [Ver]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Ver
Ver (Int -> Ver)
-> ((Int, Action FilesA) -> Int) -> (Int, Action FilesA) -> Ver
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, Action FilesA) -> Int
forall a b. (a, b) -> a
fst) [(Int, Action FilesA)]
ruleAct [Ver] -> [Ver] -> Bool
forall a. Eq a => a -> a -> Bool
== [Ver
v]
    let rebuild :: Action (RunResult FilesA)
rebuild = do
            Verbosity -> String -> Action ()
putWhen Verbosity
Verbose (String -> Action ()) -> String -> Action ()
forall a b. (a -> b) -> a -> b
$ "# " String -> ShowS
forall a. [a] -> [a] -> [a]
++ FilesQ -> String
forall a. Show a => a -> String
show FilesQ
k
            case [(Int, Action FilesA)]
ruleAct of
                [x :: (Int, Action FilesA)
x] -> (Int, Action FilesA) -> Action (RunResult FilesA)
rebuildWith (Int, Action FilesA)
x
                _ -> SomeException -> Action (RunResult FilesA)
forall (m :: * -> *) a. MonadIO m => SomeException -> m a
throwM SomeException
ruleErr

    case Maybe Result
old of
        _ | Rebuild
RebuildNow Rebuild -> [Rebuild] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Rebuild]
r -> Action (RunResult FilesA)
rebuild
        _ | Rebuild
RebuildLater Rebuild -> [Rebuild] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Rebuild]
r -> case Maybe Result
old of
            Just _ ->
                -- ignoring the currently stored value, which may trigger lint has changed
                -- so disable lint on this file
                RunResult FilesA -> Action (RunResult FilesA)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RunResult FilesA -> Action (RunResult FilesA))
-> RunResult FilesA -> Action (RunResult FilesA)
forall a b. (a -> b) -> a -> b
$ RunChanged -> ByteString -> FilesA -> RunResult FilesA
forall value. RunChanged -> ByteString -> value -> RunResult value
RunResult RunChanged
ChangedNothing (Maybe ByteString -> ByteString
forall a. Partial => Maybe a -> a
fromJust Maybe ByteString
o) (FilesA -> RunResult FilesA) -> FilesA -> RunResult FilesA
forall a b. (a -> b) -> a -> b
$ [FileA] -> FilesA
FilesA []
            Nothing -> do
                -- i don't have a previous value, so assume this is a source node, and mark rebuild in future
                Maybe FilesA
now <- IO (Maybe FilesA) -> Action (Maybe FilesA)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe FilesA) -> Action (Maybe FilesA))
-> IO (Maybe FilesA) -> Action (Maybe FilesA)
forall a b. (a -> b) -> a -> b
$ ShakeOptions -> FilesQ -> IO (Maybe FilesA)
filesStoredValue ShakeOptions
opts FilesQ
k
                case Maybe FilesA
now of
                    Nothing -> Action (RunResult FilesA)
rebuild
                    Just now :: FilesA
now -> do Action ()
alwaysRerun; RunResult FilesA -> Action (RunResult FilesA)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RunResult FilesA -> Action (RunResult FilesA))
-> RunResult FilesA -> Action (RunResult FilesA)
forall a b. (a -> b) -> a -> b
$ RunChanged -> ByteString -> FilesA -> RunResult FilesA
forall value. RunChanged -> ByteString -> value -> RunResult value
RunResult RunChanged
ChangedStore (Builder -> ByteString
runBuilder (Builder -> ByteString) -> Builder -> ByteString
forall a b. (a -> b) -> a -> b
$ Result -> Builder
forall a. BinaryEx a => a -> Builder
putEx (Result -> Builder) -> Result -> Builder
forall a b. (a -> b) -> a -> b
$ Ver -> FilesA -> Result
Result (Int -> Ver
Ver 0) FilesA
now) FilesA
now
        Just (Result ver :: Ver
ver old :: FilesA
old) | RunMode
mode RunMode -> RunMode -> Bool
forall a. Eq a => a -> a -> Bool
== RunMode
RunDependenciesSame, Ver -> Bool
verEq Ver
ver -> do
            Maybe FilesA
v <- IO (Maybe FilesA) -> Action (Maybe FilesA)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe FilesA) -> Action (Maybe FilesA))
-> IO (Maybe FilesA) -> Action (Maybe FilesA)
forall a b. (a -> b) -> a -> b
$ ShakeOptions -> FilesQ -> IO (Maybe FilesA)
filesStoredValue ShakeOptions
opts FilesQ
k
            case Maybe FilesA
v of
                Just v :: FilesA
v -> case ShakeOptions -> FilesA -> FilesA -> EqualCost
filesEqualValue ShakeOptions
opts FilesA
old FilesA
v of
                    NotEqual -> Action (RunResult FilesA)
rebuild
                    EqualCheap -> RunResult FilesA -> Action (RunResult FilesA)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RunResult FilesA -> Action (RunResult FilesA))
-> RunResult FilesA -> Action (RunResult FilesA)
forall a b. (a -> b) -> a -> b
$ RunChanged -> ByteString -> FilesA -> RunResult FilesA
forall value. RunChanged -> ByteString -> value -> RunResult value
RunResult RunChanged
ChangedNothing (Maybe ByteString -> ByteString
forall a. Partial => Maybe a -> a
fromJust Maybe ByteString
o) FilesA
v
                    EqualExpensive -> RunResult FilesA -> Action (RunResult FilesA)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RunResult FilesA -> Action (RunResult FilesA))
-> RunResult FilesA -> Action (RunResult FilesA)
forall a b. (a -> b) -> a -> b
$ RunChanged -> ByteString -> FilesA -> RunResult FilesA
forall value. RunChanged -> ByteString -> value -> RunResult value
RunResult RunChanged
ChangedStore (Builder -> ByteString
runBuilder (Builder -> ByteString) -> Builder -> ByteString
forall a b. (a -> b) -> a -> b
$ Result -> Builder
forall a. BinaryEx a => a -> Builder
putEx (Result -> Builder) -> Result -> Builder
forall a b. (a -> b) -> a -> b
$ Ver -> FilesA -> Result
Result Ver
ver FilesA
v) FilesA
v
                Nothing -> Action (RunResult FilesA)
rebuild
        _ -> Action (RunResult FilesA)
rebuild
    where
        rebuildWith :: (Int, Action FilesA) -> Action (RunResult FilesA)
rebuildWith (ver :: Int
ver, act :: Action FilesA
act) = do
            Maybe ByteString
cache <- Int -> Action (Maybe ByteString)
historyLoad Int
ver
            FilesA
v <- case Maybe ByteString
cache of
                Just res :: ByteString
res ->
                    ([FileA] -> FilesA) -> Action [FileA] -> Action FilesA
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [FileA] -> FilesA
FilesA (Action [FileA] -> Action FilesA)
-> Action [FileA] -> Action FilesA
forall a b. (a -> b) -> a -> b
$ [(ByteString, FileQ)]
-> ((ByteString, FileQ) -> Action FileA) -> Action [FileA]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM ([ByteString] -> [FileQ] -> [(ByteString, FileQ)]
forall a b. Partial => [a] -> [b] -> [(a, b)]
zipExact (ByteString -> [ByteString]
getExList ByteString
res) (FilesQ -> [FileQ]
fromFilesQ FilesQ
k)) (((ByteString, FileQ) -> Action FileA) -> Action [FileA])
-> ((ByteString, FileQ) -> Action FileA) -> Action [FileA]
forall a b. (a -> b) -> a -> b
$ \(bin :: ByteString
bin, file :: FileQ
file) -> do
                        Just (