run: do not pre-load journal(s) at the start of "run" [#2345]

wait for the first command to do this. Same for "repl"
This commit is contained in:
Dmitry Astapov 2025-03-08 16:46:04 +00:00 committed by Simon Michael
parent c0b3c932ea
commit 9963a01a15
2 changed files with 37 additions and 33 deletions

View File

@ -81,28 +81,28 @@ newtype DefaultRunJournal = DefaultRunJournal (NE.NonEmpty String) deriving (Sho
-- | The actual run command. -- | The actual run command.
run :: Maybe DefaultRunJournal -> (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> [String] -> CliOpts -> IO () run :: Maybe DefaultRunJournal -> (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> [String] -> CliOpts -> IO ()
run defaultJournalOverride findBuiltinCommand addons cliopts@CliOpts{rawopts_=rawopts} = do run defaultJournalOverride findBuiltinCommand addons cliopts@CliOpts{rawopts_=rawopts} = do
withJournalCached defaultJournalOverride cliopts $ \(_,key) -> do jpaths <- DefaultRunJournal <$> journalFilePathFromOptsOrDefault defaultJournalOverride cliopts
let args = dbg1 "args" $ listofstringopt "args" rawopts let args = dbg1 "args" $ listofstringopt "args" rawopts
isTerminal <- isStdinTerminal isTerminal <- isStdinTerminal
if args == [] && not isTerminal if args == [] && not isTerminal
then do then do
inputFiles <- journalFilePathFromOpts cliopts inputFiles <- journalFilePathFromOpts cliopts
let journalFromStdin = any (== "-") $ map (snd . splitReaderPrefix) $ NE.toList inputFiles let journalFromStdin = any (== "-") $ map (snd . splitReaderPrefix) $ NE.toList inputFiles
if journalFromStdin if journalFromStdin
then error' "'run' can't read commands from stdin, as one of the input files was stdin as well" then error' "'run' can't read commands from stdin, as one of the input files was stdin as well"
else runREPL key findBuiltinCommand addons else runREPL jpaths findBuiltinCommand addons
else do else do
-- Check if arguments start with "--". -- Check if arguments start with "--".
-- If not, assume that they are files with commands -- If not, assume that they are files with commands
case args of case args of
"--":_ -> runFromArgs key findBuiltinCommand addons args "--":_ -> runFromArgs jpaths findBuiltinCommand addons args
_ -> runFromFiles key findBuiltinCommand addons args _ -> runFromFiles jpaths findBuiltinCommand addons args
-- | The actual repl command. -- | The actual repl command.
repl :: (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> [String] -> CliOpts -> IO () repl :: (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> [String] -> CliOpts -> IO ()
repl findBuiltinCommand addons cliopts = do repl findBuiltinCommand addons cliopts = do
withJournalCached Nothing cliopts $ \(_,key) -> do jpaths <- DefaultRunJournal <$> journalFilePathFromOptsOrDefault Nothing cliopts
runREPL key findBuiltinCommand addons runREPL jpaths findBuiltinCommand addons
-- | Run commands from files given to "run". -- | Run commands from files given to "run".
runFromFiles :: DefaultRunJournal -> (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> [String] -> [String] -> IO () runFromFiles :: DefaultRunJournal -> (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> [String] -> [String] -> IO ()
@ -156,9 +156,9 @@ runCommand defaultJournalOverride findBuiltinCommand addons cmdline = do
| infoFlag -> runInfoForTopic "hledger" mmodecmdname | infoFlag -> runInfoForTopic "hledger" mmodecmdname
| manFlag -> runManForTopic "hledger" mmodecmdname | manFlag -> runManForTopic "hledger" mmodecmdname
| otherwise -> do | otherwise -> do
withJournalCached (Just defaultJournalOverride) opts $ \(j,key) -> do withJournalCached (Just defaultJournalOverride) opts $ \(j,jpaths) -> do
if cmdname == "run" -- allow "run" to call "run" if cmdname == "run" -- allow "run" to call "run"
then run (Just key) findBuiltinCommand addons opts then run (Just jpaths) findBuiltinCommand addons opts
else cmdaction opts j else cmdaction opts j
Nothing | cmdname `elem` addons -> Nothing | cmdname `elem` addons ->
system (printf "%s-%s %s" progname cmdname (unwords' args)) >>= exitWith system (printf "%s-%s %s" progname cmdname (unwords' args)) >>= exitWith
@ -208,23 +208,28 @@ stdinCache :: MVar (Maybe T.Text)
stdinCache = unsafePerformIO $ newMVar Nothing stdinCache = unsafePerformIO $ newMVar Nothing
{-# NOINLINE stdinCache #-} {-# NOINLINE stdinCache #-}
-- | Get the journal(s) to read, either from the defaultJournalOverride or from the cliopts
journalFilePathFromOptsOrDefault :: Maybe DefaultRunJournal -> CliOpts -> IO (NE.NonEmpty PrefixedFilePath)
journalFilePathFromOptsOrDefault defaultJournalOverride cliopts = do
case defaultJournalOverride of
Nothing -> journalFilePathFromOpts cliopts
Just (DefaultRunJournal defaultFiles) -> do
mbjournalpaths <- journalFilePathFromOptsNoDefault cliopts
case mbjournalpaths of
Nothing -> return defaultFiles -- use the journal(s) given to the "run" itself
Just journalpaths -> return journalpaths
-- | Similar to `withJournal`, but uses caches all the journals it reads. -- | Similar to `withJournal`, but uses caches all the journals it reads.
-- When reading from stdin, caches the stdin contents so that we could reprocess -- When reading from stdin, caches the stdin contents so that we could reprocess
-- it if a read with different InputOptions is requested. -- it if a read with different InputOptions is requested.
withJournalCached :: Maybe DefaultRunJournal -> CliOpts -> ((Journal, DefaultRunJournal) -> IO ()) -> IO () withJournalCached :: Maybe DefaultRunJournal -> CliOpts -> ((Journal, DefaultRunJournal) -> IO ()) -> IO ()
withJournalCached defaultJournalOverride cliopts cmd = do withJournalCached defaultJournalOverride cliopts cmd = do
(j,key) <- case defaultJournalOverride of journalpaths <- journalFilePathFromOptsOrDefault defaultJournalOverride cliopts
Nothing -> journalFilePathFromOpts cliopts >>= readFiles j <- readFiles journalpaths
Just (DefaultRunJournal defaultFiles) -> do cmd (j,DefaultRunJournal journalpaths)
mbjournalpaths <- journalFilePathFromOptsNoDefault cliopts
case mbjournalpaths of
Nothing -> readFiles defaultFiles -- use the journal(s) given to the "run" itself
Just journalpaths -> readFiles journalpaths
cmd (j,key)
where where
readFiles journalpaths = do readFiles journalpaths =
j <- journalTransform cliopts . sconcat <$> mapM (readAndCacheJournalFile (inputopts_ cliopts)) journalpaths journalTransform cliopts . sconcat <$> mapM (readAndCacheJournalFile (inputopts_ cliopts)) journalpaths
return (j, DefaultRunJournal journalpaths)
-- | Read a journal file, caching it (and InputOptions used to read it) if it has not been seen before. -- | Read a journal file, caching it (and InputOptions used to read it) if it has not been seen before.
-- If the same file is requested with different InputOptions, we read it anew and cache -- If the same file is requested with different InputOptions, we read it anew and cache
-- it separately. -- it separately.

View File

@ -150,7 +150,7 @@ Assets, depth 2:
-------------------- --------------------
$-1 $-1
# ** 0. Run caches input files, and re-parses files when InputOptions change # ** 11. Run caches input files, and re-parses files when InputOptions change
< <
2017-01-01 groceries 2017-01-01 groceries
assets:cash -$100 assets:cash -$100
@ -158,7 +158,6 @@ Assets, depth 2:
$ hledger run --debug 1 -f- -- accounts -- balance -f sample.journal -- balance cash --forecast -- balance cash -f sample.journal --forecast -- register -- register -f sample.journal 2>&1 | grep readAndCacheJournalFile | sed -e "s#$(pwd)/##" $ hledger run --debug 1 -f- -- accounts -- balance -f sample.journal -- balance cash --forecast -- balance cash -f sample.journal --forecast -- register -- register -f sample.journal 2>&1 | grep readAndCacheJournalFile | sed -e "s#$(pwd)/##"
> >
readAndCacheJournalFile reading and caching -: readAndCacheJournalFile reading and caching -:
readAndCacheJournalFile using cache for -:
readAndCacheJournalFile reading and caching sample.journal: readAndCacheJournalFile reading and caching sample.journal:
readAndCacheJournalFile reading and caching -: readAndCacheJournalFile reading and caching -:
readAndCacheJournalFile reading and caching sample.journal: readAndCacheJournalFile reading and caching sample.journal: