Hello community,

here is the log from the commit of package ghc-rio for openSUSE:Factory checked 
in at 2018-12-10 12:29:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-rio (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-rio.new.19453 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-rio"

Mon Dec 10 12:29:46 2018 rev:5 rq:656588 version:0.1.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-rio/ghc-rio.changes  2018-10-25 
09:03:47.678598209 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-rio.new.19453/ghc-rio.changes       
2018-12-10 12:29:48.486438822 +0100
@@ -1,0 +2,11 @@
+Sat Dec  8 03:01:23 UTC 2018 - psim...@suse.com
+
+- Update rio to version 0.1.6.0.
+  ## 0.1.6.0
+
+  * Changed `logUseColor` to default to `False` on Windows, even when verbose 
and on the terminal
+  * Add `RIO.File` module which offers a family of file handling functions
+    (`withBinaryFileDurable`, `withBinaryFileDurableAtomic`, among others.) 
with
+    better durability and atomicity guarantees
+
+-------------------------------------------------------------------

Old:
----
  rio-0.1.5.0.tar.gz

New:
----
  rio-0.1.6.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-rio.spec ++++++
--- /var/tmp/diff_new_pack.bKoVRH/_old  2018-12-10 12:29:49.854437454 +0100
+++ /var/tmp/diff_new_pack.bKoVRH/_new  2018-12-10 12:29:49.854437454 +0100
@@ -19,7 +19,7 @@
 %global pkg_name rio
 %bcond_with tests
 Name:           ghc-%{pkg_name}
-Version:        0.1.5.0
+Version:        0.1.6.0
 Release:        0
 Summary:        A standard library for Haskell
 License:        MIT

++++++ rio-0.1.5.0.tar.gz -> rio-0.1.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rio-0.1.5.0/ChangeLog.md new/rio-0.1.6.0/ChangeLog.md
--- old/rio-0.1.5.0/ChangeLog.md        2018-07-29 10:38:08.000000000 +0200
+++ new/rio-0.1.6.0/ChangeLog.md        2018-12-07 05:22:45.000000000 +0100
@@ -1,5 +1,12 @@
 # Changelog for rio
 
+## 0.1.6.0
+
+* Changed `logUseColor` to default to `False` on Windows, even when verbose 
and on the terminal
+* Add `RIO.File` module which offers a family of file handling functions
+  (`withBinaryFileDurable`, `withBinaryFileDurableAtomic`, among others.) with
+  better durability and atomicity guarantees
+
 ## 0.1.5.0
 
 * Re-export `Numeric.Natural.Natural` 
[#119](https://github.com/commercialhaskell/rio/issues/119)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rio-0.1.5.0/rio.cabal new/rio-0.1.6.0/rio.cabal
--- old/rio-0.1.5.0/rio.cabal   2018-08-02 07:51:23.000000000 +0200
+++ new/rio-0.1.6.0/rio.cabal   2018-12-07 06:30:18.000000000 +0100
@@ -1,13 +1,13 @@
-cabal-version: >= 1.10
+cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.29.0.
+-- This file has been generated from package.yaml by hpack version 0.30.0.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 065129e1a5740200c161b7c7db66dfdea6edee782d518b17f86ccd1a8defb48c
+-- hash: bbb48d8141804c3559dabe44ac2317e1d0fae65893cea408ee1fb4297e974f6a
 
 name:           rio
-version:        0.1.5.0
+version:        0.1.6.0
 synopsis:       A standard library for Haskell
 description:    See README and Haddocks at 
<https://www.stackage.org/package/rio>
 category:       Control
@@ -19,8 +19,8 @@
 license-file:   LICENSE
 build-type:     Simple
 extra-source-files:
-    ChangeLog.md
     README.md
+    ChangeLog.md
 
 source-repository head
   type: git
@@ -36,6 +36,7 @@
       RIO.Char
       RIO.Char.Partial
       RIO.Directory
+      RIO.File
       RIO.FilePath
       RIO.HashMap
       RIO.HashMap.Partial
@@ -117,6 +118,7 @@
   type: exitcode-stdio-1.0
   main-is: Spec.hs
   other-modules:
+      RIO.FileSpec
       RIO.ListSpec
       RIO.LoggerSpec
       RIO.Prelude.ExtraSpec
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rio-0.1.5.0/src/RIO/File.hs 
new/rio-0.1.6.0/src/RIO/File.hs
--- old/rio-0.1.5.0/src/RIO/File.hs     1970-01-01 01:00:00.000000000 +0100
+++ new/rio-0.1.6.0/src/RIO/File.hs     2018-12-06 09:29:44.000000000 +0100
@@ -0,0 +1,472 @@
+{-# LANGUAGE CPP                      #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE NoImplicitPrelude        #-}
+{-# LANGUAGE OverloadedStrings        #-}
+{-|
+
+== Rationale
+
+This module offers functions to handle files that offer better durability 
and/or
+atomicity.
+
+== When to use the functions on this module?
+
+Given the usage of this functions comes at a cost in performance, it is 
important
+to consider what are the use cases that are ideal for each of the functions.
+
+=== Not Durable and not Atomic
+
+For this use case, you want to use the regular functions:
+
+* 'System.IO.withBinaryFile'
+* 'RIO.writeFileBinary'
+
+The regular use case for this scenario happens when your program is dealing 
with
+outputs that are never going to be consumed again by your program. For example,
+imagine you have a program that generates sales reports for the last month, 
this
+is a report that can be generated quickly; you don't really care if the output
+file gets corrupted or lost at one particular execution of your program given
+that is cheap to execute the data export program a second time. In other words,
+your program doesn't /rely/ on the data contained in this file in order to 
work.
+
+=== Atomic but not Durable
+
+ Imagine a scenario where your program builds a temporary file that serves as 
an
+intermediate step to a bigger task, like Object files (@.o@) in a compilation
+process. The program will use an existing @.o@ file if it is present, or it 
will
+build one from scratch if it is not. The file is not really required, but if it
+is present, it *must* be valid and consistent. In this situation, you care 
about
+atomicity, but not durability.
+
+There is no function exported by this module that provides /only/ atomicity.
+
+=== Durable but not Atomic
+
+For this use case, you want to use the functions:
+
+* 'withBinaryFileDurable'
+* 'writeBinaryFileDurable'
+
+The regular use case for this scenario happens when your program deals with 
file
+modifications that must be guaranteed to be durable, but you don't care that
+changes are consistent. If you use this function, more than likely your program
+is ensuring consistency guarantees through other means, for example, SQLite 
uses
+ the Write Ahead Log (WAL) algorithm to ensure changes are atomic at an
+application level.
+
+=== Durable and Atomic
+
+For this use case, you can use the functions:
+
+* 'withBinaryFileDurableAtomic'
+* 'writeBinaryFileDurableAtomic'
+
+The regular use case for this scenario happens when you want to ensure that
+after a program is executed, the modifications done to a file are guaranteed to
+be saved, and also that changes are rolled-back in case there is a failure 
(e.g.
+hard reboot, shutdown, etc).
+
+@since 0.1.6
+-}
+module RIO.File
+  (
+    writeBinaryFileDurable
+  , writeBinaryFileDurableAtomic
+  , withBinaryFileDurable
+  , withBinaryFileDurableAtomic
+  , ensureFileDurable
+  )
+  where
+
+import           RIO.Prelude.Reexports
+
+#ifdef WINDOWS
+import           RIO.Prelude.IO
+
+#else
+
+import           RIO.Directory          (doesFileExist)
+import           RIO.ByteString         (hPut)
+import           Data.Bits              ((.|.))
+import           Data.Typeable          (cast)
+import           Foreign.C              (CInt (..), throwErrnoIfMinus1,
+                                         throwErrnoIfMinus1Retry)
+import           GHC.IO.Device          (IODeviceType (RegularFile))
+import qualified GHC.IO.Device          as Device
+import qualified GHC.IO.FD              as FD
+import qualified GHC.IO.Handle.FD       as HandleFD
+import           System.Directory       (copyFile)
+import           System.FilePath        (takeDirectory, takeFileName, (</>))
+import           System.Posix.Internals (CFilePath, c_close, c_safe_open,
+                                         withFilePath)
+import           System.Posix.Types     (CMode (..), Fd (..))
+import           System.IO              (openBinaryTempFile)
+
+#if MIN_VERSION_base(4,9,0)
+import qualified GHC.IO.Handle.Types    as HandleFD (Handle (..), Handle__ 
(..))
+#endif
+
+
+-- TODO: Add a ticket/pull request to export this symbols from
+-- System.Internal.Posix
+--
+-- NOTE: System.Posix.Internal doesn't re-export this constants so we have to
+-- recreate-them here
+foreign import ccall unsafe "HsBase.h __hscore_o_rdonly" o_RDONLY :: CInt
+foreign import ccall unsafe "HsBase.h __hscore_o_wronly" o_WRONLY :: CInt
+foreign import ccall unsafe "HsBase.h __hscore_o_rdwr"   o_RDWR   :: CInt
+foreign import ccall unsafe "HsBase.h __hscore_o_append" o_APPEND :: CInt
+foreign import ccall unsafe "HsBase.h __hscore_o_creat"  o_CREAT  :: CInt
+foreign import ccall unsafe "HsBase.h __hscore_o_noctty" o_NOCTTY :: CInt
+
+-- After here, we have our own imports
+foreign import ccall safe "fcntl.h openat"
+  c_safe_openat :: CInt -> CFilePath -> CInt -> CMode -> IO CInt
+
+foreign import ccall safe "fcntl.h renameat"
+  c_safe_renameat :: CInt -> CFilePath -> CInt -> CFilePath -> IO CInt
+
+foreign import ccall safe "unistd.h fsync"
+  c_safe_fsync :: CInt -> IO CInt
+
+std_flags, output_flags, read_flags, write_flags, rw_flags,
+    append_flags :: CInt
+std_flags    = o_NOCTTY
+output_flags = std_flags    .|. o_CREAT
+read_flags   = std_flags    .|. o_RDONLY
+write_flags  = output_flags .|. o_WRONLY
+rw_flags     = output_flags .|. o_RDWR
+append_flags = write_flags  .|. o_APPEND
+
+ioModeToFlags :: IOMode -> CInt
+ioModeToFlags iomode =
+  case iomode of
+    ReadMode      -> read_flags
+    WriteMode     -> write_flags
+    ReadWriteMode -> rw_flags
+    AppendMode    -> append_flags
+
+-- | Returns a low-level file descriptor for a directory path. This function
+-- exists given the fact that 'openFile' does not work with directories.
+--
+-- If you use this function, make sure you are working on a masked state,
+-- otherwise async exceptions may leave file descriptors open.
+--
+-- @since 0.1.6
+openDir :: MonadIO m => FilePath -> m Fd
+openDir fp
+  -- TODO: Investigate what is the situation with Windows FS in regards to 
non_blocking
+  -- NOTE: File operations _do not support_ non_blocking on various kernels, 
more
+  -- info can be found here: https://ghc.haskell.org/trac/ghc/ticket/15153
+ =
+  liftIO $
+  withFilePath fp $ \cFp ->
+    Fd <$>
+    (throwErrnoIfMinus1Retry "openDir" $
+     c_safe_open cFp (ioModeToFlags ReadMode) 0o660)
+
+-- | Closes a 'Fd' that points to a Directory.
+--
+-- @since 0.1.6
+closeDirectory :: MonadIO m => Fd -> m ()
+closeDirectory (Fd dirFd) =
+  liftIO $
+  void $
+  throwErrnoIfMinus1Retry "closeDirectory" $ c_close dirFd
+
+-- | Executes the low-level C function fsync on a C file descriptor
+--
+-- @since 0.1.6
+fsyncFileDescriptor
+  :: MonadIO m
+  => String -- ^ Meta-description for error messages
+  -> CInt   -- ^ C File Descriptor
+  -> m ()
+fsyncFileDescriptor name cFd =
+  liftIO $
+  void $
+    throwErrnoIfMinus1 ("fsync - " <> name) $
+    c_safe_fsync cFd
+
+-- | Opens a file from a directory, using this function in favour of a regular
+-- 'openFile' guarantees that any file modifications are kept in the same
+-- directory where the file was opened. An edge case scenario is a mount
+-- happening in the directory where the file was opened while your program is
+-- running.
+--
+-- If you use this function, make sure you are working on an masked state,
+-- otherwise async exceptions may leave file descriptors open.
+--
+openFileFromDir :: (MonadIO m) => Fd -> FilePath -> IOMode -> m Handle
+openFileFromDir (Fd dirFd) fp iomode =
+  liftIO $
+  withFilePath fp $ \f -> do
+    bracketOnError
+      (do fileFd <- throwErrnoIfMinus1Retry "openFileFromDir" $
+                      c_safe_openat dirFd f (ioModeToFlags iomode)
+                                            0o666 {- Can open directory with 
read only -}
+          FD.mkFD
+             fileFd
+             iomode
+             Nothing {- no stat -}
+             False {- not a socket -}
+             False {- non_blocking -}
+            `onException` c_close fileFd)
+      (liftIO . Device.close . fst)
+      (\(fD, fd_type) -> do
+         -- we want to truncate() if this is an open in WriteMode, but only if 
the
+         -- target is a RegularFile. ftruncate() fails on special files like
+         -- /dev/null.
+         when (iomode == WriteMode && fd_type == RegularFile) $
+           Device.setSize fD 0
+         HandleFD.mkHandleFromFD fD fd_type fp iomode False Nothing)
+
+-- | Opens a file using the openat C low-level API. This approach allows us to
+-- get a file descriptor for the directory that contains the file, which we can
+-- use later on to fsync the directory with.
+--
+-- If you use this function, make sure you are working on an masked state,
+-- otherwise async exceptions may leave file descriptors open.
+--
+-- @since 0.1.6
+openFileAndDirectory :: MonadUnliftIO m => FilePath -> IOMode -> m (Fd, Handle)
+openFileAndDirectory absFp iomode =  do
+  let dir = takeDirectory absFp
+      fp = takeFileName absFp
+
+  bracketOnError (openDir dir) closeDirectory $ \dirFd -> do
+    fileHandle <- openFileFromDir dirFd fp iomode
+    return (dirFd, fileHandle)
+
+-- | This sub-routine does the following tasks:
+--
+-- * It calls fsync and then closes the given Handle (mapping to a 
temporal/backup filepath)
+-- * It calls fsync and then closes the containing directory of the file
+--
+-- These steps guarantee that the file changes are durable.
+--
+-- @since 0.1.6
+closeFileDurable :: MonadIO m => Fd -> Handle -> m ()
+closeFileDurable dirFd@(Fd cDirFd) h =
+  liftIO $
+  finally
+    (do (withHandleFd h $ \fileFd ->
+           fsyncFileDescriptor "closeFileDurable/File" (FD.fdFD fileFd))
+          `finally` hClose h
+        -- NOTE: Here we are purposefully not fsyncing the directory if the 
file fails to fsync
+        fsyncFileDescriptor "closeFileDurable/Directory" cDirFd)
+    (closeDirectory dirFd)
+
+buildTemporaryFilePath :: MonadUnliftIO m => FilePath -> m FilePath
+buildTemporaryFilePath filePath = do
+  let
+    dirFp  = takeDirectory filePath
+    fileFp = takeFileName filePath
+  bracket (liftIO $ openBinaryTempFile dirFp fileFp)
+          (hClose . snd)
+          (return . fst)
+
+toTmpFilePath :: MonadUnliftIO m => FilePath -> m FilePath
+toTmpFilePath filePath =
+    buildTemporaryFilePath (dirPath </> tmpFilename)
+  where
+    dirPath = takeDirectory filePath
+    filename = takeFileName filePath
+    tmpFilename = "." <> filename <> ".tmp"
+
+withHandleFd :: Handle -> (FD.FD -> IO a) -> IO a
+withHandleFd h cb =
+  case h of
+    HandleFD.FileHandle _ mv -> do
+      withMVar mv $ \HandleFD.Handle__{HandleFD.haDevice = dev} ->
+        case cast dev of
+          Just fd -> cb fd
+          Nothing -> error "withHandleFd: not a file handle"
+    HandleFD.DuplexHandle {} -> error "withHandleFd: not a file handle"
+
+
+-- | This sub-routine does the following tasks:
+--
+-- * It calls fsync and then closes the given Handle (mapping to a 
temporal/backup filepath)
+-- * It renames the file to the original path (using renameat)
+-- * It calls fsync and then closes the containing directory of the file
+--
+-- These steps guarantee that the file is durable, and that the backup 
mechanism
+-- for catastrophic failure is discarded after no error is thrown.
+--
+-- @since 0.1.6
+closeFileDurableAtomic ::
+     MonadUnliftIO m => FilePath -> FilePath -> Fd -> Handle -> m ()
+closeFileDurableAtomic tmpFilePath filePath dirFd@(Fd cDirFd) fileHandle = do
+  liftIO $
+    finally
+      (withFilePath tmpFilePath $ \tmpFp ->
+         withFilePath filePath $ \fp -> do
+           (withHandleFd fileHandle $ \fileFd ->
+               fsyncFileDescriptor "closeFileDurableAtomic/File" (FD.fdFD 
fileFd))
+             `finally` hClose fileHandle
+           renameFile tmpFp fp
+           fsyncFileDescriptor "closeFileDurableAtomic/Directory" cDirFd)
+      (closeDirectory dirFd)
+  where
+    renameFile tmpFp origFp =
+      void $
+      throwErrnoIfMinus1Retry "closeFileDurableAtomic - renameFile" $
+      c_safe_renameat cDirFd tmpFp cDirFd origFp
+
+#endif
+
+-- | After a file is closed, it opens it again and executes fsync internally on
+-- both the file and the directory that contains it. Note this function is
+-- intended to work around the non-durability of existing file APIs, as opposed
+-- to being necessary for the API functions provided in 'RIO.File' module.
+--
+-- [The effectiveness of calling this function is
+-- 
debatable](https://stackoverflow.com/questions/37288453/calling-fsync2-after-close2/50158433#50158433),
+-- as it relies on internal implementation details at the Kernel level that
+-- might change. We argue that, despite this fact, calling this function may
+-- bring benefits in terms of durability.
+--
+-- === Cross-Platform support
+--
+-- This function is a noop on Windows platforms.
+--
+-- @since 0.1.6
+ensureFileDurable :: MonadUnliftIO m => FilePath -> m ()
+ensureFileDurable absFp =
+#if WINDOWS
+  absFp `seq` return ()
+#else
+  bracket (openFileAndDirectory absFp ReadMode)
+          (uncurry closeFileDurable)
+          (const $ return ())
+#endif
+
+
+-- | Similar to 'writeFileBinary', but it also ensures that changes executed to
+-- the file are guaranteed to be durable. It internally uses fsync and makes
+-- sure it synchronizes the file on disk.
+--
+-- === Cross-Platform support
+--
+-- This function behaves the same as 'RIO.writeFileBinary' on Windows 
platforms.
+--
+-- @since 0.1.6
+writeBinaryFileDurable :: MonadUnliftIO m => FilePath -> ByteString -> m ()
+writeBinaryFileDurable absFp bytes =
+#if WINDOWS
+  writeFileBinary absFp bytes
+#else
+  withBinaryFileDurable absFp WriteMode (liftIO . (`hPut` bytes))
+#endif
+
+-- | Similar to 'writeFileBinary', but it also guarantes that changes executed
+-- to the file are durable, also, in case of failure, the modified file is 
never
+-- going to get corrupted. It internally uses fsync and makes sure it
+-- synchronizes the file on disk.
+--
+-- === Cross-Platform support
+--
+-- This function behaves the same as 'RIO.writeFileBinary' on Windows 
platforms.
+--
+-- @since 0.1.6
+writeBinaryFileDurableAtomic :: MonadUnliftIO m => FilePath -> ByteString -> m 
()
+writeBinaryFileDurableAtomic fp bytes =
+#if WINDOWS
+  writeFileBinary fp bytes
+#else
+  withBinaryFileDurableAtomic fp WriteMode (liftIO . (`hPut` bytes))
+#endif
+
+-- | Opens a file with the following guarantees:
+--
+-- * It successfully closes the file in case of an asynchronous exception
+--
+-- * It reliably saves the file in the correct directory; including edge case
+--   situations like a different device being mounted to the current directory,
+--   or the current directory being renamed to some other name while the file 
is
+--   being used.
+--
+-- * It ensures durability by executing an fsync call before closing the file
+--   handle
+--
+-- === Cross-Platform support
+--
+-- This function behaves the same as 'System.IO.withBinaryFile' on Windows 
platforms.
+--
+-- @since 0.1.6
+withBinaryFileDurable ::
+     MonadUnliftIO m => FilePath -> IOMode -> (Handle -> m r) -> m r
+withBinaryFileDurable absFp iomode cb =
+#if WINDOWS
+  withBinaryFile absFp iomode cb
+#else
+  withRunInIO $ \run ->
+    bracket
+      (openFileAndDirectory absFp iomode)
+      (uncurry closeFileDurable)
+      (run . cb . snd)
+#endif
+
+-- | Opens a file with the following guarantees:
+--
+-- * It successfully closes the file in case of an asynchronous exception
+--
+-- * It reliably saves the file in the correct directory; including edge case
+--   situations like a different device being mounted to the current directory,
+--   or the current directory being renamed to some other name while the file 
is
+--   being used.
+--
+-- * It ensures durability by executing an fsync call before closing the file
+--   handle
+--
+ -- * It keeps all changes in a temporary file, and after it is closed it 
atomically
+--   moves the temporal file to the original filepath, in case of catastrophic
+--   failure, the original file stays unaffected.
+--
+--
+-- === Performance Considerations
+--
+-- When using a writable but non-truncating 'IOMode' (i.e. 'ReadWriteMode' and
+-- 'AppendMode'), this function performs a copy operation of the specified 
input
+-- file to guarantee the original file is intact in case of a catastrophic
+-- failure (no partial writes). This approach may be prohibitive in scenarios
+-- where the input file is expected to be large in size.
+--
+-- === Cross-Platform support
+--
+-- This function behaves the same as 'System.IO.withBinaryFile' on Windows
+-- platforms.
+--
+-- @since 0.1.6
+withBinaryFileDurableAtomic ::
+     MonadUnliftIO m => FilePath -> IOMode -> (Handle -> m r) -> m r
+withBinaryFileDurableAtomic absFp iomode cb = do
+#if WINDOWS
+  withBinaryFile absFp iomode cb
+#else
+  withRunInIO $ \run ->
+    case iomode of
+        -- We need to consider an atomic operation only when we are on 
'WriteMode', lets
+        -- use a regular withBinaryFile
+      ReadMode -> run (withBinaryFile absFp iomode cb)
+        -- Given we are not going to read contents from the original file, we
+        -- can create a temporal file and then do an atomic move
+      WriteMode ->  do
+        tmpFp <- toTmpFilePath absFp
+        withDurableAtomic tmpFp run
+      _ {- ReadWriteMode,  AppendMode -}
+       -> do
+        -- copy original file for read purposes
+        fileExists <- doesFileExist absFp
+        tmpFp <- toTmpFilePath absFp
+        when fileExists $ copyFile absFp tmpFp
+
+        withDurableAtomic tmpFp run
+  where
+    withDurableAtomic tmpFp run = do
+      bracket
+        (openFileAndDirectory tmpFp iomode)
+        (uncurry $ closeFileDurableAtomic tmpFp absFp)
+        (run . cb . snd)
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rio-0.1.5.0/src/RIO/Prelude/IO.hs 
new/rio-0.1.6.0/src/RIO/Prelude/IO.hs
--- old/rio-0.1.5.0/src/RIO/Prelude/IO.hs       2018-03-20 11:20:54.000000000 
+0100
+++ new/rio-0.1.6.0/src/RIO/Prelude/IO.hs       2018-12-06 09:29:44.000000000 
+0100
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 module RIO.Prelude.IO
   ( withLazyFile
   , readFileBinary
@@ -7,12 +8,13 @@
   , hPutBuilder
   ) where
 
-import RIO.Prelude.Reexports
-import qualified Data.ByteString.Builder  as BB
-import qualified Data.ByteString          as B
-import qualified Data.ByteString.Lazy     as BL
-import qualified Data.Text.IO             as T
-import           System.IO                (hSetEncoding, utf8)
+import           RIO.Prelude.Reexports
+import qualified Data.ByteString         as B
+import qualified Data.ByteString.Builder as BB
+import qualified Data.ByteString.Lazy    as BL
+import qualified Data.Text.IO            as T
+import           System.IO               (hSetEncoding, utf8)
+
 
 -- | Lazily get the contents of a file. Unlike 'BL.readFile', this
 -- ensures that if an exception is thrown, the file handle is closed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rio-0.1.5.0/src/RIO/Prelude/Logger.hs 
new/rio-0.1.6.0/src/RIO/Prelude/Logger.hs
--- old/rio-0.1.5.0/src/RIO/Prelude/Logger.hs   2018-07-29 10:38:08.000000000 
+0200
+++ new/rio-0.1.6.0/src/RIO/Prelude/Logger.hs   2018-12-06 09:29:44.000000000 
+0100
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 module RIO.Prelude.Logger
@@ -292,11 +293,19 @@
 -- to perform verbose logging or not. Individiual settings can be
 -- overridden using appropriate @set@ functions.
 --
+-- When Verbose Flag is @True@, the following happens:
+--
+--     * @setLogVerboseFormat@ is called with @True@
+--     * @setLogUseColor@ is called with @True@ (except on Windows)
+--     * @setLogUseLoc@ is called with @True@
+--     * @setLogUseTime@ is called with @True@
+--     * @setLogMinLevel@ is called with 'Debug' log level
+--
 -- @since 0.0.0.0
 logOptionsHandle
   :: MonadIO m
   => Handle
-  -> Bool -- ^ verbose?
+  -> Bool -- ^ Verbose Flag
   -> m LogOptions
 logOptionsHandle handle' verbose = liftIO $ do
   terminal <- hIsTerminalDevice handle'
@@ -307,7 +316,11 @@
     , logVerboseFormat = return verbose
     , logTerminal = terminal
     , logUseTime = verbose
+#if WINDOWS
+    , logUseColor = False
+#else
     , logUseColor = verbose && terminal
+#endif
     , logUseLoc = verbose
     , logSend = \builder ->
         if useUtf8 && unicode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rio-0.1.5.0/src/RIO/Prelude/RIO.hs 
new/rio-0.1.6.0/src/RIO/Prelude/RIO.hs
--- old/rio-0.1.5.0/src/RIO/Prelude/RIO.hs      2018-07-06 05:21:05.000000000 
+0200
+++ new/rio-0.1.6.0/src/RIO/Prelude/RIO.hs      2018-12-06 09:29:44.000000000 
+0100
@@ -78,8 +78,8 @@
 --
 -- @since 0.1.4.0
 modifySomeRef :: MonadIO m => SomeRef a -> (a -> a) -> m ()
-modifySomeRef (SomeRef read write) f =
-  liftIO $ (f <$> read) >>= write
+modifySomeRef (SomeRef read' write) f =
+  liftIO $ (f <$> read') >>= write
 
 ioRefToSomeRef :: IORef a -> SomeRef a
 ioRefToSomeRef ref = do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/rio-0.1.5.0/test/RIO/FileSpec.hs 
new/rio-0.1.6.0/test/RIO/FileSpec.hs
--- old/rio-0.1.5.0/test/RIO/FileSpec.hs        1970-01-01 01:00:00.000000000 
+0100
+++ new/rio-0.1.6.0/test/RIO/FileSpec.hs        2018-12-06 09:29:44.000000000 
+0100
@@ -0,0 +1,53 @@
+{-# LANGUAGE NamedFieldPuns    #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+module RIO.FileSpec where
+
+import Test.Hspec
+import System.FilePath ((</>))
+import UnliftIO.Temporary (withSystemTempDirectory)
+
+import RIO
+import qualified RIO.ByteString as BS
+import qualified RIO.File as SUT
+
+spec :: Spec
+spec = do
+  describe "ensureFileDurable" $ do
+    it "ensures a file is durable with an fsync" $
+      withSystemTempDirectory "rio" $ \dir -> do
+        let fp = dir </> "ensure_file_durable"
+        writeFileUtf8 fp "Hello World"
+        SUT.ensureFileDurable fp
+        contents <- BS.readFile fp
+        contents `shouldBe` "Hello World"
+
+  describe "withBinaryFileDurableAtomic" $ do
+    context "read/write" $ do
+      it "works correctly" $ do
+        withSystemTempDirectory "rio" $ \dir -> do
+          let fp = dir </> "ensure_file_durable_atomic"
+          writeFileUtf8 fp "Hello World"
+          SUT.withBinaryFileDurableAtomic fp ReadWriteMode $ \h -> do
+            input <- BS.hGetLine h
+            input `shouldBe` "Hello World"
+            BS.hPut h "Goodbye World"
+
+    context "happy path" $ do
+      it "works the same as withFile" $ do
+        withSystemTempDirectory "rio" $ \dir -> do
+          let fp = dir </> "with_file_durable_atomic"
+          SUT.withBinaryFileDurableAtomic fp WriteMode $ \h ->
+            BS.hPut h "Hello World"
+          contents <- BS.readFile fp
+          contents `shouldBe` "Hello World"
+
+  describe "withBinaryFileDurable" $ do
+    context "happy path" $ do
+      it "works the same as withFile" $ do
+        withSystemTempDirectory "rio" $ \dir -> do
+          let fp = dir </> "with_file_durable"
+          SUT.withBinaryFileDurable fp WriteMode $ \h ->
+            BS.hPut h "Hello World"
+          contents <- BS.readFile fp
+          contents `shouldBe` "Hello World"


Reply via email to