packages feed

handsy (empty) → 0.0.1

raw patch · 4 files changed

+100/−0 lines, 4 filesdep +basedep +bytestringdep +freesetup-changed

Dependencies added: base, bytestring, free, process, process-extras, transformers

Files

+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ handsy.cabal view
@@ -0,0 +1,26 @@+name:          handsy+version:       0.0.1+synopsis:      A DSL to describe common shell operations and interpeters for running them locally and remotely.+-- description:   +license:       BSD3+author:        Utku Demir+maintainer:    utdemir@gmail.com+category:      System+build-type:    Simple+cabal-version: >=1.10++source-repository head+  type:     git+  location: https://github.com/utdemir/master++library+  exposed-modules:  System.Handsy+                    System.Handsy.Remote+  build-depends:    base >=4.7 && <4.8+                  , bytestring+                  , process+                  , transformers+                  , free+                  , process-extras +  hs-source-dirs:   src+  default-language: Haskell2010
+ src/System/Handsy.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE DeriveFunctor     #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell   #-}++module System.Handsy where++import           Prelude                   hiding (readFile, writeFile)++import           Control.Monad.IO.Class+import qualified Data.ByteString.Char8     as B+import           System.Exit++import           Control.Monad.Free.TH+import           Control.Monad.Trans.Free+import           System.Process.ByteString++-- | Base functor for our dsl+data HandsyF k = Command      String [String] B.ByteString ((ExitCode, B.ByteString, B.ByteString) -> k)+               | ReadFile     String                       (B.ByteString -> k)+               | WriteFile    String B.ByteString          (() -> k)+             deriving (Functor)++makeFree ''HandsyF++type Handsy = FreeT HandsyF IO++run :: Handsy a -> IO a+run h = do+  x <- runFreeT h+  case x of+    Pure r -> return r+    Free (ReadFile fp next)+      -> B.readFile fp >>= run . next+    Free (WriteFile fp str next)+      -> B.writeFile fp str >>= run . next+    Free (Command prg args stdin next)+      -> readProcessWithExitCode prg args stdin >>= run . next
+ src/System/Handsy/Remote.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE OverloadedStrings #-}++module System.Handsy.Remote where++import           Prelude                  hiding (readFile, writeFile)++import           System.Handsy++import qualified Data.ByteString.Char8    as B++import           Control.Monad.IO.Class+import           Control.Monad.Trans.Free++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) -> do+      (_, stdin,  _) <- runSsh "cat" [fp] ""+      runRemote opts (next stdin)+    Free (WriteFile fp str next) -> do+      _ <- runSsh "dd" ["of=" ++ fp] str -- TODO: Escape necessary?+      runRemote opts (next ())+    Free (Command prg args stdin next) -> runSsh prg args stdin >>= run . next++  where+    (ssh, sshOpts) = sshCommand opts+    runSsh prg args stdin = run (command ssh (sshOpts ++ prg : args) stdin)