Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace sourceCmd with a much safer sourceCmdWithConsumer. #162

Merged
merged 1 commit into from Jul 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 24 additions & 18 deletions conduit-extra/Data/Conduit/Process.hs
@@ -1,10 +1,13 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}
-- | A full tutorial for this module is available on FP School of Haskell:
-- <https://www.fpcomplete.com/user/snoyberg/library-documentation/data-conduit-process>.
module Data.Conduit.Process
( -- * Functions
conduitProcess
, sourceCmdWithConsumer
, sourceProcessWithConsumer
-- * Specialized streaming types
, Inherited (..)
, ClosedStream (..)
Expand All @@ -22,14 +25,11 @@ module Data.Conduit.Process
, OutputSink
-- * Reexport
, module System.Process
-- * Deprecated compatibility functions
, sourceCmd
) where

import System.Process
import Control.Concurrent.STM (TMVar, atomically, newEmptyTMVar, putTMVar, STM, readTMVar, tryReadTMVar)
import Control.Exception (throwIO)
import System.Exit (ExitCode (ExitSuccess))
import System.Exit (ExitCode (..))
import Control.Concurrent (forkIO)
import Control.Monad.IO.Class (MonadIO, liftIO)
import System.IO (Handle, hClose)
Expand Down Expand Up @@ -170,17 +170,23 @@ conduitProcess cp = liftIO $ do
<*> getStderr stderrH
<*> return (ConduitProcessHandle ph ec)

-- | This function is dangerous, and should not be used. The running of the
-- process is completely dependent on whether or not you consume input from it,
-- which is an unintuitive and flimsy abstraction. Please move over to using
-- @conduitProcess@ instead.
sourceCmd :: MonadIO m => String -> Source m ByteString
sourceCmd cmd = do
(ClosedStream, (source, close), ClosedStream, cph) <- conduitProcess (shell cmd)
flip addCleanup source $ const $ do
close
ec <- waitForConduitProcess cph
case ec of
ExitSuccess -> return ()
_ -> liftIO $ throwIO ec
{-# DEPRECATED sourceCmd "Please use conduitProcess instead" #-}
-- | Given a @CreateProcess@, run the process, with its output being used as a
-- @Source@ to feed the provided @Consumer@. Once the process has completed,
-- return a tuple of the @ExitCode@ from the process and the output collected
-- from the @Consumer@.
--
-- Since 1.1.2
sourceProcessWithConsumer :: MonadIO m => CreateProcess -> Consumer ByteString m a -> m (ExitCode, a)
sourceProcessWithConsumer cp consumer = do
(ClosedStream, (source, close), ClosedStream, cph) <- conduitProcess cp
res <- source $$ consumer
close
ec <- waitForConduitProcess cph
return (ec, res)

-- | Like @sourceProcessWithConsumer@ but providing the command to be run as
-- a @String@.
--
-- Since 1.1.2
sourceCmdWithConsumer :: MonadIO m => String -> Consumer ByteString m a -> m (ExitCode, a)
sourceCmdWithConsumer cmd = sourceProcessWithConsumer (shell cmd)
12 changes: 6 additions & 6 deletions conduit-extra/test/Data/Conduit/ProcessSpec.hs
Expand Up @@ -39,12 +39,12 @@ spec = describe "Data.Conduit.Process" $ do
ec `shouldBe` ExitSuccess

it "handles sub-process exit code" $ do
(sourceCmd "exit 0" $$ CL.sinkNull)
`shouldReturn` ()
(sourceCmd "exit 11" $$ CL.sinkNull)
`shouldThrow` (== ExitFailure 11)
(sourceCmd "exit 12" $$ CL.sinkNull)
`shouldThrow` (== ExitFailure 12)
(sourceCmdWithConsumer "exit 0" CL.sinkNull)
`shouldReturn` (ExitSuccess, ())
(sourceCmdWithConsumer "exit 11" CL.sinkNull)
`shouldReturn` (ExitFailure 11, ())
(sourceCmdWithConsumer "exit 12" CL.sinkNull)
`shouldReturn` (ExitFailure 12, ())
#endif
it "blocking vs non-blocking" $ do
(ClosedStream, ClosedStream, ClosedStream, cph) <- conduitProcess (shell "sleep 1")
Expand Down