1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
9import Control.Concurrent (forkIO)
10import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
11import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, readMVar)
12import Control.Monad (foldM, void, when)
13import Control.Monad.Except (liftIO)
14import qualified Data.Binary as Binary
15import qualified Data.ByteString as BS
16import qualified Data.Map as Map
17import qualified Data.Time.Clock as Time
18import qualified System.Directory as Dir
20import qualified Elm.Compiler.Module as Module
21import qualified Elm.Package as Pkg
23import qualified Elm.Project.Json as Project
24import qualified Elm.Project.Summary as Summary
25import qualified File.Crawl as Crawl
26import qualified File.Header as Header
27import qualified Reporting.Task as Task
28import qualified Stuff.Paths
35type Dict value = Map.Map Module.Raw value
38plan :: Maybe FilePath -> Summary.Summary -> Crawl.Result -> Task.Task (Dict Info, Module.Interfaces)
39plan docs (Summary.Summary root project _ ifaces _) (Crawl.Graph _ locals _ foreigns _) =
42 let env = Env queue root (Project.getName project) docs
45 statusMVars <- Map.traverseWithKey (getStatus env mvar foreigns) locals
46 putMVar mvar statusMVars
49 do graph <- Map.traverseMaybeWithKey (\_ -> readMVar) statusMVars
50 writeChan queue (EndLoop graph)
52 ifaceLoader queue ifaces
60 , _docs :: Maybe FilePath
68type Status = Maybe Info
76 , _time :: Time.UTCTime
77 , _src :: BS.ByteString
78 , _clean :: [Module.Raw]
79 , _dirty :: [Module.Raw]
80 , _foreign :: [Module.Canonical] -- TODO is this needed?
90 -> MVar (Dict (MVar Status))
95getStatus env statusMVars foreigns name (Header.Info path time src deps) =
96 do mvar <- newEmptyMVar
98 void $ forkIO $ putMVar mvar =<<
99 do statuses <- readMVar statusMVars
100 info <- foldM (addDep statuses foreigns) (Info path time src [] [] []) deps
102 let elmi = Stuff.Paths.elmi (_root env) name
103 let docs = Stuff.Paths.moduleDocs (_root env) name
112 do freshElmi <- isFresh time elmi
115 Nothing -> return True
116 Just _ -> isFresh time docs
118 if freshElmi && freshDocs
120 do let canonical = Module.Canonical (_pkg env) name
121 writeChan (_queue env) (Get canonical elmi)
131addDep :: Dict (MVar Status) -> Dict Pkg.Package -> Info -> Module.Raw -> IO Info
132addDep locals foreigns info name =
133 case Map.lookup name locals of
135 do status <- readMVar mvar
138 return $ info { _clean = name : _clean info }
141 return $ info { _dirty = name : _dirty info }
144 case Map.lookup name foreigns of
145 Just (Pkg.Package pkg _vsn) ->
146 return $ info { _foreign = Module.Canonical pkg name : _foreign info }
149 return info -- must be native
156isFresh :: Time.UTCTime -> FilePath -> IO Bool
157isFresh srcTime cachedFile =
159 [ Dir.doesFileExist cachedFile
160 , do cacheTime <- Dir.getModificationTime cachedFile
161 return (cacheTime >= srcTime)
165andM :: [IO Bool] -> IO Bool
171 check : otherChecks ->
173 if bool then andM otherChecks else return False
176remove :: FilePath -> IO ()
178 do exists <- Dir.doesFileExist path
179 when exists (Dir.removeFile path)
187 = EndLoop (Dict Info)
188 | Get Module.Canonical FilePath
191ifaceLoader :: Chan Msg -> Module.Interfaces -> IO (Dict Info, Module.Interfaces)
192ifaceLoader queue ifaces =
193 do msg <- readChan queue
196 return ( dirty, ifaces )
198 Get canonical elmi ->
199 case Map.lookup canonical ifaces of
201 ifaceLoader queue ifaces
204 do iface <- Binary.decodeFile elmi
205 ifaceLoader queue $ Map.insert canonical iface ifaces
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list