Open brandon-leapyear opened 4 years ago
I used that in an old codebase:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
-- This file wraps hpc-lcov to something which understand the bazel layout
import Data.List (isPrefixOf)
import qualified Data.Map as Map
import Data.Traversable (for)
import qualified Options.Applicative as Opt
import Path (Dir, File, Path)
import qualified Path
import Path.IO (resolveFile')
import Trace.Hpc.Lcov (generateLcovFromTix, writeReport)
import Trace.Hpc.Mix (Mix (..), readMix)
import Trace.Hpc.Tix (Tix (..), TixModule, readTix, tixModuleName)
data CLIOptions = CLIOptions
{ cliTixFiles :: [FilePath],
cliOutput :: FilePath,
mixDirectories :: [FilePath]
}
getCLIOptions :: IO CLIOptions
getCLIOptions =
Opt.execParser $
Opt.info (Opt.helper <*> parseCLIOptions) $ Opt.progDesc description
where
parseCLIOptions =
CLIOptions
<$> parseCLITixFiles
<*> parseCLIOutput
<*> parseMixDirectories
parseCLITixFiles =
Opt.many $
Opt.strArgument $
mconcat
[ Opt.metavar "TIX_FILE",
Opt.help ".tix file(s) to convert"
]
parseMixDirectories =
Opt.some $
Opt.strOption $
mconcat
[ Opt.long "mix",
Opt.short 'm',
Opt.metavar "MIX_DIRECTORY",
Opt.help ".mix directories"
]
parseCLIOutput =
Opt.strOption $
mconcat
[ Opt.long "output",
Opt.short 'o',
Opt.metavar "FILE",
Opt.help "The file to save coverage information (default: lcov.info)",
Opt.value "lcov.info"
]
description = "Convert HPC coverage output into the LCOV format"
main :: IO ()
main = do
CLIOptions {..} <- getCLIOptions
tixFiles <- traverse resolveFile' cliTixFiles
tixModules <- concat <$> traverse readTixPath tixFiles
mixDirectories' <- traverse Path.parseAbsDir mixDirectories
moduleToMixList <- for tixModules $ \tixModule -> do
Mix fileLoc _ _ _ mixEntries <- readMixPath mixDirectories' (Right tixModule)
fileLocRelPath <- Path.parseRelFile fileLoc
let modulePath = fileLocRelPath
pure (tixModuleName tixModule, (Path.toFilePath modulePath, mixEntries))
let moduleToMix = Map.toList . Map.fromListWith checkDupeMix $ moduleToMixList
checkDupeMix mix1 mix2 =
if mix1 == mix2
then mix1
else error $ ".mix files differ: " <> show (mix1, mix2)
report = generateLcovFromTix moduleToMix tixModules
writeReport cliOutput report
{- HPC file readers -}
readTixPath :: Path b File -> IO [TixModule]
readTixPath path = do
Tix tixModules <-
readTix (Path.toFilePath path)
>>= maybe (error $ "Could not find tix file: " <> Path.toFilePath path) pure
pure tixModules
readMixPath :: [Path b Dir] -> Either String TixModule -> IO Mix
readMixPath = readMix . fmap Path.toFilePath
Comes with no guarantee and no more details for now, but it was able to convert .tix/mix
files from arbitrary layout (from bazel, but could work with cabal too) to an lcov file then sent to codecov.
Currently,
hpc-lcov
is hardcoded to look at Stack paths (e.g.readStack
). Enable looking at Cabal paths as well