module Data.Mole.Builder.Image where import Control.Concurrent.STM import qualified Data.Set as S import qualified Data.ByteString as BS import qualified Data.Text as T import Data.Maybe import Data.Time import Text.Printf import Data.Mole.Types import Data.Mole.Builder.Internal.Fingerprint import qualified Network.Kraken as K import System.Environment import System.FilePath import System.Directory import System.Posix.Files imageBuilder :: String -> String -> Handle -> AssetId -> IO Builder imageBuilder src contentType h aId = do originalBody <- BS.readFile src let fp = contentHash originalBody cacheDir <- lookupEnv "XDG_CACHE_DIR" let cacheName = (fromMaybe ".cache" cacheDir) "kraken" T.unpack fp inCache <- fileExist cacheName body <- if inCache then do BS.readFile cacheName else case krakenH h of Nothing -> return originalBody Just kh -> do atomically $ takeTMVar (lock h) logMessage' h aId $ "Compressing image with Kraken..." res <- K.compressImage kh (K.Options Nothing Nothing Nothing) originalBody case res of Left _ -> do atomically $ putTMVar (lock h) () return originalBody Right body -> do createDirectoryIfMissing True $ takeDirectory cacheName BS.writeFile cacheName body atomically $ putTMVar (lock h) () return body let ol = BS.length originalBody let nl = BS.length body let ratio :: Double ratio = (100.0 * ((fromIntegral nl :: Double) / (fromIntegral ol))) logMessage' h aId $ concat [ "Compressed image from " , show ol , " to " , show nl , " bytes (" , printf "%.2f" ratio , "%)" ] return $ Builder { assetSources = S.singleton src , assetDependencies = S.empty , packageAsset = const $ Right $ Result (PublicIdentifier $ fingerprint body src) $ Just (body, contentType) , sourceFingerprint = originalBody } logMessage' :: Handle -> AssetId -> String -> IO () logMessage' h aId msg = do now <- getCurrentTime atomically $ writeTQueue (messages h) (Message now aId msg)