module Language.ATS.Package.Exec ( exec
) where
import Control.Composition
import Control.Lens hiding (argument)
import Control.Monad
import Data.Bool (bool)
import Data.Maybe (fromMaybe)
import Data.Semigroup (Semigroup (..))
import qualified Data.Text.Lazy as TL
import Data.Version hiding (Version (..))
import Development.Shake.FilePath
import Language.ATS.Package.Build
import Language.ATS.Package.Compiler
import Language.ATS.Package.Dependency
import Language.ATS.Package.Type hiding (test, version)
import Options.Applicative hiding (auto)
import Paths_ats_pkg
import System.Directory
import System.Environment (getEnv)
import System.IO.Temp (withSystemTempDirectory)
wrapper :: ParserInfo Command
wrapper = info (helper <*> versionInfo <*> command')
(fullDesc
<> progDesc "The atspkg build tool for ATS-Postiats."
<> header "atspkg - a build tool for ATS")
versionInfo :: Parser (a -> a)
versionInfo = infoOption ("atspkg version: " ++ showVersion version) (short 'v' <> long "version" <> help "Show version")
data Command = Install
| Build { _targets :: [String], _recache :: Bool }
| Clean
| Test
| Fetch { _url :: String }
| Nuke
command' :: Parser Command
command' = hsubparser
(command "install" (info (pure Install) (progDesc "Install all binaries to $HOME/.local/bin"))
<> command "clean" (info (pure Clean) (progDesc "Clean current project directory"))
<> command "remote" (info fetch (progDesc "Fetch and install a binary package"))
<> command "build" (info build (progDesc "Build current package targets"))
<> command "test" (info (pure Test) (progDesc "Test current package"))
<> command "nuke" (info (pure Nuke) (progDesc "Uninstall all globally installed libraries"))
)
build :: Parser Command
build = Build
<$> many
(argument str
(metavar "TARGET"
<> help "Targets to build"))
<*> switch
(long "no-cache"
<> help "Turn off configuration caching")
fetch :: Parser Command
fetch = Fetch <$>
argument str
(metavar "URL"
<> help "URL pointing to a tarball containing the package to be installed.")
check :: Maybe FilePath -> IO Bool
check p = do
home <- getEnv "HOME"
v <- want p
doesFileExist (home ++ "/.atspkg/" ++ show v ++ "/bin/patscc")
getSubdirs :: FilePath -> IO [FilePath]
getSubdirs p = do
ds <- listDirectory p
case ds of
[] -> pure []
xs -> filterM doesDirectoryExist (((p <> "/") <>) <$> xs)
fetchPkg :: String -> IO ()
fetchPkg pkg = withSystemTempDirectory "atspkg" $ \p -> do
let (lib, dirName, url') = ("atspkg", p, pkg) & each %~ TL.pack
fetchDeps True mempty [Dependency lib dirName url' undefined] []
ps <- getSubdirs p
pkgDir <- fromMaybe p <$> findFile (p:ps) "atspkg.dhall"
let a = withCurrentDirectory (takeDirectory pkgDir) (mkPkg mempty ["install"])
bool (buildAll (Just pkgDir) >> a) a =<< check (Just pkgDir)
exec :: IO ()
exec = execParser wrapper >>= run
run :: Command -> IO ()
run Nuke = cleanAll
run (Fetch u) = fetchPkg u
run Clean = mkPkg mempty ["clean"]
run c = bool (mkPkg [buildAll Nothing] rs) (mkPkg mempty rs) =<< check Nothing
where rs = g c
g Install = ["install"]
g (Build ts _) = ts
g Test = ["test"]
g _ = undefined
want :: Maybe FilePath -> IO Version
want p = compiler <$> getConfig p
buildAll :: Maybe FilePath -> IO ()
buildAll p = on (>>) (=<< want p) fetchCompiler setupCompiler