This commit is contained in:
Dmitry Zuikov 2024-05-12 09:04:51 +03:00
parent b533e2ac46
commit 09ebc4fc0d
7 changed files with 234 additions and 78 deletions

View File

@ -101,6 +101,7 @@ library
exposed-modules: exposed-modules:
Fixme Fixme
Fixme.Config
Fixme.Run Fixme.Run
Fixme.Types Fixme.Types
Fixme.Prelude Fixme.Prelude

View File

@ -0,0 +1,26 @@
module Fixme.Config where
import Fixme.Prelude
import Fixme.Types
import HBS2.System.Dir
import System.Environment
binName :: FixmePerks m => m FilePath
binName = liftIO getProgName
localConfigDir :: FixmePerks m => m FilePath
localConfigDir = do
p <- pwd
b <- binName
pure (p </> ("." <> b))
localConfig:: FixmePerks m => m FilePath
localConfig = localConfigDir <&> (</> "config")
localDBName :: FilePath
localDBName = "state.db"
localDBPath :: FixmePerks m => m FilePath
localDBPath = localConfigDir <&> (</> localDBName)

View File

@ -2,13 +2,16 @@ module Fixme.Prelude
( module All ( module All
, GitHash(..) , GitHash(..)
, Serialise(..) , Serialise(..)
, serialise, deserialiseOrFail, deserialise
) where ) where
import HBS2.Prelude.Plated as All import HBS2.Prelude.Plated as All
import HBS2.Hash as All
import HBS2.Data.Types.Refs as All
import HBS2.Misc.PrettyStuff as All import HBS2.Misc.PrettyStuff as All
import HBS2.System.Logger.Simple.ANSI as All import HBS2.System.Logger.Simple.ANSI as All
import HBS2.Git.Local (GitHash(..)) import HBS2.Git.Local (GitHash(..))
import Codec.Serialise (Serialise(..)) import Codec.Serialise (Serialise(..),serialise,deserialise,deserialiseOrFail)
import Data.Functor as All import Data.Functor as All
import Data.Function as All import Data.Function as All
import UnliftIO as All import UnliftIO as All

View File

