1
0
Fork 0
mirror of https://code.sup39.dev/repos/Wqawg synced 2024-12-31 04:04:52 +09:00

Git: Implement pack protocol negotiation upload-haves and ack

This commit is contained in:
fr33domlover 2016-04-01 10:37:49 +00:00
parent 7b9f6e9714
commit 372368f0a0
7 changed files with 148 additions and 10 deletions

View file

@ -70,9 +70,15 @@ requireWord8 p = do
then return w then return w
else fail "Word doesn't satisfy predicate" else fail "Word doesn't satisfy predicate"
attemptWord8 :: (Word8 -> Bool) -> Get (Maybe Word8)
attemptWord8 p = Just <$> requireWord8 p <|> pure Nothing
requireSpace :: Get () requireSpace :: Get ()
requireSpace = void $ requireWord8 (== 32) requireSpace = void $ requireWord8 (== 32)
requireNewline :: Get ()
requireNewline = void $ requireWord8 (== 10)
attemptByteString :: ByteString -> Get Bool attemptByteString :: ByteString -> Get Bool
attemptByteString s = fmap isJust . lookAheadM $ do attemptByteString s = fmap isJust . lookAheadM $ do
b <- getByteString $ length s b <- getByteString $ length s

View file

@ -0,0 +1,47 @@
{- This file is part of Vervis.
-
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
-
- 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
- <http://creativecommons.org/publicdomain/zero/1.0/>.
-}
module Network.Git.Local.Ack.Put
( putAckMulti
, putAck
, putNak
)
where
putAckStatus :: AckStatus -> Put
putAckStatus AckContinue = putByteString "continue"
putAckStatus AckCommon = putByteString "common"
putAckStatus AckReady = putByteString "ready"
lenAckStatus :: AckStatus -> Int
lenAckStatus AckContinue = 8
lenAckStatus AckCommon = 6
lenAckStatus AckReady = 5
putAckMulti :: ObjId -> AckStatus -> Put
putAckMulti oid as = putDataPkt True (3 + 1 + 40 + lenAckStatus as) $ do
putByteString "ACK"
putSpace
putObjId oid
putAckStatus as
putAck :: ObjId -> Put
putAck oid = putDataPkt True (3 + 1 + 40) $ do
putByteString "ACK"
putSpace
putObjId oid
putNak :: Put
putNak = putDataPkt True 3 $ putByteString "NAK"

View file

@ -0,0 +1,21 @@
{- This file is part of Vervis.
-
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
-
- 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
- <http://creativecommons.org/publicdomain/zero/1.0/>.
-}
module Network.Git.Local.Ack.Types
( AckStatus (..)
)
where
data AckStatus = AckContinue | AckCommon | AckReady

View file

@ -41,6 +41,18 @@ getDataPkt getPayload = do
getObjId :: Get ObjId getObjId :: Get ObjId
getObjId = ObjId . fromHex <$> getByteString 40 getObjId = ObjId . fromHex <$> getByteString 40
getTaggedObjId :: ByteString -> Get ObjId
getTaggedObjId tag = getDataPkt $ \ len ->
let baselen = B.length tag + 1 + 40
in if len < baselen || baselen + 1 < len
then fail "Tagged obj id of unexpected length"
else do
requireByteString tag
requireSpace
oid <- getObjId
when (len == baselen + 1) requireNewline
return oid
getCapabilities :: Int -> Get [Capability] getCapabilities :: Int -> Get [Capability]
getCapabilities n = do getCapabilities n = do
getByteString n getByteString n

View file

@ -0,0 +1,38 @@
{- This file is part of Vervis.
-
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
-
- 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
- <http://creativecommons.org/publicdomain/zero/1.0/>.
-}
module Network.Git.Local.UploadHaves.Get
( getUploadHaves
)
where
getHaves :: Get [ObjId]
getHaves = many $ getTaggedObjId "have"
requireDone :: Get ()
requireDone = getDataPkt $ \ len ->
if len < 4 || len > 5
then fail "invalid pkt-len for a \"done\" line"
else do
requireByteString "done"
when (len == 5) requireNewline
getUploadHaves :: Get UploadHaves
getUploadHaves = do
haves <- getHaves
requireFlushPkt <|> requireDone
return UploadHaves
{ uhHave = haves
}

View file

@ -0,0 +1,23 @@
{- This file is part of Vervis.
-
- Written in 2016 by fr33domlover <fr33domlover@riseup.net>.
-
- 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
- <http://creativecommons.org/publicdomain/zero/1.0/>.
-}
module Network.Git.Local.UploadHaves.Types
( UploadHaves (..)
)
where
data UploadHaves = UploadHaves
{ uhHave :: [ObjId]
}

View file

@ -26,20 +26,11 @@ getFirstWant = getDataPkt $ \ len -> do
caps <- getCapabilities $ len - 45 caps <- getCapabilities $ len - 45
return (caps, oid) return (caps, oid)
attemptTaggedObjId :: ByteString -> Get (Maybe ObjId)
attemptTaggedObjId s = lookAheahM $ getDataPkt $ \ _len -> do
b <- getByteString $ length s
if b == s
then do
requireSpace
Just <$> getObjId
else return Nothing
-- unfoldM is from the monad-loops package -- unfoldM is from the monad-loops package
getWants :: Get ([Capability], [ObjId]) getWants :: Get ([Capability], [ObjId])
getWants = do getWants = do
(caps, oid) <- getFirstWant (caps, oid) <- getFirstWant
oids <- unfoldM $ attemptTaggedObjId "want" oids <- many $ getTaggedObjId "want"
return (caps, oid:oids) return (caps, oid:oids)
getShallows :: Get [ObjId] getShallows :: Get [ObjId]