This commit is contained in:
voidlizard 2025-01-14 07:53:05 +03:00
parent cb3752da63
commit 33cec9f40f
5 changed files with 188 additions and 1 deletions

View File

@ -19,7 +19,7 @@ import HBS2.Peer.RPC.Client.StorageClient
import HBS2.CLI.Run.Internal.Merkle (getTreeContents) import HBS2.CLI.Run.Internal.Merkle (getTreeContents)
-- move to a sepatate library -- move to Data.Config.Suckless.Script.Filea sepatate library
import HBS2.Data.Log.Structured import HBS2.Data.Log.Structured
@ -34,6 +34,7 @@ import HBS2.Git3.Config.Local
import HBS2.Git3.Git import HBS2.Git3.Git
import Data.Config.Suckless.Script import Data.Config.Suckless.Script
import Data.Config.Suckless.Script.File
import DBPipe.SQLite import DBPipe.SQLite
import Codec.Compression.Zstd.Streaming qualified as ZstdS import Codec.Compression.Zstd.Streaming qualified as ZstdS
@ -905,6 +906,56 @@ theDict = do
LBS.hPutStr fh contents LBS.hPutStr fh contents
entry $ bindMatch "reflog:index:count:missed" $ nil_ $ const $ lift $ flip runContT pure do
hashes <- gitRunCommand [qc|git rev-list --all --objects|]
>>= orThrowPassIO
<&> LBS8.lines
<&> mapMaybe (fromStringMay @GitHash . LBS8.unpack)
for_ hashes $ \h -> do
liftIO $ print $ pretty h
-- git <- findGitDir >>= orThrowUser ".git directory not found"
-- ofiles <- S.toList_ $ glob ["**/*"] ["info/**", "pack/**"] (git </> "objects") $ \fn -> do
-- S.yield fn >> pure True
-- idxFiles <- S.toList_ $ glob ["**/*.idx"] [] (git </> "objects/pack") $ \fn -> do
-- S.yield fn >> pure True
-- liftIO $ for_ ofiles $ \f -> do
-- print f
-- liftIO $ for_ idxFiles $ \f -> flip runContT pure do
-- p <- ContT withGitShowIndex
-- -- void $ ContT $ bracket (pure p) (hClose . getStdin)
-- liftIO do
-- LBS.hPutStr (getStdin p) =<< LBS.readFile f
-- hFlush (getStdin p)
-- wtf <- IO.hGetContents (getStdout p) <&> lines
-- for_ wtf $ IO.putStrLn
-- _ <- gitRunCommand [qc|git show-index|]
-- print f
-- gitCatCheck <- contWorkerPool 4 do
-- che <- ContT withGitCatCheck
-- pure $ gitCheckObjectFromHandle che
-- idx <- lift openIndex
-- missed_ <- newTVarIO ( mempty :: HashSet GitHash )
-- lift $ enumEntries idx $ \bs -> do
-- let gh = GitHash (coerce (BS.take 20 bs))
-- here <- gitCatCheck gh
-- unless (isJust here) do
-- atomically $ modifyTVar missed_ (HS.insert gh)
-- missed <- readTVarIO missed_ <&> HS.size
-- liftIO $ print $ "missed" <+> pretty missed
entry $ bindMatch "reflog:index:list:fast" $ nil_ $ const $ lift do entry $ bindMatch "reflog:index:list:fast" $ nil_ $ const $ lift do
files <- listObjectIndexFiles files <- listObjectIndexFiles
forConcurrently_ files $ \(f,_) -> do forConcurrently_ files $ \(f,_) -> do
@ -916,6 +967,13 @@ theDict = do
notice $ pretty sha1 <+> pretty blake notice $ pretty sha1 <+> pretty blake
entry $ bindMatch "reflog:index:list:count" $ nil_ $ const $ lift do
idx <- openIndex
num_ <- newIORef 0
enumEntries idx $ \_ -> void $ atomicModifyIORef num_ (\x -> (succ x, x))
readIORef num_ >>= liftIO . print . pretty
entry $ bindMatch "reflog:index:list" $ nil_ $ const $ lift do entry $ bindMatch "reflog:index:list" $ nil_ $ const $ lift do
files <- listObjectIndexFiles files <- listObjectIndexFiles
for_ files $ \(ifn,_) -> do for_ files $ \(ifn,_) -> do

View File

@ -128,6 +128,7 @@ library
HBS2.Git3.State.Index HBS2.Git3.State.Index
HBS2.Git3.Config.Local HBS2.Git3.Config.Local
HBS2.Git3.Git HBS2.Git3.Git
HBS2.Git3.Git.Pack
HBS2.Data.Log.Structured HBS2.Data.Log.Structured
@ -170,3 +171,41 @@ executable hbs2-git-daemon
test-suite spec
import: shared-properties
type: exitcode-stdio-1.0
main-is: Spec.hs
other-modules:
HBS2.Git3.Git.PackSpec
-- Data.Config.Suckless.KeyValueSpec
-- Data.Config.Suckless.AesonSpec
hs-source-dirs:
test
ghc-options:
-Wall
-threaded
-rtsopts
-with-rtsopts=-N
build-tool-depends:
hspec-discover:hspec-discover
build-depends: base, hbs2-git3
, hspec
, tasty-hunit
, tasty-quickcheck
, QuickCheck
default-language: Haskell2010
-- default-extensions:
-- DerivingStrategies
-- , FlexibleInstances
-- , MultiParamTypeClasses
-- , OverloadedStrings
-- , ScopedTypeVariables
-- , TypeApplications

