packages feed

fquery (empty) → 0.2.1

raw patch · 29 files changed

+1619/−0 lines, 29 filesdep +basedep +directorydep +haskell98setup-changed

Dependencies added: base, directory, haskell98, parsec, process, regex-compat, unix

Files

+ Adelie/Colour.hs view
@@ -0,0 +1,55 @@+-- Colour.hs+--+-- Escape codes for colouring in output.++module Adelie.Colour (+    gray,     inGray,+    red,      inRed,+    green,    inGreen,+    yellow,   inYellow,+    blue,     inBlue,+    magenta,  inMagenta,+    cyan,     inCyan,+    white,    inWhite,+    off,+    off2+) where++import Monad (when)++import Adelie.Options++gray, red, green, yellow, blue, magenta, cyan, white, off, off2 :: IO ()++gray    = whenM colourEnabled $ putStr "\27[30;01m"+red     = whenM colourEnabled $ putStr "\27[31;01m"+green   = whenM colourEnabled $ putStr "\27[32;01m"+yellow  = whenM colourEnabled $ putStr "\27[33;01m"+blue    = whenM colourEnabled $ putStr "\27[34;01m"+magenta = whenM colourEnabled $ putStr "\27[35;01m"+cyan    = whenM colourEnabled $ putStr "\27[36;01m"+white   = whenM colourEnabled $ putStr "\27[37;01m"+off     = whenM colourEnabled $ putStr "\27[0m"+off2    = do+  true <- colourEnabled+  if true+    then putStrLn "\27[0m"+    else putChar '\n'++whenM :: IO Bool -> IO () -> IO ()+whenM cond f = cond >>= (flip when f)++----------------------------------------------------------------++inGray, inRed, inGreen, inYellow    :: IO () -> IO ()+inBlue, inMagenta, inCyan, inWhite  :: IO () -> IO ()++inGray    f = gray    >> f >> off+inRed     f = red     >> f >> off+inGreen   f = yellow  >> f >> off+inYellow  f = yellow  >> f >> off+inBlue    f = blue    >> f >> off+inMagenta f = magenta >> f >> off+inCyan    f = cyan    >> f >> off+inWhite   f = white   >> f >> off+
+ Adelie/CompareVersion.hs view
@@ -0,0 +1,35 @@+-- CompareVersion.hs+--+-- Version string comparitor, which handles numbers differently: 1.10 > 1.9.++module Adelie.CompareVersion (compareVersion) where++import Char (isDigit)++import Adelie.ListEx (digitsToInt)++----------------------------------------------------------------++compareVersion :: String -> String -> Ordering+compareVersion = cmpA++cmpA :: String -> String -> Ordering+cmpA a0 b0+  | r == EQ   = cmpB as bs+  | otherwise = r+  where (a, as) = break (not.isDigit) a0+        (b, bs) = break (not.isDigit) b0+        r = compare (digitsToInt a) (digitsToInt b)++cmpB :: String -> String -> Ordering+cmpB [] []      = EQ+cmpB ('*':_) _  = EQ+cmpB _ ('*':_)  = EQ+cmpB []  _      = LT+cmpB  _ []      = GT+cmpB a0 b0+  | r == EQ   = cmpA as bs+  | otherwise = r+  where (a, as) = break isDigit a0+        (b, bs) = break isDigit b0+        r = compare a b
+ Adelie/Config.hs.in view
@@ -0,0 +1,13 @@+-- Config.hs+--+-- Auto-generated.++module Adelie.Config (+  portageTree,+  portageDB+) where++portageTree, portageDB :: String++portageTree = @@PortageTree@@+portageDB = @@PortageDB@@
+ Adelie/Contents.hs view
@@ -0,0 +1,94 @@+-- Contents.hs+--+-- Module for parsing CONTENTS files, located in portageDB/category/package/.++module Adelie.Contents (+  Contents(..),++  contentsFromCatName,+  putContents,+  putContentsLn,+  readContents+) where++import Char (isDigit, isHexDigit, isSpace)+import 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 <- try read'+  case r of+    Left  _  -> return a+    Right a' -> return a'+  where+    read' =+      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"
+ Adelie/Depend.hs view
@@ -0,0 +1,140 @@+-- Depend.hs+--+-- Module for parsing DEPEND and RDEPEND files, located in+-- portageDB/cateogry/package/.++module Adelie.Depend (+  Version,+  Dependency(..),++  dependFromCatName,+  readDepend,+  putDependency+) where++import Data.Char (isSpace)+import Data.List (nub)+import Text.ParserCombinators.Parsec+import Text.ParserCombinators.Parsec.Language+import Text.ParserCombinators.Parsec.Token++import Adelie.Portage++type Version = String++data Dependency+  = GreaterEqual  String Version+  | Equal         String Version+  | Unstable      String Version+  | NotInstalled  String+  | Any           String+    deriving (Eq, Show)++----------------------------------------------------------------++dependFromCatName :: (String, String) -> String+dependFromCatName (cat, name) = concatPath [portageDB,cat,name,"RDEPEND"]++----------------------------------------------------------------++readDepend :: FilePath -> [String] -> IO [Dependency]+readDepend fn iUse = do+  r <- (start_parser fn) `catch` (\ _ -> return $ Right [])+  case r of+    Left err -> putStr "Parse error at " >> print err >> error "Aborting"+    Right x  -> return $ nub x+  where start_parser = parseFromFile (dependParser iUse)++----------------------------------------------------------------++putDependency :: Dependency -> IO ()+putDependency (GreaterEqual p v) = putStr $ ">=" ++ p ++ '-':v+putDependency (Equal p v)        = putStr $ '=':p ++ '-':v+putDependency (Unstable p v)     = putStr $ '~':p ++ '-':v+putDependency (NotInstalled p)   = putStr $ '!':p+putDependency (Any p)            = putStr p++----------------------------------------------------------------++dependParser :: [String] -> Parser [Dependency]+dependParser iUse = do+  _skip <- spaces+  packages <- many (dependParser' iUse)+  eof+  return $ concat packages++dependParser' :: [String] -> Parser [Dependency]+dependParser' iUse = lexeme tp pp+  where tp = makeTokenParser emptyDef+        pp = parseOr iUse+         <|> parsePackageOrUse iUse++parseOr :: [String] -> Parser [Dependency]+parseOr iUse = do { string "||"+                  ; spaces+                  ; parseBrackets iUse+                  }+             <|>+                parseBrackets iUse++parsePackageOrUse :: [String] -> Parser [Dependency]+parsePackageOrUse iUse =+  do { p <- parsePackageOrUseWord+     ; do { char '?'        -- useFlag+          ; spaces+          ; r <- parseBrackets iUse+          ; let filt | head p == '!' = not $ (tail p) `elem` iUse+                     | otherwise     = p `elem` iUse+          ; if filt+              then return r+              else return []+          }+   <|> return [toDependency p]+     }++parsePackageOrUseWord :: Parser String+parsePackageOrUseWord = do { result <- many1 (satisfy cond)+                           -- skip[use]+                           -- TODO: add it to output+                           ; optionMaybe (do { char '['+                                             ; _use <- many1 (satisfy (/= ']'))+                                             ; char ']'+                                             -- ; return use+                                             ; return ()+                                             })+                           ; return result+                           }+  where+    cond '?' = False+    cond ')' = False+    cond '[' = False+    cond x = not $ isSpace x++parseBrackets :: [String] -> Parser [Dependency]+parseBrackets iUse = do { char '('+                        ; spaces+                        ; r <- manyTill (dependParser' iUse) (try (char ')'))+                        ; return $ concat r+                        }++----------------------------------------------------------------++breakVersion :: String -> (String, String)+breakVersion str = (n, v)+  where n = dropVersion str+        v = drop (length n+1) str++toDependency :: String -> Dependency++toDependency ('>':'=':str) = (GreaterEqual n v)+  where (n, v) = breakVersion str++toDependency ('=':str) = (Equal n v)+  where (n, v) = breakVersion str++toDependency ('~':str) = (Unstable n v)+  where (n, v) = breakVersion str++toDependency ('!':n) = (NotInstalled n)++toDependency n = (Any n)
+ Adelie/ListEx.hs view
@@ -0,0 +1,46 @@+-- ListEx.hs+--+-- Extra list functions.++module Adelie.ListEx (+  break2,+  concatMapM,+  digitsToInt,+  dropTail,+  dropUntilAfter,+  foldMUntil,+  pad+) where++import Char       (digitToInt)+import Data.List  (foldl')+import Monad      (liftM)++----------------------------------------------------------------++break2 :: (a -> Bool) -> [a] -> ([a], [a])+break2 f l = (h, drop 1 t)+  where (h, t) = break f l++concatMapM :: Monad m => (a -> m [b]) -> [a] -> m [b]+concatMapM f xs = liftM concat $ mapM f xs++digitsToInt :: String -> Int+digitsToInt = foldl' (\ a b -> a*10 + digitToInt b) 0++dropTail :: Int -> [a] -> [a]+dropTail n s = take (length s-n) s++dropUntilAfter :: (a -> Bool) -> [a] -> [a]+dropUntilAfter f = dropWhile f . dropWhile (not.f)++foldMUntil :: Monad m => (a -> b -> m a) -> (a -> Bool) -> a -> [b] -> m a+foldMUntil _ _ a [] = return a+foldMUntil f g a (x:xs) = do+  a' <- f a x+  case g a' of+    True  -> return a'+    False -> foldMUntil f g a' xs++pad :: Int -> a -> [a] -> [a]+pad n a str = take n (str ++ repeat a)
+ Adelie/Options.hs view
@@ -0,0 +1,13 @@+{-# OPTIONS -fglasgow-exts #-}++-- Options.hs+--+-- We keep some globals in C so we don't have to pass them around everywhere.++module Adelie.Options (+  colourEnabled,+  setColourEnabled+) where++foreign import ccall unsafe "opts.h colour_enabled" colourEnabled :: IO Bool+foreign import ccall unsafe "opts.h set_colour_enabled" setColourEnabled :: Bool -> IO ()
+ Adelie/Portage.hs view
@@ -0,0 +1,102 @@+-- Portage.hs+--+-- Portage directories and file paths.++module Adelie.Portage (+  portageTree,+  portageDB,+  useDesc,+  useDescPackage,++  dropVersion,+  concatPath,+  fullnameFromCatName,+  allInstalledPackages,+  findInstalledPackages+) where++import Data.Char         (isDigit)+import System.Directory  (getDirectoryContents, doesDirectoryExist)+import Data.List         (intersperse, sort)+import Control.Monad     (liftM)++import Adelie.ListEx+import Adelie.Config++-- Skips non-directory entries from returned list+-- (symlinks to world file in our case)+-- racy actually+safeGetDirectoryContents :: FilePath -> IO [FilePath]+safeGetDirectoryContents dir =+    do yet <- doesDirectoryExist dir+       if yet then getDirectoryContents dir+              else return []++portageProfiles :: String+portageProfiles = portageTree ++ "/profiles"++-- Where the global use flag descriptions are, 'use.desc'.+useDesc :: String+useDesc = portageProfiles ++ "/use.desc"++-- Where the package specific use flag descriptions are, 'use.local.desc'.+useDescPackage :: String+useDescPackage = portageProfiles ++ "/use.local.desc"++----------------------------------------------------------------++dropVersion :: String -> String+dropVersion [] = []+dropVersion ('-':x:xs)+  | isDigit x = []+  | otherwise = '-':x:(dropVersion xs)+dropVersion (x:xs) = x:(dropVersion xs)++concatPath :: [String] -> String+concatPath = concat.intersperse "/"++fullnameFromCatName :: (String, String) -> String+fullnameFromCatName (cat, name) = cat ++ '/':name++----------------------------------------------------------------++allInstalledPackages :: IO [(String, String)]+allInstalledPackages = do+  cats <- liftM (sort.filter filterHidden) (safeGetDirectoryContents portageDB)+  concatMapM allInstalledPackagesInCategory cats++allInstalledPackagesInCategory :: String -> IO [(String, String)]+allInstalledPackagesInCategory cat = do+  names <- liftM (sort.filter filterHidden) (safeGetDirectoryContents path)+  return $ map (\ a -> (cat, a)) names+  where path = portageDB ++ '/':cat++----------------------------------------------------------------++findInstalledPackages :: [String] -> IO [(String, String)]+findInstalledPackages names = concatMapM findInstPackages names++findInstPackages :: String -> IO [(String, String)]+findInstPackages name =+  if null b+    then findInstPackages' a+    else findInstPackagesInCategory a b+  where (a, b) = break2 (== '/') name++findInstPackages' :: String -> IO [(String, String)]+findInstPackages' pack = do+  cats  <- liftM (sort.filter filterHidden) (safeGetDirectoryContents portageDB)+  concatMapM (flip findInstPackagesInCategory pack) cats++findInstPackagesInCategory :: String -> String -> IO [(String, String)]+findInstPackagesInCategory cat pack = do+  packs <- liftM (sort.filter cond) (safeGetDirectoryContents (portageDB++'/':cat))+  return (zip (repeat cat) packs)+  where+    cond ('.':_) = False+    cond p = (pack == p) || (pack == dropVersion p)++----------------------------------------------------------------+filterHidden :: String -> Bool+filterHidden ('.':_) = False+filterHidden _ = True
+ Adelie/Pretty.hs view
@@ -0,0 +1,31 @@+-- Pretty.hs+--+-- Colourful output.++module Adelie.Pretty (+  putCatName,+  putCatNameLn,+  putNum,+  putNumLn+) where++import Adelie.Colour++----------------------------------------------------------------++putCatName, putCatNameLn :: (String, String) -> IO ()+putCatName   = putCatName' off+putCatNameLn = putCatName' off2++putCatName' :: IO () -> (String, String) -> IO ()+putCatName' f (c, n) =+  inYellow (putStr c) >> putChar '/' >> yellow >> putStr n >> f++----------------------------------------------------------------++putNum, putNumLn :: Int -> IO ()+putNum   = putNum' off+putNumLn = putNum' off2++putNum' :: IO () -> Int -> IO ()+putNum' f n = cyan >> putStr (show n) >> f
+ Adelie/Provide.hs view
@@ -0,0 +1,22 @@+-- Provide.hs+--+-- Module for parsing PROVIDE files, located in portageDB/category/package/.++module Adelie.Provide (+  provideFromCatName,+  readProvide+) where++import Monad (liftM)++import Adelie.Portage++----------------------------------------------------------------++provideFromCatName :: (String, String) -> String+provideFromCatName (cat,name) = concatPath [portageDB,cat,name,"PROVIDE"]++----------------------------------------------------------------++readProvide :: FilePath -> IO [String]+readProvide fn = (liftM words (readFile fn)) `catch` (\ _ -> return [])
+ Adelie/QChangelog.hs view
@@ -0,0 +1,169 @@+-- QChangelog.hs+--+-- Module to find the changelog of a package.++module Adelie.QChangelog (+  qChangelog,+  qLogFile+) where++import Char   (isDigit, isSpace)+import Monad  (unless)++import Adelie.Colour+import Adelie.CompareVersion+import Adelie.ListEx+import Adelie.Portage+import Adelie.Pretty++----------------------------------------------------------------++qLogFile :: [String] -> IO ()+qLogFile args = mapM_ (putStrLn.logFile) =<< findInstalledPackages args++logFile :: (String, String) -> String+logFile (cat, name) = +  portageTree ++ '/':cat ++ '/':(dropVersion name) ++ "/ChangeLog"++----------------------------------------------------------------++qChangelog :: [String] -> IO ()+qChangelog []       = return ()+qChangelog [x]      = mapM_ (changelog Nothing)  =<< findInstalledPackages [x]+qChangelog (x:y:_)  = mapM_ (changelog (Just y)) =<< findInstalledPackages [x]++changelog :: Maybe String -> (String, String) -> IO ()+changelog end catname@(_, name) = do+  putStr "ChangeLog since " >> putCatNameLn catname+  log' <- readFile (logFile catname)+  puts name end log'++----------------------------------------------------------------++puts :: String -> Maybe String -> String -> IO ()++puts _ _ [] = return ()+puts inst end ('#':l) = puts inst end (dropUntilAfter isNewLine l)++puts inst end ('*':l0) = do+  case maybeCompareVersion package end of+    GT -> puts inst end next+    _  -> case compareVersion inst package of+      LT -> putSection package date >> putDesc ls >> puts inst end next+      _  -> puts inst end next+  where (section, next) = breakSection l0+        (line, ls) = break2 isNewLine section+        (l1, l2) = break2 ('(' ==) line+        package = takeWhile (not.isSpace) l1+        date = takeWhile (')' /=) l2++puts inst end (_:ls) = puts inst end ls++maybeCompareVersion :: String -> Maybe String -> Ordering+maybeCompareVersion _ Nothing   = LT+maybeCompareVersion a (Just b)  = compareVersion a b++----------------------------------------------------------------++breakSection :: String -> (String, String)+breakSection str = (reverse h, t)+  where (h, t) = breakSection' [] str++breakSection' :: String -> String -> (String, String)+breakSection' acc [] = (acc, [])+breakSection' acc nx@('\n':'*':_) = (acc, nx)+breakSection' acc (x:xs) = breakSection' (x:acc) xs++----------------------------------------------------------------++putSection :: String -> String -> IO ()+putSection package date = do+  putStr "* " >> inYellow (putStr package) +  putStr " (" >> inWhite (putStr date) >> putStrLn ")"++----------------------------------------------------------------++putDesc :: String -> IO ()+putDesc [] = return ()+putDesc str = mapM_ putDesc' ls+  where ls = doublelines (dropWhile isNewLine str)++putDesc' :: String -> IO ()+putDesc' str = do+  if beginsWithDate (dropWhile isSpace str)+    then do+      putHeader header+      putBody body+    else+      putBody str+  where (header, body) = break2 (':' ==) str++doublelines :: String -> [String]+doublelines str =+  case t of+    []           -> h : []+    (_:'\n':xs)  -> h : doublelines xs+    (_:xs)       -> let (l0:l1) = doublelines xs +                    in (h ++ ('\n' : l0)) : l1+  where (h, t) = break ('\n' ==) str++beginsWithDate :: String -> Bool+beginsWithDate []   = False+beginsWithDate [_]  = False+beginsWithDate (x:y:_)+  | not (isDigit x)         = False+  | not (isDigitOrSpace y)  = False+  | otherwise = True++----------------------------------------------------------------++putHeader :: String -> IO ()+putHeader str0 = do+  putChar '\n'+  inWhite (putStr date)+  unless (null name) (putStr name)+  red >> putStr ('<':mail) >> putChar '>' >> off2+  putStr "    " >> putFiles 76 files+  where+    (date, str1) = break2 (';' ==) str0+    (name, str2) = break2 ('<' ==) str1+    (mail, str3) = break2 ('>' ==) str2+    files = words str3++putFiles :: Int -> [String] -> IO ()+putFiles _ [] = putChar '\n'+putFiles rem' (";":files) = putFiles rem' files+putFiles rem' (f:files) =+  if rem' < len+    then do+      putChar '\n' >> putStr "    "+      putFiles 76 (f:files)+    else do+      cyan+      if (last f == ',')+        then putStr (dropTail 1 f) >> off >> putStr ", "+        else putStr f >> off >> putChar ' '+      putFiles (rem' - len - 1) files+  where len = length f++----------------------------------------------------------------++putBody :: String -> IO ()+putBody [] = putChar '\n'++putBody ('#':c0) =+  case bug of+    [] -> putChar '#' >> putBody cs+    _  -> inMagenta (putStr ('#':bug)) >> putBody cs+  where (bug, cs) = span (isDigitOrSpace) c0++putBody (c:cs) = putChar c >> putBody cs++----------------------------------------------------------------++isNewLine :: Char -> Bool+isNewLine '\n'  = True+isNewLine _     = False++isDigitOrSpace :: Char -> Bool+isDigitOrSpace x = isDigit x || isSpace x
+ Adelie/QCheck.hs view
@@ -0,0 +1,77 @@+-- QMD5sum.hs+--+-- Check MD5sums and timestamps of installed packages.++module Adelie.QCheck (qCheck) where++import Char               (isHexDigit)+import IO++import System.Process     (runProcess, waitForProcess, ProcessHandle)+import System.Posix.Files (getFileStatus)+import System.Posix.IO    (createPipe, fdToHandle)++import Adelie.Colour+import Adelie.Contents+import Adelie.Portage+import Adelie.Pretty++-- Good, Bad+type Count = (Int, Int)++----------------------------------------------------------------++qCheck :: [String] -> IO ()+qCheck args = mapM_ check =<< findInstalledPackages args++check :: (String, String) -> IO ()+check catname = do+  putStr "Checking " >> putCatNameLn catname+  (g, b) <- readContents check' contents (0, 0)+  putNum g >> putStr " out of " >> putNum (b+g) >> putStrLn " files good"+  putChar '\n'+  where contents = contentsFromCatName catname++check' :: Contents -> Count -> IO (Bool, Count)++check' (Dir _) (g, b) = return (False, (g+1, b))++check' (Obj o m _) (g, b) = do+  r <- try (getFileStatus o)+  case r of+    Left _e -> do+      inRed (putStr "!!! ") >> putStr o >> putStrLn " does not exist"+      return (False, (g, b+1))+    Right _stat -> do+      (rd, wr) <- createPipeHandle+      runMD5sum o (Just wr) >>= waitForProcess+      ln <- hGetLine rd+      hClose rd+      hClose wr+      if m == (takeWhile isHexDigit ln)+        then return (False, (g+1, b))+        else putMD5error o >> return (False, (g, b+1))++check' (Sym _ _ _) (g, b) = return (False, (g+1, b))++----------------------------------------------------------------++createPipeHandle :: IO (Handle, Handle)+createPipeHandle = do+  (read', write) <- createPipe+  hRead  <- fdToHandle read'+  hWrite <- fdToHandle write+  return (hRead, hWrite)++----------------------------------------------------------------+runMD5sum :: String+             -> Maybe Handle+             -> IO ProcessHandle+runMD5sum f stdout' = runProcess md5sum [f] Nothing Nothing stdin' stdout' stderr'+  where md5sum = "/usr/bin/md5sum"+        stdin'  = Nothing+        stderr' = Nothing++putMD5error :: String -> IO ()+putMD5error file =+  inRed (putStr "!!! ") >> putStrLn (file ++ " has incorrect md5sum")
+ Adelie/QDepend.hs view
@@ -0,0 +1,75 @@+-- QDepend.hs+--+-- Module to list packages depending on an installed package.++module Adelie.QDepend (qDepend) where++import Adelie.Colour+import Adelie.CompareVersion+import Adelie.Depend+import Adelie.ListEx+import Adelie.Portage+import Adelie.Pretty+import Adelie.Provide+import Adelie.Use++----------------------------------------------------------------++qDepend :: [String] -> IO ()+qDepend [] = return ()+qDepend args = qDepend' =<< findInstalledPackages args++qDepend' :: [(String, String)] -> IO ()+qDepend' catnames = do+  allPacks <- allInstalledPackages+  let allPacks2 = map fullnameFromCatName allPacks+  mapM_ (dep allPacks2) catnames++dep :: [String] -> (String, String) -> IO ()+dep allPacks catname = do+  putStr "Packages depending on " >> putCatNameLn catname+  provide <- readProvide fnProvide+  mapM_ (dep' (fullname:provide)) allPacks+  putChar '\n'+  where fullname = fullnameFromCatName catname+        fnProvide = provideFromCatName catname++dep' :: [String] -> String -> IO ()+dep' provided fullname =+  readUse fnIUse >>= readDepend fnDepend >>= puts fullname provided+  where fnDepend = concatPath [portageDB,fullname,"RDEPEND"]+        fnIUse = concatPath [portageDB,fullname,"USE"]++puts :: String -> [String] -> [Dependency] -> IO ()+puts str provided iWant = mapM_ print' perms+  where perms = [ (p, w) | p <- provided, w <- iWant, w `satisfiedBy` p ]+        print' (_p, w) =+          white >> putStr (pad 32 ' ' str) >> off >>+          putStr "\t( " >> putDependency w >> putStrLn " )"++-------------------------------------------------------------++breakVersion :: String -> (String, String)+breakVersion str = (n, v)+  where n = dropVersion str+        v = drop (length n+1) str++satisfiedBy :: Dependency -> String -> Bool++(GreaterEqual wantName wantVer) `satisfiedBy` provided =+  (wantName == provName) && (compareVersion provVer wantVer) /= LT+  where (provName, provVer) = breakVersion provided++(Equal wantName wantVer) `satisfiedBy` provided = +  (wantName == provName) && (compareVersion provVer wantVer) == EQ+  where (provName, provVer) = breakVersion provided++(Unstable wantName wantVer) `satisfiedBy` provided =+  (wantName == provName) && (compareVersion provVer wantVer) == EQ+  where (provName, provVer) = breakVersion provided++(NotInstalled _) `satisfiedBy` _ = False++(Any wantName) `satisfiedBy` provided =+  wantName == provName+  where provName = dropVersion provided
+ Adelie/QHasUse.hs view
@@ -0,0 +1,38 @@+-- QHasUse.hs+--+-- Module to list all installed packages with a particular use flag.++module Adelie.QHasUse (qHasUse) where++import Monad (when)++import Adelie.Colour+import Adelie.Portage+import Adelie.Pretty+import Adelie.Use++----------------------------------------------------------------++qHasUse :: [String] -> IO ()+qHasUse [] = return ()+qHasUse args = qHasUse' args =<< allInstalledPackages ++qHasUse' :: [String] -> [(String, String)] -> IO ()+qHasUse' uses catnames = mapM_ (hasUse catnames) uses++hasUse :: [(String, String)] -> String -> IO ()+hasUse catnames use = do+  putStr "Packages installed with " >> putUse use >> putStrLn " USE flag"+  mapM_ (flip hasUse' use) catnames+  putChar '\n'++hasUse' :: (String, String) -> String -> IO ()+hasUse' catname use = do+  iUse <- readIUse fnIUse+  when (use `elem` iUse) (putCatNameLn catname)+  where fnIUse = iUseFromCatName catname++----------------------------------------------------------------++putUse :: String -> IO ()+putUse u = blue >> putStr u >> off
+ Adelie/QList.hs view
@@ -0,0 +1,56 @@+-- QList.hs+--+-- Module to list the contents of an installed package.++module Adelie.QList (+  ListTypes(..),++  qList+) where++import Adelie.Contents+import Adelie.Portage+import Adelie.Pretty++data ListTypes+  = ListDirs+  | ListFiles+  | ListLinks+  | ListAll+  deriving Eq++---------------------------------------------------------------- ++qList :: ListTypes -> [String] -> IO ()+qList types args = mapM_ (list puts) =<< findInstalledPackages args+  where+    puts = case types of+      ListDirs  -> putsD+      ListFiles -> putsF+      ListLinks -> putsL+      _         -> putsA++list :: (Contents -> () -> IO (Bool, ()))+        -> (String, String)+        -> IO ()+list puts catname = do+  putStr "Contents of " >> putCatNameLn catname+  readContents puts contents ()+  putChar '\n'+  where contents = contentsFromCatName catname++----------------------------------------------------------------++putsA, putsD, putsF, putsL :: Contents -> () -> IO (Bool, ())++putsA (Obj o _ _) _ = putStrLn o      >> return (False, ())+putsA c _           = putContentsLn c >> return (False, ())++putsD c@(Dir _) _   = putContentsLn c >> return (False, ())+putsD _ _           = return (False, ())++putsF (Obj o _ _) _ = putStrLn o >> return (False, ())+putsF _ _           = return (False, ())++putsL c@(Sym _ _ _)_= putContentsLn c >> return (False, ())+putsL _ _           = return (False, ())
+ Adelie/QOwn.hs view
@@ -0,0 +1,79 @@+-- QOwn.hs+--+-- Module to query who owns a particular file.++module Adelie.QOwn (+  qOwn,+  qOwnRegex+) where++import List       (delete)+import Monad      (when)+import Text.Regex (Regex, matchRegex, mkRegex)++import Adelie.Contents+import Adelie.ListEx+import Adelie.Portage+import Adelie.Pretty++----------------------------------------------------------------++qOwn :: [String] -> IO ()+qOwn [] = return ()+qOwn args = do+  foldMUntil qOwn' null args =<< allInstalledPackages+  putChar '\n'++qOwn' :: [String] -> (String, String) -> IO [String]+qOwn' files catname = readContents (puts catname) contents files+  where contents = contentsFromCatName catname++----------------------------------------------------------------++puts :: (String, String) -> Contents -> [String] -> IO (Bool, [String])+puts catname c fs =+  if c `contentsElem` fs+    then do+      let fs' = deleteContent c fs+      putCatName catname >> putStr " (" >> putContents c >> putStrLn ")"+      return (null fs', fs')+    else+      return (False, fs)++contentsElem :: Contents -> [String] -> Bool+(Dir d)     `contentsElem` fs = d `elem` fs+(Obj o _ _) `contentsElem` fs = o `elem` fs+(Sym l _ _) `contentsElem` fs = l `elem` fs++-- Only remove objects from the list.+deleteContent :: Contents -> [String] -> [String]+deleteContent (Obj o _ _) fs = delete o fs+deleteContent _ fs = fs++----------------------------------------------------------------++qOwnRegex :: [String] -> IO ()+qOwnRegex args = mapM_ (qOwnRegex' pats) =<< allInstalledPackages+  where pats = map mkRegex args++qOwnRegex' :: [Regex] -> (String, String) -> IO ()+qOwnRegex' pats catname = readContents (putsRegex catname pats) contents ()+  where contents = contentsFromCatName catname++putsRegex :: (String, String) -> [Regex] -> Contents -> () -> IO (Bool, ())+putsRegex catname pats c _ = do+  when (c `regexElem` pats) match+  return (False, ())+  where match = putCatName catname >> putStr " (" >> putContents c>>putStrLn ")"++regexElem :: Contents -> [Regex] -> Bool+(Dir d)     `regexElem` pats = mapMaybeOnce (flip matchRegex d) pats+(Obj o _ _) `regexElem` pats = mapMaybeOnce (flip matchRegex o) pats+(Sym l _ _) `regexElem` pats = mapMaybeOnce (flip matchRegex l) pats++mapMaybeOnce :: (a -> Maybe b) -> [a] -> Bool+mapMaybeOnce _ [] = False+mapMaybeOnce f (x:xs) =+  case f x of +    Just _a  -> True+    Nothing -> mapMaybeOnce f xs
+ Adelie/QSize.hs view
@@ -0,0 +1,61 @@+-- QSize.hs+--+-- Check the disk usage of an installed packaged.++module Adelie.QSize (qSize) where++import Directory            (doesDirectoryExist)+import IO                   (try)+import Monad                (mapM_, when)+import System.Posix.Files   (fileSize, getFileStatus)+import System.Posix.Types   (FileOffset)++import Adelie.Colour+import Adelie.Contents+import Adelie.Portage+import Adelie.Pretty++-- Size, Dir, Obj, Sym, Inaccessible+type Count = (FileOffset, Int, Int, Int, Int)++----------------------------------------------------------------++qSize :: [String] -> IO ()+qSize args = mapM_ size =<< findInstalledPackages args++size :: (String, String) -> IO ()+size catname = do+  putStr "Size of " >> putCatNameLn catname+  (size', dir, obj, sym, err) <- readContents count contents (0, 0, 0, 0, 0)+  putStr "    Directories: " >> putNumLn dir+  putStr "          Files: " >> putNumLn obj++  when (sym > 0) (putStr "          Links: " >> putNumLn sym)+  when (err > 0) (putStr "   Inaccessible: " >> putNumLn err)++  putStr "     Total size: " >> putSizeLn size'+  putChar '\n'+  where contents = contentsFromCatName catname++----------------------------------------------------------------++count :: Contents -> Count -> IO (Bool, Count)++count (Dir d) (s,w,x,y,z) = do+  r <- doesDirectoryExist d+  if r+    then return (False, (s,w+1,x,y,z))+    else return (False, (s,w,x,y,z+1)) ++count (Obj o _ _) (s,w,x,y,z) = do+  r <- try (getFileStatus o)+  case r of+    Left _err -> return (False, (s, w, x, y, z+1))+    Right st -> return (False, (s+fileSize st, w, x+1, y, z))++count (Sym _ _ _) (s,w,x,y,z) = return (False, (s,w,x,y+1,z))++----------------------------------------------------------------++putSizeLn :: FileOffset -> IO ()+putSizeLn n = cyan >> putStr (show (n `div` 1024)) >> putStr " kb" >> off2
+ Adelie/QUse.hs view
@@ -0,0 +1,75 @@+-- QUse.hs+--+-- Module to describe the use flags of an installed package.++module Adelie.QUse (qUse) where++import Data.HashTable as HashTable+import Monad (mapM_, unless)++import Adelie.Colour+import Adelie.ListEx+import Adelie.Portage+import Adelie.Pretty+import Adelie.Use+import Adelie.UseDesc++----------------------------------------------------------------++qUse :: [String] -> IO ()+qUse args = qUse' =<< findInstalledPackages args++qUse' :: [(String, String)] -> IO ()+qUse' [] = return ()+qUse' catnames = do+  useDesc' <- readUseDesc+  useDescPackage' <- readUseDescPackage min' max'+  mapM_ (use useDesc' useDescPackage') catnames+  where min' = dropVersion $ fullnameFromCatName $ minimum catnames+        max' = dropVersion $ fullnameFromCatName $ maximum catnames++use :: UseDescriptions -> UseDescriptions -> (String, String) -> IO ()+use useDesc' useDescPackage' catname = do+  iUse <- readIUse fnIUse+  pUse <- readUse  fnPUse+  let len = maximum $ map length iUse+  use' catname len useDesc' useDescPackage' iUse pUse+  where fnIUse = iUseFromCatName catname+        fnPUse = useFromCatName catname++use' :: (String, String) -> Int -> UseDescriptions -> UseDescriptions ->+        [String] -> [String] -> IO ()++use' catname _ _ _ [] _ = putStr "No USE flags for " >> putCatNameLn catname+use' catname len useDesc' useDescPackage' iUse pUse = do+  putStr "USE flags for " >> putCatNameLn catname+  mapM_ (format len useDesc' useDescPackage' pUse) iUse+  putChar '\n'++----------------------------------------------------------------++format :: Int -> UseDescriptions -> UseDescriptions ->+          [String] -> String -> IO ()++format len useDesc' useDescPackage' pUse iUse =+  inst >> putStr (pad len ' ' iUse) >> off >> putStr " : " >> desc+  where+    inst = if iUse `elem` pUse+            then putStr " + " >> red+            else putStr "   " >> blue++    desc = do+      end <- desc' useDescPackage'+      unless end (do+        end' <- desc' useDesc'+        unless end' (putStrLn "<< no description >>"))++    desc' descs = do+      r <- HashTable.lookup descs iUse +      case r of+        Just d  -> puts d >> return True+        Nothing -> return False++puts :: String -> IO ()+puts d@('!':'!':_) = red >> putStr d >> off2+puts d = putStrLn d
+ Adelie/QWant.hs view
@@ -0,0 +1,26 @@+-- QWant.hs+--+-- List the direct dependencies of a file.++module Adelie.QWant (qWant) where++import Adelie.Depend+import Adelie.Portage+import Adelie.Pretty+import Adelie.Use++-------------------------------------------------------------++qWant :: [String] -> IO ()+qWant args = mapM_ qWant' =<< findInstalledPackages args++qWant' :: (String, String) -> IO ()+qWant' catname = do+  putStr "Dependencies for " >> putCatNameLn catname+  readUse fnIUse >>= readDepend fnDepend >>= mapM_ puts+  putChar '\n'+  where fnDepend = dependFromCatName catname+        fnIUse = useFromCatName catname++puts :: Dependency -> IO ()+puts a = putDependency a >> putChar '\n'
+ Adelie/Use.hs view
@@ -0,0 +1,34 @@+-- Use.hs+--+-- Module for parsing USE and IUSE, files, located in+-- portageDB/category/package/.++module Adelie.Use (+  useFromCatName,+  iUseFromCatName,+  readUse,+  readIUse+) where++import List   (nub, sort)+import Monad  (liftM)++import Adelie.Portage++----------------------------------------------------------------++useFromCatName :: (String, String) -> String+useFromCatName (cat, name) = concatPath [portageDB,cat,name,"USE"]++iUseFromCatName :: (String, String) -> String+iUseFromCatName (cat, name) = concatPath [portageDB,cat,name,"IUSE"]++----------------------------------------------------------------++readUse :: FilePath -> IO [String]+readUse fn = (liftM words $ readFile fn) `catch` (\ _ -> return [])++-- IUSE files sometimes have duplicate USE flags.  I am not sure if it is the+-- intended behaviour, but I filter them out.+readIUse :: FilePath -> IO [String]+readIUse fn = (liftM (nub.sort.words) $ readFile fn) `catch` (\ _ -> return [])
+ Adelie/UseDesc.hs view
@@ -0,0 +1,86 @@+-- UseDesc.hs+--+-- Module for parsing portageProfile/use.desc and use.local.desc files.++module Adelie.UseDesc (+  UseDescriptions,+  readUseDesc,+  readUseDescPackage+) where++import Char (isSpace)+import Data.HashTable as HashTable+import Monad (when)++import Adelie.ListEx+import Adelie.Portage++type UseDescriptions = HashTable String String++----------------------------------------------------------------++readUseDesc :: IO UseDescriptions+readUseDesc = do+  table <- HashTable.new (==) hashString+  ls <- readFile useDesc+  mapM_ (useParser table) (lines ls)+  return table++useParser :: UseDescriptions -> String -> IO ()+useParser _ ('#':_) = return ()+useParser table line = insert table use desc+  where (use, desc) = myBreak line++myBreak :: String -> (String, String)+myBreak [] = ("", "")+myBreak (' ':'-':' ':xs) = ("", xs)+myBreak (x:xs) = (x:ys, zs)+  where (ys, zs) = myBreak xs++----------------------------------------------------------------++readUseDescPackage :: String -> String -> IO UseDescriptions+readUseDescPackage start end = do+  table <- HashTable.new (==) hashString+  ls <- readFile useDescPackage+  mapMUntil_ (useParser2 table start end) (lines ls)+  return table++mapMUntil_ :: Monad m => (a -> m Bool) -> [a] -> m ()+mapMUntil_ _ [] = return ()+mapMUntil_ f (x:xs) = do+  r <- f x+  when r (mapMUntil_ f xs)++useParser2 :: UseDescriptions -> String -> String -> String -> IO Bool+useParser2 _ _ _ [] = return True+useParser2 _ _ _ ('#':_) = return True+useParser2 table start end str = do+  case mid start catname end of+      LT -> return True+      EQ -> insert table use desc >> return True+      GT -> return False+  where str' = reverse $ dropWhile isSpace $ reverse str+        (catname, rest) = break2 (':' ==) str'+        (use, desc) = myBreak rest+  +----------------------------------------------------------------++-- In Haskell, vim-core > vim+-- In sort,    vim-core < vim+-- Work around it.+myCompare :: String -> String -> Ordering+myCompare [] [] = EQ+myCompare  _ [] = LT+myCompare []  _ = GT+myCompare (a:as) (b:bs) =+  if r == EQ+    then myCompare as bs +    else r+  where r = compare a b++mid :: String -> String -> String -> Ordering+mid l m r+  | myCompare l m == GT = LT+  | myCompare m r == GT = GT+  | otherwise = EQ
+ Adelie/opts.c view
@@ -0,0 +1,13 @@+#include "opts.h"++static bool colour = true;++bool colour_enabled(void)+{+    return colour;+}++void set_colour_enabled(const bool on)+{+    colour = on;+}
+ Adelie/opts.h view
@@ -0,0 +1,9 @@+#ifndef __included_opts_h+#define __included_opts_h++#include <stdbool.h>++extern bool colour_enabled(void);+extern void set_colour_enabled(const bool on);++#endif
+ LICENCE.txt view
@@ -0,0 +1,23 @@++  Copyright (C) 2006 David Wang++  This software is provided 'as-is', without any express or implied+  warranty.  In no event will the authors be held liable for any damages+  arising from the use of this software.++  Permission is granted to anyone to use this software for any purpose,+  including commercial applications, and to alter it and redistribute it+  freely, subject to the following restrictions:++  1. The origin of this software must not be misrepresented; you must not+     claim that you wrote the original software. If you use this software+     in a product, an acknowledgment in the product documentation would be+     appreciated but is not required.++  2. Altered source versions must be plainly marked as such, and must not+     be misrepresented as being the original software.++  3. This notice may not be removed or altered from any source distribution.+++  [For informational purposes, this is the zlib licence.]
+ Main.hs view
@@ -0,0 +1,164 @@+-- Main.hs+--+-- Adelie is a collection of scripts to querying portage packages. ++module Main (main) where++import System (getArgs, getProgName)++import Adelie.Colour+import Adelie.Options+import Adelie.QChangelog+import Adelie.QCheck+import Adelie.QDepend+import Adelie.QHasUse+import Adelie.QList+import Adelie.QOwn+import Adelie.QSize+import Adelie.QUse+import Adelie.QWant++type CommandProc = [String] -> IO ()++data Command+  = Short String String CommandProc+  | Long  String String String CommandProc++logCommands :: [Command]+logCommands = [+  (Long   "c" "changes"+          "list changes since the installed version"+          qChangelog),+  (Short  "cl"+          "find the changelog of a package"+          qLogFile)+  ]++listCommands :: [Command]+listCommands = [+  (Long   "f" "files"+          "list the contents of a package"+          (qList ListAll)),+  (Short  "fd"+          "list the directories in a package"+          (qList ListDirs)),+  (Short  "ff"+          "list the files in a package"+          (qList ListFiles)),+  (Short  "fl"+          "list the links in a package"+          (qList ListLinks))+  ]++ownCommands :: [Command]+ownCommands = [+  (Long   "b" "belongs"+          "find the package(s) owning a file"+          qOwn),+  (Short  "bp"+          "find the package(s) owning a file with regexp"+          qOwnRegex),+  (Long   "s" "size"+          "find the size of files in a package"+          qSize),+  (Long   "k" "check"+          "check MD5sums and timestamps of a package"+          qCheck)+  ]++dependCommands :: [Command]+dependCommands = [+  (Long   "d" "depends"+          "list packages directly depending on this package"+          qDepend),+  (Short  "dd"+          "list direct dependencies of a package"+          qWant)+  ]++useCommands :: [Command]+useCommands = [+  (Long   "u" "uses"+          "describe a package's USE flags"+          qUse),+  (Long   "h" "hasuse"+          "list all packages with a USE flag"+          qHasUse)+  ]++allCommands :: [Command]+allCommands = logCommands ++ listCommands ++ ownCommands ++ dependCommands ++ useCommands++----------------------------------------------------------------++main :: IO ()+main = do+  args0 <- getArgs+  let (options, commands) = span isOption args0+  mapM_ parseOptions options+  case commands of+    [] -> usage+    (cmd:cargs) -> (runCommand cmd allCommands) cargs+++isOption :: String -> Bool+isOption = ('-' ==) . head++----------------------------------------------------------------++parseOptions :: String -> IO ()+parseOptions [] = return ()++parseOptions "-C"         = setColourEnabled False+parseOptions "--nocolor"  = setColourEnabled False+parseOptions "--nocolour" = setColourEnabled False++parseOptions _ = return ()++----------------------------------------------------------------++runCommand :: String -> [Command] -> CommandProc+runCommand _ [] = (\ _ -> usage)++runCommand command ((Short cmd _ f):cs)+  | command == cmd  = f+  | otherwise       = runCommand command cs++runCommand command ((Long cmd0 cmd1 _ f):cs)+  | command == cmd0 = f+  | command == cmd1 = f+  | otherwise       = runCommand command cs++----------------------------------------------------------------++usage :: IO ()+usage = do+  prog <- getProgName+  putStrLn "fquery 0.2\n"+  putStrLn $ "Usage: " ++ prog ++ " [options] <command> <arguments>\n"++  cyan >> putStr "Options:" >> off2+  inYellow (putStr "    -C --nocolour") >> tab >> putStrLn "turn off colours"+  nl++  cyan >> putStr "Commands for Installed Packages:" >> off2+  mapM_ putCommand logCommands; nl+  mapM_ putCommand listCommands; nl+  mapM_ putCommand ownCommands; nl+  mapM_ putCommand dependCommands; nl+  mapM_ putCommand useCommands; nl++putCommand :: Command -> IO ()+putCommand (Short cmd desc _) = f `withDesc` desc+  where f = green >> putStr cmd >> off >> tab++putCommand (Long cmd0 cmd1 desc _) = f `withDesc` desc+  where f = green >> putStr (cmd0 ++ "  " ++ cmd1) >> off++withDesc :: IO () -> String -> IO ()+f `withDesc` desc = putStr "    " >> f >> tab >> putStrLn desc++tab :: IO ()+tab = putChar '\t'+nl :: IO ()+nl  = putChar '\n'
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMainWithHooks autoconfUserHooks
+ TODO view
@@ -0,0 +1,4 @@+ * make fquery a drop-in replacement of equery:+    o outpout compatible+    o options full+ * explore attoparsec in search of faster performance
+ configure view
@@ -0,0 +1,23 @@+#!/bin/sh+#+# Fake configure script.++portageq=/usr/bin/portageq++PORTAGE_TREE=`${portageq} portdir 2>/dev/null`+PORTAGE_DB=`${portageq} vdb_path 2>/dev/null`++if [ -z $PORTAGE_TREE ]; then+  PORTAGE_TREE="/usr/portage"+fi++if [ -z $PORTAGE_DB ]; then+  PORTAGE_DB="/var/db/pkg"+fi++echo "portdir: ${PORTAGE_TREE}"+echo "vdb_path: ${PORTAGE_DB}"++sed -e s,'@@PortageTree@@',"\"${PORTAGE_TREE}\"",	\+    -e s,'@@PortageDB@@',"\"${PORTAGE_DB}\"",		\+    "Adelie/Config.hs.in" > "Adelie/Config.hs"
+ fquery.cabal view
@@ -0,0 +1,53 @@+Name:		fquery+Version:	0.2.1++Author:		David Wang <millimillenary@gmail.com>, Sergei Trofimovich <slyfox@inbox.ru>+Maintainer:	Sergei Trofimovich <slyfox@inbox.ru>+Copyright:	2006 David Wang, 2009 Sergei Trofimovich++License-File:	LICENCE.txt+License:	OtherLicense++Synopsis:	Installed package query tool for Gentoo Linux+Description:	Installed package query tool for Gentoo Linux++		Home page http://home.exetel.com.au/tjaden/fquery/+		Public repository is http://repo.or.cz/w/fquery.git++Category:	Gentoo++Build-Type:	Configure+Build-Depends:	base, haskell98, parsec, unix, regex-compat, process, directory+Extra-Source-Files:+		configure+		Adelie/Config.hs.in+		Adelie/opts.h+		TODO++Executable:	fquery+Main-is:	Main.hs+Other-Modules:	Adelie.Colour+		Adelie.CompareVersion+		Adelie.Contents+		Adelie.Depend+		Adelie.ListEx+		Adelie.Options+		Adelie.Portage+		Adelie.Pretty+		Adelie.Provide+		Adelie.QChangelog+		Adelie.QCheck+		Adelie.QDepend+		Adelie.QHasUse+		Adelie.QList+		Adelie.QOwn+		Adelie.QSize+		Adelie.QUse+		Adelie.QWant+		Adelie.Use+		Adelie.UseDesc++GHC-Options:	-O2 -Wall+-- GHC-Options:	-Werror++c-sources:	Adelie/opts.c