For some reason I cannot make cd
command work in shake/command
Haskell library. It thinks directory I called with cd
does not exist even though it is present in the filesystem.
Here is an excerpt of my code:
dataDir = "data"
data Settings = Settings {
url :: String
} deriving (Eq, Show, Generic, JSON.ToJSON, JSON.FromJSON)
settings :: String -> Handler Settings
settings subfolder = let
gitPath = dataDir "/" subfolder "/git/.git"
in do
pathExists <- liftIO $ doesPathExist gitPath
-- Stdout pwdOut <- liftIO $ cmd ("pwd" :: String)
-- liftIO $ putStrLn $ pwdOut
if not pathExists
then do
liftIO $ (cmd_ ("mkdir -p" :: String) [gitPath] :: IO ())
liftIO $ (cmd_ ("cd" :: String) [gitPath] :: IO ())
liftIO $ (cmd_ ("git init" :: String) :: IO ())
return $ Settings { url = ""}
else do
liftIO $ (cmd_ (Cwd ".") ("cd" :: String) [gitPath] :: IO ())
Stdout out <- liftIO $ (cmd ("git config --get remote.origin.url" :: String))
return $ Settings {url = out}
It fails with an error cd: createProcess: runInteractiveProcess: exec: does not exist (No such file or directory)
in both cases: if dir exists and when mkdir
command is executed.
Cannot wrap my head around it. But before I submit a bug to the shake's github page, I want to make sure with you I am not doing anything stupid that might cause this kind of behavior.
Thanks in advance for help.
CodePudding user response:
Shake's Haddock page describes cmd_
, and links to its source. There we can see that cmd_
eventually calls commandExplicitIO
, which constructs a ProcessOpts
with RawCommand
and passes it to process
. process
then takes that ProcessOpts
, pattern-matches it as a RawCommand
(via cmdSpec
), and calls proc
. We have now entered the well-documented zone: you must give proc
an executable, and cd
is not an executable. (Why? Since processes cannot change the working directory of their parent, cd
must be a shell builtin.)