1 module Main (main) where
3 import qualified Codec.Compression.GZip as GZip
5 import qualified Data.ByteString.Lazy as Lazy
9 import Distribution.Package
10 import Distribution.PackageDescription
11 import Distribution.Query
13 import System.Directory
14 import System.FilePath
15 import System.FilePath.Glob
16 import Text.ParserCombinators.ReadP
19 indexURL = "http://hackage.haskell.org/packages/archive/00-index.tar.gz"
22 pkgsrcPath = "/usr/pkgsrc"
25 main = do appDir <- getAppUserDataDirectory "pkg-find-outdated-cabal"
26 createDirectoryIfMissing False appDir
28 let indexFile = appDir </> "00-index.tar.gz"
30 putStrLn "Downloading the Hackage index..."
33 runIO ("wget", ["-N", indexURL])
37 indexBin <- fmap GZip.decompress $ Lazy.readFile indexFile
38 let runQuery q = queryIndex q indexBin
40 makefiles <- namesMatching (pkgsrcPath </> "*" </> "*" </> "Makefile")
41 scanPkgs runQuery makefiles
43 scanPkgs :: (Query -> [PackageDescription]) -> [FilePath] -> IO ()
44 scanPkgs runQuery = mapM_ scanPkg
46 scanPkg :: FilePath -> IO ()
48 = do mak <- readFile makPath
49 case grep "mk/haskell.mk" (lines mak) of
53 checkPkg :: String -> IO ()
55 = case grep "DISTNAME=" (lines mak) of
56 [l] -> let line = (trd ' ' . trd '\t') l
57 distname = cut 1 '=' line
58 name = extractPkgName distname
59 ver = extractPkgVersion distname
60 pkgId = PackageIdentifier name ver
61 query = Id (sameName pkgId) :& Id (newerVers pkgId)
63 case runQuery query of
64 [] -> putStrLn (distname ++ ": is the LATEST")
65 xs -> let sorted = sortBy cmpVers xs
67 lVer = (pkgVersion . package) latest
69 putStrLn (distname ++ ": has a newer version " ++ showVersion lVer)
72 sameName :: PackageIdentifier -> PackageIdentifier -> Bool
73 sameName a b = pkgName a == pkgName b
75 newerVers :: PackageIdentifier -> PackageIdentifier -> Bool
76 newerVers a b = pkgVersion a < pkgVersion b
78 cmpVers :: PackageDescription -> PackageDescription -> Ordering
79 cmpVers a b = (pkgVersion . package) a `compare` (pkgVersion . package) b
81 extractPkgName :: String -> PackageName
82 extractPkgName = PackageName . head . split "-"
84 extractPkgVersion :: String -> Version
85 extractPkgVersion = take' . readP_to_S parseVersion . last . split "-"
87 take' ((v, ""):_ ) = v
88 take' (_ :xs) = take' xs
89 take' [] = error "Unparsable version"