{-# LANGUAGE ViewPatterns #-}
module Aura.Pacman
(
pacman
, pacmanOutput, pacmanSuccess, pacmanLines
, lockFile
, pacmanConfFile
, defaultLogFile
, getCachePath
, getLogFilePath
, getPacmanConf
, getIgnoredPkgs, getIgnoredGroups
, groupPackages
, versionInfo
, verMsgPad
) where
import Aura.Languages
import Aura.Settings.External
import Aura.Types
import RIO hiding (some, try)
import qualified RIO.ByteString as BS
import qualified RIO.ByteString.Lazy as BL
import RIO.FilePath
import RIO.Lens (_2)
import RIO.List.Partial ((!!))
import qualified RIO.Map as M
import qualified RIO.Set as S
import qualified RIO.Text as T
import System.Process.Typed
import Text.Megaparsec (parse)
pacmanConfFile :: FilePath
pacmanConfFile = "/etc/pacman.conf"
defaultLogFile :: FilePath
defaultLogFile = "/var/log/pacman.log"
lockFile :: FilePath
lockFile = "/var/lib/pacman/db.lck"
getPacmanConf :: FilePath -> IO (Either Failure Config)
getPacmanConf fp = do
file <- decodeUtf8Lenient <$> BS.readFile fp
pure . first (const (Failure confParsing_1)) $ parse config "pacman config" file
getIgnoredPkgs :: Config -> Set PkgName
getIgnoredPkgs (Config c) = maybe S.empty (S.fromList . map PkgName) $ M.lookup "IgnorePkg" c
getIgnoredGroups :: Config -> Set PkgGroup
getIgnoredGroups (Config c) = maybe S.empty (S.fromList . map PkgGroup) $ M.lookup "IgnoreGroup" c
groupPackages :: Environment -> NonEmpty PkgGroup -> IO (Set PkgName)
groupPackages env igs = fmap (f . decodeUtf8Lenient) . pacmanOutput env $ "-Qg" : asFlag igs
where
f :: Text -> Set PkgName
f = S.fromList . map (PkgName . (!! 1) . T.words) . T.lines
getCachePath :: Config -> Maybe FilePath
getCachePath (Config c) = do
fp <- T.unpack <$> (M.lookup "CacheDir" c >>= listToMaybe)
bool Nothing (Just fp) $ isAbsolute fp
getLogFilePath :: Config -> Maybe FilePath
getLogFilePath (Config c) = do
fp <- T.unpack <$> (M.lookup "LogFile" c >>= listToMaybe)
bool Nothing (Just fp) $ isAbsolute fp
pacmanProc :: Environment -> [String] -> ProcessConfig () () ()
pacmanProc env args = setEnv vars $ proc "pacman" args
where
vars :: [(String, String)]
vars = ("LC_ALL", "C") : maybe [] (\p -> [("PATH", T.unpack p)]) (M.lookup "PATH" env)
pacman :: Environment -> [Text] -> IO ()
pacman env (map T.unpack -> args) = do
ec <- runProcess $ pacmanProc env args
unless (ec == ExitSuccess) $ throwM (Failure pacmanFailure_1)
pacmanSuccess :: Environment -> [T.Text] -> IO Bool
pacmanSuccess env i = fmap (== ExitSuccess) . runProcess . setStderr closed . setStdout closed . pacmanProc env $ map T.unpack i
pacmanOutput :: Environment -> [Text] -> IO ByteString
pacmanOutput env i =
fmap (^. _2 . to BL.toStrict) . readProcess . pacmanProc env $ map T.unpack i
pacmanLines :: Environment -> [Text] -> IO [Text]
pacmanLines env s = T.lines . decodeUtf8Lenient <$> pacmanOutput env s
versionInfo :: Environment -> IO [Text]
versionInfo env = map (T.drop verMsgPad) <$> pacmanLines env ["-V"]
verMsgPad :: Int
verMsgPad = 23