-
Notifications
You must be signed in to change notification settings - Fork 0
/
Changes.hs
129 lines (113 loc) · 3.92 KB
/
Changes.hs
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
{-# LANGUAGE OverloadedStrings #-}
-- "Find differences between package versions."
import Control.Applicative
import Control.Monad
import Data.List
import Data.Monoid
import qualified Data.Text as DT
import qualified Data.Text.IO as DTI
import System.Environment
import Text.Printf
import Depcalc
main = do
progname <- getProgName
args <- getArgs
case (length args) of
2 -> printChanges Nothing (args !! 0) (args !! 1)
3 -> printChanges (Just $ args !! 2) (args !! 0) (args !! 1)
_ -> putStrLn $ usage progname
usage = printf "USAGE: %s pkgversions pkgversions [dependencies]"
getList = liftM (sort . map (DT.splitOn " ") . DT.lines) . DTI.readFile
data Changes = Changes
{ chNumAdded :: Int
, chNumDeleted :: Int
, chNumBumped :: Int
, chNumUpdated :: Int
, chAdded :: [[String]]
, chDeleted :: [[String]]
, chBumped :: [[String]]
, chUpdated :: [[String]]
}
printChanges z x y = computeChanges z x y >>= displayChanges
unpack = map (map DT.unpack)
normalize x = x'
where (_:x':_) = DT.splitOn "/hs-" x
getEffect fp (p:_) = calculateDependency fp backward (normalize p)
resolve :: [DT.Text] -> DT.Text -> DT.Text
resolve xs p =
case (find (s `DT.isInfixOf`) xs) of
Just y -> y
_ -> error (printf "This should not happen: %s" (show s))
where s = "/hs-" `DT.append` p
computeChanges deps x y = do
orig <- getList x
new <- getList y
let (deleted,added,misc) = findChanges orig new
let [numDeleted,numAdded] = length <$> [deleted,added]
(bumped,numBumped,updated,numUpdated) <-
case deps of
Just fp -> do
let (b',misc') = partition isBumped misc
let (u,_) = partition isUpdated misc'
affected <- (\\)
<$> (nub . concat <$> mapM (getEffect fp) u)
<*> pure (normalize . head <$> u)
let ub = sort (resolve (head <$> new) <$> affected)
let b = bump <$> filter ((`elem` ub) . head) orig
let [nb,nu] = length <$> [b,u]
return (b,nb,u,nu)
_ -> do
let (b,misc') = partition isBumped misc
let (u,_) = partition isUpdated misc'
let [nb,nu] = length <$> [b,u]
return (b,nb,u,nu)
return $ Changes
numAdded numDeleted numBumped numUpdated
(unpack added) (unpack deleted)
(unpack bumped) (unpack updated)
displayChanges :: Changes -> IO ()
displayChanges c = do
let numAdded = chNumAdded c
let added = chAdded c
when (numAdded > 0) (do
printf "New ports (%d):\n\n" numAdded
forM_ added $ \[p,v] -> do
printf "%-40s %s\n" p v)
let numBumped = chNumBumped c
let bumped = chBumped c
when (numBumped > 0) (do
printf "\n\n"
printf "Bumped ports (%d):\n\n" numBumped
forM_ bumped $ \[p,v1,v2] -> do
printf "%-40s %-16s --> %s\n" p v1 v2)
let numUpdated = chNumUpdated c
let updated = chUpdated c
when (numUpdated > 0) (do
printf "\n\n"
printf "Updated ports (%d):\n\n" numUpdated
forM_ updated $ \[p,v1,v2] -> do
printf "%-40s %-16s --> %s\n" p v1 v2)
let numDeleted = chNumDeleted c
let deleted = chDeleted c
when (numDeleted > 0) (do
printf "\n\n"
printf "Removed ports (%d):\n\n" numDeleted
forM_ deleted $ \[p,v] -> do
printf "%-40s %s\n" p v)
findChanges l1@((x@[nx,vx]):xs) l2@((y@[ny,vy]):ys)
| nx == ny = (mempty,mempty,[[nx,vx,vy]]) `mappend` findChanges xs ys
| nx < ny = ([x],mempty,mempty) `mappend` findChanges xs l2
| nx > ny = (mempty,[y],mempty) `mappend` findChanges l1 ys
findChanges [] ys = (mempty,ys,mempty)
findChanges xs [] = (xs,mempty,mempty)
isBumped [_,v1,v2] =
case (map (DT.splitOn "_") [v1,v2]) of
[[ver1],[ver2,_]] -> ver1 == ver2
[[ver1,r1],[ver2,r2]] -> ver1 == ver2 && r1 /= r2
_ -> False
isUpdated [_,v1,v2] = v1 /= v2
bump [p,v1] =
case ((DT.splitOn "_") v1) of
[_] -> [p,v1,v1 `DT.append` "_1"]
[ver,rev] -> [p,v1,DT.concat [ver,"_",rev']]
where rev' = DT.pack $ show (((read $ DT.unpack rev)) + 1)