fix!: error if LEDGER_FILE points to a nonexistent file [#2485]

Avoiding potentially confusing silent fallback. Also,

- Drop support for Ledger's legacy LEDGER environment variable;
  we now support only LEDGER_FILE, for simplicity.

- Clarify the behaviour, eg when a glob pattern matches multiple files
  or when the value is empty.
This commit is contained in:
Simon Michael 2025-10-24 11:48:52 -10:00
parent f7bd563fc5
commit 9031612c30
3 changed files with 34 additions and 24 deletions

View File

@ -174,7 +174,6 @@ import Text.Printf (printf)
--- ** journal reading
journalEnvVar = "LEDGER_FILE"
journalEnvVar2 = "LEDGER"
journalDefaultFilename = ".hledger.journal"
-- | Read the default journal file specified by the environment,
@ -202,29 +201,31 @@ defaultJournalSafelyWith iopts = (do
C.Handler (\(e :: C.ErrorCall) -> return $ Left $ show e)
,C.Handler (\(e :: C.IOException) -> return $ Left $ show e)
]
-- | Get the default journal file path specified by the environment.
-- Like ledger, we look first for the LEDGER_FILE environment
-- variable, and if that does not exist, for the legacy LEDGER
-- environment variable. If neither is set, or the value is blank,
-- return the hard-coded default, which is @.hledger.journal@ in the
-- users's home directory (or in the current directory, if we cannot
-- determine a home directory).
-- | Get the default journal file path.
--
-- This looks for the LEDGER_FILE environment variable, like Ledger.
-- The value should be a file path; ~ at the start is supported, meaning user's home directory.
-- The value can also be a glob pattern, for convenience; if so we consider only the first matched file.
--
-- If no such file exists, an error is raised.
--
-- If LEDGER_FILE is unset or set to the empty string, we return a default file path:
-- @.hledger.journal@ in the user's home directory.
-- Or if we can't find the user's home directory, in the current directory.
--
defaultJournalPath :: IO String
defaultJournalPath = do
p <- envJournalPath
if null p
then defpath
glob <- getEnv journalEnvVar `C.catch` (\(_::C.IOException) -> return "")
if null glob
then do
homedir <- fromMaybe "" <$> getHomeSafe
return $ homedir </> journalDefaultFilename
else do
ps <- expandGlob "." p `C.catch` (\(_::C.IOException) -> return [])
maybe defpath return $ headMay ps
where
envJournalPath =
getEnv journalEnvVar
`C.catch` (\(_::C.IOException) -> getEnv journalEnvVar2
`C.catch` (\(_::C.IOException) -> return ""))
defpath = do
home <- fromMaybe "" <$> getHomeSafe
return $ home </> journalDefaultFilename
mf <- headMay <$> expandGlob "." glob `C.catch` (\(_::C.IOException) -> return [])
case mf of
Just f -> return f
Nothing -> error' $ "LEDGER_FILE points to nonexistent file \"" <> glob <> "\""
-- | @readJournal iopts mfile txt@
--

View File

@ -406,7 +406,7 @@ expandHomePath = \case
('~':_) -> ioError $ userError "~USERNAME in paths is not supported"
p -> return p
-- | Given a current directory, convert a possibly relative, possibly tilde-containing
-- | Given a current directory, convert a possibly relative, possibly tilde-prefixed
-- file path to an absolute one.
-- ~username is not supported. Leaves "-" unchanged. Can raise an error.
expandPath :: FilePath -> FilePath -> IO FilePath -- general type sig for use in reader parsers

View File

@ -966,8 +966,17 @@ If `less` is your [pager](#paging), this variable specifies the `less` options h
(Otherwise, `LESS` + custom options are used.)
**LEDGER_FILE**
The main journal file to use when not specified with `-f/--file`.
Default: `$HOME/.hledger.journal`.
The default journal file, to be used when no `-f/--file` option is provided.
For example, it could be `~/finance/main.journal`.
This can also be a glob pattern, eg `./2???.journal`.
(If the glob matches multiple files, only the alphanumerically first one is used.)
If LEDGER_FILE points to a non-existent file, an error will be raised.
If the value is the empty string, it is ignored.
If LEDGER_FILE is not set and `-f` is not provided, the default journal file is `$HOME/.hledger.journal`
(or if a home directory can't be detected, `./.hledger.journal`).
See also [Common tasks > Setting LEDGER_FILE](#setting-ledger_file).
**NO_COLOR**
If this environment variable exists (with any value, including empty),