content: --------------------------------------------------------------------------------
  -- | Exports simple compilers to just copy files
  {-# LANGUAGE CPP                        #-}
  {-# LANGUAGE DeriveDataTypeable         #-}
  {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  module Hakyll.Core.File
      ( CopyFile (..)
      , copyFileCompiler
      , TmpFile (..)
      , newTmpFile
      ) where
  
  
  --------------------------------------------------------------------------------
  import           Data.Binary                   (Binary (..))
  import           Data.Typeable                 (Typeable)
  #if MIN_VERSION_directory(1,2,6)
  import           System.Directory              (copyFileWithMetadata)
  #else
  import           System.Directory              (copyFile)
  #endif
  import           System.Directory              (doesFileExist,
                                                  renameFile)
  import           System.FilePath               ((</>))
  import           System.Random                 (randomIO)
  
  
  --------------------------------------------------------------------------------
  import           Hakyll.Core.Compiler
  import           Hakyll.Core.Compiler.Internal
  import           Hakyll.Core.Configuration
  import           Hakyll.Core.Item
  import           Hakyll.Core.Provider
  import qualified Hakyll.Core.Store             as Store
  import           Hakyll.Core.Util.File
  import           Hakyll.Core.Writable
  
  
  --------------------------------------------------------------------------------
  -- | This will copy any file directly by using a system call
  newtype CopyFile = CopyFile FilePath
      deriving (Binary, Eq, Ord, Show, Typeable)
  
  
  --------------------------------------------------------------------------------
  instance Writable CopyFile where
  #if MIN_VERSION_directory(1,2,6)
      write dst (Item _ (CopyFile src)) = copyFileWithMetadata src dst
  #else
      write dst (Item _ (CopyFile src)) = copyFile src dst
  #endif
  --------------------------------------------------------------------------------
  copyFileCompiler :: Compiler (Item CopyFile)
  copyFileCompiler = do
      identifier <- getUnderlying
      provider   <- compilerProvider <$> compilerAsk
      makeItem $ CopyFile $ resourceFilePath provider identifier
  
  
  --------------------------------------------------------------------------------
  newtype TmpFile = TmpFile FilePath
      deriving (Typeable)
  
  
  --------------------------------------------------------------------------------
  instance Binary TmpFile where
      put _ = return ()
      get   = error $
          "Hakyll.Core.File.TmpFile: You tried to load a TmpFile, however, " ++
          "this is not possible since these are deleted as soon as possible."
  
  
  --------------------------------------------------------------------------------
  instance Writable TmpFile where
      write dst (Item _ (TmpFile fp)) = renameFile fp dst
  
  
  --------------------------------------------------------------------------------
  -- | Create a tmp file
  newTmpFile :: String            -- ^ Suffix and extension
             -> Compiler TmpFile  -- ^ Resulting tmp path
  newTmpFile suffix = do
      path <- mkPath
      compilerUnsafeIO $ makeDirectories path
      debugCompiler $ "newTmpFile " ++ path
      return $ TmpFile path
    where
      mkPath = do
          rand <- compilerUnsafeIO $ randomIO :: Compiler Int
          tmp  <- tmpDirectory . compilerConfig <$> compilerAsk
          let path = tmp </> Store.hash [show rand] ++ "-" ++ suffix
          exists <- compilerUnsafeIO $ doesFileExist path
          if exists then mkPath else return path
  