hoogle-4.1: src/Recipe/Hackage.hs
module Recipe.Hackage(makePlatform, makeDefault, makePackage, makeAll) where
import Recipe.Type
import Recipe.General
import General.Base
import General.System
import General.Util
import General.Web
avoid = words "ghc-prim integer integer-simple integer-gmp rts ghc Win32"
makePlatform :: ([Name] -> IO ()) -> IO ()
makePlatform make = do
xs <- listPlatform
forM_ xs $ \(name,ver) -> do
v2 <- version cabals name
when (ver /= v2) $ putStrLn $ "Warning: Version mismatch for " ++ name ++ " (platform=" ++ ver ++ ", cabal=" ++ v2 ++ ")"
combine make "platform" (map fst xs) False
makeAll :: ([Name] -> IO ()) -> IO ()
makeAll make = do
xs <- listing haddocks
make xs
-- create a database containing an entry for each package in hackage
makePackage :: IO ()
makePackage = do
xs <- listing cabals
xs <- forM xs $ \name -> do
ver <- version cabals name
let file = cabals </> name </> ver </> name <.> "cabal"
src <- readCabal file
return $ [""] ++ zipWith (++) ("-- | " : repeat "-- ") (cabalDescription src) ++
["--","-- Version " ++ ver, "@package " ++ name]
writeFile "package.txt" $ unlines $ concat xs
convert noDeps "package"
makeDefault :: ([Name] -> IO ()) -> [FilePath] -> Name -> IO ()
makeDefault make local name = do
b1 <- doesDirectoryExist $ cabals </> name
b2 <- doesDirectoryExist $ haddocks </> name
if not b1 || not b2 then
putError $ "Error: " ++ name ++ " couldn't find both Cabal and Haddock inputs"
else do
vc <- version cabals name
vh <- version haddocks name
when (vc /= vh) $ putStrLn $ "Warning: Version mismatch for " ++ name ++ " (cabal=" ++ vc ++ ", haddock=" ++ vh ++ ")"
let had = haddocks </> name </> vh </> name <.> "txt"
cab = cabals </> name </> vc </> name <.> "cabal"
h <- openFile had ReadMode
sz <- hFileSize h
hClose h
if sz == 0 then
putError $ "Error: " ++ name ++ " has no haddock output"
else do
had <- readFile' had
cab <- readCabal cab
loc <- findLocal local name
writeFile (name <.> "txt") $ unlines $
["@depends " ++ a | a <- cabalDepends cab, a `notElem` avoid] ++
(maybe id haddockPackageUrl loc) (haddockHacks $ lines had)
convert make name
-- try and find a local filepath
findLocal :: [FilePath] -> Name -> IO (Maybe URL)
findLocal paths name = fmap (listToMaybe . concat . concat) $ forM paths $ \p -> do
xs <- getDirectoryContents p
xs <- return [p </> x | x <- reverse $ sort xs, name == fst (rbreak (== '-') x)] -- make sure highest version comes first
forM xs $ \x -> do
b <- doesDirectoryExist $ x </> "html"
x <- return $ if b then x </> "html" else x
b <- doesFileExist $ x </> "doc-index.html"
return [filePathToURL $ x </> "index.html" | b]
---------------------------------------------------------------------
-- READ PLATFORM
listPlatform :: IO [(Name,String)]
listPlatform = do
src <- readFile platform
let xs = takeWhile (not . isPrefixOf "build-tools:" . ltrim) $
dropWhile (not . isPrefixOf "build-depends:" . ltrim) $
lines src
return [(name, takeWhile (\x -> x == '.' || isDigit x) $ drop 1 b)
| x <- xs, (a,_:b) <- [break (== '=') x], let name = trim $ dropWhile (== '-') $ trim a
, name `notElem` words "Cabal hpc Win32"]
---------------------------------------------------------------------
-- HADDOCK HACKS
-- Eliminate @version
-- Change :*: to (:*:), Haddock bug
-- Change !!Int to !Int, Haddock bug
-- Change instance [overlap ok] to instance, Haddock bug
-- Change instance [incoherent] to instance, Haddock bug
-- Change !Int to Int, HSE bug
haddockHacks :: [String] -> [String]
haddockHacks = map (unwords . map f . words) . filter (not . isPrefixOf "@version ")
where
f "::" = "::"
f (':':xs) = "(:" ++ xs ++ ")"
f ('!':'!':x:xs) | isAlpha x = xs
f ('!':x:xs) | isAlpha x || x `elem` "[(" = x:xs
f x | x `elem` ["[overlap","ok]","[incoherent]"] = ""
f x = x
haddockPackageUrl :: URL -> [String] -> [String]
haddockPackageUrl x = concatMap f
where f y | "@package " `isPrefixOf` y = ["@url " ++ x, y]
| otherwise = [y]