module Scion.PersistentHoogle.Util
( findHoogleBinPath
) where
import Data.List (find)
import Data.Maybe
import Distribution.Compiler
import Distribution.InstalledPackageInfo
import Distribution.Package
import Distribution.Simple.InstallDirs
import Scion.Packages
import System.FilePath
import System.Directory (doesFileExist, getAppUserDataDirectory, getHomeDirectory)
findHoogleBinPath :: Maybe String -> IO (Maybe String)
findHoogleBinPath extraPath = do
p1 <- findHoogleBinInLibrary getHoogleBinPath1
p2 <- findHoogleBinInLibrary getHoogleBinPath2
p3 <- getHoogleBinPathCabalAPI
p4 <- getHoogleBinPathCabalDir
p5 <- getHoogleBinPathMacOsDir
let placesToSearch = (catMaybes [extraPath, p1, p2]) ++ [p4, p5] ++ p3
findPathsAndCheck placesToSearch
findPathsAndCheck :: [String] -> IO (Maybe String)
findPathsAndCheck [] = return Nothing
findPathsAndCheck (f:fs) = do r <- findPathAndCheck f
case r of
Nothing -> findPathsAndCheck fs
_ -> return r
findPathAndCheck :: String -> IO (Maybe String)
findPathAndCheck path = do
exists <- doesFileExist path
if exists
then return (Just path)
else return Nothing
findHoogleBinInLibrary :: (String -> String) -> IO (Maybe String)
findHoogleBinInLibrary f = do minfo <- findHoogleInfo
case minfo of
Nothing -> return Nothing
Just info -> let [libDir] = libraryDirs info
in return $ Just (f libDir)
findHoogleInfo :: IO (Maybe InstalledPackageInfo)
findHoogleInfo = do infos' <- getPkgInfos
let infos = removeSmallVersions $ concat $ map snd infos'
return $ find (\m -> (pkgName (sourcePackageId m)) == PackageName "hoogle") infos
removeSmallVersions :: [InstalledPackageInfo] -> [InstalledPackageInfo]
removeSmallVersions pids = filter
(not . (\InstalledPackageInfo { sourcePackageId = (PackageIdentifier name version) } ->
any (\InstalledPackageInfo { sourcePackageId = (PackageIdentifier name' version') } ->
name' == name && version' > version)
pids))
pids
getHoogleBinPath1 :: String -> String
getHoogleBinPath1 path = let (_:(_:(_:rest))) = reverse $ splitDirectories path
in (joinPath $ reverse ("bin":rest)) </> "hoogle" <.> exeExtension
getHoogleBinPath2 :: String -> String
getHoogleBinPath2 path = let (_:(_:rest)) = reverse $ splitDirectories path
in (joinPath $ reverse ("bin":rest)) </> "hoogle" <.> exeExtension
getHoogleBinPathCabalAPI :: IO [String]
getHoogleBinPathCabalAPI = do
let ci=buildCompilerFlavor
mapM (getBinDir ci) [True,False]
getBinDir :: CompilerFlavor -> Bool -> IO FilePath
getBinDir ci user=do
ids<-defaultInstallDirs ci user True
let env=installDirsTemplateEnv ids
return $ fromPathTemplate $ substPathTemplate env $ bindir ids
getHoogleBinPathCabalDir :: IO String
getHoogleBinPathCabalDir = do
cabalDir <- getAppUserDataDirectory "cabal"
return (cabalDir </> "bin" </> "hoogle" <.> exeExtension)
getHoogleBinPathMacOsDir :: IO String
getHoogleBinPathMacOsDir = do
homeDir <- getHomeDirectory
return (homeDir </> "Library" </> "Haskell" </> "bin" </> "hoogle" <.> exeExtension)
exeExtension :: String
#ifdef mingw32_HOST_OS
exeExtension = "exe"
#else
exeExtension = ""
#endif