content: module MicroCabal.Unix(
    cmd, tryCmd, cmdOut, tryCmdOut,
    mkdir,
    wget, URL(..),
    gitClone,
    tarx,
    rmrf,
    cp, cpr,
    copyFiles,
    preserveCurrentDirectory,
    (</>),
    ) where
  import Control.Exception
  import Data.Maybe
  import System.Directory
  import System.Environment
  import System.IO
  import System.Process(callCommand)
  import MicroCabal.Env
  
  newtype URL = URL String
  
  cmd :: Env -> String -> IO ()
  cmd env s = do
    message env 2 $ "cmd: " ++ s
    callCommand s
  
  tryCmd :: Env -> String -> IO Bool
  tryCmd env s = catch (cmd env s >> return True) f
    where f :: SomeException -> IO Bool
          f _ = return False
  
  cmdOut :: Env -> String -> IO String
  cmdOut env s = do
    (fn, h) <- tmpFile
    hClose h
    cmd env $ s ++ " >" ++ fn
    o <- readFile fn
    removeFile fn
    return o
  
  tryCmdOut :: Env -> String -> IO (Maybe String)
  tryCmdOut env s = do
    (fn, h) <- tmpFile
    hClose h
    b <- tryCmd env $ s ++ " >" ++ fn
    if b then do
      o <- readFile fn
      removeFile fn
      return (Just o)
     else
      return Nothing
  
  tmpFile :: IO (String, Handle)
  tmpFile = do
    mtmp <- lookupEnv "TMPDIR"
    let tmp = fromMaybe "/tmp" mtmp
        tmplt = "mcabal.txt"
    res <- try $ openTempFile tmp tmplt
    case res :: Either SomeException (String, Handle) of
      Right x -> return x
      Left  _ -> openTempFile "." tmplt
  
  
  ---------
  
  -- Create a directory path, don't complain if it exists.
  mkdir :: Env -> String -> IO ()
  mkdir env d = cmd env $ "mkdir -p " ++ d
  
  -- Get a document, store it in a file.
  wget :: Env -> URL -> FilePath -> IO ()
  wget env (URL url) fn = do
    mw <- lookupEnv "MICROCABAL_USE_WGET"
    if isNothing mw then
      cmd env $ "curl -s -o" ++ fn ++ " " ++ url
     else
      cmd env $ "wget --quiet --output-document=" ++ fn ++ " " ++ url
  
  -- Extract a tar file
  tarx :: Env -> FilePath -> FilePath -> IO ()
  tarx env dir file = cmd env $ "tar -C " ++ dir ++ " -x -f " ++ file
  
  -- Recursively remove
  rmrf :: Env -> FilePath -> IO ()
  rmrf env fn = cmd env $ "rm -rf " ++ fn
  
  -- Copy a file to a directory
  cp :: Env -> FilePath -> FilePath -> IO ()
  cp env s d = do
    cmd env $ "cp " ++ s ++ " " ++ d
  
  -- Copy a file to a directory, delete first
  cpr :: Env -> FilePath -> FilePath -> IO ()
  cpr env s d = do
    cmd env $ "rm -f " ++ d
    cp env s d
  
  copyFiles :: Env -> FilePath -> [FilePath] -> FilePath -> IO ()
  copyFiles env src fns tgt = do
    cmd env $ "cd " ++ src ++ "; tar cf - " ++ unwords fns ++ " | (cd " ++ tgt ++ "; tar xf - )"
  
  preserveCurrentDirectory :: IO a -> IO a
  preserveCurrentDirectory io = do
    cwd <- getCurrentDirectory
    a <- io
    setCurrentDirectory cwd
    return a
  
  gitClone :: Env -> FilePath -> URL -> IO ()
  gitClone env dir (URL repo) = do
    cmd env $ "git clone " ++ repo ++ " " ++ dir
  
  -----
  
  (</>) :: FilePath -> FilePath -> FilePath
  x </> y = x ++ "/" ++ y
  