{-# LANGUAGE ScopedTypeVariables #-}
module Retrie.Util where
import Control.Applicative
import Control.Concurrent.Async
import Control.Exception
import Data.Bifunctor (second)
import Data.List
import System.Exit
import System.FilePath
import System.Process
import Retrie.GHC
overlaps :: SrcSpan -> SrcSpan -> Bool
overlaps (RealSrcSpan s1) (RealSrcSpan s2) =
srcSpanFile s1 == srcSpanFile s2 &&
((srcSpanStartLine s1, srcSpanStartCol s1) `within` s2 ||
(srcSpanEndLine s1, srcSpanEndCol s1) `within` s2)
overlaps _ _ = False
within :: (Int, Int) -> RealSrcSpan -> Bool
within (l,p) s =
srcSpanStartLine s <= l &&
srcSpanStartCol s <= p &&
srcSpanEndLine s >= l &&
srcSpanEndCol s >= p
lineCount :: [SrcSpan] -> Int
lineCount ss = sum
[ srcSpanEndLine s - srcSpanStartLine s + 1
| RealSrcSpan s <- ss
]
showRdrs :: [RdrName] -> String
showRdrs = show . map (occNameString . occName)
data Verbosity = Silent | Normal | Loud
deriving (Eq, Ord, Show)
debugPrint :: Verbosity -> String -> [String] -> IO ()
debugPrint verbosity header ls
| verbosity < Loud = return ()
| otherwise = mapM_ putStrLn (header:ls)
vcsIgnorePred :: FilePath -> IO (Maybe (FilePath -> Bool))
vcsIgnorePred fp = do
(gitPred, hgPred) <- concurrently (gitIgnorePred fp) (hgIgnorePred fp)
return $ gitPred <|> hgPred
gitIgnorePred :: FilePath -> IO (Maybe (FilePath -> Bool))
gitIgnorePred targetDir = do
let
cmd =
(proc "git"
[ "ls-files"
, "--ignored"
, "--exclude-standard"
, "--others"
, "--directory"
, targetDir
])
{ cwd = Just targetDir }
(ec, fps, _) <- readCreateProcessWithExitCode cmd ""
case ec of
ExitSuccess -> do
let
(ifiles, idirs) = partition hasExtension
[ normalise $ targetDir </> dropTrailingPathSeparator f
| f <- lines fps ]
return $ Just (\fp -> fp `elem` ifiles || any (`isPrefixOf` fp) idirs)
ExitFailure _ -> return Nothing
hgIgnorePred :: FilePath -> IO (Maybe (FilePath -> Bool))
hgIgnorePred targetDir = do
let
cmd =
(proc "hg"
[ "status"
, "--ignored"
, "--no-status"
, "-I"
, "re:.*\\.hs$"
])
{ cwd = Just targetDir }
(ec, fps, _) <- readCreateProcessWithExitCode cmd ""
case ec of
ExitSuccess -> do
let
(ifiles, dirs) = partition hasExtension
[ normalise $ targetDir </> dropTrailingPathSeparator f
| f <- lines fps ]
idirs = normalise (targetDir </> ".hg") : dirs
return $ Just $ \fp -> fp `elem` ifiles || any (`isPrefixOf` fp) idirs
ExitFailure _ -> return Nothing
trySync :: IO a -> IO (Either SomeException a)
trySync io = catch (Right <$> io) $ \e ->
case fromException e of
Just (_ :: SomeAsyncException) -> throwIO e
Nothing -> return (Left e)
uniqBag :: Uniquable a => [(a,b)] -> UniqFM [b]
uniqBag = listToUFM_C (++) . map (second pure)