packages feed

shellmate 0.3.4.2 → 0.3.4.3

raw patch · 5 files changed

+46/−8 lines, 5 filesdep ~basedep ~temporaryPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base, temporary

API changes (from Hackage documentation)

+ Control.Shell: (<$!>) :: Monad m => (a -> b) -> m a -> m b
+ Control.Shell: (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
+ Control.Shell: (=<<) :: Monad m => (a -> m b) -> m a -> m b
+ Control.Shell: (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
+ Control.Shell: (>>) :: Monad m => m a -> m b -> m b
+ Control.Shell: (>>=) :: Monad m => m a -> (a -> m b) -> m b
+ Control.Shell: -- | The type of the guard's return value, if it succeeds.
+ Control.Shell: ap :: Monad m => m (a -> b) -> m a -> m b
+ Control.Shell: class Functor (f :: Type -> Type)
+ Control.Shell: class Applicative m => Monad (m :: Type -> Type)
+ Control.Shell: class (Alternative m, Monad m) => MonadPlus (m :: Type -> Type)
+ Control.Shell: fail :: Monad m => String -> m a
+ Control.Shell: filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
+ Control.Shell: fmap :: Functor f => (a -> b) -> f a -> f b
+ Control.Shell: foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
+ Control.Shell: foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()
+ Control.Shell: forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
+ Control.Shell: forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()
+ Control.Shell: forever :: Applicative f => f a -> f b
+ Control.Shell: infixl 1 >>
+ Control.Shell: infixl 4 <$!>
+ Control.Shell: infixr 1 =<<
+ Control.Shell: join :: Monad m => m (m a) -> m a
+ Control.Shell: liftM :: Monad m => (a1 -> r) -> m a1 -> m r
+ Control.Shell: liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
+ Control.Shell: liftM3 :: Monad m => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
+ Control.Shell: liftM4 :: Monad m => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r
+ Control.Shell: liftM5 :: Monad m => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
+ Control.Shell: mapAndUnzipM :: Applicative m => (a -> m (b, c)) -> [a] -> m ([b], [c])
+ Control.Shell: mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
+ Control.Shell: mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
+ Control.Shell: mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a
+ Control.Shell: mplus :: MonadPlus m => m a -> m a -> m a
+ Control.Shell: msum :: (Foldable t, MonadPlus m) => t (m a) -> m a
+ Control.Shell: mzero :: MonadPlus m => m a
+ Control.Shell: replicateM :: Applicative m => Int -> m a -> m [a]
+ Control.Shell: replicateM_ :: Applicative m => Int -> m a -> m ()
+ Control.Shell: return :: Monad m => a -> m a
+ Control.Shell: sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
+ Control.Shell: sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
+ Control.Shell: void :: Functor f => f a -> f ()
+ Control.Shell: zipWithM :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m [c]
+ Control.Shell: zipWithM_ :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m ()
- Control.Shell: class Guard guard where type Result guard where {
+ Control.Shell: class Guard guard where {
- Control.Shell: class Monad m => MonadIO (m :: * -> *)
+ Control.Shell: class Monad m => MonadIO (m :: Type -> Type)
- Control.Shell: data BufferMode :: *
+ Control.Shell: data BufferMode
- Control.Shell: data Handle :: *
+ Control.Shell: data Handle
- Control.Shell: data IOMode :: *
+ Control.Shell: data IOMode
- Control.Shell.Concurrent: data ThreadId :: *
+ Control.Shell.Concurrent: data ThreadId
- Control.Shell.Posix: data CMode :: *
+ Control.Shell.Posix: data CMode

Files

Control/Shell/Base.hs view
@@ -58,8 +58,8 @@   wd <- Dir.getCurrentDirectory   writeIORef globalEnv env   Dir.setCurrentDirectory (envWorkDir env)-  mapM_ Env.unsetEnv (map fst evs)-  mapM_ (uncurry Env.setEnv) (envEnvVars env)+  mapM_ Env.unsetEnv (filter (not . null) $ map fst evs)+  mapM_ (uncurry Env.setEnv) (filter (not . null . fst) $ envEnvVars env)   return $ Env IO.stdin IO.stdout IO.stderr wd evs  -- | Get the current global shell environment, including standard input,
Control/Shell/Control.hs view
@@ -52,7 +52,7 @@ guard = assert "Guard failed!"  -- | Perform the given computation if the given guard passes, otherwise do---   nothing.The guard raising an error counts as failure as far as this+--   nothing. The guard raising an error counts as failure as far as this --   function is concerned. --   Corresponds to 'CM.when'. when :: Guard g => g -> Shell () -> Shell ()
Control/Shell/Directory.hs view
@@ -122,7 +122,21 @@ rmdir :: FilePath -> Shell () rmdir dir = do   e <- getEnv-  unsafeLiftIO $ Dir.removeDirectoryRecursive (absPath e dir)+  unsafeLiftIO $ do+    let p = absPath e dir+    makeWritableRecursive p+    Dir.removeDirectoryRecursive p++-- Needed to recursively remove directories with read-only files on Windows.+-- Thanks to Ruud @ https://stackoverflow.com/questions/38926895/haskell-removedirectoryrecursive-permission-denied-on-windows+makeWritableRecursive :: FilePath -> IO ()+makeWritableRecursive path = do+  permissions <- Dir.getPermissions path+  Dir.setPermissions path (Dir.setOwnerWritable True permissions)+  isDirectory <- Dir.doesDirectoryExist path+  Control.Monad.when isDirectory $ do+    contents <- Dir.getDirectoryContents path+    forM_ [path </> item | item <- contents, item /= "." && item /= ".."] makeWritableRecursive  -- | Do something with the user's home directory. withHomeDirectory :: (FilePath -> Shell a) -> Shell a
Control/Shell/Internal.hs view
@@ -7,13 +7,17 @@   , exit, run, try, getEnv, inEnv, unsafeLiftIO, (|>)   ) where import Control.Monad (when, ap, forM)+import Control.Monad.Fail import qualified Control.Concurrent as Conc import qualified Control.Exception as Ex+import qualified Data.IORef as IORef import qualified System.Exit as Exit import qualified System.Process as Proc import qualified System.IO as IO+import qualified System.IO.Unsafe as IO import qualified System.Directory as Dir (getCurrentDirectory) import qualified System.Environment as Env (getEnvironment)+import qualified System.Info as Info (os)  -- | A command name plus a ProcessHandle. data Pid = PID !String                         !Proc.ProcessHandle@@ -59,6 +63,9 @@   (>>=)  = Bind   fail   = Fail +instance MonadFail Shell where+  fail = Fail+ -- | Lift an IO computation into a shell. The lifted computation is not --   thread-safe, and should thus absolutely not use environment variables, --   relative paths or standard input/output.@@ -69,11 +76,20 @@ data ExitReason = Success | Failure !String   deriving (Show, Eq) +{-# NOINLINE warningRef #-}+warningRef :: IORef.IORef Bool+warningRef = IO.unsafePerformIO $ IORef.newIORef False+ -- | Run a shell computation. If part of the computation fails, the whole --   computation fails. The computation's environment is initially that of the --   whole process. shell :: Shell a -> IO (Either ExitReason a) shell m = do+    alreadyPrintedWarning <- IORef.atomicModifyIORef warningRef $ \x -> (True, x)+    when (not Conc.rtsSupportsBoundThreads && not alreadyPrintedWarning) $ do+      IO.hPutStrLn IO.stderr "WARNING: your program is not linked against the threaded GHC runtime."+      IO.hPutStrLn IO.stderr "You should REALLY build your program with -threaded,"+      IO.hPutStrLn IO.stderr "or you may experience deadlocks."     evs <- Env.getEnvironment     wd <- Dir.getCurrentDirectory     runSh (env wd evs) m@@ -92,12 +108,15 @@            (\(Ex.SomeException e) -> pure $ Left (Failure (show e))) runSh env (Pipe p) = flip Ex.catch except $ do   steps <- mkEnvs env p-  pids <- mapM (uncurry (runStep True)) steps+  pids <- mapM (uncurry (runStep closeFDs)) steps   ma <- waitPids pids   case ma of     Failure err -> pure $ Left (Failure err)     _           -> pure $ Right ()   where+    closeFDs+      | Info.os == "mingw32" = False+      | otherwise            = True     except = \(Ex.SomeException e) -> pure $ Left (Failure (show e)) runSh _ Done = do   return $ Left Success@@ -143,6 +162,9 @@       , Proc.new_session        = False       , Proc.child_group        = Nothing       , Proc.child_user         = Nothing+#endif+#if MIN_VERSION_process(1,5,0)+      , Proc.use_process_jobs   = False #endif       } runStep closefds env (Internal cmd) = do
shellmate.cabal view
@@ -1,7 +1,9 @@ name:                shellmate-version:             0.3.4.2+version:             0.3.4.3 synopsis:            Simple interface for shell scripting in Haskell. description:         Monadic EDSL for writing cross-platform shell scripts in Haskell.+                     Note that programs using shellmate should be built with+                     the -threaded flag to avoid deadlocks. homepage:            https://github.com/valderman/shellmate license:             BSD3 license-file:        LICENSE@@ -36,13 +38,13 @@     Control.Shell.Directory     Control.Shell.Color   build-depends:-    base         >=4.8  && <5,+    base         >=4.9  && <5,     transformers >=0.3  && <0.6,     bytestring   >=0.10 && <0.11,     filepath     >=1.3  && <1.5,     process      >=1.1  && <1.7,     directory    >=1.1  && <1.4,-    temporary    >=1.1  && <1.3+    temporary    >=1.1  && <1.4   default-language:     Haskell2010   ghc-options: