Add support for Bash 5.3 source -p .. file (just ignores the path)

This commit is contained in:
Vidar Holen 2025-07-17 12:27:43 -07:00
commit 0c26fb405d
2 changed files with 19 additions and 13 deletions

View file

@ -221,6 +221,9 @@ prop_worksWhenSourcing =
prop_worksWhenSourcingWithDashDash = prop_worksWhenSourcingWithDashDash =
null $ checkWithIncludes [("lib", "bar=1")] "source -- lib; echo \"$bar\"" null $ checkWithIncludes [("lib", "bar=1")] "source -- lib; echo \"$bar\""
prop_worksWhenSourcingWithDashP =
null $ checkWithIncludes [("lib", "bar=1")] "source -p \"$MYPATH\" lib; echo \"$bar\""
prop_worksWhenDotting = prop_worksWhenDotting =
null $ checkWithIncludes [("lib", "bar=1")] ". lib; echo \"$bar\"" null $ checkWithIncludes [("lib", "bar=1")] ". lib; echo \"$bar\""

View file

@ -48,6 +48,7 @@ import qualified Control.Monad.Reader as Mr
import qualified Control.Monad.State as Ms import qualified Control.Monad.State as Ms
import qualified Data.List.NonEmpty as NE import qualified Data.List.NonEmpty as NE
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Debug.Trace
import Test.QuickCheck.All (quickCheckAll) import Test.QuickCheck.All (quickCheckAll)
@ -2206,17 +2207,18 @@ readSimpleCommand = called "simple command" $ do
readSource :: Monad m => Token -> SCParser m Token readSource :: Monad m => Token -> SCParser m Token
readSource t@(T_Redirecting _ _ (T_SimpleCommand cmdId _ (cmd:file':rest'))) = do readSource t@(T_Redirecting _ _ (T_SimpleCommand cmdId _ (cmd:args'))) = do
let file = getFile file' rest' let file = getFile args'
override <- getSourceOverride override <- getSourceOverride
let literalFile = do let literalFile = do
name <- override `mplus` getLiteralString file `mplus` stripDynamicPrefix file name <- override `mplus` (getLiteralString =<< file) `mplus` (stripDynamicPrefix =<< file)
-- Hack to avoid 'source ~/foo' trying to read from literal tilde -- Hack to avoid 'source ~/foo' trying to read from literal tilde
guard . not $ "~/" `isPrefixOf` name guard . not $ "~/" `isPrefixOf` name
return name return name
let fileId = fromMaybe (getId cmd) (getId <$> file)
case literalFile of case literalFile of
Nothing -> do Nothing -> do
parseNoteAtId (getId file) WarningC 1090 parseNoteAtId fileId WarningC 1090
"ShellCheck can't follow non-constant source. Use a directive to specify location." "ShellCheck can't follow non-constant source. Use a directive to specify location."
return t return t
Just filename -> do Just filename -> do
@ -2224,7 +2226,7 @@ readSource t@(T_Redirecting _ _ (T_SimpleCommand cmdId _ (cmd:file':rest'))) = d
if not proceed if not proceed
then do then do
-- FIXME: This actually gets squashed without -a -- FIXME: This actually gets squashed without -a
parseNoteAtId (getId file) InfoC 1093 parseNoteAtId fileId InfoC 1093
"This file appears to be recursively sourced. Ignoring." "This file appears to be recursively sourced. Ignoring."
return t return t
else do else do
@ -2242,7 +2244,7 @@ readSource t@(T_Redirecting _ _ (T_SimpleCommand cmdId _ (cmd:file':rest'))) = d
return (contents, resolved) return (contents, resolved)
case input of case input of
Left err -> do Left err -> do
parseNoteAtId (getId file) InfoC 1091 $ parseNoteAtId fileId InfoC 1091 $
"Not following: " ++ err "Not following: " ++ err
return t return t
Right script -> do Right script -> do
@ -2254,18 +2256,19 @@ readSource t@(T_Redirecting _ _ (T_SimpleCommand cmdId _ (cmd:file':rest'))) = d
return $ T_SourceCommand id1 t (T_Include id2 src) return $ T_SourceCommand id1 t (T_Include id2 src)
let failed = do let failed = do
parseNoteAtId (getId file) WarningC 1094 parseNoteAtId fileId WarningC 1094
"Parsing of sourced file failed. Ignoring it." "Parsing of sourced file failed. Ignoring it."
return t return t
included <|> failed included <|> failed
where where
getFile :: Token -> [Token] -> Token getFile :: [Token] -> Maybe Token
getFile file (next:rest) = getFile (first:rest) =
case getLiteralString file of case getLiteralString first of
Just "--" -> next Just "--" -> rest !!! 0
x -> file Just "-p" -> rest !!! 1
getFile file _ = file _ -> return first
getFile _ = Nothing
getSourcePath t = getSourcePath t =
case t of case t of