{-# LINE 1 "Development/Hake/HiddenTools.cpphs" #-}
# 1 "Development/Hake/HiddenTools.cpphs"
# 1 "<built-in>"
# 1 "<command-line>"
# 13 "<command-line>"
# 1 "./dist/build/autogen/cabal_macros.h" 1






































# 13 "<command-line>" 2
# 1 "Development/Hake/HiddenTools.cpphs"
{- hake: make tool. ruby : rake = haskell : hake
Copyright (C) 2008-2008 Yoshikuni Jujo <PAF01143@nifty.ne.jp>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
-}

module Development.Hake.HiddenTools (
  runHake
, isOldThanSomeOf
, hakefileUpdateOption
, defaultTrgtStr
) where

import System.Directory     (createDirectory, doesDirectoryExist,
                             doesFileExist, copyFile, getModificationTime)
import System.Process       (runProcess, waitForProcess)
import System.Exit          (ExitCode(ExitSuccess))
import System.Time          (ClockTime)
import System.IO            (openFile, hClose, IOMode(WriteMode))
import Control.Applicative  ((<$>), liftA2)
import Control.Monad        (when)
import Control.Monad.Utils  (unlessM)
import Control.Exception    (bracket)

maybeGetModificationTime :: FilePath -> IO (Maybe ClockTime)
maybeGetModificationTime fn = do
  ex <- doesFileExist fn
  if ex then Just <$> getModificationTime fn
        else return Nothing

isOldThanSomeOf :: FilePath -> [FilePath] -> IO Bool
isOldThanSomeOf dfn sfns
  = liftA2 ((myOr .) . map . (<)) (maybeGetModificationTime dfn)
                                  (mapM maybeGetModificationTime sfns)
    where
      -- for task like "clean"
      myOr [] = True
      myOr bs = or bs

hakefileUpdateOption :: String
hakefileUpdateOption = "--hakefile-is-updated"

runHake :: FilePath -> FilePath -> [ FilePath ] -> [ String ] -> IO ExitCode
runHake src exe othrs args = do
  unlessM (doesDirectoryExist "_hake") $ createDirectory "_hake"
  othrsUD <- fmap or $ flip mapM othrs $ \fn -> do
    let dist = "_hake/" ++ basename fn
    updated <- isOldThanSomeOf dist [ fn ]
    when updated $ copyFile fn dist
    return updated
  hakefileUD <- isOldThanSomeOf ("_hake/" ++ exe ++ ".hs") [ src ]
  when hakefileUD $
    readFile src >>= writeFile ("_hake/" ++ exe ++ ".hs")

  ret <- bracket (flip openFile WriteMode $ "_hake/" ++ exe ++ ".error") hClose $ \errH ->
    let mErrH = Just errH in



      runProcess "ghc" [ "--make", exe ] (Just "_hake")
                 Nothing Nothing Nothing mErrH >>= waitForProcess
  let args_ = if othrsUD || hakefileUD then (hakefileUpdateOption:args) else args
  case ret of
       ExitSuccess -> return ()
       _           -> readFile ("_hake/" ++ exe ++ ".error") >>= putStr
  runProcess ("_hake/" ++ exe) (if null args then ("default":args_) else args_)
             Nothing Nothing Nothing Nothing Nothing >>= waitForProcess

basename :: FilePath -> FilePath
basename = reverse . takeWhile (/='/') . reverse

defaultTrgtStr :: String
defaultTrgtStr = "default"