packages feed

shelly 0.14.0.1 → 0.14.1

raw patch · 4 files changed

+89/−50 lines, 4 filesdep ~hspecPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: hspec

API changes (from Hackage documentation)

- Shelly: echo, echo_n_err, echo_err, echo_n :: Text -> Sh ()
- Shelly.Pipe: echo, echo_n, echo_err, echo_n_err :: Text -> Sh ()
+ Shelly: echo :: Text -> Sh ()
+ Shelly: echo_err :: Text -> Sh ()
+ Shelly: echo_n :: Text -> Sh ()
+ Shelly: echo_n_err :: Text -> Sh ()
+ Shelly: shellyNoDir :: MonadIO m => Sh a -> m a
+ Shelly.Pipe: echo :: Text -> Sh ()
+ Shelly.Pipe: echo_err :: Text -> Sh ()
+ Shelly.Pipe: echo_n :: Text -> Sh ()
+ Shelly.Pipe: echo_n_err :: Text -> Sh ()

Files

Shelly.hs view
@@ -25,7 +25,7 @@ module Shelly        (          -- * Entering Sh.-         Sh, ShIO, shelly, sub, silently, verbosely, escaping, print_stdout, print_commands, tracing, errExit+         Sh, ShIO, shelly, shellyNoDir, sub, silently, verbosely, escaping, print_stdout, print_commands, tracing, errExit           -- * Running external commands.          , run, run_, runFoldLines, cmd, (-|-), lastStderr, setStdin, lastExitCode@@ -212,8 +212,10 @@ printGetContent rH wH =     fmap B.toLazyText $ printFoldHandleLines (B.fromText "") foldBuilder rH wH +{- getContent :: Handle -> IO Text getContent h = fmap B.toLazyText $ foldHandleLines (B.fromText "") foldBuilder h+-}  type FoldCallback a = ((a, Text) -> a) @@ -329,7 +331,7 @@       where         tdir = toTextIgnore dir --- | "cd", execute a Sh action in the new directory and then pop back to the original directory+-- | 'cd', execute a Sh action in the new directory and then pop back to the original directory chdir :: FilePath -> Sh a -> Sh a chdir dir action = do   d <- gets sDirectory@@ -354,8 +356,8 @@ pack :: String -> FilePath pack = decodeString --- | Currently a "renameFile" wrapper. TODO: Support cross-filesystem--- move. TODO: Support directory paths in the second parameter, like in "cp".+-- | Currently a 'renameFile' wrapper. TODO: Support cross-filesystem+-- move. TODO: Support directory paths in the second parameter, like in 'cp'. mv :: FilePath -> FilePath -> Sh () mv a b = do a' <- absPath a             b' <- absPath b@@ -410,7 +412,7 @@   (trace . mappend "which " . toTextIgnore) fp   (liftIO . findExecutable . unpack >=> return . fmap pack) fp --- | A monadic-conditional version of the "unless" guard.+-- | A monadic-conditional version of the 'unless' guard. unlessM :: Monad m => m Bool -> m () -> m () unlessM c a = c >>= \res -> unless res a @@ -470,6 +472,7 @@  -- | add the filepath onto the PATH env variable -- FIXME: only effects the PATH once the process is ran, as per comments in 'which'+-- TODO: use cross-platform searchPathSeparator appendToPath :: FilePath -> Sh () appendToPath = absPath >=> \filepath -> do   tp <- toTextWarn filepath@@ -501,6 +504,7 @@ -- non-existent variables give the default Text value as a result get_env_def :: Text -> Text -> Sh Text get_env_def d = get_env >=> return . fromMaybe d+{-# DEPRECATED get_env_def "use fromMaybe DEFAULT get_env" #-}   -- | Create a sub-Sh in which external command outputs are not echoed and@@ -537,7 +541,15 @@   where     restoreState oldState = do       newState <- get-      put oldState { sTrace = sTrace oldState `mappend` sTrace newState  }+      put oldState {+         -- avoid losing the log+         sTrace  = sTrace oldState `mappend` sTrace newState +         -- latest command execution: not make sense to restore these to old settings+       , sCode   = sCode newState+       , sStderr = sStderr newState+         -- it is questionable what the behavior of stdin should be+       , sStdin  = sStdin newState+       }  -- | Create a sub-Sh where commands are not traced -- Defaults to True.@@ -559,20 +571,36 @@     }   action --- | named after bash -e errexit. Defaults to True.--- When True, throw an exception on a non-zero exit code.--- Not recommended to set to False unless you are specifically checking the error code with 'lastExitCode'.+-- | named after bash -e errexit. Defaults to @True@.+-- When @True@, throw an exception on a non-zero exit code.+-- When @False@, ignore a non-zero exit code.+-- Not recommended to set to @False@ unless you are specifically checking the error code with 'lastExitCode'. errExit :: Bool -> Sh a -> Sh a errExit shouldExit action = sub $ do   modify $ \st -> st { sErrExit = shouldExit }   action +data ShellyOpts = ShellyOpts { failToDir :: Bool }++-- avoid data-default dependency for now+-- instance Default ShellyOpts where +shellyOpts :: ShellyOpts+shellyOpts = ShellyOpts { failToDir = True }++-- | Using this entry point does not create a @.shelly@ directory in the case+-- of failure. Instead it logs directly into the standard error stream (@stderr@).+shellyNoDir :: MonadIO m => Sh a -> m a+shellyNoDir = shelly' shellyOpts { failToDir = False }+ -- | Enter a Sh from (Monad)IO. The environment and working directories are -- inherited from the current process-wide values. Any subsequent changes in -- processwide working directory or environment are not reflected in the -- running Sh. shelly :: MonadIO m => Sh a -> m a-shelly action = do+shelly = shelly' shellyOpts++shelly' :: MonadIO m => ShellyOpts -> Sh a -> m a+shelly' opts action = do   environment <- liftIO getEnvironment   dir <- liftIO getWorkingDirectory   let def  = State { sCode = 0@@ -603,14 +631,18 @@   where     throwExplainedException :: Exception exception => exception -> Sh a     throwExplainedException ex = get >>= errorMsg >>= liftIO . throwIO . ReThrownException ex-    errorMsg st = do-      let trc = B.toLazyText . sTrace $ st-      d <- pwd-      sf <- shellyFile-      let f = d</>shelly_dir</>sf-      (writefile f trc >> return ("log of commands saved to: " `mappend` encodeString f))-        `catchany_sh` (\_ -> return $ "Ran commands: \n" `mappend` LT.unpack trc)+    errorMsg st =+      if not (failToDir opts) then ranCommands else do+          d <- pwd+          sf <- shellyFile+          let logFile = d</>shelly_dir</>sf+          (writefile logFile trc >> return ("log of commands saved to: " `mappend` encodeString logFile))+            `catchany_sh` (\_ -> ranCommands) +      where+        trc = B.toLazyText . sTrace $ st+        ranCommands = return . mappend "Ran commands: \n" . LT.unpack $ trc+     shelly_dir = ".shelly"     shellyFile = chdir_p shelly_dir $ do       fs <- ls "."@@ -666,7 +698,7 @@ -- This interface is crude, but it works for now. -- -- Please note this sets 'escaping' to False: the commands will not be shell escaped.--- Internally the list of commands are combined with the string " && " before given to ssh.+-- Internally the list of commands are combined with the string @&&@ before given to ssh. sshPairs :: Text -> [(FilePath, [Text])] -> Sh Text sshPairs _ [] = return "" sshPairs server cmds = sshPairs' run server cmds@@ -694,13 +726,13 @@ -- just a name of something that can be found via @PATH@; FIXME: setenv'd -- @PATH@ is not taken into account when finding the exe name) ----- "stdout" and "stderr" are collected. The "stdout" is returned as--- a result of "run", and complete stderr output is available after the fact using--- "lastStderr"+-- 'stdout' and 'stderr' are collected. The 'stdout' is returned as+-- a result of 'run', and complete stderr output is available after the fact using+-- 'lastStderr' -- -- All of the stdout output will be loaded into memory--- You can avoid this but still consume the result by using "run_",--- If you want to avoid the memory and need to process the output then use "runFoldLines".+-- You can avoid this but still consume the result by using 'run_',+-- If you want to avoid the memory and need to process the output then use 'runFoldLines'. run :: FilePath -> [Text] -> Sh Text run exe args = fmap B.toLazyText $ runFoldLines (B.fromText "") foldBuilder exe args @@ -708,27 +740,31 @@ foldBuilder (b, line) = b `mappend` B.fromLazyText line `mappend` B.singleton '\n'  --- | bind some arguments to run for re-use--- Example: @monit = command "monit" ["-c", "monitrc"]@+-- | bind some arguments to run for re-use. Example:+--+-- > monit = command "monit" ["-c", "monitrc"] command :: FilePath -> [Text] -> [Text] -> Sh Text command com args more_args = run com (args ++ more_args) --- | bind some arguments to "run_" for re-use--- Example: @monit_ = command_ "monit" ["-c", "monitrc"]@+-- | bind some arguments to 'run_' for re-use. Example:+--+-- > monit_ = command_ "monit" ["-c", "monitrc"] command_ :: FilePath -> [Text] -> [Text] -> Sh () command_ com args more_args = run_ com (args ++ more_args) --- | bind some arguments to run for re-use, and expect 1 argument--- Example: @git = command1 "git" []; git "pull" ["origin", "master"]@+-- | bind some arguments to run for re-use, and expect 1 argument. Example:+--+-- > git = command1 "git" []; git "pull" ["origin", "master"] command1 :: FilePath -> [Text] -> Text -> [Text] -> Sh Text command1 com args one_arg more_args = run com ([one_arg] ++ args ++ more_args) --- | bind some arguments to run for re-use, and expect 1 argument--- Example: @git_ = command1_ "git" []; git+ "pull" ["origin", "master"]@+-- | bind some arguments to run for re-use, and expect 1 argument. Example:+--+-- > git_ = command1_ "git" []; git+ "pull" ["origin", "master"] command1_ :: FilePath -> [Text] -> Text -> [Text] -> Sh () command1_ com args one_arg more_args = run_ com ([one_arg] ++ args ++ more_args) --- | the same as "run", but return () instead of the stdout content+-- | the same as 'run', but return @()@ instead of the stdout content -- stdout will be read and discarded line-by-line run_ :: FilePath -> [Text] -> Sh () run_ = runFoldLines () (\(_, _) -> ())@@ -736,7 +772,7 @@ liftIO_ :: IO a -> Sh () liftIO_ action = liftIO action >> return () --- | used by "run". fold over stdout line-by-line as it is read to avoid keeping it in memory+-- | used by 'run'. fold over stdout line-by-line as it is read to avoid keeping it in memory -- stderr is still being placed in memory under the assumption it is always relatively small runFoldLines :: a -> FoldCallback a -> FilePath -> [Text] -> Sh a runFoldLines start cb exe args = do@@ -760,12 +796,13 @@      errV <- liftIO newEmptyMVar     outV <- liftIO newEmptyMVar++    liftIO_ $ forkIO $ printGetContent errH stderr >>= putMVar errV+    -- liftIO_ $ forkIO $ getContent errH >>= putMVar errV     if sPrintStdout state-      then do-        liftIO_ $ forkIO $ printGetContent errH stderr >>= putMVar errV+      then         liftIO_ $ forkIO $ printFoldHandleLines start cb outH stdout >>= putMVar outV-      else do-        liftIO_ $ forkIO $ getContent errH >>= putMVar errV+      else         liftIO_ $ forkIO $ foldHandleLines start cb outH >>= putMVar outV      errs <- liftIO $ takeMVar errV@@ -781,7 +818,7 @@       (True,  ExitFailure n) -> throwIO $ RunFailed exe args n errs       _                      -> takeMVar outV --- | The output of last external command. See "run".+-- | The output of last external command. See 'run'. lastStderr :: Sh Text lastStderr = gets sStderr @@ -790,11 +827,13 @@ lastExitCode :: Sh Int lastExitCode = gets sCode --- | set the stdin to be used and cleared by the next "run".+-- | set the stdin to be used and cleared by the next 'run'. setStdin :: Text -> Sh () setStdin input = modify $ \st -> st { sStdin = Just input }  -- | Pipe operator. set the stdout the first command as the stdin of the second.+-- This does not create a shell-level pipe, but hopefully it will in the future.+-- To create a shell level pipe you can always set @escaping False@ and use a pipe @|@ character in a command. (-|-) :: Sh Text -> Sh b -> Sh b one -|- two = do   res <- print_stdout False one
Shelly/Base.hs view
@@ -15,7 +15,7 @@     liftIO, (>=>),     eitherRelativeTo, relativeTo, maybeRelativeTo,     whenM-    -- * utitlities not yet exported+    -- * utilities not yet exported     , addTrailingSlash   ) where @@ -25,13 +25,12 @@ import System.IO ( Handle, hFlush, stderr, stdout )  import Control.Monad (when, (>=>) )-import Control.Applicative(Applicative)+import Control.Applicative (Applicative, (<$>)) import Filesystem (isDirectory, listDirectory) import System.PosixCompat.Files( getSymbolicLinkStatus, isSymbolicLink ) import Filesystem.Path.CurrentOS (FilePath, encodeString, relative) import qualified Filesystem.Path.CurrentOS as FP import qualified Filesystem as FS-import Control.Applicative ((<$>)) import Data.IORef (readIORef, modifyIORef, IORef) import Data.Monoid (mappend) import qualified Data.Text.Lazy as LT@@ -128,7 +127,7 @@     p FP.</> FP.empty  -- | makes an absolute path.--- Like 'canonicalize', but on an exception returns 'path'+-- Like 'canonicalize', but on an exception returns 'absPath' canonic :: FilePath -> Sh FilePath canonic fp = do   p <- absPath fp@@ -147,11 +146,12 @@  -- | Make a relative path absolute by combining with the working directory. -- An absolute path is returned as is.--- To create a relative path, use 'path'.+-- To create a relative path, use 'relPath'. absPath :: FilePath -> Sh FilePath absPath p | relative p = (FP.</> p) <$> gets sDirectory           | otherwise = return p +-- | deprecated path :: FilePath -> Sh FilePath path = absPath {-# DEPRECATED path "use absPath, canonic, or relPath instead" #-}@@ -182,7 +182,7 @@   state <- ask    liftIO (modifyIORef state f) --- | internally log what occured.+-- | internally log what occurred. -- Log will be re-played on failure. trace :: Text -> Sh () trace msg =
shelly.cabal view
@@ -1,6 +1,6 @@ Name:       shelly -Version:     0.14.0.1+Version:     0.14.1 Synopsis:    shell-like (systems) programming in Haskell  Description: Shelly provides convenient systems programming in Haskell,@@ -57,7 +57,7 @@                  , system-fileio < 0.4                  , bytestring                  , hspec-discover-                 , hspec >= 1.1+                 , hspec >= 1.3                  , HUnit  -- demonstarated that command output in Shellish was not shown until after the command finished
test/main.hs view
@@ -1,5 +1,5 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --nested #-}+{- # OPTIONS_GHC -F -pgmF hspec-discover -optF --nested #-} {-import qualified CopySpec-} {-main = CopySpec.main-}--- import qualified FindSpec--- main = FindSpec.main+import qualified FailureSpec+main = FailureSpec.main