@@ -1,25 +1,28 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3−module Deps.Get
3+module Deps.Cache
5− , AllPackages
5+ , optionalUpdate
6− , Mode(..)
6+ , mandatoryUpdate
7− , versions
7+ , PackageRegistry
8− , info
8+ , getPackageRegistry
9− , docs
9+ , getVersions
14import Prelude hiding (all)
16import Prelude hiding (all)
17+import Control.Monad (liftM2)
15import Control.Monad.Except (catchError, liftIO)
18import Control.Monad.Except (catchError, liftIO)
19+import Data.Binary (Binary, get, put)
16import qualified Data.ByteString as BS
20import qualified Data.ByteString as BS
17import Data.Function (on)
21import Data.Function (on)
18import qualified Data.List as List
22import qualified Data.List as List
19import qualified Data.Map as Map
23import qualified Data.Map as Map
20import Data.Map (Map)
24import Data.Map (Map)
21import qualified Data.Text as Text
25import qualified Data.Text as Text
22−import qualified System.Directory as Dir
23import System.FilePath ((</>))
26import System.FilePath ((</>))
25import qualified Elm.Docs as Docs
28import qualified Elm.Docs as Docs
@@ -38,53 +41,91 @@ import qualified Reporting.Task as Task
41−-- ALL VERSIONS
44+-- PACKAGE REGISTRY
44−data Mode = RequireLatest | AllowOffline
47+data PackageRegistry =
48+ PackageRegistry Int (Map Pkg.Name [Pkg.Version])
47−newtype AllPackages = AllPackages (Map Pkg.Name [Pkg.Version])
51+getPackageRegistry :: Task.Task PackageRegistry
53+ do path <- getRegistryPath
54+ exists <- IO.exists path
56+ then IO.readBinary path
50−all :: Mode -> Task.Task AllPackages
60+getRegistryPath :: Task.Task FilePath
51−all mode =
61+getRegistryPath =
52 do dir <- Task.getPackageCacheDir
62 do dir <- Task.getPackageCacheDir
53− let versionsFile = dir </> "versions.dat"
63+ return (dir </> "versions.dat")
54− exists <- liftIO $ Dir.doesFileExist versionsFile
64+
56− then fetchNew versionsFile mode
66+
57− else fetchAll versionsFile
67+-- REBUILD
60−fetchAll :: FilePath -> Task.Task AllPackages
70+rebuild :: Task.Task PackageRegistry
61−fetchAll versionsFile =
71+rebuild =
72+ do path <- getRegistryPath
62− do packages <- Website.getAllPackages
73+ packages <- Website.getAllPackages
63 let size = Map.foldr ((+) . length) 0 packages
74 let size = Map.foldr ((+) . length) 0 packages
75+ let registry = PackageRegistry size packages
64− IO.writeBinary versionsFile (size, packages)
76+ IO.writeBinary path registry
65− return (AllPackages packages)
77+ return registry
68−fetchNew :: FilePath -> Mode -> Task.Task AllPackages
69−fetchNew versionsFile mode =
70− do (size, packages) <- IO.readBinary versionsFile
75− Website.getNewPackages size
78− Website.getNewPackages size `catchError` \_ ->
79− do Task.report Progress.UnableToLoadLatestPackages
82− if null news
84+optionalUpdate :: Task.Task PackageRegistry
83− then return (AllPackages packages)
85+optionalUpdate =
89+mandatoryUpdate :: Task.Task PackageRegistry
94+update :: Bool -> Task.Task PackageRegistry
96+ do path <- getRegistryPath
97+ exists <- IO.exists path
101+ do registry <- IO.readBinary path
103+ then attemptUpdate registry
104+ else attemptUpdate registry `catchError` recoverUpdate registry
107+recoverUpdate :: PackageRegistry -> a -> Task.Task PackageRegistry
108+recoverUpdate registry _ =
109+ do Task.report Progress.UnableToLoadLatestPackages
113+attemptUpdate :: PackageRegistry -> Task.Task PackageRegistry
114+attemptUpdate oldRegistry@(PackageRegistry size packages) =
115+ do news <- Website.getNewPackages size
122+ newSize = size + length news
85− do let newAllPkgs = List.foldl' addNew packages news
123+ newPkgs = List.foldl' addNew packages news
86− IO.writeBinary versionsFile (size + length news, newAllPkgs)
124+ newRegistry = PackageRegistry newSize newPkgs
87− return (AllPackages newAllPkgs)
125+ in
126+ do path <- getRegistryPath
127+ IO.writeBinary path newRegistry
90addNew :: Map Pkg.Name [Pkg.Version] -> (Pkg.Name, Pkg.Version) -> Map Pkg.Name [Pkg.Version]
131addNew :: Map Pkg.Name [Pkg.Version] -> (Pkg.Name, Pkg.Version) -> Map Pkg.Name [Pkg.Version]
@@ -93,11 +134,11 @@ addNew packages (name, version) =
96−-- VERSIONS
137+-- GET VERSIONS
99−versions :: Pkg.Name -> AllPackages -> Either [Pkg.Name] [Pkg.Version]
140+getVersions :: Pkg.Name -> PackageRegistry -> Either [Pkg.Name] [Pkg.Version]
100−versions name (AllPackages pkgs) =
141+getVersions name (PackageRegistry _ pkgs) =
101 case Map.lookup name pkgs of
142 case Map.lookup name pkgs of
102 Just vsns ->
143 Just vsns ->
103 Right vsns
144 Right vsns
@@ -137,12 +178,12 @@ projectDistance bad possibility =
137-- PACKAGE INFO
178-- PACKAGE INFO
140−info :: Pkg.Name -> Pkg.Version -> Task.Task Project.PkgInfo
181+getElmJson :: Pkg.Name -> Pkg.Version -> Task.Task Project.PkgInfo
141−info name version =
182+getElmJson name version =
142 do dir <- Task.getPackageCacheDirFor name version
183 do dir <- Task.getPackageCacheDirFor name version
143 let elmJson = dir </> "elm.json"
184 let elmJson = dir </> "elm.json"
145− exists <- liftIO $ Dir.doesFileExist elmJson
186+ exists <- IO.exists elmJson
148 if exists
189 if exists
@@ -165,12 +206,12 @@ info name version =
168−docs :: Pkg.Name -> Pkg.Version -> Task.Task Docs.Documentation
209+getDocs :: Pkg.Name -> Pkg.Version -> Task.Task Docs.Documentation
169−docs name version =
210+getDocs name version =
170 do dir <- Task.getPackageCacheDirFor name version
211 do dir <- Task.getPackageCacheDirFor name version
171 let docsJson = dir </> "docs.json"
212 let docsJson = dir </> "docs.json"
173− exists <- liftIO $ Dir.doesFileExist docsJson
214+ exists <- IO.exists docsJson
176 if exists
217 if exists
@@ -209,3 +250,12 @@ errorToDocs err =
209 ,"<https://github.com/elm-lang/package.elm-lang.org/issues>"
250 ,"<https://github.com/elm-lang/package.elm-lang.org/issues>"
210 ,"if","you","think","it","is","on","the","Elm","side!"
251 ,"if","you","think","it","is","on","the","Elm","side!"
259+instance Binary PackageRegistry where
260+ get = liftM2 PackageRegistry get get
261+ put (PackageRegistry a b) = put a >> put b