module Scion.PersistentHoogle ( query , downloadData , checkDatabase , initDatabase , module Scion.PersistentHoogle.Types ) where import Control.Applicative import Control.Monad import Control.Monad.IO.Class (liftIO) import Scion.PersistentBrowser () import Scion.PersistentBrowser.Util import Scion.PersistentBrowser.DbTypes import Scion.PersistentBrowser.Build import Scion.PersistentBrowser.Types import Scion.PersistentHoogle.Types import Scion.PersistentHoogle.Instances.Json () import Scion.PersistentHoogle.Parser import Scion.PersistentHoogle.Util import System.Exit (ExitCode(..)) import System.Process import System.Directory import System.FilePath import Text.Parsec.Prim (runP) import Scion.PersistentBrowser.Parser (parseHoogleFile) import Data.Maybe (catMaybes) import Data.Either import Scion.PersistentBrowser.ToDb (savePackageToDb, deletePackageByInfo) import Scion.PersistentBrowser.FileUtil (withWorkingDirectory) query :: FilePath -> Maybe FilePath -> Maybe FilePath -> String -> SQL [Result] query localDB msandbox p q = do hoogleDir <- liftIO $ getHoogleDir localDB msandbox mpath <- liftIO $ findHoogleBinPath msandbox p case mpath of Nothing -> return [] Just path -> do -- use explicit search argument in case the search is itself a command, like 'data' (exitCode, output, err) <- liftIO $ readProcessWithExitCode path ["search", q,"-d",hoogleDir] "" case exitCode of ExitSuccess -> do liftIO $ logToStdout q liftIO $ logToStdout output let search = runP hoogleElements () "hoogle-output" output case search of Right result -> result Left perr -> do liftIO $ logToStdout $ show perr -- I like to see the error in the log return [] _ -> do liftIO $ logToStdout err -- I like to see the error in the log return [] downloadData :: FilePath -> Maybe FilePath -> Maybe FilePath -> IO HoogleStatus downloadData localDB msandbox p = do hoogleDir <- getHoogleDir localDB msandbox mpath <- findHoogleBinPath msandbox p case mpath of Nothing -> return Missing Just path -> do logToStdout "Downloading hoogle data..." (ec, _, err) <- readProcessWithExitCode path ["data","-d",hoogleDir] "" when (ec/= ExitSuccess) (do logToStdout path logToStdout err) return $ case ec of ExitSuccess->OK _-> Error checkDatabase :: FilePath -> Maybe FilePath -> Maybe FilePath -> IO HoogleStatus checkDatabase localDB msandbox p = do hoogleDir <- getHoogleDir localDB msandbox mpath <- findHoogleBinPath msandbox p case mpath of Nothing -> return Missing Just path -> do (ec, _, err) <- readProcessWithExitCode path ["fmap","-d",hoogleDir] "" when (ec/= ExitSuccess) (do logToStdout path logToStdout err) return $ case ec of ExitSuccess->OK _-> Error -- | Init hoogle DB, adding extra files initDatabase :: FilePath -> Maybe FilePath -> Maybe FilePath -> Bool-> IO HoogleStatus initDatabase localDB msandbox p addToDb = do hoogleDir <- getHoogleDir localDB msandbox mpath <- findHoogleBinPath msandbox p case mpath of Nothing -> return Missing Just path -> withWorkingDirectory hoogleDir $ do ok <- exec path ["fmap","-d",hoogleDir] unless ok (do exec path ["data","-d",hoogleDir] return () ) txts <- filter ((".txt" ==) . takeExtension) <$> getDirectoryContents hoogleDir docs <- forM txts $ \f -> do ret <- if addToDb then Just <$> parseHoogleFile (hoogleDir f) else return Nothing ok1 <- exec path ["convert",hoogleDir f] when ok1 $ removeFile f return ret let (errors,okDocs) = partitionEithers $ catMaybes docs unless (null errors) $ logToStdout $ "addtoDB errors:" ++ show errors unless (null okDocs) $ runSQL localDB $ do mapM_ (deletePackageByInfo . (\ (Package _ pkgid _) -> pkgid)) okDocs mapM_ savePackageToDb okDocs hoos <- filter (("default.hoo" /=) . takeFileName) <$> filter ((".hoo" ==) . takeExtension) <$> getDirectoryContents hoogleDir unless (null hoos) $ do ok2 <- exec path ("combine":hoos) when ok2 $ forM_ hoos removeFile return OK -- | Exec process and dump error exec :: FilePath -> [String] -> IO Bool exec path args= do (ec, _, err) <- readProcessWithExitCode path args "" when (ec/= ExitSuccess) (do logToStdout path logToStdout err) return $ case ec of ExitSuccess -> True _ -> False