module System.Handsy.Remote where
import System.Handsy as H
import System.Handsy.Internal (HandsyF (..))
import qualified Data.ByteString.Char8 as C8
import qualified Data.ByteString.Lazy as B
import System.Exit
import Control.Monad.IO.Class
import Control.Monad.Trans.Free
import Text.ShellEscape
data RemoteOptions =
RemoteOptions {
sshCommand :: (String, [String])
}
runRemote :: RemoteOptions -> Handsy a -> IO a
runRemote opts h = do
x <- runFreeT h
case x of
Pure r -> return r
Free (ReadFile fp next)
-> runSsh "cat" [fp] "" >>= \(_, stdin, _) -> runRemote opts (next stdin)
Free (WriteFile fp str next)
-> runSsh "dd" ["of=" ++ fp] str >> runRemote opts (next ())
Free (AppendFile fp str next)
-> runSsh "dd" ["of=" ++ fp, "conv=notrunc", "oflag=append"] str >> runRemote opts (next ())
Free (Command prg args stdin next)
-> runSsh prg args stdin >>= runRemote opts . next
where
runSsh :: String -> [String] -> B.ByteString -> IO (ExitCode, B.ByteString, B.ByteString)
runSsh prg args stdin = let c = C8.unpack . C8.intercalate " " . map (bytes . bash . C8.pack) $ (prg:args)
(ssh, sshOpts) = sshCommand opts
in run $ command ssh (sshOpts ++ [c]) stdin
pushFile :: FilePath
-> FilePath
-> Handsy ()
pushFile local remote = liftIO (B.readFile local) >>= H.writeFile remote
pullFile :: FilePath
-> FilePath
-> Handsy ()
pullFile remote local = H.readFile remote >>= liftIO . B.writeFile local