module P2 where -- Module that respect categories. -- Possibly to replace Portage.hs when the rest of the project has been -- ported to this style. import BlingBling import Control.Arrow import Control.Monad import qualified Distribution.PackageDescription as Cabal import Data.Map (Map) import qualified Data.Map as Map import qualified Data.List as List import System.Directory import System.FilePath import Text.Regex import qualified Portage.Version as Portage import Distribution.Text type Portage = PortageMap [Ebuild] type PortageMap a = Map Package a data Ebuild = Ebuild { ePackage :: Package, eVersion :: Portage.Version, eFilePath :: FilePath, ePkgDesc :: Maybe Cabal.GenericPackageDescription } deriving (Show) data Package = P { pCategory :: String, pPackage :: String } deriving (Eq, Ord) instance Show Package where show (P c p) = c ++ '/':p instance Eq Ebuild where e1 == e2 = (ePackage e1, eVersion e1) == (ePackage e2, eVersion e2) instance Ord Ebuild where compare e1 e2 = compare (ePackage e1, eVersion e1) (ePackage e2, eVersion e2) lookupEbuildWith :: Portage -> Package -> (Ebuild -> Bool) -> Maybe Ebuild lookupEbuildWith portage package comp = do es <- Map.lookup package portage List.find comp es getPackageList :: FilePath -> IO [Package] getPackageList portdir = do categories <- getDirectories portdir packages <- fmap concat $ forMbling categories $ \c -> do pkg <- getDirectories (portdir c) return (map (P c) pkg) return packages readPortagePackages :: FilePath -> [Package] -> IO Portage readPortagePackages portdir packages0 = do packages <- filterM (doesDirectoryExist . (portdir ) . show) packages0 ebuild_map0 <- forM packages $ \package -> do ebuilds <- getPackageVersions package return (package, List.sort ebuilds) let ebuild_map = filter (not . null . snd) ebuild_map0 return $ Map.fromList ebuild_map where getPackageVersions :: Package -> IO [Ebuild] getPackageVersions (P category package) = do files <- getDirectoryContents (portdir category package) let ebuilds = [ (v, portdir category package fn) | (Just v, fn) <- map ((filterVersion package) &&& id) files ] return (map (uncurry (\v f -> Ebuild (P category package) v f Nothing)) ebuilds) filterVersion :: String -> String -> Maybe Portage.Version filterVersion p fn = do [vstring] <- matchRegex (ebuildVersionRegex p) fn simpleParse vstring ebuildVersionRegex name = mkRegex ("^"++name++"-(.*)\\.ebuild$") readPortageTree :: FilePath -> IO Portage readPortageTree portdir = do packages <- getPackageList portdir readPortagePackages portdir packages getDirectories :: FilePath -> IO [String] getDirectories fp = do files <- fmap (filter (`notElem` [".", ".."])) $ getDirectoryContents fp filterM (doesDirectoryExist . (fp )) files printPortage :: Portage -> IO () printPortage port = forM_ (Map.toAscList port) $ \(package, ebuilds) -> do let (P c p) = package putStr $ c ++ '/':p putStr " " forM_ ebuilds (\e -> putStr (show $ eVersion e) >> putChar ' ') putStrLn ""