fquery-0.2.1.3: Adelie/Contents.hs
-- Contents.hs
--
-- Module for parsing CONTENTS files, located in portageDB/category/package/.
module Adelie.Contents (
Contents(..),
contentsFromCatName,
putContents,
putContentsLn,
readContents
) where
import Data.Char (isDigit, isHexDigit, isSpace)
import qualified Adelie.Error as E
import System.IO
import Adelie.Colour
import Adelie.ListEx
import Adelie.Portage
data Contents
= Dir String
| Obj String String Int
| Sym String String Int
deriving Show
----------------------------------------------------------------
contentsFromCatName :: (String, String) -> String
contentsFromCatName (cat, name) = concatPath [portageDB,cat,name,"CONTENTS"]
----------------------------------------------------------------
readContents :: (Contents -> a -> IO (Bool, a)) -> FilePath -> a -> IO a
readContents f fn a = do
r <- E.try read'
case r of
Left _ -> return a
Right a' -> return a'
where
read' =
E.bracket (openFile fn ReadMode)
hClose
(readContents' f a)
readContents' :: (Contents -> a -> IO (Bool, a)) -> a -> Handle -> IO a
readContents' f a fp = do
eof <- hIsEOF fp
if eof
then return a
else do
ln <- hGetLine fp
(done, a') <- f (contentsParser ln) a
if done
then return a'
else readContents' f a' fp
----------------------------------------------------------------
putContents, putContentsLn :: Contents -> IO ()
putContents = putContents' off
putContentsLn = putContents' off2
putContents' :: IO () -> Contents -> IO ()
putContents' f (Dir d) = blue >> putStr d >> f
putContents' f (Obj o _ _) = white >> putStr o >> f
putContents' f (Sym l t _) = cyan >> putStr (l ++ " -> " ++ t) >> f
----------------------------------------------------------------
contentsParser :: String -> Contents
contentsParser ('d':'i':'r':' ':dir) = (Dir dir)
contentsParser ('o':'b':'j':' ':ln0) = (Obj obj md5 time)
where ln1 = dropWhile isSpace $ reverse ln0
(time', ln2) = break2 (not.isDigit) ln1
(md5', obj') = break2 (not.isHexDigit) ln2
obj = reverse obj'
md5 = reverse md5'
time = digitsToInt (reverse time')
contentsParser ('s':'y':'m':' ':ln0) = (Sym link target time)
where (link, ln1) = breakLink ln0
ln2 = reverse ln1
(time', target') = break2 (not.isDigit) ln2
target = reverse target'
time = digitsToInt (reverse time')
contentsParser cont = error $ "contentsParser: 'dir: /obj: /sym: ' not found in " ++ show cont
breakLink :: String -> (String, String)
breakLink (' ':'-':'>':' ':xs) = ([], xs)
breakLink (x:xs) = (x:as, bs)
where (as, bs) = breakLink xs
breakLink [] = error "breakLink: ' -> ' not found"