packages feed

hackport-0.2.1: Config.hs

module Config where

import Network.URI
import System.Console.GetOpt
import Text.Regex

data HackPortOptions
	= OverlayPath String
        | PortagePath String
	| Server String
	| TempDir String
	| Verbosity String
	| Help
        | RefreshCache

data OperationMode
	= List String
	| Merge String
	| DiffTree DiffMode
	| Update
	| ShowHelp
	| Status String
	| MakeEbuild String

data DiffMode
	= ShowAll
	| ShowMissing
	| ShowAdditions
	| ShowNewer
	| ShowCommon
	deriving Eq

data Config = Config
	{ overlayPath		::Maybe String
        , portagePath           ::Maybe String
	, server		::URI
	, tmp			::String
	, verbosity		::Verbosity
        , refreshCache          ::Bool
	}

data Verbosity
	= Debug
	| Normal
	| Silent

packageRegex :: Regex
packageRegex = mkRegex "^(.*?)-([0-9].*)$"

defaultConfig :: Config
defaultConfig = Config
	{ overlayPath = Nothing
        , portagePath = Nothing
	, server = URI "http:" (Just $ URIAuth "" "hackage.haskell.org" "") "/packages/archive/" "" ""
	, tmp = "/tmp"
	, verbosity = Normal
        , refreshCache = False
	}

hackageOptions :: [OptDescr HackPortOptions]
hackageOptions =
	[Option ['o'] ["overlay-path"] (ReqArg OverlayPath "PATH") "The overlay tree to merge to"
        ,Option ['p'] ["portdir"] (ReqArg PortagePath "PATH") "The portage directory to use"
	,Option ['s'] ["server"] (ReqArg Server "URL") "The Hackage server to query"
	,Option ['t'] ["temp-dir"] (ReqArg TempDir "PATH") "A temp directory where tarballs can be stored"
	,Option ['v'] ["verbosity"] (ReqArg Verbosity "debug|normal|silent") "Set verbosity level (default is 'normal')"
	,Option ['h', '?'] ["help"] (NoArg Help) "Display this help message"
        ,Option ['r'] ["refresh-cache"] (NoArg RefreshCache) "Refresh the hackport cache before running the command"
	]

parseConfig :: [String] -> Either String ([HackPortOptions],OperationMode)
parseConfig opts = let
	(popts,args,errs) = getOpt Permute hackageOptions opts
	mode | not (null errs) = Left $ "Error while parsing flags:\n"
	                             ++ concat errs
	     | not (null [ () | Help <- popts ]) = Right ShowHelp
	     | otherwise = case args of
		"merge":[] -> Left "Need a package's name and version to merge it.\n"
		"merge":package:[] -> Right (Merge package)
		"merge":_:rest -> Left ("'merge' takes 1 argument("++show ((length rest)+1)++" given).\n")
		"list":[] -> Right (List "")
		"list":package:[] -> Right (List package)
		"list":rest -> Left ("'list' takes at most one argument ("++show (length rest)++" given).\n")
		"diff":[] -> Right (DiffTree ShowAll)
		"diff":"all":[] -> Right (DiffTree ShowAll)
		"diff":"missing":[] -> Right (DiffTree ShowMissing)
		"diff":"additions":[] -> Right (DiffTree ShowAdditions)
		"diff":"newer":[] -> Right (DiffTree ShowNewer)
		"diff":"common":[] -> Right (DiffTree ShowCommon)
		"diff":arg:[] -> Left ("Unknown argument to diff: '" ++ arg ++ "'. Use all,missing,additions,newer or common.\n")
		"diff":_:xs -> Left ("'diff' takes one argument("++show ((length xs)+1)++" given).\n")
		"update":[] -> Right Update
		"update":rest -> Left ("'update' takes zero arguments("++show (length rest)++" given).\n")
		"status":[] -> Right (Status "")
                "status":"toportage":[] -> Right (Status "toportage")
		"status":xs-> Left ("invalid argument(s) to 'status': " ++ show xs)
		"make-ebuild":[] -> Left "Need .cabal file to make ebuild."
		"make-ebuild":package:[] -> Right (MakeEbuild package)
		"make-ebuild":_:rest -> Left ("'make-ebuild' takes 1 argument("++show ((length rest)+1)++" given).\n")

		[] -> Right ShowHelp
		_ -> Left "Unknown opertation mode\n"
	in case mode of
		Left err -> Left err
		Right m -> Right (popts,m)

hackageUsage :: IO ()
hackageUsage = putStr $ flip usageInfo hackageOptions $ unlines
	[ "Usage:"
	, "\t\"hackport [OPTION] MODE [MODETARGET]\""
	, "\t\"hackport [OPTION] list [PKG]\" lists all packages or packages matching search term"
	, "\t\"hackport [OPTION] merge PKG-VERSION\" merges a package into the portage tree"
	, "\t\"hackport [OPTION] diff\" prints the difference between the portage-tree and the server's packages"
	, "\t\"hackport [OPTION] update\" updates the local cache"
	, "\t\"hackport [OPTION] status\" compares the overlay with the portage tree"
	, "\t\"hackport [OPTION] make-ebuild\" creates standalone ebuild from given .cabal file"
	, "Options:"
	]

parseVerbosity :: String -> Maybe Verbosity
parseVerbosity "debug" = Just Debug
parseVerbosity "normal" = Just Normal
parseVerbosity "silent" = Just Silent
parseVerbosity _ = Nothing