imp: -f now errors if given a glob matching no files, like LEDGER_FILE
Previously LEDGER_FILE=foo hledger add did, but hledger -f foo add didn't.
Now they both consistently will error if given a glob
(a path contining [, {, *, or ?) that matches nothing,
rather than auto-creating a file with a glob-like name.
Hledger.Utils.IO:
expandPathOrGlob
This commit is contained in:
parent
88f6c16dd5
commit
e7d7c49562
@ -150,7 +150,7 @@ import Data.Text (Text)
|
||||
import Data.Text qualified as T
|
||||
import Data.Text.IO qualified as T
|
||||
import Data.Time (Day)
|
||||
import Safe (headDef, headMay)
|
||||
import Safe (headDef)
|
||||
import System.Directory (doesFileExist)
|
||||
import System.Environment (getEnv)
|
||||
import System.FilePath ((<.>), (</>), splitDirectories, splitFileName, takeFileName)
|
||||
@ -223,18 +223,8 @@ defaultJournalPath = do
|
||||
homedir <- fromMaybe "" <$> getHomeSafe
|
||||
let defaultfile = homedir </> journalDefaultFilename
|
||||
return defaultfile
|
||||
else do
|
||||
-- If it contains glob metacharacters, expand the pattern and error if no matches.
|
||||
-- Otherwise just expand ~ and return the path, even if the file doesn't exist yet.
|
||||
let hasGlobChars = any (`elem` p) ("*?[{" :: [Char])
|
||||
if hasGlobChars
|
||||
then do
|
||||
mf <- headMay <$> expandGlob "." p `C.catch` (\(_::C.IOException) -> return [])
|
||||
case mf of
|
||||
Just f -> return f
|
||||
Nothing -> error' $ "LEDGER_FILE glob pattern \"" <> p <> "\" matched no files"
|
||||
else
|
||||
expandPath "." p
|
||||
else
|
||||
expandPathOrGlob "." p
|
||||
|
||||
-- | Like defaultJournalPath, but return an error message instead of raising an error.
|
||||
defaultJournalPathSafely :: IO (Either String String)
|
||||
|
||||
@ -40,6 +40,7 @@ module Hledger.Utils.IO (
|
||||
expandHomePath,
|
||||
expandPath,
|
||||
expandGlob,
|
||||
expandPathOrGlob,
|
||||
sortByModTime,
|
||||
openFileOrStdin,
|
||||
readFileOrStdinPortably,
|
||||
@ -423,6 +424,26 @@ expandPath curdir p = (if isRelative p then (curdir </>) else id) <$> expandHome
|
||||
expandGlob :: FilePath -> FilePath -> IO [FilePath]
|
||||
expandGlob curdir p = expandPath curdir p >>= glob <&> sort -- PARTIAL:
|
||||
|
||||
-- | Like expandPath, but if the path contains glob metacharacters (* ? [ {),
|
||||
-- treats it as a glob pattern and expands it, returning the first match.
|
||||
-- Raises an error if the glob pattern matches no files.
|
||||
-- If the path contains no glob metacharacters, just expands ~ and returns the path,
|
||||
-- even if the file doesn't exist yet.
|
||||
-- This is useful for options like -f and LEDGER_FILE that should:
|
||||
-- - accept non-existent files (for commands like add/import that create them)
|
||||
-- - expand glob patterns and error if they don't match anything
|
||||
expandPathOrGlob :: FilePath -> FilePath -> IO FilePath
|
||||
expandPathOrGlob curdir p = do
|
||||
let hasGlobChars = any (`elem` p) ("*?[{" :: [Char])
|
||||
if hasGlobChars
|
||||
then do
|
||||
matches <- expandGlob curdir p `catch` (\(_::IOException) -> return [])
|
||||
case headMay matches of
|
||||
Just f -> return f
|
||||
Nothing -> error' $ "glob pattern \"" <> p <> "\" matched no files"
|
||||
else
|
||||
expandPath curdir p
|
||||
|
||||
-- | Given a list of existing file paths, sort them by modification time (from oldest to newest).
|
||||
sortByModTime :: [FilePath] -> IO [FilePath]
|
||||
sortByModTime fs = do
|
||||
|
||||
@ -755,7 +755,7 @@ journalFilePathFromOptsNoDefault opts = do
|
||||
expandPathPreservingPrefix :: FilePath -> PrefixedFilePath -> IO PrefixedFilePath
|
||||
expandPathPreservingPrefix d prefixedf = do
|
||||
let (p,f) = splitReaderPrefix prefixedf
|
||||
f' <- expandPath d f
|
||||
f' <- expandPathOrGlob d f
|
||||
return $ case p of
|
||||
Just p' -> (show p') ++ ":" ++ f'
|
||||
Nothing -> f'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user