module Git.Object where

import Conduit
import Control.Monad
import Data.Function
import Data.Maybe
import Git.Types
import Prelude hiding (FilePath)

listObjects :: MonadGit r m
            => Maybe (CommitOid r) -- ^ A commit we may already have
            -> CommitOid r         -- ^ The commit we need
            -> Bool                -- ^ Include commit trees also?
            -> m [ObjectOid r]     -- ^ All the objects in between
listObjects :: Maybe (CommitOid r) -> CommitOid r -> Bool -> m [ObjectOid r]
listObjects Maybe (CommitOid r)
mhave CommitOid r
need Bool
alsoTrees =
    ConduitT () Void m [ObjectOid r] -> m [ObjectOid r]
forall (m :: * -> *) r. Monad m => ConduitT () Void m r -> m r
runConduit (ConduitT () Void m [ObjectOid r] -> m [ObjectOid r])
-> ConduitT () Void m [ObjectOid r] -> m [ObjectOid r]
forall a b. (a -> b) -> a -> b
$ Maybe (CommitOid r)
-> CommitOid r -> Bool -> ConduitT () (ObjectOid r) m ()
forall r (m :: * -> *) i.
MonadGit r m =>
Maybe (CommitOid r)
-> CommitOid r -> Bool -> ConduitT i (ObjectOid r) m ()
sourceObjects Maybe (CommitOid r)
mhave CommitOid r
need Bool
alsoTrees ConduitT () (ObjectOid r) m ()
-> ConduitM (ObjectOid r) Void m [ObjectOid r]
-> ConduitT () Void m [ObjectOid r]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM (ObjectOid r) Void m [ObjectOid r]
forall (m :: * -> *) a o. Monad m => ConduitT a o m [a]
sinkList

traverseObjects :: MonadGit r m => (ObjectOid r -> m a) -> CommitOid r -> m [a]
traverseObjects :: (ObjectOid r -> m a) -> CommitOid r -> m [a]
traverseObjects ObjectOid r -> m a
f CommitOid r
need = (ObjectOid r -> m a) -> [ObjectOid r] -> m [a]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ObjectOid r -> m a
f ([ObjectOid r] -> m [a]) -> m [ObjectOid r] -> m [a]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe (CommitOid r) -> CommitOid r -> Bool -> m [ObjectOid r]
forall r (m :: * -> *).
MonadGit r m =>
Maybe (CommitOid r) -> CommitOid r -> Bool -> m [ObjectOid r]
listObjects Maybe (CommitOid r)
forall a. Maybe a
Nothing CommitOid r
need Bool
False

traverseObjects_ :: MonadGit r m => (ObjectOid r -> m ()) -> CommitOid r -> m ()
traverseObjects_ :: (ObjectOid r -> m ()) -> CommitOid r -> m ()
traverseObjects_ = (m [()] -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m [()] -> m ()) -> (CommitOid r -> m [()]) -> CommitOid r -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((CommitOid r -> m [()]) -> CommitOid r -> m ())
-> ((ObjectOid r -> m ()) -> CommitOid r -> m [()])
-> (ObjectOid r -> m ())
-> CommitOid r
-> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ObjectOid r -> m ()) -> CommitOid r -> m [()]
forall r (m :: * -> *) a.
MonadGit r m =>
(ObjectOid r -> m a) -> CommitOid r -> m [a]
traverseObjects

-- | Given a list of objects (commit and top-level trees) return by
--   'listObjects', expand it to include all subtrees and blobs as well.
--   Ordering is preserved.
expandTreeObjects :: MonadGit r m => ConduitT (ObjectOid r) (ObjectOid r) m ()
expandTreeObjects :: ConduitT (ObjectOid r) (ObjectOid r) m ()
expandTreeObjects = (ObjectOid r -> ConduitT (ObjectOid r) (ObjectOid r) m ())
-> ConduitT (ObjectOid r) (ObjectOid r) m ()
forall (m :: * -> *) i o r.
Monad m =>
(i -> ConduitT i o m r) -> ConduitT i o m ()
awaitForever ((ObjectOid r -> ConduitT (ObjectOid r) (ObjectOid r) m ())
 -> ConduitT (ObjectOid r) (ObjectOid r) m ())
-> (ObjectOid r -> ConduitT (ObjectOid r) (ObjectOid r) m ())
-> ConduitT (ObjectOid r) (ObjectOid r) m ()
forall a b. (a -> b) -> a -> b
$ \ObjectOid r
obj -> case ObjectOid r
obj of
    TreeObjOid TreeOid r
