cblrepo 0.2.3 → 0.3.0
raw patch · 14 files changed
+539/−250 lines, 14 filesdep ~test-frameworkdep ~test-framework-th
Dependency ranges changed: test-framework, test-framework-th
Files
- cblrepo.cabal +5/−4
- src/Add.hs +157/−0
- src/AddBase.hs +0/−50
- src/AddCabal.hs +0/−87
- src/ConvertDB.hs +58/−0
- src/ListPkgs.hs +3/−2
- src/Main.hs +24/−19
- src/OldPkgDB.hs +125/−0
- src/PkgDB.hs +108/−57
- src/PkgDB.hs-boot +0/−9
- src/Updates.hs +2/−2
- src/Util/Misc.hs +10/−7
- src/Util/Translation.hs +14/−7
- tst/TestPkgDB.hs +33/−6
cblrepo.cabal view
@@ -1,5 +1,5 @@ name: cblrepo-version: 0.2.3+version: 0.3.0 cabal-version: >= 1.6 license: OtherLicense license-file: LICENSE-2.0@@ -26,8 +26,9 @@ executable cblrepo hs-source-dirs: src main-is: Main.hs- other-modules: Util.Misc PkgDB AddBase AddCabal BumpPkgs BuildPkgs IdxSync+ other-modules: Util.Misc PkgDB Add BumpPkgs BuildPkgs IdxSync IdxVersion Updates ListPkgs Urls PkgBuild Util.Translation+ OldPkgDB ConvertDB build-depends: base ==4.3.*, cmdargs ==0.7.*, filepath ==1.2.*, directory ==1.1.*, Cabal ==1.10.*, json ==0.4.*, bytestring ==0.9.*, tar ==0.3.*, zlib ==0.5.*, mtl ==2.0.*,@@ -39,8 +40,8 @@ main-is: tst.hs other-modules: TestSystem TestPkgDB if flag(BuildTests)- build-depends: base ==4.3.*, test-framework-th ==0.1.*, HUnit ==1.2.*,- test-framework-hunit ==0.2.*, test-framework ==0.3.*+ build-depends: base ==4.3.*, test-framework-th ==0.2.*, HUnit ==1.2.*,+ test-framework-hunit ==0.2.*, test-framework ==0.4.* else buildable: False
+ src/Add.hs view
@@ -0,0 +1,157 @@+{-+ - Copyright 2011 Per Magnus Therning+ -+ - Licensed under the Apache License, Version 2.0 (the "License");+ - you may not use this file except in compliance with the License.+ - You may obtain a copy of the License at+ -+ - http://www.apache.org/licenses/LICENSE-2.0+ -+ - Unless required by applicable law or agreed to in writing, software+ - distributed under the License is distributed on an "AS IS" BASIS,+ - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ - See the License for the specific language governing permissions and+ - limitations under the License.+ -}++module Add where++import Debug.Trace++-- {{{1 imports+-- {{{2 local+import PkgDB+import Util.Misc++-- {{{2 system+import Codec.Archive.Tar as Tar+import Codec.Compression.GZip as GZip+import Control.Monad+import Control.Monad.Error+import Control.Monad.Reader+import Data.List+import Data.Maybe+import Data.Version+import Distribution.Compiler+import Distribution.PackageDescription+import Distribution.PackageDescription.Configuration+import Distribution.PackageDescription.Parse+import Distribution.System+import Distribution.Text+import Distribution.Verbosity+import Distribution.Version+import System.Directory+import System.FilePath+import qualified Data.ByteString.Lazy.Char8 as BS+import qualified Distribution.Package as P+import System.Posix.Files+import System.Unix.Directory+import System.Process+import System.Exit+import System.IO++-- {{{1 add+add :: ReaderT Cmds IO ()+add = do+ t <- cfgGet pkgType+ case t of+ GhcPkgT -> addGhc+ DistroPkgT -> addDistro+ RepoPkgT -> addRepo++-- {{{2 Add ghc package+addGhc :: ReaderT Cmds IO ()+addGhc = let+ unpackPkgVer s = (p, v)+ where+ (p, _:v) = span (/= ',') s+ in do+ pkgs <- liftM (map unpackPkgVer) (cfgGet cbls)+ dR <- cfgGet dryRun+ guard $ isJust $ (sequence $ map (simpleParse . snd) pkgs :: Maybe [Version])+ let ps = map (\ (n, v) -> (n, fromJust $ (simpleParse v :: Maybe Version))) pkgs+ dbFn <- cfgGet dbFile+ db <- liftIO $ readDb dbFn+ case doAddGhc db ps of+ Left brkOthrs -> liftIO $ mapM_ printBrksOth brkOthrs+ Right newDb -> liftIO $ unless dR $ saveDb newDb dbFn++doAddGhc db pkgs = let+ canBeAdded db n v = null $ checkDependants db n v+ (_, fails) = partition (\ (n, v) -> canBeAdded db n v) pkgs+ newDb = foldl (\ d (n, v) -> addGhcPkg d n v) db pkgs+ brkOthrs = map (\ (n, v) -> ((n, v), checkDependants db n v)) fails+ in if null fails+ then Right newDb+ else Left brkOthrs++-- {{{2 Add distro package+addDistro :: ReaderT Cmds IO ()+addDistro = let+ unpackPkgVer s = (p, v, r)+ where+ (p, _:s2) = span (/= ',') s+ (v, _:r) = span (/= ',') s2+ getVersion (_, v, _) = simpleParse v :: Maybe Version+ in do+ pkgs <- liftM (map unpackPkgVer) (cfgGet cbls)+ dR <- cfgGet dryRun+ guard $ isJust $ sequence $ map getVersion pkgs+ let ps = map (\ p@(n, v, r) -> (n, fromJust $ getVersion p, r)) pkgs+ dbFn <- cfgGet dbFile+ db <- liftIO $ readDb dbFn+ case doAddDistro db ps of+ Left brkOthrs -> liftIO $ mapM_ printBrksOth brkOthrs+ Right newDb -> liftIO $ unless dR $ saveDb newDb dbFn++doAddDistro db pkgs = let+ canBeAdded db n v = null $ checkDependants db n v+ (_, fails) = partition (\ (n, v, _) -> canBeAdded db n v) pkgs+ newDb = foldl (\ d (n, v, r) -> addDistroPkg d n v r) db pkgs+ brkOthrs = map (\ (n, v, _) -> ((n, v), checkDependants db n v)) fails+ in if null fails+ then Right newDb+ else Left brkOthrs++-- {{{2 Add repo package+addRepo :: ReaderT Cmds IO ()+addRepo = do+ dbFn <- cfgGet dbFile+ db <- liftIO $ readDb dbFn+ pD <- cfgGet patchDir+ cbls <- cfgGet cbls+ dR <- cfgGet dryRun+ genPkgs <- liftIO $ mapM (\ c -> withTemporaryDirectory "/tmp/cblrepo." (readCabal pD c)) cbls+ let pkgNames = map ((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription) genPkgs+ liftIO $ when (or . catMaybes $ map (liftM isBasePkg . lookupPkg db) pkgNames) (putStrLn "Trying to add a base pkg!!" >> exitFailure)+ let tmpDb = filter (\ p -> not $ pkgName p `elem` pkgNames) db+ case doAddRepo tmpDb genPkgs of+ Left (unSats, brksOthrs) -> liftIO (mapM_ printUnSat unSats >> mapM_ printBrksOth brksOthrs)+ Right newDb -> liftIO $ unless dR $ saveDb newDb dbFn++doAddRepo db pkgs = let+ (succs, fails) = partition (canBeAdded db) pkgs+ newDb = foldl addPkg2 db (map (fromJust . finalizeToCblPkg db) succs)+ unSats = catMaybes $ map (finalizeToDeps db) fails+ genPkgName = ((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription)+ genPkgVer = P.pkgVersion . package . packageDescription+ brksOthrs = filter (not . null . snd) $ map (\ p -> ((genPkgName p, genPkgVer p), checkDependants db (genPkgName p) (genPkgVer p))) fails+ in case (succs, fails) of+ (_, []) -> Right newDb+ ([], _) -> Left (unSats, brksOthrs)+ (_, _) -> doAddRepo newDb fails++canBeAdded db p = let+ finable = either (const False) (const True) (finalizePkg db p)+ n = ((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription) p+ v = P.pkgVersion $ package $ packageDescription p+ depsOK = null $ checkDependants db n v+ in finable && depsOK++finalizeToCblPkg db p = case finalizePkg db p of+ Right (pd, _) -> Just $ createCblPkg pd+ _ -> Nothing++finalizeToDeps db p = case finalizePkg db p of+ Left ds -> Just $ (((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription) p, ds)+ _ -> Nothing
− src/AddBase.hs
@@ -1,50 +0,0 @@-{-- - Copyright 2011 Per Magnus Therning- -- - Licensed under the Apache License, Version 2.0 (the "License");- - you may not use this file except in compliance with the License.- - You may obtain a copy of the License at- -- - http://www.apache.org/licenses/LICENSE-2.0- -- - Unless required by applicable law or agreed to in writing, software- - distributed under the License is distributed on an "AS IS" BASIS,- - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.- - See the License for the specific language governing permissions and- - limitations under the License.- -}--module AddBase where--import PkgDB-import Util.Misc--import Control.Monad-import Control.Monad.Reader-import Data.List-import Data.Maybe-import Distribution.Text-import Distribution.Version-import System.FilePath--addBase :: ReaderT Cmds IO ()-addBase = do- pkgs <- cfgGet pkgVers- dR <- cfgGet dryRun- guard $ isJust $ (sequence $ map (simpleParse . snd) pkgs :: Maybe [Version])- let ps = map (\ (n, v) -> (n, fromJust $ simpleParse v)) pkgs- dbFn <- cfgGet dbFile- db <- liftIO $ readDb dbFn- case doAddBase db ps of- Left brkOthrs -> liftIO $ mapM_ printBrksOth brkOthrs- Right newDb -> liftIO $ unless dR $ saveDb newDb dbFn--doAddBase db pkgs = let- (_, fails) = partition (\ (n, v) -> canBeAdded db n v) pkgs- newDb = foldl (\ d (n, v) -> addBasePkg d n v) db pkgs- brkOthrs = map (\ (n, v) -> ((n, v), checkDependants db n v)) fails- in if null fails- then Right newDb- else Left brkOthrs--canBeAdded db n v = null $ checkDependants db n v
− src/AddCabal.hs
@@ -1,87 +0,0 @@-{-- - Copyright 2011 Per Magnus Therning- -- - Licensed under the Apache License, Version 2.0 (the "License");- - you may not use this file except in compliance with the License.- - You may obtain a copy of the License at- -- - http://www.apache.org/licenses/LICENSE-2.0- -- - Unless required by applicable law or agreed to in writing, software- - distributed under the License is distributed on an "AS IS" BASIS,- - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.- - See the License for the specific language governing permissions and- - limitations under the License.- -}--module AddCabal where--import PkgDB-import Util.Misc--import Codec.Archive.Tar as Tar-import Codec.Compression.GZip as GZip-import Control.Monad-import Control.Monad.Error-import Control.Monad.Reader-import Data.List-import Data.Maybe-import Data.Version-import Distribution.Compiler-import Distribution.PackageDescription-import Distribution.PackageDescription.Configuration-import Distribution.PackageDescription.Parse-import Distribution.System-import Distribution.Text-import Distribution.Verbosity-import Distribution.Version-import System.Directory-import System.FilePath-import qualified Data.ByteString.Lazy.Char8 as BS-import qualified Distribution.Package as P-import System.Posix.Files-import System.Unix.Directory-import System.Process-import System.Exit-import System.IO--addCabal :: ReaderT Cmds IO ()-addCabal = do- dbFn <- cfgGet dbFile- db <- liftIO $ readDb dbFn- pD <- cfgGet patchDir- cbls <- cfgGet cbls- dR <- cfgGet dryRun- genPkgs <- liftIO $ mapM (\ c -> withTemporaryDirectory "/tmp/cblrepo." (readCabal pD c)) cbls- let pkgNames = map ((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription) genPkgs- let tmpDb = filter (\ p -> not $ pkgName p `elem` pkgNames) db- case doAddCabal tmpDb genPkgs of- Left (unSats, brksOthrs) -> liftIO (mapM_ printUnSat unSats >> mapM_ printBrksOth brksOthrs)- Right newDb -> liftIO $ unless dR $ saveDb newDb dbFn--doAddCabal db pkgs = let- (succs, fails) = partition (canBeAdded db) pkgs- newDb = foldl addPkg2 db (map (fromJust . finalizeToCblPkg db) succs)- unSats = catMaybes $ map (finalizeToDeps db) fails- genPkgName = ((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription)- genPkgVer = P.pkgVersion . package . packageDescription- brksOthrs = filter (not . null . snd) $ map (\ p -> ((genPkgName p, genPkgVer p), checkDependants db (genPkgName p) (genPkgVer p))) fails- in case (succs, fails) of- (_, []) -> Right newDb- ([], _) -> Left (unSats, brksOthrs)- (_, _) -> doAddCabal newDb fails--canBeAdded db p = let- finable = either (const False) (const True) (finalizePkg db p)- n = ((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription) p- v = P.pkgVersion $ package $ packageDescription p- depsOK = null $ checkDependants db n v- in finable && depsOK--finalizeToCblPkg db p = case finalizePkg db p of- Right (pd, _) -> Just $ createCblPkg pd- _ -> Nothing--finalizeToDeps db p = case finalizePkg db p of- Left ds -> Just $ (((\ (P.PackageName n) -> n ) . P.pkgName . package . packageDescription) p, ds)- _ -> Nothing
+ src/ConvertDB.hs view
@@ -0,0 +1,58 @@+{-+ - Copyright 2011 Per Magnus Therning+ -+ - Licensed under the Apache License, Version 2.0 (the "License");+ - you may not use this file except in compliance with the License.+ - You may obtain a copy of the License at+ -+ - http://www.apache.org/licenses/LICENSE-2.0+ -+ - Unless required by applicable law or agreed to in writing, software+ - distributed under the License is distributed on an "AS IS" BASIS,+ - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ - See the License for the specific language governing permissions and+ - limitations under the License.+ -}++module ConvertDB where++-- {{{1 imports+-- {{{2 local+import Util.Misc+import qualified OldPkgDB as ODB+import qualified PkgDB as NDB++-- {{{2 system+import Control.Monad.Reader+import Data.Version+import System.IO++convertDb :: ReaderT Cmds IO ()+convertDb = do+ inDb <- cfgGet inDbFile >>= \ fn -> liftIO $ ODB.readDb fn+ outDbFn <- cfgGet outDbFile+ newDb <- liftIO $ mapM doConvert inDb+ liftIO $ NDB.saveDb newDb outDbFn++doConvert :: ODB.CblPkg -> IO NDB.CblPkg+doConvert opkg@(n, (v, d, r))+ | ODB.isBasePkg opkg = let+ withNoStdBuffering f = do+ old <- hGetBuffering stdin+ hSetBuffering stdin NoBuffering+ result <- f+ hSetBuffering stdin old+ return result+ getValidChar = do+ putStr " (g)hc or (d)istro? " >> hFlush stdout+ getChar >>= (\ c -> putStrLn "" >> return c) >>= (\ c -> if c `elem` "gd" then return c else getValidChar)+ createPkg c+ | c == 'g' = return $ NDB.createGhcPkg n v+ | c == 'd' = do+ putStr " release? " >> hFlush stdout+ rel <- getLine+ return $ NDB.createDistroPkg n v rel+ in do+ putStr n+ withNoStdBuffering $ getValidChar >>= createPkg+ | otherwise = return $ NDB.createRepoPkg n v d (show r)
src/ListPkgs.hs view
@@ -34,5 +34,6 @@ else db liftIO $ mapM_ printCblPkgShort pkgs -printCblPkgShort (p, (v, _, r)) =- putStrLn $ p ++ " ==" ++ (display v) ++ " (" ++ (show r) ++")"+-- printCblPkgShort (p, (v, _, r)) =+printCblPkgShort p =+ putStrLn $ pkgName p ++ " " ++ (display $ pkgVersion p) ++ "-" ++ pkgRelease p
src/Main.hs view
@@ -16,8 +16,7 @@ module Main where -import AddBase-import AddCabal+import Add import BuildPkgs import BumpPkgs import IdxSync@@ -27,6 +26,7 @@ import Util.Misc import Urls import PkgBuild+import ConvertDB import Paths_cblrepo @@ -42,23 +42,22 @@ argDbFile = dbFile := "cblrepo.db" += explicit += name "db" += help "package database" += typFile argDryRun = dryRun := False += explicit += name "n" += help "dry run" -cmdAddBasePkg = record defAddBasePkg- [ argAppDir, argDbFile, argDryRun- , pkgVers := def += args += typ "STRING,STRING"- ] += name "addbasepkg" += help "add base packages" += details- [ "The format for a package is <name>,<version>." ]--cmdAddPkg = record defAddPkg+cmdAddPkg = record defCmdAdd [ argAppDir, argDbFile , patchDir := "patches" += explicit += name "patchdir" += help "location of patches" += typDir , argDryRun- , cbls := def += args += typ "CABAL"+ , pkgType := RepoPkgT += explicit += name "t" += name "type" += typ "TYPE" += help "type of package ((g)hcpkg, (d)istropkg, or (r)epopkg, default: r)"+ --, isBase := False += explicit += name "b" += name "base" += help "add a base package"+ , cbls := def += args += typ "PKGVERSPEC" ] += name "add" += help "add a package from a Cabal file" += details- [ "There are three ways to specify the location of the Cabal file:"- , " 1. The filename of the Cabal file."- , " 2. A URL where the Cabal can be found (for file:// URLs the full absolute path is required)."- , " 3. A pair, <name>,<version>, will load the Cabal file out of an index file (see idxupdate)"- , "All three format may be mixed on the command line."+ [ "The package version depends on the type of the package that's added:"+ , " 1. For a ghc package specify the name and version, e.g. 'base,4.3'"+ , " 2. For a distro package specify the name, version, and release, e.g. 'HUnit,1.2.2.3,2.1"+ , " 3. For a repo package provide a Cabal file by either"+ , " - provide the filename of the Cabal file"+ , " - specify the URL where the Cabal file can be found (for file:// URLs the full absolute path is required"+ , " - specify the name and version to load the Cabal file out of an index file (see idxupdate)"+ , " All three format may be mixed on the command line." ] cmdBumpPkgs = record defBumpPkgs@@ -99,9 +98,14 @@ , pkgs := def += args += typ "PKG" ] += help "create a PKGBUILD, and other files necessary for an Arch package" +cmdConvertDb = record defConvertDb+ [ argAppDir+ , inDbFile := "cblrepo.db" += explicit += name "i" += name "indb" += typFile += help "old database"+ , outDbFile := "new-cblrepo.db" += explicit += name "o" += name "outdb" += typFile += help "new database"+ ] += help "convert an old database to the new format"+ cmds = cmdArgsMode_ $ modes_- [ cmdAddBasePkg- , cmdAddPkg+ [ cmdAddPkg , cmdBuildPkgs , cmdBumpPkgs , cmdIdxSync@@ -110,6 +114,7 @@ , cmdUpdates , cmdUrls , cmdPkgBuild+ , cmdConvertDb ] += program progName += summary (progName ++ " v" ++ (display version))@@ -123,8 +128,7 @@ let c' = c { appDir = aD } createDirectoryIfMissing True (aD) case c' of- AddBasePkg {} -> runReaderT addBase c'- AddPkg {} -> runReaderT addCabal c'+ CmdAdd {} -> runReaderT add c' BuildPkgs {} -> runReaderT buildPkgs c' BumpPkgs {} -> runReaderT bumpPkgs c' IdxSync {} -> runReaderT idxSync c'@@ -133,3 +137,4 @@ Updates {} -> runReaderT updates c' Urls {} -> runReaderT urls c' PkgBuild {} -> runReaderT pkgBuild c'+ ConvertDb {} -> runReaderT convertDb c'
+ src/OldPkgDB.hs view
@@ -0,0 +1,125 @@+{-+ - Copyright 2011 Per Magnus Therning+ -+ - Licensed under the Apache License, Version 2.0 (the "License");+ - you may not use this file except in compliance with the License.+ - You may obtain a copy of the License at+ -+ - http://www.apache.org/licenses/LICENSE-2.0+ -+ - Unless required by applicable law or agreed to in writing, software+ - distributed under the License is distributed on an "AS IS" BASIS,+ - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ - See the License for the specific language governing permissions and+ - limitations under the License.+ -}++module OldPkgDB where++import Util.Misc++import Control.Applicative+import Control.Exception as CE+import Data.List+import Data.Maybe+import Data.Maybe+import Distribution.PackageDescription+import Distribution.Text+import Distribution.Version+import System.IO.Error+import Text.JSON+import qualified Distribution.Package as P+import qualified Distribution.Version as V++type CblPkg = (String, (V.Version, [P.Dependency], Int))+type CblDB = [CblPkg]++pkgName :: CblPkg -> String+pkgName (n, _) = n++pkgVersion :: CblPkg -> V.Version+pkgVersion (_, (v, _, _)) = v++pkgDeps :: CblPkg -> [P.Dependency]+pkgDeps (_, (_, ds, _)) = ds++pkgRelease :: CblPkg -> Int+pkgRelease (_, (_, _, i)) = i++createCblPkg :: PackageDescription -> CblPkg+createCblPkg pd = (name, (version, deps, 1))+ where+ name = (\ (P.PackageName n) -> n) (P.pkgName $ package pd)+ version = P.pkgVersion $ package pd+ deps = buildDepends pd++getDependencyOn :: String -> CblPkg -> Maybe P.Dependency+getDependencyOn n p = find (\ d -> depName d == n) (pkgDeps p)++isBasePkg :: CblPkg -> Bool+isBasePkg (_, (_, ds, _)) = null ds++emptyPkgDB :: CblDB+emptyPkgDB = []++addPkg :: CblDB -> String -> V.Version -> [P.Dependency] -> Int -> CblDB+addPkg db n v ds r = nubBy cmp newdb+ where+ cmp (n1, _) (n2, _) = n1 == n2+ newdb = (n, (v, ds, r)) : db++addPkg2 db (n, (v, ds, r)) = addPkg db n v ds r++addBasePkg db n v = addPkg db n v [] 0++delPkg :: CblDB -> String -> CblDB+delPkg db n = filter (\ p -> n /= pkgName p) db++lookupPkg :: CblDB -> String -> Maybe CblPkg+lookupPkg db n = maybe Nothing (\ s -> Just (n, s)) (lookup n db)++lookupDependencies :: CblDB -> String -> Maybe [String]+lookupDependencies db n =+ case lookupPkg db n of+ Nothing -> Nothing+ Just p -> let+ ds = pkgDeps p+ in Just $ map depName ds++lookupDependants :: CblDB -> String -> [String]+lookupDependants db n = map pkgName $ filter (\ p -> doesDependOn p n) db+ where+ doesDependOn p n = n `elem` (map depName $ pkgDeps p)++checkDependants db n v = let+ d1 = catMaybes $ map (lookupPkg db) (lookupDependants db n)+ d2 = map (\ p -> (pkgName p, getDependencyOn n p)) d1+ fails = filter (not . withinRange v . depVersionRange . fromJust . snd) d2+ in fails++transitiveDependants db pkgs = keepLast $ concat $ map transUsersOfOne pkgs+ where+ transUsersOfOne pkg = pkg : (keepLast $ concat $ map (transUsersOfOne) (lookupDependants db pkg))+ keepLast = reverse . nub . reverse++lookupRelease :: CblDB -> String -> Maybe Int+lookupRelease db n = lookupPkg db n >>= return . pkgRelease++bumpRelease db n = let+ bump (n', (v', d', r')) = (n', (v', d', r' + 1))+ in maybe db (addPkg2 db . bump) (lookupPkg db n)+readDb :: FilePath -> IO CblDB+readDb fp = (flip CE.catch)+ (\ e -> if isDoesNotExistError e+ then return emptyPkgDB+ else throwIO e)+ $ do+ r <- readFile fp >>= return . sequence . map decode . lines+ case r of+ Ok a -> return a+ Error s -> fail s++saveDb :: CblDB -> FilePath -> IO ()+saveDb db fp = writeFile fp s+ where+ s = unlines $ map (encode . showJSON) db
src/PkgDB.hs view
@@ -16,96 +16,127 @@ module PkgDB where -import Util.Misc-+-- {{{1 imports import Control.Exception as CE+import Control.Monad+import Data.Data import Data.List import Data.Maybe-import Data.Maybe+import Data.Typeable import Distribution.PackageDescription import Distribution.Text-import Distribution.Version import System.IO.Error import Text.JSON import qualified Distribution.Package as P import qualified Distribution.Version as V -type CblPkg = (String, (V.Version, [P.Dependency], Int))+-- {{{ temporary+_depName (P.Dependency (P.PackageName n) _) = n+_depVersionRange (P.Dependency _ vr) = vr++-- {{{1 types+data Pkg+ = GhcPkg { version :: V.Version }+ | DistroPkg { version :: V.Version, release :: String }+ | RepoPkg { version :: V.Version, deps :: [P.Dependency], release :: String }+ deriving (Eq, Show)++type CblPkg = (String, Pkg) type CblDB = [CblPkg] +-- {{{1 packages pkgName :: CblPkg -> String pkgName (n, _) = n pkgVersion :: CblPkg -> V.Version-pkgVersion (_, (v, _, _)) = v+pkgVersion (_, p) = version p pkgDeps :: CblPkg -> [P.Dependency]-pkgDeps (_, (_, ds, _)) = ds+pkgDeps (_, RepoPkg { deps = d}) = d+pkgDeps _ = [] -pkgRelease :: CblPkg -> Int-pkgRelease (_, (_, _, i)) = i+pkgRelease :: CblPkg -> String+pkgRelease (_, GhcPkg {}) = "xx"+pkgRelease (_, DistroPkg { release = r }) = r+pkgRelease (_, RepoPkg { release = r }) = r +createGhcPkg n v = (n, GhcPkg v)+createDistroPkg n v r = (n, DistroPkg v r)+createRepoPkg n v d r = (n, RepoPkg v d r)+ createCblPkg :: PackageDescription -> CblPkg-createCblPkg pd = (name, (version, deps, 1))+createCblPkg pd = createRepoPkg name version deps "1" where name = (\ (P.PackageName n) -> n) (P.pkgName $ package pd) version = P.pkgVersion $ package pd deps = buildDepends pd getDependencyOn :: String -> CblPkg -> Maybe P.Dependency-getDependencyOn n p = find (\ d -> depName d == n) (pkgDeps p)+getDependencyOn n p = find (\ d -> _depName d == n) (pkgDeps p) -isBasePkg (_, (_, ds, _)) = null ds+isGhcPkg (_, GhcPkg {}) = True+isGhcPkg _ = False +isDistroPkg (_, DistroPkg {}) = True+isDistroPkg _ = False++isRepoPkg (_, RepoPkg {}) = True+isRepoPkg _ = False++isBasePkg :: CblPkg -> Bool+isBasePkg = not . isRepoPkg++-- {{{1 database emptyPkgDB :: CblDB emptyPkgDB = [] -addPkg :: CblDB -> String -> V.Version -> [P.Dependency] -> Int -> CblDB-addPkg db n v ds r = nubBy cmp newdb+addPkg :: CblDB -> String -> Pkg -> CblDB+addPkg db n p = nubBy cmp newdb where cmp (n1, _) (n2, _) = n1 == n2- newdb = (n, (v, ds, r)) : db+ newdb = (n, p):db -addPkg2 db (n, (v, ds, r)) = addPkg db n v ds r+addPkg2 :: CblDB -> CblPkg -> CblDB+addPkg2 db (n, p) = addPkg db n p -addBasePkg db n v = addPkg db n v [] 0+addGhcPkg :: CblDB -> String -> V.Version -> CblDB+addGhcPkg db n v = addPkg2 db (createGhcPkg n v) +addDistroPkg :: CblDB -> String -> V.Version -> String -> CblDB+addDistroPkg db n v r = addPkg2 db (createDistroPkg n v r)+ delPkg :: CblDB -> String -> CblDB delPkg db n = filter (\ p -> n /= pkgName p) db -lookupPkg :: CblDB -> String -> Maybe CblPkg-lookupPkg db n = maybe Nothing (\ s -> Just (n, s)) (lookup n db)+bumpRelease :: CblDB -> String -> CblDB+bumpRelease db n = let+ doBump (n', p@RepoPkg { release = r }) = (n', p { release = nr })+ where+ nr = show $ (read r) + 1+ doBump p = p+ in maybe db (addPkg2 db . doBump) (lookupPkg db n) -lookupDependencies :: CblDB -> String -> Maybe [String]-lookupDependencies db n =- case lookupPkg db n of- Nothing -> Nothing- Just p -> let- ds = pkgDeps p- in Just $ map depName ds+lookupPkg :: CblDB -> String -> Maybe CblPkg+lookupPkg db n = maybe Nothing (\ p -> Just (n, p)) (lookup n db) -lookupDependants :: CblDB -> String -> [String] lookupDependants db n = map pkgName $ filter (\ p -> doesDependOn p n) db where- doesDependOn p n = n `elem` (map depName $ pkgDeps p)+ doesDependOn p n = n `elem` (map _depName $ pkgDeps p) +transitiveDependants :: CblDB -> [String] -> [String]+transitiveDependants db names = keepLast $ concat $ map transUsersOfOne names+ where+ transUsersOfOne n = n : transitiveDependants db (lookupDependants db n)+ keepLast = reverse . nub . reverse++-- Todo: test+checkDependants :: CblDB -> String -> V.Version -> [(String, Maybe P.Dependency)] checkDependants db n v = let d1 = catMaybes $ map (lookupPkg db) (lookupDependants db n) d2 = map (\ p -> (pkgName p, getDependencyOn n p)) d1- fails = filter (not . withinRange v . depVersionRange . fromJust . snd) d2+ fails = filter (not . V.withinRange v . _depVersionRange . fromJust . snd) d2 in fails -transitiveDependants db pkgs = keepLast $ concat $ map transUsersOfOne pkgs- where- transUsersOfOne pkg = pkg : (keepLast $ concat $ map (transUsersOfOne) (lookupDependants db pkg))- keepLast = reverse . nub . reverse--lookupRelease :: CblDB -> String -> Maybe Int-lookupRelease db n = lookupPkg db n >>= return . pkgRelease--bumpRelease db n = let- bump (n', (v', d', r')) = (n', (v', d', r' + 1))- in maybe db (addPkg2 db . bump) (lookupPkg db n) readDb :: FilePath -> IO CblDB readDb fp = (flip CE.catch) (\ e -> if isDoesNotExistError e@@ -120,26 +151,46 @@ saveDb :: CblDB -> FilePath -> IO () saveDb db fp = writeFile fp s where- s = unlines $ map (encode . showJSON) db+ s = unlines $ map encode db +-- {{{1 JSON instances instance JSON V.Version where showJSON v = makeObj [ ("Version", showJSON $ display v) ]- readJSON (JSObject o) = let- jAssoc = fromJSObject o- resultToMaybe (Ok a) = Just a- resultToMaybe _ = Nothing- version = lookup "Version" jAssoc >>= resultToMaybe . readJSON >>= simpleParse- in- maybe (fail "Not a version object") return version- readJSON _ = fail "Not a version object" + readJSON object = do+ obj <- readJSON object+ version <- valFromObj "Version" obj+ maybe (fail "Not a Version object") return (simpleParse version)+ instance JSON P.Dependency where showJSON d = makeObj [ ("Dependency", showJSON $ display d) ]- readJSON (JSObject o) = let- jAssoc = fromJSObject o- resultToMaybe (Ok a) = Just a- resultToMaybe _ = Nothing- dependency = lookup "Dependency" jAssoc >>= resultToMaybe . readJSON >>= simpleParse- in- maybe (fail "Not a dependency object") return dependency- readJSON _ = fail "Not a version object"++ readJSON object = do+ obj <- readJSON object+ dep <- valFromObj "Dependency" obj+ maybe (fail "Not a Dependency object") return (simpleParse dep)++instance JSON Pkg where+ showJSON p@(GhcPkg { version = v}) = makeObj [("GhcPkg", showJSON v)]+ showJSON p@(DistroPkg { version = v, release = r}) =+ makeObj [("DistroPkg", showJSON (v, r))]+ showJSON p@(RepoPkg { version = v, deps = d, release = r }) =+ makeObj [("RepoPkg", showJSON (v, d, r))]++ readJSON object = let+ readGhc = do+ obj <- readJSON object+ v <- valFromObj "GhcPkg" obj >>= readJSON+ return $ GhcPkg v++ readDistro = do+ obj <- readJSON object+ (v, r) <- valFromObj "DistroPkg" obj >>= readJSON+ return $ DistroPkg v r++ readRepo = do+ obj <- readJSON object+ (v, d, r) <- valFromObj "RepoPkg" obj >>= readJSON+ return $ RepoPkg v d r++ in readGhc `mplus` readDistro `mplus` readRepo `mplus` fail "Not a Pkg object"
− src/PkgDB.hs-boot
@@ -1,9 +0,0 @@-module PkgDB where--import qualified Distribution.Package as P-import qualified Distribution.Version as V--type CblPkg = (String, (V.Version, [P.Dependency], Int))-type CblDB = [CblPkg]--lookupPkg :: CblDB -> String -> Maybe CblPkg
src/Updates.hs view
@@ -35,8 +35,8 @@ aD <- cfgGet appDir entries <- liftIO $ liftM (Tar.read . GZip.decompress) (BS.readFile $ aD </> "00-index.tar.gz")- let nonBasePkgs = filter (\ (_, (_, ds, _)) -> not $ null ds) db- let pkgsNVers = map (\ (p, (v, _, _)) -> (p, v)) nonBasePkgs+ let nonBasePkgs = filter (not . isBasePkg) db+ let pkgsNVers = map (\ p -> (pkgName p, pkgVersion p)) nonBasePkgs let availPkgs = catMaybes $ eMap extractPkgVer entries let outdated = filter (\ (p, v) -> maybe False (> v) (latestVer p availPkgs))
src/Util/Misc.hs view
@@ -17,7 +17,7 @@ module Util.Misc where -import {-# SOURCE #-} PkgDB+import qualified PkgDB as DB import Codec.Archive.Tar as Tar import Codec.Compression.GZip as GZip@@ -64,9 +64,11 @@ dbName = progName ++ ".db" -- {{{1 command line argument type+data PkgType = GhcPkgT | DistroPkgT | RepoPkgT+ deriving (Show, Data, Typeable)+ data Cmds- = AddBasePkg { appDir :: FilePath, dbFile :: FilePath, dryRun :: Bool, pkgVers :: [(String, String)] }- | AddPkg { appDir :: FilePath, dbFile :: FilePath, patchDir :: FilePath, dryRun :: Bool, cbls :: [FilePath] }+ = CmdAdd { appDir :: FilePath, dbFile :: FilePath, patchDir :: FilePath, dryRun :: Bool, pkgType :: PkgType, cbls :: [FilePath] } | BuildPkgs { appDir :: FilePath, dbFile :: FilePath, pkgs :: [String] } | BumpPkgs { appDir :: FilePath, dbFile :: FilePath, dryRun :: Bool, inclusive :: Bool, pkgs :: [String] } | IdxSync { appDir :: FilePath }@@ -75,10 +77,10 @@ | Updates { appDir :: FilePath, dbFile :: FilePath } | Urls { appDir :: FilePath, pkgVers :: [(String, String)] } | PkgBuild { appDir :: FilePath, dbFile :: FilePath, patchDir :: FilePath, pkgs :: [String] }+ | ConvertDb { appDir :: FilePath, inDbFile :: FilePath, outDbFile :: FilePath } deriving (Show, Data, Typeable) -defAddBasePkg = AddBasePkg "" "" True []-defAddPkg = AddPkg "" "" "" True []+defCmdAdd = CmdAdd "" "" "" True RepoPkgT [] defBuildPkgs = BuildPkgs "" "" [] defBumpPkgs = BumpPkgs "" "" False False [] defIdxSync = IdxSync ""@@ -87,6 +89,7 @@ defUpdates = Updates "" "" defUrls = Urls "" [] defPkgBuild = PkgBuild "" "" "" []+defConvertDb = ConvertDb "" "" "" cfgGet f = liftM f ask @@ -186,9 +189,9 @@ checkAgainstDb db dep = let dN = depName dep dVR = depVersionRange dep- in case lookupPkg db dN of+ in case DB.lookupPkg db dN of Nothing -> False- Just (_, (v, _, _)) -> withinRange v dVR+ Just (_, p) -> withinRange (DB.version p) dVR -- {{{1 allPatches allPatches pn patchDir = let
src/Util/Translation.hs view
@@ -17,7 +17,7 @@ module Util.Translation where ---import AddCabal+import Add import Distribution.PackageDescription.Parse import Distribution.Verbosity --@@ -84,7 +84,7 @@ , apShHkgName :: ShVar String , apShPkgName :: ShVar String , apShPkgVer :: ShVar Version- , apShPkgRel :: ShVar Int+ , apShPkgRel :: ShVar String , apShPkgDesc :: ShVar ShQuotedString , apShUrl :: ShVar ShQuotedString , apShLicence :: ShVar ShArray@@ -106,7 +106,7 @@ , apShHkgName = ShVar "_hkgname" "" , apShPkgName = ShVar "pkgname" "" , apShPkgVer = ShVar "pkgver" (Version [] [])- , apShPkgRel = ShVar "pkgrel" 0+ , apShPkgRel = ShVar "pkgrel" "0" , apShPkgDesc = ShVar "pkgdesc" (ShQuotedString "") , apShUrl = ShVar "url" (ShQuotedString "http://hackage.haskell.org/package/${_hkgname}") , apShLicence = ShVar "license" (ShArray [])@@ -268,7 +268,7 @@ ap = baseArchPkg (PackageName hkgName) = packageName pd pkgVer = packageVersion pd- pkgRel = maybe 1 pkgRelease (lookupPkg db hkgName)+ pkgRel = maybe "1" pkgRelease (lookupPkg db hkgName) hasLib = maybe False (const True) (library pd) licFn = let l = licenseFile pd in if null l then Nothing else Just l archName = (if hasLib then "haskell-" else "") ++ (map toLower hkgName)@@ -276,7 +276,7 @@ url = if null (homepage pd) then "http://hackage.haskell.org/package/${_hkgname}" else (homepage pd) lic = display (license pd) makeDepends = if hasLib then [] else ["ghc=7.0.3-2"] ++ calcExactDeps db pd- depends = if hasLib then ["ghc=7.0.3-2", "sh"] ++ calcExactDeps db pd else []+ depends = if hasLib then ["ghc=7.0.3-2"] ++ calcExactDeps db pd else [] extraLibDepends = maybe [] (extraLibs . libBuildInfo) (library pd) install = if hasLib then (apShInstall ap) else Nothing in ap@@ -303,9 +303,16 @@ -- • this is most likely too simplistic to create the Arch package names -- correctly for all possible dependencies calcExactDeps db pd = let- deps = filter (not . flip elem ghcPkgs) (map depName (buildDepends pd))+ remPkgs = (map DB.pkgName (filter isGhcPkg db)) ++ ghcPkgs+ deps = filter (not . flip elem remPkgs) (map depName (buildDepends pd)) lookupPkgVer = display . DB.pkgVersion . fromJust . lookupPkg db- in map (\ n -> "haskell-" ++ (map toLower n) ++ "=" ++ (lookupPkgVer n)) deps+ depString n = let+ pkg = fromJust $ lookupPkg db n+ name = map toLower $ DB.pkgName pkg+ ver = display $ DB.pkgVersion pkg+ rel = pkgRelease pkg+ in "haskell-" ++ name ++ "=" ++ ver ++ "-" ++ rel+ in map depString deps -- {{{2 ghcPkgs -- libraries included in GHC, but not marked as provided by the Arch package
tst/TestPkgDB.hs view
@@ -26,18 +26,24 @@ import Test.Framework.Providers.HUnit import Test.Framework.TH import Test.HUnit+import Text.JSON+import qualified Distribution.Package as P+import qualified Distribution.Version as V -- {{{1 transitiveDependants theDb :: CblDB theDb =- [ ("pkgA", (fromJust $ simpleParse "1.0", [])) -- nothing depends on this pkg+ [ createRepoPkg "pkgA" (fromJust $ simpleParse "1.0") [] "1" -- nothing depends on this pkg -- a chain of two- , ("pkgB", (fromJust $ simpleParse "1.0", []))- , ("pkgC", (fromJust $ simpleParse "1.0", map (fromJust . simpleParse) ["pkgB"]))+ , createRepoPkg "pkgB" (fromJust $ simpleParse "1.0") [] "1"+ , createRepoPkg "pkgC" (fromJust $ simpleParse "1.0")+ (map (fromJust . simpleParse) ["pkgB"]) "1" -- a chain of three- , ("pkgD", (fromJust $ simpleParse "1.0", []))- , ("pkgE", (fromJust $ simpleParse "1.0", map (fromJust . simpleParse) ["pkgD"]))- , ("pkgF", (fromJust $ simpleParse "1.0", map (fromJust . simpleParse) ["pkgE"]))+ , createRepoPkg "pkgD" (fromJust $ simpleParse "1.0") [] "1"+ , createRepoPkg "pkgE" (fromJust $ simpleParse "1.0")+ (map (fromJust . simpleParse) ["pkgD"]) "1"+ , createRepoPkg "pkgF" (fromJust $ simpleParse "1.0")+ (map (fromJust . simpleParse) ["pkgE"]) "1" ] case_TD_one = do transitiveDependants theDb ["pkgA"] @=? ["pkgA"]@@ -47,6 +53,27 @@ case_TD_ordering1 = do transitiveDependants theDb ["pkgD", "pkgF"] @=? ["pkgD", "pkgE", "pkgF"] -- pass in packages in reverse order case_TD_ordering2 = do transitiveDependants theDb ["pkgF", "pkgD"] @=? ["pkgD", "pkgE", "pkgF"]++-- {{{1 JSON instances+case_json_version = let+ v1_i = V.Version [1, 2, 3] []+ v1_s = "{\"Version\":\"1.2.3\"}"+ v2_i = V.Version [1, 2, 3] ["foo"]+ in do+ assertEqual "JSON Version showJSON 1" v1_s (encode $ showJSON v1_i)+ assertEqual "JSON Version showJSON 2" v1_s (encode $ showJSON v2_i)+ assertEqual "JSON Version readJSON 1" (Ok v1_i) (decode v1_s)++case_json_dependency = let+ (Just d1_i) = simpleParse "package -any" :: Maybe P.Dependency+ d1_s = "{\"Dependency\":\"package -any\"}"+ (Just d2_i) = simpleParse "ConfigFile >=1 && <1.1" :: Maybe P.Dependency+ d2_s = "{\"Dependency\":\"ConfigFile >=1 && <1.1\"}"+ in do+ assertEqual "JSON Dependency showJSON 1" d1_s (encode $ showJSON d1_i)+ assertEqual "JSON Dependency showJSON 2" d2_s (encode $ showJSON d2_i)+ assertEqual "JSON Dependency readJSON 1" (Ok d1_i) (decode d1_s)+ assertEqual "JSON Dependency readJSON 2" (Ok d2_i) (decode d2_s) -- {{{1 testGroup testGroup = $(testGroupGenerator)