-- | -- Module : RPM -- Copyright : (C) 2015-2017 Jens Petersen -- -- Maintainer : Jens Petersen -- -- Explanation: RPM utils -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. module RPM (packageManager, repoquery, repoquerySrc, rpmInstall) where import Control.Monad (unless, when) import Data.List (elemIndices) import Data.Maybe (isJust, isNothing) import System.Directory (findExecutable) -- die is available in ghc-7.10 base-4.8 import System.Exit (exitFailure) import System.IO (hPutStrLn, stderr) import Utils (cmdStdErr, singleLine, sudo) -- @since base 4.8.0.0 die :: String -> IO a die err = hPutStrLn stderr err >> exitFailure warn :: String -> IO () warn = hPutStrLn stderr requireProgram :: String -> IO () requireProgram c = do mavail <- findExecutable c when (isNothing mavail) $ die (c ++ ": command not found") optionalProgram :: String -> IO Bool optionalProgram c = do mavail <- findExecutable c return $ isJust mavail packageManager :: IO String packageManager = do havednf <- optionalProgram "dnf" if havednf then return "dnf" else requireProgram "yum" >> return "yum" rpmInstall :: [String] -> IO () rpmInstall rpms = do pkginstaller <- packageManager let (inst, arg) = if pkginstaller == "dnf" then ("dnf", "install") else ("yum", "localinstall") sudo inst $ ["-y", "--nogpgcheck", arg] ++ rpms repoquery :: [String] -> String -> IO String repoquery args key = do havednf <- optionalProgram "dnf" let (prog, subcmd) = if havednf then ("dnf", ["repoquery", "--quiet"]) else ("repoquery", []) repoqWrap prog (subcmd ++ args ++ [key]) repoqWrap :: String -> [String] -> IO String repoqWrap cmd args = do (out, err) <- cmdStdErr cmd args -- workaround noisy dnf2 repoquery --quiet -- ignore "Last metadata expiration check" warnings unless (null err || head (words err) == "Last") $ warn err return $ singleLine out repoquerySrc :: String -> IO (Maybe String) repoquerySrc key = do havednf <- optionalProgram "dnf" let (prog, subcmd) = if havednf then ("dnf", ["repoquery", "--quiet", "-s"]) else ("repoquery", ["--qf", "%{base_package_name}", "--whatprovides"]) res <- repoqWrap prog (subcmd ++ [key]) if null res then return Nothing else return $ Just $ nvrToName res nvrToName :: String -> String nvrToName nvr = if length dashes < 2 then error $ "malformed NVR string: '" ++ nvr ++ "'" else take nameDash nvr where dashes = elemIndices '-' nvr nameDash = last $ init dashes