Write hoogle DB generation errors to a file #47

This commit is contained in:
Michael Sloan 2015-01-02 20:18:01 -08:00
parent b007d36631
commit 95c5835266

View File

@ -19,7 +19,7 @@ import System.Process (createProcess, proc, cwd, waitForProcess)
import System.Exit (ExitCode (ExitSuccess)) import System.Exit (ExitCode (ExitSuccess))
import Network.Mime (defaultMimeLookup) import Network.Mime (defaultMimeLookup)
import Crypto.Hash.Conduit (sinkHash) import Crypto.Hash.Conduit (sinkHash)
import System.IO (IOMode (ReadMode), withBinaryFile, openBinaryFile) import System.IO (IOMode (ReadMode, WriteMode), withBinaryFile, openBinaryFile)
import Data.Conduit.Zlib (gzip) import Data.Conduit.Zlib (gzip)
import System.Posix.Files (createLink) import System.Posix.Files (createLink)
import qualified Data.ByteString.Base16 as B16 import qualified Data.ByteString.Base16 as B16
@ -307,17 +307,19 @@ createHaddockUnpacker root store runDB' urlRenderRef = do
ec <- waitForProcess ph ec <- waitForProcess ph
if ec == ExitSuccess then return () else throwM ec if ec == ExitSuccess then return () else throwM ec
-- TODO: run hoogle and the database update in
-- concurrent threads.
urlRender <- readIORef urlRenderRef urlRender <- readIORef urlRenderRef
runResourceT $ do runResourceT $ do
liftIO $ createTree $ dirHoogleIdent dirs ident
tmp <- liftIO getTemporaryDirectory tmp <- liftIO getTemporaryDirectory
(_releasekey, hoogletemp) <- allocate (_releasekey, hoogletemp) <- allocate
(fpFromString <$> createTempDirectory tmp "hoogle-database-gen") (fpFromString <$> createTempDirectory tmp "hoogle-database-gen")
removeTree removeTree
copyHoogleTextFiles destdir hoogletemp let logFp = fpToString (dirHoogleFp dirs ident ["error-log"])
void $ resourceForkIO $ createHoogleDb dirs stackageEnt hoogletemp urlRender (_, errorLog) <- allocate (openBinaryFile logFp WriteMode) hClose
copyHoogleTextFiles errorLog destdir hoogletemp
-- TODO: Have hoogle requests block on this finishing.
-- (Or display a "compiling DB" message to the user)
void $ resourceForkIO $ createHoogleDb dirs stackageEnt errorLog hoogletemp urlRender
-- Determine which packages have documentation and update the -- Determine which packages have documentation and update the
-- database appropriately -- database appropriately
@ -396,33 +398,39 @@ getUploadDocMapR = do
putUploadDocMapR :: Handler Html putUploadDocMapR :: Handler Html
putUploadDocMapR = getUploadDocMapR putUploadDocMapR = getUploadDocMapR
copyHoogleTextFiles :: FilePath -- ^ raw unpacked Haddock files copyHoogleTextFiles :: Handle -- ^ error log handle
-> FilePath -- ^ raw unpacked Haddock files
-> FilePath -- ^ temporary work directory -> FilePath -- ^ temporary work directory
-> ResourceT IO () -> ResourceT IO ()
copyHoogleTextFiles raw tmp = do copyHoogleTextFiles errorLog raw tmp = do
let tmptext = tmp </> "text" let tmptext = tmp </> "text"
liftIO $ createTree tmptext liftIO $ createTree tmptext
sourceDirectory raw $$ mapM_C (\fp -> sourceDirectory raw $$ mapM_C (\fp ->
forM_ (nameAndVersionFromPath fp) $ \(name, version) -> do forM_ (nameAndVersionFromPath fp) $ \(name, version) -> do
let src = fp </> fpFromText name <.> "txt" let src = fp </> fpFromText name <.> "txt"
dst = tmptext </> fpFromText (name ++ "-" ++ version) dst = tmptext </> fpFromText (name ++ "-" ++ version)
whenM (liftIO $ isFile src) $ exists <- liftIO $ isFile src
sourceFile src $$ (sinkFile dst :: Sink ByteString (ResourceT IO) ()) if exists
then sourceFile src $$ (sinkFile dst :: Sink ByteString (ResourceT IO) ())
else liftIO $ appendHoogleErrors errorLog $ HoogleErrors
{ packageName = name
, packageVersion = version
, errors = ["No textual Hoogle DB (use \"cabal haddock --hoogle\")"]
}
) )
createHoogleDb :: Dirs createHoogleDb :: Dirs
-> Entity Stackage -> Entity Stackage
-> Handle -- ^ error log handle
-> FilePath -- ^ temp directory -> FilePath -- ^ temp directory
-> (Route App -> [(Text, Text)] -> Text) -> (Route App -> [(Text, Text)] -> Text)
-> ResourceT IO () -> ResourceT IO ()
createHoogleDb dirs (Entity _ stackage) tmpdir urlRender = do createHoogleDb dirs (Entity _ stackage) errorLog tmpdir urlRender = do
let ident = stackageIdent stackage let ident = stackageIdent stackage
tmpbin = tmpdir </> "binary" tmpbin = tmpdir </> "binary"
hoogleDir = dirHoogleIdent dirs ident liftIO $ createTree tmpbin
liftIO $ do eres <- tryAny $ do
createTree hoogleDir -- Create hoogle binary databases for each package.
createTree tmpbin
-- Create hoogle binary databases for each package
sourceDirectory (tmpdir </> "text") $$ mapM_C sourceDirectory (tmpdir </> "text") $$ mapM_C
( \fp -> do ( \fp -> do
(releaseKey, srcH) <- allocate (openBinaryFile (fpToString fp) ReadMode) hClose (releaseKey, srcH) <- allocate (openBinaryFile (fpToString fp) ReadMode) hClose
@ -434,30 +442,57 @@ createHoogleDb dirs (Entity _ stackage) tmpdir urlRender = do
urlPieces = [name <> "-" <> version, "index.html"] urlPieces = [name <> "-" <> version, "index.html"]
-- Compute the filepath of the resulting hoogle -- Compute the filepath of the resulting hoogle
-- database. -- database.
out = fpToString $ tmpbin </> base <.> "hoo" out = fpToString $ tmpbin </> fpFromText base
base = F.dropExtension $ filename fp base = name <> "-" <> version <> ".hoo"
errs <- Hoogle.createDatabase "foo" Hoogle.Haskell [] src' out errs <- Hoogle.createDatabase "" Hoogle.Haskell [] src' out
-- TODO: handle these more gracefully? when (not $ null errs) $ do
when (not $ null errs) $ putStrLn $ concat -- TODO: remove this printing once errors are yielded
[ fpToText base -- to the user.
putStrLn $ concat
[ base
, " Hoogle errors: " , " Hoogle errors: "
, tshow errs , tshow errs
] ]
appendHoogleErrors errorLog $ HoogleErrors
{ packageName = name
, packageVersion = version
, errors = map show errs
}
release releaseKey release releaseKey
) )
-- Merge the individual binary databases into one big database. -- Merge the individual binary databases into one big database.
liftIO $ do liftIO $ do
dbs <- listDirectory tmpbin dbs <- listDirectory tmpbin
let merged = hoogleDir </> "default.hoo"
Hoogle.mergeDatabase Hoogle.mergeDatabase
(map fpToString (filter (/= merged) dbs)) (map fpToString dbs)
(fpToString merged) (fpToString (dirHoogleFp dirs ident ["default.hoo"]))
case eres of
Right () -> return ()
Left err -> liftIO $ appendHoogleErrors errorLog $ HoogleErrors
{ packageName = "Exception thrown while building hoogle DB"
, packageVersion = ""
, errors = [show err]
}
data HoogleErrors = HoogleErrors
{ packageName :: Text
, packageVersion :: Text
, errors :: [String]
} deriving (Generic)
instance ToJSON HoogleErrors where
instance FromJSON HoogleErrors where
-- Appends hoogle errors to a log file. By encoding within a single
-- list, the resulting file can be decoded as [HoogleErrors].
appendHoogleErrors :: Handle -> HoogleErrors -> IO ()
appendHoogleErrors h errs = hPut h (Y.encode [errs])
nameAndVersionFromPath :: FilePath -> Maybe (Text, Text) nameAndVersionFromPath :: FilePath -> Maybe (Text, Text)
nameAndVersionFromPath fp = nameAndVersionFromPath fp =
(\name -> (name, version)) <$> stripSuffix "-" name' (\name -> (name, version)) <$> stripSuffix "-" name'
where where
(name', version) = T.breakOnEnd "-" $ fpToText $ filename fp (name', version) = T.breakOnEnd "-" $ fpToText $ F.dropExtension $ filename fp
--------------------------------------------------------------------- ---------------------------------------------------------------------
-- HADDOCK HACKS -- HADDOCK HACKS