From 867110e9ee411b7dde2f7a195f09b1f80c442f40 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Fri, 5 Sep 2025 14:51:26 -0400 Subject: [PATCH] add readFileString, writeFileString, appendFileString Exported by Common, so they will be available everywhere. These are the same as readFile, writeFile, appendFile. But have two benefits: * They take OsPath, so using them avoids converting back and forth unncessarily. * They use the close-on-exec flag so can't leak FDs to child processes. Unlike the standard Haskell versions which unfortunately have that wart currently. (I do hope the standard versions get fixed eventually.) Sponsored-by: the NIH-funded NICEMAN (ReproNim TR&D3) project --- Common.hs | 1 + Utility/FileIO.hs | 41 ++++++++++++++++++++++++++++++++++++---- Utility/FileIO/String.hs | 38 +++++++++++++++++++++++++++++++++++++ git-annex.cabal | 1 + 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 Utility/FileIO/String.hs diff --git a/Common.hs b/Common.hs index fe322fa1c4..8d65125965 100644 --- a/Common.hs +++ b/Common.hs @@ -33,5 +33,6 @@ import Utility.Network as X import Utility.Split as X import Utility.FileSystemEncoding as X import Utility.OsPath as X +import Utility.FileIO as X (readFileString, writeFileString, appendFileString) import Utility.PartialPrelude as X diff --git a/Utility/FileIO.hs b/Utility/FileIO.hs index 7c13d84925..99ea538823 100644 --- a/Utility/FileIO.hs +++ b/Utility/FileIO.hs @@ -1,6 +1,8 @@ -{- This is a subset of the functions provided by file-io. +{- This is a subset of the functions provided by file-io, supplimented with + - readFileString, writeFileString, and appendFileString. - - - All exported functions set the close-on-exec flag. + - When building with file-io, all exported functions set the close-on-exec + - flag. - - When not building with file-io, this provides equvilant - RawFilePath versions. Note that those versions do not currently @@ -31,12 +33,17 @@ module Utility.FileIO appendFile, appendFile', openTempFile, + + readFileString, + writeFileString, + appendFileString, ) where #ifdef WITH_OSPATH #ifndef mingw32_HOST_OS import Utility.FileIO.CloseOnExec +import Utility.FileIO.String #else -- On Windows, System.File.OsPath does not handle UNC-style conversion itself, -- so that has to be done when calling it. See @@ -44,8 +51,9 @@ import Utility.FileIO.CloseOnExec import Utility.Path.Windows import Utility.OsPath import System.IO (IO, Handle, IOMode) -import Prelude (return) +import Prelude (String, return) import qualified Utility.FileIO.CloseOnExec as O +import qualified Utility.FileIO.String as O import qualified Data.ByteString as B import Control.Applicative @@ -106,6 +114,21 @@ openTempFile p s = do -- Avoid returning mangled path from convertToWindowsNativeNamespace let t' = p takeFileName t return (t', h) + +readFileString :: OsPath -> IO String +readFileString p = do + p' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath p) + I.readFileString p' + +writeFileString :: OsPath -> String -> IO () +writeFileString f txt = do + f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f) + I.writeFileString f' txt + +appendFileString :: OsPath -> String -> IO () +appendFileString f txt = do + f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f) + I.appendFileString f' txt #endif #else @@ -113,7 +136,8 @@ openTempFile p s = do import Utility.OsPath import Utility.FileSystemEncoding import System.IO (IO, Handle, IOMode) -import Prelude ((.), return) +import Prelude (String, (.), return) +import qualified Prelude as P import qualified System.IO import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L @@ -154,4 +178,13 @@ openTempFile p s = do (fromRawFilePath p) (fromRawFilePath s) return (toRawFilePath t, h) + +readFileString :: OsPath -> IO String +readFileString = P.readFile . fromRawFilePath + +writeFileString :: OsPath -> String -> IO () +writeFileString = P.writeFile . fromRawFilePath + +appendFileString :: OsPath -> String -> IO () +appendFileString = P.appendFile . fromRawFilePath #endif diff --git a/Utility/FileIO/String.hs b/Utility/FileIO/String.hs new file mode 100644 index 0000000000..2159960998 --- /dev/null +++ b/Utility/FileIO/String.hs @@ -0,0 +1,38 @@ +{- Functions that operate on OsPath, but treat the contents of files as + - Strings. + - + - These functions all set the close-on-exec flag to True, unlike + - the Prelude versions. + - + - Copyright 2025 Joey Hess + - + - License: BSD-2-clause + -} + +{-# OPTIONS_GHC -fno-warn-tabs #-} +{-# LANGUAGE CPP #-} + +module Utility.FileIO.String +( +#ifdef WITH_OSPATH + readFileString, + writeFileString, + appendFileString, +#endif +) where + +#ifdef WITH_OSPATH +import qualified Utility.FileIO.CloseOnExec as I +import Utility.OsPath (OsPath) +import Prelude (String, IO, (>>=)) +import System.IO (IOMode(..), hGetContents, hPutStr) + +readFileString :: OsPath -> IO String +readFileString f = I.openFile f ReadMode >>= hGetContents + +writeFileString :: OsPath -> String -> IO () +writeFileString f txt = I.withFile f WriteMode (\hdl -> hPutStr hdl txt) + +appendFileString :: OsPath -> String -> IO () +appendFileString f txt = I.withFile f AppendMode (\hdl -> hPutStr hdl txt) +#endif diff --git a/git-annex.cabal b/git-annex.cabal index efa8b275e3..8591e54d9f 100644 --- a/git-annex.cabal +++ b/git-annex.cabal @@ -1149,6 +1149,7 @@ Executable git-annex Utility.SystemDirectory Utility.FileIO Utility.FileIO.CloseOnExec + Utility.FileIO.String Utility.Terminal Utility.TimeStamp Utility.TList -- 2.30.2