module History.Scramble ( Scramble (..), getIssuesOfFile, fromComment, ) where import CMark qualified as D import Comment qualified as G import Control.Exception (Handler (..), catches) import Data.Binary (Binary) import Data.Digest.Pure.SHA qualified as S import Data.Map qualified as M import Data.Maybe (catMaybes) import Data.Text qualified as T import Data.Text.Lazy qualified as LT import Data.Text.Lazy.Encoding qualified as LT import Exception qualified as E import GHC.Generics (Generic) import Git qualified import Issue qualified as I import Issue.Parser qualified as I import Issue.Tag qualified as I import Issue.Text qualified as I import Parallel (parMapM) import Render qualified as P -- | `Scramble` records the complete issues ONLY in files that have -- been changed in the commit. data Scramble = Scramble { commitHash :: Git.CommitHash, filesChanged :: [FilePath], issues :: M.Map T.Text I.Issue } deriving (Show, Binary, Generic) -- | Get all issues in the given directory and file. getIssuesOfFile :: Git.CommitHash -> FilePath -> IO [I.Issue] getIssuesOfFile commitHash filename = ( fmap catMaybes . parMapM (fromComment commitHash) =<< G.getComments commitHash filename ) `catches` [ Handler \(_ :: E.UnknownFile) -> pure [], Handler \(_ :: E.UnsupportedLanguage) -> pure [] ] -- | Note that `provenance` is trivial and needs to be fixed up later. fromComment :: Git.CommitHash -> G.Comment -> IO (Maybe I.Issue) fromComment commitHash comment = do commit <- Git.getCommitOf commitHash let provenance = I.Provenance commit commit pure $ ( \parseResult -> let (markers, title) = I.stripIssueMarkers (T.pack (show (P.render parseResult.heading))) in I.Issue { commitHash = commitHash, language = comment.language, rawTextHash = S.sha1 (LT.encodeUtf8 (LT.fromStrict rawText)), title = title, file = comment.filePath, provenance = provenance, startByte = comment.startByte, endByte = comment.endByte, startPoint = comment.startPoint, endPoint = comment.endPoint, tags = I.extractTags parseResult.tags, markers = markers, commentStyle = commentStyle, closed = False } ) <$> I.parse I.issueMarkers (D.commonmarkToNode [] rawText) where (commentStyle, rawText) = G.uncomment comment.language comment.text