- -- we want createDirectoryIfMissing "a/" to behave like
- -- createDirectoryIfMissing "a". Also, unless we apply
- -- dropTrailingPathSeparator first, dropFileName won't drop
- -- anything from "a/".
- path = dropTrailingPathSeparator path0
+ parents = reverse . scanl1 (</>) . splitDirectories . normalise
+
+ createDirs [] = return ()
+ createDirs (dir:[]) = createDir dir throw
+ createDirs (dir:dirs) =
+ createDir dir $ \_ -> do
+ createDirs dirs
+ createDir dir throw
+
+ createDir :: FilePath -> (IOException -> IO ()) -> IO ()
+ createDir dir notExistHandler = do
+ r <- try $ createDirectory dir
+ case (r :: Either IOException ()) of
+ Right () -> return ()
+ Left e
+ | isDoesNotExistError e -> notExistHandler e
+ -- createDirectory (and indeed POSIX mkdir) does not distinguish
+ -- between a dir already existing and a file already existing. So we
+ -- check for it here. Unfortunately there is a slight race condition
+ -- here, but we think it is benign. It could report an exeption in
+ -- the case that the dir did exist but another process deletes it
+ -- before we can check that it did indeed exist.
+ | isAlreadyExistsError e -> do exists <- doesDirectoryExist dir
+ if exists then return ()
+ else throw e
+ | otherwise -> throw e