@@ -9,30 +9,26 @@ import Control.Concurrent.MVar (MVar, newMVar, newEmptyMVar, putMVar, readMVar,
9import Control.Monad (filterM, void)
9import Control.Monad (filterM, void)
10import Control.Monad.Trans (liftIO)
10import Control.Monad.Trans (liftIO)
11import qualified Data.Map as Map
11import qualified Data.Map as Map
12−import qualified Data.Set as Set
13import qualified Data.Map.Merge.Strict as Map
12import qualified Data.Map.Merge.Strict as Map
15−import Data.Set (Set)
13+import qualified Data.Set as Set
16import System.Directory (doesDirectoryExist)
14import System.Directory (doesDirectoryExist)
17import System.FilePath ((</>))
15import System.FilePath ((</>))
19−import qualified Elm.Compiler.Objects as Obj
20−import qualified Elm.Docs as Docs
21−import qualified Elm.Interface as I
22−import qualified Elm.ModuleName as ModuleName
23−import Elm.Package (Name, Version)
24−import qualified Elm.PerUserCache as PerUserCache
25−import Elm.Project.Json (Project(..), AppInfo(..), PkgInfo(..))
26−import qualified Json.Encode as Encode
28import qualified Deps.Cache as Cache
17import qualified Deps.Cache as Cache
29import qualified Deps.Explorer as Explorer
18import qualified Deps.Explorer as Explorer
30import qualified Deps.Solver as Solver
19import qualified Deps.Solver as Solver
31import qualified Deps.Website as Website
20import qualified Deps.Website as Website
32import qualified Elm.Compiler as Compiler
21import qualified Elm.Compiler as Compiler
22+import qualified Elm.Compiler.Objects as Obj
23+import qualified Elm.Constraint as Con
24+import qualified Elm.Interface as I
25+import qualified Elm.ModuleName as ModuleName
26+import qualified Elm.Package as Pkg
27+import qualified Elm.PerUserCache as PerUserCache
28+import Elm.Project.Json (Project(..), AppInfo(..), PkgInfo(..))
33import qualified Elm.Project.Json as Project
29import qualified Elm.Project.Json as Project
34−import qualified Elm.Project.Constraint as Con
35import qualified Elm.Project.Summary as Summary
30import qualified Elm.Project.Summary as Summary
31+import qualified Elm.Version as V
36import qualified File.Args as Args
32import qualified File.Args as Args
37import qualified File.Compile as Compile
33import qualified File.Compile as Compile
38import qualified File.Crawl as Crawl
34import qualified File.Crawl as Crawl
@@ -70,9 +66,9 @@ throw exit =
70-- VERIFY APP
66-- VERIFY APP
73−verifyApp :: AppInfo -> Task.Task (Map Name Version)
69+verifyApp :: AppInfo -> Task.Task (Map.Map Pkg.Name V.Version)
74verifyApp info =
70verifyApp info =
75− if _app_elm_version info /= Compiler.version then
71+ if _app_elm_version info /= V.compiler then
76 throw (E.AppBadElm (_app_elm_version info))
72 throw (E.AppBadElm (_app_elm_version info))
@@ -95,7 +91,7 @@ verifyApp info =
95-- VERIFY PKG
91-- VERIFY PKG
98−verifyPkg :: PkgInfo -> Task.Task (Map Name Version)
94+verifyPkg :: PkgInfo -> Task.Task (Map.Map Pkg.Name V.Version)
99verifyPkg info =
95verifyPkg info =
100 if not (Con.goodElm (_pkg_elm_version info)) then
96 if not (Con.goodElm (_pkg_elm_version info)) then
101 throw (E.PkgBadElm (_pkg_elm_version info))
97 throw (E.PkgBadElm (_pkg_elm_version info))
@@ -117,19 +113,19 @@ verifyPkg info =
117-- APP TO SOLUTION
113-- APP TO SOLUTION
120−appToSolution :: Project.AppInfo -> Task.Task (Map Name Version)
116+appToSolution :: Project.AppInfo -> Task.Task (Map.Map Pkg.Name V.Version)
121appToSolution (Project.AppInfo _ _ depsDirect depsTrans testDirect testTrans) =
117appToSolution (Project.AppInfo _ _ depsDirect depsTrans testDirect testTrans) =
122 do a <- union allowEqualDups depsTrans testDirect
118 do a <- union allowEqualDups depsTrans testDirect
123 b <- union noDups depsDirect testTrans
119 b <- union noDups depsDirect testTrans
124 union noDups a b
120 union noDups a b
127−noDups :: Name -> a -> a -> Task.Task a
123+noDups :: Pkg.Name -> a -> a -> Task.Task a
128noDups _ _ _ =
124noDups _ _ _ =
129 throw E.BadDeps
125 throw E.BadDeps
132−allowEqualDups :: Name -> Version -> Version -> Task.Task Version
128+allowEqualDups :: Pkg.Name -> V.Version -> V.Version -> Task.Task V.Version
133allowEqualDups _ v1 v2 =
129allowEqualDups _ v1 v2 =
134 if v1 == v2 then
130 if v1 == v2 then
135 return v1
131 return v1
@@ -137,7 +133,7 @@ allowEqualDups _ v1 v2 =
137 throw E.BadDeps
133 throw E.BadDeps
140−union :: (Name -> a -> a -> Task.Task a) -> Map Name a -> Map Name a -> Task.Task (Map Name a)
136+union :: (Pkg.Name -> a -> a -> Task.Task a) -> Map.Map Pkg.Name a -> Map.Map Pkg.Name a -> Task.Task (Map.Map Pkg.Name a)
141union tieBreaker deps1 deps2 =
137union tieBreaker deps1 deps2 =
142 Map.mergeA Map.preserveMissing Map.preserveMissing (Map.zipWithAMatched tieBreaker) deps1 deps2
138 Map.mergeA Map.preserveMissing Map.preserveMissing (Map.zipWithAMatched tieBreaker) deps1 deps2
@@ -146,13 +142,13 @@ union tieBreaker deps1 deps2 =
146-- VERIFY ARTIFACTS
142-- VERIFY ARTIFACTS
149−verifyArtifacts :: Map Name Version -> Task.Task RawInfo
145+verifyArtifacts :: Map.Map Pkg.Name V.Version -> Task.Task RawInfo
150verifyArtifacts solution =
146verifyArtifacts solution =
151 do Website.download =<< filterM noSrc (Map.toList solution)
147 do Website.download =<< filterM noSrc (Map.toList solution)
152 verifyBuildArtifacts solution
148 verifyBuildArtifacts solution
155−noSrc :: (Name, Version) -> Task.Task Bool
151+noSrc :: (Pkg.Name, V.Version) -> Task.Task Bool
156noSrc (name, version) =
152noSrc (name, version) =
157 do root <- Task.getPackageCacheDirFor name version
153 do root <- Task.getPackageCacheDirFor name version
158 liftIO $ not <$> doesDirectoryExist (root </> "src")
154 liftIO $ not <$> doesDirectoryExist (root </> "src")
@@ -162,7 +158,7 @@ noSrc (name, version) =
162-- VERIFY BUILD ARTIFACTS
158-- VERIFY BUILD ARTIFACTS
165−verifyBuildArtifacts :: Map Name Version -> Task.Task RawInfo
161+verifyBuildArtifacts :: Map.Map Pkg.Name V.Version -> Task.Task RawInfo
166verifyBuildArtifacts solution =
162verifyBuildArtifacts solution =
167 do Task.report (Progress.BuildDepsStart (Map.size solution))
163 do Task.report (Progress.BuildDepsStart (Map.size solution))
168 startMVar <- liftIO newEmptyMVar
164 startMVar <- liftIO newEmptyMVar
@@ -177,14 +173,14 @@ verifyBuildArtifacts solution =
179data RawInfo =
175data RawInfo =
180− RawInfo (Map Name PkgInfo) I.Interfaces
176+ RawInfo (Map.Map Pkg.Name PkgInfo) I.Interfaces
183verifyBuild
179verifyBuild
184− :: MVar (Map Name (MVar Answer))
180+ :: MVar (Map.Map Pkg.Name (MVar Answer))
185 -> MVar I.Interfaces
181 -> MVar I.Interfaces
186− -> Name
182+ -> Pkg.Name
187− -> Version
183+ -> V.Version
188 -> Task.Task (MVar Answer)
184 -> Task.Task (MVar Answer)
189verifyBuild pkgInfoMVar ifacesMVar name version =
185verifyBuild pkgInfoMVar ifacesMVar name version =
190 do mvar <- liftIO newEmptyMVar
186 do mvar <- liftIO newEmptyMVar
@@ -223,10 +219,10 @@ verifyBuild pkgInfoMVar ifacesMVar name version =
223data Answer
219data Answer
224 = Ok PkgInfo
220 = Ok PkgInfo
225 | Blocked
221 | Blocked
226− | Err Name Version
222+ | Err Pkg.Name V.Version
229−toInfo :: Name -> Answer -> Task.Task (Maybe PkgInfo)
225+toInfo :: Pkg.Name -> Answer -> Task.Task (Maybe PkgInfo)
230toInfo _ answer =
226toInfo _ answer =
231 case answer of
227 case answer of
232 Ok info ->
228 Ok info ->
@@ -240,7 +236,7 @@ toInfo _ answer =
240 throw (E.BuildFailure elmHome name version)
236 throw (E.BuildFailure elmHome name version)
243−ifNotBlocked :: Map Name Answer -> (Map Name PkgInfo -> IO Answer) -> IO Answer
239+ifNotBlocked :: Map.Map Pkg.Name Answer -> (Map.Map Pkg.Name PkgInfo -> IO Answer) -> IO Answer
244ifNotBlocked answers callback =
240ifNotBlocked answers callback =
245 case traverse isOk answers of
241 case traverse isOk answers of
246 Nothing ->
242 Nothing ->
@@ -263,32 +259,30 @@ isOk answer =
266− :: Name
262+ :: Pkg.Name
267− -> Version
263+ -> V.Version
268 -> PkgInfo
264 -> PkgInfo
269− -> Map Name PkgInfo
265+ -> Map.Map Pkg.Name PkgInfo
270 -> I.Interfaces
266 -> I.Interfaces
271 -> Task.Task I.Interfaces
267 -> Task.Task I.Interfaces
272getIface name version info infos depIfaces =
268getIface name version info infos depIfaces =
273 do root <- Task.getPackageCacheDirFor name version
269 do root <- Task.getPackageCacheDirFor name version
274 let solution = Map.map _pkg_version infos
270 let solution = Map.map _pkg_version infos
276− cached <- isCached root solution
272+ cached <- liftIO $ isCached root solution
278 if cached
274 if cached
279− then IO.readBinary (root </> "ifaces.dat")
276+ do maybeIfaces <- liftIO $ IO.readBinary (root </> "ifaces.dat")
277+ maybe (Task.throw (error "TODO corrupt binary 1")) return maybeIfaces
281 do Paths.removeStuff root
279 do Paths.removeStuff root
282− let docsPath = root </> "docs.json"
284 let summary = Summary.cheapInit root info infos depIfaces
280 let summary = Summary.cheapInit root info infos depIfaces
285 args <- Args.fromSummary summary
281 args <- Args.fromSummary summary
286 graph <- Crawl.crawl summary args
282 graph <- Crawl.crawl summary args
287− (dirty, cachedIfaces) <- Plan.plan (Just docsPath) summary graph
283+ (dirty, cachedIfaces) <- Plan.plan summary graph
288− answers <- Compile.compile (Pkg info) (Just docsPath) cachedIfaces dirty
284+ answers <- Compile.compile (Pkg info) cachedIfaces dirty
289 results <- Artifacts.ignore answers
285 results <- Artifacts.ignore answers
290− _ <- Artifacts.writeDocs results docsPath
292 Paths.removeStuff root
286 Paths.removeStuff root
294 updateCache root name info solution graph results
288 updateCache root name info solution graph results
@@ -298,25 +292,29 @@ getIface name version info infos depIfaces =
298-- IS CACHED?
292-- IS CACHED?
301−isCached :: FilePath -> Map Name Version -> Task.Task Bool
295+isCached :: FilePath -> Map.Map Pkg.Name V.Version -> IO Bool
302isCached root solution =
296isCached root solution =
304 [ IO.exists (root </> "cached.dat")
298 [ IO.exists (root </> "cached.dat")
305 , IO.exists (root </> "ifaces.dat")
299 , IO.exists (root </> "ifaces.dat")
306 , IO.exists (root </> "objs.dat")
300 , IO.exists (root </> "objs.dat")
307− , IO.exists (root </> "documentation.json")
308 , isCachedHelp solution <$> IO.readBinary (root </> "cached.dat")
301 , isCachedHelp solution <$> IO.readBinary (root </> "cached.dat")
312−isCachedHelp :: Map Name Version -> Map Name (Set Version) -> Bool
305+isCachedHelp :: Map.Map Pkg.Name V.Version -> Maybe (Map.Map Pkg.Name (Set.Set V.Version)) -> Bool
313−isCachedHelp solution cachedDeps =
306+isCachedHelp solution maybeCachedDeps =
307+ case maybeCachedDeps of
315− matches =
313+ matches =
316− Map.intersectionWith Set.member solution cachedDeps
314+ Map.intersectionWith Set.member solution cachedDeps
318− Map.size solution == Map.size matches
316+ Map.size solution == Map.size matches
319− && Map.foldr (&&) True matches
317+ && Map.foldr (&&) True matches
@@ -325,35 +323,31 @@ isCachedHelp solution cachedDeps =
326updateCache
324updateCache
327 :: FilePath
325 :: FilePath
328− -> Name
326+ -> Pkg.Name
329 -> PkgInfo
327 -> PkgInfo
330− -> Map Name Version
328+ -> Map.Map Pkg.Name V.Version
331 -> Crawl.Result
329 -> Crawl.Result
332− -> Map ModuleName.Raw Compiler.Artifacts
330+ -> Map.Map ModuleName.Raw Compiler.Artifacts
333 -> Task.Task I.Interfaces
331 -> Task.Task I.Interfaces
334updateCache root name info solution graph results =
332updateCache root name info solution graph results =
335 do let path = root </> "cached.dat"
333 do let path = root </> "cached.dat"
336 let deps = Map.map Set.singleton solution
334 let deps = Map.map Set.singleton solution
337 let elmi = crush name info results
335 let elmi = crush name info results
339− exists <- IO.exists path
337+ exists <- liftIO $ IO.exists path
341 if exists
339 if exists
343− do oldDeps <- IO.readBinary path
341+ do maybeOldDeps <- liftIO $ IO.readBinary path
342+ oldDeps <- maybe (error "TODO corrupt binary 2") return maybeOldDeps
344− IO.writeBinary path (Map.unionWith Set.union deps oldDeps)
343+ liftIO $ IO.writeBinary path (Map.unionWith Set.union deps oldDeps)
346 do IO.writeBinary (root </> "ifaces.dat") elmi
346 do IO.writeBinary (root </> "ifaces.dat") elmi
348 IO.writeBinary path deps
347 IO.writeBinary path deps
350 IO.writeBinary (root </> "objs.dat") $
348 IO.writeBinary (root </> "objs.dat") $
351 Map.foldr addGraph (objGraphFromKernels graph) results
349 Map.foldr addGraph (objGraphFromKernels graph) results
353− liftIO $ Encode.writeUgly (root </> "documentation.json") $
354− Encode.list Docs.encode $
355− Map.foldr addDocs [] results
357 return elmi
351 return elmi
@@ -361,7 +355,7 @@ updateCache root name info solution graph results =
361-- CRUSH INTERFACES
355-- CRUSH INTERFACES
364−crush :: Name -> PkgInfo -> Map ModuleName.Raw Compiler.Artifacts -> I.Interfaces
358+crush :: Pkg.Name -> PkgInfo -> Map.Map ModuleName.Raw Compiler.Artifacts -> I.Interfaces
365crush pkg info results =
359crush pkg info results =
367 exposed =
361 exposed =
@@ -371,8 +365,8 @@ crush pkg info results =
371 Map.mapMaybeWithKey (crushHelp exposed) results
365 Map.mapMaybeWithKey (crushHelp exposed) results
374−crushHelp :: Set ModuleName.Raw -> ModuleName.Raw -> Compiler.Artifacts -> Maybe I.Interface
368+crushHelp :: Set.Set ModuleName.Raw -> ModuleName.Raw -> Compiler.Artifacts -> Maybe I.Interface
375−crushHelp exposed name (Compiler.Artifacts elmi _ _) =
369+crushHelp exposed name (Compiler.Artifacts elmi _) =
376 if Set.member name exposed then
370 if Set.member name exposed then
377 Just elmi
371 Just elmi
@@ -381,25 +375,11 @@ crushHelp exposed name (Compiler.Artifacts elmi _ _) =
387−addDocs :: Compiler.Artifacts -> [Docs.Module] -> [Docs.Module]
388−addDocs (Compiler.Artifacts _ _ maybeDocs) docsList =
398-- OBJECT GRAPH
378-- OBJECT GRAPH
401addGraph :: Compiler.Artifacts -> Obj.Graph -> Obj.Graph
381addGraph :: Compiler.Artifacts -> Obj.Graph -> Obj.Graph
402−addGraph (Compiler.Artifacts _ elmo _) graph =
382+addGraph (Compiler.Artifacts _ elmo) graph =
403 Obj.union elmo graph
383 Obj.union elmo graph