{-# OPTIONS_HADDOCK hide #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} module Data.Git.Internal ( ObjPtr , Updatable(..) , Base(..), gitId, gitRepo, gitObj , newBase , Repository , HasRepository(..) , openRepository , createRepository , openOrCreateRepository , repositoryPtr , lookupObject' , module X ) where import Bindings.Libgit2 as X import Control.Applicative as X import Control.Category as X import Control.Exception as X import Control.Lens as X import Control.Monad as X hiding (mapM, mapM_, sequence, sequence_, forM, forM_, msum) import Data.Bool as X import Data.Either as X hiding (lefts, rights) import Data.Foldable as X import Data.Function as X hiding ((.), id) import Data.Git.Errors as X import Data.Git.Oid as X import Data.List as X hiding (foldl, foldl', foldl1, foldr1, foldl1', foldr, concat, maximum, minimum, product, sum, all, and, any, concatMap, elem, notElem, or, find, mapAccumL, mapAccumR, maximumBy, minimumBy) import Data.Maybe as X import Data.Monoid as X import Data.Stringable as X hiding (length) import Data.Text as X (Text) import Data.Tuple as X import Data.Traversable as X import Filesystem as X hiding (createTree) import qualified Filesystem.Path.CurrentOS as F import Filesystem.Path.CurrentOS as X (FilePath) import Foreign.C.String as X import Foreign.C.Types as X import Foreign.ForeignPtr as X import Foreign.Marshal.Alloc as X import Foreign.Marshal.Utils as X import Foreign.Ptr as X import Foreign.StablePtr as X import Foreign.Storable as X import Prelude as X (undefined, error, otherwise, IO, Show, show, Enum, Eq, Ord, (<), (==), (/=), round, Integer, fromIntegral, fromInteger, toInteger) import Unsafe.Coerce as X default (Text) type ObjPtr a = Maybe (ForeignPtr a) class Updatable a where getId :: a -> Ident a objectRepo :: a -> Repository objectPtr :: a -> ObjPtr C'git_object update :: a -> IO a update_ :: a -> IO () update_ = void . update objectId :: a -> IO Oid objectId x = case getId x of Pending f -> Oid <$> f x Stored y -> return $ Oid y maybeObjectId :: a -> Maybe Oid maybeObjectId x = case getId x of Pending _ -> Nothing Stored y -> Just (Oid y) lookupFunction :: Oid -> Repository -> IO (Maybe a) loadObject :: Updatable b => ObjRef a -> b -> IO (Maybe a) loadObject (IdRef coid) y = lookupFunction (Oid coid) (objectRepo y) loadObject (ObjRef x) _ = return (Just x) getObject :: ObjRef a -> Maybe a getObject (IdRef _) = Nothing getObject (ObjRef x) = Just x data Repository = Repository { _repoPath :: FilePath , _repoObj :: ObjPtr C'git_repository } makeClassy ''Repository instance Show Repository where show x = "Repository " <> toString (x^.repoPath) data Base a = Base { _gitId :: Ident a , _gitRepo :: Repository , _gitObj :: ObjPtr C'git_object } makeLenses ''Base instance Show (Base a) where show x = case x^.gitId of Pending _ -> "Base" Stored y -> "Base#" ++ show y newBase :: Repository -> Ident a -> ObjPtr C'git_object -> Base a newBase repo oid obj = Base { _gitId = oid , _gitRepo = repo , _gitObj = obj } repositoryPtr :: Repository -> ForeignPtr C'git_repository repositoryPtr repo = fromMaybe (error "Repository invalid") (repo^.repoObj) openRepository :: FilePath -> IO Repository openRepository path = openRepositoryWith path c'git_repository_open createRepository :: FilePath -> Bool -> IO Repository createRepository path bare = openRepositoryWith path (\x y -> c'git_repository_init x y (fromBool bare)) openOrCreateRepository :: FilePath -> Bool -> IO Repository openOrCreateRepository path bare = do b <- isDirectory path if b then openRepository path else createRepository path bare openRepositoryWith :: FilePath -> (Ptr (Ptr C'git_repository) -> CString -> IO CInt) -> IO Repository openRepositoryWith path fn = alloca $ \ptr -> case F.toText path of Left p -> doesNotExist p Right p -> withCStringable p $ \str -> do r <- fn ptr str when (r < 0) $ doesNotExist p ptr' <- peek ptr fptr <- newForeignPtr p'git_repository_free ptr' return Repository { _repoPath = path , _repoObj = Just fptr } where doesNotExist = throwIO . RepositoryNotExist . toString lookupObject' :: Oid -> Repository -> (Ptr (Ptr a) -> Ptr C'git_repository -> Ptr C'git_oid -> IO CInt) -> (Ptr (Ptr a) -> Ptr C'git_repository -> Ptr C'git_oid -> CUInt -> IO CInt) -> (COid -> ForeignPtr C'git_object -> Ptr C'git_object -> IO b) -> IO (Maybe b) lookupObject' oid repo lookupFn lookupPrefixFn createFn = alloca $ \ptr -> do r <- withForeignPtr (repositoryPtr repo) $ \repoPtr -> case oid of Oid (COid oid') -> withForeignPtr oid' $ \oidPtr -> lookupFn (castPtr ptr) repoPtr oidPtr PartialOid (COid oid') len -> withForeignPtr oid' $ \oidPtr -> lookupPrefixFn (castPtr ptr) repoPtr oidPtr (fromIntegral len) if r < 0 then return Nothing else do ptr' <- peek ptr coid <- c'git_object_id ptr' coidCopy <- mallocForeignPtr withForeignPtr coidCopy $ flip c'git_oid_cpy coid fptr <- newForeignPtr p'git_object_free ptr' Just <$> createFn (COid coidCopy) fptr ptr' -- Internal.hs