diff options
Diffstat (limited to 'app/History/Scramble.hs')
-rw-r--r-- | app/History/Scramble.hs | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/app/History/Scramble.hs b/app/History/Scramble.hs new file mode 100644 index 0000000..9004dbf --- /dev/null +++ b/app/History/Scramble.hs @@ -0,0 +1,76 @@ +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 |