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
|
module CPM.Repository.CacheFile
( readRepository )
where
import Data.Maybe ( maybeToList, listToMaybe )
import System.Directory ( doesFileExist )
import System.IO
import ReadShowTerm ( showQTerm, readQTerm, showTerm, readUnqualifiedTerm )
import CPM.Config ( Config, repositoryDir )
import CPM.ConfigPackage ( packageVersion )
import CPM.ErrorLogger
import CPM.Package
import CPM.Repository
readRepository :: Config -> Bool -> ErrorLogger Repository
readRepository cfg large = do
warnIfRepositoryOld cfg
mbrepo <- readRepositoryCache cfg large
case mbrepo of
Nothing -> do
repo <- readRepositoryFrom (repositoryDir cfg)
logInfo $ "Writing " ++ (if large then "large" else "base") ++
" repository cache..."
liftIOEL $ writeRepositoryCache cfg large repo
return repo
Just repo -> return repo
repositoryCache :: Config -> Bool -> String
repositoryCache cfg large =
repositoryCacheFilePrefix cfg ++ (if large then "_LARGE" else "_SMALL")
repoCacheVersion :: String
repoCacheVersion = packageVersion ++ "-1"
writeRepositoryCache :: Config -> Bool -> Repository -> IO ()
writeRepositoryCache cfg large repo =
writeFile (repositoryCache cfg large) $ unlines $
repoCacheVersion :
map (if large then showTerm . package2largetuple
else showTerm . package2smalltuple)
(allPackages repo)
where
package2smalltuple p =
( name p, version p, dependencies p, compilerCompatibility p )
package2largetuple p =
(package2smalltuple p,
(synopsis p, category p, sourceDirs p, exportedModules p,
listToMaybe (executableSpec p)))
readRepositoryCache :: Config -> Bool -> ErrorLogger (Maybe Repository)
readRepositoryCache cfg large = do
let cf = repositoryCache cfg large
excache <- liftIOEL $ doesFileExist cf
if excache
then do logDebug ("Reading repository cache from '" ++ cf ++ "'...")
((if large
then readTermInCacheFile cfg (largetuple2package . uread) cf
else readTermInCacheFile cfg (smalltuple2package . uread) cf)
>>= \repo ->
logDebug "Finished reading repository cache" >> return repo)
<|>
(do logInfo "Cleaning broken repository cache..."
cleanRepositoryCache cfg
return Nothing )
else return Nothing
where
uread s = readUnqualifiedTerm ["CPM.Package","Prelude"] s
smalltuple2package (nm,vs,dep,cmp) =
emptyPackage { name = nm
, version = vs
, dependencies = dep
, compilerCompatibility = cmp
}
largetuple2package (basics,(sy,cat,srcs,exps,exec)) =
(smalltuple2package basics)
{ synopsis = sy
, category = cat
, sourceDirs = srcs
, exportedModules = exps
, executableSpec = maybeToList exec
}
readTermInCacheFile :: Config -> (String -> Package) -> String
-> ErrorLogger (Maybe Repository)
readTermInCacheFile cfg trans cf = do
h <- liftIOEL $ openFile cf ReadMode
pv <- liftIOEL $ hGetLine h
if pv == repoCacheVersion
then liftIOEL (hGetContents h) >>= \t ->
return $!! Just (pkgsToRepository (map trans (lines t)))
else do logInfo "Cleaning repository cache (wrong version)..."
cleanRepositoryCache cfg
return Nothing
|