packages feed

nvfetcher-0.2.0.0: app/Main.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}

module Main where

import Config
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Development.Shake
import NvFetcher
import Options.Applicative.Simple
import qualified Paths_nvfetcher as Paths
import qualified Toml

data CLIOptions = CLIOptions
  { configPath :: FilePath,
    outputPath :: FilePath,
    logPath :: Maybe FilePath,
    threads :: Int,
    timing :: Bool,
    verbose :: Bool,
    target :: String
  }
  deriving (Show)

cliOptionsParser :: Parser CLIOptions
cliOptionsParser =
  CLIOptions
    <$> strOption
      ( long "config"
          <> short 'c'
          <> metavar "FILE"
          <> help "Path to nvfetcher TOML config"
          <> value "nvfetcher.toml"
          <> showDefault
          <> completer (bashCompleter "file")
      )
      <*> strOption
        ( long "output"
            <> short 'o'
            <> metavar "FILE"
            <> help "Path to output nix file"
            <> showDefault
            <> value "sources.nix"
            <> completer (bashCompleter "file")
        )
      <*> optional
        ( strOption
            ( long "changelog"
                <> short 'l'
                <> metavar "FILE"
                <> help "Dump version changes to a file"
                <> completer (bashCompleter "file")
            )
        )
      <*> ( option
              auto
              ( short 'j'
                  <> metavar "NUM"
                  <> help "Number of threads (0: detected number of processors)"
                  <> value 0
                  <> showDefault
              )
          )
      <*> switch (long "timing" <> short 't' <> help "Show build time")
      <*> switch (long "verbose" <> short 'v' <> help "Verbose mode")
      <*> strArgument
        ( metavar "TARGET"
            <> help "Two targets are available: build and clean"
            <> value "build"
            <> completer (listCompleter ["build", "clean"])
        )

version :: String
version = $(simpleVersion Paths.version)

getCLIOptions :: IO CLIOptions
getCLIOptions = do
  (opts, ()) <-
    simpleOptions
      version
      "nvfetcher - generate nix sources expr for the latest version of packages"
      ( unlines
          [ "It's important to keep .shake dir to make caches work properly.",
            "If you change the version source or fetcher of an existing package, please run target \"clean\" to rebuild everything."
          ]
      )
      cliOptionsParser
      empty
  pure opts

main :: IO ()
main = do
  CLIOptions {..} <- getCLIOptions
  let args =
        defaultArgs
          { argOutputFilePath = outputPath,
            argActionAfterBuild = maybe (pure ()) logChangesToFile logPath,
            argTarget = target,
            argShakeOptions =
              (argShakeOptions defaultArgs)
                { shakeTimings = timing,
                  shakeVerbosity = if verbose then Verbose else Info,
                  shakeThreads = threads
                }
          }
  toml <- Toml.parse <$> T.readFile configPath
  case toml of
    Left e -> error $ T.unpack $ Toml.prettyTomlDecodeError $ Toml.ParseError e
    Right x -> case parseConfig x of
      Left e -> error $ T.unpack $ Toml.prettyTomlDecodeErrors e
      Right pkgs -> runNvFetcher args $ purePackageSet pkgs

logChangesToFile :: FilePath -> Action ()
logChangesToFile fp = do
  changes <- getVersionChanges
  writeFile' fp $ unlines $ show <$> changes