haskellshake-build-system

haskell: cd command does not work in shake/command library


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.


Solution

  • 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.)