Skip to content

Commit

Permalink
Improve error message when input path doesn't exist (#2092)
Browse files Browse the repository at this point in the history
Previously if you call Juvix on a file that doesn't exist you get the
error:

```
$ juvix compile /i/don't/exist.juvix
juvix: /i/dont: changeWorkingDirectory: does not exist (No such file or directory)
```

After this change you will see:

```
$ juvix compile /i/don't/exist.juvix
The input path "/i/dont/exist.juvix" does not exist
```
  • Loading branch information
paulcadman authored May 15, 2023
1 parent 2b0668b commit 8eb4c64
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 17 deletions.
16 changes: 14 additions & 2 deletions app/Main.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{-# LANGUAGE QuasiQuotes #-}

module Main (main) where

import App
import CommonOptions
import Data.String.Interpolate (i)
import GlobalOptions
import Juvix.Compiler.Pipeline.Root
import TopCommand
Expand All @@ -13,10 +16,19 @@ main = do
invokeDir <- getCurrentDir
(_runAppIOArgsGlobalOptions, cli) <- customExecParser parserPreferences descr
mbuildDir <- mapM (prepathToAbsDir invokeDir) (_runAppIOArgsGlobalOptions ^? globalBuildDir . _Just . pathPath)
mainFileDir <- topCommandInputFile cli
_runAppIOArgsRoots <- findRootAndChangeDir mainFileDir mbuildDir invokeDir
mainFile <- topCommandInputPath cli
mapM_ checkMainFile mainFile
_runAppIOArgsRoots <- findRootAndChangeDir (containingDir <$> mainFile) mbuildDir invokeDir
runFinal
. resourceToIOFinal
. embedToFinal @IO
. runAppIO RunAppIOArgs {..}
$ runTopCommand cli
where
checkMainFile :: SomePath b -> IO ()
checkMainFile p = unlessM (doesSomePathExist p) err
where
err :: IO ()
err = do
hPutStrLn stderr [i|The input path #{p} does not exist|]
exitFailure
28 changes: 14 additions & 14 deletions app/TopCommand/Options.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,34 @@ data TopCommand
| JuvixFormat FormatOptions
deriving stock (Data)

topCommandInputFile :: TopCommand -> IO (Maybe (Path Abs Dir))
topCommandInputFile (JuvixFormat fopts) = case fopts ^. formatInput of
Just f -> getInputDirFromPrepathFileOrDir f
topCommandInputPath :: TopCommand -> IO (Maybe (SomePath Abs))
topCommandInputPath (JuvixFormat fopts) = case fopts ^. formatInput of
Just f -> getInputPathFromPrepathFileOrDir f
Nothing -> return Nothing
topCommandInputFile t = do
topCommandInputPath t = do
d <- firstJustM getInputFileOrDir (universeBi t)
f <- firstJustM getInputFileDir (universeBi t)
f <- firstJustM getInputFile (universeBi t)
return (f <|> d)
where
getInputFileDir :: AppPath File -> IO (Maybe (Path Abs Dir))
getInputFileDir p
getInputFile :: AppPath File -> IO (Maybe (SomePath Abs))
getInputFile p
| p ^. pathIsInput = do
cwd <- getCurrentDir
Just . parent <$> prepathToAbsFile cwd (p ^. pathPath)
Just . File <$> prepathToAbsFile cwd (p ^. pathPath)
| otherwise = return Nothing

getInputFileOrDir :: AppPath FileOrDir -> IO (Maybe (Path Abs Dir))
getInputFileOrDir :: AppPath FileOrDir -> IO (Maybe (SomePath Abs))
getInputFileOrDir p
| p ^. pathIsInput = getInputDirFromPrepathFileOrDir (p ^. pathPath)
| p ^. pathIsInput = getInputPathFromPrepathFileOrDir (p ^. pathPath)
| otherwise = return Nothing

getInputDirFromPrepathFileOrDir :: Prepath FileOrDir -> IO (Maybe (Path Abs Dir))
getInputDirFromPrepathFileOrDir p = do
getInputPathFromPrepathFileOrDir :: Prepath FileOrDir -> IO (Maybe (SomePath Abs))
getInputPathFromPrepathFileOrDir p = do
cwd <- getCurrentDir
lr <- fromPreFileOrDir cwd p
return . Just $ case lr of
Left file -> parent file
Right dir -> dir
Left file -> File file
Right dir -> Dir dir

parseDisplayVersion :: Parser TopCommand
parseDisplayVersion =
Expand Down
2 changes: 2 additions & 0 deletions src/Juvix/Prelude/Path.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ module Juvix.Prelude.Path
( module Juvix.Prelude.Path,
module Path,
module Path.IO,
module Juvix.Prelude.Path.SomePath,
)
where

import Data.List.NonEmpty qualified as NonEmpty
import Juvix.Prelude.Base
import Juvix.Prelude.Path.OrphanInstances ()
import Juvix.Prelude.Path.SomePath
import Path hiding ((<.>), (</>))
import Path qualified
import Path.IO hiding (listDirRel, walkDirRel)
Expand Down
27 changes: 27 additions & 0 deletions src/Juvix/Prelude/Path/SomePath.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Juvix.Prelude.Path.SomePath where

import Juvix.Prelude.Base
import Path
import Path.IO
import Prelude qualified

data SomePath b
= File (Path b File)
| Dir (Path b Dir)

-- | Return the directory containing a path. i.e the path itself if it is a
-- directory or its parent if it is a file.
containingDir :: SomePath b -> Path b Dir
containingDir = \case
File f -> parent f
Dir d -> d

doesSomePathExist :: SomePath b -> IO Bool
doesSomePathExist = \case
File p -> doesPathExist p
Dir p -> doesPathExist p

instance Show (SomePath b) where
show = \case
File p -> show p
Dir p -> show p
10 changes: 10 additions & 0 deletions tests/smoke/Commands/compile.smoke.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,13 @@ tests:
[ -f test001.lisp ]
stdout: ""
exit-status: 0

- name: input-file-does-not-exist
command:
- juvix
- compile
- positive/NonExistingCompileFile.juvix
stderr:
contains: |
positive/NonExistingCompileFile.juvix" does not exist
exit-status: 1
2 changes: 1 addition & 1 deletion tests/smoke/Commands/format.smoke.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ tests:
stdin: 'module Format; open import Stdlib.Prelude; main : Nat; main := 5; '
stderr:
contains: |
positive/NonExistingFormat.juvix: openFile: does not exist (No such file or directory)
positive/NonExistingFormat.juvix" does not exist
exit-status: 1

- name: format-stdin-module-name-not-file-name
Expand Down

0 comments on commit 8eb4c64

Please sign in to comment.