forked from commercialhaskell/stack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHoogle.hs
More file actions
178 lines (175 loc) · 7.02 KB
/
Hoogle.hs
File metadata and controls
178 lines (175 loc) · 7.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
-- | A wrapper around hoogle.
module Stack.Hoogle
( hoogleCmd
) where
import Control.Exception
import Control.Monad.IO.Class
import Control.Monad.Logger
import Control.Monad.Reader
import qualified Data.ByteString.Char8 as S8
import Data.List (find)
import qualified Data.Map.Strict as Map
import Data.Monoid
import qualified Data.Set as Set
import Lens.Micro
import Path
import Path.IO
import qualified Stack.Build
import Stack.Fetch
import Stack.Runners
import Stack.Types.Config
import Stack.Types.Internal
import Stack.Types.PackageIdentifier
import Stack.Types.PackageName
import Stack.Types.StackT
import Stack.Types.Version
import System.Exit
import System.Process.Read (resetExeCache, tryProcessStdout)
import System.Process.Run
-- | Hoogle command.
hoogleCmd :: ([String],Bool,Bool) -> GlobalOpts -> IO ()
hoogleCmd (args,setup,rebuild) go = withBuildConfig go pathToHaddocks
where
pathToHaddocks :: StackT EnvConfig IO ()
pathToHaddocks = do
hoogleIsInPath <- checkHoogleInPath
if hoogleIsInPath
then haddocksToDb
else do
if setup
then do
$logWarn
"Hoogle isn't installed or is too old. Automatically installing (use --no-setup to disable) ..."
installHoogle
haddocksToDb
else do
$logError
"Hoogle isn't installed or is too old. Not installing it due to --no-setup."
bail
haddocksToDb :: StackT EnvConfig IO ()
haddocksToDb = do
databaseExists <- checkDatabaseExists
if databaseExists && not rebuild
then runHoogle args
else if setup || rebuild
then do
$logWarn
(if rebuild
then "Rebuilding database ..."
else "No Hoogle database yet. Automatically building haddocks and hoogle database (use --no-setup to disable) ...")
buildHaddocks
$logInfo "Built docs."
generateDb
$logInfo "Generated DB."
runHoogle args
else do
$logError
"No Hoogle database. Not building one due to --no-setup"
bail
generateDb :: StackT EnvConfig IO ()
generateDb = do
do dir <- hoogleRoot
createDirIfMissing True dir
runHoogle ["generate", "--local"]
buildHaddocks :: StackT EnvConfig IO ()
buildHaddocks =
liftIO
(catch
(withBuildConfigAndLock
(set
(globalOptsBuildOptsMonoid . buildOptsMonoidHaddock)
(Just True)
go)
(\lk ->
Stack.Build.build
(const (return ()))
lk
defaultBuildOptsCLI))
(\(_ :: ExitCode) ->
return ()))
installHoogle :: StackT EnvConfig IO ()
installHoogle = do
let hooglePackageName = $(mkPackageName "hoogle")
hoogleMinVersion = $(mkVersion "5.0")
hoogleMinIdent =
PackageIdentifier hooglePackageName hoogleMinVersion
hooglePackageIdentifier <-
do (_,_,resolved) <-
resolvePackagesAllowMissing
mempty
(Set.fromList [hooglePackageName])
return
(case find
((== hooglePackageName) . packageIdentifierName)
(Map.keys resolved) of
Just ident@(PackageIdentifier _ ver)
| ver >= hoogleMinVersion -> Right ident
_ -> Left hoogleMinIdent)
case hooglePackageIdentifier of
Left{} ->
$logInfo
("Minimum " <> packageIdentifierText hoogleMinIdent <>
" is not in your index. Installing the minimum version.")
Right ident ->
$logInfo
("Minimum version is " <> packageIdentifierText hoogleMinIdent <>
". Found acceptable " <>
packageIdentifierText ident <>
" in your index, installing it.")
config <- asks getConfig
menv <- liftIO $ configEnvOverride config envSettings
liftIO
(catch
(withBuildConfigAndLock
go
(\lk ->
Stack.Build.build
(const (return ()))
lk
defaultBuildOptsCLI
{ boptsCLITargets = [ packageIdentifierText
(either
id
id
hooglePackageIdentifier)]
}))
(\(e :: ExitCode) ->
case e of
ExitSuccess -> resetExeCache menv
_ -> throwIO e))
runHoogle :: [String] -> StackT EnvConfig IO ()
runHoogle hoogleArgs = do
config <- asks getConfig
menv <- liftIO $ configEnvOverride config envSettings
dbpath <- hoogleDatabasePath
let databaseArg = ["--database=" ++ toFilePath dbpath]
runCmd
(Cmd
{ cmdDirectoryToRunIn = Nothing
, cmdCommandToRun = "hoogle"
, cmdEnvOverride = menv
, cmdCommandLineArguments = hoogleArgs ++ databaseArg
})
Nothing
bail :: StackT EnvConfig IO ()
bail = liftIO (exitWith (ExitFailure (-1)))
checkDatabaseExists = do
path <- hoogleDatabasePath
liftIO (doesFileExist path)
checkHoogleInPath = do
config <- asks getConfig
menv <- liftIO $ configEnvOverride config envSettings
result <- tryProcessStdout Nothing menv "hoogle" ["--numeric-version"]
case fmap (reads . S8.unpack) result of
Right [(ver :: Double,_)] -> return (ver >= 5.0)
_ -> return False
envSettings =
EnvSettings
{ esIncludeLocals = True
, esIncludeGhcPackagePath = True
, esStackExe = True
, esLocaleUtf8 = False
}