From 9031612c308a6d5a7ca496cb4306a2a78816cda4 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Fri, 24 Oct 2025 11:48:52 -1000 Subject: [PATCH] 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. --- hledger-lib/Hledger/Read.hs | 43 +++++++++++++++++---------------- hledger-lib/Hledger/Utils/IO.hs | 2 +- hledger/hledger.m4.md | 13 ++++++++-- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/hledger-lib/Hledger/Read.hs b/hledger-lib/Hledger/Read.hs index 27bad1165..32d9ecb2c 100644 --- a/hledger-lib/Hledger/Read.hs +++ b/hledger-lib/Hledger/Read.hs @@ -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@ -- diff --git a/hledger-lib/Hledger/Utils/IO.hs b/hledger-lib/Hledger/Utils/IO.hs index 135cb799e..744f93916 100644 --- a/hledger-lib/Hledger/Utils/IO.hs +++ b/hledger-lib/Hledger/Utils/IO.hs @@ -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 diff --git a/hledger/hledger.m4.md b/hledger/hledger.m4.md index abd1981aa..36114cda1 100644 --- a/hledger/hledger.m4.md +++ b/hledger/hledger.m4.md @@ -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),