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 :: Summary.Summary -> Crawl.Result -> Task.Task (Dict Info, Module.Interfaces)
39plan (Summary.Summary root project _ ifaces _) (Crawl.Graph _ locals _ foreigns _) =
42 let env = Env queue root (Project.getName project)
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
67type Status = Maybe Info
75 , _time :: Time.UTCTime
76 , _src :: BS.ByteString
77 , _clean :: [Module.Raw]
78 , _dirty :: [Module.Raw]
79 , _foreign :: [Module.Canonical] -- TODO is this needed?
89 -> MVar (Dict (MVar Status))
94getStatus env statusMVars foreigns name (Header.Info path time src deps) =
95 do mvar <- newEmptyMVar
97 void $ forkIO $ putMVar mvar =<<
98 do statuses <- readMVar statusMVars
99 info <- foldM (addDep statuses foreigns) (Info path time src [] [] []) deps
101 let elmi = Stuff.Paths.elmi (_root env) name
109 do fresh <- isFresh time elmi
112 do let canonical = Module.Canonical (_pkg env) name
113 writeChan (_queue env) (Get canonical elmi)
122addDep :: Dict (MVar Status) -> Dict Pkg.Package -> Info -> Module.Raw -> IO Info
123addDep locals foreigns info name =
124 case Map.lookup name locals of
126 do status <- readMVar mvar
129 return $ info { _clean = name : _clean info }
132 return $ info { _dirty = name : _dirty info }
135 case Map.lookup name foreigns of
136 Just (Pkg.Package pkg _vsn) ->
137 return $ info { _foreign = Module.Canonical pkg name : _foreign info }
140 return info -- must be native
147isFresh :: Time.UTCTime -> FilePath -> IO Bool
148isFresh srcTime elmi =
150 [ Dir.doesFileExist elmi
151 , do elmiTime <- Dir.getModificationTime elmi
152 return (elmiTime >= srcTime)
156andM :: [IO Bool] -> IO Bool
162 check : otherChecks ->
164 if bool then andM otherChecks else return False
167remove :: FilePath -> IO ()
169 do exists <- Dir.doesFileExist path
170 when exists (Dir.removeFile path)
178 = EndLoop (Dict Info)
179 | Get Module.Canonical FilePath
182ifaceLoader :: Chan Msg -> Module.Interfaces -> IO (Dict Info, Module.Interfaces)
183ifaceLoader queue ifaces =
184 do msg <- readChan queue
187 return ( dirty, ifaces )
189 Get canonical elmi ->
190 case Map.lookup canonical ifaces of
192 ifaceLoader queue ifaces
195 do iface <- Binary.decodeFile elmi
196 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