packages feed

smerdyakov-0.0.0.0: src/Smerdyakov/System.hs

{-# LANGUAGE CPP #-}
module Smerdyakov.System
  {-# WARNING "This is for me, not you." #-}
  where

import Data.Monoid ((<>))
import Control.Monad
import GHC.TypeLits
import GHC.Generics (Generic)
import Data.String (IsString(..))
import System.Exit (ExitCode(..))

import Smerdyakov.Internal.Class
import Smerdyakov.Internal.FreeIO

data Executable (s :: Symbol) = Executable String
  deriving (Eq, Show, Read, Generic)

data Sudo = Sudo
  deriving (Eq, Show, Read, Generic)

instance Gives Sudo where
  give = do
    -- This is not ideal, since attempts to sudo are logged and may result in
    -- warnings
    (exitStatus, _, _) <- shellA "sudo -n true"
    case exitStatus of
      ExitFailure _ -> throwA $ ExpectationFailure "Need sudo"
      ExitSuccess   -> return Sudo

instance Gives KnownOS where
  give = do
    uname <- shellWithErrA "uname"
    case uname of
      "Darwin" -> return OSXOS
      "Linux"  -> do
        x <- shellWithErrA "lsb_release -is"
        case x of
          "Ubuntu" -> return UbuntuOS
          "Debian" -> return DebianOS
          "Arch"   -> return ArchOS
          d        -> throwA . ExpectationFailure $ "Unknown distro: " <> d
      d        -> throwA . ExpectationFailure $ "Unknown distro: " <> d

instance (Needs KnownOS, Needs Sudo) => Gives (Executable "ack") where
  give = do
    Sudo <- give
    getPackage "ack-grep"
    return $ Executable "ack-grep"


data PackageDetails
  = PackageDetails
  { homebrew :: String
  , aptGet   :: String
  , pacman   :: String
  } deriving (Eq, Show, Read, Generic)

getPackage :: (Needs KnownOS) => PackageDetails -> Action ()
getPackage deets = do
  os <- give
  let run = void . shellWithErrA
  case os of
    OSXOS    -> run $ "brew install " <> homebrew deets
    UbuntuOS -> give >>= \Sudo -> run $ "sudo apt-get install " <> aptGet deets
    DebianOS -> give >>= \Sudo -> run $ "sudo apt-get install " <> aptGet deets
    ArchOS   -> give >>= \Sudo -> run $ "pacman -S " <> pacman deets


instance IsString PackageDetails where
  fromString s = PackageDetails s s s


-- * Operating systems



data KnownOS
  = DebianOS
  | ArchOS
  | UbuntuOS
  | OSXOS
  deriving (Eq, Show, Read, Generic)

{-
data Debian = Debian
data Arch = Arch
data OSX = OSX
data Linux = Linux
data Homebrew
type family PackageManagerNeeds a where
  PackageManagerNeeds Debian = ()
  PackageManagerNeeds Arch   = ()
  PackageManagerNeeds OSX    = Homebrew
-- This function generates a @Gives@ declaration with the OS and distribution
-- of the machine in which the program is compiled.
mkOSDec :: Q Dec
mkOSDec = do
  [d| instance Gives $osT where give = return $osC |]
  [d| hostOs :: HostOS ; hostOS = $hos |]
  -}