module Shellify (parseOptionsAndCalculateExpectedFiles, runShellify) where

import Prelude hiding (writeFile)
import Constants
import FlakeTemplate
import Options
import ShellifyTemplate
import TemplateGeneration

import Control.Monad (when, (>=>))
import Data.Bool (bool)
import Data.Text (pack, Text(), unpack)
import Data.Text.IO (hPutStrLn, writeFile)
import qualified Data.Text.IO as Text
import GHC.IO.Exception (ExitCode(ExitSuccess, ExitFailure))
import System.Directory (doesPathExist)
import System.Exit (exitWith)
import System.IO (stderr)

createAFile :: (Text, Text) -> IO ()
createAFile (Text
name, Text
content) = do ExitCode
extCde <- FilePath -> Text -> IO ExitCode
createFile (Text -> FilePath
unpack Text
name) Text
content
                                 forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ExitCode
extCde forall a. Eq a => a -> a -> Bool
/= ExitCode
ExitSuccess)
                                   forall a b. (a -> b) -> a -> b
$ forall a. ExitCode -> IO a
exitWith ExitCode
extCde


runShellify :: [Text] -> IO ()
runShellify :: [Text] -> IO ()
runShellify(Text
pName:[Text]
args) = IO (Either Text Text)
getRegistryDB
             forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
                   ((Text -> IO ExitCode
printErrorAndReturnFailure forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"Error calling nix registry: " <>) ) forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> forall a. ExitCode -> IO a
exitWith)
                   (\Text
registryDB -> forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Text -> IO ()
printError
                                          (forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Text, Text) -> IO ()
createAFile)
                                          forall a b. (a -> b) -> a -> b
$ Text -> Text -> [Text] -> Either Text [(Text, Text)]
parseOptionsAndCalculateExpectedFiles Text
registryDB Text
pName [Text]
args)


parseOptionsAndCalculateExpectedFiles :: Text -> Text -> [Text] -> Either Text [(Text,Text)]
parseOptionsAndCalculateExpectedFiles :: Text -> Text -> [Text] -> Either Text [(Text, Text)]
parseOptionsAndCalculateExpectedFiles Text
registry Text
programName =
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
    (\Options
opts ->
        (Text
"shell.nix", Options -> Text
generateShellDotNixText Options
opts)
      forall a. a -> [a] -> [a]
: forall b a. b -> (a -> b) -> Maybe a -> b
maybe
            []
            (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"flake.nix",))
            (Text -> Options -> Maybe Text
generateFlakeText Text
registry Options
opts))
  forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text] -> Either Text Options
options Text
programName

createFile :: FilePath -> Text -> IO ExitCode
createFile :: FilePath -> Text -> IO ExitCode
createFile FilePath
fileName Text
expectedContents = do
  Maybe Text
fileContents <-     FilePath -> IO Bool
doesPathExist FilePath
fileName
                  forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a. a -> a -> Bool -> a
bool
                       (forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing)
                       (forall a. a -> Maybe a
Just forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Text
Text.readFile FilePath
fileName)
  Text -> IO ()
printError forall a b. (a -> b) -> a -> b
$ Text -> Text -> Maybe Text -> Text
actionDescription (FilePath -> Text
pack FilePath
fileName) Text
expectedContents Maybe Text
fileContents
  forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Text -> Bool
shouldGenerateNewFile Maybe Text
fileContents)
    forall a b. (a -> b) -> a -> b
$ FilePath -> Text -> IO ()
writeFile FilePath
fileName Text
expectedContents
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> ExitCode
returnCode Text
expectedContents Maybe Text
fileContents

actionDescription :: Text -> Text -> Maybe Text -> Text
actionDescription :: Text -> Text -> Maybe Text -> Text
actionDescription Text
fName Text
_ Maybe Text
Nothing = Text
fName forall a. Semigroup a => a -> a -> a
<> Text
" does not exist. Creating one"
actionDescription Text
fName Text
a (Just Text
b) | Text
a forall a. Eq a => a -> a -> Bool
== Text
b = Text
"The existing " forall a. Semigroup a => a -> a -> a
<> Text
fName forall a. Semigroup a => a -> a -> a
<> Text
" is good already"
actionDescription Text
fName Text
_ Maybe Text
_ = Text
"A " forall a. Semigroup a => a -> a -> a
<> Text
fName forall a. Semigroup a => a -> a -> a
<> Text
" exists already. Delete it or move it and try again"

returnCode :: Text -> Maybe Text -> ExitCode
returnCode :: Text -> Maybe Text -> ExitCode
returnCode Text
_ Maybe Text
Nothing = ExitCode
ExitSuccess
returnCode Text
a (Just Text
b) | Text
a forall a. Eq a => a -> a -> Bool
== Text
b = ExitCode
ExitSuccess
returnCode Text
_ Maybe Text
_ = Int -> ExitCode
ExitFailure Int
1

shouldGenerateNewFile :: Maybe Text -> Bool
shouldGenerateNewFile :: Maybe Text -> Bool
shouldGenerateNewFile = (forall a. Eq a => a -> a -> Bool
== forall a. Maybe a
Nothing)

printErrorAndReturnFailure :: Text -> IO ExitCode
printErrorAndReturnFailure Text
err = Text -> IO ()
printError Text
err forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> ExitCode
ExitFailure Int
1)
printError :: Text -> IO ()
printError = Handle -> Text -> IO ()
hPutStrLn Handle
stderr