Skip to content

Commit 5b6a1dc

Browse files
Improve error messages
This commit fixes two problems: 1) When the stack command argument is a path like x/y we should not go look for an auxiliary command stack-x/y . 2) When the argument looks like a path then only show a relevant error message related to intepreting the file. In the ambiguous case we show this: ``` cueball:~$ stack x Invalid argument `x' Auxiliary command not found in path `stack-x' File does not exist or is not a regular file `x' ``` But when the argument is a path we show this: ``` cueball:~$ stack x/y File does not exist or is not a regular file `x/y' ```
1 parent b8e3bca commit 5b6a1dc

File tree

1 file changed

+43
-23
lines changed

1 file changed

+43
-23
lines changed

src/main/Main.hs

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ import qualified System.Directory as Directory (findExecutable)
9393
import System.Environment (getEnvironment, getProgName, getArgs, withArgs)
9494
import System.Exit
9595
import System.FileLock (lockFile, tryLockFile, unlockFile, SharedExclusive(Exclusive), FileLock)
96-
import System.FilePath (searchPathSeparator)
96+
import System.FilePath (pathSeparator, searchPathSeparator)
9797
import System.IO (hIsTerminalDevice, stderr, stdin, stdout, hSetBuffering, BufferMode(..), hPutStrLn, Handle, hGetEncoding, hSetEncoding)
9898
import System.Process.Read
9999

@@ -166,6 +166,12 @@ main = do
166166
printExceptionStderr e
167167
exitFailure
168168

169+
-- Vertically combine only the error component of the first argument with the
170+
-- error component of the second.
171+
vcatErrorHelp :: ParserHelp -> ParserHelp -> ParserHelp
172+
vcatErrorHelp (ParserHelp e1 _ _ _ _) (ParserHelp e2 h2 u2 b2 f2) =
173+
ParserHelp (vcatChunks [e2, e1]) h2 u2 b2 f2
174+
169175
commandLineHandler
170176
:: String
171177
-> Bool
@@ -190,13 +196,11 @@ commandLineHandler progName isInterpreter = complicatedOptions
190196
parseResultHandler args f =
191197
if isInterpreter
192198
then do
193-
let hlp = stringChunk
199+
let hlp = errorHelp $ stringChunk
194200
(unwords ["Error executing interpreter command:"
195201
, progName
196202
, unwords args])
197-
let vcatErrChunk err (ParserHelp e h u b ft) =
198-
ParserHelp (vcatChunks [err, e]) h u b ft
199-
handleParseResult (overFailure (vcatErrChunk hlp) (Failure f))
203+
handleParseResult (overFailure (vcatErrorHelp hlp) (Failure f))
200204
else handleParseResult (Failure f)
201205

202206
globalOpts hide =
@@ -460,43 +464,59 @@ secondaryCommandHandler
460464
-- fall-through to external executables in `git` style if they exist
461465
-- (i.e. `stack something` looks for `stack-something` before
462466
-- failing with "Invalid argument `something'")
463-
secondaryCommandHandler args f = do
467+
secondaryCommandHandler args f =
468+
-- don't even try when the argument looks like a path
469+
if elem pathSeparator cmd
470+
then return f
471+
else do
472+
mExternalExec <- Directory.findExecutable cmd
473+
case mExternalExec of
474+
Just ex -> do
475+
menv <- getEnvOverride buildPlatform
476+
-- TODO show the command in verbose mode
477+
-- hPutStrLn stderr $ unwords $
478+
-- ["Running", "[" ++ ex, unwords (tail args) ++ "]"]
479+
_ <- runNoLoggingT (exec menv ex (tail args))
480+
return f
481+
Nothing -> return $ fmap (vcatErrorHelp (noSuchCmd cmd)) f
482+
where
464483
-- FIXME this is broken when any options are specified before the command
465484
-- e.g. stack --verbosity silent cmd
466-
mExternalExec <- Directory.findExecutable cmd
467-
case mExternalExec of
468-
Just ex -> do
469-
menv <- getEnvOverride buildPlatform
470-
-- TODO show the command in verbose mode
471-
-- hPutStrLn stderr $ unwords $
472-
-- ["Running", "[" ++ ex, unwords (tail args) ++ "]"]
473-
_ <- runNoLoggingT (exec menv ex (tail args))
474-
return f
475-
Nothing -> return $ fmap (flip mappend (noSuchCmd cmd)) f
476-
where
477485
cmd = stackProgName ++ "-" ++ (head args)
478486
noSuchCmd name = errorHelp $ stringChunk
479-
("\nNo such auxiliary command in path `" ++ name ++ "'")
487+
("Auxiliary command not found in path `" ++ name ++ "'")
480488

481489
interpreterHandler
482490
:: Monoid t
483491
=> [String]
484492
-> ParserFailure ParserHelp
485493
-> IO (GlobalOptsMonoid, (GlobalOpts -> IO (), t))
486494
interpreterHandler args f = do
487-
let file = head args
488495
isFile <- doesFileExist file
489496
if isFile
490497
then runInterpreterCommand file
491-
else parseResultHandler (flip mappend (noSuchFile file))
498+
else parseResultHandler (errorCombine (noSuchFile file))
492499
where
500+
file = head args
501+
502+
-- if the filename contains a path separator then we know that it is not a
503+
-- command it is a file to be interpreted. In that case we only show the
504+
-- interpreter error message and exclude the command related error messages.
505+
errorCombine =
506+
if elem pathSeparator file
507+
then overrideErrorHelp
508+
else vcatErrorHelp
509+
510+
overrideErrorHelp (ParserHelp e1 _ _ _ _) (ParserHelp _ h2 u2 b2 f2) =
511+
ParserHelp e1 h2 u2 b2 f2
512+
493513
parseResultHandler fn = handleParseResult (overFailure fn (Failure f))
494514
noSuchFile name = errorHelp $ stringChunk
495-
("\nNo such source file to interpret `" ++ name ++ "'")
515+
("File does not exist or is not a regular file `" ++ name ++ "'")
496516

497-
runInterpreterCommand file = do
517+
runInterpreterCommand path = do
498518
progName <- getProgName
499-
iargs <- getInterpreterArgs file
519+
iargs <- getInterpreterArgs path
500520
let parseCmdLine = commandLineHandler progName True
501521
let cmdArgs = iargs ++ "--" : args
502522
-- TODO show the command in verbose mode

0 commit comments

Comments
 (0)