toid -> do
        ObjectOid r -> ConduitT (ObjectOid r) (ObjectOid r) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (ObjectOid r -> ConduitT (ObjectOid r) (ObjectOid r) m ())
-> ObjectOid r -> ConduitT (ObjectOid r) (ObjectOid r) m ()
forall a b. (a -> b) -> a -> b
$ TreeOid r -> ObjectOid r
forall r. TreeOid r -> ObjectOid r
TreeObjOid TreeOid r
toid
        Tree r
tr <- m (Tree r) -> ConduitT (ObjectOid r) (ObjectOid r) m (Tree r)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m (Tree r) -> ConduitT (ObjectOid r) (ObjectOid r) m (Tree r))
-> m (Tree r) -> ConduitT (ObjectOid r) (ObjectOid r) m (Tree r)
forall a b. (a -> b) -> a -> b
$ TreeOid r -> m (Tree r)
forall r (m :: * -> *). MonadGit r m => TreeOid r -> m (Tree r)
lookupTree TreeOid r
toid
        Tree r -> ConduitT (ObjectOid r) (TreeFilePath, TreeEntry r) m ()
forall r (m :: * -> *) i.
MonadGit r m =>
Tree r -> ConduitT i (TreeFilePath, TreeEntry r) m ()
sourceTreeEntries Tree r
tr
            ConduitT (ObjectOid r) (TreeFilePath, TreeEntry r) m ()
-> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ()
-> ConduitT (ObjectOid r) (ObjectOid r) m ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ((TreeFilePath, TreeEntry r)
 -> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ())
-> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ()
forall (m :: * -> *) i o r.
Monad m =>
(i -> ConduitT i o m r) -> ConduitT i o m ()
awaitForever (\(TreeFilePath, TreeEntry r)
ent -> case (TreeFilePath, TreeEntry r)
ent of
                (TreeFilePath
_, BlobEntry BlobOid r
oid BlobKind
_) -> ObjectOid r
-> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (ObjectOid r
 -> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ())
-> ObjectOid r
-> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ()
forall a b. (a -> b) -> a -> b
$ BlobOid r -> ObjectOid r
forall r. BlobOid r -> ObjectOid r
BlobObjOid BlobOid r
oid
                (TreeFilePath
_, TreeEntry TreeOid r
oid)   -> ObjectOid r
-> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield (ObjectOid r
 -> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ())
-> ObjectOid r
-> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ()
forall a b. (a -> b) -> a -> b
$ TreeOid r -> ObjectOid r
forall r. TreeOid r -> ObjectOid r
TreeObjOid TreeOid r
oid
                (TreeFilePath, TreeEntry r)
_ -> () -> ConduitM (TreeFilePath, TreeEntry r) (ObjectOid r) m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())
    ObjectOid r
_ -> ObjectOid r -> ConduitT (ObjectOid r) (ObjectOid r) m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield ObjectOid r
obj

listAllObjects :: MonadGit r m
               => Maybe (CommitOid r) -> CommitOid r -> m [ObjectOid r]
listAllObjects :: Maybe (CommitOid r) -> CommitOid r -> m [ObjectOid r]
listAllObjects Maybe (CommitOid r)
mhave CommitOid r
need =
    ConduitT () Void m [ObjectOid r] -> m [ObjectOid r]
forall (m :: * -> *) r. Monad m => ConduitT () Void m r -> m r
runConduit (ConduitT () Void m [ObjectOid r] -> m [ObjectOid r])
-> ConduitT () Void m [ObjectOid r] -> m [ObjectOid r]
forall a b. (a -> b) -> a -> b
$ Maybe (CommitOid r)
-> CommitOid r -> Bool -> ConduitT () (ObjectOid r) m ()
forall r (m :: * -> *) i.
MonadGit r m =>
Maybe (CommitOid r)
-> CommitOid r -> Bool -> ConduitT i (ObjectOid r) m ()
sourceObjects Maybe (CommitOid r)
mhave CommitOid r
need Bool
True ConduitT () (ObjectOid r) m ()
-> ConduitM (ObjectOid r) Void m [ObjectOid r]
-> ConduitT () Void m [ObjectOid r]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitT (ObjectOid r) (ObjectOid r) m ()
forall r (m :: * -> *).
MonadGit r m =>
ConduitT (ObjectOid r) (ObjectOid r) m ()
expandTreeObjects ConduitT (ObjectOid r) (ObjectOid r) m ()
-> ConduitM (ObjectOid r) Void m [ObjectOid r]
-> ConduitM (ObjectOid r) Void m [ObjectOid r]
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| ConduitM (ObjectOid r) Void m [ObjectOid r]
forall (m :: * -> *) a o. Monad m => ConduitT a o m [a]
sinkList