2 ( writeBinary, readBinary
18import Control.Exception (catch)
19import Control.Monad.Trans (liftIO)
20import qualified Data.Binary as Binary
21import qualified Data.ByteString as BS
22import qualified Data.ByteString.Internal as BS
23import qualified Data.ByteString.Builder as B
24import qualified Data.ByteString.Builder.Extra as B (defaultChunkSize)
25import qualified Foreign.ForeignPtr as FPtr
26import GHC.IO.Exception (IOException, IOErrorType(InvalidArgument))
27import qualified System.Directory as Dir
28import System.FilePath ((</>))
29import qualified System.FilePath as FP
30import qualified System.IO as IO
31import System.IO.Error (ioeGetErrorType, annotateIOError, modifyIOError)
33import qualified Reporting.Exit as Exit
34import qualified Reporting.Exit.Assets as E
35import qualified Reporting.Task as Task
42writeBinary :: (Binary.Binary a) => FilePath -> a -> Task.Task ()
43writeBinary path value =
45 do let dir = FP.dropFileName path
46 Dir.createDirectoryIfMissing True dir
47 Binary.encodeFile path value
50readBinary :: (Binary.Binary a) => FilePath -> Task.Task a
52 do exists_ <- liftIO (Dir.doesFileExist path)
54 then throwCorruptBinary path
56 do result <- liftIO (Binary.decodeFileOrFail path)
59 throwCorruptBinary path
65throwCorruptBinary :: FilePath -> Task.Task a
66throwCorruptBinary filePath =
67 Task.throw (Exit.Assets (E.CorruptBinary filePath))
74writeUtf8 :: FilePath -> BS.ByteString -> IO ()
75writeUtf8 filePath content =
76 withUtf8 filePath IO.WriteMode $ \handle ->
77 BS.hPut handle content
80withUtf8 :: FilePath -> IO.IOMode -> (IO.Handle -> IO a) -> IO a
81withUtf8 filePath mode callback =
82 IO.withFile filePath mode $ \handle ->
83 do IO.hSetEncoding handle IO.utf8
91readUtf8 :: FilePath -> IO BS.ByteString
93 withUtf8 filePath IO.ReadMode $ \handle ->
94 modifyIOError (encodingError filePath) $
95 do fileSize <- catch (IO.hFileSize handle) useZeroIfNotRegularFile
96 let readSize = max 0 (fromIntegral fileSize) + 1
97 hGetContentsSizeHint handle readSize (max 255 readSize)
100useZeroIfNotRegularFile :: IOException -> IO Integer
101useZeroIfNotRegularFile _ =
105hGetContentsSizeHint :: IO.Handle -> Int -> Int -> IO BS.ByteString
106hGetContentsSizeHint handle =
109 readChunks chunks readSize incrementSize =
110 do fp <- BS.mallocByteString readSize
111 readCount <- FPtr.withForeignPtr fp $ \buf -> IO.hGetBuf handle buf readSize
112 let chunk = BS.PS fp 0 readCount
113 if readCount < readSize && readSize > 0
114 then return $! BS.concat (reverse (chunk:chunks))
115 else readChunks (chunk:chunks) incrementSize (min 32752 (readSize + incrementSize))
118encodingError :: FilePath -> IOError -> IOError
119encodingError filePath ioErr =
120 case ioeGetErrorType ioErr of
123 (userError "Bad encoding; the file must be valid UTF-8")
136writeBuilder :: FilePath -> B.Builder -> IO ()
137writeBuilder path builder =
138 IO.withBinaryFile path IO.WriteMode $ \handle ->
139 do IO.hSetBuffering handle (IO.BlockBuffering Nothing)
140 B.hPutBuilder handle builder
148 Writer (IO.Handle -> IO ())
151put :: FilePath -> Writer -> IO ()
152put path (Writer callback) =
153 IO.withBinaryFile path IO.WriteMode callback
156putByteString :: BS.ByteString -> Writer
162putBuilder :: B.Builder -> Writer
165 B.hPutBuilder handle builder
168putFile :: FilePath -> Writer
171 IO.withBinaryFile path IO.ReadMode $ \source ->
175putHelp :: IO.Handle -> IO.Handle -> IO ()
177 do chunk <- BS.hGet source B.defaultChunkSize
181 do BS.hPut sink chunk
189exists :: FilePath -> Task.Task_ e Bool
191 liftIO $ Dir.doesFileExist filePath
198remove :: FilePath -> Task.Task_ e ()
201 do exists_ <- Dir.doesFileExist filePath
203 then Dir.removeFile filePath
207removeDir :: FilePath -> IO ()
209 do exists_ <- Dir.doesDirectoryExist path
211 then Dir.removeDirectoryRecursive path
219find :: FilePath -> IO (Maybe FilePath)
221 do subDir <- Dir.getCurrentDirectory
222 findHelp name (FP.splitDirectories subDir)
225findHelp :: FilePath -> [String] -> IO (Maybe FilePath)
231 do exists_ <- Dir.doesFileExist (FP.joinPath dirs </> name)
233 then return (Just (FP.joinPath dirs))
234 else findHelp name (init dirs)
241andM :: (Monad m) => [m Bool] -> m Bool
247 check : otherChecks ->
249 if bool then andM otherChecks else return False
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list