我正在从git存储库解析文件,并且在计划使用gitlib模块时,我现在正在使用git可执行文件获取文件内容 - 直到我找到一些教程或有时间深入了解gitlib的代码。
我有一个函数,它基本上为特定提交的特定文件运行“git show”,并返回其内容。这是一个完整的工作示例。
import System.IO
import System.Process
import System.Exit
main = do
let commit = Commit { hash = "811e22679008298176d8be24eedc65f9e8c4900b", time = ""}
fileIO <- showFileIO "/path/to/the/repo" (commit, "/path/to/the/file")
putStr (show fileIO)
showFileIO :: String -> (Commit, String) -> IO (Commit, String, String)
showFileIO directory (commit, filepath) = do
(_, Just hout, Just herr, procHandle) <- createProcess $ createCommand command directory
hSetEncoding hout utf8
hSetEncoding herr utf8
exitCode <- waitForProcess procHandle
stdOut <- hGetContents hout
stdErr <- hGetContents herr
if exitCode == ExitSuccess
then return (commit, filepath, stdOut)
-- Continue in the case of an error.
else return (commit, filepath, "")
where command = "git show " ++ (hash commit) ++ ":" ++ filepath
createCommand :: String -> FilePath -> CreateProcess
createCommand command directory = (shell command){std_out = CreatePipe, std_err = CreatePipe, cwd = Just directory}
-- Where Commit is defined as:
data Commit = Commit { hash :: String
, time :: String
} deriving (Show)
当获取带有mime-type“text / x-php”和charset“utf-8”的php文件的内容时,我最初得到一些错误(“无效的字节序列”),并且当我设置时解决了把手的编码改为utf8。还有另一个mime-type“text / html”文件实际上是一个带有charset“utf-8”的html.twig文件(Twig模板引擎)。现在,当尝试获取此文件的内容时,该函数将无限期挂起。它适用于其他文件。
任何想法都可能出错?我怎么能在Haskell中调试一些不会给我错误或任何信息的东西?是否有任何调试工具可以帮助解决这个问题?
答案 0 :(得分:3)
我会尝试这样的事情:(未经测试)
showFileIO directory (commit, filepath) = do
(_, Just hout, Just herr, procHandle) <- createProcess $ createCommand command directory
hSetEncoding hout utf8
hSetEncoding herr utf8
stdOut <- hGetContents hout
evaluate (length stdOut) -- strictify the above lazy IO
stdErr <- hGetContents herr
evaluate (length stdErr)
exitCode <- waitForProcess procHandle
if exitCode == ExitSuccess
...
或者,使用hGetContents
的一些严格IO变体。
请注意,据我所知,还有一些死锁窗口。如果该命令在stderr上产生大量数据,那么命令&amp;操作系统缓冲区将变满,写入stderr将阻止。由于Haskell消费者现在首先等待stdout被完全消耗,我们陷入僵局。请注意,对于&#34;短&#34;这不会是一个问题。错误消息。
如果我们想让它更强大,我们需要同时读取stdout和stderr。 E.g。
showFileIO directory (commit, filepath) = do
(_, Just hout, Just herr, procHandle) <- createProcess $ createCommand command directory
hSetEncoding hout utf8
hSetEncoding herr utf8
stdOutV <- newEmptyMVar
stdErrV <- newEmptyMVar
forkIO $ do
stdOut <- hGetContents hout
evaluate (length stdOut)
putMVar stdOutV stdOut
forkIO $ fo
stdErr <- hGetContents herr
evaluate (length stdErr)
putMVar stdErrV stdErr
stdOut <- takeMVar stdOutV
stdErr <- takeMVar stdErrV
exitCode <- waitForProcess procHandle
if exitCode == ExitSuccess
...
更新。这也应该有效,而且更简单。
showFileIO directory (commit, filepath) = do
(_, Just hout, Just herr, procHandle) <- createProcess $ createCommand command directory
hSetEncoding hout utf8
hSetEncoding herr utf8
stdOut <- hGetContents hout
stdErr <- hGetContents herr
forkIO $ evaluate (length stdOut)
evaluate (length stdErr)
exitCode <- waitForProcess procHandle
if exitCode == ExitSuccess
...
如果有一些图书馆功能为您完成所有这些工作,我不会感到惊讶,但我现在无法记住任何事情。
无关:我更喜欢proc
到shell
来构建CreateProcess
选项。后者需要仔细转义文件名(空格,特殊字符),而前者只需要一个字符串参数列表。