This commit is contained in:
voidlizard 2024-12-04 13:01:39 +03:00
parent a7aae31cac
commit dbcff19aed
3 changed files with 100 additions and 50 deletions

View File

@ -164,7 +164,6 @@ outputs = { self, nixpkgs, flake-utils, ... }@inputs:
pkgs.libsodium pkgs.libsodium
pkgs.file pkgs.file
pkgs.zlib pkgs.zlib
pkgs.bzip2
inputs.hspup.packages.${pkgs.system}.default inputs.hspup.packages.${pkgs.system}.default
] ]
); );

View File

@ -1,4 +1,5 @@
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
{-# Language MultiWayIf #-}
{-# Language FunctionalDependencies #-} {-# Language FunctionalDependencies #-}
{-# Language ViewPatterns #-} {-# Language ViewPatterns #-}
{-# Language PatternSynonyms #-} {-# Language PatternSynonyms #-}
@ -45,12 +46,6 @@ import HBS2.Git3.Config.Local
import Data.Config.Suckless.Script import Data.Config.Suckless.Script
import DBPipe.SQLite import DBPipe.SQLite
-- import Codec.Compression.GZip as GZ1
-- import Codec.Compression.Zlib.Internal qualified as GZ
import Codec.Compression.BZip as BZ1
import Codec.Compression.BZip.Internal qualified as BZ
-- import Codec.Compression.Zlib.Internal qualified as GZ
import Codec.Compression.Zstd qualified as Zstd import Codec.Compression.Zstd qualified as Zstd
import Codec.Compression.Zstd.Streaming qualified as ZstdS import Codec.Compression.Zstd.Streaming qualified as ZstdS
import Codec.Compression.Zstd.Streaming (Result(..)) import Codec.Compression.Zstd.Streaming (Result(..))
@ -63,6 +58,7 @@ import Data.List qualified as L
import Data.ByteString.Lazy.Char8 qualified as LBS8 import Data.ByteString.Lazy.Char8 qualified as LBS8
import Data.ByteString.Lazy qualified as LBS import Data.ByteString.Lazy qualified as LBS
import Data.ByteString qualified as BS import Data.ByteString qualified as BS
import Data.ByteString.Char8 qualified as BS8
import Data.ByteString.Lazy (ByteString) import Data.ByteString.Lazy (ByteString)
import Data.ByteString.Builder as Builder import Data.ByteString.Builder as Builder
import Text.InterpolatedString.Perl6 (qc) import Text.InterpolatedString.Perl6 (qc)
@ -77,6 +73,7 @@ import Streaming.Prelude qualified as S
import System.Exit qualified as Q import System.Exit qualified as Q
import System.Environment qualified as E import System.Environment qualified as E
import System.Process.Typed import System.Process.Typed
import Control.Applicative
import Control.Monad.Trans.Cont import Control.Monad.Trans.Cont
import Control.Monad.Trans.Maybe import Control.Monad.Trans.Maybe
import Control.Monad.Reader import Control.Monad.Reader
@ -130,6 +127,13 @@ data GitTreeEntry =
pattern GitTreeEntryView :: GitTreeEntry -> [ByteString] pattern GitTreeEntryView :: GitTreeEntry -> [ByteString]
pattern GitTreeEntryView e <- (isGitLsTreeEntry -> Just e) pattern GitTreeEntryView e <- (isGitLsTreeEntry -> Just e)
gitNormaliseRef :: GitRef -> GitRef
gitNormaliseRef r@(GitRef what) =
if BS8.isPrefixOf "refs/" what || what == "HEAD" then
r
else
fromString (joinPath $ splitPath $ "refs" </> "heads" </> BS8.unpack what)
isGitLsTreeEntry :: [ByteString] -> Maybe GitTreeEntry isGitLsTreeEntry :: [ByteString] -> Maybe GitTreeEntry
isGitLsTreeEntry = \case isGitLsTreeEntry = \case
[sa,st,sh,ss,sn] -> do [sa,st,sh,ss,sn] -> do
@ -171,6 +175,14 @@ gitRevParse ref = do
gitRevParseThrow :: (Pretty ref, MonadIO m) => ref -> m GitHash gitRevParseThrow :: (Pretty ref, MonadIO m) => ref -> m GitHash
gitRevParseThrow r = gitRevParse r >>= orThrow (UnknownRev (show $ pretty r)) gitRevParseThrow r = gitRevParse r >>= orThrow (UnknownRev (show $ pretty r))
gitReadHEAD :: MonadIO m => m (Maybe GitRef)
gitReadHEAD = runMaybeT do
gitRunCommand [qc|git symbolic-ref HEAD|]
>>= toMPlus
<&> headMay . LBS8.lines
>>= toMPlus
<&> GitRef . LBS8.toStrict
withGitCat :: (MonadIO m) => (Process Handle Handle () -> m a) -> m a withGitCat :: (MonadIO m) => (Process Handle Handle () -> m a) -> m a
withGitCat action = do withGitCat action = do
let cmd = "git" let cmd = "git"
@ -377,9 +389,6 @@ gitObjectExists what = do
data UState = data UState =
UHead ByteString UHead ByteString
pattern PEntryView :: GitObjectType -> Word32 -> GitHash -> [ByteString]
pattern PEntryView t s h <- ( unpackPEntry -> Just (t,s,h) )
unpackPEntry :: [ByteString] -> Maybe (GitObjectType, Word32, GitHash) unpackPEntry :: [ByteString] -> Maybe (GitObjectType, Word32, GitHash)
unpackPEntry = \case unpackPEntry = \case
("C" : s : h : _) -> (Commit,,) <$> readMay (LBS8.unpack s) <*> fromStringMay (LBS8.unpack h) ("C" : s : h : _) -> (Commit,,) <$> readMay (LBS8.unpack s) <*> fromStringMay (LBS8.unpack h)
@ -393,7 +402,7 @@ data ES =
enumGitPackObjectsFromLBS :: MonadIO m enumGitPackObjectsFromLBS :: MonadIO m
=> ByteString => ByteString
-> ( GitObjectType -> Word32 -> GitHash -> m Bool ) -> ( IOp -> m Bool )
-> m () -> m ()
enumGitPackObjectsFromLBS lbs action = do enumGitPackObjectsFromLBS lbs action = do
@ -424,13 +433,15 @@ enumGitPackObjectsFromLBS lbs action = do
let s0 = LBS8.dropWhile (=='\n') chunk let s0 = LBS8.dropWhile (=='\n') chunk
unless (LBS.null s0) do unless (LBS.null s0) do
let (hdr,rest) = LBS8.break (=='\n') s0 let (hdr,rest) = LBS8.break (=='\n') s0
(t,s,h) <- unpackPEntry (LBS8.words hdr) & orThrow (InvalidGitPack hdr)
void $ action t s h iop@(IOp s _) <- unpackIOp (LBS8.words hdr) & orThrow (InvalidGitPack hdr)
void $ action iop
let o = LBS.drop 1 rest let o = LBS.drop 1 rest
let (_, rest2) = LBS.splitAt (fromIntegral s) o let (_, rest2) = LBS.splitAt (fromIntegral s) o
next (UHead rest2) next (UHead rest2)
data ExportState = data ExportState =
ExportGetCommit ExportGetCommit
| ExportProcessCommit GitHash ByteString | ExportProcessCommit GitHash ByteString
@ -452,8 +463,55 @@ data WInput =
| WInputCBlock HashRef | WInputCBlock HashRef
data EOp =
EGitObject GitObjectType GitHash (Maybe GitTreeEntry) ByteString
| EGitRef GitRef Int (Maybe GitHash)
data IOpType
= IOGitObject GitObjectType GitHash
| IOSetRef GitRef Int (Maybe GitHash)
deriving (Show, Eq)
data IOp = IOp Word32 IOpType
deriving (Show, Eq)
unpackIOp :: [ByteString] -> Maybe IOp
unpackIOp = \case
("C" : s : h : _) -> do
size <- fromLBS s
hash <- fromLBS' h
pure $ IOp size (IOGitObject Commit hash)
("B" : s : h : _) -> do
size <- fromLBS s
hash <- fromLBS' h
pure $ IOp size (IOGitObject Blob hash)
("T" : s : h : _) -> do
size <- fromLBS s
hash <- fromLBS' h
pure $ IOp size (IOGitObject Tree hash)
("R" : s : n : r : rest) -> do
size <- fromLBS s
weight <- fromLBS n
refName <- pure (GitRef $ LBS8.toStrict r)
hash <- case rest of
(h : _) -> Just <$> fromStringMay (LBS8.unpack h)
_ -> pure Nothing
pure $ IOp size (IOSetRef refName weight hash)
_ -> Nothing
where
fromLBS :: forall a . Read a => ByteString -> Maybe a
fromLBS = readMay . LBS8.unpack
fromLBS' :: forall a. FromStringMaybe a => ByteString -> Maybe a
fromLBS' = fromStringMay . LBS8.unpack
data EWState = data EWState =
EWAcc Int [GitTreeEntry] Int [(GitHash, GitObjectType,Maybe GitTreeEntry, ByteString)] EWAcc Int [GitTreeEntry] Int [EOp]
newtype CacheTVH k v = CacheTVH (TVar (HashMap k v)) newtype CacheTVH k v = CacheTVH (TVar (HashMap k v))
@ -509,10 +567,12 @@ export :: ( HBS2GitPerks m
, HasStorage m , HasStorage m
, HasStateDB m , HasStateDB m
) )
=> GitHash -> m () => Maybe GitRef -> GitHash -> m ()
export r = connectedDo $ flip runContT pure do export mref' r = connectedDo $ flip runContT pure do
debug $ green "export" <+> pretty r debug $ green "export" <+> pretty r
let mref = gitNormaliseRef <$> mref'
q <- newTVarIO ( HPSQ.empty @GitHash @Double @() ) q <- newTVarIO ( HPSQ.empty @GitHash @Double @() )
done <- newTVarIO ( mempty :: HashSet GitHash ) done <- newTVarIO ( mempty :: HashSet GitHash )
@ -539,19 +599,6 @@ export r = connectedDo $ flip runContT pure do
ContT $ withAsync $ replicateM_ 2 $ forever do ContT $ withAsync $ replicateM_ 2 $ forever do
join $ atomically (readTQueue deferred) join $ atomically (readTQueue deferred)
-- let noCBlock x = do
-- here <- withState $ selectCBlock x
-- pure (isNothing here)
-- pre <- gitRunCommand [qc|git rev-list {pretty r}|]
-- <&> fromRight mempty
-- <&> LBS8.lines
-- <&> mapMaybe ( fromStringMay @GitHash . LBS8.unpack )
-- <&> take (10 * commitCacheSize)
-- >>= filterM (lift . noCBlock)
-- <&> take commitCacheSize
-- >>= \xs -> lift (mapM_ (\x -> cached commits x (gitReadObjectMaybe reader x)) xs)
lift $ flip fix ExportGetCommit $ \next -> \case lift $ flip fix ExportGetCommit $ \next -> \case
ExportStart -> do ExportStart -> do
@ -642,7 +689,7 @@ export r = connectedDo $ flip runContT pure do
out <- newTQueueIO out <- newTQueueIO
flip fix (EWAcc 1 r 0 [(co,Commit,Nothing,bs)]) $ \go -> \case flip fix (EWAcc 1 r 0 [EGitObject Commit co Nothing bs]) $ \go -> \case
EWAcc _ [] _ [] -> none EWAcc _ [] _ [] -> none
@ -663,7 +710,8 @@ export r = connectedDo $ flip runContT pure do
>>= orThrow (GitReadError (show $ pretty gitEntryHash)) >>= orThrow (GitReadError (show $ pretty gitEntryHash))
<&> snd <&> snd
go (EWAcc i rs (l + fromIntegral (LBS.length lbs)) ((gitEntryHash,gitEntryType, Just e, lbs) : acc)) let new = EGitObject gitEntryType gitEntryHash (Just e) lbs
go (EWAcc i rs (l + fromIntegral (LBS.length lbs)) (new : acc))
packs <- atomically do packs <- atomically do
allDone <- isEmptyTQueue deferred allDone <- isEmptyTQueue deferred
@ -756,10 +804,15 @@ export r = connectedDo $ flip runContT pure do
-- write -- write
-- pack -- pack
-- merkle -- merkle
--
let acc = reverse racc let acc = reverse racc
debug $ green "write pack of objects" <+> pretty l <+> pretty (length acc) debug $ green "write pack of objects" <+> pretty l <+> pretty (length acc)
parts <- for acc $ \(h,t,e,lbs) -> liftIO do let refs = [ Builder.byteString [qc|R 0 {w} {show $ pretty ref} {show $ pretty h}|]
| EGitRef ref w h <- acc
] & mconcat & (<> Builder.byteString "\n")
parts <- for [ (h,t,e,lbs) | EGitObject t h e lbs <- acc ] $ \(h,t,e,lbs) -> liftIO do
let ename = [qc|{fromMaybe mempty $ gitEntryName <$> e}|] :: ByteString let ename = [qc|{fromMaybe mempty $ gitEntryName <$> e}|] :: ByteString
-- notice $ "pack" <+> pretty h <+> pretty t -- notice $ "pack" <+> pretty h <+> pretty t
@ -824,15 +877,8 @@ theDict = do
_ -> throwIO (BadFormException @C nil) _ -> throwIO (BadFormException @C nil)
entry $ bindMatch "test:git:tree:pack:dump" $ nil_ $ \case entry $ bindMatch "test:git:normalize-ref" $ nil_ \case
[ StringLike fn ] -> do [ StringLike s ] -> display $ mkStr @C (show $ pretty $ gitNormaliseRef (fromString s))
lbs <- liftIO (LBS8.readFile fn)
enumGitPackObjectsFromLBS lbs $ \t s h -> do
liftIO $ print $ pretty h <+> pretty t <+> pretty s
pure True
_ -> throwIO (BadFormException @C nil) _ -> throwIO (BadFormException @C nil)
entry $ bindMatch "test:hbs2:peer:poke" $ nil_ $ \syn -> do entry $ bindMatch "test:hbs2:peer:poke" $ nil_ $ \syn -> do
@ -872,17 +918,25 @@ theDict = do
for_ rs $ \r -> do for_ rs $ \r -> do
what <- runExceptT (getTreeContents sto r) >>= orThrowPassIO what <- runExceptT (getTreeContents sto r) >>= orThrowPassIO
debug $ yellow "reading" <+> pretty r debug $ yellow "reading" <+> pretty r
enumGitPackObjectsFromLBS what $ \t s h -> do enumGitPackObjectsFromLBS what $ \case
IOp s (IOGitObject t h) -> do
putStrLn $ show $ pretty t <+> pretty h <+> pretty s putStrLn $ show $ pretty t <+> pretty h <+> pretty s
pure True pure True
IOp _ (IOSetRef ref w h ) -> do
putStrLn $ show $ pretty ref <+> pretty w <+> pretty h
pure True
entry $ bindMatch "test:git:tree:export" $ nil_ $ \syn -> lift do entry $ bindMatch "test:git:tree:export" $ nil_ $ \syn -> lift do
r <- case syn of (w, r) <- case syn of
[] -> gitRevParseThrow "HEAD" [] -> (Nothing,) <$> gitRevParseThrow "HEAD"
[ StringLike co ] -> gitRevParseThrow co [ StringLike co ] -> (Just (fromString co),) <$> gitRevParseThrow co
_ -> throwIO (BadFormException @C nil) _ -> throwIO (BadFormException @C nil)
export r let re = headMay [ GitRef (BS8.pack x) | ListVal [StringLike "--ref", StringLike x ] <- syn ]
hd <- gitReadHEAD
export (w <|> re <|> hd) r
-- debugPrefix :: LoggerEntry -> LoggerEntry -- debugPrefix :: LoggerEntry -> LoggerEntry
debugPrefix = toStderr . logPrefix "[debug] " debugPrefix = toStderr . logPrefix "[debug] "

View File

@ -120,7 +120,6 @@ library
build-depends: base build-depends: base
, base16-bytestring , base16-bytestring
, binary , binary
, bzlib
, psqueues , psqueues
, unix , unix
@ -134,7 +133,6 @@ executable hbs2-git3
-- other-extensions: -- other-extensions:
build-depends: build-depends:
base, hbs2-git3, hbs2-core, hbs2-peer, hbs2-git base, hbs2-git3, hbs2-core, hbs2-peer, hbs2-git
, bzlib
, binary , binary
, psqueues , psqueues
, vector , vector
@ -150,7 +148,6 @@ executable hbs2-git-daemon
-- other-extensions: -- other-extensions:
build-depends: build-depends:
base, hbs2-git3, hbs2-core, hbs2-peer, hbs2-git base, hbs2-git3, hbs2-core, hbs2-peer, hbs2-git
, bzlib
, binary , binary
, vector , vector