module Data.Git.Oid
( Oid(..)
, COid(..)
, oidToStr
, ObjRef(..)
, Ident(..)
, wrapOidPtr
, compareCOid
, compareCOidLen
, equalCOid
, stringToOid )
where
import Bindings.Libgit2.Oid
import Control.Applicative
import Control.Exception
import Control.Monad
import qualified Data.ByteString.Char8 as BC
import Data.ByteString.Unsafe
import Data.Git.Error
import Data.Stringable as S
import Foreign.C.String
import Foreign.ForeignPtr
import Foreign.Ptr
import System.IO.Unsafe
newtype COid = COid (ForeignPtr C'git_oid)
oidToStr :: Ptr C'git_oid -> IO String
oidToStr = c'git_oid_allocfmt >=> peekCString
instance Show COid where
show (COid coid) = unsafePerformIO $ withForeignPtr coid oidToStr
data ObjRef a = IdRef COid
| ObjRef a
deriving Show
wrapOidPtr :: Ptr C'git_oid -> IO (ObjRef a)
wrapOidPtr = newForeignPtr_ >=> return . IdRef . COid
data Ident a = Pending (a -> IO COid)
| Stored COid
instance Show (Ident a) where
show (Pending _) = "Pending"
show (Stored coid) = show coid
data Oid = Oid COid
| PartialOid COid Int
instance Show Oid where
show (Oid x) = show x
show (PartialOid x l) = take l $ show x
compareCOid :: COid -> COid -> Ordering
(COid x) `compareCOid` (COid y) =
let c = unsafePerformIO $
withForeignPtr x $ \x' ->
withForeignPtr y $ \y' ->
c'git_oid_cmp x' y'
in c `compare` 0
compareCOidLen :: COid -> COid -> Int -> Ordering
compareCOidLen (COid x) (COid y) l =
let c = unsafePerformIO $
withForeignPtr x $ \x' ->
withForeignPtr y $ \y' ->
c'git_oid_ncmp x' y' (fromIntegral l)
in c `compare` 0
instance Ord COid where
compare = compareCOid
equalCOid :: Ord a => a -> a -> Bool
x `equalCOid` y = (x `compare` y) == EQ
instance Eq COid where
(==) = equalCOid
instance Eq Oid where
(Oid x) == (Oid y) = x `equalCOid` y
(PartialOid x xl) == (PartialOid y yl) =
xl == yl && compareCOidLen x y xl == EQ
_ == _ = False
stringToOid :: CStringable a => a -> IO (Maybe Oid)
stringToOid str
| len > 40 = throwIO ObjectIdTooLong
| otherwise = do
oid <- mallocForeignPtr
withCStringable str $ \cstr ->
withForeignPtr oid $ \ptr -> do
r <- if len == 40
then c'git_oid_fromstr ptr cstr
else c'git_oid_fromstrn ptr cstr (fromIntegral len)
if r < 0
then return Nothing
else return . Just $ if len == 40
then Oid (COid oid)
else PartialOid (COid oid) len
where len = S.length str