-- | Maintainer: 2016 Evan Cofsky -- -- FreeBSD pkgng properties {-# Language ScopedTypeVariables, GeneralizedNewtypeDeriving, DeriveDataTypeable #-} module Propellor.Property.FreeBSD.Pkg where import Propellor.Base import Propellor.Types.Info noninteractiveEnv :: [([Char], [Char])] noninteractiveEnv = [("ASSUME_ALWAYS_YES", "yes")] pkgCommand :: String -> [String] -> (String, [String]) pkgCommand cmd args = ("pkg", (cmd:args)) runPkg :: String -> [String] -> IO [String] runPkg cmd args = let (p, a) = pkgCommand cmd args in lines <$> readProcess p a pkgCmdProperty :: String -> [String] -> UncheckedProperty FreeBSD pkgCmdProperty cmd args = tightenTargets $ let (p, a) = pkgCommand cmd args in cmdPropertyEnv p a noninteractiveEnv pkgCmd :: String -> [String] -> IO [String] pkgCmd cmd args = let (p, a) = pkgCommand cmd args in lines <$> readProcessEnv p a (Just noninteractiveEnv) newtype PkgUpdate = PkgUpdate String deriving (Typeable, Monoid, Show) instance IsInfo PkgUpdate where propagateInfo _ = PropagateInfo False pkgUpdated :: PkgUpdate -> Bool pkgUpdated (PkgUpdate _) = True update :: Property (HasInfo + FreeBSD) update = let upd = pkgCmd "update" [] go = ifM (pkgUpdated <$> askInfo) ((noChange), (liftIO upd >> return MadeChange)) in (property "pkg update has run" go :: Property FreeBSD) `setInfoProperty` (toInfo (PkgUpdate "")) newtype PkgUpgrade = PkgUpgrade String deriving (Typeable, Monoid, Show) instance IsInfo PkgUpgrade where propagateInfo _ = PropagateInfo False pkgUpgraded :: PkgUpgrade -> Bool pkgUpgraded (PkgUpgrade _) = True upgrade :: Property (HasInfo + FreeBSD) upgrade = let upd = pkgCmd "upgrade" [] go = ifM (pkgUpgraded <$> askInfo) ((noChange), (liftIO upd >> return MadeChange)) in (property "pkg upgrade has run" go :: Property FreeBSD) `setInfoProperty` (toInfo (PkgUpdate "")) `requires` update type Package = String installed :: Package -> Property FreeBSD installed pkg = check (isInstallable pkg) $ pkgCmdProperty "install" [pkg] isInstallable :: Package -> IO Bool isInstallable p = (not <$> isInstalled p) <&&> exists p isInstalled :: Package -> IO Bool isInstalled p = (runPkg "info" [p] >> return True) `catchIO` (\_ -> return False) exists :: Package -> IO Bool exists p = (runPkg "search" ["--search", "name", "--exact", p] >> return True) `catchIO` (\_ -> return False)