View File

@ -33,6 +33,8 @@ import System.Process.Typed
import Text.InterpolatedString.Perl6 (qc) import Text.InterpolatedString.Perl6 (qc)
import UnliftIO import UnliftIO
{-HLINT Ignore "Functor law"-}
pattern GitHashLike:: forall {c} . GitHash -> Syntax c pattern GitHashLike:: forall {c} . GitHash -> Syntax c
pattern GitHashLike x <- ( pattern GitHashLike x <- (
\case \case
@ -162,6 +164,15 @@ withGitCatCheck action = do
p <- startProcess config p <- startProcess config
action p action p
withGitShowIndex :: (MonadIO m) => (Process Handle Handle () -> m a) -> m a
withGitShowIndex action = do
let cmd = "git"
let args = ["show-index"]
let config = setStdin createPipe $ setStdout createPipe $ setStderr closed $ proc cmd args
p <- startProcess config
action p
gitCheckObjectFromHandle :: MonadIO m => Process Handle Handle a -> GitHash -> m (Maybe (GitObjectType, Int)) gitCheckObjectFromHandle :: MonadIO m => Process Handle Handle a -> GitHash -> m (Maybe (GitObjectType, Int))
gitCheckObjectFromHandle ph gh = liftIO do gitCheckObjectFromHandle ph gh = liftIO do

View File

@ -0,0 +1,77 @@
module HBS2.Git3.Git.Pack where
import HBS2.Prelude
import HBS2.Git.Local
import Control.Monad.Identity
import Control.Monad.Trans.Maybe
import Data.Bits
import Data.ByteString as BS
import Lens.Micro.Platform
import Data.Function
import Data.Word
import Network.ByteOrder qualified as N
import Numeric.Natural
--
-- Accordingly to https://git-scm.com/docs/pack-format
data PackFileObjectType =
OBJ_COMMIT -- (1)
| OBJ_TREE -- (2)
| OBJ_BLOB -- (3)
| OBJ_TAG -- (4)
| OBJ_RESERVED -- (5)
| OBJ_OFS_DELTA -- (6)
| OBJ_REF_DELTA -- (7)
deriving stock (Eq,Ord,Show)
instance Enum PackFileObjectType where
fromEnum OBJ_COMMIT = 1
fromEnum OBJ_TREE = 2
fromEnum OBJ_BLOB = 3
fromEnum OBJ_TAG = 4
fromEnum OBJ_RESERVED = 5
fromEnum OBJ_OFS_DELTA = 6
fromEnum OBJ_REF_DELTA = 7
toEnum 1 = OBJ_COMMIT
toEnum 2 = OBJ_TREE
toEnum 3 = OBJ_BLOB
toEnum 4 = OBJ_TAG
toEnum 6 = OBJ_OFS_DELTA
toEnum 7 = OBJ_REF_DELTA
toEnum n = error $ "Invalid PackFileObjectType: " ++ show n
encodeObjectSize :: PackFileObjectType -> Natural -> ByteString
encodeObjectSize objType size =
BS.pack $ go (fromIntegral (fromEnum objType) `shiftL` 4 .|. fromIntegral (size .&. 0x0F)) (size `shiftR` 4)
where
go :: Word8 -> Natural -> [Word8]
go prefix 0 = [prefix]
go prefix sz = (prefix .|. 0x80) : go (fromIntegral (sz .&. 0x7F)) (sz `shiftR` 7)
decodeObjectSize :: ByteString -> Maybe ((PackFileObjectType, Natural), ByteString )
decodeObjectSize source = run $ flip fix (source,0,0,0) $ \next (bs, i, tp, num) -> do
case BS.uncons bs of
Nothing -> Nothing
Just (byte, rest) -> do
let val = clearBit byte 7
let acc = case i of
0 -> (rest, succ i, fromIntegral (val `shiftR` 4), fromIntegral (val .&. 0x0F))
1 -> (rest, succ i, tp, num .|. fromIntegral val `shiftL` 4)
_ -> (rest, succ i, tp, num .|. fromIntegral val `shiftL` 7)
if testBit byte 7 then
next acc
else
pure acc
where
run loop = case loop of
Just (bs, _, tp, x) | tp > 0 && tp <= 7 -> Just ((toEnum tp, fromIntegral x), bs)
_ -> Nothing

2
hbs2-git3/test/Spec.hs Normal file
View File

@ -0,0 +1,2 @@
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}