1{- git check-ignore interface 2 - 3 - Copyright 2013 Joey Hess <id@joeyh.name> 4 - 5 - Licensed under the GNU AGPL version 3 or higher. 6 -} 7 8module Git.CheckIgnore ( 9 CheckIgnoreHandle, 10 checkIgnoreStart, 11 checkIgnoreStop, 12 checkIgnored 13) where 14 15import Common 16import Git 17import Git.Command 18import qualified Utility.CoProcess as CoProcess 19 20import System.IO.Error 21import qualified Data.ByteString as B 22 23type CheckIgnoreHandle = CoProcess.CoProcessHandle 24 25{- Starts git check-ignore running, and returns a handle. 26 - 27 - This relies on git check-ignore --non-matching -v outputting 28 - lines for both matching an non-matching files. Also relies on 29 - GIT_FLUSH behavior flushing the output buffer when git check-ignore 30 - is piping to us. 31 - 32 - check-ignore does not support --literal-pathspecs, so remove that 33 - from the gitGlobalOpts if set. 34 -} 35checkIgnoreStart :: Repo -> IO CheckIgnoreHandle 36checkIgnoreStart repo = gitCoProcessStart True params repo' 37 where 38 params = 39 [ Param "check-ignore" 40 , Param "-z" 41 , Param "--stdin" 42 , Param "--verbose" 43 , Param "--non-matching" 44 ] 45 repo' = repo { gitGlobalOpts = filter (not . pathspecs) (gitGlobalOpts repo) } 46 pathspecs (Param "--literal-pathspecs") = True 47 pathspecs _ = False 48 49{- For some reason, check-ignore --batch always exits nonzero, 50 - so ignore any error. -} 51checkIgnoreStop :: CheckIgnoreHandle -> IO () 52checkIgnoreStop = void . tryIO . CoProcess.stop 53 54{- Returns True if a file is ignored. -} 55checkIgnored :: CheckIgnoreHandle -> RawFilePath -> IO Bool 56checkIgnored h file = CoProcess.query h send (receive "") 57 where 58 send to = do 59 B.hPutStr to $ file `B.snoc` 0 60 hFlush to 61 receive c from = do 62 s <- hGetSomeString from 1024 63 if null s 64 then eofError 65 else do 66 let v = c ++ s 67 maybe (receive v from) return (parse v) 68 parse s = case segment (== '\0') s of 69 (_source:_line:pattern:_pathname:_eol:[]) -> Just $ not $ null pattern 70 _ -> Nothing 71 eofError = ioError $ mkIOError userErrorType "git cat-file EOF" Nothing Nothing 72