craft-0.0.0.1: src/Craft/Hosts.hs
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Craft.Hosts
( IP(..)
, Name(..)
, Configs
, Hosts(..)
, Craft.Hosts.lookup
, hostsfp
, get
, parse
, showConfigs
, toFile
, fromFile
, insert
, deleteIP
, deleteName
, delete
, set
)
where
import Control.Lens hiding (noneOf, set)
import Control.Monad (zipWithM)
import qualified Data.ByteString.Char8 as B8
import qualified Data.List as L
import Data.Maybe (catMaybes)
import Craft
import qualified Craft.File as File
import Craft.Hosts.Parser
import Craft.Hosts.Types
lookup :: IP -> Hosts -> Maybe [Name]
lookup ip hosts = L.lookup ip $ configs hosts
hostsMap :: ((IP, [Name]) -> (IP, [Name])) -> Hosts -> Hosts
hostsMap f (Hosts cfgs) = Hosts $ Prelude.map f cfgs
get :: Craft Hosts
get =
File.getWithContent hostsfp >>= \case
Nothing -> $craftError $ fromAbsFile hostsfp ++ " not found!"
Just f -> case f ^. fileContent of
Nothing -> $craftError $ show hostsfp ++ " not found!"
Just bs -> parse $ B8.unpack bs
parse :: String -> Craft Hosts
parse s = do
r <- zipWithM parseLine [1..] $ lines s
return . Hosts $ catMaybes r
instance Craftable Hosts Hosts where
watchCraft hosts = do
(w, f) <- watchCraft $ toFile hosts
r <- fromFile f
return (w, r)
showConfigs :: Configs -> String
showConfigs = unlines . map (\(ip, as) -> unwords (show ip:map show as))
toFile :: Hosts -> File
toFile (Hosts cfgs) = file hostsfp & strContent .~ showConfigs cfgs
fromFile :: File -> Craft Hosts
fromFile f =
case f ^. fileContent of
Nothing -> return $ Hosts []
Just c -> parse $ B8.unpack c
insert :: IP -> Name -> Hosts -> Hosts
insert newip name (Hosts cfgs) = fixUp $ Hosts go
where
go | any ((== newip) . fst) cfgs = map f cfgs
| otherwise = cfgs ++ [(newip, [name])]
f (ip, names) | ip == newip && name `notElem` names = (ip, name:names)
| otherwise = (ip, names)
deleteIP :: IP -> Hosts -> Hosts
deleteIP ip (Hosts cfgs) = fixUp . Hosts $ filter (\(ip', _) -> ip' /= ip) cfgs
deleteName :: Name -> Hosts -> Hosts
deleteName name = fixUp . hostsMap f
where
f (ip', names) = (ip', filter (/= name) names)
delete :: IP -> Name -> Hosts -> Hosts
delete ip name = fixUp . hostsMap f
where
f (ip', names) | ip' == ip = (ip', filter (/= name) names)
| otherwise = (ip', names)
set :: Name -> IP -> Hosts -> Hosts
set name ip hosts = fixUp . insert ip name $ deleteName name hosts
----------------------------------------
-- ____ _ _ --
-- | _ \ _ __(_)_ ____ _| |_ ___ --
-- | |_) | '__| \ \ / / _` | __/ _ \ --
-- | __/| | | |\ V / (_| | || __/ --
-- |_| |_| |_| \_/ \__,_|\__\___| --
----------------------------------------
fixUp :: Hosts -> Hosts
fixUp (Hosts cfgs) = Hosts $ filter f cfgs
where
f (IP ip, names) = not (null ip) && not (null names)