1 {-# LANGUAGE PatternGuards #-}
3 module Main (main) where
5 import Control.Monad.State
8 import System.Environment
16 -- * Check installed trees too
19 -- Only size changes > sizeAbs are considered an issue
23 -- Only a size change of sizePercentage% or more is considered an issue
24 sizePercentage :: Integer
28 main = do args <- getArgs
30 [bd1, bd2] -> doit bd1 bd2
31 _ -> die ["Bad args. Need 2 bindists."]
33 doit :: FilePath -> FilePath -> IO ()
35 = do tls1 <- readTarLines bd1
36 tls2 <- readTarLines bd2
37 content1 <- dieOnErrors $ mkContents tls1
38 content2 <- dieOnErrors $ mkContents tls2
39 let mySort = sortBy (compare `on` fst)
40 sortedContent1 = mySort content1
41 sortedContent2 = mySort content2
42 (nubProbs1, nubbedContent1) = nubContents sortedContent1
43 (nubProbs2, nubbedContent2) = nubContents sortedContent2
44 differences = compareContent nubbedContent1
46 allProbs = map First nubProbs1 ++ map Second nubProbs2
48 mapM_ (putStrLn . pprFileProblem) allProbs
50 mkContents :: [TarLine] -> Either Errors [(FilenameDescr, TarLine)]
51 mkContents tls = case runState (mapM f tls) [] of
53 case concat $ map (checkContent mapping) xs of
56 where f tl = do fnd <- mkFilePathDescr (tlFileName tl)
59 nubContents :: [(FilenameDescr, TarLine)]
60 -> ([Problem], [(FilenameDescr, TarLine)])
61 nubContents [] = ([], [])
62 nubContents [x] = ([], [x])
63 nubContents (x1@(fd1, tl1) : xs@((fd2, _) : _))
64 | fd1 == fd2 = (DuplicateFile (tlFileName tl1) : ps, xs')
65 | otherwise = (ps, x1 : xs')
66 where (ps, xs') = nubContents xs
68 mkFilePathDescr :: FilePath -> State ThingVersionMap FilenameDescr
70 | Just [ghcVersion, _, middle, filename]
71 <- re ("^ghc-" ++ versionRE ++ "(/.*)?/([^/]*)$") fp
72 = do ghcVersionDescr <- do mapping <- get
73 case addThingVersion mapping "ghc" ghcVersion of
76 return (VersionOf "ghc")
78 return (FP ghcVersion)
79 filename' <- mkFileNameDescr filename
80 let fd = FP "ghc-" : ghcVersionDescr : FP middle : FP "/" : filename'
82 | otherwise = return [FP fp]
84 mkFileNameDescr :: FilePath -> State ThingVersionMap FilenameDescr
85 mkFileNameDescr filename
86 | Just [thing, thingVersion, _, ghcVersion, _]
87 <- re ("^libHS(.*)-" ++ versionRE ++ "-ghc" ++ versionRE ++ "\\.so$")
90 case addThingVersion mapping "ghc" ghcVersion of
92 case addThingVersion m thing thingVersion of
95 return [FP "libHS", FP thing, FP "-", VersionOf thing,
96 FP "-ghc", VersionOf "ghc", FP ".so"]
99 | Just [way, thingVersion, _]
100 <- re ("^libHSrts(_.*)?-ghc" ++ versionRE ++ "\\.so$")
103 case addThingVersion mapping "ghc" thingVersion of
106 return [FP "libHSrts", FP way, FP "-ghc", VersionOf "ghc",
109 | Just [thing, thingVersion, _, way]
110 <- re ("^libHS(.*)-" ++ versionRE ++ "(_.*)?\\.a$")
113 case addThingVersion mapping thing thingVersion of
116 return [FP "libHS", FP thing, FP "-", VersionOf thing,
119 | Just [thing, thingVersion, _]
120 <- re ("^HS(.*)-" ++ versionRE ++ "\\.o$")
123 case addThingVersion mapping thing thingVersion of
126 return [FP "HS", FP thing, FP "-", VersionOf thing,
129 | otherwise = unchanged
130 where unchanged = return [FP filename]
132 compareContent :: [(FilenameDescr, TarLine)] -> [(FilenameDescr, TarLine)]
134 compareContent [] [] = []
135 compareContent xs [] = map (First . ExtraFile . tlFileName . snd) xs
136 compareContent [] ys = map (Second . ExtraFile . tlFileName . snd) ys
137 compareContent xs1@((fd1, tl1) : xs1') xs2@((fd2, tl2) : xs2')
138 = case fd1 `compare` fd2 of
139 EQ -> map Change (compareTarLine tl1 tl2) ++ compareContent xs1' xs2'
140 LT -> First (ExtraFile (tlFileName tl1)) : compareContent xs1' xs2
141 GT -> Second (ExtraFile (tlFileName tl2)) : compareContent xs1 xs2'
143 compareTarLine :: TarLine -> TarLine -> [Problem]
144 compareTarLine tl1 tl2
145 = [ PermissionsChanged fn1 fn2 perms1 perms2 | perms1 /= perms2 ]
146 ++ [ FileSizeChanged fn1 fn2 size1 size2 | sizeChanged ]
147 where fn1 = tlFileName tl1
149 perms1 = tlPermissions tl1
150 perms2 = tlPermissions tl2
153 sizeChanged = abs (size1 - size2) > sizeAbs
154 && (((100 * size1) `div` size2) > sizePercentage ||
155 ((100 * size2) `div` size1) > sizePercentage)
158 versionRE = "([0-9]+(\\.[0-9]+)*)"