@ -6,6 +6,8 @@ module Fixme.Run where
import Prelude hiding (init) import Prelude hiding (init)
import Fixme.Prelude hiding (indent) import Fixme.Prelude hiding (indent)
import Fixme.Types import Fixme.Types
import Fixme.Config
import Fixme.State
import Fixme.Scan.Git as Git import Fixme.Scan.Git as Git
import Fixme.Scan as Scan import Fixme.Scan as Scan
@ -74,6 +76,7 @@ pattern StringLikeList e <- (stringLikeList -> e)
data ScanGitArgs = data ScanGitArgs =
PrintBlobs PrintBlobs
| PrintFixme | PrintFixme
| ScanRunDry
deriving stock (Eq,Ord,Show,Data,Generic) deriving stock (Eq,Ord,Show,Data,Generic)
pattern ScanGitArgs :: forall {c} . ScanGitArgs -> Syntax c pattern ScanGitArgs :: forall {c} . ScanGitArgs -> Syntax c
@ -83,6 +86,7 @@ scanGitArg :: Syntax c -> Maybe ScanGitArgs
scanGitArg = \case scanGitArg = \case
SymbolVal "print-blobs" -> Just PrintBlobs SymbolVal "print-blobs" -> Just PrintBlobs
SymbolVal "print-fixme" -> Just PrintFixme SymbolVal "print-fixme" -> Just PrintFixme
SymbolVal "dry" -> Just ScanRunDry
_ -> Nothing _ -> Nothing
scanGitArgs :: [Syntax c] -> [ScanGitArgs] scanGitArgs :: [Syntax c] -> [ScanGitArgs]
@ -105,17 +109,39 @@ fixmePrefix = \case
SymbolVal s -> Just (FixmeTag (coerce s)) SymbolVal s -> Just (FixmeTag (coerce s))
_ -> Nothing _ -> Nothing
binName :: FixmePerks m => m FilePath
binName = liftIO getProgName
localConfigDir :: FixmePerks m => m FilePath runFixmeCLI :: FixmePerks m => FixmeM m a -> m a
localConfigDir = do runFixmeCLI m = do
p <- pwd db <- newDBPipeEnv dbPipeOptsDef =<< localDBPath
b <- binName env <- FixmeEnv Nothing db
pure (p </> ("." <> b)) <$> newTVarIO mempty
<*> newTVarIO mempty
<*> newTVarIO mempty
<*> newTVarIO mempty
<*> newTVarIO mempty
<*> newTVarIO defCommentMap
<*> newTVarIO Nothing
runReaderT ( setupLogger >> fromFixmeM (evolve >> m) ) env
`finally` flushLoggers
where
setupLogger = do
setLogging @ERROR $ toStderr . logPrefix "[error] "
setLogging @WARN $ toStderr . logPrefix "[warn] "
setLogging @NOTICE $ toStdout . logPrefix ""
pure ()
flushLoggers = do
silence
silence :: FixmePerks m => m ()
silence = do
setLoggingOff @DEBUG
setLoggingOff @ERROR
setLoggingOff @WARN
setLoggingOff @NOTICE
localConfig:: FixmePerks m => m FilePath
localConfig = localConfigDir <&> (</> "config")
readConfig :: FixmePerks m => FixmeM m [Syntax C] readConfig :: FixmePerks m => FixmeM m [Syntax C]
@ -140,7 +166,7 @@ init = do
unless here do unless here do
liftIO $ writeFile gitignore $ show $ liftIO $ writeFile gitignore $ show $
vcat [ "./state.db" vcat [ pretty ("." </> localDBName)
] ]
notice $ yellow "run" <> line <> vcat [ notice $ yellow "run" <> line <> vcat [
@ -211,11 +237,16 @@ filterBlobs xs = do
let r = [(h,f) | (_,(f,h),_) <- matchMany pat src] & HM.fromList & HM.toList let r = [(h,f) | (_,(f,h),_) <- matchMany pat src] & HM.fromList & HM.toList
pure $ [ (b,a) | (a,b) <- r ] pure $ [ (b,a) | (a,b) <- r ]
scanGitLocal :: FixmePerks m => [ScanGitArgs] -> Maybe FilePath -> FixmeM m () scanGitLocal :: FixmePerks m
=> [ScanGitArgs]
-> Maybe FilePath
-> FixmeM m ()
scanGitLocal args p = do scanGitLocal args p = do
env <- ask env <- ask
dbpath <- localDBPath
flip runContT pure do flip runContT pure do
(dbFn, _) <- ContT $ withSystemTempFile "fixme-db" . curry (dbFn, _) <- ContT $ withSystemTempFile "fixme-db" . curry
@ -246,6 +277,7 @@ scanGitLocal args p = do
) )
|] |]
update_ [qc|ATTACH DATABASE '{dbpath}' as fixme|]
co <- lift listCommits co <- lift listCommits
@ -304,6 +336,7 @@ scanGitLocal args p = do
poor <- lift (Scan.scanBlob (Just fp) blob) poor <- lift (Scan.scanBlob (Just fp) blob)
rich <- withDB tempDb do rich <- withDB tempDb do
let q = [qc| let q = [qc|
@ -338,7 +371,12 @@ scanGitLocal args p = do
]) ])
for poor $ \f -> do for poor $ \f -> do
pure $ over (field @"fixmeAttr") (<> what) f let ts = HM.lookup "commit-time" what
<&> Text.unpack . coerce
>>= readMay
<&> FixmeTimestamp
pure $ set (field @"fixmeTs") ts $ over (field @"fixmeAttr") (<> what) f
let fixmies = rich let fixmies = rich
@ -346,30 +384,18 @@ scanGitLocal args p = do
for_ fixmies $ \fixme -> do for_ fixmies $ \fixme -> do
liftIO $ print $ pretty fixme liftIO $ print $ pretty fixme
when ( ScanRunDry `elem` args ) $ fucked ()
debug $ "actually-import-fixmies" <+> pretty h
liftIO $ withFixmeEnv env $ withState $ transactional do
for_ fixmies $ \fixme@Fixme{..} -> do
debug $ "fixme-ts:" <+> pretty fixmeTs
insertFixme fixme
_ -> fucked () _ -> fucked ()
-- when ( PrintFixme `elem` args ) do
-- for_ blobs $ \(fp,h) -> do
-- liftIO $ IO.hPrint ssin (pretty h) >> IO.hFlush ssin
-- prefix <- liftIO (BS.hGetLine ssout) <&> BS.words
-- case prefix of
-- [_, "blob", ssize] -> do
-- let mslen = readMay @Int (BS.unpack ssize)
-- len <- ContT $ maybe1 mslen (pure ())
-- blob <- liftIO $ LBS8.hGet ssout len
-- void $ liftIO $ BS.hGetLine ssout
-- fixmies <- lift (Scan.scanBlob (Just fp) blob)
-- for_ fixmies $ \fixme -> do
-- liftIO $ print $ pretty fixme
-- _ -> fucked ()
-- debug $ red "NOW WHAT?"
startGitCatFile :: (FixmePerks m, MonadReader FixmeEnv m) => m (Process Handle Handle ()) startGitCatFile :: (FixmePerks m, MonadReader FixmeEnv m) => m (Process Handle Handle ())
@ -380,21 +406,6 @@ startGitCatFile = do
let config = setStdin createPipe $ setStdout createPipe $ setStderr closed $ shell cmd let config = setStdin createPipe $ setStdout createPipe $ setStderr closed $ shell cmd
startProcess config startProcess config
extractFixmeFromGitBlob :: FixmePerks m => FilePath -> GitHash -> FixmeM m [Fixme]
extractFixmeFromGitBlob fp gh = do
pure mempty
exractFixme :: FixmePerks m => ByteString -> m [Fixme]
exractFixme bs = do
let ls = LBS8.lines bs
pure mempty
readUtf8 :: ByteString -> Text
readUtf8 bs = LBS8.toStrict bs & Text.decodeUtf8
readFixmeStdin :: FixmePerks m => FixmeM m () readFixmeStdin :: FixmePerks m => FixmeM m ()
readFixmeStdin = do readFixmeStdin = do
@ -450,6 +461,7 @@ splitForms :: [String] -> [[String]]
splitForms s0 = runIdentity $ S.toList_ (go mempty s0) splitForms s0 = runIdentity $ S.toList_ (go mempty s0)
where where
go acc ( "then" : rest ) = emit acc >> go mempty rest go acc ( "then" : rest ) = emit acc >> go mempty rest
go acc ( "and" : rest ) = emit acc >> go mempty rest
go acc ( x : rest ) = go ( x : acc ) rest go acc ( x : rest ) = go ( x : acc ) rest
go acc [] = emit acc go acc [] = emit acc
@ -515,6 +527,20 @@ run what = do
ListVal [SymbolVal "no-debug"] -> do ListVal [SymbolVal "no-debug"] -> do
setLoggingOff @DEBUG setLoggingOff @DEBUG
ListVal [SymbolVal "silence"] -> do
silence
ListVal [SymbolVal "builtin:evolve"] -> do
evolve
ListVal [SymbolVal "trace"] -> do
setLogging @TRACE (logPrefix "[trace] " . toStderr)
trace "trace on"
ListVal [SymbolVal "no-trace"] -> do
trace "trace off"
setLoggingOff @TRACE
ListVal [SymbolVal "debug"] -> do ListVal [SymbolVal "debug"] -> do
setLogging @DEBUG $ toStderr . logPrefix "[debug] " setLogging @DEBUG $ toStderr . logPrefix "[debug] "

