{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}
module Test.Sandwich.WebDriver.Internal.Binaries (
obtainSelenium
, obtainChromeDriver
, obtainGeckoDriver
, downloadSeleniumIfNecessary
, downloadChromeDriverIfNecessary
) where
import Control.Exception
import Control.Monad
import Control.Monad.Catch
import Control.Monad.IO.Class
import Control.Monad.Logger
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Monad.Trans.Except
import Data.String.Interpolate
import qualified Data.Text as T
import GHC.Stack
import System.Directory
import System.FilePath
import System.IO.Temp
import System.Process
import Test.Sandwich.Logging
import Test.Sandwich.WebDriver.Internal.Binaries.DetectChrome
import Test.Sandwich.WebDriver.Internal.Binaries.DetectFirefox
import Test.Sandwich.WebDriver.Internal.Binaries.DetectPlatform
import Test.Sandwich.WebDriver.Internal.Types
import Test.Sandwich.WebDriver.Internal.Util
type Constraints m = (
HasCallStack
, MonadLogger m
, MonadIO m
, MonadBaseControl IO m
, MonadMask m
)
obtainSelenium :: (MonadIO m, MonadLogger m) => FilePath -> SeleniumToUse -> m (Either T.Text FilePath)
obtainSelenium :: forall (m :: * -> *).
(MonadIO m, MonadLogger m) =>
FilePath -> SeleniumToUse -> m (Either Text FilePath)
obtainSelenium FilePath
toolsDir (DownloadSeleniumFrom FilePath
url) = do
let seleniumPath :: FilePath
seleniumPath = [i|#{toolsDir}/selenium-server-standalone.jar|]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True (FilePath -> FilePath
takeDirectory FilePath
seleniumPath)
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
seleniumPath) forall a b. (a -> b) -> a -> b
$
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> CreateProcess
shell [i|curl #{url} -o #{seleniumPath}|]) FilePath
""
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right FilePath
seleniumPath
obtainSelenium FilePath
toolsDir SeleniumToUse
DownloadSeleniumDefault = do
let seleniumPath :: FilePath
seleniumPath = [i|#{toolsDir}/selenium-server-standalone-3.141.59.jar|]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True (FilePath -> FilePath
takeDirectory FilePath
seleniumPath)
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
seleniumPath) forall a b. (a -> b) -> a -> b
$
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> CreateProcess
shell [i|curl https://selenium-release.storage.googleapis.com/3.141/selenium-server-standalone-3.141.59.jar -o #{seleniumPath}|]) FilePath
""
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right FilePath
seleniumPath
obtainSelenium FilePath
_ (UseSeleniumAt FilePath
path) = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO Bool
doesFileExist FilePath
path) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
False -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left [i|Path '#{path}' didn't exist|]
Bool
True -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right FilePath
path
obtainChromeDriver :: (
MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadMask m
) => FilePath -> ChromeDriverToUse -> m (Either T.Text FilePath)
obtainChromeDriver :: forall (m :: * -> *).
(MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadMask m) =>
FilePath -> ChromeDriverToUse -> m (Either Text FilePath)
obtainChromeDriver FilePath
toolsDir (DownloadChromeDriverFrom FilePath
url) = do
let path :: FilePath
path = [i|#{toolsDir}/#{chromeDriverExecutable}|]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True (FilePath -> FilePath
takeDirectory FilePath
path)
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
path) forall a b. (a -> b) -> a -> b
$
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> CreateProcess
shell [i|curl #{url} -o #{path}|]) FilePath
""
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right FilePath
path
obtainChromeDriver FilePath
toolsDir (DownloadChromeDriverVersion ChromeDriverVersion
chromeDriverVersion) = forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT forall a b. (a -> b) -> a -> b
$ do
let path :: FilePath
path = FilePath -> ChromeDriverVersion -> FilePath
getChromeDriverPath FilePath
toolsDir ChromeDriverVersion
chromeDriverVersion
(forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
path) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
path
Bool
False -> do
let downloadPath :: Text
downloadPath = ChromeDriverVersion -> Platform -> Text
getChromeDriverDownloadUrl ChromeDriverVersion
chromeDriverVersion Platform
detectPlatform
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
(MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadMask m) =>
Text -> FilePath -> m (Either Text ())
downloadAndUnzipToPath Text
downloadPath FilePath
path
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
path
obtainChromeDriver FilePath
toolsDir (DownloadChromeDriverAutodetect Maybe FilePath
maybeChromePath) = forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT forall a b. (a -> b) -> a -> b
$ do
ChromeDriverVersion
version <- forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Maybe FilePath -> IO (Either Text ChromeDriverVersion)
getChromeDriverVersion Maybe FilePath
maybeChromePath
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
(MonadIO m, MonadLogger m, MonadBaseControl IO m, MonadMask m) =>
FilePath -> ChromeDriverToUse -> m (Either Text FilePath)
obtainChromeDriver FilePath
toolsDir (ChromeDriverVersion -> ChromeDriverToUse
DownloadChromeDriverVersion ChromeDriverVersion
version)
obtainChromeDriver FilePath
_ (UseChromeDriverAt FilePath
path) = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO Bool
doesFileExist FilePath
path) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
False -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left [i|Path '#{path}' didn't exist|]
Bool
True -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right FilePath
path
obtainGeckoDriver :: (MonadIO m, MonadLogger m, MonadBaseControl IO m) => FilePath -> GeckoDriverToUse -> m (Either T.Text FilePath)
obtainGeckoDriver :: forall (m :: * -> *).
(MonadIO m, MonadLogger m, MonadBaseControl IO m) =>
FilePath -> GeckoDriverToUse -> m (Either Text FilePath)
obtainGeckoDriver FilePath
toolsDir (DownloadGeckoDriverFrom FilePath
url) = do
let path :: FilePath
path = [i|#{toolsDir}/#{geckoDriverExecutable}|]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True (FilePath -> FilePath
takeDirectory FilePath
path)
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
path) forall a b. (a -> b) -> a -> b
$
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> CreateProcess
shell [i|curl #{url} -o #{path}|]) FilePath
""
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right FilePath
path
obtainGeckoDriver FilePath
toolsDir (DownloadGeckoDriverVersion GeckoDriverVersion
geckoDriverVersion) = forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT forall a b. (a -> b) -> a -> b
$ do
let path :: FilePath
path = FilePath -> GeckoDriverVersion -> FilePath
getGeckoDriverPath FilePath
toolsDir GeckoDriverVersion
geckoDriverVersion
(forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
path) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
path
Bool
False -> do
let downloadPath :: Text
downloadPath = GeckoDriverVersion -> Platform -> Text
getGeckoDriverDownloadUrl GeckoDriverVersion
geckoDriverVersion Platform
detectPlatform
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
(MonadIO m, MonadBaseControl IO m, MonadLogger m) =>
Text -> FilePath -> m (Either Text ())
downloadAndUntarballToPath Text
downloadPath FilePath
path
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
path
obtainGeckoDriver FilePath
toolsDir (DownloadGeckoDriverAutodetect Maybe FilePath
maybeFirefoxPath) = forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT forall a b. (a -> b) -> a -> b
$ do
GeckoDriverVersion
version <- forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Maybe FilePath -> IO (Either Text GeckoDriverVersion)
getGeckoDriverVersion Maybe FilePath
maybeFirefoxPath
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
(MonadIO m, MonadLogger m, MonadBaseControl IO m) =>
FilePath -> GeckoDriverToUse -> m (Either Text FilePath)
obtainGeckoDriver FilePath
toolsDir (GeckoDriverVersion -> GeckoDriverToUse
DownloadGeckoDriverVersion GeckoDriverVersion
version)
obtainGeckoDriver FilePath
_ (UseGeckoDriverAt FilePath
path) = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO Bool
doesFileExist FilePath
path) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
False -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. a -> Either a b
Left [i|Path '#{path}' didn't exist|]
Bool
True -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. b -> Either a b
Right FilePath
path
downloadSeleniumIfNecessary :: Constraints m => FilePath -> m (Either T.Text FilePath)
downloadSeleniumIfNecessary :: forall (m :: * -> *).
Constraints m =>
FilePath -> m (Either Text FilePath)
downloadSeleniumIfNecessary FilePath
toolsDir = forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
m a -> m (Either Text a)
leftOnException' forall a b. (a -> b) -> a -> b
$ do
let seleniumPath :: FilePath
seleniumPath = [i|#{toolsDir}/selenium-server.jar|]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO Bool
doesFileExist FilePath
seleniumPath) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (m :: * -> *). Constraints m => FilePath -> m ()
downloadSelenium FilePath
seleniumPath)
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
seleniumPath
downloadSelenium :: Constraints m => FilePath -> m ()
downloadSelenium :: forall (m :: * -> *). Constraints m => FilePath -> m ()
downloadSelenium FilePath
seleniumPath = forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ do
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
info [i|Downloading selenium-server.jar to #{seleniumPath}|]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True (FilePath -> FilePath
takeDirectory FilePath
seleniumPath)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> CreateProcess
shell [i|curl https://selenium-release.storage.googleapis.com/3.141/selenium-server-standalone-3.141.59.jar -o #{seleniumPath}|]) FilePath
""
downloadChromeDriverIfNecessary' :: Constraints m => FilePath -> ChromeDriverVersion -> m (Either T.Text FilePath)
downloadChromeDriverIfNecessary' :: forall (m :: * -> *).
Constraints m =>
FilePath -> ChromeDriverVersion -> m (Either Text FilePath)
downloadChromeDriverIfNecessary' FilePath
toolsDir ChromeDriverVersion
chromeDriverVersion = forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT forall a b. (a -> b) -> a -> b
$ do
let chromeDriverPath :: FilePath
chromeDriverPath = FilePath -> ChromeDriverVersion -> FilePath
getChromeDriverPath FilePath
toolsDir ChromeDriverVersion
chromeDriverVersion
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM (forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
chromeDriverPath) forall a b. (a -> b) -> a -> b
$ do
let downloadPath :: Text
downloadPath = ChromeDriverVersion -> Platform -> Text
getChromeDriverDownloadUrl ChromeDriverVersion
chromeDriverVersion Platform
detectPlatform
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
(MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadMask m) =>
Text -> FilePath -> m (Either Text ())
downloadAndUnzipToPath Text
downloadPath FilePath
chromeDriverPath
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
chromeDriverPath
downloadChromeDriverIfNecessary :: Constraints m => Maybe FilePath -> FilePath -> m (Either T.Text FilePath)
downloadChromeDriverIfNecessary :: forall (m :: * -> *).
Constraints m =>
Maybe FilePath -> FilePath -> m (Either Text FilePath)
downloadChromeDriverIfNecessary Maybe FilePath
maybeChromePath FilePath
toolsDir = forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT forall a b. (a -> b) -> a -> b
$ do
ChromeDriverVersion
chromeDriverVersion <- forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Maybe FilePath -> IO (Either Text ChromeDriverVersion)
getChromeDriverVersion Maybe FilePath
maybeChromePath
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
Constraints m =>
FilePath -> ChromeDriverVersion -> m (Either Text FilePath)
downloadChromeDriverIfNecessary' FilePath
toolsDir ChromeDriverVersion
chromeDriverVersion
getChromeDriverPath :: FilePath -> ChromeDriverVersion -> FilePath
getChromeDriverPath :: FilePath -> ChromeDriverVersion -> FilePath
getChromeDriverPath FilePath
toolsDir (ChromeDriverVersionTuple (Int
w, Int
x, Int
y, Int
z)) = [i|#{toolsDir}/chromedrivers/#{w}.#{x}.#{y}.#{z}/#{chromeDriverExecutable}|]
getChromeDriverPath FilePath
toolsDir (ChromeDriverVersionExactUrl (Int
w, Int
x, Int
y, Int
z) Text
_) = [i|#{toolsDir}/chromedrivers/#{w}.#{x}.#{y}.#{z}/#{chromeDriverExecutable}|]
getGeckoDriverPath :: FilePath -> GeckoDriverVersion -> FilePath
getGeckoDriverPath :: FilePath -> GeckoDriverVersion -> FilePath
getGeckoDriverPath FilePath
toolsDir (GeckoDriverVersion (Int
x, Int
y, Int
z)) = [i|#{toolsDir}/geckodrivers/#{x}.#{y}.#{z}/#{geckoDriverExecutable}|]
chromeDriverExecutable :: T.Text
chromeDriverExecutable :: Text
chromeDriverExecutable = case Platform
detectPlatform of
Platform
Windows -> Text
"chromedriver.exe"
Platform
_ -> Text
"chromedriver"
geckoDriverExecutable :: T.Text
geckoDriverExecutable :: Text
geckoDriverExecutable = case Platform
detectPlatform of
Platform
Windows -> Text
"geckodriver.exe"
Platform
_ -> Text
"geckodriver"
downloadAndUnzipToPath :: (MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadMask m) => T.Text -> FilePath -> m (Either T.Text ())
downloadAndUnzipToPath :: forall (m :: * -> *).
(MonadIO m, MonadBaseControl IO m, MonadLogger m, MonadMask m) =>
Text -> FilePath -> m (Either Text ())
downloadAndUnzipToPath Text
downloadPath FilePath
localPath = forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
m a -> m (Either Text a)
leftOnException' forall a b. (a -> b) -> a -> b
$ do
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
info [i|Downloading #{downloadPath} to #{localPath}|]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True (FilePath -> FilePath
takeDirectory FilePath
localPath)
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
FilePath -> (FilePath -> m a) -> m a
withSystemTempDirectory FilePath
"sandwich-webdriver-tool-download" forall a b. (a -> b) -> a -> b
$ \FilePath
dir -> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess ((FilePath -> [FilePath] -> CreateProcess
proc FilePath
"curl" [Text -> FilePath
T.unpack Text
downloadPath, FilePath
"-o", FilePath
"temp.zip"]) { cwd :: Maybe FilePath
cwd = forall a. a -> Maybe a
Just FilePath
dir }) FilePath
""
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess ((FilePath -> [FilePath] -> CreateProcess
proc FilePath
"unzip" [FilePath
"temp.zip", FilePath
"-d", FilePath
"unzipped"]) { cwd :: Maybe FilePath
cwd = forall a. a -> Maybe a
Just FilePath
dir }) FilePath
""
let unzipped :: FilePath
unzipped = FilePath
dir FilePath -> FilePath -> FilePath
</> FilePath
"unzipped"
[Text]
executables <- (forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Eq a => a -> a -> Bool
/= Text
"") forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> [Text]
T.splitOn Text
"\n" forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> [FilePath] -> CreateProcess
proc FilePath
"find" [FilePath
unzipped, FilePath
"-executable", FilePath
"-type", FilePath
"f"]) FilePath
""
case [Text]
executables of
[] -> forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ FilePath -> IOError
userError [i|No executable found in file downloaded from #{downloadPath}|]
[Text
x] -> do
FilePath -> FilePath -> IO ()
copyFile (Text -> FilePath
T.unpack Text
x) FilePath
localPath
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> CreateProcess
shell [i|chmod u+x #{localPath}|]) FilePath
""
[Text]
xs -> forall e a. Exception e => e -> IO a
throwIO forall a b. (a -> b) -> a -> b
$ FilePath -> IOError
userError [i|Found multiple executable found in file downloaded from #{downloadPath}: #{xs}|]
downloadAndUntarballToPath :: (MonadIO m, MonadBaseControl IO m, MonadLogger m) => T.Text -> FilePath -> m (Either T.Text ())
downloadAndUntarballToPath :: forall (m :: * -> *).
(MonadIO m, MonadBaseControl IO m, MonadLogger m) =>
Text -> FilePath -> m (Either Text ())
downloadAndUntarballToPath Text
downloadPath FilePath
localPath = forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
m a -> m (Either Text a)
leftOnException' forall a b. (a -> b) -> a -> b
$ do
forall (m :: * -> *). (HasCallStack, MonadLogger m) => Text -> m ()
info [i|Downloading #{downloadPath} to #{localPath}|]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True (FilePath -> FilePath
takeDirectory FilePath
localPath)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> CreateProcess
shell [i|wget -qO- #{downloadPath} | tar xvz -C #{takeDirectory localPath}|]) FilePath
""
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ CreateProcess -> FilePath -> IO FilePath
readCreateProcess (FilePath -> CreateProcess
shell [i|chmod u+x #{localPath}|]) FilePath
""
unlessM :: Monad m => m Bool -> m () -> m ()
unlessM :: forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM m Bool
b m ()
s = m Bool
b forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\Bool
t -> forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
t m ()
s)