packages feed

gitlib 0.5.5 → 0.6.4

raw patch · 11 files changed

+315/−235 lines, 11 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Git.Oid: stringToOid :: CStringable a => a -> IO (Maybe Oid)
- Data.Git.Reference: lookupId :: Text -> Repository -> IO Oid
+ Data.Git.Blob: instance Eq Blob
+ Data.Git.Blob: instance Eq BlobContents
+ Data.Git.Commit: PinnedEntry :: Oid -> Commit -> TreeEntry -> PinnedEntry
+ Data.Git.Commit: addCommitParent :: Commit -> Commit -> Commit
+ Data.Git.Commit: data PinnedEntry
+ Data.Git.Commit: instance Show PinnedEntry
+ Data.Git.Commit: lookupRefCommit :: Repository -> Text -> IO (Maybe Commit)
+ Data.Git.Commit: pinnedCommit :: PinnedEntry -> Commit
+ Data.Git.Commit: pinnedEntry :: PinnedEntry -> TreeEntry
+ Data.Git.Commit: pinnedOid :: PinnedEntry -> Oid
+ Data.Git.Error: TreeUpdateFailed :: GitException
+ Data.Git.Oid: instance Eq (Ident a)
+ Data.Git.Oid: parseOid :: CStringable a => a -> IO (Maybe Oid)
- Data.Git.Blob: createBlob :: ByteString -> Repository -> Blob
+ Data.Git.Blob: createBlob :: Repository -> ByteString -> Blob
- Data.Git.Blob: lookupBlob :: Oid -> Repository -> IO (Maybe Blob)
+ Data.Git.Blob: lookupBlob :: Repository -> Oid -> IO (Maybe Blob)
- Data.Git.Commit: commitEntry :: FilePath -> Commit -> IO (Maybe TreeEntry)
+ Data.Git.Commit: commitEntry :: Commit -> FilePath -> IO (Maybe TreeEntry)
- Data.Git.Commit: commitEntryHistory :: FilePath -> Commit -> IO [(Oid, TreeEntry)]
+ Data.Git.Commit: commitEntryHistory :: Commit -> FilePath -> IO [PinnedEntry]
- Data.Git.Commit: createCommit :: Repository -> Commit
+ Data.Git.Commit: createCommit :: Repository -> Signature -> Commit
- Data.Git.Commit: lookupCommit :: Oid -> Repository -> IO (Maybe Commit)
+ Data.Git.Commit: lookupCommit :: Repository -> Oid -> IO (Maybe Commit)
- Data.Git.Commit: modifyCommitTree :: FilePath -> (Maybe TreeEntry -> Either a (Maybe TreeEntry)) -> Bool -> Commit -> IO (Either a Commit)
+ Data.Git.Commit: modifyCommitTree :: Commit -> FilePath -> (Maybe TreeEntry -> Either a (Maybe TreeEntry)) -> Bool -> IO (Either a Commit)
- Data.Git.Commit: removeFromCommitTree :: FilePath -> Commit -> IO Commit
+ Data.Git.Commit: removeFromCommitTree :: Commit -> FilePath -> IO Commit
- Data.Git.Commit: updateCommit :: FilePath -> TreeEntry -> Commit -> IO Commit
+ Data.Git.Commit: updateCommit :: Commit -> FilePath -> TreeEntry -> IO Commit
- Data.Git.Commit: writeCommit :: Maybe Text -> Commit -> IO Commit
+ Data.Git.Commit: writeCommit :: Commit -> Maybe Text -> IO Commit
- Data.Git.Object: lookupObject :: Oid -> Repository -> IO (Maybe Object)
+ Data.Git.Object: lookupObject :: Repository -> Oid -> IO (Maybe Object)
- Data.Git.Reference: createRef :: Text -> RefTarget -> Repository -> Reference
+ Data.Git.Reference: createRef :: Repository -> Text -> RefTarget -> Reference
- Data.Git.Reference: lookupRef :: Text -> Repository -> IO (Maybe Reference)
+ Data.Git.Reference: lookupRef :: Repository -> Text -> IO (Maybe Reference)
- Data.Git.Reference: resolveRef :: Text -> Repository -> IO (Maybe Oid)
+ Data.Git.Reference: resolveRef :: Repository -> Text -> IO (Maybe Oid)
- Data.Git.Repository: class Updatable a where update_ = void . update objectId x = case getId x of { Pending f -> Oid <$> f x Stored y -> return $ Oid y } objectRef x = do { oid <- objectId x; case oid of { Oid coid -> return (IdRef coid) PartialOid _ _ -> error "Did not expect to see a PartialOid" } } objectRefId (IdRef coid) = return (Oid coid) objectRefId (ObjRef x) = objectId x maybeObjectId x = case getId x of { Pending _ -> Nothing Stored y -> Just (Oid y) } loadObject (IdRef coid) y = lookupFunction (Oid coid) (objectRepo y) loadObject (ObjRef x) _ = return (Just x) loadObject' x y = maybe (throwIO ObjectLookupFailed) return =<< loadObject x y getObject (IdRef _) = Nothing getObject (ObjRef x) = Just x
+ Data.Git.Repository: class Updatable a where update_ = void . update objectId x = case getId x of { Pending f -> Oid <$> f x Stored y -> return $ Oid y } objectRef x = do { oid <- objectId x; case oid of { Oid coid -> return (IdRef coid) PartialOid _ _ -> error "Did not expect to see a PartialOid" } } objectRefId (IdRef coid) = return (Oid coid) objectRefId (ObjRef x) = objectId x maybeObjectId x = case getId x of { Pending _ -> Nothing Stored y -> Just (Oid y) } loadObject (IdRef coid) y = lookupFunction (objectRepo y) (Oid coid) loadObject (ObjRef x) _ = return (Just x) loadObject' x y = maybe (throwIO ObjectLookupFailed) return =<< loadObject x y getObject (IdRef _) = Nothing getObject (ObjRef x) = Just x
- Data.Git.Repository: lookupFunction :: Updatable a => Oid -> Repository -> IO (Maybe a)
+ Data.Git.Repository: lookupFunction :: Updatable a => Repository -> Oid -> IO (Maybe a)
- Data.Git.Repository: 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)
+ Data.Git.Repository: lookupObject' :: Repository -> Oid -> (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)
- Data.Git.Tree: doLookupTreeEntry :: [Text] -> Tree -> IO (Maybe TreeEntry)
+ Data.Git.Tree: doLookupTreeEntry :: Tree -> [Text] -> IO (Maybe TreeEntry)
- Data.Git.Tree: doUpdateTree :: [Text] -> TreeEntry -> Tree -> IO Tree
+ Data.Git.Tree: doUpdateTree :: Tree -> [Text] -> TreeEntry -> IO Tree
- Data.Git.Tree: lookupTree :: Oid -> Repository -> IO (Maybe Tree)
+ Data.Git.Tree: lookupTree :: Repository -> Oid -> IO (Maybe Tree)
- Data.Git.Tree: lookupTreeEntry :: FilePath -> Tree -> IO (Maybe TreeEntry)
+ Data.Git.Tree: lookupTreeEntry :: Tree -> FilePath -> IO (Maybe TreeEntry)
- Data.Git.Tree: updateTree :: FilePath -> TreeEntry -> Tree -> IO Tree
+ Data.Git.Tree: updateTree :: Tree -> FilePath -> TreeEntry -> IO Tree