View File

@ -26,9 +26,9 @@ import Streaming.Prelude qualified as S
data SfEnv = data SfEnv =
SfEnv { lno :: Int SfEnv { lno :: Int -- ^ line number
, l0 :: Int , l0 :: Int -- ^ fixme indent
, eln :: Int , eln :: Int -- ^ empty lines counter
} }
deriving stock Generic deriving stock Generic

View File

@ -1 +1,122 @@
module Fixme.State where {-# OPTIONS_GHC -fno-warn-orphans #-}
module Fixme.State
( evolve
, withState
, insertFixme
) where
import Fixme.Prelude
import Fixme.Types
import Fixme.Config
import HBS2.System.Dir
import DBPipe.SQLite
import Data.HashMap.Strict qualified as HM
import Text.InterpolatedString.Perl6 (qc)
instance ToField HashRef where
toField x = toField $ show $ pretty x
instance FromField HashRef where
fromField = fmap (fromString @HashRef) . fromField @String
evolve :: FixmePerks m => FixmeM m ()
evolve = do
dbpath <- localDBPath
debug $ "evolve" <+> pretty dbpath
mkdir (takeDirectory dbpath)
db <- newDBPipeEnv dbPipeOptsDef dbpath
withDB db do
createTables
withState :: forall m a . (FixmePerks m, MonadReader FixmeEnv m) => DBPipeM m a -> m a
withState what = do
db <- asks fixmeEnvDb
withDB db what
createTables :: FixmePerks m => DBPipeM m ()
createTables = do
-- тут все таблицы будут называться с префиксом
-- fixme, что бы может быть можно было встроить
-- в другую бд, если вдруг понадобится
ddl [qc|
create table if not exists fixmecommit
( hash text not null
, ts int not null
, primary key (hash)
)
|]
ddl [qc|
create table if not exists fixme
( id text not null
, fixme blob not null
, primary key (id)
)
|]
ddl [qc|
create table if not exists fixmeattr
( fixme text not null
, ts integer null
, name text not null
, value text
, primary key (fixme,ts,name)
)
|]
ddl [qc| drop view if exists fixmeattrview |]
ddl [qc|
create view fixmeattrview as
with ranked as (
select
fixme,
name,
value,
row_number() over (partition by fixme, name order by ts desc nulls first) as rn
from fixmeattr
)
select
fixme,
name,
value
from ranked
where rn = 1;
|]
insertFixme :: FixmePerks m => Fixme -> DBPipeM m ()
insertFixme fx@Fixme{..} = do
let fixme = serialise fx
let fxId = hashObject @HbSync fixme & HashRef
insert [qc|insert into fixme (id, fixme) values (?,?)
on conflict(id) do nothing
|] (fxId, fixme)
for_ (HM.toList fixmeAttr) $ \(n,v) -> do
insert [qc|
insert into fixmeattr(fixme,ts,name,value)
values (?,?,?,?)
on conflict (fixme,ts,name) do update set value = excluded.value
|] (fxId, fixmeTs, n, v)
insert [qc|
insert into fixmeattr(fixme,ts,name,value)
values (?,?,?,?)
on conflict (fixme,ts,name) do update set value = excluded.value
|] (fxId, fixmeTs, "fixme-tag", fixmeTag)
insert [qc|
insert into fixmeattr(fixme,ts,name,value)
values (?,?,?,?)
on conflict (fixme,ts,name) do update set value = excluded.value
|] (fxId, fixmeTs, "fixme-title", fixmeTitle)

View File

@ -2,6 +2,7 @@
module Fixme.Types where module Fixme.Types where
import Fixme.Prelude import Fixme.Prelude
import DBPipe.SQLite import DBPipe.SQLite
import HBS2.Git.Local import HBS2.Git.Local
@ -81,6 +82,7 @@ type FixmePerks m = ( MonadUnliftIO m
data FixmeEnv = data FixmeEnv =
FixmeEnv FixmeEnv
{ fixmeEnvGitDir :: Maybe FilePath { fixmeEnvGitDir :: Maybe FilePath
, fixmeEnvDb :: DBPipeEnv
, fixmeEnvFileMask :: TVar [FilePattern] , fixmeEnvFileMask :: TVar [FilePattern]
, fixmeEnvTags :: TVar (HashSet FixmeTag) , fixmeEnvTags :: TVar (HashSet FixmeTag)
, fixmeEnvAttribs :: TVar (HashSet FixmeAttrName) , fixmeEnvAttribs :: TVar (HashSet FixmeAttrName)
@ -126,31 +128,6 @@ newtype FixmeM m a = FixmeM { fromFixmeM :: ReaderT FixmeEnv m a }
withFixmeEnv :: FixmePerks m => FixmeEnv -> FixmeM m a -> m a withFixmeEnv :: FixmePerks m => FixmeEnv -> FixmeM m a -> m a
withFixmeEnv env what = runReaderT ( fromFixmeM what) env withFixmeEnv env what = runReaderT ( fromFixmeM what) env
runFixmeCLI :: FixmePerks m => FixmeM m a -> m a
runFixmeCLI m = do
env <- FixmeEnv Nothing
<$> newTVarIO mempty
<*> newTVarIO mempty
<*> newTVarIO mempty
<*> newTVarIO mempty
<*> newTVarIO mempty
<*> newTVarIO defCommentMap
<*> newTVarIO Nothing
runReaderT ( setupLogger >> fromFixmeM m ) env
`finally` flushLoggers
where
setupLogger = do
setLogging @ERROR $ toStderr . logPrefix "[error] "
setLogging @WARN $ toStderr . logPrefix "[warn] "
setLogging @NOTICE $ toStdout . logPrefix ""
pure ()
flushLoggers = do
setLoggingOff @DEBUG
setLoggingOff @ERROR
setLoggingOff @WARN
setLoggingOff @NOTICE
instance Serialise GitLocation instance Serialise GitLocation
instance Serialise FixmeSource instance Serialise FixmeSource
@ -176,6 +153,8 @@ instance FromField GitRef where
instance FromField GitHash where instance FromField GitHash where
fromField = fmap fromString . fromField @String fromField = fmap fromString . fromField @String
instance Pretty FixmeTimestamp where
pretty = pretty . coerce @_ @Word64
instance Pretty FixmeOffset where instance Pretty FixmeOffset where
pretty = pretty . coerce @_ @Word32 pretty = pretty . coerce @_ @Word32