packages feed

craft-0.0.0.1: src/Craft/Wget.hs

module Craft.Wget where

import           Control.Lens
import           Data.Monoid    ((<>))

import           Craft
import           Craft.Checksum (Checksum)
import qualified Craft.Checksum as Checksum
import qualified Craft.File     as File

data Wget = Wget
  { _url    :: String
  , _dest   :: File
  , _chksum :: Maybe Checksum
  , _args   :: Args -- ^Additional arguments to add to the wget command, such as timeouts.
  }
  deriving (Show, Eq)
makeLenses ''Wget


wget :: String -> Path Abs FileP -> Wget
wget url' destfp =
  Wget
  { _url    = url'
  , _dest   = file destfp
  , _chksum = Nothing
  , _args   = []
  }


instance Craftable Wget Wget where
  watchCraft wg = do
    let destf  = wg ^. dest & fileContent .~ Nothing
    let destfp = wg ^. dest . path
    let mismatchError actual = "Checksum Mismatch for `"<>wg^.url<>"`. "
                            <> "Expected `"<>show (wg^.chksum)<>"` "
                            <> "Got `"<>show actual<>"`"
    let check = Checksum.check destf
    let watchDest = do
          w <- watchCraft_ destf
          return (w, wg)
    File.exists destfp >>= \case
      True ->
        case wg ^. chksum of
          Nothing      -> watchDest
          Just chksum' ->
            check chksum' >>= \case
              Checksum.Matched      -> watchDest
              Checksum.Failed r     -> $craftError $ show r
              Checksum.Mismatched _ -> do
                run wg -- Try redownloading the file if the checksum doesn't match.
                check chksum' >>= \case
                  Checksum.Matched           -> watchDest
                  Checksum.Failed r          -> $craftError $ show r
                  Checksum.Mismatched actual -> $craftError $ mismatchError actual
      False -> do
        run wg
        case wg ^. chksum of
          Nothing      -> return ()
          Just chksum' ->
            check chksum' >>= \case
              Checksum.Matched           -> return ()
              Checksum.Failed r          -> $craftError $ show r
              Checksum.Mismatched actual -> $craftError $ mismatchError actual
        void watchDest
        return (Created, wg)


run :: Wget -> Craft ()
run wg = exec_ "wget" $ (wg^.args) ++ ["-O", (fromAbsFile $ wg^.dest.path), wg^.url]