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,7 +81,7 @@ newtype DefaultRunJournal = DefaultRunJournal (NE.NonEmpty String) deriving (Sho
-- | The actual run command.
run :: Maybe DefaultRunJournal -> (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> [String] -> CliOpts -> IO ()
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
isTerminal <- isStdinTerminal
if args == [] && not isTerminal
@ -90,19 +90,19 @@ run defaultJournalOverride findBuiltinCommand addons cliopts@CliOpts{rawopts_=ra
let journalFromStdin = any (== "-") $ map (snd . splitReaderPrefix) $ NE.toList inputFiles
if journalFromStdin
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
-- Check if arguments start with "--".
-- If not, assume that they are files with commands
case args of
"--":_ -> runFromArgs key findBuiltinCommand addons args
_ -> runFromFiles key findBuiltinCommand addons args
"--":_ -> runFromArgs jpaths findBuiltinCommand addons args
_ -> runFromFiles jpaths findBuiltinCommand addons args
-- | The actual repl command.
repl :: (String -> Maybe (Mode RawOpts, CliOpts -> Journal -> IO ())) -> [String] -> CliOpts -> IO ()
repl findBuiltinCommand addons cliopts = do
withJournalCached Nothing cliopts $ \(_,key) -> do
runREPL key findBuiltinCommand addons
jpaths <- DefaultRunJournal <$> journalFilePathFromOptsOrDefault Nothing cliopts
runREPL jpaths findBuiltinCommand addons
-- | Run commands from files given to "run".
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
| manFlag -> runManForTopic "hledger" mmodecmdname
| otherwise -> do
withJournalCached (Just defaultJournalOverride) opts $ \(j,key) -> do
withJournalCached (Just defaultJournalOverride) opts $ \(j,jpaths) -> do
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
Nothing | cmdname `elem` addons ->
system (printf "%s-%s %s" progname cmdname (unwords' args)) >>= exitWith
@ -208,23 +208,28 @@ stdinCache :: MVar (Maybe T.Text)
stdinCache = unsafePerformIO $ newMVar Nothing
{-# 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.
-- When reading from stdin, caches the stdin contents so that we could reprocess
-- it if a read with different InputOptions is requested.
withJournalCached :: Maybe DefaultRunJournal -> CliOpts -> ((Journal, DefaultRunJournal) -> IO ()) -> IO ()
withJournalCached defaultJournalOverride cliopts cmd = do
(j,key) <- case defaultJournalOverride of
Nothing -> journalFilePathFromOpts cliopts >>= readFiles
Just (DefaultRunJournal defaultFiles) -> do
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)
journalpaths <- journalFilePathFromOptsOrDefault defaultJournalOverride cliopts
j <- readFiles journalpaths
cmd (j,DefaultRunJournal journalpaths)
where
readFiles journalpaths = do
j <- journalTransform cliopts . sconcat <$> mapM (readAndCacheJournalFile (inputopts_ cliopts)) journalpaths
return (j, DefaultRunJournal journalpaths)
readFiles journalpaths =
journalTransform cliopts . sconcat <$> mapM (readAndCacheJournalFile (inputopts_ cliopts)) journalpaths
-- | 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
-- it separately.

View File

@ -150,7 +150,7 @@ Assets, depth 2:
--------------------
$-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
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)/##"
>
readAndCacheJournalFile reading and caching -:
readAndCacheJournalFile using cache for -:
readAndCacheJournalFile reading and caching sample.journal:
readAndCacheJournalFile reading and caching -:
readAndCacheJournalFile reading and caching sample.journal: