module Main ( main ) where import Data.Semigroup ((<>)) import Data.Time (UTCTime, defaultTimeLocale, parseTimeM) import qualified Distribution.Compat.ReadP as P import Distribution.System (Arch (..), OS (..), Platform (..), buildPlatform) import Distribution.Text (display) import Options.Applicative import Stack2nix import System.IO (BufferMode (..), hSetBuffering, stderr, stdout) args :: Parser Args args = Args <$> optional (strOption $ long "revision" <> help "revision to use when fetching from VCS") <*> optional (strOption $ short 'o' <> help "output file for generated nix expression" <> metavar "PATH") <*> strOption (long "stack-yaml" <> help "Override project stack.yaml file" <> showDefault <> value "stack.yaml") <*> option auto (short 'j' <> help "number of threads for subprocesses" <> showDefault <> value 4 <> metavar "INT") <*> switch (long "test" <> help "enable tests") <*> switch (long "bench" <> help "enable benchmarks") <*> switch (long "haddock" <> help "enable documentation generation") <*> optional (option utcTimeReader (long "hackage-snapshot" <> help "hackage snapshot time, ISO format")) <*> option (readP platformReader) (long "platform" <> help "target platform to use when invoking stack or cabal2nix" <> value buildPlatform <> showDefaultWith display) <*> strArgument (metavar "URI") <*> flag True False (long "no-indent" <> help "disable indentation and place one item per line") <*> switch (long "verbose" <> help "verbose output") where -- | A parser for the date. Hackage updates happen maybe once or twice a month. -- Example: parseTime defaultTimeLocale "%FT%T%QZ" "2017-11-20T12:18:35Z" :: Maybe UTCTime utcTimeReader :: ReadM UTCTime utcTimeReader = eitherReader $ \arg -> case parseTimeM True defaultTimeLocale "%FT%T%QZ" arg of Nothing -> Left $ "Cannot parse date, ISO format used ('2017-11-20T12:18:35Z'): " ++ arg Just utcTime -> Right utcTime -- | A String parser for Distribution.System.Platform -- | Copied from cabal2nix/src/Cabal2nix.hs platformReader :: P.ReadP r Platform platformReader = do arch <- P.choice [ P.string "i686" >> return I386 , P.string "x86_64" >> return X86_64 ] _ <- P.char '-' os <- P.choice [ P.string "linux" >> return Linux , P.string "osx" >> return OSX , P.string "darwin" >> return OSX ] return (Platform arch os) readP :: P.ReadP a a -> ReadM a readP p = eitherReader $ \s -> case [ r' | (r',"") <- P.readP_to_S p s ] of (r:_) -> Right r _ -> Left ("invalid value " ++ show s) main :: IO () main = do hSetBuffering stdout LineBuffering hSetBuffering stderr LineBuffering stack2nix =<< execParser opts where opts = info (helper <*> infoOption ("stack2nix " ++ display version) (long "version" <> help "Show version number") <*> args) $ fullDesc <> progDesc "Generate a nix expression for a Haskell package using stack"