Files

Data/Git/Blob.hs view
@@ -28,6 +28,12 @@                   | BlobString B.ByteString                   | BlobStream ByteSource +instance Eq BlobContents where+  BlobEmpty == BlobEmpty = True+  BlobString str1 == BlobString str2 = str1 == str2+  BlobStream src1 == BlobStream src2 = False+  _ == _ = False+ blobSourceToString :: BlobContents -> IO (Maybe B.ByteString) blobSourceToString BlobEmpty = return Nothing blobSourceToString (BlobString bs) = return (Just bs)@@ -38,6 +44,7 @@  data Blob = Blob { blobInfo     :: Base Blob                  , blobContents :: BlobContents }+          deriving Eq  instance Show Blob where   show x = case gitId (blobInfo x) of@@ -62,16 +69,16 @@ -- --   Note that since empty blobs cannot exist in Git, no means is provided for --   creating one; if the give string is 'empty', it is an error.-createBlob :: B.ByteString -> Repository -> Blob-createBlob text repo+createBlob :: Repository -> B.ByteString -> Blob+createBlob repo text   | text == B.empty = error "Cannot create an empty blob"   | otherwise =     Blob { blobInfo     = newBase repo (Pending doWriteBlob) Nothing          , blobContents = BlobString text } -lookupBlob :: Oid -> Repository -> IO (Maybe Blob)-lookupBlob oid repo =-  lookupObject' oid repo c'git_blob_lookup c'git_blob_lookup_prefix $+lookupBlob :: Repository -> Oid -> IO (Maybe Blob)+lookupBlob repo oid =+  lookupObject' repo oid c'git_blob_lookup c'git_blob_lookup_prefix $     \coid obj _ ->       return Blob { blobInfo     = newBase repo (Stored coid) (Just obj)                   , blobContents = BlobEmpty }@@ -85,13 +92,16 @@         withForeignPtr blobPtr $ \ptr -> do           size <- c'git_blob_rawsize (castPtr ptr)           buf  <- c'git_blob_rawcontent (castPtr ptr)+          -- The lifetime of buf is tied to the lifetime of the blob object in+          -- libgit2, which this Blob object controls, so we can use+          -- unsafePackCStringLen to refer to its bytes.           bstr <- curry unsafePackCStringLen (castPtr buf)                         (fromIntegral size)           let contents' = BlobString bstr           return (b { blobContents = contents' }, contents' )        Nothing -> do-        b' <- lookupBlob (Oid hash) repo+        b' <- lookupBlob repo (Oid hash)         case b' of           Just blobPtr' -> getBlobContents blobPtr'           Nothing       -> return (b, BlobEmpty)
Data/Git/Commit.hs view
@@ -4,9 +4,12 @@  module Data.Git.Commit        ( Commit(..)+       , PinnedEntry(..)        , newCommitBase        , createCommit        , lookupCommit+       , lookupRefCommit+       , addCommitParent        , writeCommit        , getCommitParents        , modifyCommitTree@@ -22,6 +25,7 @@ import           Data.ByteString.Unsafe import           Data.Git.Common import           Data.Git.Internal+import           Data.Git.Reference import           Data.Git.Tree import qualified Data.Text as T import qualified Data.Text.Encoding as E@@ -49,7 +53,7 @@   getId x        = gitId (commitInfo x)   objectRepo x   = gitRepo (commitInfo x)   objectPtr x    = gitObj (commitInfo x)-  update         = writeCommit Nothing+  update         = flip writeCommit Nothing   lookupFunction = lookupCommit #if defined(PROFILING)   loadObject' x y =@@ -59,28 +63,28 @@ newCommitBase :: Commit -> Base Commit newCommitBase t =   newBase (gitRepo (commitInfo t))-          (Pending (doWriteCommit Nothing >=> return . snd)) Nothing+          (Pending (flip doWriteCommit Nothing >=> return . snd)) Nothing  -- | Create a new, empty commit. -- --   Since empty commits cannot exist in Git, attempting to write out an empty --   commit is a no-op.-createCommit :: Repository -> Commit-createCommit repo =+createCommit :: Repository -> Signature -> Commit+createCommit repo sig =   Commit { commitInfo     =-           newBase repo (Pending (doWriteCommit Nothing >=> return . snd))+           newBase repo (Pending (flip doWriteCommit Nothing >=> return . snd))                    Nothing-         , commitAuthor    = createSignature-         , commitCommitter = createSignature+         , commitAuthor    = sig+         , commitCommitter = sig          , commitTree      = ObjRef (createTree repo)          , commitParents   = []          , commitLog       = T.empty          , commitEncoding  = ""          , commitObj       = Nothing } -lookupCommit :: Oid -> Repository -> IO (Maybe Commit)-lookupCommit oid repo =-  lookupObject' oid repo c'git_commit_lookup c'git_commit_lookup_prefix $+lookupCommit :: Repository -> Oid -> IO (Maybe Commit)+lookupCommit repo oid =+  lookupObject' repo oid c'git_commit_lookup c'git_commit_lookup_prefix $     \coid obj _ ->       withForeignPtr obj $ \cobj -> do         let c = castPtr cobj@@ -112,35 +116,49 @@                       , commitEncoding  = encs                       , commitObj       = Just $ unsafeCoerce obj } +lookupRefCommit :: Repository -> Text -> IO (Maybe Commit)+lookupRefCommit repo ref = do+  oid <- resolveRef repo ref+  maybe (return Nothing) (lookupCommit repo) oid++addCommitParent :: Commit -> Commit -> Commit+addCommitParent co p = co { commitParents = commitParents co ++ [ObjRef p] }+ -- | Write out a commit to its repository.  If it has already been written, --   nothing will happen.-writeCommit :: Maybe Text -> Commit -> IO Commit-writeCommit _ c@(Commit { commitInfo = Base { gitId = Stored _ } }) =+writeCommit :: Commit -> Maybe Text -> IO Commit+writeCommit c@(Commit { commitInfo = Base { gitId = Stored _ } }) _ =   return c-writeCommit ref c = fst <$> doWriteCommit ref c+writeCommit c ref = fst <$> doWriteCommit c ref -doWriteCommit :: Maybe Text -> Commit -> IO (Commit, COid)-doWriteCommit ref c = do+withForeignPtrs :: [ForeignPtr a] -> ([Ptr a] -> IO b) -> IO b+withForeignPtrs fos io+  = do r <- io (map FU.unsafeForeignPtrToPtr fos)+       mapM touchForeignPtr fos+       return r++doWriteCommit :: Commit -> Maybe Text -> IO (Commit, COid)+doWriteCommit c ref = do   coid <- withForeignPtr repo $ \repoPtr -> do     coid <- mallocForeignPtr     withForeignPtr coid $ \coid' -> do       conv <- U.open (commitEncoding c) (Just True)       BS.useAsCString (U.fromUnicode conv (commitLog c)) $ \message ->         withRef ref $ \update_ref ->-          withSignature conv (commitAuthor c) $ \author ->-            withSignature conv (commitCommitter c) $ \committer ->-              withEncStr (commitEncoding c) $ \message_encoding ->-                withGitTree (commitTree c) c $ \commit_tree -> do-                  parentPtrs <- getCommitParentPtrs c-                  parents    <- newArray $-                               map FU.unsafeForeignPtrToPtr parentPtrs-                  r <- c'git_commit_create coid' repoPtr-                        update_ref author committer-                        message_encoding message commit_tree-                        (fromIntegral (length (commitParents c)))-                        parents-                  when (r < 0) $ throwIO CommitCreateFailed-                  return coid+        withSignature conv (commitAuthor c) $ \author ->+        withSignature conv (commitCommitter c) $ \committer ->+        withEncStr (commitEncoding c) $ \message_encoding ->+        withGitTree (commitTree c) c $ \commit_tree -> do+          parentPtrs <- getCommitParentPtrs c+          withForeignPtrs parentPtrs $ \pptrs -> do+            parents <- newArray pptrs+            r <- c'git_commit_create coid' repoPtr+                  update_ref author committer+                  message_encoding message commit_tree+                  (fromIntegral (length (commitParents c)))+                  parents+            when (r < 0) $ throwIO CommitCreateFailed+            return coid    return (c { commitInfo = (commitInfo c) { gitId = Stored (COid coid) } }          , COid coid)@@ -157,11 +175,11 @@  getCommitParents :: Commit -> IO [Commit] getCommitParents c =-  traverse (\p -> do parent <- loadObject p c-                     case parent of-                       Nothing -> error "Cannot find Git commit"-                       Just p' -> return p')-           (commitParents c)+    traverse (\p -> do parent <- loadObject p c+                       case parent of+                           Nothing -> error "Cannot find Git commit"+                           Just p' -> return p')+             (commitParents c)  getCommitParentPtrs :: Commit -> IO [ForeignPtr C'git_commit] getCommitParentPtrs c =@@ -183,34 +201,37 @@               FC.newForeignPtr ptr' (c'git_commit_free ptr')  modifyCommitTree-  :: FilePath -> (Maybe TreeEntry -> Either a (Maybe TreeEntry)) -> Bool-  -> Commit -> IO (Either a Commit)-modifyCommitTree path f createIfNotExist c =+  :: Commit -> FilePath -> (Maybe TreeEntry -> Either a (Maybe TreeEntry)) -> Bool+  -> IO (Either a Commit)+modifyCommitTree c path f createIfNotExist =   withObject (commitTree c) c $ \tr -> do     result <- modifyTree path f createIfNotExist tr     case result of       Left x    -> return (Left x)       Right tr' -> return $ Right $ c { commitTree = ObjRef tr' } -removeFromCommitTree :: FilePath -> Commit -> IO Commit-removeFromCommitTree path c =+removeFromCommitTree :: Commit -> FilePath -> IO Commit+removeFromCommitTree c path =   withObject (commitTree c) c $ \tr -> do     tr' <- removeFromTree path tr     return c { commitTree = ObjRef tr' } -doUpdateCommit :: [Text] -> TreeEntry -> Commit -> IO Commit-doUpdateCommit xs item c = do-  t <- loadObject (commitTree c) c-  case t of-    Nothing -> error "Failed to load tree for commit"-    Just t' -> do-      tr <- doModifyTree xs (const (Right (Just item))) True t'-      case tr of-        Right tr' -> return c { commitTree = ObjRef tr' }-        _ -> undefined+doUpdateCommit :: Commit -> [Text] -> TreeEntry -> IO Commit+doUpdateCommit c xs item = do+    t <- loadObject (commitTree c) c+    case t of+        Nothing -> throwIO CommitLookupFailed+        Just t' -> do+            newt <- doUpdateTree t' xs item+            return c { commitTree = ObjRef newt+                     , commitInfo =+                            newBase (objectRepo c)+                                    (Pending (flip doWriteCommit Nothing+                                              >=> return . snd)) Nothing+                     , commitObj  = Nothing } -updateCommit :: FilePath -> TreeEntry -> Commit -> IO Commit-updateCommit = doUpdateCommit . splitPath+updateCommit :: Commit -> FilePath -> TreeEntry -> IO Commit+updateCommit c = doUpdateCommit c . splitPath  commitHistoryFirstParent :: Commit -> IO [Commit] commitHistoryFirstParent c =@@ -220,20 +241,26 @@                 ps <- commitHistoryFirstParent p'                 return (c:ps) -commitEntry :: FilePath -> Commit -> IO (Maybe TreeEntry)-commitEntry path c = lookupTreeEntry path =<< loadObject' (commitTree c) c+commitEntry :: Commit -> FilePath -> IO (Maybe TreeEntry)+commitEntry c path =+  flip lookupTreeEntry path =<< loadObject' (commitTree c) c -identifyEntry :: TreeEntry -> IO (Oid,TreeEntry)-identifyEntry x = do+data PinnedEntry = PinnedEntry { pinnedOid    :: Oid+                               , pinnedCommit :: Commit+                               , pinnedEntry  :: TreeEntry }+                 deriving Show++identifyEntry :: Commit -> TreeEntry -> IO PinnedEntry+identifyEntry co x = do   oid <- case x of           BlobEntry blob _ -> objectRefId blob           TreeEntry tree   -> objectRefId tree-  return (oid,x)+  return (PinnedEntry oid co x) -commitEntryHistory :: FilePath -> Commit -> IO [(Oid,TreeEntry)]-commitEntryHistory path c = map head+commitEntryHistory :: Commit -> FilePath -> IO [PinnedEntry]+commitEntryHistory c path = map head                             . filter (not . null)-                            . groupBy ((==) `on` fst) <$> go c+                            . groupBy ((==) `on` pinnedOid) <$> go c   where go co = do           entry <- getEntry co           rest  <- case commitParents co of@@ -242,9 +269,9 @@           return $ maybe rest (:rest) entry          getEntry co = do-          ce <- commitEntry path co+          ce <- commitEntry co path           case ce of             Nothing  -> return Nothing-            Just ce' -> Just <$> identifyEntry ce'+            Just ce' -> Just <$> identifyEntry co ce'  -- Commit.hs
Data/Git/Error.hs view
@@ -24,6 +24,7 @@                   | TreeLookupFailed                   | TreeCannotTraverseBlob                   | TreeEntryLookupFailed+                  | TreeUpdateFailed                   | CommitCreateFailed                   | CommitLookupFailed                   | ReferenceCreateFailed
Data/Git/Internal.hs view
@@ -32,6 +32,7 @@ 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, unless, guard) import           Data.Bool as X@@ -104,10 +105,10 @@     Pending _ -> Nothing     Stored y  -> Just (Oid y) -  lookupFunction :: Oid -> Repository -> IO (Maybe a)+  lookupFunction :: Repository -> Oid -> IO (Maybe a)    loadObject :: Updatable b => ObjRef a -> b -> IO (Maybe a)-  loadObject (IdRef coid) y = lookupFunction (Oid coid) (objectRepo y)+  loadObject (IdRef coid) y = lookupFunction (objectRepo y) (Oid coid)   loadObject (ObjRef x) _   = return (Just x)    loadObject' :: Updatable b => ObjRef a -> b -> IO a@@ -122,6 +123,9 @@                              , repoOnWriteRef :: [Reference -> IO ()]                              , repoObj        :: ObjPtr C'git_repository } +instance Eq Repository where+  x == y = repoPath x == repoPath y && repoObj x == repoObj y+ instance Show Repository where   show x = "Repository " <> toString (repoPath x) @@ -133,11 +137,12 @@                            , refName   :: Text                            , refTarget :: RefTarget                            , refObj    :: ObjPtr C'git_reference }-               deriving Show+               deriving (Show, Eq)  data Base a = Base { gitId   :: Ident a                    , gitRepo :: Repository                    , gitObj  :: ObjPtr C'git_object }+            deriving Eq  instance Show (Base a) where   show x = case gitId x of@@ -201,12 +206,12 @@       Just objPtr -> withForeignPtr objPtr (f . castPtr)  lookupObject'-  :: Oid -> Repository+  :: Repository -> Oid   -> (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 =+lookupObject' repo oid lookupFn lookupPrefixFn createFn =   alloca $ \ptr -> do     r <- withForeignPtr (repositoryPtr repo) $ \repoPtr ->            case oid of
Data/Git/Object.hs view
@@ -12,6 +12,7 @@ import           Data.Git.Blob import           Data.Git.Commit import           Data.Git.Internal+import           Data.Git.Reference import           Data.Git.Tag import           Data.Git.Tree import qualified Data.Map as M@@ -32,24 +33,29 @@                 | Specifier a  revParse :: CStringable a => NamedRef a -> IO (Maybe Oid)-revParse (FullHash r)    = stringToOid r-revParse (PartialHash r) = stringToOid r+revParse (FullHash r)    = parseOid r+revParse (PartialHash r) = parseOid r revParse (BranchName r)  = undefined revParse (TagName r)     = undefined revParse (RefName r)     = undefined revParse (FullRefName r) = undefined revParse (Specifier r)   = undefined -lookupObject :: Oid -> Repository -> IO (Maybe Object)-lookupObject oid repo =-  lookupObject' oid repo+lookupObject :: Repository -> Oid -> IO (Maybe Object)+lookupObject repo oid =+  lookupObject' repo oid     (\x y z    -> c'git_object_lookup x y z c'GIT_OBJ_ANY)     (\x y z l  -> c'git_object_lookup_prefix x y z l c'GIT_OBJ_ANY)-    (\coid x y -> c'git_object_type y >>= createObject coid x repo)+    (\coid x y -> c'git_object_type y >>= createObject repo coid x) -createObject :: COid -> ForeignPtr C'git_object -> Repository -> C'git_otype+lookupRefObject :: Repository -> Text -> IO (Maybe Object)+lookupRefObject repo ref = do+  oid <- resolveRef repo ref+  maybe (return Nothing) (lookupObject repo) oid++createObject :: Repository -> COid -> ForeignPtr C'git_object -> C'git_otype              -> IO Object-createObject coid obj repo typ+createObject repo coid obj typ   | typ == c'GIT_OBJ_BLOB =     return $ BlobObj Blob { blobInfo =                               newBase repo (Stored coid) (Just obj)
Data/Git/Oid.hs view
@@ -13,7 +13,7 @@        , compareCOid        , compareCOidLen        , equalCOid-       , stringToOid )+       , parseOid )        where  import           Bindings.Libgit2.Oid@@ -61,6 +61,11 @@ data Ident a = Pending (a -> IO COid)              | Stored COid +instance Eq (Ident a) where+  Pending f1 == Pending f2 = False+  Stored oid1 == Stored oid2 = oid1 == oid2+  _ == _ = False+ instance Show (Ident a) where   show (Pending _) = "Ident..."   show (Stored coid) = show coid@@ -111,18 +116,18 @@ -- | Convert a hash string to a 'Maybe' 'Oid' value.  If the string is less --   than 40 hexadecimal digits, the result will be of type 'PartialOid'. ----- >>> stringToOid "a143ecf"+-- >>> parseOid "a143ecf" -- Just a143ecf--- >>> stringToOid "a143ecf" >>= (\(Just (PartialOid _ l)) -> return $ l == 7)+-- >>> parseOid "a143ecf" >>= (\(Just (PartialOid _ l)) -> return $ l == 7) -- True -- -- >>> let hash = "6cfc2ca31732fb6fa6b54bae6e586a57a0611aab"--- >>> stringToOid hash+-- >>> parseOid hash -- Just 6cfc2ca31732fb6fa6b54bae6e586a57a0611aab--- >>> stringToOid hash >>= (\(Just (Oid _)) -> return True)+-- >>> parseOid hash >>= (\(Just (Oid _)) -> return True) -- True-stringToOid :: CStringable a => a -> IO (Maybe Oid)-stringToOid str+parseOid :: CStringable a => a -> IO (Maybe Oid)+parseOid str   | len > 40 = throwIO ObjectIdTooLong   | otherwise = do     oid <- mallocForeignPtr
Data/Git/Reference.hs view
@@ -20,13 +20,12 @@        , mapOidRefs        , mapLooseOidRefs        , mapSymbolicRefs-       , lookupId        , writeRef        , writeRef_ )        where  import           Bindings.Libgit2-import           Data.ByteString.Unsafe+import           Data.ByteString import           Data.Git.Internal import           Data.IORef import qualified Data.Text as T@@ -35,26 +34,15 @@ import qualified Prelude import           Prelude ((+),(-)) --- int git_reference_lookup(git_reference **reference_out,---   git_repository *repo, const char *name)--createRef :: Text -> RefTarget -> Repository -> Reference-createRef name target repo =+createRef :: Repository -> Text -> RefTarget -> Reference+createRef repo name target =   Reference { refRepo   = repo             , refName   = name             , refTarget = target             , refObj    = Nothing } -resolveRef :: Text -> Repository -> IO (Maybe Oid)-resolveRef name repo = do-  ref <- lookupRef name repo-  case refTarget <$> ref of-    Nothing                           -> return Nothing-    Just (RefTargetSymbolic nextName) -> resolveRef nextName repo-    Just (RefTargetId oid)            -> return (Just oid)--lookupRef :: Text -> Repository -> IO (Maybe Reference)-lookupRef name repo = alloca $ \ptr -> do+lookupRef :: Repository -> Text -> IO (Maybe Reference)+lookupRef repo name = alloca $ \ptr -> do   r <- withForeignPtr (repositoryPtr repo) $ \repoPtr ->         withCStringable name $ \namePtr ->           c'git_reference_lookup ptr repoPtr namePtr@@ -69,7 +57,7 @@                     newForeignPtr_ oidPtr                       >>= return . RefTargetId . Oid . COid             else do targName <- c'git_reference_target ref-                    unsafePackCString targName+                    packCString targName                       >>= return . RefTargetSymbolic . E.decodeUtf8     return $ Just Reference { refRepo   = repo                             , refName   = name@@ -109,55 +97,17 @@ -- int git_reference_name_to_oid(git_oid *out, git_repository *repo, --   const char *name) -lookupId :: Text -> Repository -> IO Oid-lookupId name repos = alloca $ \ptr ->+resolveRef :: Repository -> Text -> IO (Maybe Oid)+resolveRef repos name = alloca $ \ptr ->   withCStringable name $ \namePtr ->     withForeignPtr repo $ \repoPtr -> do       r <- c'git_reference_name_to_oid ptr repoPtr namePtr-      when (r < 0) $ throwIO ReferenceLookupFailed-      Oid <$> COid <$> newForeignPtr_ ptr-+      if r < 0+        then return Nothing+        else Just . Oid <$> COid <$> newForeignPtr_ ptr   where     repo = fromMaybe (error "Repository invalid") (repoObj repos) --- int git_reference_create_symbolic(git_reference **ref_out,---   git_repository *repo, const char *name, const char *target, int force)----createSymbolicRef = c'git_reference_create_symbolic---- int git_reference_create_oid(git_reference **ref_out, git_repository *repo,---   const char *name, const git_oid *id, int force)----createNamedRef = c'git_reference_create_oid---- const git_oid * git_reference_oid(git_reference *ref)----refId = c'git_reference_oid---- const char * git_reference_target(git_reference *ref)----refTarget = c'git_reference_target---- git_ref_t git_reference_type(git_reference *ref)----refType = c'git_reference_type---- const char * git_reference_name(git_reference *ref)----refName = c'git_reference_name---- int git_reference_resolve(git_reference **resolved_ref, git_reference *ref)----resolveRef = c'git_reference_resolve---- int git_reference_set_target(git_reference *ref, const char *target)----setRefTarget = c'git_reference_set_target---- int git_reference_set_oid(git_reference *ref, const git_oid *id)----setRefId = c'git_reference_set_oid- -- int git_reference_rename(git_reference *ref, const char *new_name, --   int force) @@ -232,15 +182,10 @@       c'git_strarray_free c'refs       return refs ---listRefs = c'git_reference_list---- int git_reference_foreach(git_repository *repo, unsigned int list_flags,---   int (*callback)(const char *, void *), void *payload)- foreachRefCallback :: CString -> Ptr () -> IO CInt foreachRefCallback name payload = do   (callback,results) <- peek (castPtr payload) >>= deRefStablePtr-  result <- unsafePackCString name >>= callback . E.decodeUtf8+  result <- packCString name >>= callback . E.decodeUtf8   modifyIORef results (\xs -> result:xs)   return 0 @@ -270,27 +215,6 @@ mapSymbolicRefs :: Repository -> (Text -> IO a) -> IO [a] mapSymbolicRefs repo = mapRefs repo symbolicRefsFlag -{--foreachRefCallbackThunk :: Storable a =>-                           ForeachRefCallback a -> CString -> Ptr () -> IO CInt-foreachRefCallbackThunk callback name payload = do-  nameText <- E.decodeUtf8 <$> unsafePackCString name-  payloadValue <- peek (castPtr payload)-  maybe (-1) (const 0) <$> callback nameText payloadValue--mapRefsWith ::-  Storable a => Repository -> ListFlags -> a -> ForeachRefCallback a -> IO ()-mapRefsWith repo flags payload cb =-    withForeignPtr (repositoryPtr repo) $ \repoPtr -> do-      fun <- mk'git_reference_foreach_callback (foreachRefCallbackThunk cb)-      with payload $ \payloadPtr -> do-        r <- c'git_reference_foreach repoPtr (flagsToInt flags) fun-                                    (castPtr payloadPtr)-        -- jww (2012-12-14): Does the return type mean anything here?-        when (r < 0) $ return ()-        return ()--}- -- int git_reference_is_packed(git_reference *ref)  --refIsPacked = c'git_reference_is_packed@@ -298,10 +222,6 @@ -- int git_reference_reload(git_reference *ref)  --reloadRef = c'git_reference_reload---- void git_reference_free(git_reference *ref)----freeRef = c'git_reference_free  -- int git_reference_cmp(git_reference *ref1, git_reference *ref2) 
Data/Git/Tree.hs view
@@ -86,9 +86,9 @@             newBase repo (Pending (doWriteTree >=> return . snd)) Nothing        , treeContents = M.empty } -lookupTree :: Oid -> Repository -> IO (Maybe Tree)-lookupTree oid repo =-  lookupObject' oid repo c'git_tree_lookup c'git_tree_lookup_prefix $+lookupTree :: Repository -> Oid -> IO (Maybe Tree)+lookupTree repo oid =+  lookupObject' repo oid c'git_tree_lookup c'git_tree_lookup_prefix $     \coid obj _ -> do       entriesAList <- withForeignPtr obj $ \treePtr -> do         entryCount <- c'git_tree_entrycount (castPtr treePtr)@@ -116,9 +116,9 @@       return Tree { treeInfo     = newBase repo (Stored coid) (Just obj)                   , treeContents = M.fromList entriesAList } -doLookupTreeEntry :: [Text] -> Tree -> IO (Maybe TreeEntry)-doLookupTreeEntry [] t = return (Just (TreeEntry (ObjRef t)))-doLookupTreeEntry (name:names) t = do+doLookupTreeEntry :: Tree -> [Text] -> IO (Maybe TreeEntry)+doLookupTreeEntry t [] = return (Just (TreeEntry (ObjRef t)))+doLookupTreeEntry t (name:names) = do   -- Lookup the current name in this tree.  If it doesn't exist, and there are   -- more names in the path and 'createIfNotExist' is True, create a new Tree   -- and descend into it.  Otherwise, if it exists we'll have @Just (TreeEntry@@ -144,11 +144,11 @@     else       case y of         Just (BlobEntry {}) -> throw TreeCannotTraverseBlob-        Just (TreeEntry (ObjRef t')) -> doLookupTreeEntry names t'+        Just (TreeEntry (ObjRef t')) -> doLookupTreeEntry t' names         _ -> return Nothing -lookupTreeEntry :: FilePath -> Tree -> IO (Maybe TreeEntry)-lookupTreeEntry = doLookupTreeEntry . splitPath+lookupTreeEntry :: Tree -> FilePath -> IO (Maybe TreeEntry)+lookupTreeEntry tr = doLookupTreeEntry tr . splitPath  withGitTree :: Updatable b             => ObjRef Tree -> b -> (Ptr C'git_tree -> IO a) -> IO a@@ -304,22 +304,22 @@   -> Tree -> IO (Either a Tree) modifyTree = doModifyTree . splitPath -doUpdateTree :: [Text] -> TreeEntry -> Tree -> IO Tree-doUpdateTree xs item t = do+doUpdateTree :: Tree -> [Text] -> TreeEntry -> IO Tree+doUpdateTree t xs item = do   t' <- doModifyTree xs (const (Right (Just item))) True t   case t' of     Right tr -> return tr-    _ -> undefined+    _ -> throwIO TreeUpdateFailed -updateTree :: FilePath -> TreeEntry -> Tree -> IO Tree-updateTree = doUpdateTree . splitPath+updateTree :: Tree -> FilePath -> TreeEntry -> IO Tree+updateTree tr = doUpdateTree tr . splitPath  removeFromTree :: FilePath -> Tree -> IO Tree removeFromTree p tr = do   t' <- modifyTree p (const (Right Nothing)) False tr   case t' of     Right tr' -> return tr'-    _ -> undefined+    _ -> throwIO TreeUpdateFailed  splitPath :: FilePath -> [Text] splitPath path = T.splitOn "/" text
Data/Git/Tutorial.hs view
@@ -19,5 +19,69 @@  {- $intro -   The @gitlib@ library.+   The @gitlib@ library provides high-level types for working with the+   @libgit2@ C library (<http://libgit2.github.com>).  The intention is to+   make @libgit2@ easier and more type-safe, while using laziness to avoid+   unnecessary work.+-}++{- $repositories++   Every use of @gitlib@ must begin with a 'Data.Git.Repository' object.  At+   the moment each 'Repository' must be associated with a local directory,+   even if the Git objects are kept elsewhere via a custom backend (see+   <https://github.com/libgit2/libgit2/issues/1213>).++   If no 'Repository' exists yet, use 'Data.Git.Repository.createRepository';+   if one does exist, use 'Data.Git.Repository.openRepository'; or, you can+   use 'Data.Git.Repository.openOrCreateRepository'.  For example:++> repo <- openOrCreateRepository path False -- False here means "not bare"+> ... make use of the repository ...++   Note that the 'path' variable here is of type 'Filesystem.Path.FilePath',+   since @gitlib@ almost never uses the 'String' type.+-}++{- $references++   If you are working with an existing repository, probably the first thing+   you'll want to do is resolve a reference so that you can lookup a commit:++> repo   <- openOrCreateRepository path False+> ref    <- resolveRef repo "HEAD"+> commit <- maybe (return Nothing) (lookupCommit repo) ref++   'resolveRef' works for both symbolic and specific refs.  Further, this+   pattern is rather common, so there is a shortcut called+   'Data.Git.Commit.lookupRefCommit'.  Or, if you have a SHA string, you can+   use 'Data.Git.Commit.lookupCommit' with 'Data.Git.Oid.parseOid'.++> repo          <- openOrCreateRepository path False+> commitFromRef <- lookupRefCommit repo "HEAD"             :: Maybe Commit+> commitFromSHA <- lookupCommit repo (parseOid "f7acdbed") :: Maybe Commit++-}++{- $commits++   If you don't have a commit object, the recommend way to create one is by+   creating a 'Data.Git.Common.Signature' and using it to modify the return+   value from 'Data.Git.Commit.create'.  This requires a 'Repository' object:++> now <- getCurrentTime+> let sig = Signature {+>               signatureName  = "John Smith"+>             , signatureEmail = "johnsmith@nowhere.org"+>             , signatureWhen  = now }+>     c   = (createCommit repo) {+>             , commitAuthor    = sig+>             , commitCommitter = sig }+>             ++   Load a 'Data.Git.Commit.Commit', and thereafter its history through its+      parents, or load a 'Data.Git.Tree.Tree' or 'Data.Git.Blob.Blob' from+      its contents.++   3. Construct a new commit -}
gitlib.cabal view
@@ -1,7 +1,6 @@ Name:                gitlib-Version:             0.5.5+Version:             0.6.4 Synopsis:            Higher-level types for working with hlibgit2-Description:         Higher-level types for working with hlibgit2 License-file:        LICENSE License:             MIT Author:              John Wiegley@@ -9,6 +8,15 @@ Build-Type:          Simple Cabal-Version:       >=1.10 Category:            FFI+Description:+  @gitlib@ is a high-level, lazy and conduit-aware type wrapper around the+  libgit2 C library (<http://libgit2.github.com>).  The aim is both+  type-safety and convenience of use for Haskell users, combined with high+  performance and minimal memory footprint by taking advantage of Haskell's+  laziness and the conduit library's deterministic resource cleanup.+  .+  For further information, as well as typical use cases, see+  "Data.Git.Tutorial".  Source-repository head   type: git
test/Smoke.hs view
@@ -43,9 +43,9 @@  catBlob :: Repository -> Text -> IO (Maybe Text) catBlob repo sha = do-  hash <- stringToOid sha+  hash <- parseOid sha   for hash $ \hash' -> do-    obj <- lookupObject hash' repo+    obj <- lookupObject repo hash'     case obj of       Just (BlobObj b) -> do         (_, contents) <- getBlobContents b@@ -69,17 +69,15 @@   removeTree p  oid :: Updatable a => a -> IO Text-oid = objectId >=> return . oidToText+oid = objectId >=> return . oidToText . Just -oidToText :: Oid -> Text-oidToText = T.pack . show+oidToText :: Maybe Oid -> Text+oidToText = T.pack . show . fromJust  sampleCommit :: Repository -> Tree -> Signature -> Commit sampleCommit repo tr sig =-    (createCommit repo) { commitTree      = ObjRef tr-                        , commitAuthor    = sig-                        , commitCommitter = sig-                        , commitLog       = "Sample log message." }+    (createCommit repo sig) { commitTree = ObjRef tr+                            , commitLog  = "Sample log message." }  tests :: Test tests = test [@@ -87,7 +85,7 @@   "singleBlob" ~:    withRepository "singleBlob.git" $ \repo -> do-    update_ $ createBlob (E.encodeUtf8 "Hello, world!\n") repo+    update_ $ createBlob repo (E.encodeUtf8 "Hello, world!\n")      x <- catBlob repo "af5626b4a114abcb82d63db7c8082c3c4756e51b"     x @?= Just "Hello, world!\n"@@ -100,8 +98,8 @@   , "singleTree" ~:    withRepository "singleTree.git" $ \repo -> do-    let hello = createBlob (E.encodeUtf8 "Hello, world!\n") repo-    tr <- updateTree "hello/world.txt" (blobRef hello) (createTree repo)+    let hello = createBlob repo (E.encodeUtf8 "Hello, world!\n")+    tr <- updateTree (createTree repo) "hello/world.txt" (blobRef hello)     x  <- oid tr     x @?= "c0c848a2737a6a8533a18e6bd4d04266225e0271" @@ -110,13 +108,13 @@   , "twoTrees" ~:    withRepository "twoTrees.git" $ \repo -> do-    let hello = createBlob (E.encodeUtf8 "Hello, world!\n") repo-    tr <- updateTree "hello/world.txt" (blobRef hello) (createTree repo)+    let hello = createBlob repo (E.encodeUtf8 "Hello, world!\n")+    tr <- updateTree (createTree repo) "hello/world.txt" (blobRef hello)     x  <- oid tr     x @?= "c0c848a2737a6a8533a18e6bd4d04266225e0271" -    let goodbye = createBlob (E.encodeUtf8 "Goodbye, world!\n") repo-    tr <- updateTree "goodbye/files/world.txt" (blobRef goodbye) tr+    let goodbye = createBlob repo (E.encodeUtf8 "Goodbye, world!\n")+    tr <- updateTree tr "goodbye/files/world.txt" (blobRef goodbye)     x  <- oid tr     x @?= "98c3f387f63c08e1ea1019121d623366ff04de7a" @@ -125,13 +123,13 @@   , "deleteTree" ~:    withRepository "deleteTree.git" $ \repo -> do-    let hello = createBlob (E.encodeUtf8 "Hello, world!\n") repo-    tr <- updateTree "hello/world.txt" (blobRef hello) (createTree repo)+    let hello = createBlob repo (E.encodeUtf8 "Hello, world!\n")+    tr <- updateTree (createTree repo) "hello/world.txt" (blobRef hello)     x  <- oid tr     x @?= "c0c848a2737a6a8533a18e6bd4d04266225e0271" -    let goodbye = createBlob (E.encodeUtf8 "Goodbye, world!\n") repo-    tr <- updateTree "goodbye/files/world.txt" (blobRef goodbye) tr+    let goodbye = createBlob repo (E.encodeUtf8 "Goodbye, world!\n")+    tr <- updateTree tr "goodbye/files/world.txt" (blobRef goodbye)     x  <- oid tr     x @?= "98c3f387f63c08e1ea1019121d623366ff04de7a" @@ -147,11 +145,11 @@   , "createCommit" ~:    withRepository "createCommit.git" $ \repo -> do-    let hello = createBlob (E.encodeUtf8 "Hello, world!\n") repo-    tr <- updateTree "hello/world.txt" (blobRef hello) (createTree repo)+    let hello = createBlob repo (E.encodeUtf8 "Hello, world!\n")+    tr <- updateTree (createTree repo) "hello/world.txt" (blobRef hello) -    let goodbye = createBlob (E.encodeUtf8 "Goodbye, world!\n") repo-    tr <- updateTree "goodbye/files/world.txt" (blobRef goodbye) tr+    let goodbye = createBlob repo (E.encodeUtf8 "Goodbye, world!\n")+    tr <- updateTree tr "goodbye/files/world.txt" (blobRef goodbye)     x  <- oid tr     x @?= "98c3f387f63c08e1ea1019121d623366ff04de7a" @@ -177,11 +175,11 @@     backend   <- traceBackend loosePtr'     odbBackendAdd repo backend 3 -    let hello = createBlob (E.encodeUtf8 "Hello, world!\n") repo-    tr <- updateTree "hello/world.txt" (blobRef hello) (createTree repo)+    let hello = createBlob repo (E.encodeUtf8 "Hello, world!\n")+    tr <- updateTree (createTree repo) "hello/world.txt" (blobRef hello) -    let goodbye = createBlob (E.encodeUtf8 "Goodbye, world!\n") repo-    tr <- updateTree "goodbye/files/world.txt" (blobRef goodbye) tr+    let goodbye = createBlob repo (E.encodeUtf8 "Goodbye, world!\n")+    tr <- updateTree tr "goodbye/files/world.txt" (blobRef goodbye)     tr <- update tr     x  <- oid tr     x @?= "98c3f387f63c08e1ea1019121d623366ff04de7a"@@ -197,8 +195,8 @@     x <- oid c     x @?= "44381a5e564d19893d783a5d5c59f9c745155b56" -    let goodbye2 = createBlob (E.encodeUtf8 "Goodbye, world again!\n") repo-    tr <- updateTree "goodbye/files/world.txt" (blobRef goodbye2) tr+    let goodbye2 = createBlob repo (E.encodeUtf8 "Goodbye, world again!\n")+    tr <- updateTree tr "goodbye/files/world.txt" (blobRef goodbye2)     tr <- update tr     x  <- oid tr     x @?= "f2b42168651a45a4b7ce98464f09c7ec7c06d706"@@ -215,10 +213,10 @@      c2 <- update c2     cid <- objectId c2-    writeRef $ createRef "refs/heads/master" (RefTargetId cid) repo-    writeRef $ createRef "HEAD" (RefTargetSymbolic "refs/heads/master") repo+    writeRef $ createRef repo "refs/heads/master" (RefTargetId cid)+    writeRef $ createRef repo "HEAD" (RefTargetSymbolic "refs/heads/master") -    x <- oidToText <$> lookupId "refs/heads/master" repo+    x <- oidToText <$> resolveRef repo "refs/heads/master"     x @?= "2506e7fcc2dbfe4c083e2bd741871e2e14126603"      mapAllRefs repo (\name -> Prelude.putStrLn $ "Ref: " ++ unpack name)@@ -226,18 +224,54 @@     ehist <- commitHistoryFirstParent c2     Prelude.putStrLn $ "ehist: " ++ show ehist -    ehist2 <- commitEntryHistory "goodbye/files/world.txt" c2+    ehist2 <- commitEntryHistory c2 "goodbye/files/world.txt"     Prelude.putStrLn $ "ehist2: " ++ show ehist2 -    -- oid <- stringToOid ("2506e7fc" :: Text)+    -- oid <- parseOid ("2506e7fc" :: Text)     -- c3 <- lookupCommit (fromJust oid) repo     -- ehist3 <- commitEntryHistory "goodbye/files/world.txt" (fromJust c3)     -- Prelude.putStrLn $ "ehist3: " ++ show ehist3 -    oid <- stringToOid ("2506e7fc" :: Text)-    c4 <- lookupCommit (fromJust oid) repo-    ehist4 <- commitEntryHistory "goodbye/files/world.txt" (fromJust c4)+    oid <- parseOid ("2506e7fc" :: Text)+    c4 <- lookupCommit repo (fromJust oid)+    c5 <- maybe (return Nothing) (lookupCommit repo) oid+    c6 <- lookupCommit repo (fromJust oid)+    ehist4 <- commitEntryHistory (fromJust c4) "goodbye/files/world.txt"     Prelude.putStrLn $ "ehist4: " ++ show (Prelude.head ehist4)++  , "smallTest1" ~:++  withRepository "smallTest1.git" $ \repo -> do+    let blob =+          createBlob repo "# Auto-created repository for tutorial contents\n"+        masterRef = "refs/heads/master"+        sig = Signature { signatureName   = "First Name"+                        , signatureEmail = "user1@email.org"+                        , signatureWhen  = posixSecondsToUTCTime 1348981883 }+    tree <- updateTree (createTree repo) "README.md" (blobRef blob)+    commit <- writeCommit (createCommit repo sig)+            { commitLog       = "Initial commit"+            , commitTree      = ObjRef tree+            } (Just masterRef)+    c1id <- objectId commit+    print $ "commit1 sha = " ++ show c1id++    let sig2 = Signature { signatureName   = "Second Name"+                         , signatureEmail = "user2@email.org"+                         , signatureWhen  = posixSecondsToUTCTime 1348982883 }+    blob <- writeBlob $ createBlob repo "This is some content."+    blobOID <- objectId blob+    commit' <- updateCommit commit {+          commitAuthor = sig+        , commitCommitter = sig+        , commitLog = "This is another log message."+        , commitParents = [ObjRef commit]+        } "foo.txt" (blobRef blob)+    commitOID <- objectId commit'+    print $ "commit2 sha = " ++ show commitOID+    writeRef_ $ createRef repo masterRef $ RefTargetId commitOID++    True @?= True      return ()