{-# LANGUAGE ForeignFunctionInterface #-} module Main where import Control.Monad import Data.Maybe (fromMaybe) import Debian.Apt.Methods import Debian.Report import Debian.Sources import Foreign.C.Types import System.Environment (getArgs, getProgName) import System.Exit (exitFailure) import Text.XML.HaXml import Text.XML.HaXml.Pretty (document) import Text.XML.HaXml.Posn import Text.PrettyPrint.HughesPJ import System.IO import System.Posix.Env -- * main main :: IO () main = do (sourcesAFP, sourcesBFP) <- parseArgs let arch = "i386" -- not actually used for anything right now, could be when binary package list is enabled cacheDir = "." -- FIXME: replace with tempdir later sourcesA <- liftM parseSourcesList $ readFile sourcesAFP sourcesB <- liftM parseSourcesList $ readFile sourcesBFP trumpMap <- trumped (fetch emptyFetchCallbacks []) cacheDir arch sourcesA sourcesB print (showXML "trump.xsl" (trumpedXML trumpMap)) where showXML :: String -> CFilter Posn -> Doc showXML styleSheet = document . mkDocument styleSheet . cfilterToElem -- cliff says this is broken with regards to cdata cfilterToElem :: CFilter Posn -> Element Posn cfilterToElem f = case f (CString False "" noPos) of [CElem e _] -> xmlEscape stdXmlEscaper e [] -> error "RSS produced no output" _ -> error "RSS produced more than one output" -- mkDocument :: String -> Element Posn -> Document Posn mkDocument styleSheet elem = let xmlDecl = XMLDecl "1.0" (Just (EncodingDecl "utf-8")) (Just True) prolog = Prolog (Just xmlDecl) [] Nothing [PI ("xml-stylesheet","type=\"text/xsl\" href=\""++styleSheet++"\"")] -- symTable = [] in Document prolog [] elem [] -- * command-line helper functions helpText :: String -> Doc helpText progName = (text "Usage:" <+> text progName <+> text "" <+> text ""$+$ text [] $+$ (fsep $ map text $ words $ "Find all the packages referenced by the second sources.list which trump packages find in the first sources.list.") ) parseArgs :: IO (String, String) parseArgs = do args <- getArgs case args of [dista, distb] -> return (dista, distb) _ -> exitWithHelp helpText where -- |exitFailure with nicely formatted help text on stderr exitWithHelp :: (String -> Doc) -- ^ generate help text, the argument is the result of getProgName -> IO a -- ^ no value is returned, this function always calls exitFailure exitWithHelp helpText = do progName <- getProgName hPutStrLn stderr =<< renderWidth (helpText progName) exitFailure -- |render a Doc using the current terminal width renderWidth :: Doc -> IO String renderWidth doc = do columns <- return . fromMaybe 80 =<< getWidth return $ renderStyle (Style PageMode columns 1.0) doc foreign import ccall "gwinsz.h c_get_window_size" c_get_window_size :: IO CLong -- get the number of rows and columns using ioctl (0, TIOCGWINSZ, &w) -- @see also: getWidth getWinSize :: IO (Int,Int) getWinSize = do (a,b) <- (`divMod` 65536) `fmap` c_get_window_size return (fromIntegral b, fromIntegral a) -- get the number of colums. -- First tries getWinSize, if that returns 0, then try the COLUMNS -- shell variable. getWidth :: IO (Maybe Int) getWidth = do (cols, _) <- getWinSize case cols of 0 -> return . fmap read =<< getEnv "COLUMNS" _ -> return (Just cols)