diff --git a/src/Data/Git/Local.hs b/src/Data/Git/Local.hs new file mode 100644 index 0000000..67573b1 --- /dev/null +++ b/src/Data/Git/Local.hs @@ -0,0 +1,64 @@ +{- This file is part of Vervis. + - + - Written in 2016 by fr33domlover . + - + - ♡ Copying is an act of love. Please copy, reuse and share. + - + - The author(s) have dedicated all copyright and related and neighboring + - rights to this software to the public domain worldwide. This software is + - distributed without any warranty. + - + - You should have received a copy of the CC0 Public Domain Dedication along + - with this software. If not, see + - . + -} + +-- | Git repo tools using the @hit@ package. +module Data.Git.Local + ( + ) +where + +import Prelude + +import Control.Monad.IO.Class +import Data.Foldable (foldlM) +import Data.Git.Ref (Ref) +import Data.Git.Repository (getCommit) +import Data.Git.Storage (Git) +import Data.Git.Types (Commit (..)) + +-- | Load the entire graph of commits which are ancestors of the given ref +-- (and that ref itself). Fold the commit structure into a value of type @a@ +-- inside monad @m@. +-- +-- This is a low-level function which operates on a commit tree, i.e. the same +-- ref may be visited more than once (if it has more than one child commit). +-- You can use the provided flexibility to implement graph algorithms over the +-- commits, or build a graph using some graph library and use that library's +-- tools for further processing. +loadCommits + :: MonadIO m + => Git + -- ^ Open git repository context + -> ((Ref, Commit) -> (Ref, Commit) -> a -> m a) + -- ^ Given a child commit, one of its parent commits and an @a@ value, + -- generate an updated @a@ value + -> a + -- ^ Initial value + -> Ref + -- ^ Hash of the commit whose ancestor graph should be loaded + -> m a +loadCommits git func val ref = readCommit ref >>= go val ref + where + readCommit = liftIO . getCommit git + readRefCommit r = do + c <- readCommit r + return (r, c) + step p1 v p2@(r, c) = do + v' <- func p1 p2 v + go v' r c + go v r c = do + let rs = commitParents c + ps <- mapM readRefCommit rs + foldlM (step (r, c)) v ps