module Portage.Host
( getInfo
, LocalInfo(..)
) where
import Util (run_cmd)
import qualified Data.List.Split as DLS
import Data.Maybe (fromJust, isJust, mapMaybe)
import qualified System.Directory as D
import System.FilePath ((</>))
import System.IO
data LocalInfo =
LocalInfo { LocalInfo -> String
distfiles_dir :: String
, LocalInfo -> [String]
overlay_list :: [FilePath]
, LocalInfo -> String
portage_dir :: FilePath
} deriving (ReadPrec [LocalInfo]
ReadPrec LocalInfo
Int -> ReadS LocalInfo
ReadS [LocalInfo]
(Int -> ReadS LocalInfo)
-> ReadS [LocalInfo]
-> ReadPrec LocalInfo
-> ReadPrec [LocalInfo]
-> Read LocalInfo
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [LocalInfo]
$creadListPrec :: ReadPrec [LocalInfo]
readPrec :: ReadPrec LocalInfo
$creadPrec :: ReadPrec LocalInfo
readList :: ReadS [LocalInfo]
$creadList :: ReadS [LocalInfo]
readsPrec :: Int -> ReadS LocalInfo
$creadsPrec :: Int -> ReadS LocalInfo
Read, Int -> LocalInfo -> ShowS
[LocalInfo] -> ShowS
LocalInfo -> String
(Int -> LocalInfo -> ShowS)
-> (LocalInfo -> String)
-> ([LocalInfo] -> ShowS)
-> Show LocalInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LocalInfo] -> ShowS
$cshowList :: [LocalInfo] -> ShowS
show :: LocalInfo -> String
$cshow :: LocalInfo -> String
showsPrec :: Int -> LocalInfo -> ShowS
$cshowsPrec :: Int -> LocalInfo -> ShowS
Show)
defaultInfo :: LocalInfo
defaultInfo :: LocalInfo
defaultInfo = LocalInfo :: String -> [String] -> String -> LocalInfo
LocalInfo { distfiles_dir :: String
distfiles_dir = String
"/usr/portage/distfiles"
, overlay_list :: [String]
overlay_list = []
, portage_dir :: String
portage_dir = String
"/usr/portage"
}
getInfo :: IO LocalInfo
getInfo :: IO LocalInfo
getInfo = Maybe LocalInfo -> LocalInfo
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe LocalInfo -> LocalInfo)
-> IO (Maybe LocalInfo) -> IO LocalInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap`
[IO (Maybe LocalInfo)] -> IO (Maybe LocalInfo)
forall (m :: * -> *) a. Monad m => [m (Maybe a)] -> m (Maybe a)
performMaybes [ IO (Maybe LocalInfo)
readConfig
, [IO (Maybe LocalInfo)] -> IO (Maybe LocalInfo)
forall (m :: * -> *) a. Monad m => [m (Maybe a)] -> m (Maybe a)
performMaybes [ IO (Maybe LocalInfo)
getPaludisInfo
, IO (Maybe LocalInfo)
askPortageq
, Maybe LocalInfo -> IO (Maybe LocalInfo)
forall (m :: * -> *) a. Monad m => a -> m a
return (LocalInfo -> Maybe LocalInfo
forall a. a -> Maybe a
Just LocalInfo
defaultInfo)
] IO (Maybe LocalInfo)
-> (Maybe LocalInfo -> IO (Maybe LocalInfo))
-> IO (Maybe LocalInfo)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe LocalInfo -> IO (Maybe LocalInfo)
showAnnoyingWarning
]
where performMaybes :: [m (Maybe a)] -> m (Maybe a)
performMaybes [] = Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
performMaybes (m (Maybe a)
act:[m (Maybe a)]
acts) =
do Maybe a
r <- m (Maybe a)
act
if Maybe a -> Bool
forall a. Maybe a -> Bool
isJust Maybe a
r
then Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
r
else [m (Maybe a)] -> m (Maybe a)
performMaybes [m (Maybe a)]
acts
showAnnoyingWarning :: Maybe LocalInfo -> IO (Maybe LocalInfo)
showAnnoyingWarning :: Maybe LocalInfo -> IO (Maybe LocalInfo)
showAnnoyingWarning Maybe LocalInfo
info = do
Handle -> String -> IO ()
hPutStr Handle
stderr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines [ String
"-- Consider creating ~/" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
hackport_config String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" file with contents:"
, Maybe LocalInfo -> String
forall a. Show a => a -> String
show Maybe LocalInfo
info
, String
"-- It will speed hackport startup time a bit."
]
Maybe LocalInfo -> IO (Maybe LocalInfo)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe LocalInfo
info
hackport_config :: FilePath
hackport_config :: String
hackport_config = String
".hackport" String -> ShowS
</> String
"repositories"
readConfig :: IO (Maybe LocalInfo)
readConfig :: IO (Maybe LocalInfo)
readConfig =
do String
home_dir <- IO String
D.getHomeDirectory
let config_path :: String
config_path = String
home_dir String -> ShowS
</> String
hackport_config
Bool
exists <- String -> IO Bool
D.doesFileExist String
config_path
if Bool
exists then String -> Maybe LocalInfo
forall a. Read a => String -> a
read (String -> Maybe LocalInfo) -> IO String -> IO (Maybe LocalInfo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO String
readFile String
config_path else Maybe LocalInfo -> IO (Maybe LocalInfo)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe LocalInfo
forall a. Maybe a
Nothing
getPaludisInfo :: IO (Maybe LocalInfo)
getPaludisInfo :: IO (Maybe LocalInfo)
getPaludisInfo = (String -> LocalInfo) -> Maybe String -> Maybe LocalInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> LocalInfo
parsePaludisInfo (Maybe String -> Maybe LocalInfo)
-> IO (Maybe String) -> IO (Maybe LocalInfo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO (Maybe String)
run_cmd String
"cave info"
parsePaludisInfo :: String -> LocalInfo
parsePaludisInfo :: String -> LocalInfo
parsePaludisInfo String
text =
let chunks :: [[String]]
chunks = [String] -> [String] -> [[String]]
forall a. Eq a => [a] -> [a] -> [[a]]
DLS.splitOn [String
""] ([String] -> [[String]])
-> (String -> [String]) -> String -> [[String]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines (String -> [[String]]) -> String -> [[String]]
forall a b. (a -> b) -> a -> b
$ String
text
repositories :: [(String, (String, String))]
repositories = ([String] -> Maybe (String, (String, String)))
-> [[String]] -> [(String, (String, String))]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe [String] -> Maybe (String, (String, String))
parseRepository [[String]]
chunks
in Maybe LocalInfo -> LocalInfo
forall a. HasCallStack => Maybe a -> a
fromJust ([(String, (String, String))] -> Maybe LocalInfo
mkLocalInfo [(String, (String, String))]
repositories)
where
parseRepository :: [String] -> Maybe (String, (String, String))
parseRepository :: [String] -> Maybe (String, (String, String))
parseRepository [] = Maybe (String, (String, String))
forall a. Maybe a
Nothing
parseRepository (String
firstLine:[String]
lns) = do
String
name <- case String -> [String]
words String
firstLine of
[String
"Repository", String
nm] -> String -> Maybe String
forall (m :: * -> *) a. Monad m => a -> m a
return (ShowS
forall a. [a] -> [a]
init String
nm)
[String]
_ -> String -> Maybe String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"not a repository chunk"
let dict :: [(String, String)]
dict = [ ([String] -> String
forall a. [a] -> a
head [String]
ln, [String] -> String
unwords ([String] -> [String]
forall a. [a] -> [a]
tail [String]
ln)) | [String]
ln <- (String -> [String]) -> [String] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map String -> [String]
words [String]
lns ]
String
location <- String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"location" [(String, String)]
dict
String
distfiles <- String -> [(String, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"distdir" [(String, String)]
dict
(String, (String, String)) -> Maybe (String, (String, String))
forall (m :: * -> *) a. Monad m => a -> m a
return (String
name, (String
location, String
distfiles))
mkLocalInfo :: [(String, (String, String))] -> Maybe LocalInfo
mkLocalInfo :: [(String, (String, String))] -> Maybe LocalInfo
mkLocalInfo [(String, (String, String))]
repos = do
(String
gentooLocation, String
gentooDistfiles) <- String -> [(String, (String, String))] -> Maybe (String, String)
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
"gentoo" [(String, (String, String))]
repos
let overlays :: [String]
overlays = [ String
loc | (String
_, (String
loc, String
_dist)) <- [(String, (String, String))]
repos ]
LocalInfo -> Maybe LocalInfo
forall (m :: * -> *) a. Monad m => a -> m a
return (LocalInfo :: String -> [String] -> String -> LocalInfo
LocalInfo
{ distfiles_dir :: String
distfiles_dir = String
gentooDistfiles
, portage_dir :: String
portage_dir = String
gentooLocation
, overlay_list :: [String]
overlay_list = [String]
overlays
})
askPortageq :: IO (Maybe LocalInfo)
askPortageq :: IO (Maybe LocalInfo)
askPortageq = do
Maybe String
distdir <- String -> IO (Maybe String)
run_cmd String
"portageq distdir"
Maybe String
portdir <- String -> IO (Maybe String)
run_cmd String
"portageq get_repo_path / gentoo"
Maybe String
hsRepo <- String -> IO (Maybe String)
run_cmd String
"portageq get_repo_path / haskell"
let info :: Maybe LocalInfo
info = if Maybe String
forall a. Maybe a
Nothing Maybe String -> [Maybe String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Maybe String
distdir,Maybe String
portdir]
then Maybe LocalInfo
forall a. Maybe a
Nothing
else LocalInfo -> Maybe LocalInfo
forall a. a -> Maybe a
Just LocalInfo :: String -> [String] -> String -> LocalInfo
LocalInfo
{ distfiles_dir :: String
distfiles_dir = Maybe String -> String
forall a. Maybe [a] -> [a]
grab Maybe String
distdir
, portage_dir :: String
portage_dir = Maybe String -> String
forall a. Maybe [a] -> [a]
grab Maybe String
portdir
, overlay_list :: [String]
overlay_list = Maybe String -> [String]
forall a. Maybe [a] -> [[a]]
iffy Maybe String
hsRepo
}
where grab :: Maybe [a] -> [a]
grab = [a] -> [a]
forall a. [a] -> [a]
init ([a] -> [a]) -> (Maybe [a] -> [a]) -> Maybe [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe [a] -> [a]
forall a. HasCallStack => Maybe a -> a
fromJust
iffy :: Maybe [a] -> [[a]]
iffy Maybe [a]
Nothing = []
iffy (Just [a]
repo) = [[a] -> [a]
forall a. [a] -> [a]
init [a]
repo]
Maybe LocalInfo -> IO (Maybe LocalInfo)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe LocalInfo
info