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
194 lines (189 loc) · 8.14 KB
/
Hoogle.hs
File metadata and controls
194 lines (189 loc) · 8.14 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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | A wrapper around hoogle.
module Stack.Hoogle
( hoogleCmd
) where
import Stack.Prelude
import qualified Data.ByteString.Lazy.Char8 as BL8
import Data.Char (isSpace)
import qualified Data.Text as T
import Distribution.Types.PackageName (mkPackageName)
import Distribution.Version (mkVersion)
import Path (parseAbsFile)
import Path.IO hiding (findExecutable)
import qualified Stack.Build
import Stack.Runners
import Stack.Types.Config
import System.Exit
import RIO.Process
-- | Hoogle command.
hoogleCmd :: ([String],Bool,Bool,Bool) -> GlobalOpts -> IO ()
hoogleCmd (args,setup,rebuild,startServer) go = withBuildConfig go $ do
hooglePath <- ensureHoogleInPath
generateDbIfNeeded hooglePath
runHoogle hooglePath args'
where
args' :: [String]
args' = if startServer
then ["server", "--local", "--port", "8080"]
else []
++ args
generateDbIfNeeded :: Path Abs File -> RIO EnvConfig ()
generateDbIfNeeded hooglePath = do
databaseExists <- checkDatabaseExists
if databaseExists && not rebuild
then return ()
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 hooglePath
logInfo "Generated DB."
else do
logError
"No Hoogle database. Not building one due to --no-setup"
bail
generateDb :: Path Abs File -> RIO EnvConfig ()
generateDb hooglePath = do
do dir <- hoogleRoot
createDirIfMissing True dir
runHoogle hooglePath ["generate", "--local"]
buildHaddocks :: RIO EnvConfig ()
buildHaddocks =
liftIO
(catch
(withBuildConfigAndLock
(set
(globalOptsBuildOptsMonoidL . buildOptsMonoidHaddockL)
(Just True)
go)
(\lk ->
Stack.Build.build
Nothing
lk
defaultBuildOptsCLI))
(\(_ :: ExitCode) ->
return ()))
hooglePackageName = mkPackageName "hoogle"
hoogleMinVersion = mkVersion [5, 0]
hoogleMinIdent =
PackageIdentifier hooglePackageName hoogleMinVersion
installHoogle :: RIO EnvConfig ()
installHoogle = do
hooglePackageIdentifier <- do
mversion <- getLatestHackageVersion hooglePackageName UsePreferredVersions
-- FIXME For a while, we've been following the logic of
-- taking the latest Hoogle version available. However, we
-- may want to instead grab the version of Hoogle present in
-- the snapshot current being used instead.
pure $ fromMaybe (Left hoogleMinIdent) $ do
pir@(PackageIdentifierRevision _ ver _) <- mversion
guard $ ver >= hoogleMinVersion
Just $ Right pir
case hooglePackageIdentifier of
Left{} -> logInfo $
"Minimum " <>
fromString (packageIdentifierString hoogleMinIdent) <>
" is not in your index. Installing the minimum version."
Right ident -> logInfo $
"Minimum version is " <>
fromString (packageIdentifierString hoogleMinIdent) <>
". Found acceptable " <>
display ident <>
" in your index, installing it."
config <- view configL
menv <- liftIO $ configProcessContextSettings config envSettings
liftIO
(catch
(withBuildConfigAndLock
go
(\lk ->
Stack.Build.build
Nothing
lk
defaultBuildOptsCLI
{ boptsCLITargets =
pure $
either
(T.pack . packageIdentifierString)
(utf8BuilderToText . display)
hooglePackageIdentifier
}))
(\(e :: ExitCode) ->
case e of
ExitSuccess -> runRIO menv resetExeCache
_ -> throwIO e))
runHoogle :: Path Abs File -> [String] -> RIO EnvConfig ()
runHoogle hooglePath hoogleArgs = do
config <- view configL
menv <- liftIO $ configProcessContextSettings config envSettings
dbpath <- hoogleDatabasePath
let databaseArg = ["--database=" ++ toFilePath dbpath]
withProcessContext menv $ proc
(toFilePath hooglePath)
(hoogleArgs ++ databaseArg)
runProcess_
bail :: RIO EnvConfig a
bail = liftIO (exitWith (ExitFailure (-1)))
checkDatabaseExists = do
path <- hoogleDatabasePath
liftIO (doesFileExist path)
ensureHoogleInPath :: RIO EnvConfig (Path Abs File)
ensureHoogleInPath = do
config <- view configL
menv <- liftIO $ configProcessContextSettings config envSettings
mhooglePath <- runRIO menv $ findExecutable "hoogle"
eres <- case mhooglePath of
Left _ -> return $ Left "Hoogle isn't installed."
Right hooglePath -> do
result <- withProcessContext menv
$ proc hooglePath ["--numeric-version"]
$ tryAny . fmap fst . readProcess_
let unexpectedResult got = Left $ T.concat
[ "'"
, T.pack hooglePath
, " --numeric-version' did not respond with expected value. Got: "
, got
]
return $ case result of
Left err -> unexpectedResult $ T.pack (show err)
Right bs -> case parseVersion (takeWhile (not . isSpace) (BL8.unpack bs)) of
Nothing -> unexpectedResult $ T.pack (BL8.unpack bs)
Just ver
| ver >= hoogleMinVersion -> Right hooglePath
| otherwise -> Left $ T.concat
[ "Installed Hoogle is too old, "
, T.pack hooglePath
, " is version "
, T.pack $ versionString ver
, " but >= 5.0 is required."
]
case eres of
Right hooglePath -> parseAbsFile hooglePath
Left err
| setup -> do
logWarn $ display err <> " Automatically installing (use --no-setup to disable) ..."
installHoogle
mhooglePath' <- runRIO menv $ findExecutable "hoogle"
case mhooglePath' of
Right hooglePath -> parseAbsFile hooglePath
Left _ -> do
logWarn "Couldn't find hoogle in path after installing. This shouldn't happen, may be a bug."
bail
| otherwise -> do
logWarn $ display err <> " Not installing it due to --no-setup."
bail
envSettings =
EnvSettings
{ esIncludeLocals = True
, esIncludeGhcPackagePath = True
, esStackExe = True
, esLocaleUtf8 = False
, esKeepGhcRts = False
}