packages feed

epubname-2.3.2: src/epubname.hs

-- Copyright: 2008-2011 Dino Morelli
-- License: BSD3 (see LICENSE)
-- Author: Dino Morelli <dino@ui3.info>

import Codec.Epub.Opf.Format.Package
import Codec.Epub.Opf.Package
import Codec.Epub.Opf.Parse
import Control.Monad
import Control.Monad.Trans
import System.Directory ( doesFileExist, renameFile )
import System.Environment ( getArgs )
import System.Exit
import System.IO ( BufferMode ( NoBuffering )
                 , hSetBuffering, stdout, stderr 
                 )
import Text.Printf

import EpubName.Formatters ( tryFormatting )
import EpubName.Opts ( Options (..), parseOpts, usageText )
import EpubName.Util


{- Construct additional verbose output
-}
formatF :: (String, Package) -> String
formatF (fmtUsed, _) = printf "\n   formatter: %s" fmtUsed

formatFM :: (String, Package) -> String
formatFM (fmtUsed, pkg) =
   printf "\n   formatter: %s\n%s" fmtUsed
      (formatPackage False pkg)


{- Format output for a book that was processed
-}
makeOutput :: Options -> (FilePath, FilePath, String, Package) -> String
makeOutput opts (oldPath, newPath, fmtUsed, pkg) =
   printf "%s -> %s%s" oldPath newPath
      (additional (optVerbose opts) (fmtUsed, pkg))
   where
      additional Nothing  = const ""
      additional (Just 1) = formatF
      additional _        = formatFM


{- Process an individual epub book file
-}
processBook :: Options -> FilePath -> IO Bool
processBook opts oldPath = do
   result <- runEN opts $ do
      pkg <- parseEpubOpf oldPath
      let md = opMeta pkg
      (fmtUsed, newPath) <- tryFormatting (oldPath, md)

      when (not $ optOverwrite opts) $ do
         fileExists <- liftIO $ doesFileExist newPath
         when fileExists $ throwError $ 
            printf "ERROR: File %s already exists!" newPath

      unless (optNoAction opts) $ liftIO $ renameFile oldPath newPath

      return (oldPath, newPath, fmtUsed, pkg)

   let (success, report) = either ((,) False)
         (\r -> (True, makeOutput opts r)) result
   putStrLn report
   return success


main :: IO ()
main = do
   -- No buffering, it messes with the order of output
   mapM_ (flip hSetBuffering NoBuffering) [ stdout, stderr ]

   (opts, paths) <- getArgs >>= parseOpts >>= either exitWith return

   ec <- if ((optHelp opts) || (null paths))
      then do
         putStrLn usageText
         return ExitSuccess
      else do
         when (optNoAction opts) (putStrLn "No-action specified")
         codes <- mapM (processBook opts) paths
         case all id codes of
            True  -> return ExitSuccess
            False -> return . ExitFailure $ 2

   exitWith ec