Hello community, here is the log from the commit of package ghc-turtle for openSUSE:Factory checked in at 2016-04-12 19:38:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-turtle (Old) and /work/SRC/openSUSE:Factory/.ghc-turtle.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-turtle" Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-turtle/ghc-turtle.changes 2016-02-09 13:31:55.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.ghc-turtle.new/ghc-turtle.changes 2016-04-12 19:38:17.000000000 +0200 @@ -1,0 +2,5 @@ +Mon Apr 4 07:58:04 UTC 2016 - [email protected] + +- update to 1.2.6 + +------------------------------------------------------------------- Old: ---- turtle-1.2.5.tar.gz New: ---- turtle-1.2.6.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-turtle.spec ++++++ --- /var/tmp/diff_new_pack.o63otB/_old 2016-04-12 19:38:17.000000000 +0200 +++ /var/tmp/diff_new_pack.o63otB/_new 2016-04-12 19:38:17.000000000 +0200 @@ -20,7 +20,7 @@ %bcond_with tests Name: ghc-%{pkg_name} -Version: 1.2.5 +Version: 1.2.6 Release: 0 Summary: Shell programming, Haskell-style Group: System/Libraries ++++++ turtle-1.2.5.tar.gz -> turtle-1.2.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/turtle-1.2.5/src/Turtle/Format.hs new/turtle-1.2.6/src/Turtle/Format.hs --- old/turtle-1.2.5/src/Turtle/Format.hs 2016-01-07 05:54:31.000000000 +0100 +++ new/turtle-1.2.6/src/Turtle/Format.hs 2016-03-06 03:13:11.000000000 +0100 @@ -66,6 +66,7 @@ ) where import Control.Category (Category(..)) +import Control.Monad.IO.Class (MonadIO(..)) import Data.Monoid ((<>)) import Data.String (IsString(..)) import Data.Text (Text, pack) @@ -106,8 +107,8 @@ >>> printf ("Hello, "%s%"!\n") "world" Hello, world! -} -printf :: Format (IO ()) r -> r -printf fmt = fmt >>- Text.putStr +printf :: MonadIO io => Format (io ()) r -> r +printf fmt = fmt >>- (liftIO . Text.putStr) -- | Create your own format specifier makeFormat :: (a -> Text) -> Format r (a -> r) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/turtle-1.2.5/src/Turtle/Prelude.hs new/turtle-1.2.6/src/Turtle/Prelude.hs --- old/turtle-1.2.5/src/Turtle/Prelude.hs 2016-01-07 05:54:31.000000000 +0100 +++ new/turtle-1.2.6/src/Turtle/Prelude.hs 2016-03-28 00:38:05.000000000 +0200 @@ -105,15 +105,11 @@ module Turtle.Prelude ( -- * IO - proc - , shell - , procs - , shells - , procStrict - , shellStrict - , echo + echo , err , readline + , Filesystem.readTextFile + , Filesystem.writeTextFile , arguments #if MIN_VERSION_base(4,7,0) , export @@ -196,11 +192,21 @@ -- * Text , cut + -- * Subprocess management + , proc + , shell + , system + , procs + , shells + , procStrict + , shellStrict + -- * Permissions , Permissions , chmod , getmod , setmod + , copymod , readable, nonreadable , writable, nonwritable , executable, nonexecutable @@ -238,7 +244,7 @@ import qualified Control.Foldl.Text import Control.Monad (liftM, msum, when, unless) import Control.Monad.IO.Class (MonadIO(..)) -import Control.Monad.Managed (Managed, managed, runManaged) +import Control.Monad.Managed (MonadManaged(..), managed, runManaged) #ifdef mingw32_HOST_OS import Data.Bits ((.&.)) #endif @@ -276,7 +282,14 @@ #ifdef mingw32_HOST_OS import qualified System.Win32 as Win32 #else -import System.Posix (openDirStream, readDirStream, closeDirStream, touchFile) +import System.Posix ( + openDirStream, + readDirStream, + closeDirStream, + touchFile, + getSymbolicLinkStatus, + isDirectory, + isSymbolicLink ) #endif import Prelude hiding (FilePath) @@ -298,7 +311,13 @@ -- ^ Lines of standard input -> io ExitCode -- ^ Exit code -proc cmd args = system (Process.proc (unpack cmd) (map unpack args)) +proc cmd args = + system + ( (Process.proc (unpack cmd) (map unpack args)) + { Process.std_in = Process.CreatePipe + , Process.std_out = Process.Inherit + , Process.std_err = Process.Inherit + } ) {-| Run a command line using the shell, retrieving the exit code @@ -315,7 +334,13 @@ -- ^ Lines of standard input -> io ExitCode -- ^ Exit code -shell cmdLine = system (Process.shell (unpack cmdLine)) +shell cmdLine = + system + ( (Process.shell (unpack cmdLine)) + { Process.std_in = Process.CreatePipe + , Process.std_out = Process.Inherit + , Process.std_err = Process.Inherit + } ) data ProcFailed = ProcFailed { procCommand :: Text @@ -403,6 +428,10 @@ -- ^ Exit code and stdout shellStrict cmdLine = systemStrict (Process.shell (Text.unpack cmdLine)) +{-| `system` generalizes `shell` and `proc` by allowing you to supply your own + custom `CreateProcess`. This is for advanced users who feel comfortable + using the lower-level @process@ API +-} system :: MonadIO io => Process.CreateProcess @@ -412,14 +441,8 @@ -> io ExitCode -- ^ Exit code system p s = liftIO (do - let p' = p - { Process.std_in = Process.CreatePipe - , Process.std_out = Process.Inherit - , Process.std_err = Process.Inherit - } - let open = do - (Just hIn, Nothing, Nothing, ph) <- Process.createProcess p' + (Just hIn, Nothing, Nothing, ph) <- Process.createProcess p IO.hSetBuffering hIn IO.LineBuffering return (hIn, ph) @@ -619,7 +642,8 @@ {-| Run a command using the shell, streaming @stdout@ and @stderr@ as lines of `Text`. Lines from @stdout@ are wrapped in `Right` and lines from @stderr@ - are wrapped in `Left`. + are wrapped in `Left`. This does /not/ throw an exception if the command + returns a non-zero exit code -} inprocWithErr :: Text @@ -629,14 +653,15 @@ -> Shell Text -- ^ Lines of standard input -> Shell (Either Text Text) - -- ^ Lines of standard output + -- ^ Lines of either standard output (`Right`) or standard error (`Left`) inprocWithErr cmd args = streamWithErr (Process.proc (unpack cmd) (map unpack args)) {-| Run a command line using the shell, streaming @stdout@ and @stderr@ as lines of `Text`. Lines from @stdout@ are wrapped in `Right` and lines from - @stderr@ are wrapped in `Left`. + @stderr@ are wrapped in `Left`. This does /not/ throw an exception if the + command returns a non-zero exit code This command is more powerful than `inprocWithErr`, but highly vulnerable to code injection if you template the command line with untrusted input @@ -647,7 +672,7 @@ -> Shell Text -- ^ Lines of standard input -> Shell (Either Text Text) - -- ^ Lines of standard output + -- ^ Lines of either standard output (`Right`) or standard error (`Left`) inshellWithErr cmd = streamWithErr (Process.shell (unpack cmd)) -- | Print to @stdout@ @@ -778,7 +803,7 @@ lstree :: FilePath -> Shell FilePath lstree path = do child <- ls path - isDir <- liftIO (testdir child) + isDir <- testdir child if isDir then return child <|> lstree child else return child @@ -792,7 +817,7 @@ lsif :: (FilePath -> IO Bool) -> FilePath -> Shell FilePath lsif predicate path = do child <- ls path - isDir <- liftIO (testdir child) + isDir <- testdir child if isDir then do continue <- liftIO (predicate child) @@ -846,7 +871,31 @@ Use at your own risk -} rmtree :: MonadIO io => FilePath -> io () -rmtree path = liftIO (Filesystem.removeTree path) +rmtree path0 = liftIO (sh (loop path0)) + where +#ifdef mingw32_HOST_OS + loop path = do + isDir <- testdir path + if isDir + then (do + child <- ls path + loop child ) <|> rmdir path + else rm path +#else + loop path = do + let path' = Filesystem.encodeString path + stat <- liftIO $ getSymbolicLinkStatus path' + let isLink = isSymbolicLink stat + isDir = isDirectory stat + if isLink + then rm path + else do + if isDir + then (do + child <- ls path + loop child ) <|> rmdir path + else rm path +#endif -- | Check if a file exists testfile :: MonadIO io => FilePath -> io Bool @@ -924,6 +973,13 @@ let path' = deslash (Filesystem.encodeString path) Directory.setPermissions path' permissions ) +-- | Copy a file or directory's permissions (analogous to @chmod --reference@) +copymod :: MonadIO io => FilePath -> FilePath -> io () +copymod sourcePath targetPath = liftIO (do + let sourcePath' = deslash (Filesystem.encodeString sourcePath) + targetPath' = deslash (Filesystem.encodeString targetPath) + Directory.copyPermissions sourcePath' targetPath' ) + -- | @+r@ readable :: Permissions -> Permissions readable = Directory.setOwnerReadable True @@ -1066,16 +1122,17 @@ Deletes the temporary directory when done -} mktempdir - :: FilePath + :: MonadManaged managed + => FilePath -- ^ Parent directory -> Text -- ^ Directory name template - -> Managed FilePath -mktempdir parent prefix = do + -> managed FilePath +mktempdir parent prefix = using (do let parent' = Filesystem.encodeString parent let prefix' = unpack prefix dir' <- managed (withTempDirectory parent' prefix') - return (Filesystem.decodeString dir') + return (Filesystem.decodeString dir')) {-| Create a temporary file underneath the given directory @@ -1087,39 +1144,41 @@ simpler API if you don't need to worry about that possibility. -} mktemp - :: FilePath + :: MonadManaged managed + => FilePath -- ^ Parent directory -> Text -- ^ File name template - -> Managed (FilePath, Handle) -mktemp parent prefix = do + -> managed (FilePath, Handle) +mktemp parent prefix = using (do let parent' = Filesystem.encodeString parent let prefix' = unpack prefix (file', handle) <- managed (\k -> withTempFile parent' prefix' (\file' handle -> k (file', handle)) ) - return (Filesystem.decodeString file', handle) + return (Filesystem.decodeString file', handle) ) {-| Create a temporary file underneath the given directory Deletes the temporary file when done -} mktempfile - :: FilePath + :: MonadManaged managed + => FilePath -- ^ Parent directory -> Text -- ^ File name template - -> Managed FilePath -mktempfile parent prefix = do + -> managed FilePath +mktempfile parent prefix = using (do let parent' = Filesystem.encodeString parent let prefix' = unpack prefix (file', handle) <- managed (\k -> withTempFile parent' prefix' (\file' handle -> k (file', handle)) ) liftIO (hClose handle) - return (Filesystem.decodeString file') + return (Filesystem.decodeString file') ) -- | Fork a thread, acquiring an `Async` value -fork :: IO a -> Managed (Async a) -fork io = managed (withAsync io) +fork :: MonadManaged managed => IO a -> managed (Async a) +fork io = using (managed (withAsync io)) -- | Read lines of `Text` from standard input stdin :: Shell Text @@ -1182,16 +1241,16 @@ strict s = liftM Text.unlines (fold s list) -- | Acquire a `Managed` read-only `Handle` from a `FilePath` -readonly :: FilePath -> Managed Handle -readonly file = managed (Filesystem.withTextFile file IO.ReadMode) +readonly :: MonadManaged managed => FilePath -> managed Handle +readonly file = using (managed (Filesystem.withTextFile file IO.ReadMode)) -- | Acquire a `Managed` write-only `Handle` from a `FilePath` -writeonly :: FilePath -> Managed Handle -writeonly file = managed (Filesystem.withTextFile file IO.WriteMode) +writeonly :: MonadManaged managed => FilePath -> managed Handle +writeonly file = using (managed (Filesystem.withTextFile file IO.WriteMode)) -- | Acquire a `Managed` append-only `Handle` from a `FilePath` -appendonly :: FilePath -> Managed Handle -appendonly file = managed (Filesystem.withTextFile file IO.AppendMode) +appendonly :: MonadManaged managed => FilePath -> managed Handle +appendonly file = using (managed (Filesystem.withTextFile file IO.AppendMode)) -- | Combine the output of multiple `Shell`s, in order cat :: [Shell a] -> Shell a @@ -1235,6 +1294,7 @@ (tmpfile, handle) <- mktemp here "turtle" outhandle handle (sed pattern (input file)) liftIO (hClose handle) + copymod file tmpfile mv tmpfile file )) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/turtle-1.2.5/src/Turtle/Shell.hs new/turtle-1.2.6/src/Turtle/Shell.hs --- old/turtle-1.2.5/src/Turtle/Shell.hs 2016-01-07 05:54:31.000000000 +0100 +++ new/turtle-1.2.6/src/Turtle/Shell.hs 2016-03-28 00:31:24.000000000 +0200 @@ -73,7 +73,7 @@ import Control.Applicative import Control.Monad (MonadPlus(..), ap) import Control.Monad.IO.Class (MonadIO(..)) -import Control.Monad.Managed (Managed, with) +import Control.Monad.Managed (MonadManaged(..), with) import Control.Foldl (Fold(..), FoldM(..)) import qualified Control.Foldl as Foldl import Data.Monoid @@ -143,6 +143,12 @@ x' <- step x a done x' ) +instance MonadManaged Shell where + using resource = Shell (\(FoldM step begin done) -> do + x <- begin + x' <- with resource (step x) + done x' ) + instance Monoid a => Monoid (Shell a) where mempty = pure mempty mappend = liftA2 mappend @@ -165,10 +171,3 @@ x' <- step x a k $! x' foldr step' done as $! x0 ) - --- | Acquire a `Managed` resource within a `Shell` in an exception-safe way -using :: Managed a -> Shell a -using resource = Shell (\(FoldM step begin done) -> do - x <- begin - x' <- with resource (step x) - done x' ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/turtle-1.2.5/src/Turtle/Tutorial.hs new/turtle-1.2.6/src/Turtle/Tutorial.hs --- old/turtle-1.2.5/src/Turtle/Tutorial.hs 2016-01-07 05:54:31.000000000 +0100 +++ new/turtle-1.2.6/src/Turtle/Tutorial.hs 2016-03-28 01:16:25.000000000 +0200 @@ -106,6 +106,9 @@ -- * MonadIO -- $monadio + -- * MonadManaged + -- $monadmanaged + -- * Command line options -- $cmdline @@ -770,7 +773,7 @@ -- @ -- `proc` -- :: Text -- Program --- :: [Text] -- Arguments +-- -> [Text] -- Arguments -- -> Shell Text -- Standard input (as lines of \`Text\`) -- -> IO ExitCode -- Exit code of the shell command -- @ @@ -810,8 +813,15 @@ -- -- > format fp :: FilePath -> Text -- +-- For the very common case where you `echo` a formatted value, you can use +-- `printf`: +-- +-- >>> printf ("Hello, "%s%"!\n") "world" +-- Hello, world! +-- -- If you are interested in this feature, check out the "Turtle.Format" module --- for more details. +-- for more details. For more complex string formatting needs, check out the +-- @text-format@ library. -- $streams -- The @turtle@ library provides support for streaming computations, just like @@ -1440,6 +1450,7 @@ -- > Applicative Shell -- > Alternative Shell -- > MonadIO Shell +-- > MonadManaged Shell -- > ... -- -- These instances represent the overloaded functions associated with `Shell` @@ -1450,6 +1461,31 @@ -- way (such as `print`), so you will still occasionally need to wrap -- subroutines in `liftIO`. +-- $monadmanaged +-- +-- All `Managed` operations are also overloaded in @turtle@, meaning that you +-- can omit the `using` command. For example, we could change our last example +-- to: +-- +-- > #!/usr/bin/env stack +-- > -- stack --install-ghc runghc --package turtle +-- > +-- > {-# LANGUAGE OverloadedStrings #-} +-- > +-- > import Turtle +-- > +-- > main = sh (do +-- > dir <- mktempdir "/tmp" "turtle" +-- > (file, _) <- mktemp dir "turtle" +-- > liftIO (print file) +-- > die "Urk!" ) +-- +-- Any command that is generalized over the `MonadManaged` interface can run +-- in the following contexts: +-- +-- * `Managed` (obviously) +-- * `Shell` + -- $cmdline -- -- The "Turtle.Options" module lets you easily parse command line arguments, @@ -1695,6 +1731,11 @@ -- -- These are the most frequently asked questions from new users: -- +-- /Question:/ My program hangs when I run a subprocess that reads from standard +-- input. What do I do? +-- +-- /Answer:/ Make sure you compile your program with the @-threaded@ flag +-- -- /Question:/ How do I convert `FilePath` to `Text`? -- -- /Answer:/ Use @(`format` `fp`)@ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/turtle-1.2.5/turtle.cabal new/turtle-1.2.6/turtle.cabal --- old/turtle-1.2.5/turtle.cabal 2016-01-07 05:54:31.000000000 +0100 +++ new/turtle-1.2.6/turtle.cabal 2016-04-03 20:32:35.000000000 +0200 @@ -1,5 +1,5 @@ Name: turtle -Version: 1.2.5 +Version: 1.2.6 Cabal-Version: >=1.10 Build-Type: Simple License: BSD3 @@ -50,10 +50,10 @@ async >= 2.0.0.0 && < 2.2, clock >= 0.4.1.2 && < 0.7, directory >= 1.0.7 && < 1.3, - foldl >= 1.1 && < 1.2, + foldl >= 1.1 && < 1.3, hostname < 1.1, - managed < 1.1, - process >= 1.0.1.1 && < 1.3, + managed >= 1.0.3 && < 1.1, + process >= 1.0.1.1 && < 1.5, system-filepath >= 0.3.1 && < 0.5, system-fileio >= 0.2.1 && < 0.4, stm < 2.5, @@ -86,7 +86,7 @@ Default-Language: Haskell2010 Build-Depends: base >= 4 && < 5 , - doctest >= 0.9.12 && < 0.11 + doctest >= 0.9.12 && < 0.12 benchmark bench Type: exitcode-stdio-1.0
